Task 9: Operation ordering tests #9

Closed
opened 2026-09-10 17:16:06 +00:00 by Cordy · 1 comment
Owner

Depends on Task 8. Order was written there; this task proves it.

Files

  • Create: internal/sync/ops_test.go

Steps

  • Write the tests:
package sync

import "testing"

func TestOrderCreatesParentFirst(t *testing.T) {
	ops := []Operation{
		{Op: OpDownload, Path: "a/b/c.txt"},
		{Op: OpDownload, Path: "a"},
		{Op: OpDownload, Path: "a/b"},
	}
	got := Order(ops)
	want := []string{"a", "a/b", "a/b/c.txt"}
	for i, w := range want {
		if got[i].Path != w {
			t.Fatalf("position %d = %q, want %q (full: %+v)", i, got[i].Path, w, got)
		}
	}
}

func TestOrderDeletesChildFirst(t *testing.T) {
	ops := []Operation{
		{Op: OpDeleteLocal, Path: "a"},
		{Op: OpDeleteLocal, Path: "a/b/c.txt"},
		{Op: OpDeleteLocal, Path: "a/b"},
	}
	got := Order(ops)
	want := []string{"a/b/c.txt", "a/b", "a"}
	for i, w := range want {
		if got[i].Path != w {
			t.Fatalf("position %d = %q, want %q (full: %+v)", i, got[i].Path, w, got)
		}
	}
}

func TestOrderPutsNonDeletesBeforeDeletes(t *testing.T) {
	ops := []Operation{
		{Op: OpDeleteRemote, Path: "old.txt"},
		{Op: OpUpload, Path: "new.txt"},
	}
	got := Order(ops)
	if got[0].Op != OpUpload {
		t.Errorf("expected upload before delete, got %+v", got)
	}
}
  • Run them. They should pass against Task 8's implementation. If any fails, fix Order — not the test.
  • Commit: git commit -s -m "test(sync): operation ordering invariants"

Acceptance criteria

  • All three orderings hold.
  • Order does not mutate its input slice.
Depends on Task 8. `Order` was written there; this task proves it. ## Files - Create: `internal/sync/ops_test.go` ## Steps - [ ] **Write the tests:** ```go package sync import "testing" func TestOrderCreatesParentFirst(t *testing.T) { ops := []Operation{ {Op: OpDownload, Path: "a/b/c.txt"}, {Op: OpDownload, Path: "a"}, {Op: OpDownload, Path: "a/b"}, } got := Order(ops) want := []string{"a", "a/b", "a/b/c.txt"} for i, w := range want { if got[i].Path != w { t.Fatalf("position %d = %q, want %q (full: %+v)", i, got[i].Path, w, got) } } } func TestOrderDeletesChildFirst(t *testing.T) { ops := []Operation{ {Op: OpDeleteLocal, Path: "a"}, {Op: OpDeleteLocal, Path: "a/b/c.txt"}, {Op: OpDeleteLocal, Path: "a/b"}, } got := Order(ops) want := []string{"a/b/c.txt", "a/b", "a"} for i, w := range want { if got[i].Path != w { t.Fatalf("position %d = %q, want %q (full: %+v)", i, got[i].Path, w, got) } } } func TestOrderPutsNonDeletesBeforeDeletes(t *testing.T) { ops := []Operation{ {Op: OpDeleteRemote, Path: "old.txt"}, {Op: OpUpload, Path: "new.txt"}, } got := Order(ops) if got[0].Op != OpUpload { t.Errorf("expected upload before delete, got %+v", got) } } ``` - [ ] **Run them.** They should pass against Task 8's implementation. **If any fails, fix `Order` — not the test.** - [ ] **Commit:** `git commit -s -m "test(sync): operation ordering invariants"` ## Acceptance criteria - All three orderings hold. - `Order` does not mutate its input slice.
Cordy added this to the phase-1-engine milestone 2026-09-10 17:16:06 +00:00
Author
Owner

Done

What was built

  • Added internal/sync/ops_test.go with the three test functions from the issue body, verbatim.
  • Tests assert Order's three invariants: non-deletes parent-first, deletes child-first, non-deletes before deletes.
  • Order itself (internal/sync/ops.go, written in Task 8) required no change — this task only adds coverage.
  • RED step done via three targeted mutations to Order (one per invariant), each shown to break only its own test, then reverted (R10).

Tests

  • go test ./internal/sync/... -run TestOrder -v: all three tests pass against Task 8's Order.
  • Full suite green: go vet ./... clean, go test -count=1 ./... passes across remote/state/sync/vfs; gofmt -l . empty; go mod tidy leaves go.mod/go.sum unchanged.
  • CI run #9 (http://192.168.10.245/Cordy/cairn-desktop/actions/runs/9) green on linux/arm64, Go 1.25.5.

