refactor: remove test deported to keymetrics-agent

This commit is contained in:
Unitech 2018-03-26 14:15:00 +02:00
parent da56c7aff1
commit 299a52a253
13 changed files with 0 additions and 1697 deletions

View File

@ -1,239 +0,0 @@
process.env.DEBUG='pm2:aggregator';
var should = require('should');
var Aggregator = require('../../lib/Interactor/TransactionAggregator.js');
var Utility = require('../../lib/Interactor/Utility.js');
var Plan = require('../helpers/plan.js');
var TraceFactory = require('./misc/trace_factory.js');
var TraceMock = require('./misc/trace.json');
var path = require('path');
var fs = require('fs');
describe('Transactions Aggregator', function() {
var aggregator;
var stackParser;
it('should instanciate context cache', function() {
var cache = new Utility.Cache({
miss: function (key) {
try {
var content = fs.readFileSync(path.resolve(key));
return content.toString().split(/\r?\n/);
} catch (err) {
return undefined;
}
}
})
stackParser = new Utility.StackTraceParser({ cache: cache, context: 2});
});
it('should instanciate aggregator', function() {
aggregator = new Aggregator({ stackParser: stackParser});
});
describe('.censorSpans', function() {
var trace = TraceFactory.generateTrace('/yoloswag/swag', 2);
it('should not fail', function() {
aggregator.censorSpans(null);
});
it('should censor span', function() {
should.exist(trace.spans[1].labels.results);
aggregator.censorSpans(trace.spans);
should.not.exist(trace.spans[1].labels.results);
trace.spans[1].labels.cmd.should.containEql('?');
});
});
describe('.isIdentifier', function() {
it('should be an identifier (api version)', function() {
aggregator.isIdentifier('v1').should.equal(true);
});
it('should be an identifier (number)', function() {
aggregator.isIdentifier('123').should.equal(true);
});
it('should be an identifier (random str)', function() {
aggregator.isIdentifier('65f4ez656').should.equal(true);
});
it('should be an identifier (uuid)', function() {
aggregator.isIdentifier('123e4567-e89b-12d3-a456-426655440000').should.equal(true);
aggregator.isIdentifier('123e4567e89b12d3a456426655440000').should.equal(true);
});
it('should be an identifier', function() {
aggregator.isIdentifier('toto-toto-tooa').should.equal(true);
aggregator.isIdentifier('toto@toto.fr').should.equal(true);
aggregator.isIdentifier('toto@toto.fr').should.equal(true);
aggregator.isIdentifier('fontawesome-webfont.eot').should.equal(true);
aggregator.isIdentifier('life_is_just_fantasy').should.equal(true);
aggregator.isIdentifier('OR-IS_THIS-REAL_LIFE').should.equal(true);
});
it('should be NOT an identifier', function() {
aggregator.isIdentifier('bucket').should.equal(false);
aggregator.isIdentifier('admin').should.equal(false);
aggregator.isIdentifier('auth').should.equal(false);
aggregator.isIdentifier('users').should.equal(false);
aggregator.isIdentifier('version').should.equal(false);
});
});
describe('.matchPath - aggregate', function() {
var routes = {
'bucket/6465577': { spans: true }
};
it('should not fail', function() {
aggregator.matchPath();
aggregator.matchPath('/');
aggregator.matchPath('/', {});
aggregator.matchPath('/', {
'/' : {}
});
});
it('should match first route', function() {
var match = aggregator.matchPath('bucket/67754', routes);
should.exist(match);
match.should.be.a.String();
match.should.equal('bucket/*');
should.exist(routes['bucket/*'])
});
it('should NOT match any route', function() {
should.not.exist(aggregator.matchPath('toto/67754', routes));
});
it('should match aggregated route with *', function() {
var match = aggregator.matchPath('bucket/87998', routes);
should.exist(match);
match.should.be.a.String();
match.should.equal('bucket/*');
should.exist(routes['bucket/*'])
});
});
describe('merging trace together', function() {
var trace = TraceFactory.generateTrace('yoloswag/swag', 2);
var ROUTES = {
'yoloswag/swag': {}
};
it('should not fail', function() {
aggregator.mergeTrace()
aggregator.mergeTrace(null, trace)
aggregator.mergeTrace({}, trace)
aggregator.mergeTrace({})
});
it('should add a trace', function() {
aggregator.mergeTrace(ROUTES['yoloswag/swag'], trace)
ROUTES['yoloswag/swag'].meta.histogram.getCount().should.be.equal(1);
ROUTES['yoloswag/swag'].variances.length.should.be.equal(1);
ROUTES['yoloswag/swag'].variances[0].spans.length.should.be.equal(3);
});
it('should merge with the first variance', function() {
aggregator.mergeTrace(ROUTES['yoloswag/swag'], trace);
ROUTES['yoloswag/swag'].variances.length.should.be.equal(1);
ROUTES['yoloswag/swag'].variances[0].histogram.getCount().should.be.equal(2);
});
it('should merge as a new variance with the same route', function () {
var trace2 = TraceFactory.generateTrace('yoloswag/swag', 3)
trace2.spans.forEach(function (span) {
span.min = span.max = span.mean = Math.round(new Date(span.endTime) - new Date(span.startTime));
})
aggregator.mergeTrace(ROUTES['yoloswag/swag'], trace2);
ROUTES['yoloswag/swag'].meta.histogram.getCount().should.be.equal(3);
ROUTES['yoloswag/swag'].variances.length.should.be.equal(2);
ROUTES['yoloswag/swag'].variances[0].histogram.getCount().should.be.equal(2);
ROUTES['yoloswag/swag'].variances[1].histogram.getCount().should.be.equal(1);
ROUTES['yoloswag/swag'].variances[1].spans.length.should.be.equal(4);
});
});
describe('.aggregate', function() {
it('should not fail', function() {
var dt = aggregator.aggregate(null);
should(dt).be.false();
});
it('should aggregate', function() {
// Simulate some data
var packet = TraceFactory.generatePacket('yoloswag/swag', 'appname');
aggregator.aggregate(packet);
packet = TraceFactory.generatePacket('yoloswag/swag', 'appname');
aggregator.aggregate(packet);
packet = TraceFactory.generatePacket('yoloswag/swag', 'appname');
aggregator.aggregate(packet);
packet = TraceFactory.generatePacket('sisi/aight', 'appname');
aggregator.aggregate(packet);
packet = TraceFactory.generatePacket('sisi/aight', 'APP2');
aggregator.aggregate(packet);
var agg = aggregator.getAggregation();
// should get 2 apps in agg
should.exist(agg['appname']);
should.exist(agg['APP2']);
// should contain 2 routes for appname
Object.keys(agg['appname'].routes).length.should.eql(2);
should.exist(agg['appname'].process);
agg['appname'].meta.trace_count.should.eql(4);
should.exist(agg['appname'].meta.histogram.percentiles([0.5])[0.5]);
// should pm_id not taken into account
should.not.exist(agg['appname'].process.pm_id);
});
});
describe('.normalizeAggregation', function() {
it('should get normalized aggregattion', function(done) {
var ret = aggregator.prepareAggregationforShipping();
should.exist(ret['appname'].process.server);
should.exist(ret['APP2'].process.server);
done();
});
});
describe('.resetAggregation and .clearData', function() {
it('should get transactions', function() {
var cache = aggregator.getAggregation();
Object.keys(cache).length.should.eql(2);
});
it('should .resetAggregation for "appname" app', function() {
var cache = aggregator.getAggregation();
cache['appname'].meta.trace_count.should.eql(4);
Object.keys(cache['appname'].routes).length.should.eql(2);
aggregator.resetAggregation('appname', {})
cache = aggregator.getAggregation();
Object.keys(cache).length.should.eql(2);
cache['appname'].meta.trace_count.should.eql(0);
Object.keys(cache['appname'].routes).length.should.eql(0);
});
it('should .clearData', function() {
var cache = aggregator.getAggregation();
cache['APP2'].meta.trace_count.should.eql(1);
Object.keys(cache['APP2'].routes).length.should.eql(1);
aggregator.clearData();
cache = aggregator.getAggregation();
cache['APP2'].meta.trace_count.should.eql(0);
Object.keys(cache['APP2'].routes).length.should.eql(0);
});
});
});

