Extra tests for SignalProtocolStore migration
This commit is contained in:
		
					parent
					
						
							
								ce1daef9f3
							
						
					
				
			
			
				commit
				
					
						039bd072ed
					
				
			
		
					 2 changed files with 635 additions and 24 deletions
				
			
		
							
								
								
									
										137
									
								
								ts/sql/Server.ts
									
										
									
									
									
								
							
							
						
						
									
										137
									
								
								ts/sql/Server.ts
									
										
									
									
									
								
							| 
						 | 
					@ -2125,6 +2125,36 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    .pluck();
 | 
					    .pluck();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const getConversationStats = db.prepare<Query>(
 | 
				
			||||||
 | 
					    `
 | 
				
			||||||
 | 
					      SELECT uuid, e164, active_at
 | 
				
			||||||
 | 
					      FROM
 | 
				
			||||||
 | 
					        conversations
 | 
				
			||||||
 | 
					      WHERE
 | 
				
			||||||
 | 
					        id = $conversationId
 | 
				
			||||||
 | 
					      `
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const compareConvoRecency = (a: string, b: string): number => {
 | 
				
			||||||
 | 
					    const aStats = getConversationStats.get({ conversationId: a });
 | 
				
			||||||
 | 
					    const bStats = getConversationStats.get({ conversationId: b });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const isAComplete = Boolean(aStats?.uuid && aStats?.e164);
 | 
				
			||||||
 | 
					    const isBComplete = Boolean(bStats?.uuid && bStats?.e164);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!isAComplete && !isBComplete) {
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!isAComplete) {
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!isBComplete) {
 | 
				
			||||||
 | 
					      return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return aStats.active_at - bStats.active_at;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const clearSessionsAndKeys = () => {
 | 
					  const clearSessionsAndKeys = () => {
 | 
				
			||||||
    // ts/background.ts will ask user to relink so all that matters here is
 | 
					    // ts/background.ts will ask user to relink so all that matters here is
 | 
				
			||||||
    // to maintain an invariant:
 | 
					    // to maintain an invariant:
 | 
				
			||||||
| 
						 | 
					@ -2196,20 +2226,7 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const prefixKeys = (ourUuid: string) => {
 | 
					  const prefixKeys = (ourUuid: string) => {
 | 
				
			||||||
    for (const table of ['signedPreKeys', 'preKeys']) {
 | 
					    for (const table of ['signedPreKeys', 'preKeys']) {
 | 
				
			||||||
      // Add numeric `keyId` field to keys
 | 
					      // Update id to include suffix, add `ourUuid` and `keyId` fields.
 | 
				
			||||||
      db.prepare<EmptyQuery>(
 | 
					 | 
				
			||||||
        `
 | 
					 | 
				
			||||||
        UPDATE ${table}
 | 
					 | 
				
			||||||
        SET
 | 
					 | 
				
			||||||
          json = json_insert(
 | 
					 | 
				
			||||||
            json,
 | 
					 | 
				
			||||||
            '$.keyId',
 | 
					 | 
				
			||||||
            json_extract(json, '$.id')
 | 
					 | 
				
			||||||
          )
 | 
					 | 
				
			||||||
        `
 | 
					 | 
				
			||||||
      ).run();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Update id to include suffix and add `ourUuid` field
 | 
					 | 
				
			||||||
      db.prepare<Query>(
 | 
					      db.prepare<Query>(
 | 
				
			||||||
        `
 | 
					        `
 | 
				
			||||||
        UPDATE ${table}
 | 
					        UPDATE ${table}
 | 
				
			||||||
| 
						 | 
					@ -2219,17 +2236,26 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
            json,
 | 
					            json,
 | 
				
			||||||
            '$.id',
 | 
					            '$.id',
 | 
				
			||||||
            $ourUuid || ':' || json_extract(json, '$.id'),
 | 
					            $ourUuid || ':' || json_extract(json, '$.id'),
 | 
				
			||||||
 | 
					            '$.keyId',
 | 
				
			||||||
 | 
					            json_extract(json, '$.id'),
 | 
				
			||||||
            '$.ourUuid',
 | 
					            '$.ourUuid',
 | 
				
			||||||
            $ourUuid
 | 
					            $ourUuid
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        `
 | 
					        `
 | 
				
			||||||
      ).run({ ourUuid });
 | 
					      ).run({ ourUuid });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const updateSenderKeys = (ourUuid: string) => {
 | 
				
			||||||
    const senderKeys: ReadonlyArray<{
 | 
					    const senderKeys: ReadonlyArray<{
 | 
				
			||||||
      id: string;
 | 
					      id: string;
 | 
				
			||||||
      senderId: string;
 | 
					      senderId: string;
 | 
				
			||||||
    }> = db.prepare<EmptyQuery>('SELECT id, senderId FROM senderKeys').all();
 | 
					      lastUpdatedDate: number;
 | 
				
			||||||
 | 
					    }> = db
 | 
				
			||||||
 | 
					      .prepare<EmptyQuery>(
 | 
				
			||||||
 | 
					        'SELECT id, senderId, lastUpdatedDate FROM senderKeys'
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					      .all();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log(`Updating ${senderKeys.length} sender keys`);
 | 
					    console.log(`Updating ${senderKeys.length} sender keys`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2248,9 +2274,18 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
      'DELETE FROM senderKeys WHERE id = $id'
 | 
					      'DELETE FROM senderKeys WHERE id = $id'
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const pastKeys = new Map<
 | 
				
			||||||
 | 
					      string,
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        conversationId: string;
 | 
				
			||||||
 | 
					        lastUpdatedDate: number;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    >();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let updated = 0;
 | 
					    let updated = 0;
 | 
				
			||||||
    let deleted = 0;
 | 
					    let deleted = 0;
 | 
				
			||||||
    for (const { id, senderId } of senderKeys) {
 | 
					    let skipped = 0;
 | 
				
			||||||
 | 
					    for (const { id, senderId, lastUpdatedDate } of senderKeys) {
 | 
				
			||||||
      const [conversationId] = Helpers.unencodeNumber(senderId);
 | 
					      const [conversationId] = Helpers.unencodeNumber(senderId);
 | 
				
			||||||
      const uuid = getConversationUuid.get({ conversationId });
 | 
					      const uuid = getConversationUuid.get({ conversationId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2260,17 +2295,40 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      updated += 1;
 | 
					      const newId = `${ourUuid}:${id.replace(conversationId, uuid)}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const existing = pastKeys.get(newId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // We are going to delete on of the keys anyway
 | 
				
			||||||
 | 
					      if (existing) {
 | 
				
			||||||
 | 
					        skipped += 1;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        updated += 1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const isOlder =
 | 
				
			||||||
 | 
					        existing &&
 | 
				
			||||||
 | 
					        (lastUpdatedDate < existing.lastUpdatedDate ||
 | 
				
			||||||
 | 
					          compareConvoRecency(conversationId, existing.conversationId) < 0);
 | 
				
			||||||
 | 
					      if (isOlder) {
 | 
				
			||||||
 | 
					        deleteSenderKey.run({ id });
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      } else if (existing) {
 | 
				
			||||||
 | 
					        deleteSenderKey.run({ id: newId });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      pastKeys.set(newId, { conversationId, lastUpdatedDate });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      updateSenderKey.run({
 | 
					      updateSenderKey.run({
 | 
				
			||||||
        id,
 | 
					        id,
 | 
				
			||||||
        newId: `${ourUuid}:${id.replace(conversationId, uuid)}`,
 | 
					        newId,
 | 
				
			||||||
        newSenderId: `${senderId.replace(conversationId, uuid)}`,
 | 
					        newSenderId: `${senderId.replace(conversationId, uuid)}`,
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log(
 | 
					    console.log(
 | 
				
			||||||
      `Updated ${senderKeys.length} sender keys: ` +
 | 
					      `Updated ${senderKeys.length} sender keys: ` +
 | 
				
			||||||
        `updated: ${updated}, deleted: ${deleted}`
 | 
					        `updated: ${updated}, deleted: ${deleted}, skipped: ${skipped}`
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2310,8 +2368,16 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
      'DELETE FROM sessions WHERE id = $id'
 | 
					      'DELETE FROM sessions WHERE id = $id'
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const pastSessions = new Map<
 | 
				
			||||||
 | 
					      string,
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        conversationId: string;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    >();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let updated = 0;
 | 
					    let updated = 0;
 | 
				
			||||||
    let deleted = 0;
 | 
					    let deleted = 0;
 | 
				
			||||||
 | 
					    let skipped = 0;
 | 
				
			||||||
    for (const { id, conversationId } of allSessions) {
 | 
					    for (const { id, conversationId } of allSessions) {
 | 
				
			||||||
      const uuid = getConversationUuid.get({ conversationId });
 | 
					      const uuid = getConversationUuid.get({ conversationId });
 | 
				
			||||||
      if (!uuid) {
 | 
					      if (!uuid) {
 | 
				
			||||||
| 
						 | 
					@ -2322,7 +2388,27 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const newId = `${ourUuid}:${id.replace(conversationId, uuid)}`;
 | 
					      const newId = `${ourUuid}:${id.replace(conversationId, uuid)}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      updated += 1;
 | 
					      const existing = pastSessions.get(newId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // We are going to delete on of the keys anyway
 | 
				
			||||||
 | 
					      if (existing) {
 | 
				
			||||||
 | 
					        skipped += 1;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        updated += 1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const isOlder =
 | 
				
			||||||
 | 
					        existing &&
 | 
				
			||||||
 | 
					        compareConvoRecency(conversationId, existing.conversationId) < 0;
 | 
				
			||||||
 | 
					      if (isOlder) {
 | 
				
			||||||
 | 
					        deleteSession.run({ id });
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      } else if (existing) {
 | 
				
			||||||
 | 
					        deleteSession.run({ id: newId });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      pastSessions.set(newId, { conversationId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      updateSession.run({
 | 
					      updateSession.run({
 | 
				
			||||||
        id,
 | 
					        id,
 | 
				
			||||||
        newId,
 | 
					        newId,
 | 
				
			||||||
| 
						 | 
					@ -2333,7 +2419,7 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log(
 | 
					    console.log(
 | 
				
			||||||
      `Updated ${allSessions.length} sessions: ` +
 | 
					      `Updated ${allSessions.length} sessions: ` +
 | 
				
			||||||
        `updated: ${updated}, deleted: ${deleted}`
 | 
					        `updated: ${updated}, deleted: ${deleted}, skipped: ${skipped}`
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2429,6 +2515,8 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    prefixKeys(ourUuid);
 | 
					    prefixKeys(ourUuid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    updateSenderKeys(ourUuid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    updateSessions(ourUuid);
 | 
					    updateSessions(ourUuid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    moveIdentityKeyToMap(ourUuid);
 | 
					    moveIdentityKeyToMap(ourUuid);
 | 
				
			||||||
| 
						 | 
					@ -2440,7 +2528,7 @@ function updateToSchemaVersion41(currentVersion: number, db: Database) {
 | 
				
			||||||
  console.log('updateToSchemaVersion41: success!');
 | 
					  console.log('updateToSchemaVersion41: success!');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const SCHEMA_VERSIONS = [
 | 
					export const SCHEMA_VERSIONS = [
 | 
				
			||||||
  updateToSchemaVersion1,
 | 
					  updateToSchemaVersion1,
 | 
				
			||||||
  updateToSchemaVersion2,
 | 
					  updateToSchemaVersion2,
 | 
				
			||||||
  updateToSchemaVersion3,
 | 
					  updateToSchemaVersion3,
 | 
				
			||||||
| 
						 | 
					@ -2484,7 +2572,7 @@ const SCHEMA_VERSIONS = [
 | 
				
			||||||
  updateToSchemaVersion41,
 | 
					  updateToSchemaVersion41,
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function updateSchema(db: Database): void {
 | 
					export function updateSchema(db: Database) {
 | 
				
			||||||
  const sqliteVersion = getSQLiteVersion(db);
 | 
					  const sqliteVersion = getSQLiteVersion(db);
 | 
				
			||||||
  const sqlcipherVersion = getSQLCipherVersion(db);
 | 
					  const sqlcipherVersion = getSQLCipherVersion(db);
 | 
				
			||||||
  const userVersion = getUserVersion(db);
 | 
					  const userVersion = getUserVersion(db);
 | 
				
			||||||
| 
						 | 
					@ -2502,7 +2590,8 @@ function updateSchema(db: Database): void {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (userVersion > maxUserVersion) {
 | 
					  if (userVersion > maxUserVersion) {
 | 
				
			||||||
    throw new Error(
 | 
					    throw new Error(
 | 
				
			||||||
      `SQL: User version is ${userVersion} but the expected maximum version is ${maxUserVersion}. Did you try to start an old version of Signal?`
 | 
					      `SQL: User version is ${userVersion} but the expected maximum version ` +
 | 
				
			||||||
 | 
					        `is ${maxUserVersion}. Did you try to start an old version of Signal?`
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										522
									
								
								ts/test-node/sql_migrations_test.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										522
									
								
								ts/test-node/sql_migrations_test.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,522 @@
 | 
				
			||||||
 | 
					// Copyright 2021 Signal Messenger, LLC
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: AGPL-3.0-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { assert } from 'chai';
 | 
				
			||||||
 | 
					import SQL, { Database } from 'better-sqlite3';
 | 
				
			||||||
 | 
					import { v4 as generateGuid } from 'uuid';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { SCHEMA_VERSIONS } from '../sql/Server';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const THEIR_UUID = generateGuid();
 | 
				
			||||||
 | 
					const THEIR_CONVO = generateGuid();
 | 
				
			||||||
 | 
					const ANOTHER_CONVO = generateGuid();
 | 
				
			||||||
 | 
					const THIRD_CONVO = generateGuid();
 | 
				
			||||||
 | 
					const OUR_UUID = generateGuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('SQL migrations test', () => {
 | 
				
			||||||
 | 
					  let db: Database;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const updateToVersion = (version: number) => {
 | 
				
			||||||
 | 
					    const startVersion = db.pragma('user_version', { simple: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const run of SCHEMA_VERSIONS) {
 | 
				
			||||||
 | 
					      run(startVersion, db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const currentVersion = db.pragma('user_version', { simple: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (currentVersion === version) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    throw new Error(`Migration to ${version} not found`);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const addOurUuid = () => {
 | 
				
			||||||
 | 
					    const value = {
 | 
				
			||||||
 | 
					      id: 'uuid_id',
 | 
				
			||||||
 | 
					      value: `${OUR_UUID}.1`,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    db.exec(
 | 
				
			||||||
 | 
					      `
 | 
				
			||||||
 | 
					      INSERT INTO items (id, json) VALUES
 | 
				
			||||||
 | 
					        ('uuid_id', '${JSON.stringify(value)}');
 | 
				
			||||||
 | 
					      `
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const parseItems = (
 | 
				
			||||||
 | 
					    items: ReadonlyArray<{ json: string }>
 | 
				
			||||||
 | 
					  ): Array<unknown> => {
 | 
				
			||||||
 | 
					    return items.map(item => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        ...item,
 | 
				
			||||||
 | 
					        json: JSON.parse(item.json),
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const insertSession = (
 | 
				
			||||||
 | 
					    conversationId: string,
 | 
				
			||||||
 | 
					    deviceId: number,
 | 
				
			||||||
 | 
					    data: Record<string, unknown> = {}
 | 
				
			||||||
 | 
					  ): void => {
 | 
				
			||||||
 | 
					    const id = `${conversationId}.${deviceId}`;
 | 
				
			||||||
 | 
					    db.prepare(
 | 
				
			||||||
 | 
					      `
 | 
				
			||||||
 | 
					        INSERT INTO sessions (id, conversationId, json)
 | 
				
			||||||
 | 
					        VALUES ($id, $conversationId, $json)
 | 
				
			||||||
 | 
					      `
 | 
				
			||||||
 | 
					    ).run({
 | 
				
			||||||
 | 
					      id,
 | 
				
			||||||
 | 
					      conversationId,
 | 
				
			||||||
 | 
					      json: JSON.stringify({
 | 
				
			||||||
 | 
					        ...data,
 | 
				
			||||||
 | 
					        id,
 | 
				
			||||||
 | 
					        conversationId,
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(() => {
 | 
				
			||||||
 | 
					    db = new SQL(':memory:');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  afterEach(() => {
 | 
				
			||||||
 | 
					    db.close();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('updateToSchemaVersion41', () => {
 | 
				
			||||||
 | 
					    it('clears sessions and keys if UUID is not available', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db.exec(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					        INSERT INTO senderKeys
 | 
				
			||||||
 | 
					          (id, senderId, distributionId, data, lastUpdatedDate)
 | 
				
			||||||
 | 
					          VALUES
 | 
				
			||||||
 | 
					          ('1', '1', '1', '1', 1);
 | 
				
			||||||
 | 
					        INSERT INTO sessions (id, conversationId, json) VALUES
 | 
				
			||||||
 | 
					          ('1', '1', '{}');
 | 
				
			||||||
 | 
					        INSERT INTO signedPreKeys (id, json) VALUES
 | 
				
			||||||
 | 
					          ('1', '{}');
 | 
				
			||||||
 | 
					        INSERT INTO preKeys (id, json) VALUES
 | 
				
			||||||
 | 
					          ('1', '{}');
 | 
				
			||||||
 | 
					        INSERT INTO items (id, json) VALUES
 | 
				
			||||||
 | 
					          ('identityKey', '{}'),
 | 
				
			||||||
 | 
					          ('registrationId', '{}');
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const senderKeyCount = db
 | 
				
			||||||
 | 
					        .prepare('SELECT COUNT(*) FROM senderKeys')
 | 
				
			||||||
 | 
					        .pluck();
 | 
				
			||||||
 | 
					      const sessionCount = db.prepare('SELECT COUNT(*) FROM sessions').pluck();
 | 
				
			||||||
 | 
					      const signedPreKeyCount = db
 | 
				
			||||||
 | 
					        .prepare('SELECT COUNT(*) FROM signedPreKeys')
 | 
				
			||||||
 | 
					        .pluck();
 | 
				
			||||||
 | 
					      const preKeyCount = db.prepare('SELECT COUNT(*) FROM preKeys').pluck();
 | 
				
			||||||
 | 
					      const itemCount = db.prepare('SELECT COUNT(*) FROM items').pluck();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.strictEqual(senderKeyCount.get(), 1);
 | 
				
			||||||
 | 
					      assert.strictEqual(sessionCount.get(), 1);
 | 
				
			||||||
 | 
					      assert.strictEqual(signedPreKeyCount.get(), 1);
 | 
				
			||||||
 | 
					      assert.strictEqual(preKeyCount.get(), 1);
 | 
				
			||||||
 | 
					      assert.strictEqual(itemCount.get(), 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.strictEqual(senderKeyCount.get(), 0);
 | 
				
			||||||
 | 
					      assert.strictEqual(sessionCount.get(), 0);
 | 
				
			||||||
 | 
					      assert.strictEqual(signedPreKeyCount.get(), 0);
 | 
				
			||||||
 | 
					      assert.strictEqual(preKeyCount.get(), 0);
 | 
				
			||||||
 | 
					      assert.strictEqual(itemCount.get(), 0);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('adds prefix to preKeys/signedPreKeys', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const signedKeyItem = { id: 1 };
 | 
				
			||||||
 | 
					      const preKeyItem = { id: 2 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db.exec(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					        INSERT INTO signedPreKeys (id, json) VALUES
 | 
				
			||||||
 | 
					          (1, '${JSON.stringify(signedKeyItem)}');
 | 
				
			||||||
 | 
					        INSERT INTO preKeys (id, json) VALUES
 | 
				
			||||||
 | 
					          (2, '${JSON.stringify(preKeyItem)}');
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
 | 
					        parseItems(db.prepare('SELECT * FROM signedPreKeys').all()),
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            id: `${OUR_UUID}:1`,
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: `${OUR_UUID}:1`,
 | 
				
			||||||
 | 
					              keyId: 1,
 | 
				
			||||||
 | 
					              ourUuid: OUR_UUID,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
 | 
					        parseItems(db.prepare('SELECT * FROM preKeys').all()),
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            id: `${OUR_UUID}:2`,
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: `${OUR_UUID}:2`,
 | 
				
			||||||
 | 
					              keyId: 2,
 | 
				
			||||||
 | 
					              ourUuid: OUR_UUID,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('migrates senderKeys', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db.exec(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					        INSERT INTO conversations (id, uuid) VALUES
 | 
				
			||||||
 | 
					          ('${THEIR_CONVO}', '${THEIR_UUID}');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        INSERT INTO senderKeys
 | 
				
			||||||
 | 
					          (id, senderId, distributionId, data, lastUpdatedDate)
 | 
				
			||||||
 | 
					          VALUES
 | 
				
			||||||
 | 
					          ('${THEIR_CONVO}.1--234', '${THEIR_CONVO}.1', '234', '1', 1);
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.deepStrictEqual(db.prepare('SELECT * FROM senderKeys').all(), [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          id: `${OUR_UUID}:${THEIR_UUID}.1--234`,
 | 
				
			||||||
 | 
					          distributionId: '234',
 | 
				
			||||||
 | 
					          data: '1',
 | 
				
			||||||
 | 
					          lastUpdatedDate: 1,
 | 
				
			||||||
 | 
					          senderId: `${THEIR_UUID}.1`,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      ]);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('removes senderKeys that do not have conversation uuid', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db.exec(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					        INSERT INTO conversations (id) VALUES
 | 
				
			||||||
 | 
					          ('${THEIR_CONVO}');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        INSERT INTO senderKeys
 | 
				
			||||||
 | 
					          (id, senderId, distributionId, data, lastUpdatedDate)
 | 
				
			||||||
 | 
					          VALUES
 | 
				
			||||||
 | 
					          ('${THEIR_CONVO}.1--234', '${THEIR_CONVO}.1', '234', '1', 1),
 | 
				
			||||||
 | 
					          ('${ANOTHER_CONVO}.1--234', '${ANOTHER_CONVO}.1', '234', '1', 1);
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.strictEqual(
 | 
				
			||||||
 | 
					        db.prepare('SELECT COUNT(*) FROM senderKeys').pluck().get(),
 | 
				
			||||||
 | 
					        0
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('correctly merges senderKeys for conflicting conversations', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const fullA = generateGuid();
 | 
				
			||||||
 | 
					      const fullB = generateGuid();
 | 
				
			||||||
 | 
					      const fullC = generateGuid();
 | 
				
			||||||
 | 
					      const partial = generateGuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // When merging two keys for different conversations with the same uuid
 | 
				
			||||||
 | 
					      // only the most recent key would be kept in the database. We prefer keys
 | 
				
			||||||
 | 
					      // with either:
 | 
				
			||||||
 | 
					      //
 | 
				
			||||||
 | 
					      // 1. more recent lastUpdatedDate column
 | 
				
			||||||
 | 
					      // 2. conversation with both e164 and uuid
 | 
				
			||||||
 | 
					      // 3. conversation with more recent active_at
 | 
				
			||||||
 | 
					      db.exec(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					        INSERT INTO conversations (id, uuid, e164, active_at) VALUES
 | 
				
			||||||
 | 
					          ('${fullA}', '${THEIR_UUID}', '+12125555555', 1),
 | 
				
			||||||
 | 
					          ('${fullB}', '${THEIR_UUID}', '+12125555555', 2),
 | 
				
			||||||
 | 
					          ('${fullC}', '${THEIR_UUID}', '+12125555555', 3),
 | 
				
			||||||
 | 
					          ('${partial}', '${THEIR_UUID}', NULL, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        INSERT INTO senderKeys
 | 
				
			||||||
 | 
					          (id, senderId, distributionId, data, lastUpdatedDate)
 | 
				
			||||||
 | 
					        VALUES
 | 
				
			||||||
 | 
					          ('${fullA}.1--234', '${fullA}.1', 'fullA', '1', 1),
 | 
				
			||||||
 | 
					          ('${fullC}.1--234', '${fullC}.1', 'fullC', '2', 2),
 | 
				
			||||||
 | 
					          ('${fullB}.1--234', '${fullB}.1', 'fullB', '3', 2),
 | 
				
			||||||
 | 
					          ('${partial}.1--234', '${partial}.1', 'partial', '4', 2);
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.deepStrictEqual(db.prepare('SELECT * FROM senderKeys').all(), [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          id: `${OUR_UUID}:${THEIR_UUID}.1--234`,
 | 
				
			||||||
 | 
					          senderId: `${THEIR_UUID}.1`,
 | 
				
			||||||
 | 
					          distributionId: 'fullC',
 | 
				
			||||||
 | 
					          lastUpdatedDate: 2,
 | 
				
			||||||
 | 
					          data: '2',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      ]);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('migrates sessions', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db.exec(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					        INSERT INTO conversations (id, uuid) VALUES
 | 
				
			||||||
 | 
					          ('${THEIR_CONVO}', '${THEIR_UUID}');
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      insertSession(THEIR_CONVO, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
 | 
					        parseItems(db.prepare('SELECT * FROM sessions').all()),
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            conversationId: THEIR_CONVO,
 | 
				
			||||||
 | 
					            id: `${OUR_UUID}:${THEIR_UUID}.1`,
 | 
				
			||||||
 | 
					            uuid: THEIR_UUID,
 | 
				
			||||||
 | 
					            ourUuid: OUR_UUID,
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: `${OUR_UUID}:${THEIR_UUID}.1`,
 | 
				
			||||||
 | 
					              conversationId: THEIR_CONVO,
 | 
				
			||||||
 | 
					              uuid: THEIR_UUID,
 | 
				
			||||||
 | 
					              ourUuid: OUR_UUID,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('removes sessions that do not have conversation id', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      insertSession(THEIR_CONVO, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.strictEqual(
 | 
				
			||||||
 | 
					        db.prepare('SELECT COUNT(*) FROM sessions').pluck().get(),
 | 
				
			||||||
 | 
					        0
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('removes sessions that do not have conversation uuid', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db.exec(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					        INSERT INTO conversations (id) VALUES ('${THEIR_CONVO}');
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      insertSession(THEIR_CONVO, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.strictEqual(
 | 
				
			||||||
 | 
					        db.prepare('SELECT COUNT(*) FROM sessions').pluck().get(),
 | 
				
			||||||
 | 
					        0
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('correctly merges sessions for conflicting conversations', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const fullA = generateGuid();
 | 
				
			||||||
 | 
					      const fullB = generateGuid();
 | 
				
			||||||
 | 
					      const partial = generateGuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Similar merging logic to senderkeys above. We prefer sessions with
 | 
				
			||||||
 | 
					      // either:
 | 
				
			||||||
 | 
					      //
 | 
				
			||||||
 | 
					      // 1. conversation with both e164 and uuid
 | 
				
			||||||
 | 
					      // 2. conversation with more recent active_at
 | 
				
			||||||
 | 
					      db.exec(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					        INSERT INTO conversations (id, uuid, e164, active_at) VALUES
 | 
				
			||||||
 | 
					          ('${fullA}', '${THEIR_UUID}', '+12125555555', 1),
 | 
				
			||||||
 | 
					          ('${fullB}', '${THEIR_UUID}', '+12125555555', 2),
 | 
				
			||||||
 | 
					          ('${partial}', '${THEIR_UUID}', NULL, 3);
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      insertSession(fullA, 1, { name: 'A' });
 | 
				
			||||||
 | 
					      insertSession(fullB, 1, { name: 'B' });
 | 
				
			||||||
 | 
					      insertSession(partial, 1, { name: 'C' });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
 | 
					        parseItems(db.prepare('SELECT * FROM sessions').all()),
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            id: `${OUR_UUID}:${THEIR_UUID}.1`,
 | 
				
			||||||
 | 
					            conversationId: fullB,
 | 
				
			||||||
 | 
					            ourUuid: OUR_UUID,
 | 
				
			||||||
 | 
					            uuid: THEIR_UUID,
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: `${OUR_UUID}:${THEIR_UUID}.1`,
 | 
				
			||||||
 | 
					              conversationId: fullB,
 | 
				
			||||||
 | 
					              ourUuid: OUR_UUID,
 | 
				
			||||||
 | 
					              uuid: THEIR_UUID,
 | 
				
			||||||
 | 
					              name: 'B',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('moves identity key and registration id into a map', () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const items = [
 | 
				
			||||||
 | 
					        { id: 'identityKey', value: 'secret' },
 | 
				
			||||||
 | 
					        { id: 'registrationId', value: 42 },
 | 
				
			||||||
 | 
					      ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (const item of items) {
 | 
				
			||||||
 | 
					        db.prepare(
 | 
				
			||||||
 | 
					          `
 | 
				
			||||||
 | 
					          INSERT INTO items (id, json) VALUES ($id, $json);
 | 
				
			||||||
 | 
					          `
 | 
				
			||||||
 | 
					        ).run({
 | 
				
			||||||
 | 
					          id: item.id,
 | 
				
			||||||
 | 
					          json: JSON.stringify(item),
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
 | 
					        parseItems(db.prepare('SELECT * FROM items ORDER BY id').all()),
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            id: 'identityKeyMap',
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: 'identityKeyMap',
 | 
				
			||||||
 | 
					              value: { [OUR_UUID]: 'secret' },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            id: 'registrationIdMap',
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: 'registrationIdMap',
 | 
				
			||||||
 | 
					              value: { [OUR_UUID]: 42 },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            id: 'uuid_id',
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: 'uuid_id',
 | 
				
			||||||
 | 
					              value: `${OUR_UUID}.1`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it("migrates other users' identity keys", () => {
 | 
				
			||||||
 | 
					      updateToVersion(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      addOurUuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db.exec(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					        INSERT INTO conversations (id, uuid) VALUES
 | 
				
			||||||
 | 
					          ('${THEIR_CONVO}', '${THEIR_UUID}'),
 | 
				
			||||||
 | 
					          ('${ANOTHER_CONVO}', NULL);
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const identityKeys = [
 | 
				
			||||||
 | 
					        { id: THEIR_CONVO },
 | 
				
			||||||
 | 
					        { id: ANOTHER_CONVO },
 | 
				
			||||||
 | 
					        { id: THIRD_CONVO },
 | 
				
			||||||
 | 
					      ];
 | 
				
			||||||
 | 
					      for (const key of identityKeys) {
 | 
				
			||||||
 | 
					        db.prepare(
 | 
				
			||||||
 | 
					          `
 | 
				
			||||||
 | 
					            INSERT INTO identityKeys (id, json) VALUES ($id, $json);
 | 
				
			||||||
 | 
					          `
 | 
				
			||||||
 | 
					        ).run({
 | 
				
			||||||
 | 
					          id: key.id,
 | 
				
			||||||
 | 
					          json: JSON.stringify(key),
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      updateToVersion(41);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
 | 
					        parseItems(db.prepare('SELECT * FROM identityKeys ORDER BY id').all()),
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            id: THEIR_UUID,
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: THEIR_UUID,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            id: `conversation:${ANOTHER_CONVO}`,
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: `conversation:${ANOTHER_CONVO}`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            id: `conversation:${THIRD_CONVO}`,
 | 
				
			||||||
 | 
					            json: {
 | 
				
			||||||
 | 
					              id: `conversation:${THIRD_CONVO}`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ].sort((a, b) => {
 | 
				
			||||||
 | 
					          if (a.id === b.id) {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          if (a.id < b.id) {
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          return 1;
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue