@powersync/service-core-tests 0.0.0-dev-20260203155513 → 0.0.0-dev-20260223080959

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +41 -5
  2. package/dist/test-utils/general-utils.d.ts +0 -1
  3. package/dist/test-utils/general-utils.js +0 -24
  4. package/dist/test-utils/general-utils.js.map +1 -1
  5. package/dist/tests/register-compacting-tests.js +52 -57
  6. package/dist/tests/register-compacting-tests.js.map +1 -1
  7. package/dist/tests/register-data-storage-checkpoint-tests.js +11 -26
  8. package/dist/tests/register-data-storage-checkpoint-tests.js.map +1 -1
  9. package/dist/tests/register-data-storage-data-tests.js +80 -96
  10. package/dist/tests/register-data-storage-data-tests.js.map +1 -1
  11. package/dist/tests/register-data-storage-parameter-tests.js +37 -49
  12. package/dist/tests/register-data-storage-parameter-tests.js.map +1 -1
  13. package/dist/tests/register-parameter-compacting-tests.js +5 -9
  14. package/dist/tests/register-parameter-compacting-tests.js.map +1 -1
  15. package/dist/tests/register-sync-tests.d.ts +3 -1
  16. package/dist/tests/register-sync-tests.js +47 -39
  17. package/dist/tests/register-sync-tests.js.map +1 -1
  18. package/dist/tests/util.d.ts +5 -1
  19. package/dist/tests/util.js +14 -0
  20. package/dist/tests/util.js.map +1 -1
  21. package/package.json +3 -3
  22. package/src/test-utils/general-utils.ts +1 -25
  23. package/src/tests/register-compacting-tests.ts +68 -57
  24. package/src/tests/register-data-storage-checkpoint-tests.ts +21 -26
  25. package/src/tests/register-data-storage-data-tests.ts +135 -101
  26. package/src/tests/register-data-storage-parameter-tests.ts +58 -50
  27. package/src/tests/register-parameter-compacting-tests.ts +9 -9
  28. package/src/tests/register-sync-tests.ts +51 -39
  29. package/src/tests/util.ts +21 -0
  30. package/tsconfig.tsbuildinfo +1 -1
@@ -1,19 +1,20 @@
1
- import { storage } from '@powersync/service-core';
1
+ import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
2
2
  import { expect, test } from 'vitest';
3
3
  import * as test_utils from '../test-utils/test-utils-index.js';
4
+ import { bucketRequest, bucketRequestMap, bucketRequests } from './util.js';
4
5
 
5
6
  const TEST_TABLE = test_utils.makeTestTable('test', ['id']);
6
7
 
