Skip to content

Commit

Permalink
add assert/save logs, update lint rules and make fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
dominicbarnes committed Oct 25, 2024
1 parent 53cb163 commit f7d0f4f
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 31 deletions.
15 changes: 14 additions & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
linters:
enable-all: true
disable:
- copyloopvar
- depguard
- err113
- execinquery
- exhaustruct
- funlen
- gochecknoglobals
Expand All @@ -11,14 +13,17 @@ linters:
- gofumpt
- gomnd
- inamedparam
- intrange
- ireturn
- lll
- maintidx
- mnd
- nestif
- nilnil
- nlreturn
- paralleltest
- revive
- tagalign
- testpackage
- tparallel
- varnamelen
Expand All @@ -29,4 +34,12 @@ linters-settings:
gosec:
excludes:
# 0644 permissions on created files seem reasonable for this use-case
- G306
- G306

govet:
enable-all: true
disable:
# fixing this is low-priority for this library
- fieldalignment
# we test invalid struct tags intentionally
- structtag
2 changes: 1 addition & 1 deletion logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type logger struct {
}

func (log *logger) Log(args ...any) {
log.t.Log(append([]any{log.prefix}, args...))
log.t.Log(append([]any{log.prefix}, args...)...)
}

func (log *logger) Logf(msg string, args ...any) {
Expand Down
17 changes: 10 additions & 7 deletions suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,7 @@ func (s *TestSuite) Run(t tester) {
}
}

var testNames []string
for testName := range testCases {
testNames = append(testNames, testName)
}
sort.Strings(testNames)

