Ironed out issues with creation endpoints and ID mappings.

editsong
Sander Vocke 5 years ago
parent 44ebc7b15d
commit 299342824c
  1. 2
      .vscode/launch.json
  2. 88
      server/test/integration/flows/ResourceFlow.ts
  3. 2
      server/test/reference_model/DBReferenceModel.ts

@ -10,7 +10,7 @@
"name": "Jasmine Tests with SQLite", "name": "Jasmine Tests with SQLite",
"env": { "env": {
"MUDBASE_DB_CONFIG": "{\"client\": \"sqlite3\", \"connection\": \":memory:\"}", "MUDBASE_DB_CONFIG": "{\"client\": \"sqlite3\", \"connection\": \":memory:\"}",
"TEST_RANDOM_SEED": "0.15844" "TEST_RANDOM_SEED": "0.61658"
}, },
"program": "${workspaceFolder}/server/node_modules/jasmine-ts/lib/index", "program": "${workspaceFolder}/server/node_modules/jasmine-ts/lib/index",
"args": [ "args": [

@ -113,7 +113,8 @@ function transformActionIDs(action: DBAction, mappings: IDMappings, rng: any) {
for (const [_, value] of Object.entries(mapping)) { for (const [_, value] of Object.entries(mapping)) {
highest = Math.max(value, highest); highest = Math.max(value, highest);
} }
return highest + 1 + Math.floor(rng() * 100); let r = highest + 1 + Math.floor(rng() * 100);
return r;
} }
switch (r.type) { switch (r.type) {
@ -124,6 +125,25 @@ function transformActionIDs(action: DBAction, mappings: IDMappings, rng: any) {
track.albumId = track.albumId ? doMap(track.albumId, mappings.albums) : null; track.albumId = track.albumId ? doMap(track.albumId, mappings.albums) : null;
break; break;
} }
case DBActionType.CreateArtist: {
let artist = r.payload as ArtistWithRefsWithId;
artist.tagIds.forEach((id: number) => doMap(id, mappings.tags));
artist.albumIds.forEach((id: number) => doMap(id, mappings.albums));
artist.trackIds.forEach((id: number) => doMap(id, mappings.tracks));
break;
}
case DBActionType.CreateAlbum: {
let album = r.payload as AlbumWithRefsWithId;
album.tagIds.forEach((id: number) => doMap(id, mappings.tags));
album.artistIds.forEach((id: number) => doMap(id, mappings.artists));
album.trackIds.forEach((id: number) => doMap(id, mappings.tracks));
break;
}
case DBActionType.CreateTag: {
let tag = r.payload as TagWithRefsWithId;
tag.parentId = tag.parentId ? doMap(tag.parentId, mappings.tags) : null;
break;
}
case DBActionType.DeleteTrack: { case DBActionType.DeleteTrack: {
r.payload = mappings.tracks[r.payload]; r.payload = mappings.tracks[r.payload];
break; break;
@ -156,6 +176,12 @@ describe('Randomized model-based DB back-end tests', () => {
let refState: ReferenceDatabase | undefined = undefined; let refState: ReferenceDatabase | undefined = undefined;
let realState: ReferenceDatabase | undefined = undefined; let realState: ReferenceDatabase | undefined = undefined;
// As we perform operations, the real DB and reference model may assign
// different new IDs to new objects. We need to maintain mappings in order
// to keep the operations consistent (e.g. when we make references to)
// existing objects along the way.
let idMappingsRefToReal: IDMappings | undefined = undefined;
try { try {
// Create a reference DB. // Create a reference DB.
let refDB: ReferenceDatabase = _.cloneDeep(sampleDB); let refDB: ReferenceDatabase = _.cloneDeep(sampleDB);
@ -166,19 +192,14 @@ describe('Randomized model-based DB back-end tests', () => {
await helpers.login(req, "someone@email.com", "password1A!", 200); await helpers.login(req, "someone@email.com", "password1A!", 200);
// Import the starting DB. // Import the starting DB.
let importResponse: DBImportResponse = (await helpers.importDB(req, refDB[1])).body; let importResponse: DBImportResponse = (await helpers.importDB(req, refDB[1])).body;
idMappingsRefToReal = importResponse;
// As we perform operations, the real DB and reference model may assign
// different new IDs to new objects. We need to maintain mappings in order
// to keep the operations consistent (e.g. when we make references to)
// existing objects along the way.
let idMappingsRefToReal: IDMappings = importResponse;
// Check that we are starting from an equal situation // Check that we are starting from an equal situation
refState = normalizeDB(refDB); refState = refDB;
realState = normalizeDB({ realState = {
[1]: (await helpers.getExport(req)).body, [1]: (await helpers.getExport(req)).body,
}); };
expect(realState).to.deep.equal(refState); expect(normalizeDB(realState)).to.deep.equal(normalizeDB(refState));
// Create a random number generator to use throughout the test. // Create a random number generator to use throughout the test.
let rng = seedrandom(seed); let rng = seedrandom(seed);
@ -262,10 +283,16 @@ describe('Randomized model-based DB back-end tests', () => {
let { response: realResponse, status: realStatus } = await applyRealDBAction(realAction, req); let { response: realResponse, status: realStatus } = await applyRealDBAction(realAction, req);
// If this was an object creation action, we need to update the mappings. // If this was an object creation action, we need to update the mappings.
if (refStatus === 200 && realStatus === 200) {
if (refAction.type === DBActionType.CreateTrack) { if (refAction.type === DBActionType.CreateTrack) {
let refId = refResponse.id; idMappingsRefToReal.tracks[refResponse.id] = realResponse.id;
let realId = realResponse.id; } else if (refAction.type === DBActionType.CreateAlbum) {
idMappingsRefToReal.tracks[refId] = realId; idMappingsRefToReal.albums[refResponse.id] = realResponse.id;
} else if (refAction.type === DBActionType.CreateArtist) {
idMappingsRefToReal.artists[refResponse.id] = realResponse.id;
} else if (refAction.type === DBActionType.CreateTag) {
idMappingsRefToReal.tags[refResponse.id] = realResponse.id;
}
} }
// Compare the response and status. // Compare the response and status.
@ -273,33 +300,42 @@ describe('Randomized model-based DB back-end tests', () => {
expect(normalizeResponse(realResponse)).to.deep.equal(normalizeResponse(refResponse)); expect(normalizeResponse(realResponse)).to.deep.equal(normalizeResponse(refResponse));
// Compare the database state after the action. // Compare the database state after the action.
refState = normalizeDB(refDB); let newRefState = refDB;
realState = normalizeDB({ let newRealState = {
[1]: (await helpers.getExport(req)).body, [1]: (await helpers.getExport(req)).body,
}); };
expect(realState).to.deep.equal(refState); expect(normalizeDB(newRealState)).to.deep.equal(normalizeDB(newRefState));
realState = newRealState;
refState = newRefState;
} }
} catch (e) { } catch (e) {
// When catching a comparison error, add and dump various states to files for debugging. // When catching a comparison error, add and dump various states to files for debugging.
e.actionTrace = actionTrace; e.actionTrace = actionTrace;
e.startingDB = normalizeDB(sampleDB); e.startingDB = normalizeDB(sampleDB);
e.lastRefDB = refState;
e.lastRealDB = realState;
e.testSeed = seed; e.testSeed = seed;
e.idMappingsRefToReal = idMappingsRefToReal;
if (e.actual && e.expected) { if (e.actual && e.expected) {
e.realDBDump = tmp.tmpNameSync(); let basename = tmp.tmpNameSync();
e.refDBDump = tmp.tmpNameSync(); e.actionTraceDump = basename + "_actiontrace";
e.actionTraceDump = tmp.tmpNameSync(); e.startingDBDump = basename + "_startingDB";
e.startingDBDump = tmp.tmpNameSync(); e.lastRefDBDump = basename + "_lastRefDB";
fs.writeFileSync(e.realDBDump, stringify(realState, { space: ' ' })); e.lastRealDBDump = basename + "_lastRealDB";
fs.writeFileSync(e.refDBDump, stringify(refState, { space: ' ' })); e.idMappingsRefToRealDump = basename + "_idMappings";
fs.writeFileSync(e.actionTraceDump, stringify(e.actionTrace, { space: ' ' })); fs.writeFileSync(e.actionTraceDump, stringify(e.actionTrace, { space: ' ' }));
fs.writeFileSync(e.startingDBDump, stringify(e.startingDB, { space: ' ' })); fs.writeFileSync(e.startingDBDump, stringify(e.startingDB, { space: ' ' }));
fs.writeFileSync(e.lastRefDBDump, stringify(e.lastRefDB, { space: ' ' }));
fs.writeFileSync(e.lastRealDBDump, stringify(e.lastRealDB, { space: ' ' }));
fs.writeFileSync(e.idMappingsRefToRealDump, stringify(e.idMappingsRefToReal, { space: ' ' }));
console.log( console.log(
"A comparison error occurred. Wrote compared values to temporary files for debugging:\n" "A comparison error occurred. Wrote compared values to temporary files for debugging:\n"
+ ` actual: ${e.realDBDump}\n`
+ ` expected: ${e.refDBDump}\n`
+ ` DB action trace: ${e.actionTraceDump}\n` + ` DB action trace: ${e.actionTraceDump}\n`
+ ` Starting DB: ${e.startingDBDump}\n` + ` Starting DB: ${e.startingDBDump}\n`
+ ` Reference DB before last action: ${e.lastRefDBDump}\n`
+ ` Real DB before last action: ${e.lastRealDBDump}\n`
+ ` ID Mappings from ref to real DB: ${e.idMappingsRefToRealDump}\n`
+ ` TEST_RANDOM_SEED: ${seed}` + ` TEST_RANDOM_SEED: ${seed}`
); );
} }

@ -135,7 +135,7 @@ export function createTag(userId: number, tag: PostTagRequest, db: ReferenceData
userId, userId,
tag, tag,
'tags', 'tags',
[], [{ field: 'parentId', otherObjectType: 'tags' }],
[], [],
db db
); );

Loading…
Cancel
Save