Skip to content

Commit 681c55e

Browse files
ict test command with a fuzzy match target proposal
1 parent 1742593 commit 681c55e

File tree

7 files changed

+100
-19
lines changed

7 files changed

+100
-19
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ require (
1616
github.com/mattn/go-colorable v0.1.11 // indirect
1717
github.com/mattn/go-isatty v0.0.14 // indirect
1818
github.com/pmezard/go-difflib v1.0.0 // indirect
19+
github.com/schollz/closestmatch v2.1.0+incompatible // indirect
1920
github.com/spf13/cobra v1.6.1 // indirect
2021
github.com/spf13/pflag v1.0.5 // indirect
2122
github.com/stretchr/testify v1.8.1 // indirect

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
3434
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3535
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
3636
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
37+
github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=
38+
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
3739
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
3840
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
3941
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=

go_deps.bzl

+6
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,12 @@ def go_dependencies():
421421
sum = "h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=",
422422
version = "v2.1.0",
423423
)
424+
go_repository(
425+
name = "com_github_schollz_closestmatch",
426+
importpath = "github.com/schollz/closestmatch",
427+
sum = "h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=",
428+
version = "v2.1.0+incompatible",
429+
)
424430

425431
go_repository(
426432
name = "com_github_sergi_go_diff",

rs/tests/ict/cmd/BUILD.bazel

+2
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
33
go_library(
44
name = "cmd",
55
srcs = [
6+
"helpers.go",
67
"root.go",
78
"testCmd.go",
89
],
910
importpath = "github.com/dfinity/ic/rs/tests/ict/cmd",
1011
visibility = ["//visibility:public"],
1112
deps = [
1213
"@com_github_fatih_color//:color",
14+
"@com_github_schollz_closestmatch//:closestmatch",
1315
"@com_github_spf13_cobra//:cobra",
1416
],
1517
)

rs/tests/ict/cmd/cmd_test.go

-13
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,3 @@ func Test_TestCmdWithHelpArg(t *testing.T) {
5858
assert.Nil(t, err)
5959
assert.Contains(t, actual.String(), expected)
6060
}
61-
62-
func Test_TestCmdWithTargetAndDryRunArgs(t *testing.T) {
63-
expected := "bazel test my_target --config=systest --cache_test_results=yes"
64-
actual := new(bytes.Buffer)
65-
var command = cmd.NewTestCmd()
66-
command.SetArgs([]string{"my_target", "-c", "--dry-run"})
67-
command.SetOut(actual)
68-
69-
err := command.Execute()
70-
71-
assert.Nil(t, err)
72-
assert.Contains(t, actual.String(), expected)
73-
}

rs/tests/ict/cmd/helpers.go

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"os/exec"
7+
"strings"
8+
9+
"github.com/schollz/closestmatch"
10+
)
11+
12+
// see https://github.com/schollz/closestmatch
13+
var FUZZY_SEARCH_BAG_SIZES = []int{2, 3, 4}
14+
15+
func Filter(vs []string, f func(string) bool) []string {
16+
filtered := make([]string, 0)
17+
for _, v := range vs {
18+
if f(v) {
19+
filtered = append(filtered, v)
20+
}
21+
}
22+
return filtered
23+
}
24+
25+
func get_all_system_test_targets() ([]string, error) {
26+
command := []string{"bazel", "query", "tests(//rs/tests:*)"}
27+
queryCmd := exec.Command(command[0], command[1:]...)
28+
outputBuffer := &bytes.Buffer{}
29+
stdErrBuffer := &bytes.Buffer{}
30+
queryCmd.Stdout = outputBuffer
31+
queryCmd.Stderr = stdErrBuffer
32+
if err := queryCmd.Run(); err != nil {
33+
return []string{}, fmt.Errorf("Bazel command: [%s] failed: %s", strings.Join(command, " "), stdErrBuffer.String())
34+
}
35+
cmdOutput := strings.Split(outputBuffer.String(), "\n")
36+
all_targets := Filter(cmdOutput, func(s string) bool {
37+
return len(s) > 0 && strings.Contains(s, "//rs/tests:")
38+
})
39+
return all_targets, nil
40+
}
41+
42+
func get_closest_target_matches(target string) ([]string, error) {
43+
all_targets, err := get_all_system_test_targets()
44+
if err != nil {
45+
return []string{}, err
46+
}
47+
closest_matches := closestmatch.New(all_targets, FUZZY_SEARCH_BAG_SIZES).ClosestN(target, FUZZY_MATCHES_COUNT)
48+
return Filter(closest_matches, func(s string) bool {
49+
return len(s) > 0
50+
}), nil
51+
}
52+
53+
func check_target_exists(target string) (bool, error) {
54+
command := []string{"bazel", "query", target}
55+
queryCmd := exec.Command(command[0], command[1:]...)
56+
stdErrBuffer := &bytes.Buffer{}
57+
queryCmd.Stderr = stdErrBuffer
58+
if err := queryCmd.Run(); err != nil {
59+
if strings.Contains(stdErrBuffer.String(), "no such target") {
60+
return false, nil
61+
} else {
62+
return false, fmt.Errorf("Bazel command: [%s] failed: %s", strings.Join(command, " "), stdErrBuffer.String())
63+
}
64+
}
65+
return true, nil
66+
}

