|
|
|
@ -20,6 +20,8 @@ import {
|
|
|
|
|
} from '../../../../models/conversation';
|
|
|
|
|
import { PubKey } from '../../../../session/types';
|
|
|
|
|
import { generateFakeSnodes } from '../../../test-utils/utils';
|
|
|
|
|
import { resetHardForkCachedValues } from '../../../../session/apis/snode_api/hfHandling';
|
|
|
|
|
import { sleepFor } from '../../../../session/utils/Promise';
|
|
|
|
|
// tslint:disable: chai-vague-errors
|
|
|
|
|
|
|
|
|
|
chai.use(chaiAsPromised as any);
|
|
|
|
@ -37,6 +39,7 @@ describe('SwarmPolling', () => {
|
|
|
|
|
let pollOnceForKeySpy: Sinon.SinonSpy<any>;
|
|
|
|
|
|
|
|
|
|
let swarmPolling: SwarmPolling;
|
|
|
|
|
let getItemByIdStub: Sinon.SinonStub;
|
|
|
|
|
|
|
|
|
|
let clock: Sinon.SinonFakeTimers;
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
@ -44,7 +47,7 @@ describe('SwarmPolling', () => {
|
|
|
|
|
Sinon.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(ourNumber);
|
|
|
|
|
|
|
|
|
|
Sinon.stub(Data, 'getAllConversations').resolves(new ConversationCollection());
|
|
|
|
|
Sinon.stub(DataItem, 'getItemById').resolves();
|
|
|
|
|
getItemByIdStub = TestUtils.stubDataItem('getItemById');
|
|
|
|
|
Sinon.stub(Data, 'saveConversation').resolves();
|
|
|
|
|
Sinon.stub(Data, 'getSwarmNodesForPubkey').resolves();
|
|
|
|
|
Sinon.stub(Data, 'getLastHashBySnode').resolves();
|
|
|
|
@ -70,6 +73,7 @@ describe('SwarmPolling', () => {
|
|
|
|
|
Sinon.restore();
|
|
|
|
|
getConversationController().reset();
|
|
|
|
|
clock.restore();
|
|
|
|
|
resetHardForkCachedValues();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('getPollingTimeout', () => {
|
|
|
|
@ -130,6 +134,12 @@ describe('SwarmPolling', () => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('pollForAllKeys', () => {
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
Sinon.stub(DataItem, 'createOrUpdateItem').resolves();
|
|
|
|
|
});
|
|
|
|
|
afterEach(() => {
|
|
|
|
|
Sinon.restore();
|
|
|
|
|
});
|
|
|
|
|
it('does run for our pubkey even if activeAt is really old ', async () => {
|
|
|
|
|
const convo = getConversationController().getOrCreate(
|
|
|
|
|
ourNumber,
|
|
|
|
@ -139,7 +149,19 @@ describe('SwarmPolling', () => {
|
|
|
|
|
await swarmPolling.start(true);
|
|
|
|
|
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(1);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run for our pubkey even if activeAt is recent ', async () => {
|
|
|
|
|
const convo = getConversationController().getOrCreate(
|
|
|
|
|
ourNumber,
|
|
|
|
|
ConversationTypeEnum.PRIVATE
|
|
|
|
|
);
|
|
|
|
|
convo.set('active_at', Date.now());
|
|
|
|
|
await swarmPolling.start(true);
|
|
|
|
|
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(1);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run for our pubkey even if activeAt is recent ', async () => {
|
|
|
|
@ -151,7 +173,7 @@ describe('SwarmPolling', () => {
|
|
|
|
|
await swarmPolling.start(true);
|
|
|
|
|
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(1);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run for group pubkey on start no matter the recent timestamp ', async () => {
|
|
|
|
@ -166,11 +188,11 @@ describe('SwarmPolling', () => {
|
|
|
|
|
|
|
|
|
|
// our pubkey will be polled for, hence the 2
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(2);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run for group pubkey on start no matter the old timestamp ', async () => {
|
|
|
|
|
it('does run for group pubkey on start no matter the old timestamp if HF < 19', async () => {
|
|
|
|
|
const convo = getConversationController().getOrCreate(
|
|
|
|
|
TestUtils.generateFakePubKeyStr(),
|
|
|
|
|
ConversationTypeEnum.GROUP
|
|
|
|
@ -183,8 +205,67 @@ describe('SwarmPolling', () => {
|
|
|
|
|
|
|
|
|
|
// our pubkey will be polled for, hence the 2
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(2);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run for group pubkey on start no matter the old timestamp if HF >= 19.0 & < 19.1 ', async () => {
|
|
|
|
|
const convo = getConversationController().getOrCreate(
|
|
|
|
|
TestUtils.generateFakePubKeyStr(),
|
|
|
|
|
ConversationTypeEnum.GROUP
|
|
|
|
|
);
|
|
|
|
|
getItemByIdStub.restore();
|
|
|
|
|
getItemByIdStub = TestUtils.stubDataItem('getItemById');
|
|
|
|
|
getItemByIdStub
|
|
|
|
|
.withArgs('hasSeenHardfork190')
|
|
|
|
|
.resolves({ id: 'hasSeenHardfork190', value: true })
|
|
|
|
|
.withArgs('hasSeenHardfork191')
|
|
|
|
|
.resolves({ id: 'hasSeenHardfork191', value: false });
|
|
|
|
|
|
|
|
|
|
convo.set('active_at', 1);
|
|
|
|
|
const groupConvoPubkey = PubKey.cast(convo.id as string);
|
|
|
|
|
swarmPolling.addGroupId(groupConvoPubkey);
|
|
|
|
|
|
|
|
|
|
await swarmPolling.start(true);
|
|
|
|
|
|
|
|
|
|
// our pubkey will be polled for, hence the 2
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(3);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([groupConvoPubkey, true, -10]);
|
|
|
|
|
getItemByIdStub.restore();
|
|
|
|
|
getItemByIdStub = TestUtils.stubDataItem('getItemById');
|
|
|
|
|
|
|
|
|
|
getItemByIdStub.resolves();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does only poll from -10 for closed groups if HF >= 19.1 ', async () => {
|
|
|
|
|
const convo = getConversationController().getOrCreate(
|
|
|
|
|
TestUtils.generateFakePubKeyStr(),
|
|
|
|
|
ConversationTypeEnum.GROUP
|
|
|
|
|
);
|
|
|
|
|
getItemByIdStub.restore();
|
|
|
|
|
getItemByIdStub = TestUtils.stubDataItem('getItemById');
|
|
|
|
|
getItemByIdStub
|
|
|
|
|
.withArgs('hasSeenHardfork190')
|
|
|
|
|
.resolves({ id: 'hasSeenHardfork190', value: true })
|
|
|
|
|
.withArgs('hasSeenHardfork191')
|
|
|
|
|
.resolves({ id: 'hasSeenHardfork191', value: true });
|
|
|
|
|
|
|
|
|
|
convo.set('active_at', 1);
|
|
|
|
|
const groupConvoPubkey = PubKey.cast(convo.id as string);
|
|
|
|
|
swarmPolling.addGroupId(groupConvoPubkey);
|
|
|
|
|
|
|
|
|
|
await swarmPolling.start(true);
|
|
|
|
|
|
|
|
|
|
// our pubkey will be polled for, hence the 2
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(2);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true, -10]);
|
|
|
|
|
getItemByIdStub.restore();
|
|
|
|
|
getItemByIdStub = TestUtils.stubDataItem('getItemById');
|
|
|
|
|
|
|
|
|
|
getItemByIdStub.resolves();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run for group pubkey on start but not another time if activeAt is old ', async () => {
|
|
|
|
@ -204,9 +285,9 @@ describe('SwarmPolling', () => {
|
|
|
|
|
await swarmPolling.pollForAllKeys();
|
|
|
|
|
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(3);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run twice if activeAt less than one hour ', async () => {
|
|
|
|
@ -219,14 +300,21 @@ describe('SwarmPolling', () => {
|
|
|
|
|
const groupConvoPubkey = PubKey.cast(convo.id as string);
|
|
|
|
|
swarmPolling.addGroupId(groupConvoPubkey);
|
|
|
|
|
await swarmPolling.start(true);
|
|
|
|
|
clock.tick(6000);
|
|
|
|
|
// no need to do that as the tick will trigger a call in all cases after 5 secs
|
|
|
|
|
// await swarmPolling.pollForAllKeys();
|
|
|
|
|
clock.tick(9000);
|
|
|
|
|
// no need to do that as the tick will trigger a call in all cases after 5 secs await swarmPolling.pollForAllKeys();
|
|
|
|
|
/** this is not easy to explain, but
|
|
|
|
|
* - during the swarmPolling.start, we get two calls to pollOnceForKeySpy (one for our id and one for group od)
|
|
|
|
|
* - the clock ticks 9sec, and another call of pollOnceForKeySpy get started, but as we do not await them, this test fails.
|
|
|
|
|
* the only fix is to restore the clock and force the a small sleep to let the thing run in bg
|
|
|
|
|
*/
|
|
|
|
|
clock.restore();
|
|
|
|
|
await sleepFor(10);
|
|
|
|
|
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(4);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.lastCall.args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.getCall(3).args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run twice if activeAt is inactive and we tick longer than 2 minutes', async () => {
|
|
|
|
@ -246,13 +334,19 @@ describe('SwarmPolling', () => {
|
|
|
|
|
// more than week old, so inactive group but we have to tick after more than 2 min
|
|
|
|
|
convo.set('active_at', Date.now() - 7 * 25 * 3600 * 1000);
|
|
|
|
|
clock.tick(timeToTick);
|
|
|
|
|
|
|
|
|
|
/** this is not easy to explain, but
|
|
|
|
|
* - during the swarmPolling.start, we get two calls to pollOnceForKeySpy (one for our id and one for group od)
|
|
|
|
|
* - the clock ticks 9sec, and another call of pollOnceForKeySpy get started, but as we do not await them, this test fails.
|
|
|
|
|
* the only fix is to restore the clock and force the a small sleep to let the thing run in bg
|
|
|
|
|
*/
|
|
|
|
|
clock.restore();
|
|
|
|
|
await sleepFor(10);
|
|
|
|
|
// we should have two more calls here, so 4 total.
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(4);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.getCalls()[3].args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.getCalls()[3].args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run once only if group is inactive and we tick less than 2 minutes ', async () => {
|
|
|
|
@ -274,8 +368,8 @@ describe('SwarmPolling', () => {
|
|
|
|
|
|
|
|
|
|
// we should have only one more call here, the one for our direct pubkey fetch
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(3);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true]); // this one comes from the swarmPolling.start
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true, 0]); // this one comes from the swarmPolling.start
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('multiple runs', () => {
|
|
|
|
@ -309,11 +403,11 @@ describe('SwarmPolling', () => {
|
|
|
|
|
// we have 4 calls total. 2 for our direct promises run each 5 seconds, and 2 for the group pubkey active (so run every 5 sec too)
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(4);
|
|
|
|
|
// first two calls are our pubkey
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.getCalls()[3].args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.getCalls()[3].args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does run twice if activeAt is more than 2 days old and we tick more than one minute ', async () => {
|
|
|
|
@ -329,11 +423,12 @@ describe('SwarmPolling', () => {
|
|
|
|
|
expect(pollOnceForKeySpy.callCount).to.eq(4);
|
|
|
|
|
|
|
|
|
|
// first two calls are our pubkey
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.firstCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
|
|
|
|
|
expect(pollOnceForKeySpy.secondCall.args).to.deep.eq([ourPubkey, false, 0]);
|
|
|
|
|
|
|
|
|
|
expect(pollOnceForKeySpy.thirdCall.args).to.deep.eq([ourPubkey, false]);
|
|
|
|
|
expect(pollOnceForKeySpy.getCalls()[3].args).to.deep.eq([groupConvoPubkey, true]);
|
|
|
|
|
expect(pollOnceForKeySpy.getCalls()[3].args).to.deep.eq([groupConvoPubkey, true, 0]);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|