mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-02 00:07:56 +01:00
Use protopiler for protocol buffers
Co-authored-by: Jamie Kyle <jamie@signal.org>
This commit is contained in:
@@ -1,141 +0,0 @@
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { Root } from 'protobufjs';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const { Partial, Full } = (Root as any).fromJSON({
|
||||
nested: {
|
||||
test: {
|
||||
nested: {
|
||||
Partial: {
|
||||
fields: {
|
||||
a: {
|
||||
type: 'string',
|
||||
id: 1,
|
||||
},
|
||||
c: {
|
||||
type: 'int32',
|
||||
id: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
Full: {
|
||||
fields: {
|
||||
a: {
|
||||
type: 'string',
|
||||
id: 1,
|
||||
},
|
||||
b: {
|
||||
type: 'bool',
|
||||
id: 2,
|
||||
},
|
||||
c: {
|
||||
type: 'int32',
|
||||
id: 3,
|
||||
},
|
||||
d: {
|
||||
type: 'bytes',
|
||||
id: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}).nested.test;
|
||||
|
||||
describe('Proto#$unknownFields', () => {
|
||||
it('should encode and decode with unknown fields', () => {
|
||||
const full = Full.encode({
|
||||
a: 'hello',
|
||||
b: true,
|
||||
c: 42,
|
||||
d: Buffer.from('ohai'),
|
||||
}).finish();
|
||||
|
||||
const partial = Partial.decode(full);
|
||||
assert.strictEqual(partial.a, 'hello');
|
||||
assert.strictEqual(partial.c, 42);
|
||||
assert.strictEqual(partial.$unknownFields.length, 2);
|
||||
assert.strictEqual(
|
||||
Buffer.from(partial.$unknownFields[0]).toString('hex'),
|
||||
'1001'
|
||||
);
|
||||
assert.strictEqual(
|
||||
Buffer.from(partial.$unknownFields[1]).toString('hex'),
|
||||
'22046f686169'
|
||||
);
|
||||
|
||||
const encoded = Partial.encode({
|
||||
a: partial.a,
|
||||
c: partial.c,
|
||||
$unknownFields: partial.$unknownFields,
|
||||
}).finish();
|
||||
const decoded = Full.decode(encoded);
|
||||
|
||||
assert.strictEqual(decoded.a, 'hello');
|
||||
assert.strictEqual(decoded.b, true);
|
||||
assert.strictEqual(decoded.c, 42);
|
||||
assert.strictEqual(Buffer.from(decoded.d).toString(), 'ohai');
|
||||
|
||||
const concat = Partial.encode({
|
||||
a: partial.a,
|
||||
c: partial.c,
|
||||
$unknownFields: [Buffer.concat(partial.$unknownFields)],
|
||||
}).finish();
|
||||
const decodedConcat = Full.decode(concat);
|
||||
|
||||
assert.strictEqual(decodedConcat.a, 'hello');
|
||||
assert.isTrue(decodedConcat.b);
|
||||
assert.strictEqual(decodedConcat.c, 42);
|
||||
assert.strictEqual(Buffer.from(decodedConcat.d).toString(), 'ohai');
|
||||
});
|
||||
|
||||
it('should decode unknown fields before reencoding them', () => {
|
||||
const full = Full.encode({
|
||||
a: 'hello',
|
||||
b: true,
|
||||
c: 42,
|
||||
d: Buffer.from('ohai'),
|
||||
}).finish();
|
||||
|
||||
const partial = Partial.decode(full);
|
||||
assert.isUndefined(partial.b);
|
||||
|
||||
const encoded = Full.encode({
|
||||
...partial,
|
||||
b: false,
|
||||
}).finish();
|
||||
const decoded = Full.decode(encoded);
|
||||
|
||||
assert.strictEqual(decoded.a, 'hello');
|
||||
assert.isFalse(decoded.b);
|
||||
assert.strictEqual(decoded.c, 42);
|
||||
assert.strictEqual(Buffer.from(decoded.d).toString(), 'ohai');
|
||||
});
|
||||
|
||||
it('should not set unknown fields if all fields were known', () => {
|
||||
const encoded = Partial.encode({
|
||||
a: 'hello',
|
||||
c: 42,
|
||||
}).finish();
|
||||
const decoded = Full.decode(encoded);
|
||||
|
||||
assert.strictEqual(decoded.a, 'hello');
|
||||
assert.strictEqual(decoded.c, 42);
|
||||
assert.isUndefined(decoded.$unknownFields);
|
||||
|
||||
const encodedWithEmptyArray = Partial.encode({
|
||||
a: 'hi',
|
||||
c: 69,
|
||||
$unkownFields: [],
|
||||
}).finish();
|
||||
const decodedWithEmptyArray = Full.decode(encodedWithEmptyArray);
|
||||
|
||||
assert.strictEqual(decodedWithEmptyArray.a, 'hi');
|
||||
assert.strictEqual(decodedWithEmptyArray.c, 69);
|
||||
assert.isUndefined(decodedWithEmptyArray.$unknownFields);
|
||||
});
|
||||
});
|
||||
@@ -99,8 +99,8 @@ describe('group add banned member', () => {
|
||||
},
|
||||
});
|
||||
|
||||
assert.isUndefined(actions.addMembersBanned);
|
||||
assert.isUndefined(actions.deleteMembersBanned);
|
||||
assert.isNull(actions.addMembersBanned);
|
||||
assert.isNull(actions.deleteMembersBanned);
|
||||
});
|
||||
|
||||
it('should not ban already banned person', () => {
|
||||
@@ -113,7 +113,7 @@ describe('group add banned member', () => {
|
||||
},
|
||||
});
|
||||
|
||||
assert.isUndefined(actions.addMembersBanned);
|
||||
assert.isUndefined(actions.deleteMembersBanned);
|
||||
assert.isNull(actions.addMembersBanned);
|
||||
assert.isNull(actions.deleteMembersBanned);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import Long from 'long';
|
||||
import { v4 as generateUuid } from 'uuid';
|
||||
|
||||
import {
|
||||
@@ -23,9 +22,40 @@ const FLAGS = Proto.DataMessage.Flags;
|
||||
const TIMESTAMP = Date.now();
|
||||
const CLIENT_UUID = generateUuid();
|
||||
|
||||
const UNPROCESSED_ATTACHMENT: Proto.IAttachmentPointer = {
|
||||
cdnId: Long.fromNumber(123),
|
||||
cdnKey: 'cdnKey',
|
||||
const EMPTY_DATA_MESSAGE: Proto.DataMessage.Params = {
|
||||
body: null,
|
||||
attachments: null,
|
||||
groupV2: null,
|
||||
flags: null,
|
||||
expireTimer: null,
|
||||
expireTimerVersion: null,
|
||||
profileKey: null,
|
||||
timestamp: null,
|
||||
quote: null,
|
||||
contact: null,
|
||||
preview: null,
|
||||
sticker: null,
|
||||
requiredProtocolVersion: null,
|
||||
isViewOnce: null,
|
||||
reaction: null,
|
||||
delete: null,
|
||||
bodyRanges: null,
|
||||
groupCallUpdate: null,
|
||||
payment: null,
|
||||
storyContext: null,
|
||||
giftBadge: null,
|
||||
pollCreate: null,
|
||||
pollTerminate: null,
|
||||
pollVote: null,
|
||||
pinMessage: null,
|
||||
unpinMessage: null,
|
||||
adminDelete: null,
|
||||
};
|
||||
|
||||
const UNPROCESSED_ATTACHMENT: Proto.AttachmentPointer.Params = {
|
||||
attachmentIdentifier: {
|
||||
cdnKey: 'cdnKey',
|
||||
},
|
||||
cdnNumber: 2,
|
||||
blurHash: 'blurHash',
|
||||
caption: 'caption',
|
||||
@@ -35,16 +65,17 @@ const UNPROCESSED_ATTACHMENT: Proto.IAttachmentPointer = {
|
||||
contentType: IMAGE_GIF,
|
||||
incrementalMac: new Uint8Array([12, 12, 12]),
|
||||
chunkSize: 24,
|
||||
uploadTimestamp: Long.fromNumber(456),
|
||||
uploadTimestamp: 456n,
|
||||
size: 34,
|
||||
height: 64,
|
||||
width: 128,
|
||||
flags: 1,
|
||||
fileName: 'fileName',
|
||||
thumbnail: null,
|
||||
};
|
||||
|
||||
const PROCESSED_ATTACHMENT: ProcessedAttachment = {
|
||||
cdnId: '123',
|
||||
cdnId: undefined,
|
||||
cdnKey: 'cdnKey',
|
||||
cdnNumber: 2,
|
||||
blurHash: 'blurHash',
|
||||
@@ -64,12 +95,17 @@ const PROCESSED_ATTACHMENT: ProcessedAttachment = {
|
||||
};
|
||||
|
||||
describe('processDataMessage', () => {
|
||||
const check = (message: Proto.IDataMessage) =>
|
||||
const check = (
|
||||
message: Partial<Omit<Proto.DataMessage.Params, 'timestamp'>>
|
||||
) =>
|
||||
processDataMessage(
|
||||
{
|
||||
timestamp: Long.fromNumber(TIMESTAMP),
|
||||
...message,
|
||||
},
|
||||
Proto.DataMessage.decode(
|
||||
Proto.DataMessage.encode({
|
||||
...EMPTY_DATA_MESSAGE,
|
||||
timestamp: BigInt(TIMESTAMP),
|
||||
...message,
|
||||
})
|
||||
),
|
||||
TIMESTAMP,
|
||||
{
|
||||
_createName: () => 'random-path',
|
||||
@@ -94,7 +130,9 @@ describe('processDataMessage', () => {
|
||||
attachments: [
|
||||
{
|
||||
...UNPROCESSED_ATTACHMENT,
|
||||
cdnId: new Long(0),
|
||||
attachmentIdentifier: {
|
||||
cdnId: 0n,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -103,6 +141,7 @@ describe('processDataMessage', () => {
|
||||
{
|
||||
...PROCESSED_ATTACHMENT,
|
||||
cdnId: undefined,
|
||||
cdnKey: undefined,
|
||||
downloadPath: 'random-path',
|
||||
},
|
||||
]);
|
||||
@@ -154,7 +193,7 @@ describe('processDataMessage', () => {
|
||||
});
|
||||
|
||||
it('should throw on too many attachments', () => {
|
||||
const attachments: Array<Proto.IAttachmentPointer> = [];
|
||||
const attachments: Array<Proto.AttachmentPointer.Params> = [];
|
||||
for (let i = 0; i < ATTACHMENT_MAX + 1; i += 1) {
|
||||
attachments.push(UNPROCESSED_ATTACHMENT);
|
||||
}
|
||||
@@ -206,9 +245,12 @@ describe('processDataMessage', () => {
|
||||
it('should process quote, dropping second attachment', () => {
|
||||
const out = check({
|
||||
quote: {
|
||||
id: Long.fromNumber(1),
|
||||
id: 1n,
|
||||
authorAci: null,
|
||||
authorAciBinary: ACI_BINARY_1,
|
||||
text: 'text',
|
||||
bodyRanges: null,
|
||||
type: null,
|
||||
attachments: [
|
||||
{
|
||||
contentType: 'image/jpeg',
|
||||
@@ -235,20 +277,31 @@ describe('processDataMessage', () => {
|
||||
thumbnail: PROCESSED_ATTACHMENT,
|
||||
},
|
||||
],
|
||||
bodyRanges: undefined,
|
||||
bodyRanges: [],
|
||||
type: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should process contact, dropping second contact', () => {
|
||||
const EMPTY_CONTACT = {
|
||||
$unknown: [],
|
||||
number: [],
|
||||
name: null,
|
||||
email: [],
|
||||
address: [],
|
||||
organization: '',
|
||||
};
|
||||
const out = check({
|
||||
contact: [
|
||||
{
|
||||
...EMPTY_CONTACT,
|
||||
avatar: {
|
||||
avatar: UNPROCESSED_ATTACHMENT,
|
||||
isProfile: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
...EMPTY_CONTACT,
|
||||
avatar: {
|
||||
avatar: UNPROCESSED_ATTACHMENT,
|
||||
isProfile: true,
|
||||
@@ -259,7 +312,11 @@ describe('processDataMessage', () => {
|
||||
|
||||
assert.deepStrictEqual(out.contact, [
|
||||
{
|
||||
avatar: { avatar: PROCESSED_ATTACHMENT, isProfile: false },
|
||||
...EMPTY_CONTACT,
|
||||
avatar: {
|
||||
avatar: PROCESSED_ATTACHMENT,
|
||||
isProfile: false,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
@@ -273,12 +330,14 @@ describe('processDataMessage', () => {
|
||||
image: UNPROCESSED_ATTACHMENT,
|
||||
title: 'Signal Private Messenger #1',
|
||||
url: 'https://signal.org',
|
||||
date: null,
|
||||
},
|
||||
{
|
||||
description: 'Say "hello" again',
|
||||
image: UNPROCESSED_ATTACHMENT,
|
||||
title: 'Signal Private Messenger #2',
|
||||
url: 'https://signal.org',
|
||||
date: null,
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -300,8 +359,10 @@ describe('processDataMessage', () => {
|
||||
check({
|
||||
reaction: {
|
||||
emoji: '😎',
|
||||
remove: null,
|
||||
targetAuthorAci: null,
|
||||
targetAuthorAciBinary: ACI_BINARY_1,
|
||||
targetSentTimestamp: Long.fromNumber(TIMESTAMP),
|
||||
targetSentTimestamp: BigInt(TIMESTAMP),
|
||||
},
|
||||
}).reaction,
|
||||
{
|
||||
@@ -317,8 +378,9 @@ describe('processDataMessage', () => {
|
||||
reaction: {
|
||||
emoji: '😎',
|
||||
remove: true,
|
||||
targetAuthorAci: null,
|
||||
targetAuthorAciBinary: ACI_BINARY_1,
|
||||
targetSentTimestamp: Long.fromNumber(TIMESTAMP),
|
||||
targetSentTimestamp: BigInt(TIMESTAMP),
|
||||
},
|
||||
}).reaction,
|
||||
{
|
||||
@@ -334,8 +396,11 @@ describe('processDataMessage', () => {
|
||||
const out = check({
|
||||
preview: [
|
||||
{
|
||||
date: Long.fromNumber(TIMESTAMP),
|
||||
date: BigInt(TIMESTAMP),
|
||||
image: UNPROCESSED_ATTACHMENT,
|
||||
url: null,
|
||||
title: null,
|
||||
description: null,
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -343,9 +408,9 @@ describe('processDataMessage', () => {
|
||||
assert.deepStrictEqual(out.preview, [
|
||||
{
|
||||
date: TIMESTAMP,
|
||||
description: undefined,
|
||||
title: undefined,
|
||||
url: undefined,
|
||||
description: '',
|
||||
title: '',
|
||||
url: '',
|
||||
image: PROCESSED_ATTACHMENT,
|
||||
},
|
||||
]);
|
||||
|
||||
58
ts/test-node/processSent_test.node.ts
Normal file
58
ts/test-node/processSent_test.node.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import lodash from 'lodash';
|
||||
import { generateAci } from '../types/ServiceId.std.js';
|
||||
import { signalservice as Proto } from '../protobuf/compiled.std.js';
|
||||
|
||||
import { processSent } from '../textsecure/processSyncMessage.node.js';
|
||||
|
||||
const { omit } = lodash;
|
||||
|
||||
describe('processSent', () => {
|
||||
const destinationServiceId = generateAci();
|
||||
|
||||
it('should normalize UUIDs in sent', () => {
|
||||
const input = Proto.SyncMessage.Sent.decode(
|
||||
Proto.SyncMessage.Sent.encode({
|
||||
destinationServiceId: destinationServiceId.toUpperCase(),
|
||||
destinationServiceIdBinary: null,
|
||||
|
||||
unidentifiedStatus: [
|
||||
{
|
||||
destinationServiceId: destinationServiceId.toUpperCase(),
|
||||
unidentified: null,
|
||||
destinationServiceIdBinary: null,
|
||||
destinationPniIdentityKey: null,
|
||||
},
|
||||
],
|
||||
|
||||
destinationE164: null,
|
||||
timestamp: null,
|
||||
message: null,
|
||||
expirationStartTimestamp: null,
|
||||
isRecipientUpdate: null,
|
||||
storyMessage: null,
|
||||
storyMessageRecipients: null,
|
||||
editMessage: null,
|
||||
})
|
||||
);
|
||||
|
||||
const out = processSent(input);
|
||||
|
||||
assert.deepStrictEqual(out, {
|
||||
...omit(input, 'destinationServiceIdBinary', '$unknown'),
|
||||
destinationServiceId,
|
||||
unidentifiedStatus: [
|
||||
{
|
||||
$unknown: [],
|
||||
destinationPniIdentityKey: undefined,
|
||||
destinationServiceId,
|
||||
unidentified: false,
|
||||
},
|
||||
],
|
||||
storyMessageRecipients: [],
|
||||
} as unknown);
|
||||
});
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { generateAci } from '../types/ServiceId.std.js';
|
||||
|
||||
import { processSyncMessage } from '../textsecure/processSyncMessage.node.js';
|
||||
|
||||
describe('processSyncMessage', () => {
|
||||
const destinationServiceId = generateAci();
|
||||
|
||||
it('should normalize UUIDs in sent', () => {
|
||||
const out = processSyncMessage({
|
||||
sent: {
|
||||
destinationServiceId: destinationServiceId.toUpperCase(),
|
||||
|
||||
unidentifiedStatus: [
|
||||
{
|
||||
destinationServiceId: destinationServiceId.toUpperCase(),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(out, {
|
||||
sent: {
|
||||
destinationServiceId,
|
||||
|
||||
storyMessageRecipients: undefined,
|
||||
unidentifiedStatus: [
|
||||
{
|
||||
destinationServiceId,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -182,27 +182,6 @@ describe('cleanDataForIpc', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('calls `toNumber` when available', () => {
|
||||
assert.deepEqual(
|
||||
cleanDataForIpc([
|
||||
{
|
||||
toNumber() {
|
||||
return 5;
|
||||
},
|
||||
},
|
||||
{
|
||||
toNumber() {
|
||||
return Symbol('bogus');
|
||||
},
|
||||
},
|
||||
]),
|
||||
{
|
||||
cleaned: [5, undefined],
|
||||
pathsChanged: ['root.1'],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('deeply cleans objects with a `null` prototype', () => {
|
||||
const value = Object.assign(Object.create(null), {
|
||||
'key 1': 'value',
|
||||
|
||||
@@ -13,6 +13,22 @@ import {
|
||||
getTableData,
|
||||
} from './helpers.node.js';
|
||||
|
||||
const EMPTY_ENVELOPE: Proto.Envelope.Params = {
|
||||
content: null,
|
||||
type: null,
|
||||
sourceServiceId: null,
|
||||
sourceDevice: null,
|
||||
destinationServiceId: null,
|
||||
timestamp: null,
|
||||
serverGuid: null,
|
||||
serverTimestamp: null,
|
||||
ephemeral: null,
|
||||
urgent: null,
|
||||
updatedPni: null,
|
||||
story: null,
|
||||
reportSpamToken: null,
|
||||
};
|
||||
|
||||
describe('SQL/updateToSchemaVersion1280', () => {
|
||||
let db: WritableDB;
|
||||
|
||||
@@ -62,10 +78,11 @@ describe('SQL/updateToSchemaVersion1280', () => {
|
||||
attempts: 5,
|
||||
envelope: Buffer.from(
|
||||
Proto.Envelope.encode({
|
||||
...EMPTY_ENVELOPE,
|
||||
destinationServiceId: THEIR_ACI,
|
||||
content: Buffer.from('encrypted1'),
|
||||
reportSpamToken: Buffer.from('token'),
|
||||
}).finish()
|
||||
})
|
||||
).toString('base64'),
|
||||
serverTimestamp: 6,
|
||||
serverGuid: 'guid1',
|
||||
@@ -81,9 +98,10 @@ describe('SQL/updateToSchemaVersion1280', () => {
|
||||
attempts: 5,
|
||||
envelope: Buffer.from(
|
||||
Proto.Envelope.encode({
|
||||
...EMPTY_ENVELOPE,
|
||||
type: 3,
|
||||
content: Buffer.from('encrypted2'),
|
||||
}).finish()
|
||||
})
|
||||
).toString('base64'),
|
||||
serverTimestamp: 7,
|
||||
serverGuid: 'guid2',
|
||||
@@ -99,8 +117,9 @@ describe('SQL/updateToSchemaVersion1280', () => {
|
||||
attempts: 6,
|
||||
envelope: Buffer.from(
|
||||
Proto.Envelope.encode({
|
||||
...EMPTY_ENVELOPE,
|
||||
content: Buffer.from('unused'),
|
||||
}).finish()
|
||||
})
|
||||
).toString('base64'),
|
||||
decrypted: 'CAFE',
|
||||
serverTimestamp: 8,
|
||||
|
||||
@@ -5,30 +5,40 @@ import { assert } from 'chai';
|
||||
import { arePinnedConversationsEqual } from '../../util/arePinnedConversationsEqual.node.js';
|
||||
import { SignalService as Proto } from '../../protobuf/index.std.js';
|
||||
|
||||
import PinnedConversation = Proto.AccountRecord.IPinnedConversation;
|
||||
import PinnedConversation = Proto.AccountRecord.PinnedConversation.Params;
|
||||
|
||||
describe('arePinnedConversationsEqual', () => {
|
||||
it('is equal if both have same values at same indices', () => {
|
||||
const localValue = [
|
||||
{
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
e164: '+13055551234',
|
||||
identifier: {
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
serviceIdBinary: null,
|
||||
e164: '+13055551234',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
groupMasterKey: new Uint8Array(32),
|
||||
identifier: {
|
||||
groupMasterKey: new Uint8Array(32),
|
||||
},
|
||||
},
|
||||
];
|
||||
const remoteValue = [
|
||||
{
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
e164: '+13055551234',
|
||||
identifier: {
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
serviceIdBinary: null,
|
||||
e164: '+13055551234',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
groupMasterKey: new Uint8Array(32),
|
||||
identifier: {
|
||||
groupMasterKey: new Uint8Array(32),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -38,29 +48,41 @@ describe('arePinnedConversationsEqual', () => {
|
||||
it('is not equal if values are mixed', () => {
|
||||
const localValue = [
|
||||
{
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
e164: '+13055551234',
|
||||
identifier: {
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
serviceIdBinary: null,
|
||||
e164: '+13055551234',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
contact: {
|
||||
serviceId: 'f59a9fed-9e91-4bb4-a015-d49e58b47e25',
|
||||
e164: '+17865554321',
|
||||
identifier: {
|
||||
contact: {
|
||||
serviceId: 'f59a9fed-9e91-4bb4-a015-d49e58b47e25',
|
||||
serviceIdBinary: null,
|
||||
e164: '+17865554321',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
const remoteValue = [
|
||||
{
|
||||
contact: {
|
||||
serviceId: 'f59a9fed-9e91-4bb4-a015-d49e58b47e25',
|
||||
e164: '+17865554321',
|
||||
identifier: {
|
||||
contact: {
|
||||
serviceId: 'f59a9fed-9e91-4bb4-a015-d49e58b47e25',
|
||||
serviceIdBinary: null,
|
||||
e164: '+17865554321',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
e164: '+13055551234',
|
||||
identifier: {
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
serviceIdBinary: null,
|
||||
e164: '+13055551234',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -71,9 +93,12 @@ describe('arePinnedConversationsEqual', () => {
|
||||
it('is not equal if lengths are not same', () => {
|
||||
const localValue = [
|
||||
{
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
e164: '+13055551234',
|
||||
identifier: {
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
serviceIdBinary: null,
|
||||
e164: '+13055551234',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -84,15 +109,20 @@ describe('arePinnedConversationsEqual', () => {
|
||||
it('is not equal if content does not match', () => {
|
||||
const localValue = [
|
||||
{
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
e164: '+13055551234',
|
||||
identifier: {
|
||||
contact: {
|
||||
serviceId: '72313cde-2784-4a6f-a92a-abbe23763a60',
|
||||
serviceIdBinary: null,
|
||||
e164: '+13055551234',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
const remoteValue = [
|
||||
{
|
||||
groupMasterKey: new Uint8Array(32),
|
||||
identifier: {
|
||||
groupMasterKey: new Uint8Array(32),
|
||||
},
|
||||
},
|
||||
];
|
||||
assert.isFalse(arePinnedConversationsEqual(localValue, remoteValue));
|
||||
|
||||
@@ -20,11 +20,11 @@ describe('callingMessageToProto', () => {
|
||||
describe('hangup field', () => {
|
||||
it('leaves the field unset if `hangup` is not provided', () => {
|
||||
const result = callingMessageToProto(new CallingMessage());
|
||||
assert.isUndefined(result.hangup);
|
||||
assert.isNull(result.hangup);
|
||||
});
|
||||
|
||||
it('attaches the type if provided', () => {
|
||||
const callId: CallId = { high: 0, low: 0, unsigned: false };
|
||||
const callId: CallId = 0n;
|
||||
|
||||
const callingMessage = new CallingMessage();
|
||||
callingMessage.hangup = new HangupMessage(callId, HangupType.Busy, 1);
|
||||
@@ -38,7 +38,7 @@ describe('callingMessageToProto', () => {
|
||||
describe('opaque field', () => {
|
||||
it('leaves the field unset if neither `opaque` nor urgency are provided', () => {
|
||||
const result = callingMessageToProto(new CallingMessage());
|
||||
assert.isUndefined(result.opaque);
|
||||
assert.isNull(result.opaque);
|
||||
});
|
||||
|
||||
it('attaches opaque data', () => {
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import { assert } from 'chai';
|
||||
import Long from 'long';
|
||||
|
||||
import * as Bytes from '../../Bytes.std.js';
|
||||
import type { LocalUserDataType } from '../../util/sessionTranslation.node.js';
|
||||
import { sessionRecordToProtobuf } from '../../util/sessionTranslation.node.js';
|
||||
|
||||
import { toNumber } from '../../util/toNumber.std.js';
|
||||
|
||||
const getRecordCopy = (record: any): any => JSON.parse(JSON.stringify(record));
|
||||
|
||||
export const SESSION_V1_RECORD = {
|
||||
@@ -208,8 +209,8 @@ function protoToJSON(value: unknown): unknown {
|
||||
return value.map(protoToJSON);
|
||||
}
|
||||
|
||||
if (Long.isLong(value)) {
|
||||
return value.toNumber();
|
||||
if (typeof value === 'bigint') {
|
||||
return toNumber(value);
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
@@ -310,6 +311,7 @@ describe('sessionTranslation', () => {
|
||||
receiverChains: [
|
||||
{
|
||||
senderRatchetKey: 'BQo3HG1UhWIh6A7NBxZtNGezBZH8nElZjOqNCBHPzlBz',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 6,
|
||||
key: 'Wnvy2TjYs0HdZFNahmsKw5cc9KEbW1nSwraDFmGwBDw=',
|
||||
@@ -332,6 +334,8 @@ describe('sessionTranslation', () => {
|
||||
],
|
||||
remoteRegistrationId: 4243,
|
||||
localRegistrationId: 3554,
|
||||
needsRefresh: null,
|
||||
pendingPreKey: null,
|
||||
aliceBaseKey: 'BVeHv5MAbMgKeaoO/G1CMBdqhC7bo7Mtc4EWxI0oT19N',
|
||||
},
|
||||
previousSessions: [],
|
||||
@@ -370,6 +374,7 @@ describe('sessionTranslation', () => {
|
||||
receiverChains: [
|
||||
{
|
||||
senderRatchetKey: 'BQo3HG1UhWIh6A7NBxZtNGezBZH8nElZjOqNCBHPzlBz',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 6,
|
||||
key: 'Wnvy2TjYs0HdZFNahmsKw5cc9KEbW1nSwraDFmGwBDw=',
|
||||
@@ -391,8 +396,10 @@ describe('sessionTranslation', () => {
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'BTpb20+IlnBkryDC2ecQT96Hd3t9/Qh3ljnA3509kxRa',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 2,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [
|
||||
{
|
||||
@@ -405,8 +412,10 @@ describe('sessionTranslation', () => {
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'Bd5nlMVr6YMBE5eh//tOWMgoOQakkneYri/YuVJpi0pJ',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 12,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [
|
||||
{
|
||||
@@ -437,8 +446,10 @@ describe('sessionTranslation', () => {
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'BYSxQO1OIs0ZSFN7JI/vF5Rb0VwaKjs+UAAfDkhOYfkp',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 6,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [
|
||||
{
|
||||
@@ -469,22 +480,28 @@ describe('sessionTranslation', () => {
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'BbXSFD/IoivRUvfnPzOaRLqDXEAwi4YEristfwiOj3IJ',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 3,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [],
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'BRRAnr1NhizgCPPzmYV9qGBpvwCpSQH0Rx+UOtl78wUg',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 1,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [],
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'BZvOKPA+kXiCg8TIP/52fu1reCDirC7wb5nyRGce3y4N',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 7,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [
|
||||
{
|
||||
@@ -497,8 +514,10 @@ describe('sessionTranslation', () => {
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'Ba9q9bHjMHfbUNDCU8+0O7cmEcIluq+wk3/d2f7q+ThG',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 4,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [
|
||||
{
|
||||
@@ -523,28 +542,36 @@ describe('sessionTranslation', () => {
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'BTwX5SmcUeBG7mwyOZ3YgxyXIN0ktzuEdWTfBUmPfGYG',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 2,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [],
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'BV7ECvKbwKIAD61BXDYr0xr3JtckuKzR1Hw8cVPWGtlo',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 3,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [],
|
||||
},
|
||||
{
|
||||
senderRatchetKey: 'BTC7rQqoykGR5Aaix7RkAhI5fSXufc6pVGN9OIC8EW5c',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 1,
|
||||
key: null,
|
||||
},
|
||||
messageKeys: [],
|
||||
},
|
||||
],
|
||||
remoteRegistrationId: 4243,
|
||||
localRegistrationId: 3554,
|
||||
needsRefresh: null,
|
||||
pendingPreKey: null,
|
||||
aliceBaseKey: 'BVeHv5MAbMgKeaoO/G1CMBdqhC7bo7Mtc4EWxI0oT19N',
|
||||
},
|
||||
previousSessions: [],
|
||||
@@ -632,6 +659,7 @@ describe('sessionTranslation', () => {
|
||||
receiverChains: [
|
||||
{
|
||||
senderRatchetKey: 'BQo3HG1UhWIh6A7NBxZtNGezBZH8nElZjOqNCBHPzlBz',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 6,
|
||||
key: 'Wnvy2TjYs0HdZFNahmsKw5cc9KEbW1nSwraDFmGwBDw=',
|
||||
@@ -659,6 +687,7 @@ describe('sessionTranslation', () => {
|
||||
},
|
||||
remoteRegistrationId: 4243,
|
||||
localRegistrationId: 3554,
|
||||
needsRefresh: null,
|
||||
aliceBaseKey: 'BVeHv5MAbMgKeaoO/G1CMBdqhC7bo7Mtc4EWxI0oT19N',
|
||||
},
|
||||
previousSessions: [],
|
||||
@@ -821,6 +850,7 @@ describe('sessionTranslation', () => {
|
||||
receiverChains: [
|
||||
{
|
||||
senderRatchetKey: 'BQo3HG1UhWIh6A7NBxZtNGezBZH8nElZjOqNCBHPzlBz',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 6,
|
||||
key: 'Wnvy2TjYs0HdZFNahmsKw5cc9KEbW1nSwraDFmGwBDw=',
|
||||
@@ -843,6 +873,8 @@ describe('sessionTranslation', () => {
|
||||
],
|
||||
remoteRegistrationId: 4243,
|
||||
localRegistrationId: 3554,
|
||||
needsRefresh: null,
|
||||
pendingPreKey: null,
|
||||
aliceBaseKey: 'BVeHv5MAbMgKeaoO/G1CMBdqhC7bo7Mtc4EWxI0oT19N',
|
||||
},
|
||||
previousSessions: [
|
||||
@@ -865,6 +897,7 @@ describe('sessionTranslation', () => {
|
||||
receiverChains: [
|
||||
{
|
||||
senderRatchetKey: 'BQo3HG1UhWIh6A7NBxZtNGezBZH8nElZjOqNCBHPzlBz',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 6,
|
||||
key: 'Wnvy2TjYs0HdZFNahmsKw5cc9KEbW1nSwraDFmGwBDw=',
|
||||
@@ -887,6 +920,8 @@ describe('sessionTranslation', () => {
|
||||
],
|
||||
remoteRegistrationId: 2312,
|
||||
localRegistrationId: 3554,
|
||||
needsRefresh: null,
|
||||
pendingPreKey: null,
|
||||
aliceBaseKey: 'BUFOv0MAbMgKeaoO/G1CMBdqhC7bo7Mtc4EWxI0oT19N',
|
||||
},
|
||||
{
|
||||
@@ -908,6 +943,7 @@ describe('sessionTranslation', () => {
|
||||
receiverChains: [
|
||||
{
|
||||
senderRatchetKey: 'BQo3HG1UhWIh6A7NBxZtNGezBZH8nElZjOqNCBHPzlBz',
|
||||
senderRatchetKeyPrivate: null,
|
||||
chainKey: {
|
||||
index: 6,
|
||||
key: 'Wnvy2TjYs0HdZFNahmsKw5cc9KEbW1nSwraDFmGwBDw=',
|
||||
@@ -930,6 +966,8 @@ describe('sessionTranslation', () => {
|
||||
],
|
||||
remoteRegistrationId: 3432,
|
||||
localRegistrationId: 3554,
|
||||
needsRefresh: null,
|
||||
pendingPreKey: null,
|
||||
aliceBaseKey: 'BUJEv1oAbMgKeaoO/G1CMBdqhC7bo7Mtc4EWxI0oT19N',
|
||||
},
|
||||
],
|
||||
@@ -991,6 +1029,7 @@ describe('sessionTranslation', () => {
|
||||
aliceBaseKey: 'BTU+PWVWuRnbiW6+ja+XI9+2Xz0TLk7uGqUlhS1d+V8K',
|
||||
localIdentityPublic: 'Baioqfzc/5JD6b+GNqapPouf6eHK7xr9ynLJHnvl+444',
|
||||
localRegistrationId: 3554,
|
||||
needsRefresh: null,
|
||||
pendingPreKey: {
|
||||
baseKey: 'BTU+PWVWuRnbiW6+ja+XI9+2Xz0TLk7uGqUlhS1d+V8K',
|
||||
preKeyId: 386,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import Long from 'long';
|
||||
|
||||
import {
|
||||
getSafeLongFromTimestamp,
|
||||
@@ -12,34 +11,38 @@ import {
|
||||
getCheckedTimestampOrUndefinedFromLong,
|
||||
} from '../../util/timestampLongUtils.std.js';
|
||||
import { MAX_SAFE_DATE } from '../../util/timestamp.std.js';
|
||||
import { MAX_VALUE } from '../../util/long.std.js';
|
||||
|
||||
import { toNumber } from '../../util/toNumber.std.js';
|
||||
|
||||
describe('getSafeLongFromTimestamp', () => {
|
||||
it('returns zero when passed undefined', () => {
|
||||
assert(getSafeLongFromTimestamp(undefined).isZero());
|
||||
assert.strictEqual(getSafeLongFromTimestamp(undefined), 0n);
|
||||
});
|
||||
|
||||
it('returns the number as a Long when passed a "normal" number', () => {
|
||||
assert(getSafeLongFromTimestamp(0).isZero());
|
||||
assert.strictEqual(getSafeLongFromTimestamp(0), 0n);
|
||||
assert.strictEqual(getSafeLongFromTimestamp(123).toString(), '123');
|
||||
assert.strictEqual(getSafeLongFromTimestamp(-456).toString(), '-456');
|
||||
});
|
||||
|
||||
it('returns MAX_SAFE_DATE when passed Infinity', () => {
|
||||
assert.strictEqual(
|
||||
getSafeLongFromTimestamp(Infinity).toNumber(),
|
||||
toNumber(getSafeLongFromTimestamp(Infinity)),
|
||||
MAX_SAFE_DATE
|
||||
);
|
||||
});
|
||||
|
||||
it('returns Long.MAX_VALUE when passed Infinity and overriden', () => {
|
||||
assert(
|
||||
getSafeLongFromTimestamp(Infinity, Long.MAX_VALUE).equals(Long.MAX_VALUE)
|
||||
it('returns MAX_VALUE when passed Infinity and overriden', () => {
|
||||
assert.strictEqual(
|
||||
getSafeLongFromTimestamp(Infinity, MAX_VALUE),
|
||||
MAX_VALUE
|
||||
);
|
||||
});
|
||||
|
||||
it("returns MAX_SAFE_DATE when passed very large numbers, outside of JavaScript's safely representable range", () => {
|
||||
assert.strictEqual(
|
||||
getSafeLongFromTimestamp(Number.MAX_VALUE).toNumber(),
|
||||
toNumber(getSafeLongFromTimestamp(Number.MAX_VALUE)),
|
||||
MAX_SAFE_DATE
|
||||
);
|
||||
});
|
||||
@@ -47,19 +50,19 @@ describe('getSafeLongFromTimestamp', () => {
|
||||
|
||||
describe('getTimestampFromLong', () => {
|
||||
it('returns zero when passed negative Long', () => {
|
||||
assert.equal(getTimestampFromLong(Long.fromNumber(-1)), 0);
|
||||
assert.equal(getTimestampFromLong(BigInt(-1)), 0);
|
||||
});
|
||||
|
||||
it('returns zero when passed 0 Long', () => {
|
||||
assert.equal(getTimestampFromLong(Long.fromNumber(0)), 0);
|
||||
assert.equal(getTimestampFromLong(0n), 0);
|
||||
});
|
||||
|
||||
it('returns MAX_SAFE_DATE when passed Long.MAX_VALUE', () => {
|
||||
assert.equal(getTimestampFromLong(Long.MAX_VALUE), MAX_SAFE_DATE);
|
||||
it('returns MAX_SAFE_DATE when passed MAX_VALUE', () => {
|
||||
assert.equal(getTimestampFromLong(MAX_VALUE), MAX_SAFE_DATE);
|
||||
});
|
||||
|
||||
it('returns a normal number', () => {
|
||||
assert.equal(getTimestampFromLong(Long.fromNumber(16)), 16);
|
||||
assert.equal(getTimestampFromLong(16n), 16);
|
||||
});
|
||||
|
||||
it('returns 0 for null value', () => {
|
||||
@@ -73,35 +76,29 @@ describe('getCheckedTimestampFromLong', () => {
|
||||
});
|
||||
|
||||
it('throws on negative Long', () => {
|
||||
assert.throws(() => getCheckedTimestampFromLong(Long.fromNumber(-1)));
|
||||
assert.throws(() => getCheckedTimestampFromLong(BigInt(-1)));
|
||||
});
|
||||
|
||||
it('throws on Long.MAX_VALUE', () => {
|
||||
assert.throws(() => getCheckedTimestampFromLong(Long.MAX_VALUE));
|
||||
it('throws on MAX_VALUE', () => {
|
||||
assert.throws(() => getCheckedTimestampFromLong(MAX_VALUE));
|
||||
});
|
||||
|
||||
it('does not throw otherwise', () => {
|
||||
assert.equal(getCheckedTimestampFromLong(Long.fromNumber(16)), 16);
|
||||
assert.equal(getCheckedTimestampFromLong(16n), 16);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTimestampOrUndefinedFromLong', () => {
|
||||
it('returns undefined when passed 0 Long', () => {
|
||||
assert.equal(
|
||||
getTimestampOrUndefinedFromLong(Long.fromNumber(0)),
|
||||
undefined
|
||||
);
|
||||
assert.equal(getTimestampOrUndefinedFromLong(0n), undefined);
|
||||
});
|
||||
|
||||
it('returns MAX_SAFE_DATE when passed Long.MAX_VALUE', () => {
|
||||
assert.equal(
|
||||
getTimestampOrUndefinedFromLong(Long.MAX_VALUE),
|
||||
MAX_SAFE_DATE
|
||||
);
|
||||
it('returns MAX_SAFE_DATE when passed MAX_VALUE', () => {
|
||||
assert.equal(getTimestampOrUndefinedFromLong(MAX_VALUE), MAX_SAFE_DATE);
|
||||
});
|
||||
|
||||
it('returns a normal number', () => {
|
||||
assert.equal(getTimestampOrUndefinedFromLong(Long.fromNumber(16)), 16);
|
||||
assert.equal(getTimestampOrUndefinedFromLong(16n), 16);
|
||||
});
|
||||
|
||||
it('returns undefined for null value', () => {
|
||||
@@ -111,9 +108,7 @@ describe('getTimestampOrUndefinedFromLong', () => {
|
||||
|
||||
describe('getCheckedTimestampOrUndefinedFromLong', () => {
|
||||
it('throws on negative Long', () => {
|
||||
assert.throws(() =>
|
||||
getCheckedTimestampOrUndefinedFromLong(Long.fromNumber(-1))
|
||||
);
|
||||
assert.throws(() => getCheckedTimestampOrUndefinedFromLong(-1n));
|
||||
});
|
||||
|
||||
it('returns undefined on absent Long', () => {
|
||||
@@ -121,13 +116,10 @@ describe('getCheckedTimestampOrUndefinedFromLong', () => {
|
||||
});
|
||||
|
||||
it('returns undefined on zero Long', () => {
|
||||
assert.equal(getCheckedTimestampOrUndefinedFromLong(Long.ZERO), undefined);
|
||||
assert.equal(getCheckedTimestampOrUndefinedFromLong(0n), undefined);
|
||||
});
|
||||
|
||||
it('returns a normal number', () => {
|
||||
assert.equal(
|
||||
getCheckedTimestampOrUndefinedFromLong(Long.fromNumber(16)),
|
||||
16
|
||||
);
|
||||
assert.equal(getCheckedTimestampOrUndefinedFromLong(16n), 16);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user