Acceptance criteria

  • All three orderings hold. Met — TestOrderCreatesParentFirst, TestOrderDeletesChildFirst, TestOrderPutsNonDeletesBeforeDeletes all pass; each was independently driven red by a mutation targeting exactly the property it checks.
  • Order does not mutate its input slice. Met by Task 8's implementation (copy(out, ops) before sort.SliceStable); not one of the issue's three mandated tests, so verified via an uncommitted probe and reproduced independently during review.

Rulings

  • R10: the red step is shown by temporarily mutating Order (e.g. reversing the depth comparison), observing each test fail, then reverting.
  • R12: commit subject is the exact text from the issue, always git commit -s, carrying the Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> trailer.
  • Parked (completeness): the verbatim tests don't check len(got), but Order's make+copy+sort.SliceStable cannot drop or duplicate elements, and a shorter result would panic (a go test FAIL), not pass silently; carried to #12/#13 reviewers as a watch item.
  • Parked (CV1): RED transcripts for mutations A/B/C plus the no-mutation probe were reproduced independently in a scratch clone of 5f2188d — same pass/fail results as reported.
  • Parked (CV2): full suite, go vet, gofmt -l ., go mod tidy reproduced independently in a scratch clone — all clean, matching the report.
  • Parked (CV3): CI is the gate for closing this issue (R11); 5f2188d was pushed alone since its only unlanded ancestor, 6ccb7fb, is already origin/main.

Deferred

  • F1 (minor): "Order does not mutate its input" has no committed regression test — true today, checked only by an uncommitted probe; a future in-place-sort refactor wouldn't be caught by CI. Deferred to the final review.
  • F2 (minor): the issue's verbatim tests don't assert len(got) or that Order is a full permutation of its input — this is issue text and must stay verbatim; a stronger test can be added at final review if wanted.

Implemented and reviewed by Claude (subagent-driven), landed on main after review and green CI.

**Done** - [test(sync): operation ordering invariants](http://192.168.10.245/Cordy/cairn-desktop/commit/5f2188d8927b4ee9872987fca4aa59c88a8b72a0) **What was built** - Added `internal/sync/ops_test.go` with the three test functions from the issue body, verbatim. - Tests assert `Order`'s three invariants: non-deletes parent-first, deletes child-first, non-deletes before deletes. - `Order` itself (`internal/sync/ops.go`, written in Task 8) required no change — this task only adds coverage. - RED step done via three targeted mutations to `Order` (one per invariant), each shown to break only its own test, then reverted (R10). **Tests** - `go test ./internal/sync/... -run TestOrder -v`: all three tests pass against Task 8's `Order`. - Full suite green: `go vet ./...` clean, `go test -count=1 ./...` passes across remote/state/sync/vfs; `gofmt -l .` empty; `go mod tidy` leaves go.mod/go.sum unchanged. - CI run #9 (http://192.168.10.245/Cordy/cairn-desktop/actions/runs/9) green on linux/arm64, Go 1.25.5. **Acceptance criteria** - *All three orderings hold.* Met — `TestOrderCreatesParentFirst`, `TestOrderDeletesChildFirst`, `TestOrderPutsNonDeletesBeforeDeletes` all pass; each was independently driven red by a mutation targeting exactly the property it checks. - *`Order` does not mutate its input slice.* Met by Task 8's implementation (`copy(out, ops)` before `sort.SliceStable`); not one of the issue's three mandated tests, so verified via an uncommitted probe and reproduced independently during review. **Rulings** - R10: the red step is shown by temporarily mutating `Order` (e.g. reversing the depth comparison), observing each test fail, then reverting. - R12: commit subject is the exact text from the issue, always `git commit -s`, carrying the `Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>` trailer. - Parked (completeness): the verbatim tests don't check `len(got)`, but `Order`'s make+copy+sort.SliceStable cannot drop or duplicate elements, and a shorter result would panic (a `go test` FAIL), not pass silently; carried to #12/#13 reviewers as a watch item. - Parked (CV1): RED transcripts for mutations A/B/C plus the no-mutation probe were reproduced independently in a scratch clone of 5f2188d — same pass/fail results as reported. - Parked (CV2): full suite, `go vet`, `gofmt -l .`, `go mod tidy` reproduced independently in a scratch clone — all clean, matching the report. - Parked (CV3): CI is the gate for closing this issue (R11); 5f2188d was pushed alone since its only unlanded ancestor, 6ccb7fb, is already `origin/main`. **Deferred** - F1 (minor): "`Order` does not mutate its input" has no committed regression test — true today, checked only by an uncommitted probe; a future in-place-sort refactor wouldn't be caught by CI. Deferred to the final review. - F2 (minor): the issue's verbatim tests don't assert `len(got)` or that `Order` is a full permutation of its input — this is issue text and must stay verbatim; a stronger test can be added at final review if wanted. _Implemented and reviewed by Claude (subagent-driven), landed on main after review and green CI._
Cordy closed this issue 2026-09-10 22:35:03 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/cairn-desktop#9
No description provided.