@powersync/service-core-tests 0.14.0 → 0.15.0

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 (35) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/test-utils/general-utils.d.ts +9 -2
  3. package/dist/test-utils/general-utils.js +26 -2
  4. package/dist/test-utils/general-utils.js.map +1 -1
  5. package/dist/tests/register-compacting-tests.d.ts +1 -1
  6. package/dist/tests/register-compacting-tests.js +122 -68
  7. package/dist/tests/register-compacting-tests.js.map +1 -1
  8. package/dist/tests/register-data-storage-checkpoint-tests.d.ts +1 -1
  9. package/dist/tests/register-data-storage-checkpoint-tests.js +38 -6
  10. package/dist/tests/register-data-storage-checkpoint-tests.js.map +1 -1
  11. package/dist/tests/register-data-storage-data-tests.d.ts +2 -2
  12. package/dist/tests/register-data-storage-data-tests.js +666 -142
  13. package/dist/tests/register-data-storage-data-tests.js.map +1 -1
  14. package/dist/tests/register-data-storage-parameter-tests.d.ts +1 -1
  15. package/dist/tests/register-data-storage-parameter-tests.js +60 -33
  16. package/dist/tests/register-data-storage-parameter-tests.js.map +1 -1
  17. package/dist/tests/register-parameter-compacting-tests.d.ts +1 -1
  18. package/dist/tests/register-parameter-compacting-tests.js +8 -4
  19. package/dist/tests/register-parameter-compacting-tests.js.map +1 -1
  20. package/dist/tests/register-sync-tests.d.ts +2 -1
  21. package/dist/tests/register-sync-tests.js +40 -18
  22. package/dist/tests/register-sync-tests.js.map +1 -1
  23. package/dist/tests/util.d.ts +5 -4
  24. package/dist/tests/util.js +27 -12
  25. package/dist/tests/util.js.map +1 -1
  26. package/package.json +3 -3
  27. package/src/test-utils/general-utils.ts +41 -3
  28. package/src/tests/register-compacting-tests.ts +127 -82
  29. package/src/tests/register-data-storage-checkpoint-tests.ts +64 -11
  30. package/src/tests/register-data-storage-data-tests.ts +640 -52
  31. package/src/tests/register-data-storage-parameter-tests.ts +101 -47
  32. package/src/tests/register-parameter-compacting-tests.ts +9 -4
  33. package/src/tests/register-sync-tests.ts +45 -19
  34. package/src/tests/util.ts +46 -17
  35. package/tsconfig.tsbuildinfo +1 -1
@@ -14,14 +14,11 @@ import * as timers from 'timers/promises';
14
14
  import { fileURLToPath } from 'url';
15
15
  import { expect, test } from 'vitest';
16
16
  import * as test_utils from '../test-utils/test-utils-index.js';
17
- import { METRICS_HELPER } from '../test-utils/test-utils-index.js';
18
- import { bucketRequest } from './util.js';
17
+ import { bucketRequest, METRICS_HELPER } from '../test-utils/test-utils-index.js';
19
18
 
20
19
  const __filename = fileURLToPath(import.meta.url);
21
20
  const __dirname = path.dirname(__filename);
22
21
 
23
- const TEST_TABLE = test_utils.makeTestTable('test', ['id']);
24
-
25
22
  const BASIC_SYNC_RULES = `
26
23
  bucket_definitions:
27
24
  mybucket:
@@ -39,7 +36,15 @@ export const SYNC_SNAPSHOT_PATH = path.resolve(__dirname, '../__snapshots/sync.t
39
36
  * });
40
37
  * ```
41
38
  */