rs/tests/ict/cmd/testCmd.go

+23-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"fmt"
45
"os"
56
"os/exec"
67
"strings"
@@ -12,18 +13,33 @@ var RED = "\033[1;31m"
1213
var GREEN = "\033[1;32m"
1314
var CYAN = "\033[0;36m"
1415
var NC = "\033[0m"
16+
var FUZZY_MATCHES_COUNT = 7
1517

1618
type Config struct {
17-
isCacheTestResult bool
18-
testTmpDir string
19-
isDryRun bool
19+
useCachedTestResult bool
20+
testTmpDir string
21+
isDryRun bool
22+
useFuzzyMatchedTarget bool
2023
}
2124

2225
func TestCommandWithConfig(cfg *Config) func(cmd *cobra.Command, args []string) error {
2326
return func(cmd *cobra.Command, args []string) error {
2427
target := args[0]
28+
if res, err_target := check_target_exists(target); !res {
29+
if err_target != nil {
30+
return err_target
31+
} else if closest_matches, err_match := get_closest_target_matches(target); err_match != nil {
32+
return err_match
33+
} else if len(closest_matches) == 0 {
34+
return fmt.Errorf("No test target `%s` was found", target)
35+
} else if cfg.useFuzzyMatchedTarget {
36+
target = closest_matches[0]
37+
} else {
38+
return fmt.Errorf("No test target `%s` was found: \nDid you mean any of:\n%s", target, strings.Join(closest_matches, "\n"))
39+
}
40+
}
2541
cache_test_results := "--cache_test_results="
26-
if cfg.isCacheTestResult {
42+
if cfg.useCachedTestResult {
2743
cache_test_results += "yes"
2844
} else {
2945
cache_test_results += "no"
@@ -49,15 +65,16 @@ func TestCommandWithConfig(cfg *Config) func(cmd *cobra.Command, args []string)
4965
func NewTestCmd() *cobra.Command {
5066
var cfg = Config{}
5167
var testCmd = &cobra.Command{
52-
Use: "test",
68+
Use: "test <system_test_target_arg>",
5369
Aliases: []string{"system_test", "t"},
5470
Short: "Run system_test target with Bazel",
5571
Example: "ict test //rs/tests:basic_health_test",
5672
Args: cobra.ExactArgs(1),
5773
RunE: TestCommandWithConfig(&cfg),
5874
}
75+
testCmd.Flags().BoolVarP(&cfg.useFuzzyMatchedTarget, "use-fuzzy-match", "f", false, "If test target is not found, use the closest fuzzy matched one.")
5976
testCmd.Flags().BoolVarP(&cfg.isDryRun, "dry-run", "n", false, "Print raw Bazel command to be invoked.")
60-
testCmd.Flags().BoolVarP(&cfg.isCacheTestResult, "cache_test_results", "c", false, "Bazel's cache_test_results, see --cache_test_results tag in Bazel docs.")
77+
testCmd.Flags().BoolVarP(&cfg.useCachedTestResult, "cache_test_results", "c", false, "Bazel's cache_test_results, see --cache_test_results tag in Bazel docs.")
6178
testCmd.PersistentFlags().StringVarP(&cfg.testTmpDir, "test_tmpdir", "t", "", "Dir for storing test results, see --test-tmpdir tag in Bazel docs.")
6279
return testCmd
6380
}

0 commit comments

Comments
 (0)