fix: wait for prompt on rich param CLI test (#15406)

Fixes a race in TestUpdateValidateRichParameters where the parameter is sent prior to the prompt.

Causes errors like: https://github.com/coder/coder/actions/runs/11681622439/job/32527173007

```
    ptytest.go:132: 2024-11-05 10:02:18.819: cmd: "bool_parameter"
    ptytest.go:167: 2024-11-05 10:02:18.819: cmd: matched "bool_parameter" = "bool_parameter"
    update_test.go:440: 2024-11-05 10:02:18.819: cmd: stdin: "cat\r\n"
    ptytest.go:132: 2024-11-05 10:02:18.819: cmd: "> Enter a value (default: \"\"): can't validate build parameter \"bool_parameter\": boolean value can be either \"true\" or \"false\""
    ptytest.go:167: 2024-11-05 10:02:18.819: cmd: matched "boolean value can be either" = "\n> Enter a value (default: \"\"): can't validate build parameter \"bool_parameter\": boolean value can be either"
    update_test.go:440: 2024-11-05 10:02:18.819: cmd: stdin: "\r\n"
    ptytest.go:167: 2024-11-05 10:02:18.819: cmd: matched "Enter a value" = " \"true\" or \"false\"\n> Enter a value"
    update_test.go:440: 2024-11-05 10:02:18.819: cmd: stdin: "false\r\n"
    ptytest.go:132: 2024-11-05 10:02:18.821: cmd: "> Enter a value (default: \"\"): can't validate build parameter \"bool_parameter\": boolean value can be either \"true\" or \"false\""
```
This commit is contained in:
Spike Curtis
2024-11-07 16:47:15 +04:00
committed by GitHub
parent 6781b0fc87
commit cee6b1ebde
2 changed files with 58 additions and 47 deletions

View File

@ -323,7 +323,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
err := inv.Run() err := inv.Run()
require.NoError(t, err) require.NoError(t, err)
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace", "--always-prompt") inv, root = clitest.New(t, "update", "my-workspace", "--always-prompt")
inv = inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv) pty := ptytest.New(t).Attach(inv)
@ -333,18 +335,16 @@ func TestUpdateValidateRichParameters(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
}() }()
matches := []string{ pty.ExpectMatch(stringParameterName)
stringParameterName, "$$", pty.ExpectMatch("> Enter a value (default: \"\"): ")
"does not match", "", pty.WriteLine("$$")
"Enter a value", "abc", pty.ExpectMatch("does not match")
} pty.ExpectMatch("> Enter a value (default: \"\"): ")
for i := 0; i < len(matches); i += 2 { pty.WriteLine("")
match := matches[i] pty.ExpectMatch("does not match")
value := matches[i+1] pty.ExpectMatch("> Enter a value (default: \"\"): ")
pty.ExpectMatch(match) pty.WriteLine("abc")
pty.WriteLine(value) _ = testutil.RequireRecvCtx(ctx, t, doneChan)
}
<-doneChan
}) })
t.Run("ValidateNumber", func(t *testing.T) { t.Run("ValidateNumber", func(t *testing.T) {
@ -369,7 +369,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
err := inv.Run() err := inv.Run()
require.NoError(t, err) require.NoError(t, err)
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace", "--always-prompt") inv, root = clitest.New(t, "update", "my-workspace", "--always-prompt")
inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv) pty := ptytest.New(t).Attach(inv)
@ -379,21 +381,16 @@ func TestUpdateValidateRichParameters(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
}() }()
matches := []string{ pty.ExpectMatch(numberParameterName)
numberParameterName, "12", pty.ExpectMatch("> Enter a value (default: \"\"): ")
"is more than the maximum", "", pty.WriteLine("12")
"Enter a value", "8", pty.ExpectMatch("is more than the maximum")
} pty.ExpectMatch("> Enter a value (default: \"\"): ")
for i := 0; i < len(matches); i += 2 { pty.WriteLine("")
match := matches[i] pty.ExpectMatch("is not a number")
value := matches[i+1] pty.ExpectMatch("> Enter a value (default: \"\"): ")
pty.ExpectMatch(match) pty.WriteLine("8")
_ = testutil.RequireRecvCtx(ctx, t, doneChan)
if value != "" {
pty.WriteLine(value)
}
}
<-doneChan
}) })
t.Run("ValidateBool", func(t *testing.T) { t.Run("ValidateBool", func(t *testing.T) {
@ -418,7 +415,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
err := inv.Run() err := inv.Run()
require.NoError(t, err) require.NoError(t, err)
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace", "--always-prompt") inv, root = clitest.New(t, "update", "my-workspace", "--always-prompt")
inv = inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv) pty := ptytest.New(t).Attach(inv)
@ -428,18 +427,16 @@ func TestUpdateValidateRichParameters(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
}() }()
matches := []string{ pty.ExpectMatch(boolParameterName)
boolParameterName, "cat", pty.ExpectMatch("> Enter a value (default: \"\"): ")
"boolean value can be either", "", pty.WriteLine("cat")
"Enter a value", "false", pty.ExpectMatch("boolean value can be either \"true\" or \"false\"")
} pty.ExpectMatch("> Enter a value (default: \"\"): ")
for i := 0; i < len(matches); i += 2 { pty.WriteLine("")
match := matches[i] pty.ExpectMatch("boolean value can be either \"true\" or \"false\"")
value := matches[i+1] pty.ExpectMatch("> Enter a value (default: \"\"): ")
pty.ExpectMatch(match) pty.WriteLine("false")
pty.WriteLine(value) _ = testutil.RequireRecvCtx(ctx, t, doneChan)
}
<-doneChan
}) })
t.Run("RequiredParameterAdded", func(t *testing.T) { t.Run("RequiredParameterAdded", func(t *testing.T) {
@ -485,7 +482,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Update the workspace // Update the workspace
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace") inv, root = clitest.New(t, "update", "my-workspace")
inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv) pty := ptytest.New(t).Attach(inv)
@ -508,7 +507,7 @@ func TestUpdateValidateRichParameters(t *testing.T) {
pty.WriteLine(value) pty.WriteLine(value)
} }
} }
<-doneChan _ = testutil.RequireRecvCtx(ctx, t, doneChan)
}) })
t.Run("OptionalParameterAdded", func(t *testing.T) { t.Run("OptionalParameterAdded", func(t *testing.T) {
@ -555,7 +554,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Update the workspace // Update the workspace
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace") inv, root = clitest.New(t, "update", "my-workspace")
inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv) pty := ptytest.New(t).Attach(inv)
@ -566,7 +567,7 @@ func TestUpdateValidateRichParameters(t *testing.T) {
}() }()
pty.ExpectMatch("Planning workspace...") pty.ExpectMatch("Planning workspace...")
<-doneChan _ = testutil.RequireRecvCtx(ctx, t, doneChan)
}) })
t.Run("ParameterOptionChanged", func(t *testing.T) { t.Run("ParameterOptionChanged", func(t *testing.T) {
@ -612,7 +613,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Update the workspace // Update the workspace
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace") inv, root = clitest.New(t, "update", "my-workspace")
inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv) pty := ptytest.New(t).Attach(inv)
@ -636,7 +639,7 @@ func TestUpdateValidateRichParameters(t *testing.T) {
} }
} }
<-doneChan _ = testutil.RequireRecvCtx(ctx, t, doneChan)
}) })
t.Run("ParameterOptionDisappeared", func(t *testing.T) { t.Run("ParameterOptionDisappeared", func(t *testing.T) {
@ -683,7 +686,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Update the workspace // Update the workspace
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace") inv, root = clitest.New(t, "update", "my-workspace")
inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv) pty := ptytest.New(t).Attach(inv)
@ -707,7 +712,7 @@ func TestUpdateValidateRichParameters(t *testing.T) {
} }
} }
<-doneChan _ = testutil.RequireRecvCtx(ctx, t, doneChan)
}) })
t.Run("ParameterOptionFailsMonotonicValidation", func(t *testing.T) { t.Run("ParameterOptionFailsMonotonicValidation", func(t *testing.T) {
@ -739,7 +744,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Update the workspace // Update the workspace
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace", "--always-prompt=true") inv, root = clitest.New(t, "update", "my-workspace", "--always-prompt=true")
inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
@ -762,7 +769,7 @@ func TestUpdateValidateRichParameters(t *testing.T) {
pty.ExpectMatch(match) pty.ExpectMatch(match)
} }
<-doneChan _ = testutil.RequireRecvCtx(ctx, t, doneChan)
}) })
t.Run("ImmutableRequiredParameterExists_MutableRequiredParameterAdded", func(t *testing.T) { t.Run("ImmutableRequiredParameterExists_MutableRequiredParameterAdded", func(t *testing.T) {
@ -804,7 +811,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Update the workspace // Update the workspace
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace") inv, root = clitest.New(t, "update", "my-workspace")
inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv) pty := ptytest.New(t).Attach(inv)
@ -828,7 +837,7 @@ func TestUpdateValidateRichParameters(t *testing.T) {
} }
} }
<-doneChan _ = testutil.RequireRecvCtx(ctx, t, doneChan)
}) })
t.Run("MutableRequiredParameterExists_ImmutableRequiredParameterAdded", func(t *testing.T) { t.Run("MutableRequiredParameterExists_ImmutableRequiredParameterAdded", func(t *testing.T) {
@ -874,7 +883,9 @@ func TestUpdateValidateRichParameters(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Update the workspace // Update the workspace
ctx := testutil.Context(t, testutil.WaitLong)
inv, root = clitest.New(t, "update", "my-workspace") inv, root = clitest.New(t, "update", "my-workspace")
inv.WithContext(ctx)
clitest.SetupConfig(t, member, root) clitest.SetupConfig(t, member, root)
doneChan := make(chan struct{}) doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv) pty := ptytest.New(t).Attach(inv)
@ -898,6 +909,6 @@ func TestUpdateValidateRichParameters(t *testing.T) {
} }
} }
<-doneChan _ = testutil.RequireRecvCtx(ctx, t, doneChan)
}) })
} }

View File

@ -198,7 +198,7 @@ func (e *outExpecter) expectMatcherFunc(ctx context.Context, str string, fn func
e.fatalf("read error", "%v (wanted %q; got %q)", err, str, buffer.String()) e.fatalf("read error", "%v (wanted %q; got %q)", err, str, buffer.String())
return "" return ""
} }
e.logf("matched %q = %q", str, stripansi.Strip(buffer.String())) e.logf("matched %q = %q", str, buffer.String())
return buffer.String() return buffer.String()
} }