From f7194b8e6609e7a9550d90ee0b36ad3ade45dbc6 Mon Sep 17 00:00:00 2001 From: Hariom Verma Date: Tue, 29 Aug 2023 14:41:24 +0530 Subject: [PATCH 1/8] pattern support for gno test args --- .github/workflows/examples.yml | 2 +- examples/Makefile | 4 +-- gnovm/cmd/gno/test.go | 4 +-- gnovm/cmd/gno/util.go | 54 ++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index d4b3079d612..b17c66d8e5a 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -50,7 +50,7 @@ jobs: with: go-version: ${{ matrix.goversion }} - run: go install -v ./gnovm/cmd/gno - - run: go run ./gnovm/cmd/gno test --verbose ./examples + - run: go run ./gnovm/cmd/gno test --verbose ./examples/... lint: strategy: fail-fast: false diff --git a/examples/Makefile b/examples/Makefile index 5075df198ac..f20072d9df2 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -19,7 +19,7 @@ build: precompile .PHONY: test test: - go run ../gnovm/cmd/gno test --verbose . + go run ../gnovm/cmd/gno test --verbose ./... .PHONY: lint lint: @@ -27,7 +27,7 @@ lint: .PHONY: test.sync test.sync: - go run ../gnovm/cmd/gno test --verbose --update-golden-tests . + go run ../gnovm/cmd/gno test --verbose --update-golden-tests ./... .PHONY: clean clean: diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 8cacfd5623b..878dbcaa69d 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -182,9 +182,9 @@ func execTest(cfg *testCfg, args []string, io *commands.IO) error { cfg.rootDir = guessRootDir() } - paths, err := gnoPackagesFromArgs(args) + paths, err := targetFromPatterns(args) if err != nil { - return fmt.Errorf("list package paths from args: %w", err) + return fmt.Errorf("list targets from patterns: %w", err) } if len(paths) == 0 { io.ErrPrintln("no packages to test") diff --git a/gnovm/cmd/gno/util.go b/gnovm/cmd/gno/util.go index 8288539c97b..dc4b1ded336 100644 --- a/gnovm/cmd/gno/util.go +++ b/gnovm/cmd/gno/util.go @@ -105,6 +105,60 @@ func gnoPackagesFromArgs(args []string) ([]string, error) { return paths, nil } +func targetFromPatterns(patterns []string) ([]string, error) { + paths := []string{} + for _, p := range patterns { + recursiveLookup := false + + // TODO: + // - Support more patterns + // - Move this logic to separate helper function? + if strings.HasSuffix(p, "/...") { + recursiveLookup = true + p = strings.TrimSuffix(p, "/...") + } + + info, err := os.Stat(p) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + // if the pattern is: + // - a file + // - a dir not followed by /... + // then we'll just add it to the list + if !info.IsDir() || !recursiveLookup { + paths = append(paths, p) + continue + } + + // the passed arg is a dir folllowed by /... then we'll walk the dir recursively + // and look for directories containing at least one .gno file. + visited := map[string]bool{} // used to run the builder only once per folder. + err = filepath.WalkDir(p, func(curpath string, f fs.DirEntry, err error) error { + if err != nil { + return fmt.Errorf("%s: walk dir: %w", p, err) + } + if f.IsDir() || !isGnoFile(f) { + return nil // skip + } + + parentDir := filepath.Dir(curpath) + if _, found := visited[parentDir]; found { + return nil + } + visited[parentDir] = true + + paths = append(paths, parentDir) + return nil + }) + if err != nil { + return nil, err + } + } + return paths, nil +} + func fmtDuration(d time.Duration) string { return fmt.Sprintf("%.2fs", d.Seconds()) } From d22b0d27e12cf37742104489b46319a9acb7365a Mon Sep 17 00:00:00 2001 From: Hariom Verma Date: Wed, 30 Aug 2023 03:11:46 +0530 Subject: [PATCH 2/8] support `/...` pattern --- gnovm/cmd/gno/util.go | 70 ++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/gnovm/cmd/gno/util.go b/gnovm/cmd/gno/util.go index dc4b1ded336..e1ba067a880 100644 --- a/gnovm/cmd/gno/util.go +++ b/gnovm/cmd/gno/util.go @@ -9,6 +9,7 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "strings" "time" @@ -105,51 +106,61 @@ func gnoPackagesFromArgs(args []string) ([]string, error) { return paths, nil } +// targetFromPatterns returns a list of target paths that match the patterns. +// Each pattern can represent a file or a directory, and if the pattern +// includes `/...“, it signifies a directory search. +// Intended to be used by gno commands such as `gno test`. func targetFromPatterns(patterns []string) ([]string, error) { paths := []string{} for _, p := range patterns { - recursiveLookup := false - - // TODO: - // - Support more patterns - // - Move this logic to separate helper function? - if strings.HasSuffix(p, "/...") { - recursiveLookup = true - p = strings.TrimSuffix(p, "/...") + var match func(string) bool + patternLookup := false + dirToSearch := p + + // Check if the pattern includes `/...`` + if strings.Contains(p, "/...") { + index := strings.Index(p, "/...") + if index != -1 { + dirToSearch = p[:index] // Extract the directory path to search + } + match = matchPattern(strings.TrimPrefix(p, "./")) + patternLookup = true } - info, err := os.Stat(p) + info, err := os.Stat(dirToSearch) if err != nil { return nil, fmt.Errorf("invalid file or package path: %w", err) } - // if the pattern is: - // - a file - // - a dir not followed by /... - // then we'll just add it to the list - if !info.IsDir() || !recursiveLookup { + // If the pattern is a file or a directory + // without `/...``, add it to the list. + if !info.IsDir() || !patternLookup { paths = append(paths, p) continue } - // the passed arg is a dir folllowed by /... then we'll walk the dir recursively - // and look for directories containing at least one .gno file. + // the pattern is a dir containing `/...`, walk the dir recursively and + // look for directories containing at least one .gno file and match pattern. visited := map[string]bool{} // used to run the builder only once per folder. - err = filepath.WalkDir(p, func(curpath string, f fs.DirEntry, err error) error { + err = filepath.WalkDir(dirToSearch, func(curpath string, f fs.DirEntry, err error) error { if err != nil { - return fmt.Errorf("%s: walk dir: %w", p, err) + return fmt.Errorf("%s: walk dir: %w", dirToSearch, err) } + // Skip directories and non ".gno" files. if f.IsDir() || !isGnoFile(f) { - return nil // skip + return nil } parentDir := filepath.Dir(curpath) if _, found := visited[parentDir]; found { return nil } + visited[parentDir] = true + if match(parentDir) { + paths = append(paths, parentDir) + } - paths = append(paths, parentDir) return nil }) if err != nil { @@ -159,6 +170,25 @@ func targetFromPatterns(patterns []string) ([]string, error) { return paths, nil } +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +// Stolen from the go tool +// Taken from: https://github.com/rogpeppe/showdeps/blob/master/showdeps.go +func matchPattern(pattern string) func(name string) bool { + re := regexp.QuoteMeta(pattern) + re = strings.Replace(re, `\.\.\.`, `.*`, -1) + // Special case: foo/... matches foo too. + if strings.HasSuffix(re, `/.*`) { + re = re[:len(re)-len(`/.*`)] + `(/.*)?` + } + reg := regexp.MustCompile(`^` + re + `$`) + return func(name string) bool { + return reg.MatchString(name) + } +} + func fmtDuration(d time.Duration) string { return fmt.Sprintf("%.2fs", d.Seconds()) } From 031f567778269e70c6454c8430a8bd73370249d1 Mon Sep 17 00:00:00 2001 From: Hariom Verma Date: Wed, 30 Aug 2023 03:18:57 +0530 Subject: [PATCH 3/8] fix typos --- gnovm/cmd/gno/util.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnovm/cmd/gno/util.go b/gnovm/cmd/gno/util.go index e1ba067a880..41a6b2fa281 100644 --- a/gnovm/cmd/gno/util.go +++ b/gnovm/cmd/gno/util.go @@ -117,7 +117,7 @@ func targetFromPatterns(patterns []string) ([]string, error) { patternLookup := false dirToSearch := p - // Check if the pattern includes `/...`` + // Check if the pattern includes `/...` if strings.Contains(p, "/...") { index := strings.Index(p, "/...") if index != -1 { @@ -133,7 +133,7 @@ func targetFromPatterns(patterns []string) ([]string, error) { } // If the pattern is a file or a directory - // without `/...``, add it to the list. + // without `/...`, add it to the list. if !info.IsDir() || !patternLookup { paths = append(paths, p) continue From 34c428620caf8ed52313522c75b9d8499916afde Mon Sep 17 00:00:00 2001 From: Hariom Verma Date: Thu, 31 Aug 2023 03:12:17 +0530 Subject: [PATCH 4/8] Fix failing txtar files --- gnovm/cmd/gno/testdata/gno_test/empty_dir.txtar | 5 +++++ gnovm/cmd/gno/testdata/gno_test/empty_gno1.txtar | 2 +- gnovm/cmd/gno/testdata/gno_test/error_correct.txtar | 2 +- gnovm/cmd/gno/testdata/gno_test/failing_filetest.txtar | 4 ++-- gnovm/cmd/gno/testdata/gno_test/minim1.txtar | 2 +- gnovm/cmd/gno/testdata/gno_test/minim2.txtar | 2 +- gnovm/cmd/gno/testdata/gno_test/minim3.txtar | 2 +- gnovm/cmd/gno/testdata/gno_test/output_correct.txtar | 2 +- gnovm/cmd/gno/testdata/gno_test/output_sync.txtar | 2 +- gnovm/cmd/gno/testdata/gno_test/realm_correct.txtar | 2 +- gnovm/cmd/gno/testdata/gno_test/realm_sync.txtar | 2 +- gnovm/cmd/gno/testdata/gno_test/valid_filetest.txtar | 4 ++-- gnovm/cmd/gno/testdata/gno_test/valid_test.txtar | 7 ++++++- 13 files changed, 24 insertions(+), 14 deletions(-) diff --git a/gnovm/cmd/gno/testdata/gno_test/empty_dir.txtar b/gnovm/cmd/gno/testdata/gno_test/empty_dir.txtar index 73f0da72dfe..ffed64ab9c7 100644 --- a/gnovm/cmd/gno/testdata/gno_test/empty_dir.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/empty_dir.txtar @@ -2,5 +2,10 @@ gno test . +! stdout .+ +stderr '[no test files]' + +gno test ./... + ! stdout .+ stderr 'no packages to test' diff --git a/gnovm/cmd/gno/testdata/gno_test/empty_gno1.txtar b/gnovm/cmd/gno/testdata/gno_test/empty_gno1.txtar index ae73b3ab275..cc673bb38ff 100644 --- a/gnovm/cmd/gno/testdata/gno_test/empty_gno1.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/empty_gno1.txtar @@ -3,7 +3,7 @@ gno test . ! stdout .+ -stderr '\? \./\. \[no test files\]' +stderr '\? \. \[no test files\]' ! gno test --precompile . diff --git a/gnovm/cmd/gno/testdata/gno_test/error_correct.txtar b/gnovm/cmd/gno/testdata/gno_test/error_correct.txtar index c7d3187424c..a66d831b48c 100644 --- a/gnovm/cmd/gno/testdata/gno_test/error_correct.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/error_correct.txtar @@ -5,7 +5,7 @@ gno test -verbose . stdout 'Machine\.RunMain\(\) panic: oups' stderr '=== RUN file/x_filetest.gno' stderr '--- PASS: file/x_filetest.gno \(\d\.\d\ds\)' -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' -- x_filetest.gno -- package main diff --git a/gnovm/cmd/gno/testdata/gno_test/failing_filetest.txtar b/gnovm/cmd/gno/testdata/gno_test/failing_filetest.txtar index bc3efc1a8c9..c739c1ce328 100644 --- a/gnovm/cmd/gno/testdata/gno_test/failing_filetest.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/failing_filetest.txtar @@ -9,8 +9,8 @@ stderr 'panic: fail on failing_filetest.gno: got unexpected error: beep boop' ! gno test -verbose --precompile . stdout 'Machine.RunMain\(\) panic: beep boop' -stderr '=== PREC \./\.' -stderr '=== BUILD \./\.' +stderr '=== PREC \.' +stderr '=== BUILD \.' stderr '=== RUN file/failing_filetest.gno' stderr 'panic: fail on failing_filetest.gno: got unexpected error: beep boop' diff --git a/gnovm/cmd/gno/testdata/gno_test/minim1.txtar b/gnovm/cmd/gno/testdata/gno_test/minim1.txtar index 231ef4a270c..b0a77186086 100644 --- a/gnovm/cmd/gno/testdata/gno_test/minim1.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/minim1.txtar @@ -3,7 +3,7 @@ gno test . ! stdout .+ -stderr '\? \./\. \[no test files\]' +stderr '\? \. \[no test files\]' -- minim.gno -- package minim diff --git a/gnovm/cmd/gno/testdata/gno_test/minim2.txtar b/gnovm/cmd/gno/testdata/gno_test/minim2.txtar index 038dfd19289..3c4d1d085f0 100644 --- a/gnovm/cmd/gno/testdata/gno_test/minim2.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/minim2.txtar @@ -3,7 +3,7 @@ gno test . ! stdout .+ -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' -- minim.gno -- package minim diff --git a/gnovm/cmd/gno/testdata/gno_test/minim3.txtar b/gnovm/cmd/gno/testdata/gno_test/minim3.txtar index 8e657104801..ac8ae0c41d4 100644 --- a/gnovm/cmd/gno/testdata/gno_test/minim3.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/minim3.txtar @@ -3,7 +3,7 @@ gno test . ! stdout .+ -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' -- minim.gno -- package minim diff --git a/gnovm/cmd/gno/testdata/gno_test/output_correct.txtar b/gnovm/cmd/gno/testdata/gno_test/output_correct.txtar index ce12874f669..4e5495ab839 100644 --- a/gnovm/cmd/gno/testdata/gno_test/output_correct.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/output_correct.txtar @@ -5,7 +5,7 @@ gno test -verbose . ! stdout .+ # stdout should be empty stderr '=== RUN file/x_filetest.gno' stderr '--- PASS: file/x_filetest.gno \(\d\.\d\ds\)' -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' -- x_filetest.gno -- package main diff --git a/gnovm/cmd/gno/testdata/gno_test/output_sync.txtar b/gnovm/cmd/gno/testdata/gno_test/output_sync.txtar index 85fec4ab316..b21db788924 100644 --- a/gnovm/cmd/gno/testdata/gno_test/output_sync.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/output_sync.txtar @@ -5,7 +5,7 @@ gno test -verbose . -update-golden-tests ! stdout .+ # stdout should be empty stderr '=== RUN file/x_filetest.gno' stderr '--- PASS: file/x_filetest.gno \(\d\.\d\ds\)' -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' cmp x_filetest.gno x_filetest.gno.golden diff --git a/gnovm/cmd/gno/testdata/gno_test/realm_correct.txtar b/gnovm/cmd/gno/testdata/gno_test/realm_correct.txtar index f376e61d9a4..c3d3b983e34 100644 --- a/gnovm/cmd/gno/testdata/gno_test/realm_correct.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/realm_correct.txtar @@ -5,7 +5,7 @@ gno test -verbose . ! stdout .+ # stdout should be empty stderr '=== RUN file/x_filetest.gno' stderr '--- PASS: file/x_filetest.gno \(\d\.\d\ds\)' -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' -- x_filetest.gno -- // PKGPATH: gno.land/r/x diff --git a/gnovm/cmd/gno/testdata/gno_test/realm_sync.txtar b/gnovm/cmd/gno/testdata/gno_test/realm_sync.txtar index 918fb0b88c9..236e69f8641 100644 --- a/gnovm/cmd/gno/testdata/gno_test/realm_sync.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/realm_sync.txtar @@ -5,7 +5,7 @@ gno test -verbose . -update-golden-tests ! stdout .+ # stdout should be empty stderr '=== RUN file/x_filetest.gno' stderr '--- PASS: file/x_filetest.gno \(\d\.\d\ds\)' -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' cmp x_filetest.gno x_filetest.gno.golden diff --git a/gnovm/cmd/gno/testdata/gno_test/valid_filetest.txtar b/gnovm/cmd/gno/testdata/gno_test/valid_filetest.txtar index 51b5f323654..545607a9082 100644 --- a/gnovm/cmd/gno/testdata/gno_test/valid_filetest.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/valid_filetest.txtar @@ -3,14 +3,14 @@ gno test . ! stdout .+ -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' gno test -verbose . ! stdout .+ stderr '=== RUN file/valid_filetest.gno' stderr '--- PASS: file/valid_filetest.gno \(\d\.\d\ds\)' -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' -- valid.gno -- package valid diff --git a/gnovm/cmd/gno/testdata/gno_test/valid_test.txtar b/gnovm/cmd/gno/testdata/gno_test/valid_test.txtar index cb5f7286f60..9590626776c 100644 --- a/gnovm/cmd/gno/testdata/gno_test/valid_test.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/valid_test.txtar @@ -3,7 +3,12 @@ gno test . ! stdout .+ -stderr 'ok \./\. \d\.\d\ds' +stderr 'ok \. \d\.\d\ds' + +gno test ./... + +! stdout .+ +stderr 'ok \. \d\.\d\ds' -- valid.gno -- package valid From 42f19383498556de71eccb15679a9db599b80241 Mon Sep 17 00:00:00 2001 From: Hariom Verma Date: Thu, 31 Aug 2023 03:31:45 +0530 Subject: [PATCH 5/8] fix long help --- gnovm/cmd/gno/test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 878dbcaa69d..b5170c1bc07 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -50,7 +50,7 @@ func newTestCmd(io *commands.IO) *commands.Command { 'gno test' recompiles each package along with any files with names matching the file pattern "*_test.gno" or "*_filetest.gno". -The only supported for now is a directory (relative or absolute). +The can be directory or file path (relative or absolute). - "*_test.gno" files work like "*_test.go" files, but they contain only test functions. Benchmark and fuzz functions aren't supported yet. Similarly, only From cef6b804e2908ba2819894fa1401c165167f898e Mon Sep 17 00:00:00 2001 From: Hariom Verma Date: Fri, 1 Sep 2023 04:18:13 +0530 Subject: [PATCH 6/8] Fix review comments --- gnovm/cmd/gno/test.go | 2 +- gnovm/cmd/gno/util.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index b5170c1bc07..85fe3f7ee7d 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -182,7 +182,7 @@ func execTest(cfg *testCfg, args []string, io *commands.IO) error { cfg.rootDir = guessRootDir() } - paths, err := targetFromPatterns(args) + paths, err := targetsFromPatterns(args) if err != nil { return fmt.Errorf("list targets from patterns: %w", err) } diff --git a/gnovm/cmd/gno/util.go b/gnovm/cmd/gno/util.go index 41a6b2fa281..73ee0f0323b 100644 --- a/gnovm/cmd/gno/util.go +++ b/gnovm/cmd/gno/util.go @@ -106,11 +106,11 @@ func gnoPackagesFromArgs(args []string) ([]string, error) { return paths, nil } -// targetFromPatterns returns a list of target paths that match the patterns. +// targetsFromPatterns returns a list of target paths that match the patterns. // Each pattern can represent a file or a directory, and if the pattern -// includes `/...“, it signifies a directory search. +// includes "/...", the "..." is treated as a wildcard, matching any string. // Intended to be used by gno commands such as `gno test`. -func targetFromPatterns(patterns []string) ([]string, error) { +func targetsFromPatterns(patterns []string) ([]string, error) { paths := []string{} for _, p := range patterns { var match func(string) bool @@ -174,8 +174,8 @@ func targetFromPatterns(patterns []string) ([]string, error) { // name matches pattern. Pattern is a limited glob // pattern in which '...' means 'any string' and there // is no other special syntax. -// Stolen from the go tool -// Taken from: https://github.com/rogpeppe/showdeps/blob/master/showdeps.go +// Simplified version of go source's matchPatternInternal +// (see $GOROOT/src/cmd/internal/pkgpattern) func matchPattern(pattern string) func(name string) bool { re := regexp.QuoteMeta(pattern) re = strings.Replace(re, `\.\.\.`, `.*`, -1) From ebcda4ed0e283dc692e1445f732afdeca6d4e319 Mon Sep 17 00:00:00 2001 From: Hariom Verma Date: Sun, 1 Oct 2023 10:56:17 +0530 Subject: [PATCH 7/8] TestMatchPattern --- gnovm/cmd/gno/util_test.go | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 gnovm/cmd/gno/util_test.go diff --git a/gnovm/cmd/gno/util_test.go b/gnovm/cmd/gno/util_test.go new file mode 100644 index 00000000000..05b0c3a09b5 --- /dev/null +++ b/gnovm/cmd/gno/util_test.go @@ -0,0 +1,61 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMatchPattern(t *testing.T) { + tests := []struct { + pattern string + names []string + expected []bool + }{ + { + pattern: "foo", + names: []string{"foo", "bar", "baz", "foo/bar"}, + expected: []bool{true, false, false, false}, + }, + { + pattern: "foo/...", + names: []string{"foo", "foo/bar", "foo/bar/baz", "bar", "baz"}, + expected: []bool{true, true, true, false, false}, + }, + { + pattern: "foo/bar/...", + names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, + expected: []bool{true, true, false, false, false}, + }, + { + pattern: "foo/.../baz", + names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, + expected: []bool{false, true, false, false, false}, + }, + { + pattern: "foo/.../baz/...", + names: []string{"foo/bar/baz", "foo/baz/bar", "foo/bar/baz/qux", "foo/baz/bar/qux"}, + expected: []bool{true, false, true, false}, + }, + { + pattern: "...", + names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, + expected: []bool{true, true, true, true, true}, + }, + { + pattern: ".../bar", + names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, + expected: []bool{false, false, false, true, false}, + }, + } + + for _, test := range tests { + t.Run(test.pattern, func(t *testing.T) { + matchFunc := matchPattern(test.pattern) + for i, name := range test.names { + res := matchFunc(name) + assert.Equal(t, test.expected[i], res, "Expected: %v, Got: %v", test.expected[i], res) + } + }) + } +} From 32137ff29ccf17b1f6f0ee5ea6ab204762457be9 Mon Sep 17 00:00:00 2001 From: Hariom Verma Date: Thu, 12 Oct 2023 18:27:48 +0530 Subject: [PATCH 8/8] TestTargetsFromPatterns --- gnovm/cmd/gno/util_test.go | 236 +++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) diff --git a/gnovm/cmd/gno/util_test.go b/gnovm/cmd/gno/util_test.go index 05b0c3a09b5..9e9659bfe4f 100644 --- a/gnovm/cmd/gno/util_test.go +++ b/gnovm/cmd/gno/util_test.go @@ -1,9 +1,12 @@ package main import ( + "os" + "path/filepath" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMatchPattern(t *testing.T) { @@ -59,3 +62,236 @@ func TestMatchPattern(t *testing.T) { }) } } + +func TestTargetsFromPatterns(t *testing.T) { + tmpDir := t.TempDir() + createGnoPackages(t, tmpDir) + + for _, tc := range []struct { + desc string + in, expected []string + errorShouldContain string + }{ + { + desc: "valid1", + in: []string{ + tmpDir, + }, + expected: []string{ + tmpDir, + }, + }, + { + desc: "valid2", + in: []string{ + tmpDir + "/foo", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + }, + }, + { + desc: "valid_recursive1", + in: []string{ + tmpDir + "/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "baz"), + filepath.Join(tmpDir, "foo", "qux"), + filepath.Join(tmpDir, "bar", "quux"), + filepath.Join(tmpDir, "foo", "qux", "corge"), + }, + }, + { + desc: "valid_recursive2", + in: []string{ + tmpDir + "/foo/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "foo", "qux"), + filepath.Join(tmpDir, "foo", "qux", "corge"), + }, + }, + { + desc: "valid_recursive2", + in: []string{ + tmpDir + "/.../qux", + }, + expected: []string{ + filepath.Join(tmpDir, "foo", "qux"), + }, + }, + { + desc: "valid_recursive3", + in: []string{ + tmpDir + "/.../qux/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo", "qux"), + filepath.Join(tmpDir, "foo", "qux", "corge"), + }, + }, + { + desc: "multiple_input", + in: []string{ + tmpDir + "/foo", + tmpDir + "/bar", + tmpDir + "/baz", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "baz"), + }, + }, + { + desc: "mixed_input1", + in: []string{ + tmpDir + "/foo", + tmpDir + "/bar/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "bar", "quux"), + }, + }, + { + desc: "mixed_input2", + in: []string{ + tmpDir + "/foo", + tmpDir + "/bar/...", + tmpDir + "/baz/baz.gno", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "bar", "quux"), + filepath.Join(tmpDir, "baz", "baz.gno"), + }, + }, + { + desc: "not_exists1", + in: []string{ + tmpDir + "/notexists", // dir path + }, + errorShouldContain: "no such file or directory", + }, + { + desc: "not_exists2", + in: []string{ + tmpDir + "/foo/bar.gno", // file path + }, + errorShouldContain: "no such file or directory", + }, + { + desc: "not_exists3", // mixed + in: []string{ + tmpDir + "/foo", // exists + tmpDir + "/notexists", // not exists + }, + errorShouldContain: "no such file or directory", + }, + } { + t.Run(tc.desc, func(t *testing.T) { + targets, err := targetsFromPatterns(tc.in) + if tc.errorShouldContain != "" { + assert.ErrorContains(t, err, tc.errorShouldContain) + return + } + assert.NoError(t, err) + require.Equal(t, len(tc.expected), len(targets)) + for _, tr := range targets { + assert.Contains(t, tc.expected, tr) + } + }) + } +} + +func createGnoPackages(t *testing.T, tmpDir string) { + t.Helper() + + type file struct { + name, data string + } + // Gno pkgs to create + pkgs := []struct { + dir string + files []file + }{ + // pkg 'foo', 'bar' and 'baz' + { + dir: filepath.Join(tmpDir, "foo"), + files: []file{ + { + name: "foo.gno", + data: `package foo`, + }, + }, + }, + { + dir: filepath.Join(tmpDir, "bar"), + files: []file{ + { + name: "bar.gno", + data: `package bar`, + }, + }, + }, + { + dir: filepath.Join(tmpDir, "baz"), + files: []file{ + { + name: "baz.gno", + data: `package baz`, + }, + }, + }, + + // pkg inside 'foo' pkg + { + dir: filepath.Join(tmpDir, "foo", "qux"), + files: []file{ + { + name: "qux.gno", + data: `package qux`, + }, + }, + }, + + // pkg inside 'bar' pkg + { + dir: filepath.Join(tmpDir, "bar", "quux"), + files: []file{ + { + name: "quux.gno", + data: `package quux`, + }, + }, + }, + + // pkg inside 'foo/qux' pkg + { + dir: filepath.Join(tmpDir, "foo", "qux", "corge"), + files: []file{ + { + name: "corge.gno", + data: `package corge`, + }, + }, + }, + } + + // Create pkgs + for _, p := range pkgs { + err := os.MkdirAll(p.dir, 0o700) + require.NoError(t, err) + for _, f := range p.files { + err = os.WriteFile(filepath.Join(p.dir, f.name), []byte(f.data), 0o644) + require.NoError(t, err) + } + } +}