Updates to backup infrastructure
This commit is contained in:
parent
47f834cf5c
commit
e4babdaef0
14 changed files with 599 additions and 710 deletions
|
@ -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();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue