Skip to content

Commit 434ef4a

Browse files
committed
Testing iterator consistency
1 parent 04c5448 commit 434ef4a

File tree

1 file changed

+67
-6
lines changed

1 file changed

+67
-6
lines changed

tests/rocksdb/rocksdbP.test.ts

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,19 @@ describe('rocksdbP', () => {
130130
await rocksdbP.iteratorClose(iter);
131131
await rocksdbP.snapshotRelease(snap);
132132
});
133+
test('iterators have consistent iteration', async () => {
134+
await rocksdbP.dbPut(db, 'K1', '100', {});
135+
await rocksdbP.dbPut(db, 'K2', '100', {});
136+
const iter = rocksdbP.iteratorInit(db, {});
137+
expect(await rocksdbP.iteratorNextv(iter, 1)).toEqual(
138+
[[['K1', '100']], false]
139+
);
140+
await rocksdbP.dbPut(db, 'K2', '200', {});
141+
expect(await rocksdbP.iteratorNextv(iter, 1)).toEqual(
142+
[[['K2', '100']], false]
143+
);
144+
await rocksdbP.iteratorClose(iter);
145+
});
133146
});
134147
describe('transactions', () => {
135148
test('transactionCommit is idempotent', async () => {
@@ -232,6 +245,32 @@ describe('rocksdbP', () => {
232245
expect(await rocksdbP.transactionGet(tran, 'K1', {})).toBe('200');
233246
await rocksdbP.transactionCommit(tran);
234247
});
248+
test('iterator non-repeatable reads', async () => {
249+
await rocksdbP.dbPut(db, 'K1', '100', {});
250+
await rocksdbP.dbPut(db, 'K2', '100', {});
251+
const tran = rocksdbP.transactionInit(db, {});
252+
await rocksdbP.dbPut(db, 'K1', '200', {});
253+
await rocksdbP.dbPut(db, 'K2', '200', {});
254+
const iter1 = rocksdbP.transactionIteratorInit(tran, {});
255+
expect(await rocksdbP.iteratorNextv(iter1, 2)).toEqual(
256+
[[
257+
['K1', '200'],
258+
['K2', '200'],
259+
], false]
260+
);
261+
await rocksdbP.iteratorClose(iter1);
262+
await rocksdbP.dbPut(db, 'K1', '300', {});
263+
await rocksdbP.dbPut(db, 'K2', '300', {});
264+
const iter2 = rocksdbP.transactionIteratorInit(tran, {});
265+
expect(await rocksdbP.iteratorNextv(iter2, 2)).toEqual(
266+
[[
267+
['K1', '300'],
268+
['K2', '300'],
269+
], false]
270+
);
271+
await rocksdbP.iteratorClose(iter2);
272+
await rocksdbP.transactionRollback(tran);
273+
});
235274
});
236275
describe('transaction with snapshot', () => {
237276
test('conflicts when db write occurs after snapshot creation', async () => {
@@ -263,14 +302,14 @@ describe('rocksdbP', () => {
263302
expect(await rocksdbP.transactionGet(tran, 'K1', { snapshot: tranSnap })).toBe('300');
264303
await rocksdbP.transactionRollback(tran);
265304
});
266-
test.only('iterator repeatable reads', async () => {
305+
test('iterator repeatable reads', async () => {
267306
await rocksdbP.dbPut(db, 'K1', '100', {});
268307
await rocksdbP.dbPut(db, 'K2', '100', {});
269308
const tran = rocksdbP.transactionInit(db, {});
270309
await rocksdbP.transactionPut(tran, 'K3', '100');
271-
const tranSnap = rocksdbP.transactionSnapshot(tran);
310+
const tranSnap1 = rocksdbP.transactionSnapshot(tran);
272311
const iter1 = rocksdbP.transactionIteratorInit(tran, {
273-
snapshot: tranSnap
312+
snapshot: tranSnap1
274313
});
275314
expect(await rocksdbP.iteratorNextv(iter1, 3)).toEqual(
276315
[[
@@ -284,16 +323,38 @@ describe('rocksdbP', () => {
284323
await rocksdbP.transactionPut(tran, 'K3', '200');
285324
await rocksdbP.dbPut(db, 'K1', '200', {});
286325
const iter2 = rocksdbP.transactionIteratorInit(tran, {
287-
snapshot: tranSnap
326+
snapshot: tranSnap1
288327
});
328+
// Notice that this iteration uses the new values written
329+
// to in this transaction, this mean the snapshot only applies
330+
// to the underlying database, it's not a snapshot on the transaction
331+
// writes
289332
expect(await rocksdbP.iteratorNextv(iter2, 3)).toEqual(
290333
[[
291334
['K1', '100'],
292-
['K2', '100'],
293-
['K3', '100'],
335+
['K2', '200'],
336+
['K3', '200'],
294337
], false]
295338
);
296339
await rocksdbP.iteratorClose(iter2);
340+
// Resetting the snapshot for the transaction
341+
// Now the snapshot takes the current state of the DB,
342+
// but the transaction writes are overlayed on top
343+
const tranSnap2 = rocksdbP.transactionSnapshot(tran);
344+
await rocksdbP.dbPut(db, 'K2', '300', {});
345+
const iter3 = rocksdbP.transactionIteratorInit(tran, {
346+
snapshot: tranSnap2
347+
});
348+
expect(await rocksdbP.iteratorNextv(iter3, 3)).toEqual(
349+
[[
350+
['K1', '200'],
351+
['K2', '200'],
352+
['K3', '200'],
353+
], false]
354+
);
355+
await rocksdbP.iteratorClose(iter3);
356+
// Therefore iterators should always use the snapshot taken
357+
// at the beginning of the transaction
297358
await rocksdbP.transactionRollback(tran);
298359
});
299360
});

0 commit comments

Comments
 (0)