Updates to backup infrastructure

This commit is contained in:
Scott Nonnenberg 2018-12-13 13:41:42 -08:00
parent 47f834cf5c
commit e4babdaef0
14 changed files with 599 additions and 710 deletions

View file

@ -1,10 +1,6 @@
/* global Signal: false */
/* global Whisper: false */
/* global assert: false */
/* global textsecure: false */
/* global _: false */
/* global Signal, Whisper, assert, textsecure, _, libsignal */
/* eslint-disable no-unreachable, no-console */
/* eslint-disable no-console */
'use strict';
@ -240,8 +236,8 @@ describe('Backup', () => {
});
describe('end-to-end', () => {
it('exports then imports to produce the same data we started with', async () => {
return;
it('exports then imports to produce the same data we started with', async function thisNeeded() {
this.timeout(6000);
const { attachmentsPath, fse, glob, path, tmp } = window.test;
const {
@ -249,46 +245,32 @@ describe('Backup', () => {
loadAttachmentData,
} = window.Signal.Migrations;
const key = new Uint8Array([
1,
3,
4,
5,
6,
7,
8,
11,
23,
34,
1,
34,
3,
5,
45,
45,
1,
3,
4,
5,
6,
7,
8,
11,
23,
34,
1,
34,
3,
5,
45,
45,
]);
const staticKeyPair = await libsignal.KeyHelper.generateIdentityKeyPair();
const attachmentsPattern = path.join(attachmentsPath, '**');
const OUR_NUMBER = '+12025550000';
const CONTACT_ONE_NUMBER = '+12025550001';
const CONTACT_TWO_NUMBER = '+12025550002';
const toArrayBuffer = nodeBuffer =>
nodeBuffer.buffer.slice(
nodeBuffer.byteOffset,
nodeBuffer.byteOffset + nodeBuffer.byteLength
);
const getFixture = target => toArrayBuffer(fse.readFileSync(target));
const FIXTURES = {
gif: getFixture('fixtures/giphy-7GFfijngKbeNy.gif'),
mp4: getFixture('fixtures/pixabay-Soap-Bubble-7141.mp4'),
jpg: getFixture('fixtures/koushik-chowdavarapu-105425-unsplash.jpg'),
mp3: getFixture('fixtures/incompetech-com-Agnus-Dei-X.mp3'),
txt: getFixture('fixtures/lorem-ipsum.txt'),
png: getFixture(
'fixtures/freepngs-2cd43b_bed7d1327e88454487397574d87b64dc_mv2.png'
),
};
async function wrappedLoadAttachment(attachment) {
return _.omit(await loadAttachmentData(attachment), ['path']);
}
@ -376,16 +358,30 @@ describe('Backup', () => {
})
),
attachments: await Promise.all(
(message.attachments || []).map(attachment =>
wrappedLoadAttachment(attachment)
)
(message.attachments || []).map(async attachment => {
await wrappedLoadAttachment(attachment);
if (attachment.thumbnail) {
await wrappedLoadAttachment(attachment.thumbnail);
}
if (attachment.screenshot) {
await wrappedLoadAttachment(attachment.screenshot);
}
return attachment;
})
),
});
}
let backupDir;
try {
const ATTACHMENT_COUNT = 3;
// Seven total:
// - Five from image/video attachments
// - One from embedded contact avatar
// - Another from embedded quoted attachment thumbnail
const ATTACHMENT_COUNT = 7;
const MESSAGE_COUNT = 1;
const CONVERSATION_COUNT = 1;
@ -397,47 +393,20 @@ describe('Backup', () => {
timestamp: 1524185933350,
errors: [],
attachments: [
// Note: generates two more files: screenshot and thumbnail
{
contentType: 'image/gif',
fileName: 'sad_cat.gif',
data: new Uint8Array([
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
]).buffer,
contentType: 'video/mp4',
fileName: 'video.mp4',
data: FIXTURES.mp4,
},
// Note: generates one more file: thumbnail
{
contentType: 'image/png',
fileName: 'landscape.png',
data: FIXTURES.png,
},
],
hasAttachments: 1,
hasFileAttachments: undefined,
hasVisualMediaAttachments: 1,
quote: {
text: "Isn't it cute?",
@ -450,43 +419,10 @@ describe('Backup', () => {
},
{
contentType: 'image/gif',
fileName: 'happy_cat.gif',
fileName: 'avatar.gif',
thumbnail: {
contentType: 'image/png',
data: new Uint8Array([
2,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
]).buffer,
data: FIXTURES.gif,
},
},
],
@ -506,40 +442,7 @@ describe('Backup', () => {
isProfile: false,
avatar: {
contentType: 'image/png',
data: new Uint8Array([
3,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
]).buffer,
data: FIXTURES.png,
},
},
},
@ -552,107 +455,30 @@ describe('Backup', () => {
console.log('Backup test: Create models, save to db/disk');
const message = await upgradeMessageSchema(messageWithAttachments);
console.log({ message });
const messageModel = new Whisper.Message(message);
const id = await window.Signal.Data.saveMessage(
messageModel.attributes,
{
Message: Whisper.Message,
}
);
messageModel.set({ id });
await window.Signal.Data.saveMessage(message, {
Message: Whisper.Message,
});
const conversation = {
active_at: 1524185933350,
color: 'orange',
expireTimer: 0,
id: CONTACT_ONE_NUMBER,
lastMessage: 'Heyo!',
name: 'Someone Somewhere',
profileAvatar: {
contentType: 'image/jpeg',
data: new Uint8Array([
4,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
]).buffer,
data: FIXTURES.jpeg,
size: 64,
},
profileKey: new Uint8Array([
5,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
1,
2,
3,
4,
5,
6,
7,
8,
]).buffer,
profileKey: 'BASE64KEY',
profileName: 'Someone! 🤔',
profileSharing: true,
timestamp: 1524185933350,
tokens: [
'someone somewhere',
'someone',
'somewhere',
'2025550001',
'12025550001',
],
type: 'private',
unreadCount: 0,
verified: 0,
sealedSender: 0,
version: 2,
};
console.log({ conversation });
await window.Signal.Data.saveConversation(conversation, {
@ -669,11 +495,13 @@ describe('Backup', () => {
console.log('Backup test: Export!');
backupDir = tmp.dirSync().name;
console.log({ backupDir });
await Signal.Backup.exportToDirectory(backupDir, { key });
await Signal.Backup.exportToDirectory(backupDir, {
key: staticKeyPair.pubKey,
});
console.log('Backup test: Ensure that messages.zip exists');
const zipPath = path.join(backupDir, 'messages.zip');
const messageZipExists = fse.existsSync(zipPath);
console.log('Backup test: Ensure that messages.tar.gz exists');
const archivePath = path.join(backupDir, 'messages.tar.gz');
const messageZipExists = fse.existsSync(archivePath);
assert.strictEqual(true, messageZipExists);
console.log(
@ -688,43 +516,9 @@ describe('Backup', () => {
await clearAllData();
console.log('Backup test: Import!');
await Signal.Backup.importFromDirectory(backupDir, { key });
console.log('Backup test: ensure that all attachments were imported');
const recreatedAttachmentFiles = removeDirs(
glob.sync(attachmentsPattern)
);
console.log({ recreatedAttachmentFiles });
assert.strictEqual(ATTACHMENT_COUNT, recreatedAttachmentFiles.length);
assert.deepEqual(attachmentFiles, recreatedAttachmentFiles);
console.log('Backup test: Check messages');
const messageCollection = await window.Signal.Data.getAllMessages({
MessageCollection: Whisper.MessageCollection,
await Signal.Backup.importFromDirectory(backupDir, {
key: staticKeyPair.privKey,
});
assert.strictEqual(messageCollection.length, MESSAGE_COUNT);
const messageFromDB = removeId(messageCollection.at(0).attributes);
const expectedMessage = omitUndefinedKeys(message);
console.log({ messageFromDB, expectedMessage });
assert.deepEqual(messageFromDB, expectedMessage);
console.log(
'Backup test: Check that all attachments were successfully imported'
);
const messageWithAttachmentsFromDB = await loadAllFilesFromDisk(
messageFromDB
);
const expectedMessageWithAttachments = omitUndefinedKeys(
messageWithAttachments
);
console.log({
messageWithAttachmentsFromDB,
expectedMessageWithAttachments,
});
assert.deepEqual(
_.omit(messageWithAttachmentsFromDB, ['schemaVersion']),
expectedMessageWithAttachments
);
console.log('Backup test: Check conversations');
const conversationCollection = await window.Signal.Data.getAllConversations(
@ -741,6 +535,42 @@ describe('Backup', () => {
_.omit(conversation, ['profileAvatar'])
);
console.log('Backup test: Check messages');
const messageCollection = await window.Signal.Data.getAllMessages({
MessageCollection: Whisper.MessageCollection,
});
assert.strictEqual(messageCollection.length, MESSAGE_COUNT);
const messageFromDB = removeId(messageCollection.at(0).attributes);
const expectedMessage = messageFromDB;
console.log({ messageFromDB, expectedMessage });
assert.deepEqual(messageFromDB, expectedMessage);
console.log('Backup test: ensure that all attachments were imported');
const recreatedAttachmentFiles = removeDirs(
glob.sync(attachmentsPattern)
);
console.log({ recreatedAttachmentFiles });
assert.strictEqual(ATTACHMENT_COUNT, recreatedAttachmentFiles.length);
assert.deepEqual(attachmentFiles, recreatedAttachmentFiles);
console.log(
'Backup test: Check that all attachments were successfully imported'
);
const messageWithAttachmentsFromDB = await loadAllFilesFromDisk(
messageFromDB
);
const expectedMessageWithAttachments = await loadAllFilesFromDisk(
omitUndefinedKeys(message)
);
console.log({
messageWithAttachmentsFromDB,
expectedMessageWithAttachments,
});
assert.deepEqual(
messageWithAttachmentsFromDB,
expectedMessageWithAttachments
);
console.log('Backup test: Clear all data');
await clearAllData();