From d3c9de4712cd90dff1c1654ece39575f7ce3fe94 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Wed, 28 Mar 2018 18:16:35 -0400 Subject: [PATCH] Add debug module Lets us generate large conversations with large attachments. --- js/modules/debug.js | 132 ++++++++++++++++++++++++++++++++++++++++++++ preload.js | 1 + 2 files changed, 133 insertions(+) create mode 100644 js/modules/debug.js diff --git a/js/modules/debug.js b/js/modules/debug.js new file mode 100644 index 000000000..7a3f7fd28 --- /dev/null +++ b/js/modules/debug.js @@ -0,0 +1,132 @@ +const isFunction = require('lodash/isFunction'); +const isNumber = require('lodash/isNumber'); +const isObject = require('lodash/isObject'); +const isString = require('lodash/isString'); +const random = require('lodash/random'); +const range = require('lodash/range'); +const sample = require('lodash/sample'); + +const Message = require('./types/message'); +const { deferredToPromise } = require('./deferred_to_promise'); +const { sleep } = require('./sleep'); + + +// See: https://en.wikipedia.org/wiki/Fictitious_telephone_number#North_American_Numbering_Plan +const SENDER_ID = '+12126647665'; + +exports.createConversation = async ({ + ConversationController, + numMessages, + WhisperMessage, +} = {}) => { + if (!isObject(ConversationController) || + !isFunction(ConversationController.getOrCreateAndWait)) { + throw new TypeError('"ConversationController" is required'); + } + + if (!isNumber(numMessages) || numMessages <= 0) { + throw new TypeError('"numMessages" must be a positive number'); + } + + if (!isFunction(WhisperMessage)) { + throw new TypeError('"WhisperMessage" is required'); + } + + const conversation = + await ConversationController.getOrCreateAndWait(SENDER_ID, 'private'); + conversation.set({ + active_at: Date.now(), + unread: numMessages, + }); + await deferredToPromise(conversation.save()); + + const conversationId = conversation.get('id'); + + await Promise.all(range(0, numMessages).map(async (index) => { + await sleep(index * 100); + console.log(`Create message ${index + 1}`); + const message = new WhisperMessage(createRandomMessage({ conversationId })); + return deferredToPromise(message.save()); + })); +}; + +const SAMPLE_MESSAGES = [ + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + 'Integer et rutrum leo, eu ultrices ligula.', + 'Nam vel aliquam quam.', + 'Suspendisse posuere nunc vitae pulvinar lobortis.', + 'Nunc et sapien ex.', + 'Duis nec neque eu arcu ultrices ullamcorper in et mauris.', + 'Praesent mi felis, hendrerit a nulla id, mattis consectetur est.', + 'Duis venenatis posuere est sit amet congue.', + 'Vestibulum vitae sapien ultricies, auctor purus vitae, laoreet lacus.', + 'Fusce laoreet nisi dui, a bibendum metus consequat in.', + 'Nulla sed iaculis odio, sed lobortis lacus.', + 'Etiam massa felis, gravida at nibh viverra, tincidunt convallis justo.', + 'Maecenas ut egestas urna.', + 'Pellentesque consectetur mattis imperdiet.', + 'Maecenas pulvinar efficitur justo a cursus.', +]; + +const ATTACHMENT_SAMPLE_RATE = 0.33; +const createRandomMessage = ({ conversationId } = {}) => { + if (!isString(conversationId)) { + throw new TypeError('"conversationId" must be a string'); + } + + const sentAt = Date.now() - random(100 * 24 * 60 * 60 * 1000); + const receivedAt = sentAt + random(30 * 1000); + + const hasAttachment = Math.random() <= ATTACHMENT_SAMPLE_RATE; + const attachments = hasAttachment + ? [createRandomInMemoryAttachment()] : []; + const type = sample(['incoming', 'outgoing']); + const commonProperties = { + attachments, + body: sample(SAMPLE_MESSAGES), + conversationId, + received_at: receivedAt, + sent_at: sentAt, + timestamp: receivedAt, + type, + }; + + const message = (() => { + switch (type) { + case 'incoming': + return Object.assign({}, commonProperties, { + flags: 0, + source: conversationId, + sourceDevice: 1, + }); + case 'outgoing': + return Object.assign({}, commonProperties, { + delivered: 1, + delivered_to: [conversationId], + expireTimer: 0, + recipients: [conversationId], + sent_to: [conversationId], + synced: true, + }); + default: + throw new TypeError(`Unknown message type: '${type}'`); + } + })(); + + return Message.initializeSchemaVersion(message); +}; + +const MEGA_BYTE = 1e6; +const createRandomInMemoryAttachment = () => { + const numBytes = (1 + Math.ceil((Math.random() * 50))) * MEGA_BYTE; + const array = new Uint32Array(numBytes).fill(1); + const data = array.buffer; + const fileName = Math.random().toString().slice(2); + + return { + contentType: 'application/octet-stream', + data, + fileName, + size: numBytes, + }; +}; diff --git a/preload.js b/preload.js index 54944514e..99e8d5f88 100644 --- a/preload.js +++ b/preload.js @@ -125,6 +125,7 @@ window.Signal.Backup = require('./js/modules/backup'); window.Signal.Crypto = require('./js/modules/crypto'); window.Signal.Database = require('./js/modules/database'); + window.Signal.Debug = require('./js/modules/debug'); window.Signal.Logs = require('./js/modules/logs'); window.Signal.Migrations = {}; window.Signal.Migrations.loadAttachmentData = Attachment.loadData(readAttachmentData);