diff --git a/kyaml/kio/pkgio_reader.go b/kyaml/kio/pkgio_reader.go index f2ed9f004..4279e6c91 100644 --- a/kyaml/kio/pkgio_reader.go +++ b/kyaml/kio/pkgio_reader.go @@ -9,6 +9,7 @@ import ( "path/filepath" "sigs.k8s.io/kustomize/kyaml/errors" + "sigs.k8s.io/kustomize/kyaml/filesys" "sigs.k8s.io/kustomize/kyaml/kio/kioutil" "sigs.k8s.io/kustomize/kyaml/sets" "sigs.k8s.io/kustomize/kyaml/yaml" @@ -78,6 +79,9 @@ type LocalPackageReadWriter struct { // FileSkipFunc is a function which returns true if reader should ignore // the file FileSkipFunc LocalPackageSkipFileFunc + + // FileSystem can be used to mock the disk file system. + FileSystem filesys.FileSystemOrOnDisk } func (r *LocalPackageReadWriter) Read() ([]*yaml.RNode, error) { @@ -90,6 +94,7 @@ func (r *LocalPackageReadWriter) Read() ([]*yaml.RNode, error) { PackageFileName: r.PackageFileName, FileSkipFunc: r.FileSkipFunc, PreserveSeqIndent: r.PreserveSeqIndent, + FileSystem: r.FileSystem, }.Read() if err != nil { return nil, errors.Wrap(err) @@ -184,6 +189,9 @@ type LocalPackageReader struct { // PreserveSeqIndent if true adds kioutil.SeqIndentAnnotation to each resource PreserveSeqIndent bool + + // FileSystem can be used to mock the disk file system. + FileSystem filesys.FileSystemOrOnDisk } var _ Reader = LocalPackageReader{} @@ -207,12 +215,15 @@ func (r LocalPackageReader) Read() ([]*yaml.RNode, error) { var operand ResourceNodeSlice var pathRelativeTo string var err error - ignoreFilesMatcher := &ignoreFilesMatcher{} - r.PackagePath, err = filepath.Abs(r.PackagePath) + ignoreFilesMatcher := &ignoreFilesMatcher{ + fs: r.FileSystem, + } + dir, file, err := r.FileSystem.CleanedAbs(r.PackagePath) if err != nil { return nil, errors.Wrap(err) } - err = filepath.Walk(r.PackagePath, func( + r.PackagePath = filepath.Join(string(dir), file) + err = r.FileSystem.Walk(r.PackagePath, func( path string, info os.FileInfo, err error) error { if err != nil { return errors.Wrap(err) @@ -263,7 +274,7 @@ func (r LocalPackageReader) Read() ([]*yaml.RNode, error) { // readFile reads the ResourceNodes from a file func (r *LocalPackageReader) readFile(path string, _ os.FileInfo) ([]*yaml.RNode, error) { - f, err := os.Open(path) + f, err := r.FileSystem.Open(path) if err != nil { return nil, err } @@ -321,11 +332,8 @@ func (r *LocalPackageReader) shouldSkipDir(path string, matcher *ignoreFilesMatc return nil } // check if this is a subpackage - _, err := os.Stat(filepath.Join(path, r.PackageFileName)) - if os.IsNotExist(err) { + if !r.FileSystem.Exists(filepath.Join(path, r.PackageFileName)) { return nil - } else if err != nil { - return errors.Wrap(err) } if !r.IncludeSubpackages { return filepath.SkipDir diff --git a/kyaml/kio/pkgio_reader_test.go b/kyaml/kio/pkgio_reader_test.go index e5462d88a..a6df5ec10 100644 --- a/kyaml/kio/pkgio_reader_test.go +++ b/kyaml/kio/pkgio_reader_test.go @@ -5,10 +5,12 @@ package kio_test import ( "path/filepath" + "runtime" "strings" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "sigs.k8s.io/kustomize/kyaml/filesys" . "sigs.k8s.io/kustomize/kyaml/kio" ) @@ -42,36 +44,27 @@ var pkgFile = []byte(``) func TestLocalPackageReader_Read_empty(t *testing.T) { var r LocalPackageReader nodes, err := r.Read() - if assert.Error(t, err) { - assert.Contains(t, err.Error(), "must specify package path") - } - assert.Nil(t, nodes) + require.Error(t, err) + require.Contains(t, err.Error(), "must specify package path") + require.Nil(t, nodes) } func TestLocalPackageReader_Read_pkg(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - s.WriteFile(t, filepath.Join("a_test.yaml"), readFileA) - s.WriteFile(t, filepath.Join("b_test.yaml"), readFileB) - s.WriteFile(t, filepath.Join("c_test.yaml"), readFileC) - s.WriteFile(t, filepath.Join("d_test.yaml"), readFileD) - - paths := []struct { - path string - }{ - {path: "./"}, - {path: s.Root}, - } - for _, p := range paths { - rfr := LocalPackageReader{PackagePath: p.path} + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a_test.yaml", content: readFileA}, + {path: "b_test.yaml", content: readFileB}, + {path: "c_test.yaml", content: readFileC}, + {path: "d_test.yaml", content: readFileD}, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { + rfr := LocalPackageReader{ + PackagePath: path, + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, + } nodes, err := rfr.Read() - if !assert.NoError(t, err) { - return - } - - if !assert.Len(t, nodes, 5) { - return - } + require.NoError(t, err) + require.Len(t, nodes, 5) expected := []string{ `a: b #first metadata: @@ -111,45 +104,29 @@ metadata: } for i := range nodes { val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } + require.NoError(t, err) + require.Equal(t, expected[i], val) } - } + }) } func TestLocalPackageReader_Read_pkgAndSkipFile(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - s.WriteFile(t, filepath.Join("a_test.yaml"), readFileA) - s.WriteFile(t, filepath.Join("b_test.yaml"), readFileB) - s.WriteFile(t, filepath.Join("c_test.yaml"), readFileC) - s.WriteFile(t, filepath.Join("d_test.yaml"), readFileD) - - paths := []struct { - path string - }{ - {path: "./"}, - {path: s.Root}, - } - for _, p := range paths { + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a_test.yaml", content: readFileA}, + {path: "b_test.yaml", content: readFileB}, + {path: "c_test.yaml", content: readFileC}, + {path: "d_test.yaml", content: readFileD}, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { rfr := LocalPackageReader{ - PackagePath: p.path, - FileSkipFunc: func(relPath string) bool { - return relPath == "d_test.yaml" - }, + PackagePath: path, + FileSkipFunc: func(relPath string) bool { return relPath == "d_test.yaml" }, + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, } nodes, err := rfr.Read() - if !assert.NoError(t, err) { - return - } - - if !assert.Len(t, nodes, 4) { - return - } + require.NoError(t, err) + require.Len(t, nodes, 4) expected := []string{ `a: b #first metadata: @@ -183,46 +160,36 @@ metadata: } for i := range nodes { val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } + require.NoError(t, err) + require.Equal(t, expected[i], val) } - } + }) } func TestLocalPackageReader_Read_JSON(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - - s.WriteFile(t, filepath.Join("a_test.json"), []byte(`{ - "a": "b" -}`)) - s.WriteFile(t, filepath.Join("b_test.json"), []byte(`{ - "e": "f", - "g": { - "h": ["i", "j"] - } -}`)) - - paths := []struct { - path string - }{ - {path: "./"}, - {path: s.Root}, - } - for _, p := range paths { - rfr := LocalPackageReader{PackagePath: p.path, MatchFilesGlob: []string{"*.json"}} + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a_test.json", content: []byte(`{ + "a": "b" + }`), + }, + {path: "b_test.json", content: []byte(`{ + "e": "f", + "g": { + "h": ["i", "j"] + } + }`), + }, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { + rfr := LocalPackageReader{ + PackagePath: path, + MatchFilesGlob: []string{"*.json"}, + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, + } nodes, err := rfr.Read() - if !assert.NoError(t, err) { - return - } - - if !assert.Len(t, nodes, 2) { - t.FailNow() - } + require.NoError(t, err) + require.Len(t, nodes, 2) expected := []string{ `{"a": "b", metadata: {annotations: {config.kubernetes.io/index: '0', config.kubernetes.io/path: 'a_test.json'}}} `, @@ -231,38 +198,26 @@ func TestLocalPackageReader_Read_JSON(t *testing.T) { } for i := range nodes { val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } + require.NoError(t, err) + require.Equal(t, expected[i], val) } - } + }) } func TestLocalPackageReader_Read_file(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - s.WriteFile(t, filepath.Join("a_test.yaml"), readFileA) - s.WriteFile(t, filepath.Join("b_test.yaml"), readFileB) - - paths := []struct { - path string - }{ - {path: "./"}, - {path: s.Root}, - } - for _, p := range paths { - rfr := LocalPackageReader{PackagePath: filepath.Join(p.path, "a_test.yaml")} + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a_test.yaml", content: readFileA}, + {path: "b_test.yaml", content: readFileB}, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { + rfr := LocalPackageReader{ + PackagePath: filepath.Join(path, "a_test.yaml"), + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, + } nodes, err := rfr.Read() - if !assert.NoError(t, err) { - return - } - - if !assert.Len(t, nodes, 2) { - return - } + require.NoError(t, err) + require.Len(t, nodes, 2) expected := []string{ `a: b #first metadata: @@ -279,39 +234,27 @@ metadata: } for i := range nodes { val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } + require.NoError(t, err) + require.Equal(t, expected[i], val) } - } + }) } func TestLocalPackageReader_Read_pkgOmitAnnotations(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - s.WriteFile(t, filepath.Join("a_test.yaml"), readFileA) - s.WriteFile(t, filepath.Join("b_test.yaml"), readFileB) - - paths := []struct { - path string - }{ - {path: "./"}, - {path: s.Root}, - } - for _, p := range paths { - // empty path - rfr := LocalPackageReader{PackagePath: p.path, OmitReaderAnnotations: true} + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a_test.yaml", content: readFileA}, + {path: "b_test.yaml", content: readFileB}, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { + rfr := LocalPackageReader{ + PackagePath: path, + OmitReaderAnnotations: true, + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, + } nodes, err := rfr.Read() - if !assert.NoError(t, err) { - return - } - - if !assert.Len(t, nodes, 3) { - return - } + require.NoError(t, err) + require.Len(t, nodes, 3) expected := []string{ `a: b #first `, @@ -327,39 +270,27 @@ g: } for i := range nodes { val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } + require.NoError(t, err) + require.Equal(t, expected[i], val) } - } + }) } func TestLocalPackageReader_Read_PreserveSeqIndent(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - s.WriteFile(t, filepath.Join("a_test.yaml"), readFileA) - s.WriteFile(t, filepath.Join("b_test.yaml"), readFileB) - - paths := []struct { - path string - }{ - {path: "./"}, - {path: s.Root}, - } - for _, p := range paths { - // empty path - rfr := LocalPackageReader{PackagePath: p.path, PreserveSeqIndent: true} + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a_test.yaml", content: readFileA}, + {path: "b_test.yaml", content: readFileB}, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { + rfr := LocalPackageReader{ + PackagePath: path, + PreserveSeqIndent: true, + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, + } nodes, err := rfr.Read() - if !assert.NoError(t, err) { - return - } - - if !assert.Len(t, nodes, 3) { - return - } + require.NoError(t, err) + require.Len(t, nodes, 3) expected := []string{ `a: b #first metadata: @@ -390,39 +321,26 @@ metadata: } for i := range nodes { val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } - if !assert.Equal(t, expected[i], val) { - return - } + require.NoError(t, err) + require.Equal(t, expected[i], val) } - } + }) } func TestLocalPackageReader_Read_nestedDirs(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - s.WriteFile(t, filepath.Join("a", "b", "a_test.yaml"), readFileA) - s.WriteFile(t, filepath.Join("a", "b", "b_test.yaml"), readFileB) - - paths := []struct { - path string - }{ - {path: "./"}, - {path: s.Root}, - } - for _, p := range paths { - // empty path - rfr := LocalPackageReader{PackagePath: p.path} + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a/b/a_test.yaml", content: readFileA}, + {path: "a/b/b_test.yaml", content: readFileB}, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { + rfr := LocalPackageReader{ + PackagePath: path, + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, + } nodes, err := rfr.Read() - if !assert.NoError(t, err) { - assert.FailNow(t, err.Error()) - } - - if !assert.Len(t, nodes, 3) { - return - } + require.NoError(t, err) + require.Len(t, nodes, 3) expected := []string{ `a: b #first metadata: @@ -450,130 +368,126 @@ metadata: } for i := range nodes { val, err := nodes[i].String() - if !assert.NoError(t, err) { - return - } + require.NoError(t, err) want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator)) - if !assert.Equal(t, want, val) { - return - } + require.Equal(t, want, val) } - } + }) } func TestLocalPackageReader_Read_matchRegex(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - s.WriteFile(t, filepath.Join("a", "b", "a_test.yaml"), readFileA) - s.WriteFile(t, filepath.Join("a", "b", "b_test.yaml"), readFileB) + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a/b/a_test.yaml", content: readFileA}, + {path: "a/b/b_test.yaml", content: readFileB}, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { + rfr := LocalPackageReader{ + PackagePath: path, + MatchFilesGlob: []string{`a*.yaml`}, + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, + } + nodes, err := rfr.Read() + require.NoError(t, err) + require.Len(t, nodes, 2) - // empty path - rfr := LocalPackageReader{PackagePath: s.Root, MatchFilesGlob: []string{`a*.yaml`}} - nodes, err := rfr.Read() - if !assert.NoError(t, err) { - assert.FailNow(t, err.Error()) - } - - if !assert.Len(t, nodes, 2) { - assert.FailNow(t, "wrong number items") - } - - expected := []string{ - `a: b #first + expected := []string{ + `a: b #first metadata: annotations: config.kubernetes.io/index: '0' config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml' `, - `c: d # second + `c: d # second metadata: annotations: config.kubernetes.io/index: '1' config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml' `, - } + } - for i, node := range nodes { - val, err := node.String() - assert.NoError(t, err) - want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator)) - assert.Equal(t, want, val) - } + for i, node := range nodes { + val, err := node.String() + require.NoError(t, err) + want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator)) + require.Equal(t, want, val) + } + }) } func TestLocalPackageReader_Read_skipSubpackage(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - s.WriteFile(t, filepath.Join("a", "b", "a_test.yaml"), readFileA) - s.WriteFile(t, filepath.Join("a", "c", "c_test.yaml"), readFileB) - s.WriteFile(t, filepath.Join("a", "c", "pkgFile"), pkgFile) + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a/b/a_test.yaml", content: readFileA}, + {path: "a/c/c_test.yaml", content: readFileB}, + {path: "a/c/pkgFile", content: pkgFile}, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { + rfr := LocalPackageReader{ + PackagePath: path, + PackageFileName: "pkgFile", + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, + } + nodes, err := rfr.Read() + require.NoError(t, err) + require.Len(t, nodes, 2) - // empty path - rfr := LocalPackageReader{PackagePath: s.Root, PackageFileName: "pkgFile"} - nodes, err := rfr.Read() - if !assert.NoError(t, err) { - assert.FailNow(t, err.Error()) - } - - if !assert.Len(t, nodes, 2) { - assert.FailNow(t, "wrong number items") - } - - expected := []string{ - `a: b #first + expected := []string{ + `a: b #first metadata: annotations: config.kubernetes.io/index: '0' config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml' `, - `c: d # second + `c: d # second metadata: annotations: config.kubernetes.io/index: '1' config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml' `, - } + } - for i, node := range nodes { - val, err := node.String() - assert.NoError(t, err) - want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator)) - assert.Equal(t, want, val) - } + for i, node := range nodes { + val, err := node.String() + require.NoError(t, err) + want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator)) + require.Equal(t, want, val) + } + }) } func TestLocalPackageReader_Read_includeSubpackage(t *testing.T) { - s := SetupDirectories(t, filepath.Join("a", "b"), filepath.Join("a", "c")) - defer s.Clean() - s.WriteFile(t, filepath.Join("a", "b", "a_test.yaml"), readFileA) - s.WriteFile(t, filepath.Join("a", "c", "c_test.yaml"), readFileB) - s.WriteFile(t, filepath.Join("a", "c", "pkgFile"), pkgFile) + testOnDiskAndOnMem(t, []mockFile{ + {path: "a/b"}, + {path: "a/c"}, + {path: "a/b/a_test.yaml", content: readFileA}, + {path: "a/c/c_test.yaml", content: readFileB}, + {path: "a/c/pkgFile", content: pkgFile}, + }, func(t *testing.T, path string, mockFS filesys.FileSystem) { + rfr := LocalPackageReader{ + PackagePath: path, + IncludeSubpackages: true, + PackageFileName: "pkgFile", + FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS}, + } + nodes, err := rfr.Read() + require.NoError(t, err) + require.Len(t, nodes, 3) - // empty path - rfr := LocalPackageReader{PackagePath: s.Root, IncludeSubpackages: true, PackageFileName: "pkgFile"} - nodes, err := rfr.Read() - if !assert.NoError(t, err) { - assert.FailNow(t, err.Error()) - } - - if !assert.Len(t, nodes, 3) { - assert.FailNow(t, "wrong number items") - } - - expected := []string{ - `a: b #first + expected := []string{ + `a: b #first metadata: annotations: config.kubernetes.io/index: '0' config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml' `, - `c: d # second + `c: d # second metadata: annotations: config.kubernetes.io/index: '1' config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml' `, - `# second thing + `# second thing e: f g: h: @@ -584,61 +498,60 @@ metadata: config.kubernetes.io/index: '0' config.kubernetes.io/path: 'a${SEP}c${SEP}c_test.yaml' `, - } + } - for i, node := range nodes { - val, err := node.String() - assert.NoError(t, err) - want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator)) - assert.Equal(t, want, val) - } + for i, node := range nodes { + val, err := node.String() + require.NoError(t, err) + want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator)) + require.Equal(t, want, val) + } + }) } -// func TestLocalPackageReaderWriter_DeleteFiles(t *testing.T) { -// g, _, clean := testutil.SetupDefaultRepoAndWorkspace(t) -// defer clean() -// if !assert.NoError(t, os.Chdir(g.RepoDirectory)) { -// return -// } -// -// rw := LocalPackageReadWriter{PackagePath: "."} -// nodes, err := rw.Read() -// if !assert.NoError(t, err) { -// t.FailNow() -// } -// _, err = os.Stat(filepath.Join("java", "java-deployment.resource.yaml")) -// if !assert.NoError(t, err) { -// t.FailNow() -// } -// -// // delete one of the nodes -// var newNodes []*yaml.RNode -// for i := range nodes { -// meta, err := nodes[i].GetMeta() -// if !assert.NoError(t, err) { -// t.FailNow() -// } -// if meta.Name == "app" && meta.Kind == "Deployment" { -// continue -// } -// newNodes = append(newNodes, nodes[i]) -// } -// -// if !assert.NoError(t, rw.Write(newNodes)) { -// t.FailNow() -// } -// -// _, err = os.Stat(filepath.Join("java", "java-deployment.resource.yaml")) -// if !assert.Error(t, err) { -// t.FailNow() -// } -// -// diff, err := copyutil.Diff(filepath.Join(g.DatasetDirectory, testutil.Dataset1), ".") -// if !assert.NoError(t, err) { -// t.FailNow() -// } -// -// assert.ElementsMatch(t, -// diff.List(), -// []string{filepath.Join("java", "java-deployment.resource.yaml")}) -// } +type mockFile struct { + path string + // nil content implies this is a directory + content []byte +} + +func testOnDiskAndOnMem(t *testing.T, files []mockFile, f func(t *testing.T, path string, fs filesys.FileSystem)) { + t.Run("on_disk", func(t *testing.T) { + var dirs []string + for _, file := range files { + if file.content == nil { + dirs = append(dirs, filepath.FromSlash(file.path)) + } + } + + s := SetupDirectories(t, dirs...) + defer s.Clean() + for _, file := range files { + if file.content != nil { + s.WriteFile(t, filepath.FromSlash(file.path), file.content) + } + } + + f(t, "./", nil) + f(t, s.Root, nil) + }) + + // TODO: Once fsnode supports Windows, we should also run the tests below. + if runtime.GOOS == "windows" { + return + } + + t.Run("on_mem", func(t *testing.T) { + fs := filesys.MakeFsInMemory() + for _, file := range files { + path := filepath.FromSlash(file.path) + if file.content == nil { + require.NoError(t, fs.MkdirAll(path)) + } else { + require.NoError(t, fs.WriteFile(path, file.content)) + } + } + + f(t, "/", fs) + }) +}