Commit ee2bb183 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent e40c32c9
......@@ -28,6 +28,7 @@ import (
"os"
"os/exec"
"regexp"
"sort"
"strings"
"testing"
......@@ -35,7 +36,6 @@ import (
"lab.nexedi.com/kirr/go123/xerr"
"lab.nexedi.com/kirr/neo/go/transaction"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/zodb/btree"
)
// TreeGen represents connection to running `treegen trees` server.
......@@ -148,7 +148,7 @@ func (tg *TreeGen) Commit(tree string) (_ zodb.Tid, err error) {
// XGetTree loads LOBtree from zurl@at->obj<root>.
// Tree values must be ZBlk whose data is returned instead of references to ZBlk.
func XGetTree(db *zodb.DB, at zodb.Tid, root zodb.Oid) map[int64]string {
func XGetTree(db *zodb.DB, at zodb.Tid, root zodb.Oid) map[Key]string {
defer exc.Contextf("%s: @%s: get tree %s", db.Storage().URL(), at, root)
X := exc.Raiseif
......@@ -158,16 +158,16 @@ func XGetTree(db *zodb.DB, at zodb.Tid, root zodb.Oid) map[int64]string {
zconn, err := db.Open(ctx, &zodb.ConnOptions{At: at}); X(err)
xztree, err := zconn.Get(ctx, root); X(err)
ztree, ok := xztree.(*btree.LOBTree)
ztree, ok := xztree.(*Tree)
if !ok {
exc.Raisef("expected LOBTree, got %s", zodb.ClassOf(xztree))
exc.Raisef("expected %s, got %s", typeOf(ztree), typeOf(xztree))
}
err = ztree.PActivate(ctx); X(err)
defer ztree.PDeactivate()
zbucket := ztree.FirstBucket()
kv := make(map[int64]string)
kv := make(map[Key]string)
for zbucket != nil {
err = zbucket.PActivate(ctx); X(err)
defer zbucket.PDeactivate()
......@@ -190,13 +190,59 @@ func XGetTree(db *zodb.DB, at zodb.Tid, root zodb.Oid) map[int64]string {
return kv
}
// verifyΔBTail verifies how ΔBTail handles ZODB update for a tree with changes in between at1->at2.
//
// it is known that @at1 and @at2 the tree has kv1 and kv2 values correspondingly.
// it is known that for at1->at2 ZODB-level change is δZ.
func verifyΔBTail(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, at1, at2 zodb.Tid, kv1, kv2 map[Key]string, δZ *zodb.EventCommit) {
// verify transition at1->at2 for all initial states of tracked {keys} from kv1
keyv1 := []Key{}
for k1 := range kv1 {
keyv1 = append(keyv1, k1)
}
sort.Slice(keyv1, func(i, j int) bool {
return keyv1[i] < keyv1[j]
})
for kidx := range IntSets(len(keyv1)) {
keys := make([]Key, len(kidx))
for _, i := range kidx {
keys[i] = keyv1[i]
}
verifyΔBTail1(t, db, treeRoot, at1,at2, kv1,kv2, δZ, keys)
}
}
// verifyΔBTail1 verifies how ΔBTail handles ZODB update at1->at2 from initial
// tracked state defined by initialTrackedKeys.
func verifyΔBTail1(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, at1,at2 zodb.Tid, kv1,kv2 map[Key]string, δZ *zodb.EventCommit, initialTrackedKeys []Key) {
X := exc.Raiseif
txn, ctx := transaction.New(context.Background())
defer txn.Abort()
zconn, err := db.Open(ctx, &zodb.ConnOptions{At: at1}); X(err)
δbtail := NewΔBtail(zconn.At())
xtree, err := zconn.Get(ctx, treeRoot); X(err)
ztree := xtree.(*Tree)
for _, k := range initialTrackedKeys {
treePath := []Node{}
_, _, err = ztree.VGet(ctx, k, func(node Node) {
treePath = append(treePath, node)
}); X(err)
}
}
func TestΔBTail(t *testing.T) {
X := exc.Raiseif
// XXX test known cases tree1 -> tree2
testv := []struct { tree1, tree2 string } {
{"T/B:", "T/B:"},
{"T/B:", "T/B1:a"},
// test known cases going through tree1 -> tree2 -> ...
testv := []string {
"T/B:",
"T/B1:a",
// XXX
}
......@@ -248,12 +294,48 @@ func TestΔBTail(t *testing.T) {
fmt.Println(kv2)
}
for _, test := range testv {
XXX(test.tree1, test.tree2)
XXX(test.tree2, test.tree1)
// direct tree_i -> tree_{i+1}
at1 := tg.head
kv1 := XGetTree(db, at1, tg.treeRoot)
for _, tree := range testv {
at2, err := tg.Commit(tree); X(err) // tree2
kv2 := XGetTree(db, at2, tg.treeRoot)
var δZ *zodb.EventCommit // XXX
verifyΔBTail(t, db, tg.treeRoot, at1,at2, kv1,kv2, δZ)
at1 = at2
kv1 = kv2
}
// TODO reverse tree_i <- tree_{i+1}
}
func TestΔBTreeAllStructs(t *testing.T) {
// XXX given (kv1, kv2) test on automatically generated (tree1 -> tree2)
}
// IntSets generates all sets of integers in range [0,N)
func IntSets(N int) chan []int {
ch := make(chan []int)
go intSets(ch, 0, N)
return ch
}
// intSets generates all sets of integers in range [lo,hi)
func intSets(ch chan []int, lo, hi int) {
ch <- []int{} // ø
if lo < hi-1 {
chTail := make(chan []int)
go intSets(chTail, lo+1, hi)
for tail := range chTail {
ch <- append([]int{lo}, tail...) // lo + tail
}
}
close(ch)
}
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