Commit f07502fc authored by Kirill Smelkov's avatar Kirill Smelkov

X xbtreetest: Teach T & Commit to automatically provide At in symbolic form

parent 6e619d3d
......@@ -22,6 +22,8 @@ package xbtreetest
import (
"context"
"fmt"
"sort"
"testing"
"lab.nexedi.com/kirr/go123/exc"
......@@ -44,15 +46,17 @@ type T struct {
zstor zodb.IStorage
DB *zodb.DB
// all committed trees
commitv []*Commit
commitv []*Commit // all committed trees
at0idx int // index of current "at₀" in commitv
}
// Commit represent test commit changing a tree.
type Commit struct {
T *T // created via T.CommitTree
idx int // lives in .T.commitv[idx]
Tree string // the tree in topology-encoding
Prev *Commit // previous commit
At zodb.Tid // commit revision
At zodb.Tid // committed revision
ΔZ *zodb.EventCommit // raw ZODB changes; δZ.tid == at
Xkv RBucketSet // full tree state as of @at
Δxkv map[Key]Δstring // full tree-diff against parent
......@@ -70,7 +74,7 @@ func NewT(t *testing.T) *T {
X := exc.Raiseif
t.Helper()
tt := &T{T: t}
tt := &T{T: t, at0idx: 1 /* at₀ starts from first CommitTree */}
var err error
work := t.TempDir()
......@@ -98,6 +102,8 @@ func NewT(t *testing.T) *T {
head := tt.treeSrv.head
t1 := &Commit{
T: tt,
idx: 0,
Tree: "T/B:", // treegen.py creates the tree as initially empty
Prev: nil,
At: head,
......@@ -130,6 +136,45 @@ func (t *T) Head() *Commit {
return t.commitv[len(t.commitv)-1]
}
// XGetCommit finds and returns Commit created with revision at.
func (t *T) XGetCommit(at zodb.Tid) *Commit {
l := len(t.commitv)
i := sort.Search(l, func(i int) bool {
return at <= t.commitv[i].At
})
var commit *Commit
if i < l {
commit = t.commitv[i]
if commit.At != at {
commit = nil
}
}
if commit == nil {
panicf("no commit corresponding to @%s", at)
}
if commit.idx != i {
panicf("BUG: commit.idx (%d) != i (%d)", commit.idx, i)
}
return commit
}
// AtSymb returns symbolic representation of at, for example "at3".
//
// at must correspond to a Commit.
func (t *T) AtSymb(at zodb.Tid) string {
return t.XGetCommit(at).AtSymb()
}
// AtSymb returns symbolic representation of c.At, for example "at3".
func (c *Commit) AtSymb() string {
return fmt.Sprintf("at%d", c.idx - c.T.at0idx)
}
// AtSymbReset shifts symbolic numbers and adjust AtSymb setup so that c.AtSymb() returns "at<i>".
func (t *T) AtSymbReset(c *Commit, i int) {
t.at0idx = c.idx - i
}
// CommitTree calls t.treeSrv.Commit and returns Commit corresponding to committed transaction.
// XXX naming -> Commit ?
func (t *T) CommitTree(tree string) *Commit {
......@@ -183,6 +228,7 @@ func (t *T) CommitTree(tree string) *Commit {
}
ttree := &Commit{
T: t,
Tree: tree,
At: δZ.Tid,
ΔZ: δZ,
......@@ -194,6 +240,7 @@ func (t *T) CommitTree(tree string) *Commit {
ttree.Prev = tprev
ttree.Δxkv = KVDiff(tprev.Xkv.Flatten(), ttree.Xkv.Flatten())
ttree.idx = len(t.commitv)
t.commitv = append(t.commitv, ttree)
return ttree
......@@ -252,23 +299,23 @@ func xGetBlkTab(db *zodb.DB, at zodb.Tid) map[zodb.Oid]ZBlkInfo {
return blkTab
}
// XGetBlkData loads blk data for ZBlk<oid> @t.at
// XGetBlkData loads blk data for ZBlk<oid> @c.at
//
// For speed the load is done via preloaded t.blkDataTab instead of access to the DB.
func (t *Commit) XGetBlkData(oid zodb.Oid) string {
// For speed the load is done via preloaded c.blkDataTab instead of access to the DB.
func (c *Commit) XGetBlkData(oid zodb.Oid) string {
if oid == VDEL {
return DEL
}
zblki, ok := t.ZBlkTab[oid]
zblki, ok := c.ZBlkTab[oid]
if !ok {
exc.Raisef("getBlkData ZBlk<%s> @%s: no such ZBlk", oid, t.At)
exc.Raisef("getBlkData ZBlk<%s> @%s: no such ZBlk", oid, c.At)
}
return zblki.Data
}
// XGetBlkByName returns ZBlk info associated with ZBlk<name>
func (t *Commit) XGetBlkByName(name string) (zodb.Oid, ZBlkInfo) {
for oid, zblki := range t.ZBlkTab {
func (c *Commit) XGetBlkByName(name string) (zodb.Oid, ZBlkInfo) {
for oid, zblki := range c.ZBlkTab {
if zblki.Name == name {
return oid, zblki
}
......
This diff is collapsed.
......@@ -184,8 +184,6 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
t := xbtreetest.NewT(t_)
X := exc.Raiseif
xat := map[zodb.Tid]string{} // tid -> "at<i>"
// data built via applying changes from testq
vδf := []*ΔFile{} // (rev↑, {}blk)
vδE := []_ΔFileEpoch{} // (rev↑, EPOCH)
......@@ -203,7 +201,6 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
// start δFtail when zfile does not yet exists
// this way we'll verify how ΔFtail rebuilds vδE for started-to-be-tracked file
t0 := t.CommitTree("øf")
xat[t0.At] = "at0"
t.Logf("# @at0 (%s)", t0.At)
epochv = append(epochv, t0.At)
δFtail := NewΔFtail(t.Head().At, t.DB)
......@@ -212,7 +209,6 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
// vδf + friends will be updated after "load zfile"
δt1 := map[int64]string{0:"a"}
t1 := t.CommitTree(fmt.Sprintf("t%s D%s", xbtreetest.KVTxt(δt1), dataTabTxt(dataTab)))
xat[t1.At] = "at1"
δblk1 := setI64{}
for blk := range δt1 {
δblk1.Add(blk)
......@@ -276,9 +272,9 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
retrack()
// δfstr/vδfstr converts δf/vδf to string taking xat into account
// δfstr/vδfstr converts δf/vδf to string taking symbolic at into account
δfstr := func(δf *ΔFile) string {
s := fmt.Sprintf("@%s·%s", xat[δf.Rev], δf.Blocks)
s := fmt.Sprintf("@%s·%s", t.AtSymb(δf.Rev), δf.Blocks)
if δf.Epoch {
s += "E"
}
......@@ -379,12 +375,11 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
if newEpoch {
epochv = append(epochv, commit.At)
}
xat[commit.At] = fmt.Sprintf("at%d", i)
flags := ""
if newEpoch {
flags += "\tEPOCH"
}
t.Logf("# → @%s (%s) δT%s δD%s\t; %s\tδ%s%s", xat[commit.At], commit.At, xbtreetest.KVTxt(test.δblkTab), test.δdataTab, commit.Tree, δblk, flags)
t.Logf("# → @%s (%s) δT%s δD%s\t; %s\tδ%s%s", commit.AtSymb(), commit.At, xbtreetest.KVTxt(test.δblkTab), test.δdataTab, commit.Tree, δblk, flags)
//t.Logf("# vδf: %s", vδfstr(vδf))
......@@ -406,7 +401,7 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
}
blkRevAt[commit.At] = blkRev
/*
fmt.Printf("blkRevAt[@%s]:\n", xat[commit.At])
fmt.Printf("blkRevAt[@%s]:\n", commit.AtSymb())
blkv := []int64{}
for blk := range blkRev {
blkv = append(blkv, blk)
......@@ -515,7 +510,7 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
const ncut = 5
if len(vδf) >= ncut {
revcut := vδf[0].Rev
t.Logf("# forget ≤ @%s", xat[revcut])
t.Logf("# forget ≤ @%s", t.AtSymb(revcut))
δFtail.ForgetPast(revcut)
vδf = vδf[1:]
//t.Logf("# vδf: %s", vδfstr(vδf))
......@@ -559,7 +554,7 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
vδf_ok := vδf[j:k+1] // [j,k]
vδf_ := δFtail.SliceByFileRev(zfile, lo, hi)
if !reflect.DeepEqual(vδf_, vδf_ok) {
t.Errorf("slice (@%s,@%s]:\nhave: %v\nwant: %v", xat[lo], xat[hi], vδfstr(vδf_), vδfstr(vδf_ok))
t.Errorf("slice (@%s,@%s]:\nhave: %v\nwant: %v", t.AtSymb(lo), t.AtSymb(hi), vδfstr(vδf_), vδfstr(vδf_ok))
}
}
}
......@@ -597,7 +592,7 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
revOK, exactOK = δFtail.Tail(), false
}
if !(rev == revOK && exact == exactOK) {
t.Errorf("blkrev #%d @%s:\nhave: @%s, %v\nwant: @%s, %v", blk, xat[at], xat[rev], exact, xat[revOK], exactOK)
t.Errorf("blkrev #%d @%s:\nhave: @%s, %v\nwant: @%s, %v", blk, t.AtSymb(at), t.AtSymb(rev), exact, t.AtSymb(revOK), exactOK)
}
}
......@@ -619,31 +614,25 @@ func TestΔFtailSliceUntrackedUniform(t_ *testing.T) {
t := xbtreetest.NewT(t_)
X := exc.Raiseif
xat := map[zodb.Tid]string{}
at0 := t.Head().At
xat[at0] = "at0"
δFtail := NewΔFtail(at0, t.DB)
// commit t1. all 0, 1 and 2 are in the same bucket.
t1 := t.CommitTree("T/B0:a,1:b,2:c")
xat[t1.At] = "at1"
δF, err := δFtail.Update(t1.ΔZ); X(err)
// XXX assert δF == ø
_ = δF
t2 := t.CommitTree("t0:d,1:e,2:c Da:a,b:b,c:c2,d:d,e:e") // 0:-a+d 1:-b+e δc₂
xat[t2.At] = "at2"
δF, err = δFtail.Update(t2.ΔZ); X(err)
// XXX assert δF
t3 := t.CommitTree("t0:d,1:e,2:c Da:a,b:b,c:c3,d:d3,e:e3") // δc₃ δd₃ δe₃
xat[t3.At] = "at3"
δF, err = δFtail.Update(t3.ΔZ); X(err)
// XXX assert δF
t4 := t.CommitTree("t0:d,1:e,2:c Da:a,b:b,c:c4,d:d3,e:e4") // δc₄ δe₄
xat[t4.At] = "at4"
δF, err = δFtail.Update(t4.ΔZ); X(err)
// XXX assert δF
......@@ -675,10 +664,10 @@ func TestΔFtailSliceUntrackedUniform(t_ *testing.T) {
δFtail.Track(zfile, blk, path, zblk)
}
// δfstr/vδfstr converts δf/vδf to string taking xat into account
// δfstr/vδfstr converts δf/vδf to string taking symbolic at into account
// XXX dup
δfstr := func(δf *ΔFile) string {
s := fmt.Sprintf("@%s·%s", xat[δf.Rev], δf.Blocks)
s := fmt.Sprintf("@%s·%s", t.AtSymb(δf.Rev), δf.Blocks)
if δf.Epoch {
s += "E"
}
......@@ -710,7 +699,7 @@ func TestΔFtailSliceUntrackedUniform(t_ *testing.T) {
&ΔFile{Rev: t4.At, Blocks: b( 1), Size: false},
}
if !reflect.DeepEqual(vδf, vδf_ok) {
t.Errorf("slice (@%s,@%s]:\nhave: %v\nwant: %v", xat[lo], xat[hi], vδfstr(vδf), vδfstr(vδf_ok))
t.Errorf("slice (@%s,@%s]:\nhave: %v\nwant: %v", t.AtSymb(lo), t.AtSymb(hi), vδfstr(vδf), vδfstr(vδf_ok))
}
......@@ -721,7 +710,7 @@ func TestΔFtailSliceUntrackedUniform(t_ *testing.T) {
&ΔFile{Rev: t3.At, Blocks: b(0), Size: false},
}
if !reflect.DeepEqual(vδf, vδf_ok) {
t.Errorf("slice (@%s,@%s]:\nhave: %v\nwant: %v", xat[lo], xat[hi], vδfstr(vδf), vδfstr(vδf_ok))
t.Errorf("slice (@%s,@%s]:\nhave: %v\nwant: %v", t.AtSymb(lo), t.AtSymb(hi), vδfstr(vδf), vδfstr(vδf_ok))
}
// (at3, at4] -> changes to only 0, ----/----
......@@ -729,7 +718,7 @@ func TestΔFtailSliceUntrackedUniform(t_ *testing.T) {
vδf = δFtail.SliceByFileRev(zfile, lo, hi)
vδf_ok = []*ΔFile(nil)
if !reflect.DeepEqual(vδf, vδf_ok) {
t.Errorf("slice (@%s,@%s]:\nhave: %v\nwant: %v", xat[lo], xat[hi], vδfstr(vδf), vδfstr(vδf_ok))
t.Errorf("slice (@%s,@%s]:\nhave: %v\nwant: %v", t.AtSymb(lo), t.AtSymb(hi), vδfstr(vδf), vδfstr(vδf_ok))
}
}
......
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