View File

@ -1,86 +0,0 @@
var should = require('should');
var Utility = require('../../lib/Interactor/Utility.js');
var path = require('path');
var fs = require('fs');
describe('Cache Utility', function() {
var aggregator;
var stackParser;
var cache;
it('should instanciate context cache', function() {
cache = new Utility.Cache({
miss: function (key) {
try {
var content = fs.readFileSync(path.resolve(key));
return content.toString().split(/\r?\n/);
} catch (err) {
return null;
}
}
})
});
it('should get null without key', function() {
should(cache.get()).be.null();
});
it('should get null with unknow value', function() {
should(cache.get('toto')).be.null();
});
it('should get null', function() {
should(cache.get()).be.null();
});
it('should set null', function() {
should(cache.set()).be.false();
});
it('should not set key without value', function() {
should(cache.set('toto')).be.false();
});
it('should set value', function() {
should(cache.set('toto', 'val')).be.true();
});
it('should get value', function() {
should(cache.get('toto')).eql('val');
});
it('should reset', function() {
cache.reset();
});
it('should get null with unknow value', function() {
should(cache.get('toto')).be.null();
});
it('should instanciate context cache with ttl', function() {
cache = new Utility.Cache({
miss: function (key) {
try {
var content = fs.readFileSync(path.resolve(key));
return content.toString().split(/\r?\n/);
} catch (err) {
return null;
}
},
ttl: 1
});
});
it('should add a key', function () {
should(cache.set('toto', 'yeslife')).be.true();
});
it('should wait one second to see the key disapear', function (done) {
setTimeout(function () {
should(cache.get('toto')).be.null();
done();
}, 3000);
});
});

View File