7
8
  export function registerCompactTests(generateStorageFactory: storage.TestStorageFactory) {
8
9
  test('compacting (1)', async () => {
9
10
  await using factory = await generateStorageFactory();
10
- const syncRules = await factory.updateSyncRules({
11
- content: `
11
+ const syncRules = await factory.updateSyncRules(
12
+ updateSyncRulesFromYaml(`
12
13
  bucket_definitions:
13
14
  global:
14
15
  data: [select * from test]
15
- `
16
- });
16
+ `)
17
+ );
17
18
  const bucketStorage = factory.getInstance(syncRules);
18
19
 
19
20
  const result = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
@@ -50,10 +51,10 @@ bucket_definitions:
50
51
  const checkpoint = result!.flushed_op;
51
52
 
52
53
  const batchBefore = await test_utils.oneFromAsync(
53
- bucketStorage.getBucketDataBatch(checkpoint, new Map([['global[]', 0n]]))
54
+ bucketStorage.getBucketDataBatch(checkpoint, bucketRequestMap(syncRules, [['global[]', 0n]]))
54
55
  );
55
56
  const dataBefore = batchBefore.chunkData.data;
56
- const checksumBefore = await bucketStorage.getChecksums(checkpoint, ['global[]']);
57
+ const checksumBefore = await bucketStorage.getChecksums(checkpoint, bucketRequests(syncRules, ['global[]']));
57
58
 
58
59
  expect(dataBefore).toMatchObject([
59
60
  {
@@ -81,16 +82,17 @@ bucket_definitions:
81
82
  clearBatchLimit: 2,
82
83
  moveBatchLimit: 1,
83
84
  moveBatchQueryLimit: 1,
84
- minBucketChanges: 1
85
+ minBucketChanges: 1,
86
+ minChangeRatio: 0
85
87
  });
86
88
 
87
89
  const batchAfter = await test_utils.oneFromAsync(
88
- bucketStorage.getBucketDataBatch(checkpoint, new Map([['global[]', 0n]]))
90
+ bucketStorage.getBucketDataBatch(checkpoint, bucketRequestMap(syncRules, [['global[]', 0n]]))
89
91
  );
90
92
  const dataAfter = batchAfter.chunkData.data;
91
- const checksumAfter = await bucketStorage.getChecksums(checkpoint, ['global[]']);
93
+ const checksumAfter = await bucketStorage.getChecksums(checkpoint, bucketRequests(syncRules, ['global[]']));
92
94
  bucketStorage.clearChecksumCache();
93
- const checksumAfter2 = await bucketStorage.getChecksums(checkpoint, ['global[]']);
95
+ const checksumAfter2 = await bucketStorage.getChecksums(checkpoint, bucketRequests(syncRules, ['global[]']));
94
96
 
95
97
  expect(batchAfter.targetOp).toEqual(3n);
96
98
  expect(dataAfter).toMatchObject([
@@ -113,21 +115,25 @@ bucket_definitions:
113
115
  }
114
116
  ]);
115
117
 
116
- expect(checksumAfter.get('global[]')).toEqual(checksumBefore.get('global[]'));
117
- expect(checksumAfter2.get('global[]')).toEqual(checksumBefore.get('global[]'));
118
+ expect(checksumAfter.get(bucketRequest(syncRules, 'global[]'))).toEqual(
119
+ checksumBefore.get(bucketRequest(syncRules, 'global[]'))
120
+ );
121
+ expect(checksumAfter2.get(bucketRequest(syncRules, 'global[]'))).toEqual(
122
+ checksumBefore.get(bucketRequest(syncRules, 'global[]'))
123
+ );
118
124
 
119
125
  test_utils.validateCompactedBucket(dataBefore, dataAfter);
120
126
  });
121
127
 
122
128
  test('compacting (2)', async () => {
123
129
  await using factory = await generateStorageFactory();
124
- const syncRules = await factory.updateSyncRules({
125
- content: `
130
+ const syncRules = await factory.updateSyncRules(
131
+ updateSyncRulesFromYaml(`
126
132
  bucket_definitions:
127
133
  global:
128
134
  data: [select * from test]
129
- `
130
- });
135
+ `)
136
+ );
131
137
  const bucketStorage = factory.getInstance(syncRules);
132
138
 
133
139
  const result = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
@@ -173,10 +179,10 @@ bucket_definitions:
173
179
  const checkpoint = result!.flushed_op;
174
180
 
175
181
  const batchBefore = await test_utils.oneFromAsync(
176
- bucketStorage.getBucketDataBatch(checkpoint, new Map([['global[]', 0n]]))
182
+ bucketStorage.getBucketDataBatch(checkpoint, bucketRequestMap(syncRules, [['global[]', 0n]]))
177
183
  );
178
184
  const dataBefore = batchBefore.chunkData.data;
179
- const checksumBefore = await bucketStorage.getChecksums(checkpoint, ['global[]']);
185
+ const checksumBefore = await bucketStorage.getChecksums(checkpoint, bucketRequests(syncRules, ['global[]']));
180
186
 
181
187
  expect(dataBefore).toMatchObject([
182
188
  {
@@ -209,15 +215,16 @@ bucket_definitions:
209
215
  clearBatchLimit: 2,
210
216
  moveBatchLimit: 1,
211
217
  moveBatchQueryLimit: 1,
212
- minBucketChanges: 1
218
+ minBucketChanges: 1,
219
+ minChangeRatio: 0
213
220
  });
214
221
 
215
222
  const batchAfter = await test_utils.oneFromAsync(
216
- bucketStorage.getBucketDataBatch(checkpoint, new Map([['global[]', 0n]]))
223
+ bucketStorage.getBucketDataBatch(checkpoint, bucketRequestMap(syncRules, [['global[]', 0n]]))
217
224
  );
218
225
  const dataAfter = batchAfter.chunkData.data;
219
226
  bucketStorage.clearChecksumCache();
220
- const checksumAfter = await bucketStorage.getChecksums(checkpoint, ['global[]']);
227
+ const checksumAfter = await bucketStorage.getChecksums(checkpoint, bucketRequests(syncRules, ['global[]']));
221
228
 
222
229
  expect(batchAfter.targetOp).toEqual(4n);
223
230
  expect(dataAfter).toMatchObject([
@@ -233,8 +240,8 @@ bucket_definitions:
233
240
  op_id: '4'
234
241
  }
235
242
  ]);
236
- expect(checksumAfter.get('global[]')).toEqual({
237
- ...checksumBefore.get('global[]'),
243
+ expect(checksumAfter.get(bucketRequest(syncRules, 'global[]'))).toEqual({
244
+ ...checksumBefore.get(bucketRequest(syncRules, 'global[]')),
238
245
  count: 2
239
246
  });
240
247
 
@@ -243,13 +250,13 @@ bucket_definitions:
243
250
 
244
251
  test('compacting (3)', async () => {
245
252
  await using factory = await generateStorageFactory();
246
- const syncRules = await factory.updateSyncRules({
247
- content: `
253
+ const syncRules = await factory.updateSyncRules(
254
+ updateSyncRulesFromYaml(`
248
255
  bucket_definitions:
249
256
  global:
250
257
  data: [select * from test]
251
- `
252
- });
258
+ `)
259
+ );
253
260
  const bucketStorage = factory.getInstance(syncRules);
254
261
 
255
262
  const result = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
@@ -284,7 +291,7 @@ bucket_definitions:
284
291
  });
285
292
 
286
293
  const checkpoint1 = result!.flushed_op;
287
- const checksumBefore = await bucketStorage.getChecksums(checkpoint1, ['global[]']);
294
+ const checksumBefore = await bucketStorage.getChecksums(checkpoint1, bucketRequests(syncRules, ['global[]']));
288
295
 
289
296
  const result2 = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
290
297
  await batch.save({
@@ -303,15 +310,16 @@ bucket_definitions:
303
310
  clearBatchLimit: 2,
304
311
  moveBatchLimit: 1,
305
312
  moveBatchQueryLimit: 1,
306
- minBucketChanges: 1
313
+ minBucketChanges: 1,
314
+ minChangeRatio: 0
307
315
  });
308
316
 
309
317
  const batchAfter = await test_utils.oneFromAsync(
310
- bucketStorage.getBucketDataBatch(checkpoint2, new Map([['global[]', 0n]]))
318
+ bucketStorage.getBucketDataBatch(checkpoint2, bucketRequestMap(syncRules, [['global[]', 0n]]))
311
319
  );
312
320
  const dataAfter = batchAfter.chunkData.data;
313
321
  await bucketStorage.clearChecksumCache();
314
- const checksumAfter = await bucketStorage.getChecksums(checkpoint2, ['global[]']);
322
+ const checksumAfter = await bucketStorage.getChecksums(checkpoint2, bucketRequests(syncRules, ['global[]']));
315
323
 
316
324
  expect(batchAfter.targetOp).toEqual(4n);
317
325
  expect(dataAfter).toMatchObject([
@@ -321,8 +329,8 @@ bucket_definitions:
321
329
  op_id: '4'
322
330
  }
323
331
  ]);
324
- expect(checksumAfter.get('global[]')).toEqual({
325
- bucket: 'global[]',
332
+ expect(checksumAfter.get(bucketRequest(syncRules, 'global[]'))).toEqual({
333
+ bucket: bucketRequest(syncRules, 'global[]'),
326
334
  count: 1,
327
335
  checksum: 1874612650
328
336
  });
@@ -330,16 +338,16 @@ bucket_definitions:
330
338
 
331
339
  test('compacting (4)', async () => {
332
340
  await using factory = await generateStorageFactory();
333
- const syncRules = await factory.updateSyncRules({
334
- /* yaml */ content: ` bucket_definitions:
341
+ const syncRules = await factory.updateSyncRules(
342
+ updateSyncRulesFromYaml(` bucket_definitions:
335
343
  grouped:
336
344
  # The parameter query here is not important
337
345
  # We specifically don't want to create bucket_parameter records here
338
346
  # since the op_ids for bucket_data could vary between storage implementations.
339
347
  parameters: select 'b' as b
340
348
  data:
341
- - select * from test where b = bucket.b`
342
- });
349
+ - select * from test where b = bucket.b`)
350
+ );
343
351
  const bucketStorage = factory.getInstance(syncRules);
344
352
 
345
353
  const result = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
@@ -416,13 +424,14 @@ bucket_definitions:
416
424
  clearBatchLimit: 100,
417
425
  moveBatchLimit: 100,
418
426
  moveBatchQueryLimit: 100, // Larger limit for a larger window of operations
419
- minBucketChanges: 1
427
+ minBucketChanges: 1,
428
+ minChangeRatio: 0
420
429
  });
421
430
 
422
431
  const batchAfter = await test_utils.fromAsync(
423
432
  bucketStorage.getBucketDataBatch(
424
433
  checkpoint,
425
- new Map([
434
+ bucketRequestMap(syncRules, [
426
435
  ['grouped["b1"]', 0n],
427
436
  ['grouped["b2"]', 0n]
428
437
  ])
@@ -459,13 +468,13 @@ bucket_definitions:
459
468
 
460
469
  test('partial checksums after compacting', async () => {
461
470
  await using factory = await generateStorageFactory();
462
- const syncRules = await factory.updateSyncRules({
463
- content: `
471
+ const syncRules = await factory.updateSyncRules(
472
+ updateSyncRulesFromYaml(`
464
473
  bucket_definitions:
465
474
  global:
466
475
  data: [select * from test]
467
- `
468
- });
476
+ `)
477
+ );
469
478
  const bucketStorage = factory.getInstance(syncRules);
470
479
 
471
480
  const result = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
@@ -503,7 +512,8 @@ bucket_definitions:
503
512
  clearBatchLimit: 2,
504
513
  moveBatchLimit: 1,
505
514
  moveBatchQueryLimit: 1,
506
- minBucketChanges: 1
515
+ minBucketChanges: 1,
516
+ minChangeRatio: 0
507
517
  });
508
518
 
509
519
  const result2 = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
@@ -519,9 +529,9 @@ bucket_definitions:
519
529
  });
520
530
  const checkpoint2 = result2!.flushed_op;
521
531
  await bucketStorage.clearChecksumCache();
522
- const checksumAfter = await bucketStorage.getChecksums(checkpoint2, ['global[]']);
523
- expect(checksumAfter.get('global[]')).toEqual({
524
- bucket: 'global[]',
532
+ const checksumAfter = await bucketStorage.getChecksums(checkpoint2, bucketRequests(syncRules, ['global[]']));
533
+ expect(checksumAfter.get(bucketRequest(syncRules, 'global[]'))).toEqual({
534
+ bucket: bucketRequest(syncRules, 'global[]'),
525
535
  count: 4,
526
536
  checksum: 1874612650
527
537
  });
@@ -529,13 +539,13 @@ bucket_definitions:
529
539
 
530
540
  test('partial checksums after compacting (2)', async () => {
531
541
  await using factory = await generateStorageFactory();
532
- const syncRules = await factory.updateSyncRules({
533
- content: `
542
+ const syncRules = await factory.updateSyncRules(
543
+ updateSyncRulesFromYaml(`
534
544
  bucket_definitions:
535
545
  global:
536
546
  data: [select * from test]
537
- `
538
- });
547
+ `)
548
+ );
539
549
  const bucketStorage = factory.getInstance(syncRules);
540
550
 
541
551
  const result = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
@@ -561,7 +571,7 @@ bucket_definitions:
561
571
  });
562
572
 
563
573
  // Get checksums here just to populate the cache
564
- await bucketStorage.getChecksums(result!.flushed_op, ['global[]']);
574
+ await bucketStorage.getChecksums(result!.flushed_op, bucketRequests(syncRules, ['global[]']));
565
575
  const result2 = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
566
576
  await batch.save({
567
577
  sourceTable: TEST_TABLE,
@@ -578,14 +588,15 @@ bucket_definitions:
578
588
  clearBatchLimit: 20,
579
589
  moveBatchLimit: 10,
580
590
  moveBatchQueryLimit: 10,
581
- minBucketChanges: 1
591
+ minBucketChanges: 1,
592
+ minChangeRatio: 0
582
593
  });
583
594
 
584
595
  const checkpoint2 = result2!.flushed_op;
585
596
  // Check that the checksum was correctly updated with the clear operation after having a cached checksum
586
- const checksumAfter = await bucketStorage.getChecksums(checkpoint2, ['global[]']);
587
- expect(checksumAfter.get('global[]')).toMatchObject({
588
- bucket: 'global[]',
597
+ const checksumAfter = await bucketStorage.getChecksums(checkpoint2, bucketRequests(syncRules, ['global[]']));
598
+ expect(checksumAfter.get(bucketRequest(syncRules, 'global[]'))).toMatchObject({
599
+ bucket: bucketRequest(syncRules, 'global[]'),
589
600
  count: 1,
590
601
  checksum: -1481659821
591
602
  });
@@ -1,4 +1,4 @@
1
- import { storage } from '@powersync/service-core';
1
+ import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
2
2
  import { expect, test } from 'vitest';
3
3
  import * as test_utils from '../test-utils/test-utils-index.js';
4
4
 
@@ -15,14 +15,13 @@ import * as test_utils from '../test-utils/test-utils-index.js';
15
15
  export function registerDataStorageCheckpointTests(generateStorageFactory: storage.TestStorageFactory) {
16
16
  test('managed write checkpoints - checkpoint after write', async (context) => {
17
17
  await using factory = await generateStorageFactory();
18
- const r = await factory.configureSyncRules({
19
- content: `
18
+ const r = await factory.configureSyncRules(
19
+ updateSyncRulesFromYaml(`
20
20
  bucket_definitions:
21
21
  mybucket:
22
22
  data: []
23
- `,
24
- validate: false
25
- });
23
+ `)
24
+ );
26
25
  const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
27
26
 
28
27
  const abortController = new AbortController();
@@ -55,14 +54,13 @@ bucket_definitions:
55
54
 
56
55
  test('managed write checkpoints - write after checkpoint', async (context) => {
57
56
  await using factory = await generateStorageFactory();
58
- const r = await factory.configureSyncRules({
59
- content: `
57
+ const r = await factory.configureSyncRules(
58
+ updateSyncRulesFromYaml(`
60
59
  bucket_definitions:
61
60
  mybucket:
62
61
  data: []
63
- `,
64
- validate: false
65
- });
62
+ `)
63
+ );
66
64
  const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
67
65
 
68
66
  const abortController = new AbortController();
@@ -117,14 +115,13 @@ bucket_definitions:
117
115
 
118
116
  test('custom write checkpoints - checkpoint after write', async (context) => {
119
117
  await using factory = await generateStorageFactory();
120
- const r = await factory.configureSyncRules({
121
- content: `
118
+ const r = await factory.configureSyncRules(
119
+ updateSyncRulesFromYaml(`
122
120
  bucket_definitions:
123
121
  mybucket:
124
122
  data: []
125
- `,
126
- validate: false
127
- });
123
+ `)
124
+ );
128
125
  const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
129
126
  bucketStorage.setWriteCheckpointMode(storage.WriteCheckpointMode.CUSTOM);
130
127
 
@@ -157,14 +154,13 @@ bucket_definitions:
157
154
 
158
155
  test('custom write checkpoints - standalone checkpoint', async (context) => {
159
156
  await using factory = await generateStorageFactory();
160
- const r = await factory.configureSyncRules({
161
- content: `
157
+ const r = await factory.configureSyncRules(
158
+ updateSyncRulesFromYaml(`
162
159
  bucket_definitions:
163
160
  mybucket:
164
161
  data: []
165
- `,
166
- validate: false
167
- });
162
+ `)
163
+ );
168
164
  const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
169
165
  bucketStorage.setWriteCheckpointMode(storage.WriteCheckpointMode.CUSTOM);
170
166
 
@@ -200,14 +196,13 @@ bucket_definitions:
200
196
 
201
197
  test('custom write checkpoints - write after checkpoint', async (context) => {
202
198
  await using factory = await generateStorageFactory();
203
- const r = await factory.configureSyncRules({
204
- content: `
199
+ const r = await factory.configureSyncRules(
200
+ updateSyncRulesFromYaml(`
205
201
  bucket_definitions:
206
202
  mybucket:
207
203
  data: []
208
- `,
209
- validate: false
210
- });
204
+ `)
205
+ );
211
206
  const bucketStorage = factory.getInstance(r.persisted_sync_rules!);
212
207
  bucketStorage.setWriteCheckpointMode(storage.WriteCheckpointMode.CUSTOM);
213
208