package kvstore import ( "fmt" "math/rand" "os" "reflect" "testing" "time" ) // ---------------------------------------------------------------------------- func (kv *KV) waitForSeqNum(x uint64) { for { seqNum := kv.MaxSeqNum() if seqNum >= x { return } time.Sleep(100 * time.Millisecond) } } func (kv *KV) dump(collection string) map[uint64]string { m := map[uint64]string{} kv.Iterate(collection, func(id uint64, data []byte) { m[id] = string(data) }) return m } func (kv *KV) equals(collection string, expected map[uint64]string) error { m := kv.dump(collection) if len(m) != len(expected) { return fmt.Errorf("Expected %d values but found %d", len(expected), len(m)) } for key, exp := range expected { val, ok := m[key] if !ok { return fmt.Errorf("Value for %d not found.", key) } if val != exp { return fmt.Errorf("%d: Expected %s but found %s.", key, exp, val) } } return nil } func (kv *KV) equalsKV(collection string, rhs *KV) error { l1 := []record{} kv.replay(0, func(rec record) error { l1 = append(l1, rec) return nil }) idx := -1 err := rhs.replay(0, func(rec record) error { idx++ if !reflect.DeepEqual(rec, l1[idx]) { return fmt.Errorf("Records not equal: %d %v %v", idx, rec, l1[idx]) } return nil }) if err != nil { return err } return kv.equals(collection, rhs.dump(collection)) } // Collection one of ("a", "b", "c"). // ID one of [1,10] var ( randCollections = []string{"a", "b", "c"} randIDs = []uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} ) func (kv *KV) randAction() { c := randCollections[rand.Intn(len(randCollections))] id := randIDs[rand.Intn(len(randIDs))] // Mostly stores. if rand.Float64() < 0.9 { kv.Store(c, id, randBytes()) } else { kv.Delete(c, id) } } // ---------------------------------------------------------------------------- func TestKV(t *testing.T) { run := func(name string, inner func(t *testing.T, kv *KV)) { dir, _ := os.MkdirTemp("", "") defer os.RemoveAll(dir) kv := NewPrimary(dir) defer kv.Close() inner(t, kv) } run("simple", func(t *testing.T, kv *KV) { kv.Store("a", 1, _b("Hello")) kv.Store("a", 2, _b("World")) kv.waitForSeqNum(2) err := kv.equals("a", map[uint64]string{ 1: "Hello", 2: "World", }) if err != nil { t.Fatal(err) } }) }