Parcourir la source

Provide more helpful error message and require input for every non-bool option. (#519)

Provide more helpful error message and require input for every non-bool option.
Garrett Wang il y a 5 ans
Parent
révision
c6e0a841f4
No account linked to committer's email address
2 fichiers modifiés avec 50 ajouts et 58 suppressions
  1. 8
    0
      internal/driver/interactive.go
  2. 42
    58
      internal/driver/interactive_test.go

+ 8
- 0
internal/driver/interactive.go Voir le fichier

@@ -70,6 +70,11 @@ func interactive(p *profile.Profile, o *plugin.Options) error {
70 70
 					value = strings.TrimSpace(value)
71 71
 				}
72 72
 				if v := pprofVariables[name]; v != nil {
73
+					// All non-bool options require inputs
74
+					if v.kind != boolKind && value == "" {
75
+						o.UI.PrintErr(fmt.Errorf("please specify a value, e.g. %s=<val>", name))
76
+						continue
77
+					}
73 78
 					if name == "sample_index" {
74 79
 						// Error check sample_index=xxx to ensure xxx is a valid sample type.
75 80
 						index, err := p.SampleIndexByName(value)
@@ -267,6 +272,9 @@ func parseCommandLine(input []string) ([]string, variables, error) {
267 272
 		}
268 273
 	}
269 274
 	if c == nil {
275
+		if v := pprofVariables[name]; v != nil {
276
+			return nil, nil, fmt.Errorf("did you mean: %s=%s", name, args[0])
277
+		}
270 278
 		return nil, nil, fmt.Errorf("unrecognized command: %q", name)
271 279
 	}
272 280
 

+ 42
- 58
internal/driver/interactive_test.go Voir le fichier

@@ -40,62 +40,53 @@ func TestShell(t *testing.T) {
40 40
 	savedVariables := pprofVariables
41 41
 	defer func() { pprofVariables = savedVariables }()
42 42
 
43
-	// Random interleave of independent scripts
44
-	pprofVariables = testVariables(savedVariables)
43
+	shortcuts1, scScript1 := makeShortcuts(interleave(script, 2), 1)
44
+	shortcuts2, scScript2 := makeShortcuts(interleave(script, 1), 2)
45 45
 
46
-	// pass in HTTPTransport when setting defaults, because otherwise default
47
-	// transport will try to add flags to the default flag set.
48
-	o := setDefaults(&plugin.Options{HTTPTransport: transport.New(nil)})
49
-	o.UI = newUI(t, interleave(script, 0))
50
-	if err := interactive(p, o); err != nil {
51
-		t.Error("first attempt:", err)
52
-	}
53
-	// Random interleave of independent scripts
54
-	pprofVariables = testVariables(savedVariables)
55
-	o.UI = newUI(t, interleave(script, 1))
56
-	if err := interactive(p, o); err != nil {
57
-		t.Error("second attempt:", err)
46
+	var testcases = []struct {
47
+		name              string
48
+		input             []string
49
+		shortcuts         shortcuts
50
+		allowRx           string
51
+		numAllowRxMatches int
52
+		propagateError    bool
53
+	}{
54
+		{"Random interleave of independent scripts 1", interleave(script, 0), pprofShortcuts, "", 0, false},
55
+		{"Random interleave of independent scripts 2", interleave(script, 1), pprofShortcuts, "", 0, false},
56
+		{"Random interleave of independent scripts with shortcuts 1", scScript1, shortcuts1, "", 0, false},
57
+		{"Random interleave of independent scripts with shortcuts 2", scScript2, shortcuts2, "", 0, false},
58
+		{"Group with invalid value", []string{"cumulative=this"}, pprofShortcuts, `unrecognized value for cumulative: "this". Use one of cum, flat`, 1, false},
59
+		{"No special value provided for the option", []string{"sample_index"}, pprofShortcuts, `please specify a value, e.g. sample_index=<val>`, 1, false},
60
+		{"No string value provided for the option", []string{"focus="}, pprofShortcuts, `please specify a value, e.g. focus=<val>`, 1, false},
61
+		{"No float value provided for the option", []string{"divide_by"}, pprofShortcuts, `please specify a value, e.g. divide_by=<val>`, 1, false},
62
+		{"Helpful input format reminder", []string{"sample_index 0"}, pprofShortcuts, `did you mean: sample_index=0`, 1, false},
63
+		{"Verify propagation of IO errors", []string{"**error**"}, pprofShortcuts, "", 0, true},
58 64
 	}
59 65
 
60
-	// Random interleave of independent scripts with shortcuts
61
-	pprofVariables = testVariables(savedVariables)
62
-	var scScript []string
63
-	pprofShortcuts, scScript = makeShortcuts(interleave(script, 2), 1)
64
-	o.UI = newUI(t, scScript)
65
-	if err := interactive(p, o); err != nil {
66
-		t.Error("first shortcut attempt:", err)
67
-	}
66
+	o := setDefaults(&plugin.Options{HTTPTransport: transport.New(nil)})
67
+	for _, tc := range testcases {
68
+		t.Run(tc.name, func(t *testing.T) {
69
+			pprofVariables = testVariables(savedVariables)
70
+			pprofShortcuts = tc.shortcuts
71
+			ui := &proftest.TestUI{
72
+				T:       t,
73
+				Input:   tc.input,
74
+				AllowRx: tc.allowRx,
75
+			}
76
+			o.UI = ui
68 77
 
69
-	// Random interleave of independent scripts with shortcuts
70
-	pprofVariables = testVariables(savedVariables)
71
-	pprofShortcuts, scScript = makeShortcuts(interleave(script, 1), 2)
72
-	o.UI = newUI(t, scScript)
73
-	if err := interactive(p, o); err != nil {
74
-		t.Error("second shortcut attempt:", err)
75
-	}
78
+			err := interactive(p, o)
79
+			if (tc.propagateError && err == nil) || (!tc.propagateError && err != nil) {
80
+				t.Errorf("%s: %v", tc.name, err)
81
+			}
76 82
 
77
-	// Group with invalid value
78
-	pprofVariables = testVariables(savedVariables)
79
-	ui := &proftest.TestUI{
80
-		T:       t,
81
-		Input:   []string{"cumulative=this"},
82
-		AllowRx: `unrecognized value for cumulative: "this". Use one of cum, flat`,
83
-	}
84
-	o.UI = ui
85
-	if err := interactive(p, o); err != nil {
86
-		t.Error("invalid group value:", err)
87
-	}
88
-	// Confirm error message written out once.
89
-	if ui.NumAllowRxMatches != 1 {
90
-		t.Errorf("want error message to be printed 1 time, got %v", ui.NumAllowRxMatches)
91
-	}
92
-	// Verify propagation of IO errors
93
-	pprofVariables = testVariables(savedVariables)
94
-	o.UI = newUI(t, []string{"**error**"})
95
-	if err := interactive(p, o); err == nil {
96
-		t.Error("expected IO error, got nil")
83
+			// Confirm error message written out once.
84
+			if tc.numAllowRxMatches != ui.NumAllowRxMatches {
85
+				t.Errorf("want error message to be printed %d time(s), got %d",
86
+					tc.numAllowRxMatches, ui.NumAllowRxMatches)
87
+			}
88
+		})
97 89
 	}
98
-
99 90
 }
100 91
 
101 92
 var testCommands = commands{
@@ -132,7 +123,7 @@ var script = []string{
132 123
 	"f=-1;f=-2.5;check f=-2.5;f=0.0001;check f=0.0001",
133 124
 	"check ff=0;ff=-1.01;check ff=-1.01;ff=100;check ff=100",
134 125
 	"s=one;s=two;check s=two",
135
-	"ss=tree;check ss=tree;ss=;check ss;ss=forest;check ss=forest",
126
+	"ss=tree;check ss=tree;ss=forest;check ss=forest",
136 127
 	"ta=true;check ta=true;check tb=false;check tc=false;tb=1;check tb=true;check ta=false;check tc=false;tc=yes;check tb=false;check ta=false;check tc=true",
137 128
 }
138 129
 
@@ -162,13 +153,6 @@ func makeShortcuts(input []string, seed int) (shortcuts, []string) {
162 153
 	return s, output
163 154
 }
164 155
 
165
-func newUI(t *testing.T, input []string) plugin.UI {
166
-	return &proftest.TestUI{
167
-		T:     t,
168
-		Input: input,
169
-	}
170
-}
171
-
172 156
 func checkValue(p *profile.Profile, cmd []string, vars variables, o *plugin.Options) error {
173 157
 	if len(cmd) != 2 {
174 158
 		return fmt.Errorf("expected len(cmd)==2, got %v", cmd)