package tui import ( "os/exec" "reflect" "strings" "testing" ) // TestShellQuoteArgsRoundTrip guards the updater's poll-script generation: cv fields // (e.g. cert_dir_path) are operator-entered and get embedded into a shell script run // inside the updater container. If shellQuote/shellQuoteArgs mis-escapes a value, that's // a command-injection bug, not just a cosmetic one. This feeds tricky values through a // real `sh` and checks they come back out exactly as they went in. func TestShellQuoteArgsRoundTrip(t *testing.T) { if _, err := exec.LookPath("sh"); err != nil { t.Skip("sh not available") } cases := [][]string{ {"simple"}, {"has space"}, {"it's got a quote"}, {"$(echo injected)"}, {"a;b|c&d"}, {"back`tick`"}, {"multi", "arg space", "o'clock", "$HOME", "'"}, } for _, args := range cases { script := "printf '%s\\n' " + shellQuoteArgs(args) out, err := exec.Command("sh", "-c", script).Output() if err != nil { t.Fatalf("sh failed for %v: %v", args, err) } got := strings.Split(strings.TrimRight(string(out), "\n"), "\n") if !reflect.DeepEqual(got, args) { t.Errorf("round trip mismatch for %v: got %v", args, got) } } } // TestBuildRecreateCmdUsesLivePort guards against the updater silently reverting a host // port that was changed by hand after install: the recreate command must reference the // live $PORT read at recreate time, not replay the port typed into the wizard. func TestBuildRecreateCmdUsesLivePort(t *testing.T) { if _, err := exec.LookPath("sh"); err != nil { t.Skip("sh not available") } args := []string{"run", "-d", "-p", "9999:8080", "--name", "app-dono-cliente"} cmd := buildRecreateCmd(args, "9999") if strings.Contains(cmd, "9999:8080") { t.Fatalf("recreate command still contains the wizard-time port literal: %s", cmd) } if !strings.Contains(cmd, `"$PORT:8080"`) { t.Fatalf("recreate command missing live $PORT reference: %s", cmd) } // Swap the leading `docker` for `printf` so we can inspect the argv sh would have // passed to docker, with PORT set as the poll script would set it live. script := "PORT=8081\n" + strings.Replace(cmd, "docker ", "printf '%s\\n' ", 1) out, err := exec.Command("sh", "-c", script).Output() if err != nil { t.Fatalf("sh failed: %v", err) } got := strings.Split(strings.TrimRight(string(out), "\n"), "\n") want := []string{"run", "-d", "-p", "8081:8080", "--name", "app-dono-cliente"} if !reflect.DeepEqual(got, want) { t.Errorf("got %v, want %v", got, want) } }