@ -1,169 +0,0 @@
var PM2 = require('../..');
var should = require('should');
var nssocket = require('nssocket');
var events = require('events');
var util = require('util');
var Cipher = require('../../lib/Interactor/Cipher.js');
var cst = require('../../constants.js');
var Plan = require('../helpers/plan.js');
var Interactor = require('../../lib/Interactor/InteractorDaemonizer.js');
var server = new events.EventEmitter();
var pm2_bus;
process.env.NODE_ENV = 'local_test';
var meta_connect = {
secret_key : 'osef',
public_key : 'osef',
machine_name : 'osef'
};
/**
* Mock server receiving data
* @method forkInteractor
* @return CallExpression
*/
function createMockServer(cb) {
var server = nssocket.createServer(function(_socket) {
console.log('Got new connection in Mock server');
server.on('cmd', function(data) {
console.log('Sending command %j', data);
_socket.send(data._type, data);
});
_socket.data('*', function(data) {
this.event.forEach(function(ev) {
server.emit(ev, data);
});
});
});
server.on('error', function(e) {
throw new Error(e);
});
server.on('listening', function() {
cb(null, server);
});
server.listen(4322, '0.0.0.0');
}
function startSomeApps(pm2, cb) {
pm2.start({
script : './events/custom_action.js',
name : 'custom-action'
}, cb);
}
describe('Custom actions', function() {
var server;
var interactor;
var pm2 = new PM2.custom({
independent : true,
cwd : __dirname + '/../fixtures',
secret_key : 'osef',
public_key : 'osef',
machine_name : 'osef',
daemon_mode: true
});;
before(function(done) {
createMockServer(function(err, _server) {
server = _server;
pm2.connect(function(err) {
startSomeApps(pm2, function() {
pm2.launchBus(function(err, bus) {
pm2_bus = bus;
setTimeout(done, 500);
});
});
});
});
});
after(function(done) {
server.close();
pm2.destroy(done);
});
it('should send ask, receive ask:rep and identify agent', function(done) {
server.once('ask:rep', function(pck) {
var data = Cipher.decipherMessage(pck.data, meta_connect.secret_key);
data.machine_name.should.eql(meta_connect.machine_name);
done();
});
server.emit('cmd', { _type : 'ask' });
});
/**
* PM2 agent is now identified
*/
it('should trigger remote action successfully', function(done) {
var plan = new Plan(2, done);
var success = function(pck) {
plan.ok(true);
server.removeListener('trigger:action:failure', failure);
};
var failure = function(pck) {
console.log(pck);
plan.ok(false);
};
server.once('trigger:action:success', success);
server.once('trigger:action:failure', failure);
pm2_bus.on('axm:reply', function(pck) {
pck.data.return.success.should.be.true;
pck.data.return.subobj.a.should.eql('b');
plan.ok(true);
});
server.emit('cmd', {
_type : 'trigger:action',
process_id : 0,
action_name : 'refresh:db'
});
});
it('should trigger failure action', function(done) {
var plan = new Plan(1, done);
var success = function(pck) {
plan.ok(false);
};
var failure = function(pck) {
server.removeListener('trigger:action:success', success);
plan.ok(true);
};
server.once('trigger:action:success', success);
server.once('trigger:action:failure', failure);
pm2_bus.on('axm:reply', function(pck) {
plan.ok(false);
});
server.emit('cmd', {
_type : 'trigger:action',
process_id : 0,
action_name : 'unknown:action'
});
});
});

View File

@ -1,88 +0,0 @@
process.env.NODE_ENV = 'local_test';
process.env.KM_URL_REFRESH_RATE = 1000;
var axon = require('pm2-axon');
var PM2 = require('../..');
var should = require('should');
var sub;
function listen(cb) {
sub = axon.socket('sub');
sub.bind(8080, cb);
}
function listenRev(cb) {
var listener_server = require('nssocket').createServer(function(_socket) {
});
listener_server.listen(4322, '0.0.0.0', function() {
console.log('Reverse interact online');
cb();
});
}
describe('Programmatically test interactor', function() {
var pm2;
before(function(done) {
listen(function() {
listenRev(function() {
pm2 = new PM2.custom({
public_key : 'xxx',
secret_key : 'yyy',
cwd : __dirname + '/../fixtures/interface'
});
pm2.connect(function() {
pm2.kill(function() {
done();
});
});
});
});
});
after(function(done) {
pm2.kill(done);
});
describe('application testing', function() {
it('should start test application', function(done) {
sub.once('message', function(data) {
var packet = JSON.parse(data);
packet.data['process:event'].length.should.eql(2)
done();
});
pm2.start({
script : 'process_exception_with_logs.js',
name : 'API'
}, function(err, data) {
if (err) done(err);
//console.log(arguments);
});
});
it('should get transaction trace via interactor output', function(done) {
(function callAgain() {
sub.once('message', function(data) {
var packet = JSON.parse(data);
if (packet.data['process:exception']) {
packet.data['process:exception'][0].data.callsite.should.containEql('process_exception_with_logs.js:7');
packet.data['process:exception'][0].data.context.should.containEql('console.log');
should.exist(packet.data['process:exception'][0].data.last_logs);
//console.log
done();
}
else callAgain();
});
})()
pm2.trigger('API', 'exception');
});
});
});

View File

