diff options
Diffstat (limited to 'back/qver/version_test.go')
| -rw-r--r-- | back/qver/version_test.go | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/back/qver/version_test.go b/back/qver/version_test.go new file mode 100644 index 0000000..4bc9eff --- /dev/null +++ b/back/qver/version_test.go @@ -0,0 +1,206 @@ +package qver_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "git.samanthony.xyz/buth/back/qver" +) + +// Bump() should increment the version. +func TestBump(t *testing.T) { + t.Parallel() + + ver := qver.New() + defer ver.Close() + var i uint32 + for i = 0; i < 5; i++ { + requireVer(t, i, ver) + ver.Bump() + } +} + +// Bumping the child version should bump the parent version too. +func TestBumpChild(t *testing.T) { + t.Parallel() + + parent := qver.New() + child := qver.New(qver.Parent(parent)) + defer parent.Close() + defer child.Close() + + var i uint32 + for i = 0; i < 5; i++ { + requireVer(t, i, child) + requireVer(t, i, parent) + child.Bump() + } +} + +// Bumping the parent version should not affect the child. +func TestBumpParent(t *testing.T) { + t.Parallel() + + parent := qver.New() + child := qver.New(qver.Parent(parent)) + defer parent.Close() + defer child.Close() + + requireVer(t, 0, parent) + requireVer(t, 0, child) + + for i := 0; i < 5; i++ { + parent.Bump() + } + requireVer(t, 5, parent) + requireVer(t, 0, child) +} + +// Bumps should propagate up the chain from parent to child. +func TestBumpChain(t *testing.T) { + t.Parallel() + + a := qver.New() + b := qver.New(qver.Parent(a)) + c := qver.New(qver.Parent(b)) + defer a.Close() + defer b.Close() + defer c.Close() + + var i uint32 + for i = 0; i < 5; i++ { + requireVer(t, i, a) + requireVer(t, i, b) + requireVer(t, i, c) + c.Bump() + } +} + +// Parent can have several children. +func TestMultiChild(t *testing.T) { + t.Parallel() + + root := qver.New() + a, b := qver.New(qver.Parent(root)), qver.New(qver.Parent(root)) + defer root.Close() + defer a.Close() + defer b.Close() + + var i uint32 + for i = 0; i < 3; i++ { + requireVer(t, i, root) + a.Bump() + } + + for i = 0; i < 3; i++ { + requireVer(t, i+3, root) + b.Bump() + } + + root.Bump() + requireVer(t, 3+3+1, root) +} + +func TestUpdate(t *testing.T) { + t.Parallel() + + state, update := newUpdateFunc() + ver := qver.New(qver.Update(state, update)) + defer ver.Close() + + requireVer(t, 0, ver) + state <- true + requireVer(t, 1, ver) + requireVer(t, 1, ver) + state <- false + requireVer(t, 1, ver) + state <- true + requireVer(t, 2, ver) +} + +// Updating the child should bump the parent's version. +func TestUpdateChild(t *testing.T) { + t.Parallel() + + parent := qver.New() + defer parent.Close() + + state, update := newUpdateFunc() + child := qver.New(qver.Parent(parent), qver.Update(state, update)) + defer close(state) + defer child.Close() + + requireVer(t, 0, parent) + requireVer(t, 0, child) + state <- true // update child + requireVer(t, 1, parent) + requireVer(t, 1, child) +} + +// Updating the parent should not affect the child. +func TestUpdateParent(t *testing.T) { + t.Parallel() + + state, update := newUpdateFunc() + parent := qver.New(qver.Update(state, update)) + child := qver.New(qver.Parent(parent)) + defer close(state) + defer parent.Close() + defer child.Close() + + requireVer(t, 0, parent) + requireVer(t, 0, child) + state <- true // update parent + requireVer(t, 1, parent) + requireVer(t, 0, child) +} + +// Parent should keep working after child is closed. +func TestCloseChild(t *testing.T) { + t.Parallel() + + a := qver.New() + requireVer(t, 0, a) + a.Bump() + requireVer(t, 1, a) + + b := qver.New(qver.Parent(a)) + b.Bump() + requireVer(t, 2, a) + b.Close() + requireVer(t, 2, a) + a.Bump() + requireVer(t, 3, a) + + a.Close() +} + +// Update when state buffer contains 'true'. +func newUpdateFunc() (state chan bool, f qver.UpdateFunc) { + return make(chan bool, 1), func(v uint32, state interface{}) (uint32, interface{}, error) { + s := state.(chan bool) + select { + case inc := <-s: + if inc { + v++ + } + default: + } + return v, s, nil + } +} + +func requireVer(t *testing.T, want uint32, v *qver.Version) { + t.Helper() + got, err := v.Get() + require.NoError(t, err) + require.Equal(t, want, got) +} + +func requireAllVer(t *testing.T, want uint32, vs ...*qver.Version) { + t.Helper() + for _, v := range vs { + requireVer(t, want, v) + } +} |