42
- export function registerSyncTests(factory: storage.TestStorageFactory, options: { storageVersion?: number } = {}) {
39
+ export function registerSyncTests(
40
+ configOrFactory: storage.TestStorageConfig | storage.TestStorageFactory,
41
+ options: { storageVersion?: number; tableIdStrings?: boolean } = {}
42
+ ) {
43
+ const config: storage.TestStorageConfig =
44
+ typeof configOrFactory == 'function'
45
+ ? { factory: configOrFactory, tableIdStrings: options.tableIdStrings ?? true }
46
+ : configOrFactory;
47
+ const factory = config.factory;
43
48
  createCoreAPIMetrics(METRICS_HELPER.metricsEngine);
44
49
  const tracker = new sync.RequestTracker(METRICS_HELPER.metricsEngine);
45
50
  const syncContext = new sync.SyncContext({
@@ -48,6 +53,7 @@ export function registerSyncTests(factory: storage.TestStorageFactory, options:
48
53
  maxDataFetchConcurrency: 2
49
54
  });
50
55
 
56
+ const TEST_TABLE = test_utils.makeTestTable('test', ['id'], config);
51
57
  const updateSyncRules = (bucketStorageFactory: storage.BucketStorageFactory, updateOptions: { content: string }) => {
52
58
  return bucketStorageFactory.updateSyncRules(
53
59
  updateSyncRulesFromYaml(updateOptions.content, {
@@ -66,7 +72,9 @@ export function registerSyncTests(factory: storage.TestStorageFactory, options:
66
72
 
67
73
  const bucketStorage = f.getInstance(syncRules);
68
74
 
69
- const result = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
75
+ await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
76
+ await batch.markAllSnapshotDone('0/1');
77
+
70
78
  await batch.save({
71
79
  sourceTable: TEST_TABLE,
72
80
  tag: storage.SaveOperationTag.INSERT,
@@ -127,7 +135,8 @@ bucket_definitions:
127
135
 
128
136
  const bucketStorage = f.getInstance(syncRules);
129
137
 
130
- const result = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
138
+ await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
139
+ await batch.markAllSnapshotDone('0/1');
131
140
  await batch.save({
132
141
  sourceTable: TEST_TABLE,
133
142
  tag: storage.SaveOperationTag.INSERT,
@@ -189,6 +198,7 @@ bucket_definitions:
189
198
  const bucketStorage = f.getInstance(syncRules);
190
199
 
191
200
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
201
+ await batch.markAllSnapshotDone('0/1');
192
202
  // Initial data: Add one priority row and 10k low-priority rows.
193
203
  await batch.save({
194
204
  sourceTable: TEST_TABLE,
@@ -299,6 +309,7 @@ bucket_definitions:
299
309
  const bucketStorage = f.getInstance(syncRules);
300
310
 
301
311
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
312
+ await batch.markAllSnapshotDone('0/1');
302
313
  // Initial data: Add one priority row and 10k low-priority rows.
303
314
  await batch.save({
304
315
  sourceTable: TEST_TABLE,
@@ -440,6 +451,7 @@ bucket_definitions:
440
451
  const bucketStorage = f.getInstance(syncRules);
441
452
 
442
453
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
454
+ await batch.markAllSnapshotDone('0/1');
443
455
  // Initial data: Add one priority row and 10k low-priority rows.
444
456
  await batch.save({
445
457
  sourceTable: TEST_TABLE,
@@ -569,6 +581,7 @@ bucket_definitions:
569
581
  const bucketStorage = f.getInstance(syncRules);
570
582
 
571
583
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
584
+ await batch.markAllSnapshotDone('0/1');
572
585
  await batch.save({
573
586
  sourceTable: TEST_TABLE,
574
587
  tag: storage.SaveOperationTag.INSERT,
@@ -633,6 +646,7 @@ bucket_definitions:
633
646
  const bucketStorage = await f.getInstance(syncRules);
634
647
 
635
648
  const result = await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
649
+ await batch.markAllSnapshotDone('0/1');
636
650
  await batch.save({
637
651
  sourceTable: TEST_TABLE,
638
652
  tag: storage.SaveOperationTag.INSERT,
@@ -704,6 +718,7 @@ bucket_definitions:
704
718
  const bucketStorage = await f.getInstance(syncRules);
705
719
  // Activate
706
720
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
721
+ await batch.markAllSnapshotDone('0/0');
707
722
  await batch.keepalive('0/0');
708
723
  });
709
724
 
@@ -772,12 +787,13 @@ bucket_definitions:
772
787
  `
773
788
  });
774
789
 
775
- const usersTable = test_utils.makeTestTable('users', ['id']);
776
- const listsTable = test_utils.makeTestTable('lists', ['id']);
790
+ const usersTable = test_utils.makeTestTable('users', ['id'], config);
791
+ const listsTable = test_utils.makeTestTable('lists', ['id'], config);
777
792
 
778
793
  const bucketStorage = await f.getInstance(syncRules);
779
794
  // Activate
780
795
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
796
+ await batch.markAllSnapshotDone('0/0');
781
797
  await batch.keepalive('0/0');
782
798
  });
783
799
 
@@ -819,10 +835,11 @@ bucket_definitions:
819
835
  await batch.commit('0/1');
820
836
  });
821
837
 
838
+ const { bucket } = bucketRequest(syncRules, 'by_user["user1"]');
822
839
  const checkpoint2 = await getCheckpointLines(iter);
823
840
  expect(
824
841
  (checkpoint2[0] as StreamingSyncCheckpointDiff).checkpoint_diff?.updated_buckets?.map((b) => b.bucket)
825
- ).toEqual([bucketRequest(syncRules, 'by_user["user1"]')]);
842
+ ).toEqual([bucket]);
826
843
  expect(checkpoint2).toMatchSnapshot();
827
844
  });
828
845
 
@@ -838,12 +855,13 @@ bucket_definitions:
838
855
  `
839
856
  });
840
857
 
841
- const usersTable = test_utils.makeTestTable('users', ['id']);
842
- const listsTable = test_utils.makeTestTable('lists', ['id']);
858
+ const usersTable = test_utils.makeTestTable('users', ['id'], config);
859
+ const listsTable = test_utils.makeTestTable('lists', ['id'], config);
843
860
 
844
861
  const bucketStorage = await f.getInstance(syncRules);
845
862
 
846
863
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
864
+ await batch.markAllSnapshotDone('0/1');
847
865
  await batch.save({
848
866
  sourceTable: usersTable,
849
867
  tag: storage.SaveOperationTag.INSERT,
@@ -875,10 +893,9 @@ bucket_definitions:
875
893
  iter.return?.();
876
894
  });
877
895
 
896
+ const { bucket } = bucketRequest(syncRules, 'by_user["user1"]');
878
897
  const checkpoint1 = await getCheckpointLines(iter);
879
- expect((checkpoint1[0] as StreamingSyncCheckpoint).checkpoint?.buckets?.map((b) => b.bucket)).toEqual([
880
- bucketRequest(syncRules, 'by_user["user1"]')
881
- ]);
898
+ expect((checkpoint1[0] as StreamingSyncCheckpoint).checkpoint?.buckets?.map((b) => b.bucket)).toEqual([bucket]);
882
899
  expect(checkpoint1).toMatchSnapshot();
883
900
 
884
901
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
@@ -899,7 +916,7 @@ bucket_definitions:
899
916
  const checkpoint2 = await getCheckpointLines(iter);
900
917
  expect(
901
918
  (checkpoint2[0] as StreamingSyncCheckpointDiff).checkpoint_diff?.updated_buckets?.map((b) => b.bucket)
902
- ).toEqual([bucketRequest(syncRules, 'by_user["user1"]')]);
919
+ ).toEqual([bucket]);
903
920
  expect(checkpoint2).toMatchSnapshot();
904
921
  });
905
922
 
@@ -915,12 +932,13 @@ bucket_definitions:
915
932
  `
916
933
  });
917
934
 
918
- const usersTable = test_utils.makeTestTable('users', ['id']);
919
- const listsTable = test_utils.makeTestTable('lists', ['id']);
935
+ const usersTable = test_utils.makeTestTable('users', ['id'], config);
936
+ const listsTable = test_utils.makeTestTable('lists', ['id'], config);
920
937
 
921
938
  const bucketStorage = await f.getInstance(syncRules);
922
939
  // Activate
923
940
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
941
+ await batch.markAllSnapshotDone('0/0');
924
942
  await batch.keepalive('0/0');
925
943
  });
926
944
 
@@ -946,6 +964,7 @@ bucket_definitions:
946
964
  expect(await getCheckpointLines(iter)).toMatchSnapshot();
947
965
 
948
966
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
967
+ await batch.markAllSnapshotDone('0/1');
949
968
  await batch.save({
950
969
  sourceTable: listsTable,
951
970
  tag: storage.SaveOperationTag.INSERT,
@@ -970,10 +989,11 @@ bucket_definitions:
970
989
  await batch.commit('0/1');
971
990
  });
972
991
 
992
+ const { bucket } = bucketRequest(syncRules, 'by_user["user1"]');
973
993
  const checkpoint2 = await getCheckpointLines(iter);
974
994
  expect(
975
995
  (checkpoint2[0] as StreamingSyncCheckpointDiff).checkpoint_diff?.updated_buckets?.map((b) => b.bucket)
976
- ).toEqual([bucketRequest(syncRules, 'by_user["user1"]')]);
996
+ ).toEqual([bucket]);
977
997
  expect(checkpoint2).toMatchSnapshot();
978
998
  });
979
999
 
@@ -987,6 +1007,7 @@ bucket_definitions:
987
1007
  const bucketStorage = await f.getInstance(syncRules);
988
1008
  // Activate
989
1009
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
1010
+ await batch.markAllSnapshotDone('0/0');
990
1011
  await batch.keepalive('0/0');
991
1012
  });
992
1013
 
@@ -1032,6 +1053,7 @@ bucket_definitions:
1032
1053
  const bucketStorage = await f.getInstance(syncRules);
1033
1054
 
1034
1055
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
1056
+ await batch.markAllSnapshotDone('0/1');
1035
1057
  await batch.save({
1036
1058
  sourceTable: TEST_TABLE,
1037
1059
  tag: storage.SaveOperationTag.INSERT,
@@ -1087,6 +1109,7 @@ bucket_definitions:
1087
1109
  // This invalidates the checkpoint we've received above.
1088
1110
 
1089
1111
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
1112
+ await batch.markAllSnapshotDone('0/1');
1090
1113
  await batch.save({
1091
1114
  sourceTable: TEST_TABLE,
1092
1115
  tag: storage.SaveOperationTag.UPDATE,
@@ -1175,6 +1198,7 @@ bucket_definitions:
1175
1198
  const bucketStorage = f.getInstance(syncRules);
1176
1199
 
1177
1200
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
1201
+ await batch.markAllSnapshotDone('0/1');
1178
1202
  // <= the managed write checkpoint LSN below
1179
1203
  await batch.commit('0/1');
1180
1204
  });
@@ -1210,6 +1234,7 @@ bucket_definitions:
1210
1234
  });
1211
1235
 
1212
1236
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
1237
+ await batch.markAllSnapshotDone('0/1');
1213
1238
  // must be >= the managed write checkpoint LSN
1214
1239
  await batch.commit('1/0');
1215
1240
  });
@@ -1245,6 +1270,7 @@ config:
1245
1270
  const bucketStorage = f.getInstance(syncRules);
1246
1271
 
1247
1272
  await bucketStorage.startBatch(test_utils.BATCH_OPTIONS, async (batch) => {
1273
+ await batch.markAllSnapshotDone('0/1');
1248
1274
  await batch.save({
1249
1275
  sourceTable: TEST_TABLE,
1250
1276
  tag: storage.SaveOperationTag.INSERT,
package/src/tests/util.ts CHANGED
@@ -1,24 +1,53 @@
1
1
  import { storage } from '@powersync/service-core';
2
- import { test_utils } from '../index.js';
2
+ import {
3
+ ParameterIndexLookupCreator,
4
+ SourceTableInterface,
5
+ SqliteRow,
6
+ TablePattern
7
+ } from '@powersync/service-sync-rules';
8
+ import { ParameterLookupScope } from '@powersync/service-sync-rules/src/HydrationState.js';
9
+ import { bucketRequest } from '../test-utils/general-utils.js';
3
10
 
4
- export const TEST_TABLE = test_utils.makeTestTable('test', ['id']);
5
-
6
- export function bucketRequest(syncRules: storage.PersistedSyncRulesContent, bucketName: string): string {
7
- if (/^\d+#/.test(bucketName)) {
8
- return bucketName;
9
- }
10
-
11
- const versionedBuckets = storage.STORAGE_VERSION_CONFIG[syncRules.storageVersion]?.versionedBuckets ?? false;
12
- return versionedBuckets ? `${syncRules.id}#${bucketName}` : bucketName;
11
+ export function bucketRequestMap(
12
+ syncRules: storage.PersistedSyncRulesContent,
13
+ buckets: Iterable<readonly [string, bigint]>
14
+ ): storage.BucketDataRequest[] {
15
+ return Array.from(buckets, ([bucketName, opId]) => bucketRequest(syncRules, bucketName, opId));
13
16
  }
14
17
 
15
- export function bucketRequests(syncRules: storage.PersistedSyncRulesContent, bucketNames: string[]): string[] {
16
- return bucketNames.map((bucketName) => bucketRequest(syncRules, bucketName));
18
+ export function bucketRequests(
19
+ syncRules: storage.PersistedSyncRulesContent,
20
+ bucketNames: string[]
21
+ ): storage.BucketChecksumRequest[] {
22
+ return bucketNames.map((bucketName) => {
23
+ const request = bucketRequest(syncRules, bucketName, 0n);
24
+ return { bucket: request.bucket, source: request.source };
25
+ });
17
26
  }
18
27
 
19
- export function bucketRequestMap(
20
- syncRules: storage.PersistedSyncRulesContent,
21
- buckets: Iterable<readonly [string, bigint]>
22
- ): Map<string, bigint> {
23
- return new Map(Array.from(buckets, ([bucketName, opId]) => [bucketRequest(syncRules, bucketName), opId]));
28
+ const EMPTY_LOOKUP_SOURCE: ParameterIndexLookupCreator = {
29
+ get defaultLookupScope(): ParameterLookupScope {
30
+ return {
31
+ lookupName: 'lookup',
32
+ queryId: '0',
33
+ source: EMPTY_LOOKUP_SOURCE
34
+ };
35
+ },
36
+ getSourceTables(): Set<TablePattern> {
37
+ return new Set();
38
+ },
39
+ evaluateParameterRow(_sourceTable: SourceTableInterface, _row: SqliteRow) {
40
+ return [];
41
+ },
42
+ tableSyncsParameters(_table: SourceTableInterface): boolean {
43
+ return false;
44
+ }
45
+ };
46
+
47
+ export function parameterLookupScope(
48
+ lookupName: string,
49
+ queryId: string,
50
+ source: ParameterIndexLookupCreator = EMPTY_LOOKUP_SOURCE
51
+ ): ParameterLookupScope {
52
+ return { lookupName, queryId, source };
24
53
  }