| index bbde67b4d..5071e7b82 100644 |
| --- a/e2e_test.go |
| +++ b/e2e_test.go |
| @@ -1437,6 +1437,64 @@ func TestAddAccountIDRefusesAName(t *testing.T) { |
| } |
| } |
| |
| +// carlos add on an existing host is an update and must say so — the vitogo |
| +// incident (issue #69) started with `added vito.platform.tito.io` printed |
| +// over what was actually a rewrite of an existing row. |
| +func TestAddOnExistingRouteSaysUpdated(t *testing.T) { |
| + goBin, err := exec.LookPath("go") |
| + if err != nil { |
| + t.Skip("go toolchain not found") |
| + } |
| + tmp := t.TempDir() |
| + carlosBin := filepath.Join(tmp, "carlos") |
| + build := exec.Command(goBin, "build", "-o", carlosBin, ".") |
| + build.Env = os.Environ() |
| + if out, err := build.CombinedOutput(); err != nil { |
| + t.Fatalf("build carlos: %v\n%s", err, out) |
| + } |
| + regPath := filepath.Join(tmp, "registry.db") |
| + |
| + run := func(args ...string) (string, error) { |
| + cmd := exec.Command(carlosBin, args...) |
| + cmd.Env = carlosTestEnv(t) |
| + cmd.Dir = tmp |
| + out, err := cmd.CombinedOutput() |
| + return string(out), err |
| + } |
| + |
| + out, err := run("add", "-registry", regPath, "-app", "vitogo", |
| + "-db", "/data/first.db", "vito.example.com") |
| + if err != nil { |
| + t.Fatalf("first add: %v\n%s", err, out) |
| + } |
| + if !strings.Contains(out, "added vito.example.com") { |
| + t.Errorf("first add output = %q, want %q", out, "added vito.example.com") |
| + } |
| + |
| + out, err = run("add", "-registry", regPath, "-app", "vitogo", |
| + "-db", "/data/second.db", "vito.example.com") |
| + if err != nil { |
| + t.Fatalf("re-add: %v\n%s", err, out) |
| + } |
| + if !strings.Contains(out, "updated vito.example.com") { |
| + t.Errorf("re-add output = %q, want it to say updated, not added", out) |
| + } |
| + |
| + // And the rewrite must actually land — the row carries the new path. |
| + reg, err := registry.Open(regPath) |
| + if err != nil { |
| + t.Fatalf("open registry: %v", err) |
| + } |
| + defer reg.Close() |
| + rt, err := reg.Get("vito.example.com") |
| + if err != nil || rt == nil { |
| + t.Fatalf("get route: %v (rt=%v)", err, rt) |
| + } |
| + if rt.DBPath != "/data/second.db" { |
| + t.Errorf("db_path = %q, want /data/second.db", rt.DBPath) |
| + } |
| +} |
| + |
| // An app still on the pre-accounts keys can be moved INTO ops. Until `-from |
| // legacy` existed there was no way to say it: a bare move into ops is refused |
| // (ops is also the default source, and the verb will not guess a direction), |