Skip to content

Commit 81a8635

Browse files
committed
Add index replay test for OplogRestore.Apply
1 parent 88eec87 commit 81a8635

File tree

3 files changed

+364
-3
lines changed

3 files changed

+364
-3
lines changed

pbm/oplog/restore_test.go

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ func (d *mdbTestClient) applyOps(entries []interface{}) error {
6060
"op": oe.Operation,
6161
"ns": oe.Namespace,
6262
}
63+
if oe.Operation == "c" && oe.Object != nil && len(oe.Object) > 0 {
64+
invParams["cmd"] = oe.Object[0].Key
65+
invParams["coll"] = oe.Object[0].Value.(string)
66+
}
6367
d.applyOpsInv = append(d.applyOpsInv, invParams)
6468

6569
return nil
@@ -139,14 +143,114 @@ func TestIsOpForCloning(t *testing.T) {
139143
}
140144

141145
func TestApply(t *testing.T) {
142-
t.Run("oplog restore", func(t *testing.T) {
143-
//todo:
146+
t.Run("collection restore", func(t *testing.T) {
147+
testCases := []struct {
148+
desc string
149+
oplogFile string
150+
resOps []string
151+
resNS []string
152+
resCmd []string
153+
resColl []string
154+
}{
155+
{
156+
desc: "collection: create-drop-create",
157+
oplogFile: "ops_cmd_create_drop",
158+
resOps: []string{"c", "c", "c", "c", "c"},
159+
resNS: []string{"mydb.$cmd", "mydb.$cmd", "mydb.$cmd", "mydb.$cmd", "mydb.$cmd"},
160+
resCmd: []string{"drop", "create", "drop", "drop", "create"},
161+
resColl: []string{"c1", "c1", "c1", "c2", "c2"},
162+
},
163+
//todo: add more cases
164+
}
165+
for _, tC := range testCases {
166+
t.Run(tC.desc, func(t *testing.T) {
167+
db := newMDBTestClient()
168+
oRestore := newOplogRestoreTest(db)
169+
170+
fr := useTestFile(t, tC.oplogFile)
171+
172+
_, err := oRestore.Apply(fr)
173+
if err != nil {
174+
t.Fatalf("error while applying oplog: %v", err)
175+
}
176+
177+
if len(tC.resOps) != len(db.applyOpsInv) {
178+
t.Errorf("wrong number of applyOps invocation, want=%d, got=%d", len(tC.resOps), len(db.applyOpsInv))
179+
}
180+
for i, wantOp := range tC.resOps {
181+
gotOp := db.applyOpsInv[i]["op"]
182+
if wantOp != gotOp {
183+
t.Errorf("wrong #%d. operation: want=%s, got=%s", i, wantOp, gotOp)
184+
}
185+
}
186+
for i, wantNS := range tC.resNS {
187+
gotNS := db.applyOpsInv[i]["ns"]
188+
if wantNS != gotNS {
189+
t.Errorf("wrong #%d. namespace: want=%s, got=%s", i, wantNS, gotNS)
190+
}
191+
}
192+
for i, wantCmd := range tC.resCmd {
193+
gotCmd := db.applyOpsInv[i]["cmd"]
194+
if wantCmd != gotCmd {
195+
t.Errorf("wrong #%d. command: want=%s, got=%s", i, wantCmd, gotCmd)
196+
}
197+
}
198+
for i, wantColl := range tC.resColl {
199+
gotColl := db.applyOpsInv[i]["coll"]
200+
if wantColl != gotColl {
201+
t.Errorf("wrong #%d. collection: want=%s, got=%s", i, wantColl, gotColl)
202+
}
203+
}
204+
})
205+
}
144206
})
145207

146208
t.Run("selective restore", func(t *testing.T) {
147209
//todo:
148210
})
149211

212+
t.Run("index restore", func(t *testing.T) {
213+
testCases := []struct {
214+
desc string
215+
oplogFile string
216+
db string
217+
coll string
218+
idxs bson.D
219+
}{
220+
{
221+
desc: "index: dropIndexes-createIndexes",
222+
oplogFile: "ops_cmd_createIndexes_dropIndexes",
223+
db: "mydb",
224+
coll: "c1",
225+
idxs: bson.D{{"fieldX", -1}, {"fieldZ", -1}},
226+
},
227+
//todo: add more cases
228+
}
229+
for _, tC := range testCases {
230+
t.Run(tC.desc, func(t *testing.T) {
231+
db := newMDBTestClient()
232+
oRestore := newOplogRestoreTest(db)
233+
234+
fr := useTestFile(t, tC.oplogFile)
235+
236+
_, err := oRestore.Apply(fr)
237+
if err != nil {
238+
t.Fatalf("error while applying oplog: %v", err)
239+
}
240+
241+
idxs := oRestore.indexCatalog.GetIndexes(tC.db, tC.coll)
242+
if len(idxs) != len(tC.idxs) {
243+
t.Errorf("wrong number of indexes: want=%d, got=%d", len(tC.idxs), len(idxs))
244+
}
245+
for i, idx := range idxs {
246+
if idx.Key[0].Key != tC.idxs[i].Key {
247+
t.Errorf("wrong key: want=%v, got=%v", tC.idxs[i], idx.Key[0])
248+
}
249+
}
250+
})
251+
}
252+
})
253+
150254
t.Run("cloning namespace", func(t *testing.T) {
151255
testCases := []struct {
152256
desc string
@@ -180,6 +284,7 @@ func TestApply(t *testing.T) {
180284
resOps: []string{},
181285
resNS: []string{},
182286
},
287+
// add index creation
183288
}
184289
for _, tC := range testCases {
185290
t.Run(tC.desc, func(t *testing.T) {
@@ -223,7 +328,7 @@ func useTestFile(t *testing.T, testFileName string) io.ReadCloser {
223328
t.Fatalf("failed to read test json file: filename=%s, err=%v", f, err)
224329
}
225330

226-
var jsonDocs []map[string]interface{}
331+
var jsonDocs []db.Oplog
227332
err = bson.UnmarshalExtJSON(jsonData, false, &jsonDocs)
228333
if err != nil {
229334
t.Fatalf("failed to parse test json array: filename=%s, err=%v", f, err)
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
[
2+
{
3+
"op": "c",
4+
"ns": "mydb.$cmd",
5+
"ui": {
6+
"$binary": {
7+
"base64": "dh2oYeQGTUO5UiXZLQXVsQ==",
8+
"subType": "04"
9+
}
10+
},
11+
"o": {
12+
"createIndexes": "c1",
13+
"v": 2,
14+
"key": {
15+
"fieldX": -1
16+
},
17+
"name": "fieldX_-1"
18+
},
19+
"ts": {
20+
"$timestamp": {
21+
"t": 1730655388,
22+
"i": 1
23+
}
24+
},
25+
"t": {
26+
"$numberLong": "1"
27+
},
28+
"v": {
29+
"$numberLong": "2"
30+
},
31+
"wall": {
32+
"$date": "2024-11-03T17:36:28.142Z"
33+
}
34+
},
35+
{
36+
"op": "c",
37+
"ns": "mydb.$cmd",
38+
"ui": {
39+
"$binary": {
40+
"base64": "dh2oYeQGTUO5UiXZLQXVsQ==",
41+
"subType": "04"
42+
}
43+
},
44+
"o": {
45+
"createIndexes": "c1",
46+
"v": 2,
47+
"key": {
48+
"fieldY": 1
49+
},
50+
"name": "fieldY_1"
51+
},
52+
"ts": {
53+
"$timestamp": {
54+
"t": 1730655389,
55+
"i": 1
56+
}
57+
},
58+
"t": {
59+
"$numberLong": "1"
60+
},
61+
"v": {
62+
"$numberLong": "2"
63+
},
64+
"wall": {
65+
"$date": "2024-11-03T17:36:28.142Z"
66+
}
67+
},
68+
{
69+
"op": "c",
70+
"ns": "mydb.$cmd",
71+
"ui": {
72+
"$binary": {
73+
"base64": "dh2oYeQGTUO5UiXZLQXVsQ==",
74+
"subType": "04"
75+
}
76+
},
77+
"o": {
78+
"dropIndexes": "c1",
79+
"index": "fieldY_1"
80+
},
81+
"o2": {
82+
"v": 2,
83+
"key": {
84+
"email": -1
85+
},
86+
"name": "fieldY_1"
87+
},
88+
"ts": {
89+
"$timestamp": {
90+
"t": 1730655616,
91+
"i": 1
92+
}
93+
},
94+
"t": {
95+
"$numberLong": "1"
96+
},
97+
"v": {
98+
"$numberLong": "2"
99+
},
100+
"wall": {
101+
"$date": "2024-11-03T17:40:16.298Z"
102+
}
103+
},
104+
{
105+
"op": "c",
106+
"ns": "mydb.$cmd",
107+
"ui": {
108+
"$binary": {
109+
"base64": "dh2oYeQGTUO5UiXZLQXVsQ==",
110+
"subType": "04"
111+
}
112+
},
113+
"o": {
114+
"createIndexes": "c1",
115+
"v": 2,
116+
"key": {
117+
"fieldZ": 1
118+
},
119+
"name": "fieldZ_1"
120+
},
121+
"ts": {
122+
"$timestamp": {
123+
"t": 1730655389,
124+
"i": 1
125+
}
126+
},
127+
"t": {
128+
"$numberLong": "1"
129+
},
130+
"v": {
131+
"$numberLong": "2"
132+
},
133+
"wall": {
134+
"$date": "2024-11-03T17:36:28.142Z"
135+
}
136+
}
137+
]

0 commit comments

Comments
 (0)