package moves import ( "encoding/json" "strings" "testing" ) func stoppedWith(ok map[string]bool) StoppedReport { r := StoppedReport{V: 1, Steps: map[string]Check{}} for id, pass := range ok { if pass { r.Steps[id] = Check{OK: true} } else { r.Steps[id] = Check{Reason: "no"} } } return r } func TestStoppedReportTreeStoppedNeedsStepsOneToFour(t *testing.T) { all := map[string]bool{StepTree: true, StepStray: true, StepFDs: true, StepLease: true} if r := stoppedWith(all); !r.TreeStopped() || r.Complete() { t.Fatalf("steps 1 to 4 OK: TreeStopped %v Complete %v, want true false", r.TreeStopped(), r.Complete()) } for _, step := range []string{StepTree, StepStray, StepFDs, StepLease} { failed := map[string]bool{StepTree: true, StepStray: true, StepFDs: true, StepLease: true, StepReplica: true} failed[step] = false if r := stoppedWith(failed); r.TreeStopped() || r.Complete() { t.Fatalf("%s failed but TreeStopped %v Complete %v", step, r.TreeStopped(), r.Complete()) } missing := map[string]bool{StepTree: true, StepStray: true, StepFDs: true, StepLease: true, StepReplica: true} delete(missing, step) if r := stoppedWith(missing); r.TreeStopped() || r.Complete() { t.Fatalf("%s never ran but TreeStopped %v Complete %v", step, r.TreeStopped(), r.Complete()) } } if (StoppedReport{}).TreeStopped() || (StoppedReport{}).Complete() { t.Fatal("the zero report passed") } } func TestStoppedReportCompleteNeedsTheReplicaAndEveryStep(t *testing.T) { all := map[string]bool{StepTree: true, StepStray: true, StepFDs: true, StepLease: true, StepReplica: true} if r := stoppedWith(all); !r.Complete() || !r.TreeStopped() { t.Fatalf("every step OK: Complete %v TreeStopped %v", r.Complete(), r.TreeStopped()) } all[StepReplica] = false if r := stoppedWith(all); r.Complete() || !r.TreeStopped() { t.Fatalf("replica failed: Complete %v TreeStopped %v, want false true", r.Complete(), r.TreeStopped()) } // A step this version does not know about still has to pass: Complete // fails closed on anything a newer writer recorded as failed. all[StepReplica] = true all["later"] = false if r := stoppedWith(all); r.Complete() { t.Fatal("a failed extra step passed Complete") } } func TestStoppedReportWireNames(t *testing.T) { r := StoppedReport{V: 1, Role: "source", Box: "b", Incarnation: "i", ClaimGen: 7, Host: "h.example.com", OpID: "op", Steps: map[string]Check{StepTree: {OK: true}}, Stray: []int{9}, FinalTXID: 12, DBSHA256: "d", FilesPlain: "f", TimersSHA256: "t"} raw, err := json.Marshal(r) if err != nil { t.Fatal(err) } for _, name := range []string{`"v":1`, `"role":"source"`, `"box":"b"`, `"incarnation":"i"`, `"claim_gen":7`, `"host":"h.example.com"`, `"op_id":"op"`, `"steps":{"tree":{"ok":true,"reason":""}}`, `"stray":[9]`, `"final_txid":12`, `"db_sha256":"d"`, `"files_plain":"f"`, `"timers_sha256":"t"`, `"checked_at":`} { if !strings.Contains(string(raw), name) { t.Fatalf("%s missing from %s", name, raw) } } }