@ -1,23 +0,0 @@
var Filter = require('../../lib/Interactor/Filter.js');
var should = require('should');
var os = require('os');
describe('Filter Utility', function() {
it('should .machineSnapshot works as expected', function() {
var filtered = Filter.machineSnapshot([], {
REVERSE_INTERACT : true,
PM2_VERSION : '2.2.0'
});
filtered.server.should.have.properties(['loadavg', 'total_mem', 'free_mem']);
should(filtered.server.total_mem).eql(os.totalmem());
should(filtered.server.arch).eql(os.arch());
});
it('should .monitoring works as expected', function() {
var filtered = Filter.monitoring([], {});
filtered.should.have.properties(['loadavg', 'total_mem', 'free_mem', 'processes']);
filtered.total_mem.should.eql(os.totalmem());
});
});

View File

@ -1,227 +0,0 @@
process.env.NODE_ENV = 'local_test';
process.env.TRAVIS = true;
process.env.DEBUG='interface:*';
var PM2 = require('../..');
var should = require('should');
var nssocket = require('nssocket');
var events = require('events');
var util = require('util');
var axon = require('pm2-axon');
var sock = axon.socket('sub');
var pub_sock = sock.bind(8080);
var Cipher = require('../../lib/Interactor/Cipher.js');
var cst = require('../../constants.js');
var Plan = require('../helpers/plan.js');
var Configuration = require('../../lib/Configuration.js');
var Helpers = require('../helpers/apps.js');
var server = null;
var listener_server;
var _socket_list = [];
var meta_connect = {
secret_key : 'osef',
public_key : 'osef',
machine_name : 'osef'
};
/**
* Mock server receiving data
* @method forkInteractor
* @return CallExpression
*/
function createMockServer(cb) {
pub_sock.server.on('connection', function(socket) {
_socket_list.push(socket);
console.log('Got new connection on mock server');
});
server = new events.EventEmitter();
listener_server = nssocket.createServer(function(_socket) {
server.on('cmd', function(data) {
_socket.send(data._type, data);
});
_socket.data('*', function(data) {
this.event.forEach(function(ev) {
server.emit(ev, data);
});
});
});
listener_server.on('error', function(e) {
throw new Error(e);
});
listener_server.on('listening', function() {
cb(null, server);
});
listener_server.listen(4322, '0.0.0.0');
}
describe('Interactor testing', function() {
var server;
var interactor;
var pm2_bus;
var pm2 = new PM2.custom({
independent : true,
cwd : __dirname + '/../fixtures',
secret_key : 'osef',
public_key : 'osef',
machine_name : 'osef',
daemon_mode: true
});
before(function(done) {
Configuration.unset('pm2:passwd', function(err, data) {
createMockServer(function(err, _server) {
server = _server;
pm2.connect(function(err, data) {
Helpers.startSomeApps(pm2, function(err, dt) {
done();
});
});
});
});
});
after(function(done) {
listener_server.close();
pm2.destroy(done);
});
describe('Interactor methods', function() {
it('should display info', function(done) {
pm2.interactInfos(function(err, meta) {
meta.should.have.properties([
'machine_name',
'public_key',
'secret_key',
'socket_path',
'pm2_home_monitored'
])
meta.pm2_home_monitored.should.eql(pm2.pm2_home);
done();
});
});
});
describe('Input command / Output data checks', function() {
it('should send ask, receive ask:rep and identify agent', function(done) {
server.once('ask:rep', function(pck) {
var data = Cipher.decipherMessage(pck.data, meta_connect.secret_key);
data.machine_name.should.eql(meta_connect.machine_name);
done();
});
server.emit('cmd', { _type : 'ask' });
});
it('should get status via PushInteractor and PM2 should be statused as not protected', function(done) {
sock.once('message', function(data) {
var dt = JSON.parse(data);
dt.public_key.should.eql('osef');
var status = dt.data.status.data;
var procs = status.process;
var server = status.server;
procs.length.should.eql(1);
var meta = dt.data.status;
should.exists(dt.sent_at);
meta.protected.should.be.false();
meta.rev_con.should.be.true();
meta.server_name.should.eql('osef');
done();
});
it('should get status via PushInteractor and PM2 should be statused as not protected', function(done) {
sock.once('message', function(data) {
var dt = JSON.parse(data);
dt.public_key.should.eql('osef');
var status = dt.data.status.data;
var procs = status.process;
var server = status.server;
procs.length.should.eql(1);
var meta = dt.data.status;
should.exists(dt.sent_at);
meta.protected.should.be.false();
meta.rev_con.should.be.true();
meta.server_name.should.eql('osef');
done();
});
});
});
describe('General behaviors', function() {
it('should receive event application restart', function(done) {
sock.once('message', function(data) {
var dt = JSON.parse(data);
var monitoring = dt.data.monitoring;
var process_event = dt.data['process:event'];
//console.log(JSON.stringify(process_event, '', 2));
done();
});
pm2.restart('all', function() {});
});
});
describe('PM2 password checking', function() {
it('should set a password', function(done) {
pm2.set('pm2:passwd', 'testpass', function(err, data) {
should.not.exists(err);
setTimeout(done, 1000);
});
});
it('should interactor be notified of password set', function(done) {
sock.once('message', function(data) {
var dt = JSON.parse(data);
// Has switched to true
dt.data.status.protected.should.be.true();
done();
});
});
});
});
describe('Offline', function() {
it('should handle offline gracefully', function(done) {
_socket_list.forEach(function(socket, i) {
_socket_list[i].destroy();
});
sock.closeSockets();
pub_sock.server.close(function() {
console.log('Server closed');
});
setTimeout(done, 500);
});
});
});

