Why: a crash after a tool was about to run left the call unpaired, and workspace writes could not be rewound. Evidence: GOWORK=off go test ./runtime/ ./runtime/llm/ ./runtime/checkpoint/ ./runtime/telemetry/ ./runtime/tools/ ./runtime/session/ ./adapters/native/ Impact: pending calls rerun only when both the stored and current replay declarations are safe; otherwise the result is an error. Empty fallback lists and a nil checkpoint log keep the previous behavior. Refs: feature/durable-rewind Co-authored-by: Cursor <cursoragent@cursor.com>
81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
package checkpoint
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestRewindRestoresTrackedWriteAndSkipsExternalChange(t *testing.T) {
|
|
root := t.TempDir()
|
|
log, err := Open(filepath.Join(t.TempDir(), "cp.jsonl"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, "keep.txt"), []byte("old"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := log.Record("m1", root, "keep.txt", []byte("old"), true, []byte("new")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, "keep.txt"), []byte("new"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, "side.txt"), []byte("from-shell"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := log.Record("m1", root, "moved.txt", []byte("a"), true, []byte("b")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, "moved.txt"), []byte("someone-else"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
got, err := log.Rewind("m1", []string{"m1"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(got.Restored) != 1 || got.Restored[0] != "keep.txt" {
|
|
t.Fatalf("restored %#v", got.Restored)
|
|
}
|
|
if len(got.Skipped) != 1 || got.Skipped[0] != "moved.txt" {
|
|
t.Fatalf("skipped %#v", got.Skipped)
|
|
}
|
|
body, err := os.ReadFile(filepath.Join(root, "keep.txt"))
|
|
if err != nil || string(body) != "old" {
|
|
t.Fatalf("keep.txt %q %v", body, err)
|
|
}
|
|
side, err := os.ReadFile(filepath.Join(root, "side.txt"))
|
|
if err != nil || string(side) != "from-shell" {
|
|
t.Fatalf("untracked file changed: %q %v", side, err)
|
|
}
|
|
moved, _ := os.ReadFile(filepath.Join(root, "moved.txt"))
|
|
if string(moved) != "someone-else" {
|
|
t.Fatalf("external edit was reverted: %q", moved)
|
|
}
|
|
}
|
|
|
|
func TestRewindRemovesCreatedFile(t *testing.T) {
|
|
root := t.TempDir()
|
|
log, err := Open(filepath.Join(t.TempDir(), "cp.jsonl"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, "new.txt"), []byte("hi"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := log.Record("m2", root, "new.txt", nil, false, []byte("hi")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := log.Rewind("m2", []string{"m1", "m2"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(got.Restored) != 1 {
|
|
t.Fatalf("restored %#v", got.Restored)
|
|
}
|
|
if _, err := os.Stat(filepath.Join(root, "new.txt")); !os.IsNotExist(err) {
|
|
t.Fatalf("created file still present: %v", err)
|
|
}
|
|
}
|