You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
learn_mqtt_go/clock/clock_test.go

212 lines
4.8 KiB
Go

package clock
import (
"math"
"reflect"
"testing"
)
func assertClocksEqual[T Uint](t testing.TB, got, want []T) {
t.Helper()
if !reflect.DeepEqual(got, want) {
t.Errorf("Error: got %v want %v", got, want)
}
}
func TestVectorClock(t *testing.T) {
t.Run("test cases for uint32 type", func(t *testing.T) {
testCases := []struct {
a []uint32
b []uint32
expected []uint32
}{
{[]uint32{0, 0}, []uint32{0, 0}, []uint32{0, 0}},
{[]uint32{2, 0}, []uint32{0, 2}, []uint32{2, 2}},
{[]uint32{4, 11}, []uint32{3, 10}, []uint32{4, 11}},
{[]uint32{5, 9}, []uint32{8, 12}, []uint32{8, 12}},
{[]uint32{1, 1}, []uint32{1, 1}, []uint32{1, 1}},
{[]uint32{math.MaxUint32, 1}, []uint32{2, 1}, []uint32{4294967295, 1}},
}
for _, tc := range testCases {
vc := VectorClock[uint32]{clock: tc.a}
clock, err := vc.Sync(VectorClock[uint32]{clock: tc.b})
if err != nil {
t.Errorf("Sync should not have errored")
}
assertClocksEqual(t, clock, tc.expected)
}
})
t.Run("test cases for uint64 type", func(t *testing.T) {
testCases := []struct {
a []uint64
b []uint64
expected []uint64
}{
{[]uint64{0, 0}, []uint64{0, 0}, []uint64{0, 0}},
{[]uint64{2, 0}, []uint64{0, 2}, []uint64{2, 2}},
{[]uint64{4, 11}, []uint64{3, 10}, []uint64{4, 11}},
{[]uint64{5, 9}, []uint64{8, 12}, []uint64{8, 12}},
{[]uint64{1, 1}, []uint64{1, 1}, []uint64{1, 1}},
{[]uint64{math.MaxUint64, 1}, []uint64{2, 1}, []uint64{18446744073709551615, 1}},
}
for _, tc := range testCases {
vc := VectorClock[uint64]{clock: tc.a}
clock, err := vc.Sync(VectorClock[uint64]{clock: tc.b})
if err != nil {
t.Errorf("Sync should not have errored")
}
assertClocksEqual(t, clock, tc.expected)
}
})
t.Run("test empty new", func(t *testing.T) {
got := NewVectorClock[uint32](2)
want := VectorClock[uint32]{clock: []uint32{0, 0}}
assertClocksEqual(t, got.GetClock(), want.GetClock())
})
t.Run("test new vc for uint32", func(t *testing.T) {
vc := VectorClock[uint32]{clock: []uint32{4, 11}}
clock, err := vc.Increment(0)
if err != nil {
t.Errorf("Increment should not have errored")
}
assertClocksEqual(t, clock, []uint32{5, 11})
clock, err = vc.Increment(1)
if err != nil {
t.Errorf("Increment should not have errored")
}
assertClocksEqual(t, clock, []uint32{5, 12})
})
t.Run("test overflow condition", func(t *testing.T) {
vc := VectorClock[uint32]{clock: []uint32{math.MaxUint32, 11}}
clock, err := vc.Increment(0)
if err != nil {
t.Errorf("Increment should not have errored")
}
assertClocksEqual(t, clock, []uint32{0, 11})
})
t.Run("test index cannot be incremented", func(t *testing.T) {
vc := VectorClock[uint64]{}
clock, err := vc.Increment(0)
if clock != nil {
t.Errorf("Clock should be nil")
}
if err == nil {
t.Errorf("There should have been an error")
}
})
}
func TestNewVectorClock(t *testing.T) {
t.Run("test new vc for uint32", func(t *testing.T) {
got := NewVectorClock[uint32](2)
want := VectorClock[uint32]{clock: []uint32{0, 0}}
assertClocksEqual(t, got.GetClock(), want.GetClock())
})
t.Run("test new vc for uint64", func(t *testing.T) {
got := NewVectorClock[uint64](2)
want := VectorClock[uint64]{clock: []uint64{0, 0}}
assertClocksEqual(t, got.GetClock(), want.GetClock())
})
}
func TestArrayToVectorClock(t *testing.T) {
t.Run("from empty slice", func(t *testing.T) {
got := ArrayToVectorClock([]uint32{})
want := VectorClock[uint32]{
clock: []uint32{},
}
if len(got.GetClock()) != 0 {
t.Errorf("Expected VectorClock.clock to be of length zero.")
}
if !reflect.DeepEqual(got.GetClock(), want.GetClock()) {
t.Errorf("Error: got %v want %v", got.GetClock(), want.GetClock())
}
})
t.Run("from zero slice", func(t *testing.T) {
got := ArrayToVectorClock(make([]uint64, 6))
want := VectorClock[uint64]{
clock: []uint64{0, 0, 0, 0, 0, 0},
}
assertClocksEqual(t, got.GetClock(), want.GetClock())
})
t.Run("from start clock", func(t *testing.T) {
want := NewVectorClock[uint64](3)
got := ArrayToVectorClock(want.GetClock())
assertClocksEqual(t, got.GetClock(), want.GetClock())
})
t.Run("from a populated clock", func(t *testing.T) {
want := VectorClock[uint32]{
clock: []uint32{2, 3},
}
got := ArrayToVectorClock(want.GetClock())
assertClocksEqual(t, got.GetClock(), want.GetClock())
})
t.Run("from a slice that is then modified", func(t *testing.T) {
initial_a := []uint64{1, 2, 3, 4}
got := ArrayToVectorClock(initial_a)
want := make([]uint64, len(initial_a))
copy(want, initial_a)
initial_a[0] = 12
initial_a[2] = 4
assertClocksEqual(t, got.GetClock(), want)
if reflect.DeepEqual(initial_a, got.GetClock()) {
t.Errorf("Initial array %v should not be equal to clock %v", initial_a, got.GetClock())
}
})
}