Files
go-golden/golden_test.go

999 lines
24 KiB
Go

package golden
import (
"fmt"
"io/fs"
"path/filepath"
"reflect"
"runtime"
"sync"
"testing"
"github.com/jimeh/envctl"
"github.com/jimeh/go-golden/test/testfs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
//
// Test Helpers
//
func funcID(f interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
}
func prepareDefaultGoldenForTests(t *testing.T) *testfs.FS {
realDefault := DefaultGolden
t.Cleanup(func() { DefaultGolden = realDefault })
fs := testfs.New()
DefaultGolden = New(WithFS(fs))
return fs
}
func testInGoroutine(t *testing.T, f func()) {
t.Helper()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
f()
}()
wg.Wait()
}
//
// Tests
//
func TestDefault(t *testing.T) {
require.IsType(t, &gold{}, DefaultGolden)
dg := DefaultGolden.(*gold)
assert.Equal(t, fs.FileMode(0o755), dg.dirMode)
assert.Equal(t, fs.FileMode(0o644), dg.fileMode)
assert.Equal(t, ".golden", dg.suffix)
assert.Equal(t, "testdata", dg.dirname)
assert.Equal(t, funcID(EnvUpdateFunc), funcID(dg.updateFunc))
assert.Equal(t, NewFS(), dg.fs)
assert.Equal(t, true, dg.logOnWrite)
}
func TestDo(t *testing.T) {
tests := []struct {
name string
testName string
content []byte
existing []byte
wantFilepath string
wantNoUpdateLogs []string
wantNoUpdateFatals []string
wantUpdateLogs []string
wantUpdateFatals []string
}{
{
name: "empty test name",
testName: "",
wantUpdateFatals: []string{
"golden: could not determine filename for TestingT instance",
},
wantNoUpdateFatals: []string{
"golden: could not determine filename for TestingT instance",
},
},
{
name: "without slashes",
testName: "TestFoo",
content: []byte("new content"),
existing: []byte("old content"),
wantFilepath: filepath.Join("testdata", "TestFoo.golden"),
wantUpdateLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestFoo.golden"),
),
},
},
{
name: "with slashes",
testName: "TestFoo/bar",
content: []byte("new stuff with slashes"),
existing: []byte("old stuff"),
wantFilepath: filepath.Join("testdata", "TestFoo", "bar.golden"),
wantUpdateLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestFoo", "bar.golden"),
),
},
},
{
name: "with spaces and special characters",
testName: `TestFoo/John's "lost" flip-flop?<>:*|"`,
content: []byte("Did John lose his flip-flop again?"),
existing: []byte("Where is the flip-flop?"),
wantFilepath: filepath.Join(
"testdata", "TestFoo", "John's__lost__flip-flop_______.golden",
),
wantUpdateLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join(
"testdata", "TestFoo",
"John's__lost__flip-flop_______.golden",
),
),
},
},
{
name: "does not exist",
testName: "TestFoo/nope",
content: []byte("new stuff with slashes"),
existing: nil,
wantFilepath: filepath.Join("testdata", "TestFoo", "nope.golden"),
wantUpdateLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestFoo", "nope.golden"),
),
},
wantNoUpdateFatals: []string{
fmt.Sprintf(
"golden: open %s: no such file or directory",
filepath.Join(
"/root", "testdata", "TestFoo", "nope.golden",
),
),
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name+"/no update", func(t *testing.T) {
require.False(t, Update())
fs := prepareDefaultGoldenForTests(t)
ft := &fakeTestingT{name: tt.testName}
if tt.existing != nil {
err := fs.MkdirAll(filepath.Dir(tt.wantFilepath), 0o755)
require.NoError(t, err)
err = fs.WriteFile(tt.wantFilepath, tt.existing, 0o600)
require.NoError(t, err)
}
var got []byte
testInGoroutine(t, func() {
got = Do(ft, tt.content)
})
if tt.existing == nil {
assert.Equal(t, tt.existing, got)
} else {
assert.GreaterOrEqual(t, 1, len(ft.fatals))
}
assert.Equal(t, tt.wantNoUpdateFatals, ft.fatals)
assert.Equal(t, tt.wantNoUpdateLogs, ft.logs)
})
t.Run(tt.name+"/update", func(t *testing.T) {
envctl.WithClean(map[string]string{"GOLDEN_UPDATE": "1"}, func() {
require.True(t, Update())
fs := prepareDefaultGoldenForTests(t)
ft := &fakeTestingT{name: tt.testName}
if tt.existing != nil {
err := fs.MkdirAll(filepath.Dir(tt.wantFilepath), 0o755)
require.NoError(t, err)
err = fs.WriteFile(tt.wantFilepath, tt.existing, 0o600)
require.NoError(t, err)
}
var got []byte
testInGoroutine(t, func() {
got = Do(ft, tt.content)
})
assert.Equal(t, tt.content, got)
assert.Equal(t, tt.wantUpdateFatals, ft.fatals)
assert.Equal(t, tt.wantUpdateLogs, ft.logs)
})
})
}
}
func TestDoP(t *testing.T) {
tests := []struct {
name string
testName string
goldenName string
content []byte
existing []byte
wantFilepath string
wantNoUpdateLogs []string
wantNoUpdateFatals []string
wantUpdateLogs []string
wantUpdateFatals []string
}{
{
name: "empty test name",
testName: "",
goldenName: "junk",
wantUpdateFatals: []string{
"golden: could not determine filename for TestingT instance",
},
wantNoUpdateFatals: []string{
"golden: could not determine filename for TestingT instance",
},
},
{
name: "empty golden name",
testName: "TestBar",
goldenName: "",
wantUpdateFatals: []string{
"golden: name cannot be empty",
},
wantNoUpdateFatals: []string{
"golden: name cannot be empty",
},
},
{
name: "without slashes",
testName: "TestBar",
goldenName: "foo",
content: []byte("new content"),
existing: []byte("old content"),
wantFilepath: filepath.Join("testdata", "TestBar", "foo.golden"),
wantUpdateLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestBar", "foo.golden"),
),
},
},
{
name: "with slashes in test name",
testName: "TestBar/foo",
goldenName: "junk",
content: []byte("new stuff with slashes"),
existing: []byte("old stuff"),
wantFilepath: filepath.Join(
"testdata", "TestBar", "foo", "junk.golden",
),
wantUpdateLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestBar", "foo", "junk.golden"),
),
},
},
{
name: "with slashes in golden name",
testName: "TestBar",
goldenName: "foo/junk",
content: []byte("new stuff with slashes"),
existing: []byte("old stuff"),
wantFilepath: filepath.Join(
"testdata", "TestBar", "foo", "junk.golden",
),
wantUpdateLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestBar", "foo", "junk.golden"),
),
},
},
{
name: "with spaces and special characters",
testName: `TestBar/John's "lost" flip-flop?<>:*|"`,
goldenName: "junk/*plastic*",
content: []byte("Did John lose his flip-flop again?"),
existing: []byte("Where is the flip-flop?"),
wantFilepath: filepath.Join(
"testdata", "TestBar", "John's__lost__flip-flop_______",
"junk", "_plastic_.golden",
),
wantUpdateLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join(
"testdata", "TestBar", "John's__lost__flip-flop_______",
"junk", "_plastic_.golden",
),
),
},
},
{
name: "does not exist",
testName: "TestBar",
goldenName: "junk",
content: []byte("new stuff with slashes"),
existing: nil,
wantFilepath: filepath.Join("testdata", "TestBar", "junk.golden"),
wantUpdateLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestBar", "junk.golden"),
),
},
wantNoUpdateFatals: []string{
fmt.Sprintf(
"golden: open %s: no such file or directory",
filepath.Join(
"/root", "testdata", "TestBar", "junk.golden",
),
),
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name+"/no update", func(t *testing.T) {
require.False(t, Update())
fs := prepareDefaultGoldenForTests(t)
ft := &fakeTestingT{name: tt.testName}
if tt.existing != nil {
err := fs.MkdirAll(filepath.Dir(tt.wantFilepath), 0o755)
require.NoError(t, err)
err = fs.WriteFile(tt.wantFilepath, tt.existing, 0o600)
require.NoError(t, err)
}
var got []byte
testInGoroutine(t, func() {
got = DoP(ft, tt.goldenName, tt.content)
})
if tt.existing == nil {
assert.Equal(t, tt.existing, got)
} else {
assert.GreaterOrEqual(t, 1, len(ft.fatals))
}
assert.Equal(t, tt.wantNoUpdateFatals, ft.fatals)
assert.Equal(t, tt.wantNoUpdateLogs, ft.logs)
})
t.Run(tt.name+"/update", func(t *testing.T) {
envctl.WithClean(map[string]string{"GOLDEN_UPDATE": "1"}, func() {
require.True(t, Update())
fs := prepareDefaultGoldenForTests(t)
ft := &fakeTestingT{name: tt.testName}
if tt.existing != nil {
err := fs.MkdirAll(filepath.Dir(tt.wantFilepath), 0o755)
require.NoError(t, err)
err = fs.WriteFile(tt.wantFilepath, tt.existing, 0o600)
require.NoError(t, err)
}
var got []byte
testInGoroutine(t, func() {
got = DoP(ft, tt.goldenName, tt.content)
})
assert.Equal(t, tt.content, got)
assert.Equal(t, tt.wantUpdateFatals, ft.fatals)
assert.Equal(t, tt.wantUpdateLogs, ft.logs)
})
})
}
}
func TestFile(t *testing.T) {
tests := []struct {
name string
testName string
want string
wantFatals []string
}{
{
name: "empty test name",
testName: "",
wantFatals: []string{
"golden: could not determine filename for TestingT instance",
},
},
{
name: "without slashes",
testName: "TestFoo",
want: filepath.Join("testdata", "TestFoo.golden"),
},
{
name: "with slashes",
testName: "TestFoo/bar",
want: filepath.Join("testdata", "TestFoo", "bar.golden"),
},
{
name: "with slashes and special characters",
testName: `TestFoo/John's "lost" flip-flop?<>:*|"`,
want: filepath.Join(
"testdata", "TestFoo", "John's__lost__flip-flop_______.golden",
),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ft := &fakeTestingT{name: tt.testName}
var got string
testInGoroutine(t, func() {
got = File(ft)
})
assert.Equal(t, tt.want, got)
assert.Equal(t, tt.wantFatals, ft.fatals)
})
}
}
func TestFileP(t *testing.T) {
tests := []struct {
name string
testName string
goldenName string
want string
wantFatals []string
}{
{
name: "empty test name",
testName: "",
goldenName: "junk",
wantFatals: []string{
"golden: could not determine filename for TestingT instance",
},
},
{
name: "empty golden name",
testName: "TestFoo",
goldenName: "",
wantFatals: []string{
"golden: name cannot be empty",
},
},
{
name: "without slashes",
testName: "TestFoo",
goldenName: "bar",
want: filepath.Join("testdata", "TestFoo", "bar.golden"),
},
{
name: "slashes in test name",
testName: "TestFoo/bar",
goldenName: "junk",
want: filepath.Join(
"testdata", "TestFoo", "bar", "junk.golden",
),
},
{
name: "slashes in golden name",
testName: "TestFoo",
goldenName: "bar/junk",
want: filepath.Join(
"testdata", "TestFoo", "bar", "junk.golden",
),
},
{
name: "slashes in test and golden name",
testName: "TestFoo/bar",
goldenName: "junk/plastic",
want: filepath.Join(
"testdata", "TestFoo", "bar", "junk", "plastic.golden",
),
},
{
name: "slashes and special characters",
testName: `TestFoo/John's "lost" flip-flop?<>:*|"`,
goldenName: "junk/*plastic*",
want: filepath.Join(
"testdata", "TestFoo", "John's__lost__flip-flop_______",
"junk", "_plastic_.golden",
),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ft := &fakeTestingT{name: tt.testName}
var got string
testInGoroutine(t, func() {
got = FileP(ft, tt.goldenName)
})
assert.Equal(t, tt.want, got)
assert.Equal(t, tt.wantFatals, ft.fatals)
})
}
}
func TestGet(t *testing.T) {
tests := []struct {
name string
testName string
files map[string][]byte
want []byte
wantFatals []string
}{
{
name: "empty test name",
testName: "",
wantFatals: []string{
"golden: could not determine filename for TestingT instance",
},
},
{
name: "without slashes",
testName: "TestFoo",
files: map[string][]byte{
filepath.Join("testdata", "TestFoo.golden"): []byte("bar\n"),
},
want: []byte("bar\n"),
},
{
name: "with slashes",
testName: "TestFoo/bar",
files: map[string][]byte{
filepath.Join("testdata", "TestFoo", "bar.golden"): []byte(
"bar\n",
),
},
want: []byte("bar\n"),
},
{
name: "with slashes and special characters",
testName: `TestFoo/John's "lost" flip-flop?<>:*|"`,
files: map[string][]byte{
filepath.Join(
"testdata", "TestFoo",
"John's__lost__flip-flop_______.golden",
): []byte("bar nope\n"),
},
want: []byte("bar nope\n"),
},
{
name: "file does not exist",
testName: "TestFoo",
files: map[string][]byte{},
wantFatals: []string{
fmt.Sprintf(
"golden: open %s: no such file or directory",
filepath.Join("/root", "testdata", "TestFoo.golden"),
),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fs := prepareDefaultGoldenForTests(t)
ft := &fakeTestingT{name: tt.testName}
for file, content := range tt.files {
err := fs.MkdirAll(filepath.Dir(file), 0o755)
require.NoError(t, err)
err = fs.WriteFile(file, content, 0o600)
require.NoError(t, err)
}
var got []byte
testInGoroutine(t, func() {
got = Get(ft)
})
assert.Equal(t, tt.want, got)
assert.Equal(t, tt.wantFatals, ft.fatals)
})
}
}
func TestGetP(t *testing.T) {
tests := []struct {
name string
testName string
goldenName string
files map[string][]byte
want []byte
wantFatals []string
}{
{
name: "empty test name",
testName: "",
goldenName: "junk",
wantFatals: []string{
"golden: could not determine filename for TestingT instance",
},
},
{
name: "empty golden name",
testName: "TestBar",
goldenName: "",
wantFatals: []string{
"golden: name cannot be empty",
},
},
{
name: "without slashes",
testName: "TestBar",
goldenName: "junk",
files: map[string][]byte{
filepath.Join("testdata", "TestBar", "junk.golden"): []byte(
"foo junk\n",
),
},
want: []byte("foo junk\n"),
},
{
name: "with slashes in test name",
testName: "TestBar/foo",
goldenName: "junk",
files: map[string][]byte{
filepath.Join(
"testdata", "TestBar", "foo", "junk.golden",
): []byte("foo\n"),
},
want: []byte("foo\n"),
},
{
name: "with slashes in golden name",
testName: "TestBar",
goldenName: "foo/junk",
files: map[string][]byte{
filepath.Join(
"testdata", "TestBar", "foo", "junk.golden",
): []byte("foo\n"),
},
want: []byte("foo\n"),
},
{
name: "slashes and special characters",
testName: `TestFoo/John's "lost" flip-flop?<>:*|"`,
goldenName: "junk/*plastic*",
files: map[string][]byte{
filepath.Join(
"testdata", "TestFoo", "John's__lost__flip-flop_______",
"junk", "_plastic_.golden",
): []byte("junk here\n"),
},
want: []byte("junk here\n"),
},
{
name: "file does not exist",
testName: "TestBar",
goldenName: "junk",
files: map[string][]byte{},
wantFatals: []string{
fmt.Sprintf(
"golden: open %s: no such file or directory",
filepath.Join(
"/root", "testdata", "TestBar", "junk.golden",
),
),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fs := prepareDefaultGoldenForTests(t)
ft := &fakeTestingT{name: tt.testName}
for file, content := range tt.files {
err := fs.MkdirAll(filepath.Dir(file), 0o755)
require.NoError(t, err)
err = fs.WriteFile(file, content, 0o600)
require.NoError(t, err)
}
var got []byte
testInGoroutine(t, func() {
got = GetP(ft, tt.goldenName)
})
assert.Equal(t, tt.want, got)
assert.Equal(t, tt.wantFatals, ft.fatals)
})
}
}
func TestSet(t *testing.T) {
tests := []struct {
name string
testName string
wantFilepath string
content []byte
wantLogs []string
wantFatals []string
}{
{
name: "empty test name",
testName: "",
wantFatals: []string{
"golden: could not determine filename for TestingT instance",
},
},
{
name: "without slashes",
testName: "TestFoo",
content: []byte("foobar here"),
wantFilepath: filepath.Join("testdata", "TestFoo.golden"),
wantLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestFoo.golden"),
),
},
},
{
name: "with slashes",
testName: "TestFoo/bar",
content: []byte("foo/bar style sub-sub-folders works too"),
wantFilepath: filepath.Join("testdata", "TestFoo", "bar.golden"),
wantLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestFoo", "bar.golden"),
),
},
},
{
name: "with spaces and special characters",
testName: `TestFoo/John's "lost" flip-flop?<>:*|"`,
content: []byte("Did John lose his flip-flop again?"),
wantFilepath: filepath.Join(
"testdata", "TestFoo", "John's__lost__flip-flop_______.golden",
),
wantLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join(
"testdata", "TestFoo",
"John's__lost__flip-flop_______.golden",
),
),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fs := prepareDefaultGoldenForTests(t)
ft := &fakeTestingT{name: tt.testName}
testInGoroutine(t, func() {
Set(ft, tt.content)
})
assert.Equal(t, tt.wantLogs, ft.logs)
if len(tt.wantFatals) == 0 {
got, err := fs.ReadFile(tt.wantFilepath)
require.NoError(t, err)
assert.Equal(t, tt.content, got)
filePerms, err := fs.FileMode(tt.wantFilepath)
require.NoError(t, err)
dirPerms, err := fs.FileMode(filepath.Dir(tt.wantFilepath))
require.NoError(t, err)
assert.Equal(t, filePerms, DefaultFileMode)
assert.Equal(t, dirPerms, DefaultDirMode)
} else {
assert.Equal(t, tt.wantFatals, ft.fatals)
assert.False(t,
fs.Exists(tt.wantFilepath),
"file should not exist",
)
}
})
}
}
func TestSetP(t *testing.T) {
tests := []struct {
name string
testName string
goldenName string
wantFilepath string
content []byte
wantLogs []string
wantFatals []string
}{
{
name: "empty test name",
testName: "",
goldenName: "junk",
wantFatals: []string{
"golden: could not determine filename for TestingT instance",
},
},
{
name: "empty golden name",
testName: "TestBar",
goldenName: "",
wantFatals: []string{
"golden: name cannot be empty",
},
},
{
name: "without slashes",
testName: "TestBar",
goldenName: "junk",
content: []byte("junk here"),
wantFilepath: filepath.Join("testdata", "TestBar", "junk.golden"),
wantLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestBar", "junk.golden"),
),
},
},
{
name: "with slashes in test name",
testName: "TestBar/foo",
goldenName: "junk",
content: []byte("foo/bar style sub-sub-folders works too"),
wantFilepath: filepath.Join(
"testdata", "TestBar", "foo", "junk.golden",
),
wantLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestBar", "foo", "junk.golden"),
),
},
},
{
name: "with slashes in golden name",
testName: "TestBar",
goldenName: "foo/junk",
content: []byte("foo/bar style sub-sub-folders works too"),
wantFilepath: filepath.Join(
"testdata", "TestBar", "foo", "junk.golden",
),
wantLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join("testdata", "TestBar", "foo", "junk.golden"),
),
},
},
{
name: "slashes and special characters",
testName: `TestFoo/John's "lost" flip-flop?<>:*|"`,
goldenName: "junk/*plastic*",
content: []byte("Did John lose his flip-flop again?"),
wantFilepath: filepath.Join(
"testdata", "TestFoo", "John's__lost__flip-flop_______",
"junk", "_plastic_.golden",
),
wantLogs: []string{
fmt.Sprintf(
"golden: writing golden file: %s",
filepath.Join(
"testdata", "TestFoo", "John's__lost__flip-flop_______",
"junk", "_plastic_.golden",
),
),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fs := prepareDefaultGoldenForTests(t)
ft := &fakeTestingT{name: tt.testName}
testInGoroutine(t, func() {
SetP(ft, tt.goldenName, tt.content)
})
assert.Equal(t, tt.wantLogs, ft.logs)
if len(tt.wantFatals) == 0 {
got, err := fs.ReadFile(tt.wantFilepath)
require.NoError(t, err)
assert.Equal(t, tt.content, got)
filePerms, err := fs.FileMode(tt.wantFilepath)
require.NoError(t, err)
dirPerms, err := fs.FileMode(filepath.Dir(tt.wantFilepath))
require.NoError(t, err)
assert.Equal(t, filePerms, DefaultFileMode)
assert.Equal(t, dirPerms, DefaultDirMode)
} else {
assert.Equal(t, tt.wantFatals, ft.fatals)
assert.False(t, fs.Exists(tt.wantFilepath))
}
})
}
}
func TestUpdate(t *testing.T) {
for _, tt := range envUpdateFuncTestCases {
t.Run(tt.name, func(t *testing.T) {
envctl.WithClean(tt.env, func() {
got := Update()
assert.Equal(t, tt.want, got)
})
})
}
}
func TestNew(t *testing.T) {
myUpdateFunc := func() bool { return false }
type args struct {
options []Option
}
tests := []struct {
name string
args args
want *gold
}{
{
name: "no options",
args: args{options: nil},
want: &gold{
dirMode: 0o755,
fileMode: 0o644,
suffix: ".golden",
dirname: "testdata",
updateFunc: EnvUpdateFunc,
fs: NewFS(),
logOnWrite: true,
},
},
{
name: "all options",
args: args{
options: []Option{
WithDirMode(0o777),
WithFileMode(0o666),
WithSuffix(".gold"),
WithDirname("goldstuff"),
WithUpdateFunc(myUpdateFunc),
WithFS(testfs.New()),
WithSilentWrites(),
},
},
want: &gold{
dirMode: 0o777,
fileMode: 0o666,
suffix: ".gold",
dirname: "goldstuff",
updateFunc: myUpdateFunc,
fs: testfs.New(),
logOnWrite: false,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := New(tt.args.options...)
got, ok := g.(*gold)
require.True(t, ok, "New did not returns a *gold type")
assert.Equal(t, tt.want.dirMode, got.dirMode)
assert.Equal(t, tt.want.fileMode, got.fileMode)
assert.Equal(t, tt.want.suffix, got.suffix)
assert.Equal(t, tt.want.dirname, got.dirname)
assert.Equal(t, funcID(tt.want.updateFunc), funcID(got.updateFunc))
assert.IsType(t, tt.want.fs, got.fs)
assert.Equal(t, tt.want.logOnWrite, got.logOnWrite)
})
}
}