View File

@ -1,90 +0,0 @@
/* eslint-env mocha */
process.env.NODE_ENV='test';
'use strict';
var pm2 = require('../../index.js');
var async = require('async');
var assert = require('assert');
var path = require('path');
var PushInteractor = require('../../lib/Interactor/PushInteractor.js');
describe('unmonitor process', function () {
before(function (done) {
pm2.connect(function (err) {
if (err) return done(err);
pm2.delete('all', function () {
return done();
});
});
});
after(function (done) {
pm2.delete('all', function (_) {
return done();
});
});
it('should start some processes', function (done) {
async.times(3, function (n, next) {
pm2.start({
script: path.resolve(__dirname, '../fixtures/empty.js'),
name: 'test-' + n
}, next);
}, done);
});
it('should have 3 processes started', function (done) {
pm2.list(function (err, processes) {
assert(err === null);
assert(processes.length === 3);
return done(err);
});
});
it('should start the push interactor', function (done) {
PushInteractor.start({
url: 'toto',
conf: {
ipm2: require('../../lib/Interactor/pm2-interface.js')()
}
});
return setTimeout(done, 100);
});
it('should return three processes with interactor', function (done) {
PushInteractor.preparePacket(function (err, data) {
if (err) return done(err);
assert(data.process.length === 3);
return done();
});
});
it('should run the unmonitor command', function (done) {
pm2.monitorState('unmonitor', '0', done);
});
it('should return two processes with interactor', function (done) {
PushInteractor.preparePacket(function (err, data) {
if (err) return done(err);
assert(data.process.length === 2);
return done();
});
});
it('should run the unmonitor command', function (done) {
pm2.monitorState('monitor', '0', done);
});
it('should return three processes with interactor', function (done) {
PushInteractor.preparePacket(function (err, data) {
if (err) return done(err);
assert(data.process.length === 3);
return done();
});
});
});

View File

@ -1,20 +0,0 @@
var Password = require('../../lib/Interactor/Password.js');
var should = require('should');
describe('Password test', function() {
var crypted = '';
it('should crypt a password', function() {
crypted = Password.generate('testpass');
});
it('should fail with wrong password', function() {
Password.verify('testpasds', crypted).should.be.false;
});
it('should success with right password', function() {
Password.verify('testpass', crypted).should.be.true;
});
});

View File

@ -1,225 +0,0 @@
process.env.NODE_ENV = 'local_test';
var PM2 = require('../..');
var should = require('should');
var nssocket = require('nssocket');
var events = require('events');
var util = require('util');
var Cipher = require('../../lib/Interactor/Cipher.js');
var cst = require('../../constants.js');
var send_cmd = new events.EventEmitter();
var meta_connect = {
secret_key : 'test-secret-key',
public_key : 'test-public-key',
machine_name : 'test-machine-name'
};
function createMockServer(cb) {
var server = nssocket.createServer(function(_socket) {
console.log('Got new connection in Mock server');
send_cmd.on('cmd', function(data) {
if (process.env.DEBUG)
console.log('Sending command %j', data);
_socket.send(data._type, data);
});
_socket.data('*', function(data) {
this.event.forEach(function(ev) {
send_cmd.emit(ev, data);
});
});
});
server.on('error', function(e) {
throw new Error(e);
});
server.on('listening', function() {
cb(null, server);
});
server.listen(4322, '0.0.0.0');
}
function startSomeApps(pm2, cb) {
pm2.start('./child.js', {instances : 4, name : 'child'}, cb);
}
describe('REMOTE PM2 ACTIONS', function() {
var server;
var interactor;
var pm2 = new PM2.custom({
independent : true,
cwd : __dirname + '/../fixtures',
secret_key : 'test-secret-key',
public_key : 'test-public-key',
machine_name : 'test-machine-name',
daemon_mode: true
});;
after(function(done) {
server.close();
pm2.destroy(done);
});
before(function(done) {
createMockServer(function(err, _server) {
console.log('Mock server created');
server = _server;
pm2.connect(function(err, _pm2) {
startSomeApps(pm2, function() {
done();
});
});
});
});
it('should send ask, receive ask:rep and identify agent', function(done) {
send_cmd.once('ask:rep', function(pck) {
var data = Cipher.decipherMessage(pck.data, meta_connect.secret_key);
data.machine_name.should.eql(meta_connect.machine_name);
done();
});
send_cmd.emit('cmd', { _type : 'ask' });
});
/**
* PM2 agent is now identified
*/
it('should act on PM2', function(done) {
send_cmd.once('trigger:pm2:result', function(pck) {
if (pck.ret.data.length > 0)
done();
else
done(new Error('wrong data rcvied'));
});
send_cmd.emit('cmd', {
_type : 'trigger:pm2:action',
method_name : 'restart',
parameters : {name : 'child' }
});
});
it('should act on PM2 but handle failure', function(done) {
send_cmd.once('trigger:pm2:result', function(pck) {
// Error is present telling process does not exists
pck.ret.err.should.not.be.null();
done();
});
send_cmd.emit('cmd', {
_type : 'trigger:pm2:action',
method_name : 'restart',
parameters : {name : 'UNKNOWN APP' }
});
});
it('should RELOAD', function(done) {
send_cmd.once('trigger:pm2:result', function(pck) {
/**
* Once remote command is finished...
*/
should(pck.ret.err).be.null();
pm2.list(function(err, ret) {
ret.forEach(function(proc) {
proc.pm2_env.restart_time.should.eql(2);
});
});
done();
});
send_cmd.emit('cmd', {
_type : 'trigger:pm2:action',
method_name : 'reload',
parameters : {name : 'child' }
});
});
it('should RESET metadata', function(done) {
send_cmd.once('trigger:pm2:result', function(pck) {
/**
* Once remote command is finished...
*/
should(pck.ret.err).be.null();
pm2.list(function(err, ret) {
ret.forEach(function(proc) {
proc.pm2_env.restart_time.should.eql(0);
});
});
done();
});
send_cmd.emit('cmd', {
_type : 'trigger:pm2:action',
method_name : 'reset',
parameters : {name : 'child' }
});
});
it('should delete all processes', function(done) {
pm2.delete('all', {}, function() {
startSomeApps(pm2, function() {
pm2.list(function(err, ret) {
ret.forEach(function(proc) {
proc.pm2_env.restart_time.should.eql(0);
});
done();
});
});
});
});
it('should test .remote', function(done) {
pm2.remote('restart', {
name : 'child'
}, function(err, procs) {
pm2.list(function(err, ret) {
ret.forEach(function(proc) {
proc.pm2_env.restart_time.should.eql(1);
});
done();
});
});
});
it('should test .remote and handle failure', function(done) {
pm2.remote('restart', {
name : 'UNKNOWN_NAME'
}, function(err, procs) {
pm2.list(function(err, ret) {
ret.forEach(function(proc) {
proc.pm2_env.restart_time.should.eql(1);
});
done();
});
});
});
it('should test .remote #2', function(done) {
pm2.remote('reload', {
name : 'child'
}, function(err, procs) {
pm2.list(function(err, ret) {
ret.forEach(function(proc) {
proc.pm2_env.restart_time.should.eql(2);
});
done();
});
});
});
});

