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