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) } }