aboutsummaryrefslogtreecommitdiff
path: root/internal/engine/property_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/engine/property_test.go')
-rw-r--r--internal/engine/property_test.go42
1 files changed, 30 insertions, 12 deletions
diff --git a/internal/engine/property_test.go b/internal/engine/property_test.go
index 39589da..135c20a 100644
--- a/internal/engine/property_test.go
+++ b/internal/engine/property_test.go
@@ -102,27 +102,41 @@ func propertySeeds(t *testing.T) []int64 {
// chain loses no content - every file's content is still somewhere under
// the home directory, the Trash included - and undoing the run then puts
// the home directory back exactly: every file's content, mode and
-// modification time, and nothing extra. A failing subtest names its seed.
+// modification time, every directory, and nothing extra. A failing subtest
+// names its seed. It also fails when fewer than half the cases applied
+// anything, so a broken Apply cannot make it pass vacuously (review undo
+// F7).
func TestApplyUndoProperty(t *testing.T) {
- for _, seed := range propertySeeds(t) {
+ seeds := propertySeeds(t)
+ applied := 0
+ for _, seed := range seeds {
t.Run(fmt.Sprintf("seed=%d", seed), func(t *testing.T) {
- checkApplyUndo(t, genCase(rand.New(rand.NewSource(seed))))
+ if checkApplyUndo(t, genCase(rand.New(rand.NewSource(seed)))) {
+ applied++
+ }
})
}
+ if len(seeds) >= 20 && applied*2 < len(seeds) {
+ t.Errorf("only %d of %d cases applied anything; the property is not being exercised", applied, len(seeds))
+ }
}
-// contentCounts counts the files of a snapshot by content hash.
+// contentCounts counts the files of a snapshot by content hash; directory
+// entries have no content and are not counted.
func contentCounts(snap map[string]string) map[string]int {
counts := map[string]int{}
for _, v := range snap {
- counts[strings.Fields(v)[0]]++
+ if v != "dir" {
+ counts[strings.Fields(v)[0]]++
+ }
}
return counts
}
// checkApplyUndo builds c in a sandbox, applies every chain, checks nothing
-// was lost, undoes the run and checks the home directory is as it was.
-func checkApplyUndo(t *testing.T, c propertyCase) {
+// was lost, undoes the run and checks the home directory - files and
+// directories - is as it was. It reports whether any file was applied.
+func checkApplyUndo(t *testing.T, c propertyCase) bool {
h := sandbox(t)
old := time.Date(2026, 3, 1, 12, 0, 0, 0, time.UTC)
put := func(p, body string) {
@@ -147,12 +161,15 @@ func checkApplyUndo(t *testing.T, c propertyCase) {
put(filepath.Join(h, rel), body)
}
main := writeConfig(t, h, `(include "dl")`, map[string]string{"dl": c.rules})
- // userTree is the home directory without krino's own config and state.
+ // userTree is the home directory, files and directories, without
+ // krino's own config, state, Trash and cache.
userTree := func() map[string]string {
- snap := snapshot(t, h)
+ snap := treeSnapshot(t, h)
for rel := range snap {
- if strings.HasPrefix(rel, ".config/") || strings.HasPrefix(rel, ".local/") {
- delete(snap, rel)
+ for _, own := range []string{".config/", ".local/", ".cache/"} {
+ if strings.HasPrefix(rel, own) {
+ delete(snap, rel)
+ }
}
}
return snap
@@ -193,7 +210,7 @@ func checkApplyUndo(t *testing.T, c propertyCase) {
if after := userTree(); !reflect.DeepEqual(after, before) {
t.Fatalf("nothing was applied, yet the tree changed")
}
- return
+ return false
}
have := contentCounts(snapshot(t, h))
@@ -236,4 +253,5 @@ func checkApplyUndo(t *testing.T, c propertyCase) {
}
}
}
+ return true
}