test: add tests for pendingchangesforus

pull/2873/head
Audric Ackermann 2 years ago
parent d134da3421
commit ceffa1e13b

@ -16,14 +16,14 @@ import {
GenericWrapperActions,
MetaGroupWrapperActions,
} from '../../../webworker/workers/browser/libsession_worker_interface';
import { SnodeNamespaces, UserConfigNamespaces } from '../../apis/snode_api/namespaces';
import { ed25519Str } from '../../onions/onionPath';
import { PubKey } from '../../types';
import { UserSync } from '../job_runners/jobs/UserSyncJob';
import {
BatchResultEntry,
NotEmptyArrayOfBatchResults,
} from '../../apis/snode_api/SnodeRequestTypes';
import { SnodeNamespaces, UserConfigNamespaces } from '../../apis/snode_api/namespaces';
import { ed25519Str } from '../../onions/onionPath';
import { PubKey } from '../../types';
import { UserSync } from '../job_runners/jobs/UserSyncJob';
const requiredUserVariants: Array<ConfigWrapperUser> = [
'UserConfig',
@ -165,7 +165,7 @@ async function pendingChangesForUs(): Promise<UserDestinationChanges> {
namespace, // we only use the namespace to know to wha
});
hashes.forEach(results.allOldHashes.add); // add all the hashes to the set
hashes.forEach(h => results.allOldHashes.add(h)); // add all the hashes to the set
}
window.log.info(`those user variants needs push: "${[...variantsNeedingPush]}"`);

