package api import ( "go/ast" "go/parser" "go/token" "strings" "testing" ) // R-474 — the remove handler really deletes the whole unit, the Tier-2 mirror and the prefs. func TestR474_RemoveHandlerDeletesUnitMirrorAndPrefs(t *testing.T) { fset := token.NewFileSet() f, err := parser.ParseFile(fset, "router.go", nil, 0) if err != nil { t.Fatal(err) } var sel []string for _, d := range f.Decls { fn, ok := d.(*ast.FuncDecl) if !ok || fn.Name.Name != "removeStack" || fn.Body == nil { continue } ast.Inspect(fn.Body, func(n ast.Node) bool { if s, ok := n.(*ast.SelectorExpr); ok { sel = append(sel, s.Sel.Name) } return true }) } joined := " " + strings.Join(sel, " ") + " " for _, want := range []string{"RecoveryUnitPath", "Tier2MirrorDirsForApp", "RemoveTier2Mirrors", "DeleteAppBackupPrefs"} { if !strings.Contains(joined, " "+want+" ") { t.Errorf("removeStack must call %s", want) } } } // R-486 — removing an app with its backups KEPT keeps its Tier-2 record. The only call that may // forget the record is DeleteAppBackupPrefs, which the R-474 branch guards on remove_backups. // // COMPANION RED-PROOF (REPORT.md): put `r.sett.SetCrossDriveConfig(name, nil)` back into // removeStack unconditionally — this fails. func TestR486_RemovalKeepsTheTier2RecordUnlessBackupsGo(t *testing.T) { fset := token.NewFileSet() f, err := parser.ParseFile(fset, "router.go", nil, 0) if err != nil { t.Fatal(err) } for _, d := range f.Decls { fn, ok := d.(*ast.FuncDecl) if !ok || fn.Name.Name != "removeStack" || fn.Body == nil { continue } ast.Inspect(fn.Body, func(n ast.Node) bool { if s, ok := n.(*ast.SelectorExpr); ok && s.Sel.Name == "SetCrossDriveConfig" { t.Errorf("removeStack calls SetCrossDriveConfig at line %d — a removal with backups kept would forget the mirror it kept (R-486)", fset.Position(s.Pos()).Line) } return true }) } }