|
|
@@ -462,31 +462,44 @@ func runRandTest(rt randTest) bool {
|
|
|
return false
|
|
|
}
|
|
|
case opCheckCacheInvariant:
|
|
|
- return checkCacheInvariant(tr.root, tr.cachegen, 0)
|
|
|
+ return checkCacheInvariant(tr.root, nil, tr.cachegen, false, 0)
|
|
|
}
|
|
|
}
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
-func checkCacheInvariant(n node, parentCachegen uint16, depth int) bool {
|
|
|
+func checkCacheInvariant(n, parent node, parentCachegen uint16, parentDirty bool, depth int) bool {
|
|
|
+ var children []node
|
|
|
+ var flag nodeFlag
|
|
|
switch n := n.(type) {
|
|
|
case *shortNode:
|
|
|
- if n.flags.gen > parentCachegen {
|
|
|
- fmt.Printf("cache invariant violation: %d > %d\nat depth %d node %s", n.flags.gen, parentCachegen, depth, spew.Sdump(n))
|
|
|
- return false
|
|
|
- }
|
|
|
- return checkCacheInvariant(n.Val, n.flags.gen, depth+1)
|
|
|
+ flag = n.flags
|
|
|
+ children = []node{n.Val}
|
|
|
case *fullNode:
|
|
|
- if n.flags.gen > parentCachegen {
|
|
|
- fmt.Printf("cache invariant violation: %d > %d\nat depth %d node %s", n.flags.gen, parentCachegen, depth, spew.Sdump(n))
|
|
|
+ flag = n.flags
|
|
|
+ children = n.Children[:]
|
|
|
+ default:
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ showerror := func() {
|
|
|
+ fmt.Printf("at depth %d node %s", depth, spew.Sdump(n))
|
|
|
+ fmt.Printf("parent: %s", spew.Sdump(parent))
|
|
|
+ }
|
|
|
+ if flag.gen > parentCachegen {
|
|
|
+ fmt.Printf("cache invariant violation: %d > %d\n", flag.gen, parentCachegen)
|
|
|
+ showerror()
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if depth > 0 && !parentDirty && flag.dirty {
|
|
|
+ fmt.Printf("cache invariant violation: child is dirty but parent isn't\n")
|
|
|
+ showerror()
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ for _, child := range children {
|
|
|
+ if !checkCacheInvariant(child, n, flag.gen, flag.dirty, depth+1) {
|
|
|
return false
|
|
|
}
|
|
|
- for _, child := range n.Children {
|
|
|
- if !checkCacheInvariant(child, n.flags.gen, depth+1) {
|
|
|
- return false
|
|
|
- }
|
|
|
- }
|
|
|
- return true
|
|
|
}
|
|
|
return true
|
|
|
}
|