@ -299,9 +299,7 @@ const decryptBlindedMessage = async (
const version = data[0];
if (version !== 0) {
window?.log?.error(
'decryptBlindedMessage - Dropping message due to unsupported encryption version'
);
console.warn('decryptBlindedMessage - Dropping message due to unsupported encryption version');
return undefined;
}
@ -319,7 +317,7 @@ const decryptBlindedMessage = async (
if (plaintextIncoming.length <= 32) {
// throw Error;
window?.log?.error('decryptBlindedMessage: plaintext insufficient length');
console.error('decryptBlindedMessage: plaintext insufficient length');
return undefined;
}

@ -0,0 +1,352 @@
import { expect } from 'chai';
import { GroupPubkeyType, PubkeyType } from 'libsession_util_nodejs';
import { randombytes_buf } from 'libsodium-wrappers-sumo';
import Long from 'long';
import Sinon from 'sinon';
import { ConfigDumpData } from '../../../../data/configDump/configDump';
import { GetNetworkTime } from '../../../../session/apis/snode_api/getNetworkTime';
import { SnodeNamespaces } from '../../../../session/apis/snode_api/namespaces';
import { UserUtils } from '../../../../session/utils';
import { LibSessionUtil } from '../../../../session/utils/libsession/libsession_utils';
import {
GenericWrapperActions,
MetaGroupWrapperActions,
} from '../../../../webworker/workers/browser/libsession_worker_interface';
import { TestUtils } from '../../../test-utils';
describe('LibSessionUtil saveDumpsToDb', () => {
describe('for group', () => {
let groupPk: GroupPubkeyType;
beforeEach(() => {
groupPk = TestUtils.generateFakeClosedGroupV3PkStr();
});
afterEach(() => {
Sinon.restore();
});
it('does not save to DB if needsDump reports false', async () => {
Sinon.stub(MetaGroupWrapperActions, 'needsDump').resolves(false);
const metaDump = Sinon.stub(MetaGroupWrapperActions, 'metaDump').resolves(new Uint8Array());
const saveConfigDump = Sinon.stub(ConfigDumpData, 'saveConfigDump').resolves();
await LibSessionUtil.saveDumpsToDb(groupPk);
expect(saveConfigDump.callCount).to.be.equal(0);
expect(metaDump.callCount).to.be.equal(0);
});
it('does save to DB if needsDump reports true', async () => {
Sinon.stub(MetaGroupWrapperActions, 'needsDump').resolves(true);
const dump = [1, 2, 3, 4, 5];
const metaDump = Sinon.stub(MetaGroupWrapperActions, 'metaDump').resolves(
new Uint8Array(dump)
);
const saveConfigDump = Sinon.stub(ConfigDumpData, 'saveConfigDump').resolves();
await LibSessionUtil.saveDumpsToDb(groupPk);
expect(saveConfigDump.callCount).to.be.equal(1);
expect(metaDump.callCount).to.be.equal(1);
expect(metaDump.firstCall.args).to.be.deep.eq([groupPk]);
expect(saveConfigDump.firstCall.args).to.be.deep.eq([
{
publicKey: groupPk,
variant: `MetaGroupConfig-${groupPk}`,
data: new Uint8Array(dump),
},
]);
});
});
describe('for user', () => {
let userDetails: TestUtils.TestUserKeyPairs;
let sessionId: PubkeyType;
beforeEach(async () => {
userDetails = await TestUtils.generateUserKeyPairs();
sessionId = userDetails.x25519KeyPair.pubkeyHex;
});
afterEach(() => {
Sinon.restore();
});
it('does not save to DB if all needsDump reports false', async () => {
Sinon.stub(GenericWrapperActions, 'needsDump').resolves(false);
const dump = Sinon.stub(GenericWrapperActions, 'dump').resolves(new Uint8Array());
const saveConfigDump = Sinon.stub(ConfigDumpData, 'saveConfigDump').resolves();
Sinon.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(sessionId);
await LibSessionUtil.saveDumpsToDb(sessionId);
expect(saveConfigDump.callCount).to.be.equal(0);
expect(dump.callCount).to.be.equal(0);
});
it('does save to DB if any needsDump reports true', async () => {
Sinon.stub(GenericWrapperActions, 'needsDump')
.resolves(false)
.withArgs('ConvoInfoVolatileConfig')
.resolves(true);
const dump = Sinon.stub(GenericWrapperActions, 'dump').resolves(new Uint8Array());
const saveConfigDump = Sinon.stub(ConfigDumpData, 'saveConfigDump').resolves();
Sinon.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(sessionId);
await LibSessionUtil.saveDumpsToDb(sessionId);
expect(saveConfigDump.callCount).to.be.equal(1);
expect(dump.callCount).to.be.equal(1);
});
it('does save to DB if all needsDump reports true', async () => {
const needsDump = Sinon.stub(GenericWrapperActions, 'needsDump').resolves(true);
const dumped = new Uint8Array([1, 2, 3]);
const dump = Sinon.stub(GenericWrapperActions, 'dump').resolves(dumped);
const saveConfigDump = Sinon.stub(ConfigDumpData, 'saveConfigDump').resolves();
Sinon.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(sessionId);
await LibSessionUtil.saveDumpsToDb(userDetails.x25519KeyPair.pubkeyHex);
expect(needsDump.callCount).to.be.equal(4);
expect(dump.callCount).to.be.equal(4);
expect(needsDump.getCalls().map(call => call.args)).to.be.deep.eq([
['UserConfig'],
['ContactsConfig'],
['UserGroupsConfig'],
['ConvoInfoVolatileConfig'],
]);
expect(saveConfigDump.callCount).to.be.equal(4);
expect(saveConfigDump.getCalls().map(call => call.args)).to.be.deep.eq([
[{ variant: 'UserConfig', publicKey: sessionId, data: dumped }],
[{ variant: 'ContactsConfig', publicKey: sessionId, data: dumped }],
[{ variant: 'UserGroupsConfig', publicKey: sessionId, data: dumped }],
[{ variant: 'ConvoInfoVolatileConfig', publicKey: sessionId, data: dumped }],
]);
expect(dump.getCalls().map(call => call.args)).to.be.deep.eq([
['UserConfig'],
['ContactsConfig'],
['UserGroupsConfig'],
['ConvoInfoVolatileConfig'],
]);
});
});
});
describe('LibSessionUtil pendingChangesForGroup', () => {
let groupPk: GroupPubkeyType;
beforeEach(() => {
groupPk = TestUtils.generateFakeClosedGroupV3PkStr();
});
afterEach(() => {
Sinon.restore();
});
it('empty results if needsPush is false', async () => {
Sinon.stub(MetaGroupWrapperActions, 'needsPush').resolves(false);
const result = await LibSessionUtil.pendingChangesForGroup(groupPk);
expect(result.allOldHashes.size).to.be.equal(0);
expect(result.messages.length).to.be.equal(0);
});
it('valid results if needsPush is true', async () => {
const pushResults = {
groupKeys: { data: new Uint8Array([3, 2, 1]), namespace: 13 },
groupInfo: {
seqno: 1,
data: new Uint8Array([1, 2, 3]),
hashes: ['123', '333'],
namespace: 12,
},
groupMember: {
seqno: 2,
data: new Uint8Array([1, 2]),
hashes: ['321', '111'],
namespace: 14,
},
};
Sinon.stub(MetaGroupWrapperActions, 'needsPush').resolves(true);
Sinon.stub(MetaGroupWrapperActions, 'push').resolves(pushResults);
Sinon.stub(GetNetworkTime, 'getNowWithNetworkOffset').returns(1234);
const result = await LibSessionUtil.pendingChangesForGroup(groupPk);
expect(result.allOldHashes.size).to.be.equal(4);
// check that all of the hashes are there
expect([...result.allOldHashes]).to.have.members([
...pushResults.groupInfo.hashes,
...pushResults.groupMember.hashes,
]);
expect(result.messages.length).to.be.equal(3);
// check for the keys push content
expect(result.messages[0]).to.be.deep.eq({
type: 'GroupKeys',
ciphertext: new Uint8Array([3, 2, 1]),
namespace: 13,
});
// check for the info push content
expect(result.messages[1]).to.be.deep.eq({
type: 'GroupInfo',
ciphertext: new Uint8Array([1, 2, 3]),
namespace: 12,
seqno: Long.fromInt(pushResults.groupInfo.seqno),
});
// check for the members pusu content
expect(result.messages[2]).to.be.deep.eq({
type: 'GroupMember',
ciphertext: new Uint8Array([1, 2]),
namespace: 14,
seqno: Long.fromInt(pushResults.groupMember.seqno),
});
});
it('skips entry results if needsPush one of the wrapper has no changes', async () => {
const pushResults = {
groupInfo: {
seqno: 1,
data: new Uint8Array([1, 2, 3]),
hashes: ['123', '333'],
namespace: 12,
},
groupMember: null,
groupKeys: { data: new Uint8Array([3, 2, 1]), namespace: 13 },
};
Sinon.stub(MetaGroupWrapperActions, 'needsPush').resolves(true);
Sinon.stub(MetaGroupWrapperActions, 'push').resolves(pushResults);
const result = await LibSessionUtil.pendingChangesForGroup(groupPk);
expect(result.allOldHashes.size).to.be.equal(2);
expect(result.messages.length).to.be.equal(2);
});
});
describe('LibSessionUtil pendingChangesForUser', () => {
beforeEach(async () => {});
afterEach(() => {
Sinon.restore();
});
it('empty results if all needsPush is false', async () => {
Sinon.stub(GenericWrapperActions, 'needsPush').resolves(false);
const result = await LibSessionUtil.pendingChangesForUs();
expect(result.allOldHashes.size).to.be.equal(0);
expect(result.messages.length).to.be.equal(0);
});
it('valid results if ConvoVolatile needsPush only is true', async () => {
// this is what would be supposedly returned by libsession
const pushResultsConvo = {
data: randombytes_buf(300),
seqno: 123,
hashes: ['123'],
namespace: SnodeNamespaces.ConvoInfoVolatile,
};
const needsPush = Sinon.stub(GenericWrapperActions, 'needsPush');
needsPush.resolves(false).withArgs('ConvoInfoVolatileConfig').resolves(true);
const push = Sinon.stub(GenericWrapperActions, 'push')
.throws()
.withArgs('ConvoInfoVolatileConfig')
.resolves(pushResultsConvo);
Sinon.stub(GetNetworkTime, 'getNowWithNetworkOffset').returns(1234);
const result = await LibSessionUtil.pendingChangesForUs();
expect(needsPush.callCount).to.be.eq(4);
expect(needsPush.getCalls().map(m => m.args)).to.be.deep.eq([
['UserConfig'],
['ContactsConfig'],
['UserGroupsConfig'],
['ConvoInfoVolatileConfig'],
]);
expect(push.callCount).to.be.eq(1);
expect(push.getCalls().map(m => m.args)).to.be.deep.eq([['ConvoInfoVolatileConfig']]);
// check that all of the hashes are there
expect(result.allOldHashes.size).to.be.equal(1);
expect([...result.allOldHashes]).to.have.members([...pushResultsConvo.hashes]);
// check for the messages to push are what we expect
expect(result.messages).to.be.deep.eq([
{
ciphertext: pushResultsConvo.data,
namespace: pushResultsConvo.namespace,
seqno: Long.fromNumber(pushResultsConvo.seqno),
},
]);
});
it('valid results if all wrappers needsPush only are true', async () => {
// this is what would be supposedly returned by libsession
const pushConvo = {
data: randombytes_buf(300),
seqno: 123,
hashes: ['123'],
namespace: SnodeNamespaces.ConvoInfoVolatile,
};
const pushContacts = {
data: randombytes_buf(300),
seqno: 321,
hashes: ['321', '4444'],
namespace: SnodeNamespaces.UserContacts,
};
const pushGroups = {
data: randombytes_buf(300),
seqno: 222,
hashes: ['222', '5555'],
namespace: SnodeNamespaces.UserGroups,
};
const pushUser = {
data: randombytes_buf(300),
seqno: 111,
hashes: ['111'],
namespace: SnodeNamespaces.UserProfile,
};
const needsPush = Sinon.stub(GenericWrapperActions, 'needsPush');
needsPush.resolves(true);
const push = Sinon.stub(GenericWrapperActions, 'push');
push
.throws()
.withArgs('ContactsConfig')
.resolves(pushContacts)
.withArgs('UserConfig')
.resolves(pushUser)
.withArgs('UserGroupsConfig')
.resolves(pushGroups)
.withArgs('ConvoInfoVolatileConfig')
.resolves(pushConvo);
Sinon.stub(GetNetworkTime, 'getNowWithNetworkOffset').returns(1234);
const result = await LibSessionUtil.pendingChangesForUs();
expect(needsPush.callCount).to.be.eq(4);
expect(needsPush.getCalls().map(m => m.args)).to.be.deep.eq([
['UserConfig'],
['ContactsConfig'],
['UserGroupsConfig'],
['ConvoInfoVolatileConfig'],
]);
expect(push.callCount).to.be.eq(4);
expect(push.getCalls().map(m => m.args)).to.be.deep.eq([
['UserConfig'],
['ContactsConfig'],
['UserGroupsConfig'],
['ConvoInfoVolatileConfig'],
]);
// check that all of the hashes are there
expect(result.allOldHashes.size).to.be.equal(6);
expect([...result.allOldHashes]).to.have.members([
...pushContacts.hashes,
...pushConvo.hashes,
...pushGroups.hashes,
...pushUser.hashes,
]);
// check for the messages to push are what we expect
expect(result.messages).to.be.deep.eq(
[pushUser, pushContacts, pushGroups, pushConvo].map(m => ({
ciphertext: m.data,
namespace: m.namespace,
seqno: Long.fromNumber(m.seqno),
}))
);
});
});

@ -3,7 +3,6 @@ import { GroupPubkeyType } from 'libsession_util_nodejs';
import { omit } from 'lodash';
import Long from 'long';
import Sinon from 'sinon';
import { ConfigDumpData } from '../../../../../../data/configDump/configDump';
import { getSodiumNode } from '../../../../../../node/sodiumNode';
import { NotEmptyArrayOfBatchResults } from '../../../../../../session/apis/snode_api/SnodeRequestTypes';
import { GetNetworkTime } from '../../../../../../session/apis/snode_api/getNetworkTime';
@ -53,132 +52,6 @@ function validKeys(sodium: LibSodiumWrappers) {
} as const;
}
describe('GroupSyncJob saveDumpsToDb', () => {
let groupPk: GroupPubkeyType;
beforeEach(async () => {});
beforeEach(() => {
groupPk = TestUtils.generateFakeClosedGroupV3PkStr();
});
afterEach(() => {
Sinon.restore();
});
it('does not save to DB if needsDump reports false', async () => {
Sinon.stub(MetaGroupWrapperActions, 'needsDump').resolves(false);
const metaDump = Sinon.stub(MetaGroupWrapperActions, 'metaDump').resolves(new Uint8Array());
const saveConfigDump = Sinon.stub(ConfigDumpData, 'saveConfigDump').resolves();
await LibSessionUtil.saveDumpsToDb(groupPk);
expect(saveConfigDump.callCount).to.be.equal(0);
expect(metaDump.callCount).to.be.equal(0);
});
it('does save to DB if needsDump reports true', async () => {
Sinon.stub(MetaGroupWrapperActions, 'needsDump').resolves(true);
const dump = [1, 2, 3, 4, 5];
const metaDump = Sinon.stub(MetaGroupWrapperActions, 'metaDump').resolves(new Uint8Array(dump));
const saveConfigDump = Sinon.stub(ConfigDumpData, 'saveConfigDump').resolves();
await LibSessionUtil.saveDumpsToDb(groupPk);
expect(saveConfigDump.callCount).to.be.equal(1);
expect(metaDump.callCount).to.be.equal(1);
expect(metaDump.firstCall.args).to.be.deep.eq([groupPk]);
expect(saveConfigDump.firstCall.args).to.be.deep.eq([
{
publicKey: groupPk,
variant: `MetaGroupConfig-${groupPk}`,
data: new Uint8Array(dump),
},
]);
});
});
describe('GroupSyncJob pendingChangesForGroup', () => {
let groupPk: GroupPubkeyType;
beforeEach(() => {
groupPk = TestUtils.generateFakeClosedGroupV3PkStr();
});
afterEach(() => {
Sinon.restore();
});
it('empty results if needsPush is false', async () => {
Sinon.stub(MetaGroupWrapperActions, 'needsPush').resolves(false);
const result = await LibSessionUtil.pendingChangesForGroup(groupPk);
expect(result.allOldHashes.size).to.be.equal(0);
expect(result.messages.length).to.be.equal(0);
});
it('valid results if needsPush is true', async () => {
const pushResults = {
groupKeys: { data: new Uint8Array([3, 2, 1]), namespace: 13 },
groupInfo: {
seqno: 1,
data: new Uint8Array([1, 2, 3]),
hashes: ['123', '333'],
namespace: 12,
},
groupMember: {
seqno: 2,
data: new Uint8Array([1, 2]),
hashes: ['321', '111'],
namespace: 14,
},
};
Sinon.stub(MetaGroupWrapperActions, 'needsPush').resolves(true);
Sinon.stub(MetaGroupWrapperActions, 'push').resolves(pushResults);
Sinon.stub(GetNetworkTime, 'getNowWithNetworkOffset').returns(1234);
const result = await LibSessionUtil.pendingChangesForGroup(groupPk);
expect(result.allOldHashes.size).to.be.equal(4);
// check that all of the hashes are there
expect([...result.allOldHashes]).to.have.members([
...pushResults.groupInfo.hashes,
...pushResults.groupMember.hashes,
]);
expect(result.messages.length).to.be.equal(3);
// check for the keys push content
expect(result.messages[0]).to.be.deep.eq({
type: 'GroupKeys',
ciphertext: new Uint8Array([3, 2, 1]),
namespace: 13,
});
// check for the info push content
expect(result.messages[1]).to.be.deep.eq({
type: 'GroupInfo',
ciphertext: new Uint8Array([1, 2, 3]),
namespace: 12,
seqno: Long.fromInt(pushResults.groupInfo.seqno),
});
// check for the members pusu content
expect(result.messages[2]).to.be.deep.eq({
type: 'GroupMember',
ciphertext: new Uint8Array([1, 2]),
namespace: 14,
seqno: Long.fromInt(pushResults.groupMember.seqno),
});
});
it('skips entry results if needsPush one of the wrapper has no changes', async () => {
const pushResults = {
groupInfo: {
seqno: 1,
data: new Uint8Array([1, 2, 3]),
hashes: ['123', '333'],
namespace: 12,
},
groupMember: null,
groupKeys: { data: new Uint8Array([3, 2, 1]), namespace: 13 },
};
Sinon.stub(MetaGroupWrapperActions, 'needsPush').resolves(true);
Sinon.stub(MetaGroupWrapperActions, 'push').resolves(pushResults);
const result = await LibSessionUtil.pendingChangesForGroup(groupPk);
expect(result.allOldHashes.size).to.be.equal(2);
expect(result.messages.length).to.be.equal(2);
});
});
describe('GroupSyncJob run()', () => {
afterEach(() => {
Sinon.restore();

@ -1,5 +1,5 @@
import * as crypto from 'crypto';
import { GroupPubkeyType, UserGroupsWrapperNode } from 'libsession_util_nodejs';
import { GroupPubkeyType, PubkeyType, UserGroupsWrapperNode } from 'libsession_util_nodejs';
import { KeyPair, to_hex } from 'libsodium-wrappers-sumo';
import _ from 'lodash';
import { Snode } from '../../../data/data';
@ -28,7 +28,7 @@ export function generateFakePubKeyStr(): string {
export type TestUserKeyPairs = {
x25519KeyPair: {
pubkeyHex: string;
pubkeyHex: PubkeyType;
pubKey: Uint8Array;
privKey: Uint8Array;
};
@ -51,7 +51,7 @@ export async function generateUserKeyPairs(): Promise<TestUserKeyPairs> {
// prepend with 05 the public key
const userKeys = {
x25519KeyPair: {
pubkeyHex: to_hex(prependedX25519PublicKey),
pubkeyHex: to_hex(prependedX25519PublicKey) as PubkeyType,
pubKey: prependedX25519PublicKey,
privKey: x25519SecretKey,
},

Loading…
Cancel
Save