View File

@ -1,91 +0,0 @@
process.env.DEBUG="interface:*";
var should = require('should');
var assert = require('assert');
var HttpRequest = require('../../lib/Interactor/HttpRequest.js');
var PORT = 8080;
function mockIrritableServer(cb) {
var http = require('http');
var url = require('url');
function handleRequest(req, res) {
var uri = url.parse(req.url).pathname;
if (uri == '/api/node/verifyPM2') {
// res.writeHead(505, {"Content-Type": "text/json"});
// return res.end(new Buffer(50).fill('h'));
// }
// console.log(uri);
return false;
}
if (uri == '/api/misc/pm2_version') {
res.writeHead(505);
return res.end();
}
}
//Create a server
var server = http.createServer(handleRequest);
//Lets start our server
server.listen(PORT, function(err){
if (err) console.error(err);
cb(null, server);
});
}
describe('Http requests', function() {
var _server = null;
before(function(done) {
mockIrritableServer(function(err, server) {
_server = server;
done();
});
});
after(function(done) {
_server.close(done);
});
describe('POST', function() {
it('should post to 404 URL', function(done) {
HttpRequest.post({
port : 9999,
url : 'http://keymetrics.io/NOTHING',
data : { no : 'thing' }
}, function(err, data) {
assert(err);
assert(err.code == 'ENOTFOUND');
assert(data == null);
done();
})
});
it('should timeout after 7secs', function(done) {
HttpRequest.post({
port : PORT,
url : '127.0.0.1',
data : { no : 'thing' }
}, function(err, data) {
assert(err);
assert(err.code == 'ECONNRESET');
assert(data == null);
done();
});
});
});
// @todo: more behavioral tests (reverse interactor failcheck)
// @todo: do more tests when doing changeUrls
it.skip('should change urls (forcing reconnection)', function(done) {
InterfaceD.changeUrls('app.km.io', 'app.km.io:4322');
setTimeout(done, 2000);
});
});

View File

