Skip to content

Commit

Permalink
test: fix existing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alexey-yarmosh committed Dec 1, 2023
1 parent 4dc3b00 commit 569bdf1
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 149 deletions.
1 change: 1 addition & 0 deletions public/v1/components/schemas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ components:
- continent
- region
- country
- state
- city
- asn
- network
Expand Down
8 changes: 4 additions & 4 deletions src/measurement/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class MeasurementStore {
return ips || [];
}

async createMeasurement (request: MeasurementRequest, probes: Map<number, Probe>, allProbes: (Probe | OfflineProbe)[]): Promise<string> {
async createMeasurement (request: MeasurementRequest, onlineProbesMap: Map<number, Probe>, allProbes: (Probe | OfflineProbe)[]): Promise<string> {
const id = cryptoRandomString({ length: 16, type: 'alphanumeric' });
const key = getMeasurementKey(id);

Expand All @@ -76,11 +76,11 @@ export class MeasurementStore {

await Promise.all([
this.redis.hSet('gp:in-progress', id, startTime.getTime()),
this.redis.set(getMeasurementKey(id, 'probes_awaiting'), probes.size, { EX: probesAwaitingTtl }),
this.redis.json.set(getMeasurementKey(id, 'ips'), '$', allProbes.map(probe => probe.ipAddress)),
this.redis.set(getMeasurementKey(id, 'probes_awaiting'), onlineProbesMap.size, { EX: probesAwaitingTtl }),
this.redis.json.set(key, '$', measurementWithoutDefaults),
this.redis.expire(getMeasurementKey(id, 'ips'), config.get<number>('measurement.resultTTL')),
this.redis.expire(key, config.get<number>('measurement.resultTTL')),
this.redis.json.set(getMeasurementKey(id, 'ips'), '$', allProbes.map(probe => probe.ipAddress)),
this.redis.expire(getMeasurementKey(id, 'ips'), config.get<number>('measurement.resultTTL')),
]);

return id;
Expand Down
2 changes: 1 addition & 1 deletion src/probe/probes-location-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export class ProbesLocationFilter {
Object.keys(location).forEach((key) => {
if (key === 'tags') {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
probes = probes.filter(probe => location.tags!.every(tag => ProbesLocationFilter.hasTag(probe, tag)));
filteredProbes = probes.filter(probe => location.tags!.every(tag => ProbesLocationFilter.hasTag(probe, tag)));
} else if (key === 'magic') {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
filteredProbes = ProbesLocationFilter.magicFilter(filteredProbes, location.magic!);
Expand Down
11 changes: 6 additions & 5 deletions src/probe/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import type { LocationWithLimit, MeasurementRecord, MeasurementResult } from '..
import type { Location } from '../lib/location/types.js';
import type { OfflineProbe, Probe } from './types.js';
import { ProbesLocationFilter } from './probes-location-filter.js';
import { getMeasurementStore } from '../measurement/store.js';
import { getMeasurementStore, MeasurementStore } from '../measurement/store.js';
import { normalizeFromPublicName, normalizeNetworkName } from '../lib/geoip/utils.js';

export class ProbeRouter {
private readonly probesFilter = new ProbesLocationFilter();

private readonly store = getMeasurementStore();

constructor (private readonly fetchWsSockets: typeof fetchSockets) {}
constructor (
private readonly fetchWsSockets: typeof fetchSockets,
private readonly store: MeasurementStore,
) {}

public async findMatchingProbes (
locations: LocationWithLimit[] | string = [],
Expand Down Expand Up @@ -165,7 +166,7 @@ let router: ProbeRouter;

export const getProbeRouter = () => {
if (!router) {
router = new ProbeRouter(fetchSockets);
router = new ProbeRouter(fetchSockets, getMeasurementStore());
}

return router;
Expand Down
4 changes: 4 additions & 0 deletions test/tests/integration/probes/get-probes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ describe('Get Probes', () => {
continent: 'SA',
region: 'South America',
country: 'AR',
state: null,
city: 'Buenos Aires',
asn: 61004,
latitude: -34.6131,
Expand Down Expand Up @@ -163,6 +164,7 @@ describe('Get Probes', () => {
continent: 'SA',
region: 'South America',
country: 'AR',
state: null,
city: 'Buenos Aires',
asn: 61004,
latitude: -34.6131,
Expand Down Expand Up @@ -197,6 +199,7 @@ describe('Get Probes', () => {
continent: 'SA',
region: 'South America',
country: 'AR',
state: null,
city: 'Buenos Aires',
asn: 61004,
latitude: -34.6131,
Expand Down Expand Up @@ -276,6 +279,7 @@ describe('Get Probes', () => {
continent: 'SA',
region: 'South America',
country: 'AR',
state: null,
city: 'Cordoba',
latitude: -31.4135,
longitude: -64.18105,
Expand Down
8 changes: 7 additions & 1 deletion test/tests/unit/adopted-probes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const defaultAdoptedProbe = {
status: 'ready',
version: '0.26.0',
country: 'IE',
state: null,
countryOfCustomCity: '',
city: 'Dublin',
latitude: 53.3331,
Expand All @@ -33,6 +34,7 @@ const defaultConnectedProbe: Probe = {
continent: 'EU',
region: 'Northern Europe',
country: 'IE',
state: null,
city: 'Dublin',
normalizedCity: 'dublin',
asn: 16509,
Expand Down Expand Up @@ -225,13 +227,14 @@ describe('AdoptedProbes', () => {
continent: 'EU',
region: 'Northern Europe',
country: 'GB',
state: null,
city: 'London',
asn: 20473,
latitude: 51.50853,
longitude: -0.12574,
network: 'The Constant Company, LLC',
},
},
} as Probe,
},
}]);

Expand Down Expand Up @@ -269,6 +272,7 @@ describe('AdoptedProbes', () => {
continent: 'EU',
region: 'Northern Europe',
country: 'GB',
state: null,
city: 'London',
asn: 20473,
latitude: 51.50853,
Expand Down Expand Up @@ -320,6 +324,7 @@ describe('AdoptedProbes', () => {
continent: 'EU',
region: 'Northern Europe',
country: 'GB',
state: null,
city: 'London',
asn: 20473,
latitude: 51.50853,
Expand Down Expand Up @@ -393,6 +398,7 @@ describe('AdoptedProbes', () => {
region: 'Northern Europe',
country: 'IE',
city: 'Dundalk',
state: null,
normalizedCity: 'dundalk',
asn: 16509,
latitude: 54,
Expand Down
105 changes: 74 additions & 31 deletions test/tests/unit/measurement/runner.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Context } from 'koa';
import * as sinon from 'sinon';
import { Server } from 'socket.io';
import { expect } from 'chai';
import * as td from 'testdouble';
import type { RedisClient } from '../../../../src/lib/redis/client.js';
import { MeasurementStore } from '../../../../src/measurement/store.js';
import { ProbeRouter } from '../../../../src/probe/router.js';
import { MetricsAgent } from '../../../../src/lib/metrics.js';
Expand All @@ -12,13 +12,17 @@ import type { MeasurementRecord, MeasurementResultMessage } from '../../../../sr

const getProbe = (id: number) => ({ client: id } as unknown as Probe);

const req = {
headers: {
'x-client-ip': '1.1.1.1',
},
};

describe('MeasurementRunner', () => {
const set = sinon.stub();
const emit = sinon.stub();
const to = sinon.stub();
const io = sinon.createStubInstance(Server);
const redis = {
recordResult: sinon.stub(),
} as sinon.SinonStubbedInstance<RedisClient>;
const store = sinon.createStubInstance(MeasurementStore);
const router = sinon.createStubInstance(ProbeRouter);
const metrics = sinon.createStubInstance(MetricsAgent);
Expand All @@ -28,7 +32,7 @@ describe('MeasurementRunner', () => {
before(async () => {
td.replaceEsm('crypto-random-string', null, () => testId++);
const { MeasurementRunner } = await import('../../../../src/measurement/runner.js');
runner = new MeasurementRunner(io, redis, store, router, metrics);
runner = new MeasurementRunner(io, store, router, metrics);
});

beforeEach(() => {
Expand All @@ -40,30 +44,49 @@ describe('MeasurementRunner', () => {
store.createMeasurement.reset();
store.createMeasurement.resolves('measurementid');
metrics.recordMeasurement.reset();
redis.recordResult.reset();
testId = 0;
});

it('should run measurement for the required amount of probes', async () => {
router.findMatchingProbes.resolves([ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ]);
router.findMatchingProbes.resolves({
onlineProbesMap: new Map([ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ].entries()),
allProbes: [ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ],
});

await runner.run({
type: 'ping',
target: 'jsdelivr.com',
measurementOptions: {
packets: 3,
set,
req,
request: {
body: {
type: 'ping',
target: 'jsdelivr.com',
measurementOptions: {
packets: 3,
},
locations: [],
limit: 10,
inProgressUpdates: false,
},
},
locations: [],
limit: 10,
inProgressUpdates: false,
});
} as unknown as Context);


expect(router.findMatchingProbes.callCount).to.equal(1);
expect(router.findMatchingProbes.args[0]).to.deep.equal([ [], 10 ]);
expect(store.createMeasurement.callCount).to.equal(1);

expect(store.createMeasurement.args[0]![1]).to.deep.equal([{ client: 0 }, { client: 1 }, { client: 2 }, { client: 3 }]);
expect(store.createMeasurement.args[0]).to.deep.equal([
{
type: 'ping',
target: 'jsdelivr.com',
measurementOptions: { packets: 3 },
locations: [],
limit: 10,
inProgressUpdates: false,
},
new Map([ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ].entries()),
[ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ],
]);

expect(to.callCount).to.equal(4);
expect(emit.callCount).to.equal(4);
Expand Down Expand Up @@ -124,25 +147,45 @@ describe('MeasurementRunner', () => {
});

it('should send `inProgressUpdates: true` to the first N probes if requested', async () => {
router.findMatchingProbes.resolves([ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ]);
router.findMatchingProbes.resolves({
onlineProbesMap: new Map([ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ].entries()),
allProbes: [ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ],
});

await runner.run({
type: 'ping',
target: 'jsdelivr.com',
measurementOptions: {
packets: 3,
set,
req,
request: {
body: {
type: 'ping',
target: 'jsdelivr.com',
measurementOptions: {
packets: 3,
},
locations: [],
limit: 10,
inProgressUpdates: true,
},
},
locations: [],
limit: 10,
inProgressUpdates: true,
});
} as unknown as Context);


expect(router.findMatchingProbes.callCount).to.equal(1);
expect(router.findMatchingProbes.args[0]).to.deep.equal([ [], 10 ]);
expect(store.createMeasurement.callCount).to.equal(1);

expect(store.createMeasurement.args[0]![1]).to.deep.equal([{ client: 0 }, { client: 1 }, { client: 2 }, { client: 3 }]);
expect(store.createMeasurement.args[0]).to.deep.equal([
{
type: 'ping',
target: 'jsdelivr.com',
measurementOptions: { packets: 3 },
locations: [],
limit: 10,
inProgressUpdates: true,
},
new Map([ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ].entries()),
[ getProbe(0), getProbe(1), getProbe(2), getProbe(3) ],
]);

expect(to.callCount).to.equal(4);
expect(emit.callCount).to.equal(4);
Expand Down Expand Up @@ -197,7 +240,7 @@ describe('MeasurementRunner', () => {

it('should properly handle result events from probes', async () => {
const sandbox = sinon.createSandbox({ useFakeTimers: { now: new Date('2023-05-24T09:56:55.000Z').getTime() } });
redis.recordResult
store.storeMeasurementResult
.onFirstCall().resolves(null)
.onSecondCall().resolves({ type: 'ping', createdAt: '2023-05-24T09:56:30.000Z' } as MeasurementRecord)
.onThirdCall().resolves(null);
Expand All @@ -206,10 +249,10 @@ describe('MeasurementRunner', () => {
await runner.recordResult({ measurementId: 'measurementid', testId: 'testid2', result: {} as MeasurementResultMessage['result'] });
await runner.recordResult({ measurementId: 'measurementid', testId: 'testid3', result: {} as MeasurementResultMessage['result'] });

expect(redis.recordResult.callCount).to.equal(3);
expect(redis.recordResult.args[0]).to.deep.equal([ 'measurementid', 'testid1', {}]);
expect(redis.recordResult.args[1]).to.deep.equal([ 'measurementid', 'testid2', {}]);
expect(redis.recordResult.args[2]).to.deep.equal([ 'measurementid', 'testid3', {}]);
expect(store.storeMeasurementResult.callCount).to.equal(3);
expect(store.storeMeasurementResult.args[0]).to.deep.equal([{ measurementId: 'measurementid', testId: 'testid1', result: {} }]);
expect(store.storeMeasurementResult.args[1]).to.deep.equal([{ measurementId: 'measurementid', testId: 'testid2', result: {} }]);
expect(store.storeMeasurementResult.args[2]).to.deep.equal([{ measurementId: 'measurementid', testId: 'testid3', result: {} }]);
expect(metrics.recordMeasurementTime.callCount).to.equal(1);
expect(metrics.recordMeasurementTime.args[0]).to.deep.equal([ 'ping', 25000 ]);
sandbox.restore();
Expand Down
Loading

0 comments on commit 569bdf1

Please sign in to comment.