Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions test/e2e/vm_user_journey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ func TestVM_Journey_FirstTimeUser(t *testing.T) {

vm := testutil.NewMacHost(t)
vmInstallHomebrew(t, vm)
// Uninstall the minimal preset packages so openboot actually installs them
// rather than finding them pre-installed on the GHA runner image.
// Remove the brew-installed openboot (left by TestVM_Interactive_InstallScript)
// and the minimal preset packages so openboot actually installs them.
vm.Run(fmt.Sprintf(
"export PATH=%q && brew uninstall --ignore-dependencies jq ripgrep fd bat fzf htop tree gh 2>/dev/null || true",
"export PATH=%q && brew uninstall --ignore-dependencies openboot jq ripgrep fd bat fzf htop tree gh 2>/dev/null || true",
brewPath,
))
bin := vmCopyDevBinary(t, vm)
Expand Down
15 changes: 14 additions & 1 deletion testutil/machost.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@

var script strings.Builder
fmt.Fprintf(&script, "set timeout %d\n", timeoutSec)
fmt.Fprintf(&script, "spawn bash -c %s\n", shellescape(command))
// Use Tcl quoting so the entire command is a single word.
// shellescape produces POSIX single-quote escaping which Tcl's word
// splitter does not honour — it splits on whitespace regardless.
fmt.Fprintf(&script, "spawn bash -c %s\n", tclBrace(command))
for _, step := range steps {
fmt.Fprintf(&script, "expect %q\n", step.Expect)
fmt.Fprintf(&script, "send %q\n", step.Send)
Expand Down Expand Up @@ -102,10 +105,20 @@
return nil
}

func shellescape(s string) string {

Check failure on line 108 in testutil/machost.go

View workflow job for this annotation

GitHub Actions / deadcode (drift)

unreachable func: shellescape
return "'" + strings.ReplaceAll(s, "'", "'\\''") + "'"
}

// tclBrace quotes s as a single Tcl word. Uses brace quoting {s} when safe
// (no unbalanced braces), otherwise falls back to Tcl double-quote escaping.
func tclBrace(s string) string {
if !strings.ContainsAny(s, "{}") {
return "{" + s + "}"
}
r := strings.NewReplacer(`\`, `\\`, `"`, `\"`, `$`, `\$`, `[`, `\[`)
return `"` + r.Replace(s) + `"`
}

func requireEphemeralHost(t *testing.T) {
t.Helper()
if os.Getenv("OPENBOOT_IN_VM") == "1" {
Expand Down
Loading