TestApplyKeepsPreviousBinaryAsOld is the cross-platform-parity guard: Apply must rename execPath aside to execPath+".old" before moving the new download in, never replace it directly. Windows requires this (MoveFileEx with REPLACE_EXISTING fails against a running .exe's sharing lock), and the same r
(t *testing.T)
| 391 | // rename-aside on linux/macos keeps the flow identical everywhere. CleanupOld |
| 392 | // deletes the stale .old on the next launch. |
| 393 | func TestApplyKeepsPreviousBinaryAsOld(t *testing.T) { |
| 394 | asset := platformAsset(t) |
| 395 | newBody := []byte("new release v2\n") |
| 396 | oldBody := []byte("running binary v1\n") |
| 397 | r := newFakeRelease(t, asset, newBody, hashOf(newBody)) |
| 398 | withReleaseURLs(t, r.srv.URL) |
| 399 | |
| 400 | tmpDir := t.TempDir() |
| 401 | exec := filepath.Join(tmpDir, "codehamr") |
| 402 | if err := os.WriteFile(exec, oldBody, 0o755); err != nil { |
| 403 | t.Fatal(err) |
| 404 | } |
| 405 | |
| 406 | if err := Apply(context.Background(), exec); err != nil { |
| 407 | t.Fatalf("Apply: %v", err) |
| 408 | } |
| 409 | got, err := os.ReadFile(exec) |
| 410 | if err != nil { |
| 411 | t.Fatal(err) |
| 412 | } |
| 413 | if string(got) != string(newBody) { |
| 414 | t.Fatalf("execPath should hold the new binary, got %q", got) |
| 415 | } |
| 416 | oldPath := exec + ".old" |
| 417 | gotOld, err := os.ReadFile(oldPath) |
| 418 | if err != nil { |
| 419 | t.Fatalf("Apply must preserve previous binary at %s, got %v", oldPath, err) |
| 420 | } |
| 421 | if string(gotOld) != string(oldBody) { |
| 422 | t.Fatalf("%s should hold the previous binary, got %q", oldPath, gotOld) |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | // TestCleanupOldRemovesStaleFile: the previous Apply's .old must be removed at |
| 427 | // the next launch so it doesn't accumulate. On Windows .old stays locked until |
nothing calls this directly
no test coverage detected