mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-24 10:28:03 +01:00
Normalize message attachments
This commit is contained in:
89
ts/test-node/sql/migration_1360_test.ts
Normal file
89
ts/test-node/sql/migration_1360_test.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
import { sql, sqlJoin } from '../../sql/util';
|
||||
import { createDB, explain, updateToVersion } from './helpers';
|
||||
import type { WritableDB } from '../../sql/Interface';
|
||||
import { DataWriter } from '../../sql/Server';
|
||||
|
||||
describe('SQL/updateToSchemaVersion1360', () => {
|
||||
let db: WritableDB;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = createDB();
|
||||
updateToVersion(db, 1360);
|
||||
await DataWriter.removeAll(db);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
db.close();
|
||||
});
|
||||
|
||||
describe('message attachments', () => {
|
||||
it('uses covering index to delete based on messageId', async () => {
|
||||
const details = explain(
|
||||
db,
|
||||
sql`DELETE from message_attachments WHERE messageId = ${'messageId'}`
|
||||
);
|
||||
assert.strictEqual(
|
||||
details,
|
||||
'SEARCH message_attachments USING COVERING INDEX message_attachments_messageId (messageId=?)'
|
||||
);
|
||||
});
|
||||
|
||||
it('uses index to select based on messageId', async () => {
|
||||
const details = explain(
|
||||
db,
|
||||
sql`SELECT * from message_attachments WHERE messageId IN (${sqlJoin(['id1', 'id2'])});`
|
||||
);
|
||||
assert.strictEqual(
|
||||
details,
|
||||
'SEARCH message_attachments USING INDEX message_attachments_messageId (messageId=?)'
|
||||
);
|
||||
});
|
||||
|
||||
it('uses index find path with existing plaintextHash', async () => {
|
||||
const details = explain(
|
||||
db,
|
||||
sql`
|
||||
SELECT path, localKey
|
||||
FROM message_attachments
|
||||
WHERE plaintextHash = ${'plaintextHash'}
|
||||
LIMIT 1;
|
||||
`
|
||||
);
|
||||
assert.strictEqual(
|
||||
details,
|
||||
'SEARCH message_attachments USING INDEX message_attachments_plaintextHash (plaintextHash=?)'
|
||||
);
|
||||
});
|
||||
|
||||
it('uses all path indices to find if path is being referenced', async () => {
|
||||
const path = 'path';
|
||||
const details = explain(
|
||||
db,
|
||||
sql`
|
||||
SELECT 1 FROM message_attachments
|
||||
WHERE
|
||||
path = ${path} OR
|
||||
thumbnailPath = ${path} OR
|
||||
screenshotPath = ${path} OR
|
||||
backupThumbnailPath = ${path};
|
||||
`
|
||||
);
|
||||
assert.deepStrictEqual(details.split('\n'), [
|
||||
'MULTI-INDEX OR',
|
||||
'INDEX 1',
|
||||
'SEARCH message_attachments USING INDEX message_attachments_path (path=?)',
|
||||
'INDEX 2',
|
||||
'SEARCH message_attachments USING INDEX message_attachments_all_thumbnailPath (thumbnailPath=?)',
|
||||
'INDEX 3',
|
||||
'SEARCH message_attachments USING INDEX message_attachments_all_screenshotPath (screenshotPath=?)',
|
||||
'INDEX 4',
|
||||
'SEARCH message_attachments USING INDEX message_attachments_all_backupThumbnailPath (backupThumbnailPath=?)',
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -197,9 +197,6 @@ describe('Message', () => {
|
||||
fileName: 'test\uFFFDfig.exe',
|
||||
},
|
||||
],
|
||||
hasAttachments: 1,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: undefined,
|
||||
schemaVersion: Message.CURRENT_SCHEMA_VERSION,
|
||||
});
|
||||
|
||||
@@ -848,6 +845,7 @@ describe('Message', () => {
|
||||
const result = await Message.upgradeSchema(message, {
|
||||
...getDefaultContext(),
|
||||
doesAttachmentExist: async () => false,
|
||||
maxVersion: 14,
|
||||
});
|
||||
|
||||
assert.deepEqual({ ...message, schemaVersion: 14 }, result);
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
// Copyright 2018 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
import * as Message from '../../../types/message/initializeAttachmentMetadata';
|
||||
import { SignalService } from '../../../protobuf';
|
||||
import * as MIME from '../../../types/MIME';
|
||||
import * as Bytes from '../../../Bytes';
|
||||
import type { MessageAttributesType } from '../../../model-types.d';
|
||||
|
||||
function getDefaultMessage(
|
||||
props?: Partial<MessageAttributesType>
|
||||
): MessageAttributesType {
|
||||
return {
|
||||
id: 'some-id',
|
||||
type: 'incoming',
|
||||
sent_at: 45,
|
||||
received_at: 45,
|
||||
timestamp: 45,
|
||||
conversationId: 'some-conversation-id',
|
||||
...props,
|
||||
};
|
||||
}
|
||||
|
||||
describe('Message', () => {
|
||||
describe('initializeAttachmentMetadata', () => {
|
||||
it('should classify visual media attachments', async () => {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.IMAGE_JPEG,
|
||||
data: Bytes.fromString('foo'),
|
||||
fileName: 'foo.jpg',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.IMAGE_JPEG,
|
||||
data: Bytes.fromString('foo'),
|
||||
fileName: 'foo.jpg',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
hasAttachments: 1,
|
||||
hasVisualMediaAttachments: 1,
|
||||
hasFileAttachments: undefined,
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should classify file attachments', async () => {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.APPLICATION_OCTET_STREAM,
|
||||
data: Bytes.fromString('foo'),
|
||||
fileName: 'foo.bin',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.APPLICATION_OCTET_STREAM,
|
||||
data: Bytes.fromString('foo'),
|
||||
fileName: 'foo.bin',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
hasAttachments: 1,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: 1,
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('should classify voice message attachments', async () => {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.AUDIO_AAC,
|
||||
flags: SignalService.AttachmentPointer.Flags.VOICE_MESSAGE,
|
||||
data: Bytes.fromString('foo'),
|
||||
fileName: 'Voice Message.aac',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.AUDIO_AAC,
|
||||
flags: SignalService.AttachmentPointer.Flags.VOICE_MESSAGE,
|
||||
data: Bytes.fromString('foo'),
|
||||
fileName: 'Voice Message.aac',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
hasAttachments: 1,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: undefined,
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('does not include long message attachments', async () => {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.LONG_MESSAGE,
|
||||
data: Bytes.fromString('foo'),
|
||||
fileName: 'message.txt',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [
|
||||
{
|
||||
contentType: MIME.LONG_MESSAGE,
|
||||
data: Bytes.fromString('foo'),
|
||||
fileName: 'message.txt',
|
||||
size: 1111,
|
||||
},
|
||||
],
|
||||
hasAttachments: 0,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: undefined,
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
|
||||
it('handles not attachments', async () => {
|
||||
const input = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [],
|
||||
});
|
||||
const expected = getDefaultMessage({
|
||||
type: 'incoming',
|
||||
conversationId: 'foo',
|
||||
id: '11111111-1111-1111-1111-111111111111',
|
||||
timestamp: 1523317140899,
|
||||
received_at: 1523317140899,
|
||||
sent_at: 1523317140800,
|
||||
attachments: [],
|
||||
hasAttachments: 0,
|
||||
hasVisualMediaAttachments: undefined,
|
||||
hasFileAttachments: undefined,
|
||||
});
|
||||
|
||||
const actual = await Message.initializeAttachmentMetadata(input);
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user