Skip to content

Commit 9b22357

Browse files
committed
Add test.
1 parent 1adea54 commit 9b22357

File tree

4 files changed

+230
-11
lines changed

4 files changed

+230
-11
lines changed

packages/firestore/src/local/indexeddb_schema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { DbTimestampKey } from './indexeddb_sentinels';
3131
// TODO(indexing): Remove this constant
3232
const INDEXING_ENABLED = false;
3333

34-
export const INDEXING_SCHEMA_VERSION = 14;
34+
export const INDEXING_SCHEMA_VERSION = 15;
3535

3636
/**
3737
* Schema Version for the Web client:
@@ -57,7 +57,7 @@ export const INDEXING_SCHEMA_VERSION = 14;
5757
* 14. Add indexing support.
5858
*/
5959

60-
export const SCHEMA_VERSION = INDEXING_ENABLED ? INDEXING_SCHEMA_VERSION : 13;
60+
export const SCHEMA_VERSION = INDEXING_ENABLED ? INDEXING_SCHEMA_VERSION : 14;
6161

6262
/**
6363
* Wrapper class to store timestamps (seconds and nanos) in IndexedDb objects.

packages/firestore/src/local/indexeddb_schema_converter.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,11 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
249249
}
250250

251251
if (fromVersion < 14 && toVersion >= 14) {
252-
p = p
253-
.next(() => createFieldIndex(db))
254-
.next(() => this.runOverlayMigration(db, simpleDbTransaction));
252+
p = p.next(() => this.runOverlayMigration(db, simpleDbTransaction));
253+
}
254+
255+
if (fromVersion < 15 && toVersion >= 15) {
256+
p = p.next(() => createFieldIndex(db));
255257
}
256258

257259
return p;
@@ -477,6 +479,10 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
477479
DbMutationBatch
478480
>(DbMutationBatchStore);
479481

482+
const remoteDocumentCache = newIndexedDbRemoteDocumentCache(
483+
this.serializer
484+
);
485+
480486
const promises: Array<PersistencePromise<void>> = [];
481487
let userIds = new Set<string>();
482488

@@ -491,9 +497,6 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
491497
}
492498
userIds = userIds.add(userId);
493499
const user = new User(userId);
494-
const remoteDocumentCache = newIndexedDbRemoteDocumentCache(
495-
this.serializer
496-
);
497500
const documentOverlayCache = IndexedDbDocumentOverlayCache.forUser(
498501
this.serializer,
499502
user

packages/firestore/src/local/indexeddb_sentinels.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,9 @@ export const V13_STORES = [
407407
DbNamedQueryStore,
408408
DbDocumentOverlayStore
409409
];
410-
export const V14_STORES = [
411-
...V13_STORES,
410+
export const V14_STORES = V13_STORES;
411+
export const V15_STORES = [
412+
...V14_STORES,
412413
DbIndexConfigurationStore,
413414
DbIndexStateStore,
414415
DbIndexEntryStore
@@ -423,7 +424,9 @@ export const ALL_STORES = V12_STORES;
423424

424425
/** Returns the object stores for the provided schema. */
425426
export function getObjectStores(schemaVersion: number): string[] {
426-
if (schemaVersion === 14) {
427+
if (schemaVersion === 15) {
428+
return V15_STORES;
429+
} else if (schemaVersion === 14) {
427430
return V14_STORES;
428431
} else if (schemaVersion === 13) {
429432
return V13_STORES;

packages/firestore/test/unit/local/indexeddb_persistence.test.ts

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence';
3030
import {
3131
DbCollectionParent,
3232
DbDocumentMutation,
33+
DbDocumentOverlay,
3334
DbMutationBatch,
3435
DbMutationQueue,
3536
DbPrimaryClient,
@@ -52,6 +53,8 @@ import {
5253
DbDocumentMutationKey,
5354
DbDocumentMutationPlaceholder,
5455
DbDocumentMutationStore,
56+
DbDocumentOverlayKey,
57+
DbDocumentOverlayStore,
5558
DbMutationBatchKey,
5659
DbMutationBatchStore,
5760
DbMutationQueueKey,
@@ -81,6 +84,7 @@ import {
8184
import {
8285
fromDbTarget,
8386
LocalSerializer,
87+
toDbDocumentOverlayKey,
8488
toDbRemoteDocument,
8589
toDbTarget,
8690
toDbTimestamp,
@@ -92,6 +96,7 @@ import { ClientId } from '../../../src/local/shared_client_state';
9296
import { SimpleDb, SimpleDbTransaction } from '../../../src/local/simple_db';
9397
import { TargetData, TargetPurpose } from '../../../src/local/target_data';
9498
import { MutableDocument } from '../../../src/model/document';
99+
import { DocumentKey } from '../../../src/model/document_key';
95100
import { getWindow } from '../../../src/platform/dom';
96101
import { firestoreV1ApiClientInterfaces } from '../../../src/protos/firestore_proto_api';
97102
import {
@@ -1044,6 +1049,214 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => {
10441049
});
10451050
});
10461051

1052+
it('can upgrade from schema version 13 to 14 (overlay migration)', function (this: Context) {
1053+
// This test creates a database with schema version 13 that has three users,
1054+
// two of whom have local mutations.
1055+
const testWriteFoo = {
1056+
update: {
1057+
name: 'projects/test-project/databases/(default)/documents/docs/foo',
1058+
fields: {}
1059+
}
1060+
};
1061+
const testWriteBar = {
1062+
update: {
1063+
name: 'projects/test-project/databases/(default)/documents/docs/bar',
1064+
fields: {}
1065+
}
1066+
};
1067+
const testWriteBaz = {
1068+
update: {
1069+
name: 'projects/test-project/databases/(default)/documents/docs/baz',
1070+
fields: {}
1071+
}
1072+
};
1073+
const testWritePending = {
1074+
update: {
1075+
name: 'projects/test-project/databases/(default)/documents/docs/pending',
1076+
fields: {}
1077+
}
1078+
};
1079+
const testMutations: DbMutationBatch[] = [
1080+
{
1081+
userId: 'user1',
1082+
batchId: 1,
1083+
localWriteTimeMs: 1337,
1084+
baseMutations: undefined,
1085+
mutations: [testWriteFoo]
1086+
},
1087+
{
1088+
userId: 'user1',
1089+
batchId: 2,
1090+
localWriteTimeMs: 1337,
1091+
baseMutations: undefined,
1092+
mutations: [testWriteFoo]
1093+
},
1094+
{
1095+
userId: 'user2',
1096+
batchId: 3,
1097+
localWriteTimeMs: 1337,
1098+
baseMutations: undefined,
1099+
mutations: [testWriteBar, testWriteBaz]
1100+
},
1101+
{
1102+
userId: 'user2',
1103+
batchId: 4,
1104+
localWriteTimeMs: 1337,
1105+
baseMutations: undefined,
1106+
mutations: [testWritePending]
1107+
},
1108+
{
1109+
userId: 'user1',
1110+
batchId: 5,
1111+
localWriteTimeMs: 1337,
1112+
baseMutations: undefined,
1113+
mutations: [testWritePending]
1114+
}
1115+
];
1116+
1117+
return withDb(13, db => {
1118+
return db.runTransaction(
1119+
this.test!.fullTitle(),
1120+
'readwrite',
1121+
V13_STORES,
1122+
txn => {
1123+
const mutationBatchStore = txn.store<
1124+
DbMutationBatchKey,
1125+
DbMutationBatch
1126+
>(DbMutationBatchStore);
1127+
const documentMutationStore = txn.store<
1128+
DbDocumentMutationKey,
1129+
DbDocumentMutation
1130+
>(DbDocumentMutationStore);
1131+
const mutationQueuesStore = txn.store<
1132+
DbMutationQueueKey,
1133+
DbMutationQueue
1134+
>(DbMutationQueueStore);
1135+
// Manually populate the mutation queue and create all indicies.
1136+
return PersistencePromise.forEach(
1137+
testMutations,
1138+
(testMutation: DbMutationBatch) => {
1139+
return mutationBatchStore.put(testMutation).next(() => {
1140+
return PersistencePromise.forEach(
1141+
testMutation.mutations,
1142+
(write: firestoreV1ApiClientInterfaces.Write) => {
1143+
const indexKey = newDbDocumentMutationKey(
1144+
testMutation.userId,
1145+
path(write.update!.name!, 5),
1146+
testMutation.batchId
1147+
);
1148+
return documentMutationStore.put(
1149+
indexKey,
1150+
DbDocumentMutationPlaceholder
1151+
);
1152+
}
1153+
);
1154+
});
1155+
}
1156+
).next(() =>
1157+
// Populate the mutation queues' metadata
1158+
PersistencePromise.waitFor([
1159+
mutationQueuesStore.put({
1160+
userId: 'user1',
1161+
lastAcknowledgedBatchId: -1,
1162+
lastStreamToken: ''
1163+
}),
1164+
mutationQueuesStore.put({
1165+
userId: 'user2',
1166+
lastAcknowledgedBatchId: -1,
1167+
lastStreamToken: ''
1168+
}),
1169+
mutationQueuesStore.put({
1170+
userId: 'user3',
1171+
lastAcknowledgedBatchId: -1,
1172+
lastStreamToken: ''
1173+
})
1174+
])
1175+
);
1176+
}
1177+
);
1178+
}).then(() =>
1179+
withDb(14, (db, version) => {
1180+
expect(version).to.be.equal(14);
1181+
1182+
return db.runTransaction(
1183+
this.test!.fullTitle(),
1184+
'readwrite',
1185+
V14_STORES,
1186+
txn => {
1187+
const documentOverlayStore = txn.store<
1188+
DbDocumentOverlayKey,
1189+
DbDocumentOverlay
1190+
>(DbDocumentOverlayStore);
1191+
1192+
// We should have a total of 5 overlays:
1193+
// For user1: testWriteFoo, and testWritePending
1194+
// For user2: testWriteBar, testWriteBaz, and testWritePending
1195+
// For user3: NO OVERLAYS!
1196+
let p = documentOverlayStore.count().next(count => {
1197+
expect(count).to.equal(5);
1198+
});
1199+
p = p.next(() => {
1200+
const key = toDbDocumentOverlayKey(
1201+
'user1',
1202+
DocumentKey.fromPath('docs/foo')
1203+
);
1204+
return documentOverlayStore.get(key).next(overlay => {
1205+
expect(overlay).to.not.be.null;
1206+
expect(overlay!.overlayMutation).to.deep.equal(testWriteFoo);
1207+
});
1208+
});
1209+
p = p.next(() => {
1210+
const key = toDbDocumentOverlayKey(
1211+
'user1',
1212+
DocumentKey.fromPath('docs/pending')
1213+
);
1214+
return documentOverlayStore.get(key).next(overlay => {
1215+
expect(overlay).to.not.be.null;
1216+
expect(overlay!.overlayMutation).to.deep.equal(
1217+
testWritePending
1218+
);
1219+
});
1220+
});
1221+
p = p.next(() => {
1222+
const key = toDbDocumentOverlayKey(
1223+
'user2',
1224+
DocumentKey.fromPath('docs/bar')
1225+
);
1226+
return documentOverlayStore.get(key).next(overlay => {
1227+
expect(overlay).to.not.be.null;
1228+
expect(overlay!.overlayMutation).to.deep.equal(testWriteBar);
1229+
});
1230+
});
1231+
p = p.next(() => {
1232+
const key = toDbDocumentOverlayKey(
1233+
'user2',
1234+
DocumentKey.fromPath('docs/baz')
1235+
);
1236+
return documentOverlayStore.get(key).next(overlay => {
1237+
expect(overlay).to.not.be.null;
1238+
expect(overlay!.overlayMutation).to.deep.equal(testWriteBaz);
1239+
});
1240+
});
1241+
p = p.next(() => {
1242+
const key = toDbDocumentOverlayKey(
1243+
'user2',
1244+
DocumentKey.fromPath('docs/pending')
1245+
);
1246+
return documentOverlayStore.get(key).next(overlay => {
1247+
expect(overlay).to.not.be.null;
1248+
expect(overlay!.overlayMutation).to.deep.equal(
1249+
testWritePending
1250+
);
1251+
});
1252+
});
1253+
return p;
1254+
}
1255+
);
1256+
})
1257+
);
1258+
});
1259+
10471260
it('can upgrade from version 13 to 14', async () => {
10481261
await withDb(13, async () => {});
10491262
await withDb(14, async (db, version, objectStores) => {

0 commit comments

Comments
 (0)