@ -1,258 +0,0 @@
var PM2 = require('../..');
var should = require('should');
var nssocket = require('nssocket');
var events = require('events');
var util = require('util');
var Cipher = require('../../lib/Interactor/Cipher.js');
var cst = require('../../constants.js');
var Plan = require('../helpers/plan.js');
var Configuration = require('../../lib/Configuration.js');
var Helpers = require('../helpers/apps.js');
var Interactor = require('../../lib/Interactor/InteractorDaemonizer.js');
var gl_interactor_process;
var send_cmd = new events.EventEmitter();
process.env.NODE_ENV = 'local_test';
var meta_connect = {
secret_key : 'test-secret-key',
public_key : 'test-public-key',
machine_name : 'test-machine-name'
};
/**
* Description
* @method forkInteractor
* @return CallExpression
*/
function forkInteractor(cb) {
Interactor.launchAndInteract(meta_connect, function(err, data, interactor_process) {
gl_interactor_process = interactor_process;
cb();
});
}
/**
* Mock server receiving data
* @method forkInteractor
* @return CallExpression
*/
function createMockServer(cb) {
var server = nssocket.createServer(function(_socket) {
send_cmd.on('cmd', function(data) {
if (process.env.DEBUG)
console.log('Sending command %j', data);
_socket.send(data._type, data);
});
_socket.data('*', function(data) {
this.event.forEach(function(ev) {
send_cmd.emit(ev, data);
});
});
});
server.on('error', function(e) {
throw new Error(e);
});
server.on('listening', function() {
cb(null, server);
});
server.listen(4322, '0.0.0.0');
}
function startSomeApps(cb) {
pm2.start('./child.js', {instances : 1, name : 'child'}, cb);
}
var pm2 = new PM2.custom({
independent : true,
cwd : __dirname + '/../fixtures',
secret_key : 'test-secret-key',
public_key : 'test-public-key',
machine_name : 'test-machine-name',
daemon_mode: true
});
describe('SCOPED PM2 ACTIONS', function() {
var server;
var interactor;
after(function(done) {
server.close();
pm2.destroy(done);
});
before(function(done) {
createMockServer(function(err, _server) {
server = _server;
pm2.connect(function() {
startSomeApps(function(err) {
gl_interactor_process = pm2.Client.interactor_process;
// @todo: would be nice to know when an app is ready
// @priotity: minor
setTimeout(done, 1500);
});
});
});
});
it('should send ask, receive ask:rep and identify agent', function(done) {
send_cmd.once('ask:rep', function(pck) {
var data = Cipher.decipherMessage(pck.data, meta_connect.secret_key);
data.machine_name.should.eql(meta_connect.machine_name);
done();
});
send_cmd.emit('cmd', { _type : 'ask' });
});
/**
* PM2 agent is now identified
*/
describe('Test non auth remote commands', function() {
before(function(done) {
Configuration.unset('pm2:passwd', function(err, data) {
should.not.exists(err);
done();
});
});
it('should restart command via scoped pm2 action (no pass needed)', function(done) {
var good = false;
var plan = new Plan(2, function() {
gl_interactor_process.removeListener('message', actionCheck);
good = true;
done();
});
function actionCheck(pck) {
if (good) return false;
if (pck.event == 'pm2:scoped:stream' && pck.data.out === 'Action restart received')
return plan.ok(true);
if (pck.event == 'pm2:scoped:end')
return plan.ok(true);
if (pck.event == 'pm2:scoped:error')
return plan.ok(false, pck);
return false;
}
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'restart',
uuid : '1234',
options : { args : ['child'] }
});
});
});
describe('Password verification', function() {
before(function(done) {
Configuration.unset('pm2:passwd', function(err, data) {
should.not.exists(err);
done();
});
});
it('should error when call an action that is password protected', function(done) {
function actionCheck(pck) {
if (pck.event == 'pm2:scoped:error' && pck.data.out.indexOf('Missing password') > -1) {
gl_interactor_process.removeListener('message', actionCheck);
done();
}
};
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'install',
uuid : '5678',
options : { args : ['child'] }
});
});
it('should fail when password passed but no pm2 password configured', function(done) {
function actionCheck(pck) {
if (pck.event == 'pm2:scoped:error' && pck.data.out.indexOf('Password at PM2') > -1) {
gl_interactor_process.removeListener('message', actionCheck);
done();
}
};
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'install',
uuid : '5678',
password : 'random-pass',
options : { args : ['pm2-module'] }
});
});
it('should set a password', function(done) {
pm2.set('pm2:passwd', 'testpass', function(err, data) {
should.not.exists(err);
done();
});
});
it('should fail when wrong password', function(done) {
function actionCheck(pck) {
if (pck.event == 'pm2:scoped:error' && pck.data.out.indexOf('Password does not match') > -1) {
gl_interactor_process.removeListener('message', actionCheck);
setTimeout(done, 100);
}
};
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'install',
uuid : '5678',
password : 'random-pass',
options : { args : ['pm2-module'] }
});
});
it('should work when good password passed', function(done) {
function actionCheck(pck) {
if (pck.event === 'pm2:scoped:end') {
gl_interactor_process.removeListener('message', actionCheck);
done();
}
if (pck.event === 'pm2:scoped:error') {
gl_interactor_process.removeListener('message', actionCheck);
done('{ERROR} Wrong password!' + JSON.stringify(pck));
}
};
gl_interactor_process.on('message', actionCheck);
send_cmd.emit('cmd', {
_type : 'trigger:pm2:scoped:action',
action_name : 'ping',
uuid : '5678',
password : 'testpass',
options : {}
});
});
});
});

View File

