Skip to content

Commit 8efca19

Browse files
committed
Add tests for OplogRestore.isOpForCloning
1 parent 2a4dcd0 commit 8efca19

File tree

1 file changed

+340
-0
lines changed

1 file changed

+340
-0
lines changed

pbm/oplog/restore_test.go

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
package oplog
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/mongodb/mongo-tools/common/db"
8+
"github.com/percona/percona-backup-mongodb/pbm/snapshot"
9+
"go.mongodb.org/mongo-driver/bson"
10+
"go.mongodb.org/mongo-driver/bson/primitive"
11+
)
12+
13+
func newOplogRestoreTest(mdb mDBCl) *OplogRestore {
14+
return &OplogRestore{
15+
mdb: mdb,
16+
}
17+
}
18+
19+
type mdbTestClient struct {
20+
}
21+
22+
func (d *mdbTestClient) getUUIDForNS(_ context.Context, _ string) (primitive.Binary, error) {
23+
return primitive.Binary{Subtype: 0x00, Data: []byte{0x01, 0x02, 0x03}}, nil
24+
}
25+
26+
func (d *mdbTestClient) ensureCollExists(_ string) error {
27+
return nil
28+
}
29+
30+
func (d *mdbTestClient) applyOps(entries []interface{}) error {
31+
return nil
32+
}
33+
34+
func TestIsOpForCloning(t *testing.T) {
35+
oRestore := newOplogRestoreTest(&mdbTestClient{})
36+
oRestore.SetCloneNS(context.Background(), snapshot.CloneNS{FromNS: "mydb.cloningFrom", ToNS: "mydb.cloningTo"})
37+
38+
testCases := []struct {
39+
desc string
40+
entry *db.Oplog
41+
isForCloning bool
42+
}{
43+
// i op
44+
{
45+
desc: "insert op for cloning ",
46+
entry: createInsertOp(t, "mydb.cloningFrom"),
47+
isForCloning: true,
48+
},
49+
{
50+
desc: "insert op, collection not for cloning",
51+
entry: createInsertOp(t, "mydb.x"),
52+
isForCloning: false,
53+
},
54+
{
55+
desc: "insert op, db not for cloning",
56+
entry: createInsertOp(t, "x.cloningFrom"),
57+
isForCloning: false,
58+
},
59+
60+
// u op
61+
{
62+
desc: "update op for cloning ",
63+
entry: createUpdateOp(t, "mydb.cloningFrom"),
64+
isForCloning: true,
65+
},
66+
{
67+
desc: "update op, collection not for cloning",
68+
entry: createUpdateOp(t, "mydb.x"),
69+
isForCloning: false,
70+
},
71+
{
72+
desc: "update op, db not for cloning",
73+
entry: createUpdateOp(t, "x.cloningFrom"),
74+
isForCloning: false,
75+
},
76+
77+
// d op
78+
{
79+
desc: "delete op for cloning ",
80+
entry: createDeleteOp(t, "mydb.cloningFrom"),
81+
isForCloning: true,
82+
},
83+
{
84+
desc: "delete op, collection not for cloning",
85+
entry: createDeleteOp(t, "mydb.x"),
86+
isForCloning: false,
87+
},
88+
{
89+
desc: "delete op, db not for cloning",
90+
entry: createDeleteOp(t, "x.cloningFrom"),
91+
isForCloning: false,
92+
},
93+
}
94+
95+
for _, tC := range testCases {
96+
t.Run(tC.desc, func(t *testing.T) {
97+
res := oRestore.isOpForCloning(tC.entry)
98+
if res != tC.isForCloning {
99+
t.Errorf("%s: for entry: %+v isOpForCloning is: %t, but it should be opposite",
100+
tC.desc, tC.entry, tC.isForCloning)
101+
102+
}
103+
})
104+
}
105+
}
106+
107+
func createInsertOp(t *testing.T, ns string) *db.Oplog {
108+
t.Helper()
109+
iOpJSON := `
110+
{
111+
"lsid": {
112+
"id": {
113+
"$binary": {
114+
"base64": "YYbkO7kpRt6xFqJqIh+h9g==",
115+
"subType": "04"
116+
}
117+
},
118+
"uid": {
119+
"$binary": {
120+
"base64": "8L/kOoqHkvDRIRJTrmrrO3wwOr+ToO8WLvmn15Ql7G0=",
121+
"subType": "00"
122+
}
123+
}
124+
},
125+
"txnNumber": {
126+
"$numberLong": "9"
127+
},
128+
"op": "i",
129+
"ns": "db.coll",
130+
"ui": {
131+
"$binary": {
132+
"base64": "v+mHa8niRBKG7Z+uqJGARQ==",
133+
"subType": "04"
134+
}
135+
},
136+
"o": {
137+
"_id": {
138+
"$oid": "6747008178d82a2b1134a2b8"
139+
},
140+
"d": {
141+
"$numberInt": "6"
142+
},
143+
"desc": "doc-6"
144+
},
145+
"o2": {
146+
"_id": {
147+
"$oid": "6747008178d82a2b1134a2b8"
148+
}
149+
},
150+
"stmtId": {
151+
"$numberInt": "0"
152+
},
153+
"ts": {
154+
"$timestamp": {
155+
"t": 1732706433,
156+
"i": 1
157+
}
158+
},
159+
"t": {
160+
"$numberLong": "2"
161+
},
162+
"v": {
163+
"$numberLong": "2"
164+
},
165+
"wall": {
166+
"$date": {
167+
"$numberLong": "1732706433987"
168+
}
169+
},
170+
"prevOpTime": {
171+
"ts": {
172+
"$timestamp": {
173+
"t": 0,
174+
"i": 0
175+
}
176+
},
177+
"t": {
178+
"$numberLong": "-1"
179+
}
180+
}
181+
}`
182+
183+
return replaceNsWithinOpEntry(t, iOpJSON, ns)
184+
}
185+
186+
func createUpdateOp(t *testing.T, ns string) *db.Oplog {
187+
t.Helper()
188+
189+
uOpJSON := `
190+
{
191+
"lsid": {
192+
"id": {
193+
"$binary": {
194+
"base64": "HxXre7SSRxe8eq+OjOQOhw==",
195+
"subType": "04"
196+
}
197+
},
198+
"uid": {
199+
"$binary": {
200+
"base64": "Bh/Anp+//gSHltMgOtOX+7sunrF/VwW+VDdA3fRANl0=",
201+
"subType": "00"
202+
}
203+
}
204+
},
205+
"txnNumber": {
206+
"$numberLong": "5"
207+
},
208+
"op": "u",
209+
"ns": "db.coll",
210+
"ui": {
211+
"$binary": {
212+
"base64": "f774YvKERIKXSJVH+xCtPw==",
213+
"subType": "04"
214+
}
215+
},
216+
"o": {
217+
"$v": 2,
218+
"diff": {
219+
"i": {
220+
"city": "split"
221+
}
222+
}
223+
},
224+
"o2": {
225+
"_id": {
226+
"$oid": "6728e3fcedfb509c06f01307"
227+
}
228+
},
229+
"stmtId": 0,
230+
"ts": {
231+
"$timestamp": {
232+
"t": 1730733212,
233+
"i": 1
234+
}
235+
},
236+
"t": {
237+
"$numberLong": "7"
238+
},
239+
"v": {
240+
"$numberLong": "2"
241+
},
242+
"wall": {
243+
"$date": "2024-11-04T15:13:32.123Z"
244+
},
245+
"prevOpTime": {
246+
"ts": {
247+
"$timestamp": {
248+
"t": 0,
249+
"i": 0
250+
}
251+
},
252+
"t": {
253+
"$numberLong": "-1"
254+
}
255+
}
256+
}`
257+
return replaceNsWithinOpEntry(t, uOpJSON, ns)
258+
}
259+
260+
func createDeleteOp(t *testing.T, ns string) *db.Oplog {
261+
t.Helper()
262+
263+
dOpJSON := `
264+
{
265+
"lsid": {
266+
"id": {
267+
"$binary": {
268+
"base64": "HxXre7SSRxe8eq+OjOQOhw==",
269+
"subType": "04"
270+
}
271+
},
272+
"uid": {
273+
"$binary": {
274+
"base64": "Bh/Anp+//gSHltMgOtOX+7sunrF/VwW+VDdA3fRANl0=",
275+
"subType": "00"
276+
}
277+
}
278+
},
279+
"txnNumber": {
280+
"$numberLong": "6"
281+
},
282+
"op": "d",
283+
"ns": "db.coll",
284+
"ui": {
285+
"$binary": {
286+
"base64": "f774YvKERIKXSJVH+xCtPw==",
287+
"subType": "04"
288+
}
289+
},
290+
"o": {
291+
"_id": {
292+
"$oid": "6728e3fcedfb509c06f01307"
293+
}
294+
},
295+
"stmtId": 0,
296+
"ts": {
297+
"$timestamp": {
298+
"t": 1730733256,
299+
"i": 1
300+
}
301+
},
302+
"t": {
303+
"$numberLong": "7"
304+
},
305+
"v": {
306+
"$numberLong": "2"
307+
},
308+
"wall": {
309+
"$date": "2024-11-04T15:14:16.626Z"
310+
},
311+
"prevOpTime": {
312+
"ts": {
313+
"$timestamp": {
314+
"t": 0,
315+
"i": 0
316+
}
317+
},
318+
"t": {
319+
"$numberLong": "-1"
320+
}
321+
}
322+
}`
323+
324+
return replaceNsWithinOpEntry(t, dOpJSON, ns)
325+
}
326+
327+
func replaceNsWithinOpEntry(t *testing.T, jsonEntry, ns string) *db.Oplog {
328+
t.Helper()
329+
330+
oe := db.Oplog{}
331+
err := bson.UnmarshalExtJSON([]byte(jsonEntry), false, &oe)
332+
if err != nil {
333+
t.Errorf("err while unmarshal from json: %v", err)
334+
}
335+
336+
if ns != "" {
337+
oe.Namespace = ns
338+
}
339+
return &oe
340+
}

0 commit comments

Comments
 (0)