128 lines
2.5 KiB
Go
128 lines
2.5 KiB
Go
// +build !change
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"gitlab.com/slon/shad-go/tools/testtool"
|
|
)
|
|
|
|
const wordcountImportPath = "gitlab.com/slon/shad-go/wordcount"
|
|
|
|
var binCache testtool.BinCache
|
|
|
|
func TestMain(m *testing.M) {
|
|
os.Exit(func() int {
|
|
var teardown testtool.CloseFunc
|
|
binCache, teardown = testtool.NewBinCache()
|
|
defer teardown()
|
|
|
|
return m.Run()
|
|
}())
|
|
}
|
|
|
|
func TestWordCount(t *testing.T) {
|
|
binary, err := binCache.GetBinary(wordcountImportPath)
|
|
require.Nil(t, err)
|
|
|
|
type counts map[string]int64
|
|
type files []string
|
|
|
|
for _, tc := range []struct {
|
|
name string
|
|
files files
|
|
expected map[string]int64
|
|
}{
|
|
{
|
|
name: "empty",
|
|
files: files{``},
|
|
expected: make(counts),
|
|
},
|
|
{
|
|
name: "simple",
|
|
files: files{
|
|
`a
|
|
a
|
|
b
|
|
|
|
|
|
a
|
|
b`,
|
|
},
|
|
expected: counts{"a": 3, "b": 2, "": 2},
|
|
},
|
|
{
|
|
name: "multiple-files",
|
|
files: files{
|
|
`a
|
|
a`,
|
|
`a
|
|
b`,
|
|
`b`,
|
|
},
|
|
expected: counts{"a": 3, "b": 2},
|
|
},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
// Create temp directory.
|
|
testDir, err := ioutil.TempDir("", "wordcount-testdata-")
|
|
require.Nil(t, err)
|
|
defer func() { _ = os.RemoveAll(testDir) }()
|
|
|
|
// Create test files in temp directory.
|
|
var files []string
|
|
for _, f := range tc.files {
|
|
file := path.Join(testDir, testtool.RandomName())
|
|
err = ioutil.WriteFile(file, []byte(f), 0644)
|
|
require.Nil(t, err)
|
|
files = append(files, file)
|
|
}
|
|
|
|
// Run wordcount executable.
|
|
cmd := exec.Command(binary, files...)
|
|
cmd.Stderr = os.Stderr
|
|
|
|
output, err := cmd.Output()
|
|
require.Nil(t, err)
|
|
|
|
// Parse output and compare with an expected one.
|
|
counts, err := parseStdout(output)
|
|
require.Nil(t, err)
|
|
|
|
require.True(t, reflect.DeepEqual(tc.expected, counts),
|
|
fmt.Sprintf("expected: %v; got: %v", tc.expected, counts))
|
|
})
|
|
}
|
|
}
|
|
|
|
// parseStdout parses wordcount's output of the ['<COUNT>\t<LINE>'] format.
|
|
func parseStdout(data []byte) (map[string]int64, error) {
|
|
counts := make(map[string]int64)
|
|
|
|
for _, line := range strings.Split(string(data), "\n") {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
parts := strings.SplitN(line, "\t", 2)
|
|
if len(parts) != 2 {
|
|
return nil, fmt.Errorf("unexpected line format: %s", parts)
|
|
}
|
|
c, err := strconv.ParseInt(parts[0], 10, 64)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to parse line count: %w", err)
|
|
}
|
|
counts[parts[1]] = c
|
|
}
|
|
|
|
return counts, nil
|
|
}
|