mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-18 07:36:00 +01:00
Improve ref counting when deduplicating attachments on disk
Co-authored-by: trevor-signal <131492920+trevor-signal@users.noreply.github.com>
This commit is contained in:
175
ts/test-node/sql/migration_1660_test.node.ts
Normal file
175
ts/test-node/sql/migration_1660_test.node.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
// Copyright 2026 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
import type { WritableDB } from '../../sql/Interface.std.js';
|
||||
import {
|
||||
createDB,
|
||||
getTableData,
|
||||
insertData,
|
||||
updateToVersion,
|
||||
} from './helpers.node.js';
|
||||
|
||||
describe('SQL/updateToSchemaVersion1660', () => {
|
||||
let db: WritableDB;
|
||||
|
||||
beforeEach(() => {
|
||||
db = createDB();
|
||||
updateToVersion(db, 1660);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
db.close();
|
||||
});
|
||||
|
||||
it('allows same path for different messageIds', () => {
|
||||
insertData(db, 'attachments_protected_from_deletion', [
|
||||
{ path: 'shared', messageId: 'msg1' },
|
||||
{ path: 'shared', messageId: 'msg2' },
|
||||
]);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
getTableData(db, 'attachments_protected_from_deletion'),
|
||||
[
|
||||
{ path: 'shared', messageId: 'msg1' },
|
||||
{ path: 'shared', messageId: 'msg2' },
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('insert trigger only removes protection for matching messageId', () => {
|
||||
insertData(db, 'messages', [{ id: 'msg1', conversationId: 'convoId' }]);
|
||||
|
||||
insertData(db, 'attachments_protected_from_deletion', [
|
||||
{ path: 'a', messageId: 'msg1' },
|
||||
{ path: 'a', messageId: 'msg2' },
|
||||
]);
|
||||
|
||||
insertData(db, 'message_attachments', [
|
||||
{
|
||||
messageId: 'msg1',
|
||||
editHistoryIndex: -1,
|
||||
orderInMessage: 0,
|
||||
attachmentType: 'attachment',
|
||||
receivedAt: 42,
|
||||
sentAt: 42,
|
||||
size: 128,
|
||||
contentType: 'image/png',
|
||||
conversationId: 'convoId',
|
||||
path: 'a',
|
||||
},
|
||||
]);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
getTableData(db, 'attachments_protected_from_deletion'),
|
||||
[{ path: 'a', messageId: 'msg2' }]
|
||||
);
|
||||
});
|
||||
|
||||
it('insert trigger removes protection for all 4 path types', () => {
|
||||
insertData(db, 'messages', [{ id: 'msg1', conversationId: 'convoId' }]);
|
||||
|
||||
insertData(db, 'attachments_protected_from_deletion', [
|
||||
{ path: 'path', messageId: 'msg1' },
|
||||
{ path: 'thumbnailPath', messageId: 'msg1' },
|
||||
{ path: 'screenshotPath', messageId: 'msg1' },
|
||||
{ path: 'backupThumbnailPath', messageId: 'msg1' },
|
||||
{ path: 'unrelated', messageId: 'msg1' },
|
||||
]);
|
||||
|
||||
insertData(db, 'message_attachments', [
|
||||
{
|
||||
messageId: 'msg1',
|
||||
editHistoryIndex: -1,
|
||||
orderInMessage: 0,
|
||||
attachmentType: 'attachment',
|
||||
receivedAt: 42,
|
||||
sentAt: 42,
|
||||
size: 128,
|
||||
contentType: 'image/png',
|
||||
conversationId: 'convoId',
|
||||
path: 'path',
|
||||
thumbnailPath: 'thumbnailPath',
|
||||
screenshotPath: 'screenshotPath',
|
||||
backupThumbnailPath: 'backupThumbnailPath',
|
||||
},
|
||||
]);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
getTableData(db, 'attachments_protected_from_deletion'),
|
||||
[{ path: 'unrelated', messageId: 'msg1' }]
|
||||
);
|
||||
});
|
||||
|
||||
it('update trigger only removes protection for matching messageId', () => {
|
||||
insertData(db, 'messages', [{ id: 'msg1', conversationId: 'convoId' }]);
|
||||
|
||||
insertData(db, 'message_attachments', [
|
||||
{
|
||||
messageId: 'msg1',
|
||||
editHistoryIndex: -1,
|
||||
orderInMessage: 0,
|
||||
attachmentType: 'attachment',
|
||||
receivedAt: 42,
|
||||
sentAt: 42,
|
||||
size: 128,
|
||||
contentType: 'image/png',
|
||||
conversationId: 'convoId',
|
||||
path: 'old',
|
||||
},
|
||||
]);
|
||||
|
||||
insertData(db, 'attachments_protected_from_deletion', [
|
||||
{ path: 'new', messageId: 'msg1' },
|
||||
{ path: 'new', messageId: 'msg2' },
|
||||
]);
|
||||
|
||||
db.prepare("UPDATE message_attachments SET path='new'").run();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
getTableData(db, 'attachments_protected_from_deletion'),
|
||||
[{ path: 'new', messageId: 'msg2' }]
|
||||
);
|
||||
});
|
||||
|
||||
it('update trigger removes protection for all 4 path types', () => {
|
||||
insertData(db, 'messages', [{ id: 'msg1', conversationId: 'convoId' }]);
|
||||
|
||||
insertData(db, 'message_attachments', [
|
||||
{
|
||||
messageId: 'msg1',
|
||||
editHistoryIndex: -1,
|
||||
orderInMessage: 0,
|
||||
attachmentType: 'attachment',
|
||||
receivedAt: 42,
|
||||
sentAt: 42,
|
||||
size: 128,
|
||||
contentType: 'image/png',
|
||||
conversationId: 'convoId',
|
||||
path: 'old',
|
||||
},
|
||||
]);
|
||||
|
||||
insertData(db, 'attachments_protected_from_deletion', [
|
||||
{ path: 'path', messageId: 'msg1' },
|
||||
{ path: 'thumbnailPath', messageId: 'msg1' },
|
||||
{ path: 'screenshotPath', messageId: 'msg1' },
|
||||
{ path: 'backupThumbnailPath', messageId: 'msg1' },
|
||||
{ path: 'unrelated', messageId: 'msg1' },
|
||||
]);
|
||||
|
||||
db.prepare(
|
||||
`UPDATE message_attachments SET
|
||||
path='path',
|
||||
thumbnailPath='thumbnailPath',
|
||||
screenshotPath='screenshotPath',
|
||||
backupThumbnailPath='backupThumbnailPath'`
|
||||
).run();
|
||||
|
||||
assert.deepStrictEqual(
|
||||
getTableData(db, 'attachments_protected_from_deletion'),
|
||||
[{ path: 'unrelated', messageId: 'msg1' }]
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user