@ -1,157 +0,0 @@
var should = require('should');
var Aggregator = require('../../lib/Interactor/TransactionAggregator.js');
var Utility = require('../../lib/Interactor/Utility.js');
var TraceFactory = require('./misc/trace_factory.js');
var path = require('path');
var fs = require('fs');
var assert = require('assert');
describe('StackTrace Utility', function() {
var aggregator;
var stackParser;
it('should instanciate context cache', function() {
var cache = new Utility.Cache({
miss: function (key) {
try {
var content = fs.readFileSync(path.resolve(key));
return content.toString().split(/\r?\n/);
} catch (err) {
return undefined;
}
}
})
stackParser = new Utility.StackTraceParser({ cache: cache, context: 2});
});
it('should instanciate aggregator', function() {
aggregator = new Aggregator({ stackParser: stackParser});
});
describe('.parse', function() {
it('should parse stacktrace and get context', function(done) {
var obj = [{
labels: {
stacktrace: JSON.stringify(TraceFactory.stacktrace)
}
}];
aggregator.parseStacktrace(obj);
obj[0].labels['source/file'].indexOf('test/interface/misc/trace_factory.js:10').should.be.above(0);
should(obj[0].labels['source/context']).eql("var random_routes = [\n '/api/bucket',\n>>'/api/bucket/users',\n '/api/bucket/chameau',\n '/backo/testo'");
done();
});
it('should handle malformated stacktraces', function() {
aggregator.parseStacktrace([{
labels: {
stacktrace: JSON.stringify({
stack_frame: [{
line_number: 10,
column_number: 10,
method_name: '<anonymous function>'
}, {
file_name: 'node_modules/express.js',
column_number: 10,
method_name: '<anonymous function>'
}, {
file_name: path.resolve(__dirname, 'trace_factory.js'),
line_number: 10,
column_number: 10,
method_name: '<anonymous function>'
}]
})
}
}]);
});
it('should handle malformated stacktrace v1', function() {
aggregator.parseStacktrace([{
labels: {
stacktrace: JSON.stringify({
stack_frame: [{
file_name: 'events.js'
},{
file_name: 'node_modules/express.js'
},{
file_name: path.resolve(__dirname, 'trace_factory.js')
}]
})
}
}]);
});
it('should handle malformated stacktrace v2', function() {
aggregator.parseStacktrace([{
labels: {
stacktrace: JSON.stringify({
stack_frame: [{
file_name: 'events.js',
column_number: 10,
method_name: '<anonymous function>'
},{
file_name: 'node_modules/express.js',
column_number: 10,
method_name: '<anonymous function>'
},{
file_name: path.resolve(__dirname, 'trace_factory.js'),
line_number: 10,
column_number: 10,
method_name: '<anonymous function>'
}]
})
}
}]);
});
it('should handle malformated stacktrace v3', function() {
aggregator.parseStacktrace([{
labels: {}
}]);
});
it('should handle malformated stacktrace v4', function() {
aggregator.parseStacktrace([{
}]);
});
it('should handle malformated stacktrace v5', function() {
aggregator.parseStacktrace([]);
});
it('should handle malformated stacktrace v5', function() {
aggregator.parseStacktrace();
});
});
describe('.attachContext', function () {
it('should extract context from stackframes', function () {
var error = stackParser.attachContext({
stackframes: [
{
file_name: '/toto/tmp/lol',
line_number: 10
}
]
});
assert(error !== undefined);
assert(error.stackframes === undefined);
assert(error.callsite !== undefined);
assert(error.callsite.indexOf('/toto/tmp/lol') >= 0);
});
it('should extract context from the stack string', function () {
var error = new Error();
// stack is lazy so we need to load it
error.stack = error.stack;
error = stackParser.attachContext(error);
assert(error !== undefined);
assert(error.stackframes === undefined);
assert(error.callsite.indexOf(__filename) >= 0);
assert(error.context.indexOf('var error = new Error()') >= 0);
});
});
});

View File

@ -95,37 +95,13 @@ cd ../interface
# echo $PM2_HOME
mocha --opts ./mocha.opts ./exception.e2e.mocha.js
spec "E2E exception system checking"
mocha --opts ./mocha.opts ./interactor.connect.mocha.js
spec "Interactor test #1 with password setting"
mocha --opts ./mocha.opts ./interactor.daemonizer.mocha.js
spec "Remote interactor keys save verification"
mocha --opts ./mocha.opts ./scoped_pm2_actions.mocha.js
spec "Scoped PM2 Remote interactions test"
mocha --opts ./mocha.opts ./remote.mocha.js
spec "Remote interactions test"
mocha --opts ./mocha.opts ./password.mocha.js
spec "Password library checking"
mocha --opts ./mocha.opts ./custom-actions.mocha.js
spec "Custom actions test"
mocha --opts ./mocha.opts ./bus.spec.mocha.js
spec "Protocol communication test"
mocha --opts ./mocha.opts ./bus.fork.spec.mocha.js
spec "Protocol communication test"
mocha --opts ./mocha.opts ./request.mocha.js
spec "Protocol communication test"
mocha --opts ./mocha.opts ./aggregator.mocha.js
spec "Transaction trace aggregator test"
mocha --opts ./mocha.opts ./stacktrace.mocha.js
spec "Stacktrace Utility"
mocha --opts ./mocha.opts ./cache.mocha.js
spec "Cache Utility"
mocha --opts ./mocha.opts ./filter.mocha.js
spec "Filter Utility"
mocha --opts ./mocha.opts ./utility.mocha.js
spec "PM2 Utility"
mocha --opts ./mocha.opts ./pm2.link.check.mocha.js
spec "Transaction option enablement"
mocha --opts ./mocha.opts ./monitor.mocha.js
spec "Monitor / Unmonitor commands"