Commit aafcacdf authored by Kirill Smelkov's avatar Kirill Smelkov

X xbtree: GetAt test

parent e003e87e
...@@ -840,17 +840,29 @@ func (δTtail *_ΔTtail) forgetPast(revCut zodb.Tid) { ...@@ -840,17 +840,29 @@ func (δTtail *_ΔTtail) forgetPast(revCut zodb.Tid) {
// and revExact=true are returned. If revision of root[key]@at cannot be // and revExact=true are returned. If revision of root[key]@at cannot be
// determined (rev=δBtail.Tail, revExact=false) are returned. // determined (rev=δBtail.Tail, revExact=false) are returned.
// //
// In particular:
//
// If δBtail has no δB entry that covers root[key]@at, return is // If δBtail has no δB entry that covers root[key]@at, return is
// //
// (value=VDEL, valueExact=false, rev=δBtail.Tail, revExact=false) // value: VDEL,
// valueExact: false,
// rev: δBtail.Tail,
// revExact: false
// //
// .rev and exact=true are returned: // If δBtail has δB entry that covers root[key]@at, return is
// //
// (δB[root/key].δvalue.New, δB.rev, exact=true) // value: δB.δvalue.New,
// valueExact: true,
// rev: δB.rev,
// revExact: true
// //
// If δBtail has no δB entry for root[key] with .rev ≤ @at, return is // If δBtail has δB entry that covers value for root[key]@at via
// δB.δvalue.Old, but not entry that covers root[key]@at fully, return is:
// //
// (VDEL, δBtail.Tail, exact=false) // value: δB.δvalue.Old,
// valueExact: true,
// rev: δBtail.Tail,
// revExact: false
// //
// key must be tracked // key must be tracked
// at must ∈ (tail, head] // at must ∈ (tail, head]
......
...@@ -1067,94 +1067,6 @@ func xverifyΔBTail_rebuild_TR(t *testing.T, δbtail *ΔBtail, tj *xbtreetest.Co ...@@ -1067,94 +1067,6 @@ func xverifyΔBTail_rebuild_TR(t *testing.T, δbtail *ΔBtail, tj *xbtreetest.Co
assertΔTtail(t, subj, δbtail, tj, treeRoot, vδTok...) assertΔTtail(t, subj, δbtail, tj, treeRoot, vδTok...)
} }
// xverifyΔBTail_GetAt verifies δBtail.Get on series of vt ZODB changes.
// XXX
// XXX kill
/*
func ___xverifyΔBTail_GetAt(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, vt ...*xbtreetest.Commit) {
subj := vt[0].Tree
for _, t := range vt[1:] {
subj += "→" + t.Tree
}
t.Run(fmt.Sprintf("Get/%s", subj), func(t *testing.T) {
// XXX ResetAtSymb(~vt[0])
for i := range vt {
fmt.Printf("@%s: %v\n", vt[i].AtSymb(), vt[i].Xkv.Flatten())
}
tkeys := allTestKeys(vt...)
tkeyv := tkeys.SortedElements()
// verify t1->t2-> ... ->tn Track(keys) Get(keys, @at)
// for all combinations of tracked keys and at
for kidx := range IntSets(len(tkeyv)) {
keys := setKey{}
for _, idx := range kidx {
keys.Add(tkeyv[idx])
}
t.Run(fmt.Sprintf("track=%s", keys), func(t *testing.T) {
xverifyΔBTail_GetAt1(t, db, treeRoot, vt, keys)
})
}
})
}
func xverifyΔBTail_GetAt1(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, vt []*xbtreetest.Commit, keys setKey) {
X := exc.Raiseif
// t1->t2-> ... -> tn
δbtail := NewΔBtail(vt[0].At, db)
for i := 1; i < len(vt); i++ {
_, err := δbtail.Update(vt[i].ΔZ); X(err)
}
// Track(keys)
txn, ctx := transaction.New(context.Background())
defer txn.Abort()
zconn, err := db.Open(ctx, &zodb.ConnOptions{At: vt[len(vt)-1].At}); X(err)
xtree, err := zconn.Get(ctx, treeRoot); X(err)
ztree := xtree.(*Tree)
for k := range keys {
_, _, path, err := ZTreeGetBlkData(ctx, ztree, k); X(err)
err = δbtail.Track(k, path); X(err)
}
// verify GetAt(k, @at) for all keys and @at
for i := 1; i < len(vt); i++ {
at := vt[i].At
for _, k := range keys.SortedElements() {
vOid, ok, rev, revExact, err := δbtail.GetAt(ctx, ztree, k, at); X(err)
v := xzgetBlkDataAt(db, vOid, rev)
v_, ok_ := vt[i].Xkv.Get(k).kv[k]
rev_, revExact_ := vt[i].At, false
for j := i-1; j >= 0; j-- {
v__ := vt[j].Xkv.Get(k).kv[k]
if v__ != v_ {
rev_ = vt[j+1].At
revExact_ = true
break
}
rev_ = vt[j].At
}
if v == "" { v = DEL }
if v_ == "" { v_ = DEL }
if !(v == v_ && ok == ok_ && rev == rev_ && revExact == revExact_) {
t.Errorf("Get(%d, @%s) ->\nhave: %s, %v, @%s, %v\nwant: %s, %v, @%s, %v",
k, T.AtSymb(at),
v, ok, T.AtSymb(rev), revExact,
v_, ok_, T.AtSymb(rev_), revExact_)
}
}
}
}
*/
// ---------------------------------------- // ----------------------------------------
...@@ -1189,6 +1101,71 @@ func TestΔBtailForget(t_ *testing.T) { ...@@ -1189,6 +1101,71 @@ func TestΔBtailForget(t_ *testing.T) {
// XXX verify no aliasing // XXX verify no aliasing
} }
func TestΔBtailGetAt(t_ *testing.T) {
// GetAt is thin wrapper around data in ΔTtail.vδT and (TODO) lastRevOf index.
// Recomputing ΔTtail.vδT itself (and TODO lastRevOf) is exercised in depth
// by xverifyΔBTail_rebuild. Here we verify only properties of the wrapper.
t := xbtreetest.NewT(t_)
X := exc.Raiseif
const ø = "ø"
t.CommitTree("T/B:")
t1 := t.CommitTree("T/B2:b,3:c") ; at1 := t1.At // 2:b 3:c
t2 := t.CommitTree("T/B2:b,3:c,4:d") ; at2 := t2.At // 4:d
t3 := t.CommitTree("T/B2:b,3:e,4:d") ; at3 := t3.At // 3:e
t4 := t.CommitTree("T/B2:b,3:e,4:f") ; at4 := t4.At // 4:f
t5 := t.CommitTree("T/B2:b,3:g,4:f") ; at5 := t5.At // 3:g
δBtail := NewΔBtail(t1.At, t.DB)
_, err := δBtail.Update(t2.ΔZ); X(err)
_, err = δBtail.Update(t3.ΔZ); X(err)
_, err = δBtail.Update(t4.ΔZ); X(err)
_, err = δBtail.Update(t5.ΔZ); X(err)
// track everything
_1234 := setKey{}; _1234.Add(1); _1234.Add(2); _1234.Add(3); _1234.Add(4)
trackKeys(δBtail, t5, _1234)
// assertGetAt asserts that GetAt returns expected result.
assertGetAt := func(at zodb.Tid, key Key, valueOK string, revOK zodb.Tid, valueExactOK, revExactOK bool) {
t.Helper()
valueOid, rev, valueExact, revExact, err := δBtail.GetAt(t.Root(), key, at); X(err)
value := ø
if valueOid != VDEL {
value = t.XGetCommit(rev).XGetBlkData(valueOid)
}
if !(value == valueOK && rev == revOK && valueExact == valueExactOK && revExact == revExactOK) {
t.Errorf("GetAt(%v@%s):\nhave: %s @%s %t %t\nwant: %s @%s %t %t",
key, t.AtSymb(at),
value, t.AtSymb(rev), valueExact, revExact,
valueOK, t.AtSymb(revOK), valueExactOK, revExactOK,
)
}
}
// @at key value rev valueExact revExact
assertGetAt(at2, 1, ø, at1, false, false)
assertGetAt(at2, 2, ø, at1, false, false)
assertGetAt(at2, 3, "c", at1, true, false)
assertGetAt(at2, 4, "d", at2, true, true)
assertGetAt(at3, 1, ø, at1, false, false)
assertGetAt(at3, 2, ø, at1, false, false)
assertGetAt(at3, 3, "e", at3, true, true)
assertGetAt(at3, 4, "d", at2, true, true)
assertGetAt(at4, 1, ø, at1, false, false)
assertGetAt(at4, 2, ø, at1, false, false)
assertGetAt(at4, 3, "e", at3, true, true)
assertGetAt(at4, 4, "f", at4, true, true)
assertGetAt(at5, 1, ø, at1, false, false)
assertGetAt(at5, 2, ø, at1, false, false)
assertGetAt(at5, 3, "g", at5, true, true)
assertGetAt(at5, 4, "f", at4, true, true)
}
func TestΔBtailSliceByRootRev(t_ *testing.T) { func TestΔBtailSliceByRootRev(t_ *testing.T) {
// SliceByRootRev is thin wrapper to return ΔTtail.vδT slice. // SliceByRootRev is thin wrapper to return ΔTtail.vδT slice.
// Recomputing ΔTtail.vδT itself is exercised in depth by xverifyΔBTail_rebuild. // Recomputing ΔTtail.vδT itself is exercised in depth by xverifyΔBTail_rebuild.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment