Skip to content
Open
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ apiBenchmark.measure(service, routes, function(err, results){
(String, default 'get'): Http verb.

#### route
(String): the route to benchmark
(String): the route to benchmark. In case of function (that has to return an string) it will be evaulated for each request.

#### headers
(Object): the headers to send. In case of function (that has to return an object) it will be evaulated for each request.
Expand Down
8 changes: 6 additions & 2 deletions lib/request-agent.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

var _ = require('underscore');
var url = require('url');

module.exports = function(agent){
this.agent = agent;
Expand All @@ -12,13 +13,16 @@ module.exports = function(agent){
this.make = function(options, callback){
var data = evalIfFunction(options.data) || {},
query = evalIfFunction(options.query) || {},
route = evalIfFunction(options.route) || '',
headers = evalIfFunction(options.headers) || {},
method = options.method === 'delete' ? 'del' : options.method,
request = this.agent[method](options.url);
service = options.service || '',
requestUrl = url.resolve(service, route),
request = this.agent[method](requestUrl);

if(!_.isEmpty(data)) {
request.send(data);
}
}

if(!_.isEmpty(query)) {
request.query(query);
Expand Down
11 changes: 8 additions & 3 deletions lib/request-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
var format = require('./format');
var settings = require('./settings');
var _ = require('underscore');
var url = require('url');

module.exports = {
make: function(req, suite, suiteName, requestAgent, callback){
Expand Down Expand Up @@ -34,9 +35,9 @@ module.exports = {
}
});
},
setup: function(suiteName, suiteHref, suite, requestAgent){
setup: function(suiteName, service, suite, requestAgent){
var self = this,
req = _.extend(_.clone(suite.endpoint), { url: suiteHref }),
req = _.extend(_.clone(suite.endpoint), { service: service }),
suiteOptions = {
expectedStatusCode: suite.endpoint.expectedStatusCode,
maxMean: suite.endpoint.maxMean,
Expand All @@ -45,6 +46,10 @@ module.exports = {
},
suiteRequest = {};

if(!!suite.endpoint.route){
suiteRequest.route = _.isFunction(suite.endpoint.route) ? 'Dynamic route on ' + service : url.resolve(service, suite.endpoint.route);
}

if(!!suite.endpoint.headers){
suiteRequest.headers = _.isFunction(suite.endpoint.headers) ? 'Dynamic headers' : suite.endpoint.headers;
}
Expand All @@ -57,7 +62,7 @@ module.exports = {
suiteRequest.query = _.isFunction(suite.endpoint.query) ? 'Dynamic query' : suite.endpoint.query;
}

suite.runner.add(suiteName, suiteHref, suiteOptions, suiteRequest, function(done){
suite.runner.add(suiteName, suiteRequest.route, suiteOptions, suiteRequest, function(done){
self.make(req, suite, suiteName, requestAgent, done);
});
}
Expand Down
7 changes: 3 additions & 4 deletions lib/suites-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var ResultsHandler = require('./results-handler');
var Runner = require('./runner');
var sanitise = require('./sanitise');
var settings = require('./settings');
var url = require('url');

var validator = require('./validator');
var _ = require('underscore');

Expand Down Expand Up @@ -45,11 +45,10 @@ module.exports = function(agent, debugHelper){
_.forEach(this.services, function(service, serviceName){
_.forEach(this.routes, function(route){

var routeHref = url.resolve(service, route.endpoint.route),
routeName = serviceName + '/' + route.name,
var routeName = serviceName + '/' + route.name,
self = this;

requestHandler.setup(routeName, routeHref, route, self.requestAgent);
requestHandler.setup(routeName, service, route, self.requestAgent);
}, this);
}, this);

Expand Down
12 changes: 9 additions & 3 deletions templates/report.html
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,15 @@
'<li>99% Percentile: ' + fixNumber(routeData.stats.p99, 6) + '</li>' +
'<li>99.9% Percentile: ' + fixNumber(routeData.stats.p999, 6) + '</li>' +
'</ul></div></div><div class="distribution panel"><div class="distchart" id="distchart' + i + '">' +
'</div></div><div class="request panel hide">Request: ' + routeData.options.method.toUpperCase() +
' <a href="' + routeData.href + '" target="_blank">' +
routeData.href + '</a><br />Concurrency level: ' + routeData.options.concurrencyLevel + '<br />';
'</div></div><div class="request panel hide">Request: ' + routeData.options.method.toUpperCase() + ' ';

if (routeData.href.indexOf('Dynamic route') > -1) {
template += routeData.href;
} else {
template += '<a href="' + routeData.href + '" target="_blank">' + routeData.href + '</a>';
}

template += '<br />Concurrency level: ' + routeData.options.concurrencyLevel + '<br />';

if(routeData.options.delay)
template += 'Delay between bench cycles: ' + routeData.options.delay + '<br />';
Expand Down
9 changes: 6 additions & 3 deletions test/fixtures/test-agent.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
'use strict';

module.exports.FakeAgent = function(){
module.exports.FakeAgent = function(){

this.end = function(callback){
callback(null, {
url: this.url,
data: this.data,
headers: this.headers,
query: this.queryData
});
};

this.get = function(request){
this.get = function(url){
this.url = url;
return this;
};

this.post = function(request){
this.post = function(url){
this.url = url;
return this;
};

Expand Down
31 changes: 31 additions & 0 deletions test/unit/request-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe('requestAgent.make function', function(){

it('should correctly handle null data', function(done){
requestAgent.make({
service: 'http://service/',
route: '/post',
method: 'post',
data: null
Expand All @@ -29,6 +30,7 @@ describe('requestAgent.make function', function(){

it('should correctly handle undefined data', function(done){
requestAgent.make({
service: 'http://service/',
route: '/post',
method: 'post',
data: undefined
Expand All @@ -38,6 +40,30 @@ describe('requestAgent.make function', function(){
});
});

it('should correctly handle route as a function', function(done){

var i = 0;

var routeFunc = function(){
i++;
return '/endpoint'+i;
};

var request = {
service: 'http://service/',
route: routeFunc,
method: 'post'
};

requestAgent.make(request, function(err, fakeResults){
fakeResults.url.should.be.eql('http://service/endpoint1');
requestAgent.make(request, function(err, fakeResults){
fakeResults.url.should.be.eql('http://service/endpoint2');
done();
});
});
});

it('should correctly handle data as a function', function(done){

var i = 0;
Expand All @@ -48,6 +74,7 @@ describe('requestAgent.make function', function(){
};

var request = {
service: 'http://service/',
route: '/post',
method: 'post',
data: dataFunc
Expand All @@ -72,6 +99,7 @@ describe('requestAgent.make function', function(){
};

var request = {
service: 'http://service/',
route: '/get',
method: 'get',
query: queryFunc
Expand All @@ -88,6 +116,7 @@ describe('requestAgent.make function', function(){

it('should correctly handle cookies', function(done){
requestAgent.make({
service: 'http://service/',
route: '/get',
method: 'get',
headers: {
Expand All @@ -101,6 +130,7 @@ describe('requestAgent.make function', function(){

it('should correctly handle headers', function(done){
requestAgent.make({
service: 'http://service/',
route: '/get',
method: 'get',
headers: {
Expand All @@ -124,6 +154,7 @@ describe('requestAgent.make function', function(){
};

var request = {
service: 'http://service/',
route: '/get',
method: 'get',
headers: headersFunc
Expand Down
43 changes: 40 additions & 3 deletions test/unit/request-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ describe('requestHandler.setup function', function(){

var suiteObj = {
endpoint: {
aProperty: 'value'
aProperty: 'value',
route: 'someRoute'
},
runner: {
add: function(suiteName, suiteHref, suiteOptions, suiteRequest, callback){
Expand All @@ -26,11 +27,47 @@ describe('requestHandler.setup function', function(){
}
};

requestHandler.setup('suiteName', 'suiteHref', suiteObj, fakeAgent);
requestHandler.setup('suiteName', 'serviceRoot', suiteObj, fakeAgent);

var req = fakeAgentStack[0][0];

req.url.should.be.eql('suiteHref');
req.route.should.be.eql('someRoute');
req.service.should.be.eql('serviceRoot');
req.aProperty.should.be.eql('value');

done();
});

it('should properly handle dynamic routes', function(done){

var fakeAgentStack = [];

var fakeAgent = {
make: function(){
fakeAgentStack.push(arguments);
}
};

var suiteObj = {
endpoint: {
aProperty: 'value',
route: function () {
return 'someDynamicRoute';
}
},
runner: {
add: function(suiteName, suiteHref, suiteOptions, suiteRequest, callback){
suiteRequest.route.should.be.eql('Dynamic route on serviceRoot');
callback();
}
}
};

requestHandler.setup('suiteName', 'serviceRoot', suiteObj, fakeAgent);

var req = fakeAgentStack[0][0];
req.route.should.be.a.Function();
req.service.should.be.eql('serviceRoot');
req.aProperty.should.be.eql('value');

done();
Expand Down