Skip to content

Commit

Permalink
Add some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
timdp committed Apr 25, 2018
1 parent 46b2dc4 commit 82db424
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 30 deletions.
30 changes: 30 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: 2
jobs:
build:
docker:
- image: circleci/golang:1.10.1-stretch
working_directory: /go/src/github.com/timdp/lwc
environment:
TEST_RESULTS: /tmp/test-results
steps:
- checkout
- run: mkdir -p $TEST_RESULTS
- restore_cache:
keys:
- v1-pkg-cache
- run: go get github.com/jstemmer/go-junit-report
- run:
command: |
trap "go-junit-report < $TEST_RESULTS/go-test.out > $TEST_RESULTS/go-test-report.xml" EXIT
go test -v $( go list ./... ) | tee $TEST_RESULTS/go-test.out
- save_cache:
key: v1-pkg-cache
paths:
- /go/pkg
- store_test_results:
path: /tmp/test-results
when: always
- store_artifacts:
path: /tmp/test-results
destination: test-results
when: always
41 changes: 24 additions & 17 deletions internal/app/lwc/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package lwc

import (
"fmt"
"log"
"os"
"time"

Expand All @@ -20,31 +21,37 @@ type Config struct {
Help bool
Version bool
Files []string
g *getopt.Set
}

func BuildConfig() Config {
var config Config
func (c *Config) PrintUsage() {
c.g.PrintUsage(os.Stdout)
}

func BuildConfig(args []string) Config {
intervalMs := DEFAULT_INTERVAL
getopt.FlagLong(&config.Lines, "lines", 'l', "print the newline counts")
getopt.FlagLong(&config.Words, "words", 'w', "print the word counts")
getopt.FlagLong(&config.Chars, "chars", 'm', "print the character counts")
getopt.FlagLong(&config.Bytes, "bytes", 'c', "print the byte counts")
getopt.FlagLong(&config.MaxLineLength, "max-line-length", 'L', "print the maximum display width")
getopt.FlagLong(&intervalMs, "interval", 'i',
g := getopt.New()
var config Config
config.g = g
g.FlagLong(&config.Lines, "lines", 'l', "print the newline counts")
g.FlagLong(&config.Words, "words", 'w', "print the word counts")
g.FlagLong(&config.Chars, "chars", 'm', "print the character counts")
g.FlagLong(&config.Bytes, "bytes", 'c', "print the byte counts")
g.FlagLong(&config.MaxLineLength, "max-line-length", 'L', "print the maximum display width")
g.FlagLong(&intervalMs, "interval", 'i',
fmt.Sprintf("set update interval in ms (default %d ms)", DEFAULT_INTERVAL))
getopt.FlagLong(&config.Help, "help", 'h', "display this help and exit")
getopt.FlagLong(&config.Version, "version", 'V', "output version information and exit")
getopt.Parse()
config.Interval = time.Duration(intervalMs * 1e6)
config.Files = getopt.Args()
g.FlagLong(&config.Help, "help", 'h', "display this help and exit")
g.FlagLong(&config.Version, "version", 'V', "output version information and exit")
g.Parse(args)
if intervalMs < 0 {
log.Fatal("Update interval cannot be negative")
}
config.Interval = time.Duration(intervalMs) * time.Millisecond
config.Files = g.Args()
if !(config.Lines || config.Words || config.Chars || config.Bytes) {
config.Lines = true
config.Words = true
config.Bytes = true
}
return config
}

func PrintUsage() {
getopt.PrintUsage(os.Stdout)
}
116 changes: 116 additions & 0 deletions internal/app/lwc/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package lwc

import (
"reflect"
"testing"
"time"
)

type configTest struct {
args []string
expected Config
}

var configTests = []configTest{
{
[]string{},
Config{
true, true, false, true, false,
time.Duration(DEFAULT_INTERVAL) * time.Millisecond,
false, false,
[]string{},
nil,
},
},
{
[]string{"-w", "--lines"},
Config{
true, true, false, false, false,
time.Duration(DEFAULT_INTERVAL) * time.Millisecond,
false, false,
[]string{},
nil,
},
},
{
[]string{"foo"},
Config{
true, true, false, true, false,
time.Duration(DEFAULT_INTERVAL) * time.Millisecond,
false, false,
[]string{"foo"},
nil,
},
},
{
[]string{"--", "/path/to/file"},
Config{
true, true, false, true, false,
time.Duration(DEFAULT_INTERVAL) * time.Millisecond,
false, false,
[]string{"/path/to/file"},
nil,
},
},
{
[]string{"--max-line-length", "--bytes", "/etc/passwd", "/etc/group"},
Config{
false, false, false, true, true,
time.Duration(DEFAULT_INTERVAL) * time.Millisecond,
false, false,
[]string{"/etc/passwd", "/etc/group"},
nil,
},
},
{
[]string{"-i", "5000"},
Config{
true, true, false, true, false,
time.Duration(5000) * time.Millisecond,
false, false,
[]string{},
nil,
},
},
{
[]string{"--interval=2000"},
Config{
true, true, false, true, false,
time.Duration(2000) * time.Millisecond,
false, false,
[]string{},
nil,
},
},
{
[]string{"--interval", "3000"},
Config{
true, true, false, true, false,
time.Duration(3000) * time.Millisecond,
false, false,
[]string{},
nil,
},
},
{
[]string{"-i", "0"},
Config{
true, true, false, true, false,
time.Duration(0),
false, false,
[]string{},
nil,
},
},
}

func TestBuildConfig(t *testing.T) {
for i, test := range configTests {
actual := BuildConfig(append([]string{"lwc"}, test.args...))
// Clear getopt Set because we don't want to compare it
actual.g = nil
if !reflect.DeepEqual(test.expected, actual) {
t.Errorf("Test #%d failed: expecting %#v, got %#v", i, test.expected, actual)
}
}
}
8 changes: 6 additions & 2 deletions internal/app/lwc/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const CARRIAGE_RETURN byte = 13
const LINE_FEED byte = 10
const SPACE byte = 32

func PrintCounts(counts *[]uint64, label string, cr bool, lf bool) {
func FormatCounts(counts *[]uint64, label string, cr bool, lf bool) string {
var sb strings.Builder
if cr {
sb.WriteByte(CARRIAGE_RETURN)
Expand All @@ -29,7 +29,11 @@ func PrintCounts(counts *[]uint64, label string, cr bool, lf bool) {
if lf {
sb.WriteByte(LINE_FEED)
}
os.Stdout.WriteString(sb.String())
return sb.String()
}

func PrintCounts(counts *[]uint64, label string, cr bool, lf bool) {
os.Stdout.WriteString(FormatCounts(counts, label, cr, lf))
}

func PollCounts(name string, counts *[]uint64, interval time.Duration, done chan bool) {
Expand Down
93 changes: 93 additions & 0 deletions internal/app/lwc/output_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package lwc

import (
"bufio"
"fmt"
"reflect"
"strings"
"testing"
)

type formatTest struct {
counts []uint64
label string
cr bool
lf bool
}

func (t *formatTest) expected() []string {
result := make([]string, len(t.counts))
for i, num := range t.counts {
result[i] = fmt.Sprintf("%d", num)
}
if t.label != "" {
result = append(result, t.label)
}
return result
}

func withWithout(b bool) string {
if b {
return "with"
} else {
return "without"
}
}

func tokenize(str string) []string {
tokens := make([]string, 100)
count := 0
scanner := bufio.NewScanner(strings.NewReader(str))
scanner.Split(bufio.ScanWords)
for scanner.Scan() {
tokens[count] = scanner.Text()
count++
}
return tokens[0:count]
}

var formatTests = []formatTest{
{
[]uint64{42939},
"",
false,
false,
},
{
[]uint64{42, 2993},
"bar",
true,
false,
},
{
[]uint64{90210},
"baz-quux",
false,
true,
},
{
[]uint64{123, 4567, 899999},
"/etc/passwd",
true,
true,
},
}

func TestFormatCounts(t *testing.T) {
for i, test := range formatTests {
result := FormatCounts(&test.counts, test.label, test.cr, test.lf)
hasCr := strings.HasPrefix(result, "\r")
if test.cr != hasCr {
t.Errorf("Test #%d failed: expecting string %s LF", i, withWithout(test.lf))
}
hasLf := strings.HasSuffix(result, "\n")
if test.lf != hasLf {
t.Errorf("Test #%d failed: expecting string %s LF", i, withWithout(test.lf))
}
actual := tokenize(result)
expected := test.expected()
if !reflect.DeepEqual(expected, actual) {
t.Errorf("Test #%d failed: expecting %#v, got %#v", i, expected, actual)
}
}
}
5 changes: 3 additions & 2 deletions internal/app/lwc/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ package lwc

import (
"fmt"
"os"
)

func Run(version string) {
// Read command-line args
config := BuildConfig()
config := BuildConfig(os.Args)

switch {
case config.Version:
// Print version and exit
fmt.Printf("lwc %s\n", version)
case config.Help:
// Print usage and exit
PrintUsage()
config.PrintUsage()
default:
// Process input
processors := BuildProcessors(&config)
Expand Down
18 changes: 9 additions & 9 deletions internal/app/lwc/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ import (

type ScanFunc func(*bufio.Scanner, *uint64, *uint64)

func ScanCount(scanner *bufio.Scanner, count *uint64, total *uint64) {
for scanner.Scan() {
atomic.AddUint64(count, 1)
if total != nil {
atomic.AddUint64(total, 1)
}
}
}

func ScanMaxLength(scanner *bufio.Scanner, count *uint64, total *uint64) {
var localMax uint64
var globalMax uint64
Expand All @@ -26,12 +35,3 @@ func ScanMaxLength(scanner *bufio.Scanner, count *uint64, total *uint64) {
}
}
}

func ScanCount(scanner *bufio.Scanner, count *uint64, total *uint64) {
for scanner.Scan() {
atomic.AddUint64(count, 1)
if total != nil {
atomic.AddUint64(total, 1)
}
}
}
Loading

0 comments on commit 82db424

Please sign in to comment.