orator 2.0.3 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.travis.yml +6 -2
- package/Debug-Harness.js +24 -0
- package/README.md +3 -3
- package/package.json +18 -19
- package/source/Orator.js +96 -99
- package/test/Orator-proxy_tests.js +14 -5
- package/test/Orator_basic_tests.js +116 -15
- package/test/Orator_cluster_test.js.deferred +11 -9
- package/test/Orator_logging_tests.js +53 -9
- package/test/Test.html +1 -0
- package/.vscode/launch.json +0 -24
- package/test/Orator_cachegrinder_tests.js +0 -100
- package/test/Orator_chromecpu_notrace_tests.js +0 -90
- package/test/Orator_chromecpu_tests.js +0 -90
package/.travis.yml
CHANGED
|
@@ -2,7 +2,11 @@ services:
|
|
|
2
2
|
- mongodb
|
|
3
3
|
language: node_js
|
|
4
4
|
node_js:
|
|
5
|
-
- "
|
|
5
|
+
- "8"
|
|
6
|
+
- "10"
|
|
7
|
+
- "12"
|
|
8
|
+
- "14"
|
|
9
|
+
- "15"
|
|
6
10
|
addons:
|
|
7
11
|
code_climate:
|
|
8
12
|
repo_token: 63ba2b0cf307133c314376df4b05fa8f0aa5e98919eb76488ad27a07f163cb77
|
|
@@ -12,4 +16,4 @@ after_script:
|
|
|
12
16
|
- cat coverage/lcov.info | ./node_modules/codeclimate-test-reporter/bin/codeclimate.js
|
|
13
17
|
- cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
|
|
14
18
|
notifications:
|
|
15
|
-
slack: paviateam:C1q99hL9XXpiPpau2PUrVZPC
|
|
19
|
+
slack: paviateam:C1q99hL9XXpiPpau2PUrVZPC
|
package/Debug-Harness.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Load the orator module with a few settings
|
|
2
|
+
var libOrator = require(__dirname+'/source/Orator.js').new(
|
|
3
|
+
{
|
|
4
|
+
Product: 'MyMicroserviceHash',
|
|
5
|
+
ProductVersion: '9.8.7',
|
|
6
|
+
|
|
7
|
+
"APIServerPort": 8080
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// Add an API endpoint
|
|
11
|
+
libOrator.webServer.get
|
|
12
|
+
(
|
|
13
|
+
'/test/:hash',
|
|
14
|
+
function(pRequest, pResponse, fNext)
|
|
15
|
+
{
|
|
16
|
+
// Send back whatever was sent as "name" in the URI
|
|
17
|
+
pResponse.send(pRequest.params);
|
|
18
|
+
libOrator.fable.log.info('WTF');
|
|
19
|
+
return fNext();
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// Start the web service
|
|
24
|
+
libOrator.startWebServer();
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Orator API Server, meant to interact well with Fable, Meadow and FoxHound.
|
|
4
4
|
|
|
5
|
-
[](https://coveralls.io/r/stevenvelozo/orator?branch=master) [](https://travis-ci.org/stevenvelozo/orator) [](https://david-dm.org/stevenvelozo/orator) [](https://david-dm.org/stevenvelozo/orator#info=devDependencies)
|
|
6
6
|
|
|
7
7
|
This is not an attempt to reinvent the wheel. Nor do we want to make a car with five of them.
|
|
8
8
|
|
|
@@ -29,7 +29,7 @@ var libOrator = require('orator').new(
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
// Add an API endpoint
|
|
32
|
-
|
|
32
|
+
libOrator.webServer.post
|
|
33
33
|
(
|
|
34
34
|
'/echo/:name',
|
|
35
35
|
function(pRequest, pResponse, fNext)
|
|
@@ -61,7 +61,7 @@ var libOrator = require('orator').new(
|
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
// Add an API endpoint
|
|
64
|
-
|
|
64
|
+
libOrator.webServer.post
|
|
65
65
|
(
|
|
66
66
|
'/echo/:name',
|
|
67
67
|
function(pRequest, pResponse, fNext)
|
package/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orator",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"description": "Restful web API server. Using restify 6.",
|
|
5
5
|
"main": "source/Orator.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "node source/Orator.js",
|
|
8
8
|
"coverage": "npm run coverage-normal && npm run coverage-cluster && npm run coverage-report",
|
|
9
|
-
"coverage-normal": "./node_modules/istanbul/lib/cli.js cover --dir ./coverage/normal ./node_modules/mocha/bin/_mocha -- -u tdd -R spec",
|
|
10
|
-
"coverage-cluster": "./node_modules/istanbul/lib/cli.js cover --dir ./coverage/cluster ./node_modules/mocha/bin/_mocha -- -u tdd -R spec ./test/Orator_cluster_test.js.deferred",
|
|
9
|
+
"coverage-normal": "./node_modules/istanbul/lib/cli.js cover --dir ./coverage/normal ./node_modules/mocha/bin/_mocha -- --exit -u tdd -R spec",
|
|
10
|
+
"coverage-cluster": "./node_modules/istanbul/lib/cli.js cover --dir ./coverage/cluster ./node_modules/mocha/bin/_mocha -- --exit -u tdd -R spec ./test/Orator_cluster_test.js.deferred",
|
|
11
11
|
"coverage-report": "./node_modules/istanbul/lib/cli.js report",
|
|
12
12
|
"test": "npm run test-normal && npm run test-cluster",
|
|
13
|
-
"
|
|
14
|
-
"test-
|
|
13
|
+
"tests": "mocha --exit -u tdd -R spec -g",
|
|
14
|
+
"test-normal": "./node_modules/mocha/bin/_mocha --exit -u tdd -R spec",
|
|
15
|
+
"test-cluster": "./node_modules/mocha/bin/_mocha --exit -u tdd -R spec ./test/Orator_cluster_test.js.deferred"
|
|
15
16
|
},
|
|
16
17
|
"repository": {
|
|
17
18
|
"type": "git",
|
|
@@ -29,25 +30,23 @@
|
|
|
29
30
|
},
|
|
30
31
|
"homepage": "https://github.com/stevenvelozo/orator",
|
|
31
32
|
"devDependencies": {
|
|
32
|
-
"async": "
|
|
33
|
-
"chai": "
|
|
34
|
-
"codeclimate-test-reporter": "0.
|
|
35
|
-
"coveralls": "
|
|
36
|
-
"istanbul": "0.4.
|
|
37
|
-
"mocha": "
|
|
38
|
-
"supertest": "
|
|
39
|
-
},
|
|
40
|
-
"optionalDependencies": {
|
|
41
|
-
"nodegrind": "git+https://github.com/stevenvelozo/nodegrind.git"
|
|
33
|
+
"async": "2.6.1",
|
|
34
|
+
"chai": "4.1.2",
|
|
35
|
+
"codeclimate-test-reporter": "0.5.0",
|
|
36
|
+
"coveralls": "3.0.2",
|
|
37
|
+
"istanbul": "0.4.5",
|
|
38
|
+
"mocha": "5.2.0",
|
|
39
|
+
"supertest": "3.1.0"
|
|
42
40
|
},
|
|
43
41
|
"dependencies": {
|
|
42
|
+
"cachetrax": "^1.0.0",
|
|
44
43
|
"cluster": "^0.7.7",
|
|
45
|
-
"fable": "~1.0.
|
|
46
|
-
"fable-uuid": "~1.0.
|
|
44
|
+
"fable": "~1.0.2",
|
|
45
|
+
"fable-uuid": "~1.0.2",
|
|
47
46
|
"http-forward": "^0.1.3",
|
|
48
|
-
"request": "^2.
|
|
47
|
+
"request": "^2.88.2",
|
|
49
48
|
"restify": "^6.4.0",
|
|
50
|
-
"restify-await-promise": "^
|
|
49
|
+
"restify-await-promise": "^2.2.0",
|
|
51
50
|
"restify-cors-middleware": "^1.1.1"
|
|
52
51
|
}
|
|
53
52
|
}
|
package/source/Orator.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const libRestifyCORS = require('restify-cors-middleware');
|
|
8
8
|
const restifyPromise = require('restify-await-promise');
|
|
9
|
+
const RestifyErrors = require('restify-errors');
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Orator Web API Server
|
|
@@ -25,14 +26,13 @@ var Orator = function()
|
|
|
25
26
|
|
|
26
27
|
// Restify for the routing and API serving
|
|
27
28
|
var libRestify = require('restify');
|
|
28
|
-
// NodeGrind for request profiling
|
|
29
|
-
var libNodegrind = false;
|
|
30
29
|
// FS for writing out profiling information
|
|
31
30
|
var libFS = require('fs');
|
|
32
31
|
// Cluster API for spawning multiple worker processes
|
|
33
32
|
var libCluster = require('cluster');
|
|
34
33
|
// HTTP Forward Proxy
|
|
35
34
|
var libHttpForward = require('http-forward');
|
|
35
|
+
|
|
36
36
|
var _ProxyRoutes = [];
|
|
37
37
|
|
|
38
38
|
// This state is used to lazily initialize the Native Restify Modules on route creation the first time
|
|
@@ -112,7 +112,7 @@ var Orator = function()
|
|
|
112
112
|
// This is used as the base object for instantiating the server. You can add custom parsers and formatters safely with lambdas here.
|
|
113
113
|
RawServerParameters: {},
|
|
114
114
|
|
|
115
|
-
//
|
|
115
|
+
// Enable request lifecycle logging if desired, for debugging
|
|
116
116
|
Profiling: (
|
|
117
117
|
{
|
|
118
118
|
// Tracelog is just log-based request timing encapsulation.
|
|
@@ -120,16 +120,7 @@ var Orator = function()
|
|
|
120
120
|
|
|
121
121
|
// Requestlog is to log each request ID and Session ID.
|
|
122
122
|
RequestLog: false,
|
|
123
|
-
|
|
124
|
-
// These profiling settings determine if we generate cpu or call graphs
|
|
125
|
-
Enabled: false,
|
|
126
|
-
Folder: '/tmp/',
|
|
127
|
-
// Currently supported profile types: CallGrinder or ChromeCPU
|
|
128
|
-
Type: 'CallGrinder'
|
|
129
123
|
}),
|
|
130
|
-
|
|
131
|
-
// Turning this on logs stack traces
|
|
132
|
-
LogStackTraces: true
|
|
133
124
|
});
|
|
134
125
|
|
|
135
126
|
var _Fable = require('fable').new(pSettings);
|
|
@@ -251,7 +242,7 @@ var Orator = function()
|
|
|
251
242
|
// Lazily initialize the Restify parsers the first time we access this object.
|
|
252
243
|
// This creates a behavior where changing the "enabledModules" property does not
|
|
253
244
|
// do anything after routes have been created. We may want to eventually
|
|
254
|
-
// throw a warning (and
|
|
245
|
+
// throw a warning (and ignore the change) if someone accesses the property
|
|
255
246
|
// after _RestifyParsersInitialized is true.
|
|
256
247
|
if (!_RestifyParsersInitialized)
|
|
257
248
|
{
|
|
@@ -259,21 +250,6 @@ var Orator = function()
|
|
|
259
250
|
initializeHeaderParsers(_Fable.settings, _WebServer);
|
|
260
251
|
initializeContentParsers(_Fable.settings, _WebServer);
|
|
261
252
|
initializeLogicParsers(_Fable.settings, _WebServer);
|
|
262
|
-
_WebServer.on
|
|
263
|
-
(
|
|
264
|
-
'uncaughtException',
|
|
265
|
-
function (pRequest, pResponse, pRoute, pError)
|
|
266
|
-
{
|
|
267
|
-
if (typeof(_Fable.settings.UncaughtExceptionHook) === 'function')
|
|
268
|
-
{
|
|
269
|
-
_Fable.settings.UncaughtExceptionHook(pRequest, pResponse, pRoute, pError);
|
|
270
|
-
}
|
|
271
|
-
if (_Fable.settings.LogStackTraces)
|
|
272
|
-
{
|
|
273
|
-
_Fable.log.error('Request error', {Error:true, Stack:pError.stack});
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
);
|
|
277
253
|
}
|
|
278
254
|
};
|
|
279
255
|
|
|
@@ -299,18 +275,6 @@ var Orator = function()
|
|
|
299
275
|
_Fable.log.trace('Request start...',{RequestUUID: pRequest.RequestUUID});
|
|
300
276
|
}
|
|
301
277
|
|
|
302
|
-
if (_Fable.settings.Profiling.Enabled)
|
|
303
|
-
{
|
|
304
|
-
// Lazily load NodeGrind
|
|
305
|
-
if (!libNodegrind)
|
|
306
|
-
{
|
|
307
|
-
libNodegrind = require('nodegrind');
|
|
308
|
-
}
|
|
309
|
-
// If profiling is enabled, build a callgrind file
|
|
310
|
-
_Fable.log.debug('Request '+pRequest.RequestUUID+' starting with full profiling...');
|
|
311
|
-
pRequest.ProfilerName = _Fable.settings.Product+'-'+_Fable.settings.ProductVersion+'-'+pRequest.RequestUUID;
|
|
312
|
-
libNodegrind.startCPU(pRequest.RequestUUID);
|
|
313
|
-
}
|
|
314
278
|
|
|
315
279
|
return fNext();
|
|
316
280
|
}
|
|
@@ -325,34 +289,6 @@ var Orator = function()
|
|
|
325
289
|
{
|
|
326
290
|
_Fable.log.trace("... Request finished.",{RequestUUID: pRequest.RequestUUID, ResponseCode: pResponse.code, ResponseLength: pResponse.contentLength});
|
|
327
291
|
}
|
|
328
|
-
|
|
329
|
-
if (typeof(pRequest.ProfilerName) === 'string')
|
|
330
|
-
{
|
|
331
|
-
var tmpRequestProfile = '';
|
|
332
|
-
var tmpRequestProfilePrefix = '';
|
|
333
|
-
var tmpRequestProfilePostfix = '';
|
|
334
|
-
|
|
335
|
-
if (_Fable.settings.Profiling.Type === 'CallGrinder')
|
|
336
|
-
{
|
|
337
|
-
// Get the callgrind profile as a string
|
|
338
|
-
tmpRequestProfile = libNodegrind.stopCPU(pRequest.RequestUUID);
|
|
339
|
-
tmpRequestProfilePrefix = 'callgrind.';
|
|
340
|
-
}
|
|
341
|
-
else
|
|
342
|
-
{
|
|
343
|
-
// Alternatively, get a Chrome *.cpuprofile that you can load into the Chrome
|
|
344
|
-
// profiler (right-click on 'Profiles' in left pane in the 'Profiles' tab)
|
|
345
|
-
tmpRequestProfile = libNodegrind.stopCPU(pRequest.RequestUUID, 'cpuprofile');
|
|
346
|
-
tmpRequestProfilePostfix = '.cpuprofile';
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
libFS.writeFileSync(_Fable.settings.Profiling.Folder+tmpRequestProfilePrefix+pRequest.ProfilerName+tmpRequestProfilePostfix, tmpRequestProfile);
|
|
350
|
-
|
|
351
|
-
if (_Fable.settings.Profiling.TraceLog)
|
|
352
|
-
{
|
|
353
|
-
_Fable.log.trace('... Request '+pRequest.RequestUUID+' profile written to: '+_Fable.settings.Profiling.Folder+pRequest.ProfilerName);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
292
|
}
|
|
357
293
|
);
|
|
358
294
|
};
|
|
@@ -366,16 +302,16 @@ var Orator = function()
|
|
|
366
302
|
*
|
|
367
303
|
* @method startWorkers
|
|
368
304
|
*/
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
305
|
+
var startWorkers = function(pWorkers, fCallback)
|
|
306
|
+
{
|
|
307
|
+
if (pWorkers === 0)
|
|
308
|
+
{
|
|
309
|
+
return fCallback();
|
|
310
|
+
}
|
|
311
|
+
else if (pWorkers < 0)
|
|
312
|
+
{
|
|
313
|
+
pWorkers = require('os').cpus().length;
|
|
314
|
+
}
|
|
379
315
|
|
|
380
316
|
for (var i=0; i<pWorkers; i++)
|
|
381
317
|
{
|
|
@@ -386,25 +322,25 @@ var Orator = function()
|
|
|
386
322
|
|
|
387
323
|
libCluster.on('message', function(message)
|
|
388
324
|
{
|
|
389
|
-
|
|
325
|
+
_Fable.log.trace('Orator Worker ' + message.pid + ' started.');
|
|
390
326
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
327
|
+
if (++tmpActiveWorkers === pWorkers)
|
|
328
|
+
{
|
|
329
|
+
//The Master process fires the callback when all
|
|
330
|
+
// the workers have started. This is used by
|
|
331
|
+
// unit tests.
|
|
332
|
+
return fCallback();
|
|
333
|
+
}
|
|
398
334
|
});
|
|
399
335
|
libCluster.on('exit', function(worker, code, signal)
|
|
400
336
|
{
|
|
401
|
-
|
|
337
|
+
_Fable.log.trace('Orator Worker ' + worker.id + '/' + worker.process.pid + ' died');
|
|
402
338
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
339
|
+
// APIWorkerRestart flag auto-restarts a worker if it crashes
|
|
340
|
+
if (_Fable.settings.APIWorkerRestart)
|
|
341
|
+
{
|
|
342
|
+
libCluster.fork();
|
|
343
|
+
}
|
|
408
344
|
});
|
|
409
345
|
};
|
|
410
346
|
|
|
@@ -438,7 +374,7 @@ var Orator = function()
|
|
|
438
374
|
if (!libCluster.isMaster)
|
|
439
375
|
{
|
|
440
376
|
// notify master about the request
|
|
441
|
-
|
|
377
|
+
process.send({ signal: 'notifyListening', pid: process.pid });
|
|
442
378
|
}
|
|
443
379
|
return tmpNext();
|
|
444
380
|
}
|
|
@@ -501,7 +437,8 @@ var Orator = function()
|
|
|
501
437
|
'application/octet-stream',
|
|
502
438
|
'application/javascript',
|
|
503
439
|
'application/json'
|
|
504
|
-
]
|
|
440
|
+
],
|
|
441
|
+
handleUncaughtExceptions: true,
|
|
505
442
|
});
|
|
506
443
|
_Fable.settings.RawServerParameters = _WebServerParameters;
|
|
507
444
|
};
|
|
@@ -604,7 +541,7 @@ var Orator = function()
|
|
|
604
541
|
_Fable.log.error('Proxy error', pError);
|
|
605
542
|
}
|
|
606
543
|
|
|
607
|
-
return fNext(
|
|
544
|
+
return fNext(false);
|
|
608
545
|
});
|
|
609
546
|
};
|
|
610
547
|
|
|
@@ -652,16 +589,45 @@ var Orator = function()
|
|
|
652
589
|
);
|
|
653
590
|
};
|
|
654
591
|
|
|
592
|
+
var userErrorTransformer;
|
|
593
|
+
var registerErrorTransformer = function(transformError)
|
|
594
|
+
{
|
|
595
|
+
if (typeof(transformError) === 'function')
|
|
596
|
+
{
|
|
597
|
+
userErrorTransformer = transformError;
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
var userUnhandledErrorHandler;
|
|
602
|
+
var registerUnhandledErrorHandler = function(callback)
|
|
603
|
+
{
|
|
604
|
+
if (typeof(callback) === 'function')
|
|
605
|
+
{
|
|
606
|
+
userUnhandledErrorHandler = callback;
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
|
|
655
610
|
var handleError = function(req, res, err, callback)
|
|
656
611
|
{
|
|
612
|
+
// allow application to customize this error handling
|
|
613
|
+
if (typeof userUnhandledErrorHandler == 'function' && !userUnhandledErrorHandler(req, res, err))
|
|
614
|
+
{
|
|
615
|
+
return callback();
|
|
616
|
+
}
|
|
657
617
|
//the default for a string error is 'Route not found', though it isn't accurate
|
|
658
618
|
err.message = err.message.replace('Route not found: ', '');
|
|
659
619
|
//log error
|
|
660
620
|
let sessionId = '';
|
|
661
621
|
if (req.UserSession && req.UserSession.SessionID)
|
|
622
|
+
{
|
|
662
623
|
sessionId = req.UserSession.SessionID;
|
|
663
|
-
|
|
664
|
-
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
if (!err.logged)
|
|
627
|
+
{
|
|
628
|
+
_Fable.log.error('REQUEST ERROR: ' + err.message || err,
|
|
629
|
+
{ SessionID: sessionId, Action: 'APIError', RequestUUID: req.RequestUUID, Error: err.message || err, Stack: err.stack, });
|
|
630
|
+
}
|
|
665
631
|
return callback();
|
|
666
632
|
}
|
|
667
633
|
|
|
@@ -682,6 +648,9 @@ var Orator = function()
|
|
|
682
648
|
serveStatic: libRestify.plugins.serveStatic,
|
|
683
649
|
getHeader: getHeader,
|
|
684
650
|
|
|
651
|
+
registerErrorTransformer: registerErrorTransformer,
|
|
652
|
+
registerUnhandledErrorHandler: registerUnhandledErrorHandler,
|
|
653
|
+
|
|
685
654
|
new: createNew
|
|
686
655
|
});
|
|
687
656
|
|
|
@@ -691,7 +660,7 @@ var Orator = function()
|
|
|
691
660
|
* @property webServer
|
|
692
661
|
* @type Object
|
|
693
662
|
*/
|
|
694
|
-
var getWebServer = function()
|
|
663
|
+
var getWebServer = function()
|
|
695
664
|
{
|
|
696
665
|
// Lazily load the webserver the first time it is accessed
|
|
697
666
|
if (typeof(_WebServer) === 'undefined')
|
|
@@ -701,7 +670,35 @@ var Orator = function()
|
|
|
701
670
|
_WebServerParameters.version = _Fable.settings.ProductVersion;
|
|
702
671
|
_WebServer = libRestify.createServer(_WebServerParameters);
|
|
703
672
|
//enable support for Promise endpoint methods
|
|
704
|
-
restifyPromise.install(_WebServer
|
|
673
|
+
restifyPromise.install(_WebServer,
|
|
674
|
+
{
|
|
675
|
+
/*
|
|
676
|
+
* We provide an error transformer here to handle uncaught exceptions, as the
|
|
677
|
+
* old code path is broken by this plugin. This at least allows us to send back
|
|
678
|
+
* some kind of error to the caller. Without this, you get a 500 with a body of {}
|
|
679
|
+
*/
|
|
680
|
+
errorTransformer:
|
|
681
|
+
{
|
|
682
|
+
transform: (originalError) =>
|
|
683
|
+
{
|
|
684
|
+
let error = originalError;
|
|
685
|
+
if (typeof userErrorTransformer == 'function')
|
|
686
|
+
{
|
|
687
|
+
error = userErrorTransformer(error);
|
|
688
|
+
}
|
|
689
|
+
// duck typing for error objects; means an exception was thrown; but status code means it was handled upstream
|
|
690
|
+
if (error && error.message && error.stack && !error.statusCode)
|
|
691
|
+
{
|
|
692
|
+
_Fable.log.fatal('Unhandled request error', { Error: error.message || error, Stack: error.stack, });
|
|
693
|
+
|
|
694
|
+
const wrappedError = new RestifyErrors.InternalError(error, error.message || 'Unhandled error');
|
|
695
|
+
wrappedError.logged = true; // dumb, but prevents double logging in handleError
|
|
696
|
+
return wrappedError;
|
|
697
|
+
}
|
|
698
|
+
return error || new Error('fail request'); // returning no error here is bad news; request can get stuck, so at least return something
|
|
699
|
+
},
|
|
700
|
+
},
|
|
701
|
+
});
|
|
705
702
|
//handle errors - DOES NOT HANDLE uncaught exceptions! (DOES work with Promises however)
|
|
706
703
|
_WebServer.on('restifyError', handleError);
|
|
707
704
|
initializeInstrumentation();
|
|
@@ -16,12 +16,12 @@ var _MockSettings = (
|
|
|
16
16
|
{
|
|
17
17
|
Product: 'MockOratorAlternate',
|
|
18
18
|
ProductVersion: '0.0.0',
|
|
19
|
-
APIServerPort: 8181
|
|
19
|
+
APIServerPort: 8181,
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
suite
|
|
23
23
|
(
|
|
24
|
-
'Orator',
|
|
24
|
+
'Orator Proxy',
|
|
25
25
|
function()
|
|
26
26
|
{
|
|
27
27
|
var _Orator;
|
|
@@ -34,6 +34,14 @@ suite
|
|
|
34
34
|
}
|
|
35
35
|
);
|
|
36
36
|
|
|
37
|
+
suiteTeardown
|
|
38
|
+
(
|
|
39
|
+
function()
|
|
40
|
+
{
|
|
41
|
+
_Orator.stopWebServer();
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
|
|
37
45
|
suite
|
|
38
46
|
(
|
|
39
47
|
'Object Sanity',
|
|
@@ -99,7 +107,7 @@ suite
|
|
|
99
107
|
fNext();
|
|
100
108
|
}
|
|
101
109
|
);
|
|
102
|
-
|
|
110
|
+
|
|
103
111
|
// Create a route to proxy HTTP requests to google, dropping the prefix for the remote request
|
|
104
112
|
_Orator.addProxyRoute('google/', 'https://www.google.com/');
|
|
105
113
|
|
|
@@ -112,7 +120,7 @@ suite
|
|
|
112
120
|
_Orator.addStaticRoute(__dirname+'/../', 'LICENSE', /\/content\/(.*)/, '/content/');
|
|
113
121
|
// You should be able to host files just with a path
|
|
114
122
|
_Orator.addStaticRoute(__dirname+'/');
|
|
115
|
-
|
|
123
|
+
|
|
116
124
|
_Orator.startWebServer(fDone);
|
|
117
125
|
}
|
|
118
126
|
);
|
|
@@ -184,7 +192,7 @@ suite
|
|
|
184
192
|
//check for not found
|
|
185
193
|
Expect(pResponse.statusCode)
|
|
186
194
|
.to.equal(404);
|
|
187
|
-
|
|
195
|
+
|
|
188
196
|
return fDone();
|
|
189
197
|
}
|
|
190
198
|
);
|
|
@@ -196,6 +204,7 @@ suite
|
|
|
196
204
|
'Shutdown Orator web server',
|
|
197
205
|
function()
|
|
198
206
|
{
|
|
207
|
+
//TODO: this test assumes the order of test execution; is that safe?
|
|
199
208
|
_Orator.stopWebServer();
|
|
200
209
|
}
|
|
201
210
|
);
|
|
@@ -16,21 +16,47 @@ var _MockSettings = (
|
|
|
16
16
|
{
|
|
17
17
|
Product: 'MockOratorAlternate',
|
|
18
18
|
ProductVersion: '0.0.0',
|
|
19
|
-
APIServerPort:
|
|
19
|
+
APIServerPort: 8999,
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
suite
|
|
23
23
|
(
|
|
24
|
-
'Orator',
|
|
24
|
+
'Orator basic',
|
|
25
25
|
function()
|
|
26
26
|
{
|
|
27
27
|
var _Orator;
|
|
28
|
+
let capturedOriginalErr = null;
|
|
29
|
+
let capturedReq = null;
|
|
30
|
+
let capturedRes = null;
|
|
31
|
+
let capturedErr = null;
|
|
28
32
|
|
|
29
33
|
setup
|
|
30
34
|
(
|
|
31
35
|
function()
|
|
32
36
|
{
|
|
33
37
|
_Orator = require('../source/Orator.js').new(_MockSettings);
|
|
38
|
+
_Orator.registerUnhandledErrorHandler((req, res, err) =>
|
|
39
|
+
{
|
|
40
|
+
capturedReq = req;
|
|
41
|
+
capturedRes = res;
|
|
42
|
+
capturedErr = err;
|
|
43
|
+
return err.statusCode > 0;
|
|
44
|
+
});
|
|
45
|
+
_Orator.registerErrorTransformer((err) =>
|
|
46
|
+
{
|
|
47
|
+
capturedOriginalErr = err;
|
|
48
|
+
return err;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
teardown(() => { capturedReq = undefined; capturedRes = undefined; capturedErr = undefined; capturedOriginalErr = undefined; });
|
|
54
|
+
|
|
55
|
+
suiteTeardown
|
|
56
|
+
(
|
|
57
|
+
function()
|
|
58
|
+
{
|
|
59
|
+
_Orator.stopWebServer();
|
|
34
60
|
}
|
|
35
61
|
);
|
|
36
62
|
|
|
@@ -95,8 +121,8 @@ suite
|
|
|
95
121
|
'/ThirdAPI',
|
|
96
122
|
function (pRequest, pResponse, fNext)
|
|
97
123
|
{
|
|
98
|
-
|
|
99
|
-
|
|
124
|
+
throw new Error('The server should give a nice stack trace');
|
|
125
|
+
fNext();
|
|
100
126
|
}
|
|
101
127
|
);
|
|
102
128
|
_Orator.webServer.get (
|
|
@@ -113,29 +139,48 @@ suite
|
|
|
113
139
|
return Promise.reject('error promise response');
|
|
114
140
|
}
|
|
115
141
|
);
|
|
142
|
+
_Orator.webServer.get (
|
|
143
|
+
'/SyncBug',
|
|
144
|
+
function (pRequest, pResponse, fNext)
|
|
145
|
+
{
|
|
146
|
+
const cat = null;
|
|
147
|
+
cat.dog();
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
_Orator.webServer.get (
|
|
151
|
+
'/AsyncBug',
|
|
152
|
+
async function (pRequest, pResponse)
|
|
153
|
+
{
|
|
154
|
+
await new Promise((resolve) => setTimeout(() => resolve()), 1);
|
|
155
|
+
const cat = null;
|
|
156
|
+
cat.dog();
|
|
157
|
+
}
|
|
158
|
+
);
|
|
116
159
|
// Expect this to fail
|
|
117
160
|
_Orator.addStaticRoute();
|
|
118
161
|
// And you can specify a path for bonus
|
|
119
|
-
|
|
162
|
+
var libPath = require('path');
|
|
163
|
+
var tmpPath = libPath.normalize(__dirname+'/');
|
|
164
|
+
_Orator.addStaticRoute(tmpPath, 'Test.html', /\/content\/(.*)/, '/content/');
|
|
120
165
|
// You should be able to host files just with a path
|
|
121
166
|
_Orator.addStaticRoute(__dirname+'/');
|
|
122
167
|
_Orator.startWebServer
|
|
123
168
|
(
|
|
124
169
|
function ()
|
|
125
170
|
{
|
|
126
|
-
libSuperTest(
|
|
171
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
127
172
|
.get('PIN')
|
|
128
173
|
.end(
|
|
129
174
|
function (pError, pResponse)
|
|
130
175
|
{
|
|
131
176
|
Expect(pResponse.text)
|
|
132
177
|
.to.contain('PON');
|
|
133
|
-
libSuperTest(
|
|
178
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
134
179
|
.get('ThirdAPI')
|
|
135
180
|
.end(
|
|
136
181
|
function (pError, pResponse)
|
|
137
182
|
{
|
|
138
|
-
libSuperTest(
|
|
183
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
139
184
|
.get('Test.css')
|
|
140
185
|
.end(
|
|
141
186
|
function (pError, pResponse)
|
|
@@ -143,13 +188,13 @@ suite
|
|
|
143
188
|
_Orator.settings.Profiling.TraceLog = true;
|
|
144
189
|
Expect(pResponse.text)
|
|
145
190
|
.to.contain('50000px');
|
|
146
|
-
libSuperTest(
|
|
191
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
147
192
|
.get('content/')
|
|
148
193
|
.end(
|
|
149
194
|
function (pError, pResponse)
|
|
150
195
|
{
|
|
151
196
|
Expect(pResponse.text)
|
|
152
|
-
.to.contain('
|
|
197
|
+
.to.contain('Um');
|
|
153
198
|
fDone();
|
|
154
199
|
}
|
|
155
200
|
);
|
|
@@ -168,7 +213,7 @@ suite
|
|
|
168
213
|
'promise routes should work',
|
|
169
214
|
function(fDone)
|
|
170
215
|
{
|
|
171
|
-
libSuperTest(
|
|
216
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
172
217
|
.get('PromiseAPI')
|
|
173
218
|
.end(
|
|
174
219
|
function (pError, pResponse)
|
|
@@ -186,14 +231,69 @@ suite
|
|
|
186
231
|
'promise routes error handling',
|
|
187
232
|
function(fDone)
|
|
188
233
|
{
|
|
189
|
-
libSuperTest(
|
|
234
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
190
235
|
.get('PromiseAPIError')
|
|
191
236
|
.end(
|
|
192
237
|
function (pError, pResponse)
|
|
193
238
|
{
|
|
239
|
+
Expect(capturedErr).to.exist;
|
|
240
|
+
Expect(capturedReq).to.exist;
|
|
241
|
+
Expect(capturedRes).to.exist;
|
|
194
242
|
Expect(pResponse.text)
|
|
195
243
|
.to.contain('error promise response');
|
|
196
244
|
|
|
245
|
+
return fDone();
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
test
|
|
251
|
+
(
|
|
252
|
+
'unhandled error interception',
|
|
253
|
+
function(fDone)
|
|
254
|
+
{
|
|
255
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
256
|
+
.get('SyncBug')
|
|
257
|
+
.end(
|
|
258
|
+
function (pError, pResponse)
|
|
259
|
+
{
|
|
260
|
+
Expect(pError).to.not.exist;
|
|
261
|
+
Expect(capturedOriginalErr).to.exist;
|
|
262
|
+
Expect(capturedErr).to.exist;
|
|
263
|
+
Expect(capturedOriginalErr.statusCode).to.not.exist; // raw error
|
|
264
|
+
Expect(capturedErr.statusCode).to.equal(500); // wrapped to give reasonable http response
|
|
265
|
+
Expect(capturedReq).to.exist; // shows we called the custom error handler
|
|
266
|
+
Expect(capturedReq.RequestUUID).to.be.a('string'); // so we can log this from the handler
|
|
267
|
+
Expect(capturedRes).to.exist; // shows we called the custom error handler
|
|
268
|
+
Expect(capturedErr.message).to.contain('Cannot read property \'dog\'');
|
|
269
|
+
Expect(pResponse.text).to.contain('Cannot read property \'dog\'');
|
|
270
|
+
|
|
271
|
+
return fDone();
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
test
|
|
277
|
+
(
|
|
278
|
+
'unhandled error interception async',
|
|
279
|
+
function(fDone)
|
|
280
|
+
{
|
|
281
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
282
|
+
.get('AsyncBug')
|
|
283
|
+
.end(
|
|
284
|
+
function (pError, pResponse)
|
|
285
|
+
{
|
|
286
|
+
Expect(pError).to.not.exist;
|
|
287
|
+
Expect(capturedOriginalErr).to.exist;
|
|
288
|
+
Expect(capturedErr).to.exist;
|
|
289
|
+
Expect(capturedOriginalErr.statusCode).to.not.exist; // raw error
|
|
290
|
+
Expect(capturedErr.statusCode).to.equal(500); // wrapped to give reasonable http response
|
|
291
|
+
Expect(capturedReq).to.exist; // shows we called the custom error handler
|
|
292
|
+
Expect(capturedReq.RequestUUID).to.be.a('string'); // so we can log this from the handler
|
|
293
|
+
Expect(capturedRes).to.exist; // shows we called the custom error handler
|
|
294
|
+
Expect(capturedErr.message).to.contain('Cannot read property \'dog\'');
|
|
295
|
+
Expect(pResponse.text).to.contain('Cannot read property \'dog\'');
|
|
296
|
+
|
|
197
297
|
return fDone();
|
|
198
298
|
}
|
|
199
299
|
);
|
|
@@ -215,7 +315,7 @@ suite
|
|
|
215
315
|
{
|
|
216
316
|
Product: 'MockOratorInverted',
|
|
217
317
|
ProductVersion: '0.0.0',
|
|
218
|
-
APIServerPort:
|
|
318
|
+
APIServerPort: _MockSettings.APIServerPort - 10,
|
|
219
319
|
LogStackTraces: false
|
|
220
320
|
});
|
|
221
321
|
var _OratorInverted = require('../source/Orator.js').new(_MockSettingsInvertedParameters);
|
|
@@ -249,11 +349,12 @@ suite
|
|
|
249
349
|
}
|
|
250
350
|
);
|
|
251
351
|
_OratorInverted.startWebServer();
|
|
252
|
-
libSuperTest(
|
|
352
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort - 10}/`)
|
|
253
353
|
.get('PINGU')
|
|
254
354
|
.end(
|
|
255
355
|
function (pError, pResponse)
|
|
256
356
|
{
|
|
357
|
+
_OratorInverted.stopWebServer();
|
|
257
358
|
if (pError)
|
|
258
359
|
{
|
|
259
360
|
console.log('Error on Inverted Results: '+JSON.stringify(pError));
|
|
@@ -280,4 +381,4 @@ suite
|
|
|
280
381
|
}
|
|
281
382
|
);
|
|
282
383
|
}
|
|
283
|
-
);
|
|
384
|
+
);
|
|
@@ -17,7 +17,7 @@ var _MockSettings = (
|
|
|
17
17
|
{
|
|
18
18
|
Product: 'MockOratorAlternate',
|
|
19
19
|
ProductVersion: '0.0.0',
|
|
20
|
-
APIServerPort:
|
|
20
|
+
APIServerPort: 8099,
|
|
21
21
|
APIWorkers: 3,
|
|
22
22
|
APIWorkerRestart: false
|
|
23
23
|
});
|
|
@@ -99,7 +99,9 @@ suite
|
|
|
99
99
|
// Expect this to fail
|
|
100
100
|
_Orator.addStaticRoute();
|
|
101
101
|
// And you can specify a path for bonus
|
|
102
|
-
|
|
102
|
+
var libPath = require('path');
|
|
103
|
+
var tmpPath = libPath.normalize(__dirname+'/');
|
|
104
|
+
_Orator.addStaticRoute(tmpPath, 'Test.html', /\/content\/(.*)/, '/content/');
|
|
103
105
|
// You should be able to host files just with a path
|
|
104
106
|
_Orator.addStaticRoute(__dirname+'/');
|
|
105
107
|
|
|
@@ -133,19 +135,19 @@ suite
|
|
|
133
135
|
function(fDone)
|
|
134
136
|
{
|
|
135
137
|
|
|
136
|
-
libSuperTest('http://localhost:
|
|
138
|
+
libSuperTest('http://localhost:8099/')
|
|
137
139
|
.get('PIN')
|
|
138
140
|
.end(
|
|
139
141
|
function (pError, pResponse)
|
|
140
142
|
{
|
|
141
143
|
Expect(pResponse.text)
|
|
142
144
|
.to.contain('PON');
|
|
143
|
-
libSuperTest('http://localhost:
|
|
145
|
+
libSuperTest('http://localhost:8099/')
|
|
144
146
|
.get('ThirdAPI')
|
|
145
147
|
.end(
|
|
146
148
|
function (pError, pResponse)
|
|
147
149
|
{
|
|
148
|
-
libSuperTest('http://localhost:
|
|
150
|
+
libSuperTest('http://localhost:8099/')
|
|
149
151
|
.get('Test.css')
|
|
150
152
|
.end(
|
|
151
153
|
function (pError, pResponse)
|
|
@@ -153,13 +155,13 @@ suite
|
|
|
153
155
|
_Orator.settings.Profiling.TraceLog = true;
|
|
154
156
|
Expect(pResponse.text)
|
|
155
157
|
.to.contain('50000px');
|
|
156
|
-
libSuperTest('http://localhost:
|
|
158
|
+
libSuperTest('http://localhost:8099/')
|
|
157
159
|
.get('content/')
|
|
158
160
|
.end(
|
|
159
161
|
function (pError, pResponse)
|
|
160
162
|
{
|
|
161
163
|
Expect(pResponse.text)
|
|
162
|
-
.to.contain('
|
|
164
|
+
.to.contain('Um');
|
|
163
165
|
|
|
164
166
|
return fDone();
|
|
165
167
|
}
|
|
@@ -189,7 +191,7 @@ suite
|
|
|
189
191
|
|
|
190
192
|
for(var i=0; i<DISTRIBUTION_LOAD_COUNT; i++)
|
|
191
193
|
{
|
|
192
|
-
libSuperTest('http://localhost:
|
|
194
|
+
libSuperTest('http://localhost:8099/')
|
|
193
195
|
.get('GetPID')
|
|
194
196
|
.end(
|
|
195
197
|
function (pError, pResponse)
|
|
@@ -228,4 +230,4 @@ suite
|
|
|
228
230
|
);
|
|
229
231
|
}
|
|
230
232
|
}
|
|
231
|
-
);
|
|
233
|
+
);
|
|
@@ -15,7 +15,7 @@ var libSuperTest = require('supertest');
|
|
|
15
15
|
var _MockSettings = (
|
|
16
16
|
{
|
|
17
17
|
Product: 'MockOratorRequestLogging',
|
|
18
|
-
APIServerPort:
|
|
18
|
+
APIServerPort: 8985,
|
|
19
19
|
Profiling: (
|
|
20
20
|
{
|
|
21
21
|
// Tracelog is just log-based request timing encapsulation.
|
|
@@ -40,6 +40,14 @@ suite
|
|
|
40
40
|
}
|
|
41
41
|
);
|
|
42
42
|
|
|
43
|
+
suiteTeardown
|
|
44
|
+
(
|
|
45
|
+
function()
|
|
46
|
+
{
|
|
47
|
+
_Orator.stopWebServer();
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
|
|
43
51
|
suite
|
|
44
52
|
(
|
|
45
53
|
'Request Logging Server Start',
|
|
@@ -51,24 +59,31 @@ suite
|
|
|
51
59
|
function(fDone)
|
|
52
60
|
{
|
|
53
61
|
_Orator.webServer.get (
|
|
54
|
-
'/PINGOLo',
|
|
55
|
-
function (pRequest, pResponse, fNext)
|
|
62
|
+
'/PINGOLo',
|
|
63
|
+
function (pRequest, pResponse, fNext)
|
|
56
64
|
{
|
|
57
65
|
pResponse.send('Loggo');
|
|
58
66
|
fNext();
|
|
59
67
|
}
|
|
60
68
|
);
|
|
61
69
|
_Orator.webServer.get (
|
|
62
|
-
'/PINataGOLo',
|
|
63
|
-
function (pRequest, pResponse, fNext)
|
|
70
|
+
'/PINataGOLo',
|
|
71
|
+
function (pRequest, pResponse, fNext)
|
|
64
72
|
{
|
|
65
73
|
throw new Error("Something absolutely dire has occurred.");
|
|
66
74
|
pResponse.send('Loggso');
|
|
67
75
|
fNext();
|
|
68
76
|
}
|
|
69
77
|
);
|
|
78
|
+
_Orator.webServer.get (
|
|
79
|
+
'/PINataGOLo_promise',
|
|
80
|
+
async function (pRequest, pResponse)
|
|
81
|
+
{
|
|
82
|
+
return Promise.reject("Something absolutely dire has occurred.");
|
|
83
|
+
}
|
|
84
|
+
);
|
|
70
85
|
_Orator.startWebServer();
|
|
71
|
-
libSuperTest(
|
|
86
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
72
87
|
.get('PINGOLo')
|
|
73
88
|
.end(
|
|
74
89
|
function (pError, pResponse)
|
|
@@ -83,7 +98,7 @@ suite
|
|
|
83
98
|
Expect(pResponse.text)
|
|
84
99
|
.to.contain('Loggo');
|
|
85
100
|
}
|
|
86
|
-
libSuperTest(
|
|
101
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
87
102
|
.get('PINataGOLo')
|
|
88
103
|
.end(
|
|
89
104
|
function (pError, pResponse)
|
|
@@ -95,6 +110,8 @@ suite
|
|
|
95
110
|
}
|
|
96
111
|
else
|
|
97
112
|
{
|
|
113
|
+
Expect(pResponse.statusCode)
|
|
114
|
+
.to.equal(500);
|
|
98
115
|
Expect(pResponse.text)
|
|
99
116
|
.to.contain('dire');
|
|
100
117
|
}
|
|
@@ -112,8 +129,35 @@ suite
|
|
|
112
129
|
'uncaught exceptions should throw properly.',
|
|
113
130
|
function(fDone)
|
|
114
131
|
{
|
|
115
|
-
libSuperTest(
|
|
132
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
116
133
|
.get('PINataGOLo')
|
|
134
|
+
.end(
|
|
135
|
+
function (pError, pResponse)
|
|
136
|
+
{
|
|
137
|
+
if (pError)
|
|
138
|
+
{
|
|
139
|
+
console.log('Error on Logfile Results: '+JSON.stringify(pError));
|
|
140
|
+
Expect('Logged Request Error').to.equal('Nothing');
|
|
141
|
+
}
|
|
142
|
+
else
|
|
143
|
+
{
|
|
144
|
+
Expect(pResponse.statusCode)
|
|
145
|
+
.to.equal(500);
|
|
146
|
+
Expect(pResponse.text)
|
|
147
|
+
.to.contain('dire');
|
|
148
|
+
}
|
|
149
|
+
fDone();
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
test
|
|
155
|
+
(
|
|
156
|
+
'rejected promises should throw properly.',
|
|
157
|
+
function(fDone)
|
|
158
|
+
{
|
|
159
|
+
libSuperTest(`http://localhost:${_MockSettings.APIServerPort}/`)
|
|
160
|
+
.get('PINataGOLo_promise')
|
|
117
161
|
.end(
|
|
118
162
|
function (pError, pResponse)
|
|
119
163
|
{
|
|
@@ -135,4 +179,4 @@ suite
|
|
|
135
179
|
}
|
|
136
180
|
);
|
|
137
181
|
}
|
|
138
|
-
);
|
|
182
|
+
);
|
package/test/Test.html
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<html><head></head><body>Um</body></html>
|
package/.vscode/launch.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Use IntelliSense to learn about possible attributes.
|
|
3
|
-
// Hover to view descriptions of existing attributes.
|
|
4
|
-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
-
"version": "0.2.0",
|
|
6
|
-
"configurations": [
|
|
7
|
-
{
|
|
8
|
-
"type": "node",
|
|
9
|
-
"request": "launch",
|
|
10
|
-
"name": "Mocha Tests",
|
|
11
|
-
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
|
|
12
|
-
"args": [
|
|
13
|
-
"-u",
|
|
14
|
-
"tdd",
|
|
15
|
-
"--bail",
|
|
16
|
-
"--timeout",
|
|
17
|
-
"999999",
|
|
18
|
-
"--colors",
|
|
19
|
-
"${workspaceFolder}/test/Orator_basic_tests.js"
|
|
20
|
-
],
|
|
21
|
-
"internalConsoleOptions": "openOnSessionStart"
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for the Orator Server
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
var Chai = require("chai");
|
|
10
|
-
var Expect = Chai.expect;
|
|
11
|
-
var Assert = Chai.assert;
|
|
12
|
-
|
|
13
|
-
var libSuperTest = require('supertest');
|
|
14
|
-
|
|
15
|
-
var _MockSettings = (
|
|
16
|
-
{
|
|
17
|
-
Product: 'MockOratorGRINDER',
|
|
18
|
-
ProductVersion: '0.0.0',
|
|
19
|
-
APIServerPort: 8082,
|
|
20
|
-
Profiling: (
|
|
21
|
-
{
|
|
22
|
-
// Tracelog is just log-based request timing encapsulation.
|
|
23
|
-
TraceLog: true,
|
|
24
|
-
|
|
25
|
-
// These profiling settings determine if we generate cpu or call graphs
|
|
26
|
-
Enabled: true,
|
|
27
|
-
Folder: '/tmp/',
|
|
28
|
-
// Currently supported profile types: CallGrinder or ChromeCPU
|
|
29
|
-
Type: 'CallGrinder'
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
suite
|
|
35
|
-
(
|
|
36
|
-
'Orator',
|
|
37
|
-
function()
|
|
38
|
-
{
|
|
39
|
-
var _Orator;
|
|
40
|
-
|
|
41
|
-
setup
|
|
42
|
-
(
|
|
43
|
-
function()
|
|
44
|
-
{
|
|
45
|
-
_Orator = require('../source/Orator.js').new(_MockSettings);
|
|
46
|
-
}
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
suite
|
|
50
|
-
(
|
|
51
|
-
'Alternate (cachegrinder) Server Start',
|
|
52
|
-
function()
|
|
53
|
-
{
|
|
54
|
-
test
|
|
55
|
-
(
|
|
56
|
-
'simple routes should work',
|
|
57
|
-
function(fDone)
|
|
58
|
-
{
|
|
59
|
-
_Orator.webServer.get (
|
|
60
|
-
'/PING',
|
|
61
|
-
function (pRequest, pResponse, fNext)
|
|
62
|
-
{
|
|
63
|
-
pResponse.send('PONG');
|
|
64
|
-
fNext();
|
|
65
|
-
}
|
|
66
|
-
);
|
|
67
|
-
_Orator.startWebServer(
|
|
68
|
-
function()
|
|
69
|
-
{
|
|
70
|
-
libSuperTest('http://localhost:8082/')
|
|
71
|
-
.get('PING')
|
|
72
|
-
.end(
|
|
73
|
-
function (pError, pResponse)
|
|
74
|
-
{
|
|
75
|
-
if (pError)
|
|
76
|
-
{
|
|
77
|
-
console.log('Error on Inverted Results: '+JSON.stringify(pError));
|
|
78
|
-
Expect('CacheGrinder Request Error').to.equal('Nothing');
|
|
79
|
-
}
|
|
80
|
-
else
|
|
81
|
-
{
|
|
82
|
-
Expect(pResponse.text)
|
|
83
|
-
.to.contain('PONG');
|
|
84
|
-
}
|
|
85
|
-
// This is just to exercise the lazy loaded cachegrinder module
|
|
86
|
-
libSuperTest('http://localhost:8082/')
|
|
87
|
-
.get('PING')
|
|
88
|
-
.end(function (pError, pResponse) {fDone();});
|
|
89
|
-
}
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
);
|
|
93
|
-
Expect(_Orator)
|
|
94
|
-
.to.be.an('object', 'Orator should initialize as an object directly from the require statement.');
|
|
95
|
-
}
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
);
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for the Orator Server
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
var Chai = require("chai");
|
|
10
|
-
var Expect = Chai.expect;
|
|
11
|
-
var Assert = Chai.assert;
|
|
12
|
-
|
|
13
|
-
var libSuperTest = require('supertest');
|
|
14
|
-
|
|
15
|
-
var _MockSettings = (
|
|
16
|
-
{
|
|
17
|
-
Product: 'MockOratorCHROMENOTRACE',
|
|
18
|
-
APIServerPort: 8083,
|
|
19
|
-
Profiling: (
|
|
20
|
-
{
|
|
21
|
-
// Tracelog is just log-based request timing encapsulation.
|
|
22
|
-
TraceLog: false,
|
|
23
|
-
|
|
24
|
-
// These profiling settings determine if we generate cpu or call graphs
|
|
25
|
-
Enabled: true,
|
|
26
|
-
Folder: '/tmp/',
|
|
27
|
-
// Currently supported profile types: CallGrinder or ChromeCPU
|
|
28
|
-
Type: 'ChromeCPU'
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
suite
|
|
34
|
-
(
|
|
35
|
-
'Orator',
|
|
36
|
-
function()
|
|
37
|
-
{
|
|
38
|
-
var _Orator;
|
|
39
|
-
|
|
40
|
-
setup
|
|
41
|
-
(
|
|
42
|
-
function()
|
|
43
|
-
{
|
|
44
|
-
_Orator = require('../source/Orator.js').new(_MockSettings);
|
|
45
|
-
}
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
suite
|
|
49
|
-
(
|
|
50
|
-
'Alternate (chromecpu) without Trace Server Start',
|
|
51
|
-
function()
|
|
52
|
-
{
|
|
53
|
-
test
|
|
54
|
-
(
|
|
55
|
-
'simple routes should work',
|
|
56
|
-
function(fDone)
|
|
57
|
-
{
|
|
58
|
-
_Orator.webServer.get (
|
|
59
|
-
'/PI',
|
|
60
|
-
function (pRequest, pResponse, fNext)
|
|
61
|
-
{
|
|
62
|
-
pResponse.send('PO');
|
|
63
|
-
fNext();
|
|
64
|
-
}
|
|
65
|
-
);
|
|
66
|
-
_Orator.startWebServer();
|
|
67
|
-
libSuperTest('http://localhost:8083/')
|
|
68
|
-
.get('PI')
|
|
69
|
-
.end(
|
|
70
|
-
function (pError, pResponse)
|
|
71
|
-
{
|
|
72
|
-
if (pError)
|
|
73
|
-
{
|
|
74
|
-
console.log('Error on Inverted Results: '+JSON.stringify(pError));
|
|
75
|
-
Expect('No Trace Request Error').to.equal('Nothing');
|
|
76
|
-
}
|
|
77
|
-
else
|
|
78
|
-
{
|
|
79
|
-
Expect(pResponse.text)
|
|
80
|
-
.to.contain('PO');
|
|
81
|
-
}
|
|
82
|
-
fDone();
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
);
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for the Orator Server
|
|
3
|
-
*
|
|
4
|
-
* @license MIT
|
|
5
|
-
*
|
|
6
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
var Chai = require("chai");
|
|
10
|
-
var Expect = Chai.expect;
|
|
11
|
-
var Assert = Chai.assert;
|
|
12
|
-
|
|
13
|
-
var libSuperTest = require('supertest');
|
|
14
|
-
|
|
15
|
-
var _MockSettings = (
|
|
16
|
-
{
|
|
17
|
-
Product: 'MockOratorCHROME',
|
|
18
|
-
APIServerPort: 8081,
|
|
19
|
-
Profiling: (
|
|
20
|
-
{
|
|
21
|
-
// Tracelog is just log-based request timing encapsulation.
|
|
22
|
-
TraceLog: true,
|
|
23
|
-
|
|
24
|
-
// These profiling settings determine if we generate cpu or call graphs
|
|
25
|
-
Enabled: true,
|
|
26
|
-
Folder: '/tmp/',
|
|
27
|
-
// Currently supported profile types: CallGrinder or ChromeCPU
|
|
28
|
-
Type: 'ChromeCPU'
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
suite
|
|
34
|
-
(
|
|
35
|
-
'Orator',
|
|
36
|
-
function()
|
|
37
|
-
{
|
|
38
|
-
var _Orator;
|
|
39
|
-
|
|
40
|
-
setup
|
|
41
|
-
(
|
|
42
|
-
function()
|
|
43
|
-
{
|
|
44
|
-
_Orator = require('../source/Orator.js').new(_MockSettings);
|
|
45
|
-
}
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
suite
|
|
49
|
-
(
|
|
50
|
-
'Alternate (chromecpu) Server Start',
|
|
51
|
-
function()
|
|
52
|
-
{
|
|
53
|
-
test
|
|
54
|
-
(
|
|
55
|
-
'simple routes should work',
|
|
56
|
-
function(fDone)
|
|
57
|
-
{
|
|
58
|
-
_Orator.webServer.get (
|
|
59
|
-
'/PINGO',
|
|
60
|
-
function (pRequest, pResponse, fNext)
|
|
61
|
-
{
|
|
62
|
-
pResponse.send('PONGO');
|
|
63
|
-
fNext();
|
|
64
|
-
}
|
|
65
|
-
);
|
|
66
|
-
_Orator.startWebServer();
|
|
67
|
-
libSuperTest('http://localhost:8081/')
|
|
68
|
-
.get('PINGO')
|
|
69
|
-
.end(
|
|
70
|
-
function (pError, pResponse)
|
|
71
|
-
{
|
|
72
|
-
if (pError)
|
|
73
|
-
{
|
|
74
|
-
console.log('Error on Inverted Results: '+JSON.stringify(pError));
|
|
75
|
-
Expect('Chrome Trace Request Error').to.equal('Nothing');
|
|
76
|
-
}
|
|
77
|
-
else
|
|
78
|
-
{
|
|
79
|
-
Expect(pResponse.text)
|
|
80
|
-
.to.contain('PONGO');
|
|
81
|
-
}
|
|
82
|
-
fDone();
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
);
|