1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

add tests, rename folders to ava defaults for helpers/fixtures, remove migration og

This commit is contained in:
sveisvei 2016-11-13 20:33:23 +01:00 committed by Ivar Conradi Østhus
parent e730937849
commit 067b93abfd
29 changed files with 187 additions and 43 deletions

View File

@ -12,10 +12,53 @@ test('should work without state', (t) => {
t.truthy(metrics.getMetricsOverview());
t.truthy(metrics.getTogglesMetrics());
t.truthy(metrics.toJSON());
metrics.destroy();
});
test.cb('data should expire', (t) => {
const clock = sinon.useFakeTimers();
const metrics = new UnleashClientMetrics();
metrics.addPayload({
appName,
instanceId,
bucket: {
start: Date.now() - 2000,
stop: Date.now() - 1000,
toggles: {
toggleX: {
yes: 123,
no: 0,
},
},
},
});
let lastHourExpires = 0;
metrics.lastHourList.on('expire', () => {
lastHourExpires++;
});
let lastMinExpires = 0;
metrics.lastMinuteList.on('expire', () => {
lastMinExpires++;
});
clock.tick(60 * 1000);
t.true(lastMinExpires === 1);
t.true(lastHourExpires === 0);
clock.tick(60 * 60 * 1000);
t.true(lastMinExpires === 1);
t.true(lastHourExpires === 1);
sinon.restore();
t.end();
});
test('addPayload', t => {
const metrics = new UnleashClientMetrics();
metrics.addPayload({

View File

@ -15,13 +15,6 @@ class Node {
}
}
/*
* linked list
* ranged list, assumes start to end(tail) is a known order
* remove() is only implemented in reverse order for the usecase
* emits events on eviction
*/
module.exports = class List extends EventEmitter {
constructor () {
super();
@ -116,17 +109,17 @@ module.exports = class List extends EventEmitter {
return result;
}
toArrayReverse () {
const result = [];
// toArrayReverse () {
// const result = [];
if (this.tail) {
let cursor = this.tail;
while (cursor) {
result.push(cursor.value);
cursor = cursor.prev;
}
}
// if (this.tail) {
// let cursor = this.tail;
// while (cursor) {
// result.push(cursor.value);
// cursor = cursor.prev;
// }
// }
return result;
}
// return result;
// }
};

View File

@ -77,6 +77,16 @@ test('list can be cleared and re-add entries', (t) => {
t.true(list.toArray().length === 3);
});
test('should not iterate empty list ', (t) => {
const list = new List();
let iterateCount = 0;
list.iterate(() => {
iterateCount++;
});
t.true(iterateCount === 0);
});
test('should iterate', (t) => {
const list = getList();
@ -105,3 +115,13 @@ test('should reverse iterate', (t) => {
});
t.true(iterateCount === 5);
});
test('should not reverse iterate empty list', (t) => {
const list = new List();
let iterateCount = 0;
list.iterateReverse(() => {
iterateCount++;
});
t.true(iterateCount === 0);
});

View File

@ -1,17 +1,19 @@
'use strict';
const POLL_INTERVAL = 10000;
const { EventEmitter } = require('events');
module.exports = class UnleashClientMetrics extends EventEmitter {
constructor (metricsDb) {
constructor (metricsDb, interval = 10000) {
super();
this.interval = interval;
this.db = metricsDb;
this.highestIdSeen = 0;
this.db.getMetricsLastHour().then(metrics => {
this.addMetrics(metrics);
this.startPoller();
this.emit('ready');
});
this.timer = null;
}
addMetrics (metrics) {
@ -22,13 +24,20 @@ module.exports = class UnleashClientMetrics extends EventEmitter {
}
startPoller () {
setInterval(() => {
this.timer = setInterval(() => {
this.db.getNewMetrics(this.highestIdSeen)
.then(metrics => this.addMetrics(metrics));
}, POLL_INTERVAL).unref();
}, this.interval);
this.timer.unref();
}
insert (metrics) {
return this.db.insert(metrics);
}
destroy () {
try {
clearTimeout(this.timer);
} catch (e) {}
}
};

View File

@ -0,0 +1,66 @@
'use strict';
const { test } = require('ava');
const MetricsService = require('./service');
const sinon = require('sinon');
function getMockDb () {
const list = [{ id: 2 }, { id: 3 }, { id: 4 }];
const db = {
getMetricsLastHour () {
return Promise.resolve([{ id: 1 }]);
},
getNewMetrics () {
return Promise.resolve([list.pop() || { id: 0 }]);
},
};
return {
db,
};
}
test.cb('should call database on startup', (t) => {
const mock = getMockDb();
const service = new MetricsService(mock.db);
t.plan(2);
service.on('metrics', ([metric]) => {
t.true(service.highestIdSeen === 1);
t.true(metric.id === 1);
t.end();
service.destroy();
});
});
test.cb('should poll for updates', (t) => {
const clock = sinon.useFakeTimers();
const mock = getMockDb();
const service = new MetricsService(mock.db, 100);
const metrics = [];
service.on('metrics', (_metrics) => {
_metrics.forEach(m => m && metrics.push(m));
});
t.true(metrics.length === 0);
service.on('ready', () => {
t.true(metrics.length === 1);
clock.tick(300);
clock.restore();
process.nextTick(() => {
t.true(metrics.length === 4);
t.true(metrics[0].id === 1);
t.true(metrics[1].id === 4);
t.true(metrics[2].id === 3);
t.true(metrics[3].id === 2);
service.destroy();
t.end();
});
});
});

View File

@ -5,13 +5,14 @@ const List = require('./list');
const moment = require('moment');
// this list must have entries with sorted ttl range
module.exports = class FIFOTTLList extends EventEmitter {
module.exports = class TTLList extends EventEmitter {
constructor ({
interval = 1000,
expireAmount = 1,
expireType = 'hours',
} = {}) {
super();
this.interval = interval;
this.expireAmount = expireAmount;
this.expireType = expireType;
@ -20,10 +21,18 @@ module.exports = class FIFOTTLList extends EventEmitter {
this.list.on('evicted', ({ value, ttl }) => {
this.emit('expire', value, ttl);
});
this.startTimer();
}
this.timer = setInterval(() => {
this.timedCheck();
}, interval);
startTimer () {
if (this.list) {
this.timer = setTimeout(() => {
if (this.list) {
this.timedCheck();
}
}, this.interval);
this.timer.unref();
}
}
add (value, timestamp = new Date()) {
@ -34,11 +43,13 @@ module.exports = class FIFOTTLList extends EventEmitter {
timedCheck () {
const now = moment(new Date());
this.list.reverseRemoveUntilTrue(({ value }) => now.isBefore(value.ttl));
this.startTimer();
}
destroy () {
clearTimeout(this.timer);
delete this.timer;
// https://github.com/nodejs/node/issues/9561
// clearTimeout(this.timer);
// this.timer = null;
this.list = null;
}
};

View File

@ -1,7 +1,7 @@
'use strict';
const test = require('ava');
const mapper = require('../../../lib/helper/legacy-feature-mapper');
const mapper = require('./legacy-feature-mapper');
test('adds old fields to feature', t => {
const feature = {

View File

@ -8,7 +8,7 @@ const ValidationError = require('../error/validation-error.js');
const validateRequest = require('../error/validate-request');
const extractUser = require('../extract-user');
const legacyFeatureMapper = require('../helper/legacy-feature-mapper');
const legacyFeatureMapper = require('../data-helper/legacy-feature-mapper');
const version = 1;
const handleErrors = (req, res, error) => {

View File

@ -1,3 +1,5 @@
'use strict';
const joi = require('joi');
const clientMetricsSchema = joi.object().keys({
@ -21,4 +23,4 @@ const clientRegisterSchema = joi.object().keys({
interval: joi.number().required(),
});
module.exports = { clientMetricsSchema, clientRegisterSchema }
module.exports = { clientMetricsSchema, clientRegisterSchema }

View File

@ -39,7 +39,7 @@
"start:dev:pg-chain": "export DATABASE_URL=postgres://$PGUSER:$PGPASSWORD@localhost:$PGPORT/postgres ; db-migrate up && npm run start:dev",
"db-migrate": "db-migrate up",
"db-migrate:down": "db-migrate down",
"test": "PORT=4243 ava **/**/*test.js",
"test": "PORT=4243 ava test lib/*/*.test.js",
"test:docker": "./scripts/docker-postgres.sh",
"test:watch": "npm run test -- --watch",
"test:pg-virtualenv": "pg_virtualenv npm run test:pg-virtualenv-chai",

View File

@ -1,7 +1,7 @@
'use strict';
const test = require('ava');
const { setupApp } = require('./util/test-helper');
const { setupApp } = require('./helpers/test-helper');
const logger = require('../../lib/logger');
test.beforeEach(() => {

View File

@ -1,7 +1,7 @@
'use strict';
const { test } = require('ava');
const { setupApp } = require('./util/test-helper');
const { setupApp } = require('./helpers/test-helper');
const logger = require('../../lib/logger');
test.beforeEach(() => {

View File

@ -1,7 +1,7 @@
'use strict';
const test = require('ava');
const { setupApp } = require('./util/test-helper');
const { setupApp } = require('./helpers/test-helper');
const logger = require('../../lib/logger');
test.beforeEach(() => {

View File

@ -7,6 +7,7 @@ const migrator = require('../../../migrator');
const { createStores } = require('../../../lib/db');
const { createDb } = require('../../../lib/db/db-pool');
const _app = require('../../../app');
require('db-migrate-shared').log.silence(true);
// because of migrator bug
delete process.env.DATABASE_URL;

View File

@ -1,6 +1,6 @@
'use strict';
const test = require('ava');
const { setupApp } = require('./util/test-helper');
const { setupApp } = require('./helpers/test-helper');
const logger = require('../../lib/logger');
test.beforeEach(() => {

View File

@ -1,7 +1,7 @@
'use strict';
const test = require('ava');
const { setupApp } = require('./util/test-helper');
const { setupApp } = require('./helpers/test-helper');
const logger = require('../../lib/logger');
test.beforeEach(() => {

View File

@ -1,7 +1,7 @@
'use strict';
const test = require('ava');
const { setupApp } = require('./util/test-helper');
const { setupApp } = require('./helpers/test-helper');
const logger = require('../../lib/logger');
test.beforeEach(() => {

View File

@ -1,7 +1,7 @@
'use strict';
const test = require('ava');
const store = require('./mocks/store');
const store = require('./fixtures/store');
const supertest = require('supertest');
const logger = require('../../../lib/logger');

View File

@ -1,7 +1,7 @@
'use strict';
const test = require('ava');
const store = require('./mocks/store');
const store = require('./fixtures/store');
const supertest = require('supertest');
const logger = require('../../../lib/logger');
@ -29,7 +29,6 @@ test('should give 500 when db is failing', t => {
db.select = () => ({
from: () => Promise.reject(new Error('db error')),
});
return request
.get('/health')
.expect(500)

View File

@ -1,7 +1,7 @@
'use strict';
const test = require('ava');
const store = require('./mocks/store');
const store = require('./fixtures/store');
const supertest = require('supertest');
const logger = require('../../../lib/logger');

View File

@ -1,7 +1,7 @@
'use strict';
const test = require('ava');
const store = require('./mocks/store');
const store = require('./fixtures/store');
const supertest = require('supertest');
const logger = require('../../../lib/logger');