for _, testName := range testNames {
for _, testName := range getSortedTestNames(testCases) {
testCase := testCases[testName]

t.Run(testCase.Name, func(t *testing.T) {
Expand All @@ -163,6 +157,15 @@ func (s *TestSuite) Run(t tester) {
}
}

func getSortedTestNames(input map[string]TestCase) []string {
testNames := make([]string, 0, len(input))
for testName := range input {
testNames = append(testNames, testName)
}
sort.Strings(testNames)
return testNames
}

func listSubDirs(t tester, dir string) []string {
t.Helper()

Expand Down
15 changes: 15 additions & 0 deletions suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func TestRunTestSuite(t *testing.T) {
}

RunTestSuite(t, "testdata/suite/assert", func(t *testing.T, tc TestCase, test Test) Expected {
t.Helper()
return Expected{Output: strings.ToUpper(test.Input)}
})
}
Expand All @@ -29,6 +30,8 @@ func TestTestSuite(t *testing.T) {
suite := TestSuite{
Dir: "testdata/suite/single-case",
TestFunc: func(t *testing.T, tc TestCase) {
t.Helper()

cases = append(cases, tc)

type Test struct {
Expand Down Expand Up @@ -66,6 +69,8 @@ func TestTestSuite(t *testing.T) {
suite := TestSuite{
Dir: "testdata/suite/multiple-cases",
TestFunc: func(t *testing.T, tc TestCase) {
t.Helper()

cases = append(cases, tc)

type Test struct {
Expand Down Expand Up @@ -113,6 +118,8 @@ func TestTestSuite(t *testing.T) {
suite := TestSuite{
Dir: "testdata/suite/skip",
TestFunc: func(t *testing.T, tc TestCase) {
t.Helper()

cases = append(cases, tc)

type Test struct {
Expand Down Expand Up @@ -155,6 +162,8 @@ func TestTestSuite(t *testing.T) {
suite := TestSuite{
Dir: "testdata/suite/only",
TestFunc: func(t *testing.T, tc TestCase) {
t.Helper()

cases = append(cases, tc)

type Test struct {
Expand Down Expand Up @@ -194,6 +203,8 @@ func TestTestSuite(t *testing.T) {
Dir: "testdata/suite/shared-dir/cases",
SharedDir: "testdata/suite/shared-dir/common",
TestFunc: func(t *testing.T, tc TestCase) {
t.Helper()

cases = append(cases, tc)

type Test struct {
Expand Down Expand Up @@ -257,6 +268,8 @@ func TestTestSuite(t *testing.T) {
Dir: "testdata/suite/shared-dir-only/cases",
SharedDir: "testdata/suite/shared-dir-only/common",
TestFunc: func(t *testing.T, tc TestCase) {
t.Helper()

cases = append(cases, tc)

type Test struct {
Expand Down Expand Up @@ -299,6 +312,8 @@ func TestTestSuite(t *testing.T) {
Dir: "testdata/suite/shared-dir-skip/cases",
SharedDir: "testdata/suite/shared-dir-skip/common",
TestFunc: func(t *testing.T, tc TestCase) {
t.Helper()

cases = append(cases, tc)

type Test struct {
Expand Down
31 changes: 19 additions & 12 deletions testdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"reflect"
"sort"

"github.com/dominicbarnes/got/codec"
"github.com/fatih/structtag"
Expand Down Expand Up @@ -195,13 +196,13 @@ func loadDirInput(log *logger, input string, tag *structtag.Tag, field reflect.S
}

key := reflect.ValueOf(rel)
value := reflect.New(m.Type().Elem()).Elem()
val := reflect.New(m.Type().Elem()).Elem()

if err := loadFile(log.WithPrefix(fmt.Sprintf("field %s", field.Name)), match, value); err != nil {
if err := loadFile(log.WithPrefix("field "+field.Name), match, val); err != nil {
return fmt.Errorf("field %s: %w", field.Name, err)
}

m.SetMapIndex(key, value)
m.SetMapIndex(key, val)
}

if m.Len() > 0 {
Expand All @@ -211,7 +212,7 @@ func loadDirInput(log *logger, input string, tag *structtag.Tag, field reflect.S
return nil
}

if err := loadFile(log.WithPrefix(fmt.Sprintf("field %s", field.Name)), file, value); err != nil {
if err := loadFile(log.WithPrefix("field "+field.Name), file, value); err != nil {
return err
}

Expand Down Expand Up @@ -285,7 +286,7 @@ func saveDir(log *logger, dir string, input any) error {
continue
}

if err := saveDirField(log.WithPrefix(fmt.Sprintf("field %s", field.Name)), dir, tag, field, value); err != nil {
if err := saveDirField(log.WithPrefix("field "+field.Name), dir, tag, field, value); err != nil {
return fmt.Errorf("field %s error: %w", field.Name, err)
}
}
Expand All @@ -295,11 +296,13 @@ func saveDir(log *logger, dir string, input any) error {

func saveDirField(log *logger, dir string, tag *structtag.Tag, field reflect.StructField, value reflect.Value) error {
if isMap(field.Type) && tag.HasOption("explode") {
iter := value.MapRange()
keys := value.MapKeys()
sort.Slice(keys, func(i, j int) bool {
return keys[i].String() < keys[j].String()
})

for iter.Next() {
k := iter.Key()
v := iter.Value()
for _, k := range keys {
v := value.MapIndex(k)

file := filepath.Join(dir, k.String())
if err := saveFile(log, file, v); err != nil {
Expand All @@ -319,9 +322,9 @@ func saveDirField(log *logger, dir string, tag *structtag.Tag, field reflect.Str
}

func saveFile(log *logger, file string, val reflect.Value) error {
data, err := encode(log, file, val)
data, err := encode(file, val)
if err != nil {
return fmt.Errorf("failed to encode file %s: %w", file, err)
return fmt.Errorf("failed to encode file %q: %w", file, err)
}

if len(data) == 0 {
Expand All @@ -330,6 +333,8 @@ func saveFile(log *logger, file string, val reflect.Value) error {
return fmt.Errorf("failed to delete file %s: %w", file, err)
}
}

log.Logf("removed file %q: empty", file)
} else {
dir := filepath.Dir(file)

Expand All @@ -340,12 +345,14 @@ func saveFile(log *logger, file string, val reflect.Value) error {
if err := os.WriteFile(file, data, 0644); err != nil {
return fmt.Errorf("failed to write file %s: %w", file, err)
}

log.Logf("saved file %q (size %d)", file, len(data))
}

return nil
}

func encode(log *logger, file string, val reflect.Value) ([]byte, error) {
func encode(file string, val reflect.Value) ([]byte, error) {
switch {
case val.IsZero():
return nil, nil
Expand Down
53 changes: 43 additions & 10 deletions testdata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ func TestAssert(t *testing.T) {
name string
expected any
fail bool
logs []string
}{
{
name: "string",
Expand All @@ -408,6 +409,9 @@ func TestAssert(t *testing.T) {
}{
Input: "hello world",
},
logs: []string{
`[GoT] Assert: field Input: saved file "<tmp>/input.txt" (size 11)`,
},
},
{
name: "bytes",
Expand All @@ -416,6 +420,9 @@ func TestAssert(t *testing.T) {
}{
Input: []byte("hello world"),
},
logs: []string{
`[GoT] Assert: field Input: saved file "<tmp>/input.txt" (size 11)`,
},
},
{
name: "json raw",
Expand All @@ -424,6 +431,9 @@ func TestAssert(t *testing.T) {
}{
Input: json.RawMessage(`{}`),
},
logs: []string{
`[GoT] Assert: field Input: saved file "<tmp>/input.json" (size 2)`,
},
},
{
name: "json struct",
Expand All @@ -438,6 +448,9 @@ func TestAssert(t *testing.T) {
Hello: "world",
},
},
logs: []string{
`[GoT] Assert: field Input: saved file "<tmp>/input.json" (size 22)`,
},
},
{
name: "map json",
Expand All @@ -446,6 +459,9 @@ func TestAssert(t *testing.T) {
}{
Input: map[string]string{"hello": "world"},
},
logs: []string{
`[GoT] Assert: field Input: saved file "<tmp>/input.json" (size 22)`,
},
},
{
name: "map explode",
Expand All @@ -454,6 +470,10 @@ func TestAssert(t *testing.T) {
}{
Files: map[string]string{"a.txt": "A", "b.txt": "B"},
},
logs: []string{
`[GoT] Assert: field Files: saved file "<tmp>/a.txt" (size 1)`,
`[GoT] Assert: field Files: saved file "<tmp>/b.txt" (size 1)`,
},
},
{
name: "unknown codec",
Expand All @@ -476,6 +496,9 @@ func TestAssert(t *testing.T) {
Output string `testdata:"output.txt"`
Empty string `testdata:"-"`
}{},
logs: []string{
`[GoT] Assert: field Output: removed file "<tmp>/output.txt": empty`,
},
},
{
name: "struct tag empty",
Expand All @@ -485,6 +508,9 @@ func TestAssert(t *testing.T) {
}{
Output: "hello world",
},
logs: []string{
`[GoT] Assert: field Output: saved file "<tmp>/output.txt" (size 11)`,
},
},
{
name: "struct tag dash",
Expand All @@ -494,16 +520,17 @@ func TestAssert(t *testing.T) {
}{
Output: "hello world",
},
logs: []string{
`[GoT] Assert: field Output: saved file "<tmp>/output.txt" (size 11)`,
},
},
{
name: "struct tag invalid",
expected: &struct {
Output string `testdata:"invalid...`
}{},
fail: true,
},
// FIXME: go vet will not allow code with invalid struct tags, even
// if we are intentionally testing this behavior
// {
// name: "struct tag invalid",
// expected: &struct {
// Output string `testdata:"invalid...`
// }{},
// fail: true,
// },
{
name: "struct tag missing",
expected: &struct {
Expand Down Expand Up @@ -538,8 +565,14 @@ func TestAssert(t *testing.T) {
Load(t, dir, actual)
require.EqualValues(t, test.expected, actual)

// strip the temp directory name from logs, as it makes the
// assertion non-deterministic
for i := range mt.logs {
mt.logs[i] = strings.ReplaceAll(mt.logs[i], dir, "<tmp>")
}

require.False(t, mt.failed)
require.Empty(t, mt.logs)
require.EqualValues(t, test.logs, mt.logs)
}

require.True(t, mt.helper)
Expand Down

0 comments on commit f7d0f4f

Please sign in to comment.