@powersync/service-core-tests 0.0.0-dev-20250829094737 → 0.0.0-dev-20250903064005
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -4
- package/dist/tests/register-compacting-tests.js +68 -0
- package/dist/tests/register-compacting-tests.js.map +1 -1
- package/dist/tests/register-data-storage-checkpoint-tests.d.ts +12 -0
- package/dist/tests/register-data-storage-checkpoint-tests.js +357 -0
- package/dist/tests/register-data-storage-checkpoint-tests.js.map +1 -0
- package/dist/tests/register-data-storage-data-tests.d.ts +12 -0
- package/dist/tests/{register-data-storage-tests.js → register-data-storage-data-tests.js} +151 -1035
- package/dist/tests/register-data-storage-data-tests.js.map +1 -0
- package/dist/tests/{register-data-storage-tests.d.ts → register-data-storage-parameter-tests.d.ts} +1 -2
- package/dist/tests/register-data-storage-parameter-tests.js +707 -0
- package/dist/tests/register-data-storage-parameter-tests.js.map +1 -0
- package/dist/tests/register-report-tests.d.ts +78 -0
- package/dist/tests/register-report-tests.js +119 -0
- package/dist/tests/register-report-tests.js.map +1 -0
- package/dist/tests/register-sync-tests.js +2 -1
- package/dist/tests/register-sync-tests.js.map +1 -1
- package/dist/tests/tests-index.d.ts +5 -1
- package/dist/tests/tests-index.js +5 -1
- package/dist/tests/tests-index.js.map +1 -1
- package/dist/tests/util.d.ts +1 -0
- package/dist/tests/util.js +3 -0
- package/dist/tests/util.js.map +1 -0
- package/package.json +2 -2
- package/src/tests/register-compacting-tests.ts +63 -0
- package/src/tests/register-data-storage-checkpoint-tests.ts +277 -0
- package/src/tests/{register-data-storage-tests.ts → register-data-storage-data-tests.ts} +38 -865
- package/src/tests/register-data-storage-parameter-tests.ts +613 -0
- package/src/tests/register-report-tests.ts +136 -0
- package/src/tests/register-sync-tests.ts +2 -1
- package/src/tests/tests-index.ts +5 -1
- package/src/tests/util.ts +3 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/tests/register-data-storage-tests.js.map +0 -1
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { storage } from '@powersync/service-core';
|
|
2
|
+
import { expect, test } from 'vitest';
|
|
3
|
+
import * as test_utils from '../test-utils/test-utils-index.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @example
|
|
7
|
+
* ```TypeScript
|
|
8
|
+
*
|
|
9
|
+
* describe('store - mongodb', function () {
|
|
10
|
+
* registerDataStorageCheckpointTests(MONGO_STORAGE_FACTORY);
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function registerDataStorageCheckpointTests(generateStorageFactory: storage.TestStorageFactory) {
|
|
16
|
+
test('managed write checkpoints - checkpoint after write', async (context) => {
|
|
17
|
+
await using factory = await generateStorageFactory();
|
|
18
|
+
const r = await factory.configureSyncRules({
|
|
19
|
+
content: `
|
|
20
|
+
bucket_definitions:
|
|
21
|
+
mybucket:
|
|
22
|
+
data: []
|
|
23
|
+
`,
|
|
24
|
+
validate: false
|
|
25
|
+
});
|
|
26
|
+
const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
|
|
27
|
+
|
|
28
|
+
const abortController = new AbortController();
|
|
29
|
+
context.onTestFinished(() => abortController.abort());
|
|
30
|
+
const iter = bucketStorage
|
|
31
|
+
.watchCheckpointChanges({ user_id: 'user1', signal: abortController.signal })
|
|
32
|
+
[Symbol.asyncIterator]();
|
|
33
|
+
|
|
34
|
+
const writeCheckpoint = await bucketStorage.createManagedWriteCheckpoint({
|
|
35
|
+
heads: { '1': '5/0' },
|
|
36
|
+
user_id: 'user1'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
|
|
40
|
+
await batch.keepalive('5/0');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const result = await iter.next();
|
|
44
|
+
expect(result).toMatchObject({
|
|
45
|
+
done: false,
|
|
46
|
+
value: {
|
|
47
|
+
base: {
|
|
48
|
+
checkpoint: 0n,
|
|
49
|
+
lsn: '5/0'
|
|
50
|
+
},
|
|
51
|
+
writeCheckpoint: writeCheckpoint
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('managed write checkpoints - write after checkpoint', async (context) => {
|
|
57
|
+
await using factory = await generateStorageFactory();
|
|
58
|
+
const r = await factory.configureSyncRules({
|
|
59
|
+
content: `
|
|
60
|
+
bucket_definitions:
|
|
61
|
+
mybucket:
|
|
62
|
+
data: []
|
|
63
|
+
`,
|
|
64
|
+
validate: false
|
|
65
|
+
});
|
|
66
|
+
const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
|
|
67
|
+
|
|
68
|
+
const abortController = new AbortController();
|
|
69
|
+
context.onTestFinished(() => abortController.abort());
|
|
70
|
+
const iter = bucketStorage
|
|
71
|
+
.watchCheckpointChanges({ user_id: 'user1', signal: abortController.signal })
|
|
72
|
+
[Symbol.asyncIterator]();
|
|
73
|
+
|
|
74
|
+
await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
|
|
75
|
+
await batch.keepalive('5/0');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const result = await iter.next();
|
|
79
|
+
expect(result).toMatchObject({
|
|
80
|
+
done: false,
|
|
81
|
+
value: {
|
|
82
|
+
base: {
|
|
83
|
+
checkpoint: 0n,
|
|
84
|
+
lsn: '5/0'
|
|
85
|
+
},
|
|
86
|
+
writeCheckpoint: null
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const writeCheckpoint = await bucketStorage.createManagedWriteCheckpoint({
|
|
91
|
+
heads: { '1': '6/0' },
|
|
92
|
+
user_id: 'user1'
|
|
93
|
+
});
|
|
94
|
+
// We have to trigger a new keepalive after the checkpoint, at least to cover postgres storage.
|
|
95
|
+
// This is what is effetively triggered with RouteAPI.createReplicationHead().
|
|
96
|
+
// MongoDB storage doesn't explicitly need this anymore.
|
|
97
|
+
await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
|
|
98
|
+
await batch.keepalive('6/0');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
let result2 = await iter.next();
|
|
102
|
+
if (result2.value?.base?.lsn == '5/0') {
|
|
103
|
+
// Events could arrive in a different order in some cases - this caters for it
|
|
104
|
+
result2 = await iter.next();
|
|
105
|
+
}
|
|
106
|
+
expect(result2).toMatchObject({
|
|
107
|
+
done: false,
|
|
108
|
+
value: {
|
|
109
|
+
base: {
|
|
110
|
+
checkpoint: 0n,
|
|
111
|
+
lsn: '6/0'
|
|
112
|
+
},
|
|
113
|
+
writeCheckpoint: writeCheckpoint
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test('custom write checkpoints - checkpoint after write', async (context) => {
|
|
119
|
+
await using factory = await generateStorageFactory();
|
|
120
|
+
const r = await factory.configureSyncRules({
|
|
121
|
+
content: `
|
|
122
|
+
bucket_definitions:
|
|
123
|
+
mybucket:
|
|
124
|
+
data: []
|
|
125
|
+
`,
|
|
126
|
+
validate: false
|
|
127
|
+
});
|
|
128
|
+
const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
|
|
129
|
+
bucketStorage.setWriteCheckpointMode(storage.WriteCheckpointMode.CUSTOM);
|
|
130
|
+
|
|
131
|
+
const abortController = new AbortController();
|
|
132
|
+
context.onTestFinished(() => abortController.abort());
|
|
133
|
+
const iter = bucketStorage
|
|
134
|
+
.watchCheckpointChanges({ user_id: 'user1', signal: abortController.signal })
|
|
135
|
+
[Symbol.asyncIterator]();
|
|
136
|
+
|
|
137
|
+
await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
|
|
138
|
+
await batch.addCustomWriteCheckpoint({
|
|
139
|
+
checkpoint: 5n,
|
|
140
|
+
user_id: 'user1'
|
|
141
|
+
});
|
|
142
|
+
await batch.flush();
|
|
143
|
+
await batch.keepalive('5/0');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const result = await iter.next();
|
|
147
|
+
expect(result).toMatchObject({
|
|
148
|
+
done: false,
|
|
149
|
+
value: {
|
|
150
|
+
base: {
|
|
151
|
+
lsn: '5/0'
|
|
152
|
+
},
|
|
153
|
+
writeCheckpoint: 5n
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('custom write checkpoints - standalone checkpoint', async (context) => {
|
|
159
|
+
await using factory = await generateStorageFactory();
|
|
160
|
+
const r = await factory.configureSyncRules({
|
|
161
|
+
content: `
|
|
162
|
+
bucket_definitions:
|
|
163
|
+
mybucket:
|
|
164
|
+
data: []
|
|
165
|
+
`,
|
|
166
|
+
validate: false
|
|
167
|
+
});
|
|
168
|
+
const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
|
|
169
|
+
bucketStorage.setWriteCheckpointMode(storage.WriteCheckpointMode.CUSTOM);
|
|
170
|
+
|
|
171
|
+
const abortController = new AbortController();
|
|
172
|
+
context.onTestFinished(() => abortController.abort());
|
|
173
|
+
const iter = bucketStorage
|
|
174
|
+
.watchCheckpointChanges({ user_id: 'user1', signal: abortController.signal })
|
|
175
|
+
[Symbol.asyncIterator]();
|
|
176
|
+
|
|
177
|
+
await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
|
|
178
|
+
// Flush to clear state
|
|
179
|
+
await batch.flush();
|
|
180
|
+
|
|
181
|
+
await batch.addCustomWriteCheckpoint({
|
|
182
|
+
checkpoint: 5n,
|
|
183
|
+
user_id: 'user1'
|
|
184
|
+
});
|
|
185
|
+
await batch.flush();
|
|
186
|
+
await batch.keepalive('5/0');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const result = await iter.next();
|
|
190
|
+
expect(result).toMatchObject({
|
|
191
|
+
done: false,
|
|
192
|
+
value: {
|
|
193
|
+
base: {
|
|
194
|
+
lsn: '5/0'
|
|
195
|
+
},
|
|
196
|
+
writeCheckpoint: 5n
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('custom write checkpoints - write after checkpoint', async (context) => {
|
|
202
|
+
await using factory = await generateStorageFactory();
|
|
203
|
+
const r = await factory.configureSyncRules({
|
|
204
|
+
content: `
|
|
205
|
+
bucket_definitions:
|
|
206
|
+
mybucket:
|
|
207
|
+
data: []
|
|
208
|
+
`,
|
|
209
|
+
validate: false
|
|
210
|
+
});
|
|
211
|
+
const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
|
|
212
|
+
bucketStorage.setWriteCheckpointMode(storage.WriteCheckpointMode.CUSTOM);
|
|
213
|
+
|
|
214
|
+
const abortController = new AbortController();
|
|
215
|
+
context.onTestFinished(() => abortController.abort());
|
|
216
|
+
const iter = bucketStorage
|
|
217
|
+
.watchCheckpointChanges({ user_id: 'user1', signal: abortController.signal })
|
|
218
|
+
[Symbol.asyncIterator]();
|
|
219
|
+
|
|
220
|
+
await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
|
|
221
|
+
await batch.keepalive('5/0');
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const result = await iter.next();
|
|
225
|
+
expect(result).toMatchObject({
|
|
226
|
+
done: false,
|
|
227
|
+
value: {
|
|
228
|
+
base: {
|
|
229
|
+
lsn: '5/0'
|
|
230
|
+
},
|
|
231
|
+
writeCheckpoint: null
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
|
|
236
|
+
batch.addCustomWriteCheckpoint({
|
|
237
|
+
checkpoint: 6n,
|
|
238
|
+
user_id: 'user1'
|
|
239
|
+
});
|
|
240
|
+
await batch.flush();
|
|
241
|
+
await batch.keepalive('6/0');
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
let result2 = await iter.next();
|
|
245
|
+
expect(result2).toMatchObject({
|
|
246
|
+
done: false,
|
|
247
|
+
value: {
|
|
248
|
+
base: {
|
|
249
|
+
// can be 5/0 or 6/0 - actual value not relevant for custom write checkpoints
|
|
250
|
+
// lsn: '6/0'
|
|
251
|
+
},
|
|
252
|
+
writeCheckpoint: 6n
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
|
|
257
|
+
batch.addCustomWriteCheckpoint({
|
|
258
|
+
checkpoint: 7n,
|
|
259
|
+
user_id: 'user1'
|
|
260
|
+
});
|
|
261
|
+
await batch.flush();
|
|
262
|
+
await batch.keepalive('7/0');
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
let result3 = await iter.next();
|
|
266
|
+
expect(result3).toMatchObject({
|
|
267
|
+
done: false,
|
|
268
|
+
value: {
|
|
269
|
+
base: {
|
|
270
|
+
// can be 5/0, 6/0 or 7/0 - actual value not relevant for custom write checkpoints
|
|
271
|
+
// lsn: '7/0'
|
|
272
|
+
},
|
|
273
|
+
writeCheckpoint: 7n
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
}
|