blob: 30366116fab6d6bd4c5aef8937e2ce8acc4b6832 [file] [log] [blame]
Himabindu Pucha2752a7e2015-06-12 14:07:07 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package vsync
6
7import (
8 "reflect"
Himabindu Puchab41fc142015-09-10 17:10:57 -07009 "strconv"
Himabindu Pucha2752a7e2015-06-12 14:07:07 -070010 "testing"
11 "time"
12
Raja Daoudd4543072015-06-30 11:15:55 -070013 _ "v.io/x/ref/runtime/factories/generic"
Adam Sadovskyf2efeb52015-08-31 14:17:49 -070014 "v.io/x/ref/services/syncbase/server/interfaces"
15 "v.io/x/ref/services/syncbase/store"
Himabindu Pucha2752a7e2015-06-12 14:07:07 -070016)
17
18// Tests for sync state management and storage in Syncbase.
19
20// TestReserveGenAndPos tests reserving generation numbers and log positions in a
21// Database log.
22func TestReserveGenAndPos(t *testing.T) {
23 svc := createService(t)
Himabindu Pucha03ef3932015-06-26 17:56:09 -070024 defer destroyService(t, svc)
Himabindu Pucha2752a7e2015-06-12 14:07:07 -070025 s := svc.sync
26
Himabindu Puchab41fc142015-09-10 17:10:57 -070027 sgids := []string{"", "100", "200"}
28 for _, sgid := range sgids {
29 var wantGen, wantPos uint64 = 1, 0
30 for i := 0; i < 5; i++ {
31 gotGen, gotPos := s.reserveGenAndPosInternal("mockapp", "mockdb", sgid, 5, 10)
32 if gotGen != wantGen || gotPos != wantPos {
33 t.Fatalf("reserveGenAndPosInternal failed, gotGen %v wantGen %v, gotPos %v wantPos %v", gotGen, wantGen, gotPos, wantPos)
34 }
35 wantGen += 5
36 wantPos += 10
Himabindu Pucha2752a7e2015-06-12 14:07:07 -070037
Himabindu Puchab41fc142015-09-10 17:10:57 -070038 name := appDbName("mockapp", "mockdb")
39 var info *localGenInfoInMem
40 if sgid == "" {
41 info = s.syncState[name].data
42 } else {
43 id, err := strconv.ParseUint(sgid, 10, 64)
44 if err != nil {
45 t.Fatalf("reserveGenAndPosInternal failed, invalid sgid %v", sgid)
46 }
47 info = s.syncState[name].sgs[interfaces.GroupId(id)]
48 }
49 if info.gen != wantGen || info.pos != wantPos {
50 t.Fatalf("reserveGenAndPosInternal failed, gotGen %v wantGen %v, gotPos %v wantPos %v", info.gen, wantGen, info.pos, wantPos)
51 }
Himabindu Pucha2752a7e2015-06-12 14:07:07 -070052 }
53 }
54}
55
56// TestPutGetDbSyncState tests setting and getting sync metadata.
57func TestPutGetDbSyncState(t *testing.T) {
58 svc := createService(t)
Himabindu Pucha03ef3932015-06-26 17:56:09 -070059 defer destroyService(t, svc)
Himabindu Pucha2752a7e2015-06-12 14:07:07 -070060 st := svc.St()
61
62 checkDbSyncState(t, st, false, nil)
63
64 gv := interfaces.GenVector{
65 "mocktbl/foo": interfaces.PrefixGenVector{
66 1: 2, 3: 4, 5: 6,
67 },
68 }
Himabindu Puchab41fc142015-09-10 17:10:57 -070069 sggv := interfaces.GenVector{
70 "mocksg1": interfaces.PrefixGenVector{
71 10: 20, 30: 40, 50: 60,
72 },
73 "mocksg2": interfaces.PrefixGenVector{
74 100: 200, 300: 400, 500: 600,
75 },
76 }
77 localsgs := make(map[interfaces.GroupId]localGenInfo)
78 localsgs[interfaces.GroupId(8888)] = localGenInfo{Gen: 56, CheckptGen: 2000}
79 localsgs[interfaces.GroupId(1008888)] = localGenInfo{Gen: 25890, CheckptGen: 100}
Himabindu Pucha2752a7e2015-06-12 14:07:07 -070080
81 tx := st.NewTransaction()
Himabindu Puchab41fc142015-09-10 17:10:57 -070082 wantSt := &dbSyncState{
83 Data: localGenInfo{Gen: 40},
84 Sgs: localsgs,
85 GenVec: gv,
86 SgGenVec: sggv,
87 }
Himabindu Pucha2752a7e2015-06-12 14:07:07 -070088 if err := putDbSyncState(nil, tx, wantSt); err != nil {
89 t.Fatalf("putDbSyncState failed, err %v", err)
90 }
91 if err := tx.Commit(); err != nil {
92 t.Fatalf("cannot commit putting db sync state, err %v", err)
93 }
94
95 checkDbSyncState(t, st, true, wantSt)
96}
97
98// TestPutGetDelLogRec tests setting, getting, and deleting a log record.
99func TestPutGetDelLogRec(t *testing.T) {
100 svc := createService(t)
Himabindu Pucha03ef3932015-06-26 17:56:09 -0700101 defer destroyService(t, svc)
Himabindu Pucha2752a7e2015-06-12 14:07:07 -0700102 st := svc.St()
103
104 var id uint64 = 10
105 var gen uint64 = 100
106
107 checkLogRec(t, st, id, gen, false, nil)
108
109 tx := st.NewTransaction()
110 wantRec := &localLogRec{
111 Metadata: interfaces.LogRecMetadata{
112 Id: id,
113 Gen: gen,
114 RecType: interfaces.NodeRec,
115 ObjId: "foo",
116 CurVers: "3",
117 Parents: []string{"1", "2"},
Himabindu Pucha53497022015-06-19 11:57:13 -0700118 UpdTime: time.Now().UTC(),
Himabindu Pucha2752a7e2015-06-12 14:07:07 -0700119 Delete: false,
120 BatchId: 10000,
121 BatchCount: 1,
122 },
123 Pos: 10,
124 }
Himabindu Puchab41fc142015-09-10 17:10:57 -0700125 if err := putLogRec(nil, tx, logDataPrefix, wantRec); err != nil {
126 t.Fatalf("putLogRec(%s:%d:%d) failed err %v", logDataPrefix, id, gen, err)
Himabindu Pucha2752a7e2015-06-12 14:07:07 -0700127 }
128 if err := tx.Commit(); err != nil {
129 t.Fatalf("cannot commit putting log rec, err %v", err)
130 }
131
132 checkLogRec(t, st, id, gen, true, wantRec)
133
134 tx = st.NewTransaction()
Himabindu Puchab41fc142015-09-10 17:10:57 -0700135 if err := delLogRec(nil, tx, logDataPrefix, id, gen); err != nil {
136 t.Fatalf("delLogRec(%s:%d:%d) failed err %v", logDataPrefix, id, gen, err)
Himabindu Pucha2752a7e2015-06-12 14:07:07 -0700137 }
138 if err := tx.Commit(); err != nil {
139 t.Fatalf("cannot commit deleting log rec, err %v", err)
140 }
141
142 checkLogRec(t, st, id, gen, false, nil)
143}
144
Himabindu Pucha0ff9b0c2015-07-14 11:40:45 -0700145func TestLogRecKeyUtils(t *testing.T) {
Himabindu Puchab41fc142015-09-10 17:10:57 -0700146 invalid := []string{"$sync:100:bb", "log:100:bb", "$sync:log:data:100:xx", "$sync:log:data:aa:bb", "$sync:log:xx:100:bb"}
Himabindu Pucha0ff9b0c2015-07-14 11:40:45 -0700147
148 for _, k := range invalid {
Himabindu Puchab41fc142015-09-10 17:10:57 -0700149 if _, _, _, err := splitLogRecKey(nil, k); err == nil {
Himabindu Pucha0ff9b0c2015-07-14 11:40:45 -0700150 t.Fatalf("splitting log rec key didn't fail %q", k)
151 }
152 }
153
154 valid := []struct {
Himabindu Puchab41fc142015-09-10 17:10:57 -0700155 pfx string
Himabindu Pucha0ff9b0c2015-07-14 11:40:45 -0700156 id uint64
157 gen uint64
158 }{
Himabindu Puchab41fc142015-09-10 17:10:57 -0700159 {logDataPrefix, 10, 20},
160 {"2500", 190, 540},
161 {"4200", 9999, 999999},
Himabindu Pucha0ff9b0c2015-07-14 11:40:45 -0700162 }
163
164 for _, v := range valid {
Himabindu Puchab41fc142015-09-10 17:10:57 -0700165 gotPfx, gotId, gotGen, err := splitLogRecKey(nil, logRecKey(v.pfx, v.id, v.gen))
166 if gotPfx != v.pfx || gotId != v.id || gotGen != v.gen || err != nil {
167 t.Fatalf("failed key conversion pfx got %v want %v, id got %v want %v, gen got %v want %v, err %v", gotPfx, v.pfx, gotId, v.id, gotGen, v.gen, err)
Himabindu Pucha0ff9b0c2015-07-14 11:40:45 -0700168 }
169 }
170}
171
Himabindu Pucha2752a7e2015-06-12 14:07:07 -0700172//////////////////////////////
173// Helpers
174
Adam Sadovsky6a6214f2015-09-03 18:20:18 -0700175// TODO(hpucha): Look into using v.io/x/ref/services/syncbase/testutil.Fatalf()
Himabindu Pucha53497022015-06-19 11:57:13 -0700176// for getting the stack trace. Right now cannot import the package due to a
177// cycle.
178
Himabindu Pucha2752a7e2015-06-12 14:07:07 -0700179func checkDbSyncState(t *testing.T, st store.StoreReader, exists bool, wantSt *dbSyncState) {
180 gotSt, err := getDbSyncState(nil, st)
181
182 if (!exists && err == nil) || (exists && err != nil) {
183 t.Fatalf("getDbSyncState failed, exists %v err %v", exists, err)
184 }
185
186 if !reflect.DeepEqual(gotSt, wantSt) {
187 t.Fatalf("getDbSyncState() failed, got %v, want %v", gotSt, wantSt)
188 }
189}
190
191func checkLogRec(t *testing.T, st store.StoreReader, id, gen uint64, exists bool, wantRec *localLogRec) {
Himabindu Puchab41fc142015-09-10 17:10:57 -0700192 gotRec, err := getLogRec(nil, st, logDataPrefix, id, gen)
Himabindu Pucha2752a7e2015-06-12 14:07:07 -0700193
194 if (!exists && err == nil) || (exists && err != nil) {
195 t.Fatalf("getLogRec(%d:%d) failed, exists %v err %v", id, gen, exists, err)
196 }
197
198 if !reflect.DeepEqual(gotRec, wantRec) {
199 t.Fatalf("getLogRec(%d:%d) failed, got %v, want %v", id, gen, gotRec, wantRec)
200 }
201
Himabindu Puchab41fc142015-09-10 17:10:57 -0700202 if ok, err := hasLogRec(st, logDataPrefix, id, gen); err != nil || ok != exists {
Himabindu Pucha2752a7e2015-06-12 14:07:07 -0700203 t.Fatalf("hasLogRec(%d:%d) failed, want %v", id, gen, exists)
204 }
Himabindu Pucha53497022015-06-19 11:57:13 -0700205}