support for invoke tests, and improved cli debugger: kill the debugger when the activation finishes
diff --git a/client/lib/debug-nodejs.js b/client/lib/debug-nodejs.js
index 894895e..cc9ecd0 100644
--- a/client/lib/debug-nodejs.js
+++ b/client/lib/debug-nodejs.js
@@ -15,19 +15,20 @@
*/
var fs = require('fs'),
+ ok_ = require('./repl-messages').ok_,
tmp = require('tmp'),
open = require('open'),
path = require('path'),
spawn = require('child_process').spawn;
-exports.debug = function debugNodeJS(message, ws, echoChamberNames, done, commandLineOptions) {
+exports.debug = function debugNodeJS(message, ws, echoChamberNames, done, commandLineOptions, eventBus) {
try {
- exports._debug(message, ws, echoChamberNames, done, commandLineOptions);
+ exports._debug(message, ws, echoChamberNames, done, commandLineOptions, eventBus);
} catch (e) {
console.error(e);
}
};
-exports._debug = function debugNodeJS(message, ws, echoChamberNames, done, commandLineOptions) {
+exports._debug = function debugNodeJS(message, ws, echoChamberNames, done, commandLineOptions, eventBus) {
var code = message.action.exec.code;
var r = new RegExp(/main[\s]*\([^\)]*\)/);
@@ -123,7 +124,7 @@
}
if (!addrInUse) {
try { tmpfileCleanupCallback(); } catch (e) { }
- done();
+ ok_(done());
}
}
child.on('close', cleanUpSubprocesses);
@@ -139,14 +140,21 @@
var child = spawn('node',
['debug', tmpFilePath],
spawnOpts);
- child.on('exit', (message) => console.error('EXIT',message));
-
+ child.on('exit', (code) => {
+ if (code !== 0) {
+ console.error('The debugger exited abnormally with code ' + code);
+ }
+ });
+
+ eventBus.on('invocation-done', () => child.kill());
+
child.on('close', () => {
try { tmpfileCleanupCallback(); } catch (e) { }
- done();
+ done(); // we don't need to "ok" here, as the invoker will do that for us
});
} catch (e) {
console.error('Error spawning debugger', e);
+ console.error(e.stack);
done();
}
}
@@ -159,6 +167,7 @@
});
} catch (e) {
console.error(e);
+ console.error(e.stack);
}
});
};
diff --git a/client/lib/repl.js b/client/lib/repl.js
index 25b77f2..6824456 100644
--- a/client/lib/repl.js
+++ b/client/lib/repl.js
@@ -72,6 +72,7 @@
var invoke = {
handler: rewriter.invoke,
description: 'Invoke an action',
+ needsEventBus: true,
synchronous: true
};
var list = {
@@ -124,7 +125,7 @@
'?': help
};
-function repl(wskprops) {
+function repl(wskprops, eventBus) {
prompt.prompt([{
name: 'command', message: '(wskdb)',
prefixMessage: '', // override the default question mark prefix
@@ -135,7 +136,7 @@
}]).then(function(response) {
if (response.command.length === 0) {
// user hit return;
- return repl(wskprops);
+ return repl(wskprops, eventBus);
}
var commandLine = response.command.split(/\s+/);
@@ -156,13 +157,17 @@
if (handler.synchronous) {
// the second parameter is the call back to the repl
// when done with the synchronous operation
- commandLine.unshift(repl.bind(undefined, wskprops));
+ commandLine.unshift(repl.bind(undefined, wskprops, eventBus));
}
if (handler.options) {
commandLine.unshift(options);
}
+ if (handler.needsEventBus) {
+ commandLine.unshift(eventBus);
+ }
+
// the first parameter is wskprops
commandLine.unshift(wskprops);
@@ -175,7 +180,7 @@
if (!handler.synchronous) {
// if async, then restart the repl right away
- repl(wskprops);
+ repl(wskprops, eventBus);
}
});
}
diff --git a/client/lib/rewriter.js b/client/lib/rewriter.js
index b471c35..f8c2649 100644
--- a/client/lib/rewriter.js
+++ b/client/lib/rewriter.js
@@ -302,6 +302,12 @@
*/
exports.attach = function attach(wskprops, options, next, entity) {
if (options.help) {
+ // the user passed -h or --help, so there is nothing to do here
+ return next();
+ }
+ if (!entity) {
+ console.error('Error: Please specify an entity ');
+ console.error();
return next();
}
@@ -317,7 +323,7 @@
//
// user asked not to instrument any rules or sequences
//
- return next();
+ return ok_(next);
}
doPar(ow, 'action', entity, next, (otherEntityWithDetails, countDown) => {
if (SequenceRewriter.rewriteNeeded(otherEntityWithDetails, entity, entityNamespace)) {
@@ -461,6 +467,7 @@
exports._invoke = function invoke() {
var args = Array.prototype.slice.call(arguments);
var wskprops = args.shift();
+ var eventBus = args.shift();
var namespace = wskprops.NAMESPACE;
var next = args.shift();
var action = args.shift();
@@ -534,7 +541,8 @@
clearInterval(timer);
owForActivations.activations.get({ activation: activation.activationId }).then(function(activation) {
console.log(JSON.stringify(activation, undefined, 4));
- next();
+ eventBus.emit('invocation-done', activation);
+ ok_(next);
});
break;
}
diff --git a/client/test/helpers/driver.js b/client/test/helpers/driver.js
index 19035a0..c40e397 100644
--- a/client/test/helpers/driver.js
+++ b/client/test/helpers/driver.js
@@ -1,57 +1,60 @@
'use strict'
-var test = require('ava').test;
+const test = require('ava').test;
const uuid = require('uuid');
const spawn = require('child_process').spawn;
function Driver() {
}
-Driver.prototype.it = function it(shouldDoThisSuccessfully, stepFn, rootPath) {
+Driver.prototype.it = function it(shouldDoThisSuccessfully, stepFn, args, rootPath) {
test(shouldDoThisSuccessfully, t => {
return new Promise((resolve,reject) => {
- const child = spawn('node', ['wskdb.js'], { cwd: rootPath || '../..' });
+ const child = spawn('node', ['wskdb.js'].concat(args || []), { cwd: rootPath || '../..' });
- var name = uuid.v4();
- var steps = stepFn(name);
+ const name = uuid.v4();
+ const steps = stepFn(name);
- var stepNumber = 0;
- var goody = false;
+ var stepNumber = 0;
+ var goody = false;
- function doStep() {
- child.stdin.write(steps[stepNumber++] + '\n');
- }
- doStep(); // do the first step
+ function doStep() {
+ // console.log("STEP " + steps[stepNumber]);
+ child.stdout.pause();
+ child.stdin.write(steps[stepNumber++] + '\n');
+ child.stdout.resume();
+ }
+ doStep(); // do the first step
- child.stderr.on('data', (data) => {
- console.error('stderr: ' + data);
- });
+ child.stderr.on('data', (data) => {
+ console.error('stderr: ' + data);
+ });
- child.stdout.on('data', (data) => {
- //console.log('stdout: ' + data)
- if (data.indexOf('Error') >= 0) {
- goody = false;
- reject('Step ' + (stepNumber - 1) + ' failed');
+ child.stdout.on('data', (data) => {
+ //console.log('stdout: ' + data + " ||| " + data.indexOf('(wskdb)'))
+ if (data.indexOf('Error') >= 0) {
+ goody = false;
+ reject('Step ' + (stepNumber - 1) + ' failed');
- } else if (data.indexOf('ok') >= 0) {
- goody = true;
+ } else if (data.indexOf('ok') == 0 || data.indexOf('break in') >= 0) {
+ goody = true;
- if (stepNumber === steps.length) {
- child.stdin.write('quit\n');
- child.stdin.end();
- } else {
- doStep();
- }
- }
- });
- child.on('exit', (code) => {
- if (code === 0 && goody) {
- resolve();
+ if (stepNumber === steps.length) {
+ child.stdin.write('quit\n');
+ child.stdin.end();
} else {
- reject('code=${code} goody=${goody}');
+ doStep();
}
- });
- }).then(result => t.is(result));
- });
+ }
+ });
+ child.on('exit', (code) => {
+ if (code === 0 && goody) {
+ resolve();
+ } else {
+ reject('code=${code} goody=${goody}');
+ }
+ });
+ }).then(result => t.is(result));
+ });
} /* the end of it! */
module.exports = new Driver().it;
diff --git a/client/test/rewriter/createAttachDetachDelete.js b/client/test/rewriter/createAttachDetachDelete.js
index 8e0218c..c03ccfe 100644
--- a/client/test/rewriter/createAttachDetachDelete.js
+++ b/client/test/rewriter/createAttachDetachDelete.js
@@ -1,6 +1,6 @@
import it from '../helpers/driver'
-it('should create an attach, then attach, detach, delete, and finally quit without error', (name) => [
+it('should create an action, then attach, detach, delete, and finally quit without error', (name) => [
`create ${name} nodejs function main(params) { return { message: "Hello " + params.name } }`,
`attach ${name}`,
`detach ${name}`,
diff --git a/client/test/rewriter/createAttachInvokeDetachDelete.js b/client/test/rewriter/createAttachInvokeDetachDelete.js
new file mode 100644
index 0000000..c62e6e0
--- /dev/null
+++ b/client/test/rewriter/createAttachInvokeDetachDelete.js
@@ -0,0 +1,12 @@
+import it from '../helpers/driver'
+
+it('should create an action, then attach, invoke, detach, delete, and finally quit without error', (name) => [
+ `create ${name} nodejs function main(params) { return { message: "Hello " + params.name } }`,
+ `attach ${name} -a`,
+ `invoke ${name}`,
+ `c`,
+ `c`,
+ `quit`, // quit the debugger
+ `detach ${name}`,
+ `delete ${name}`
+], ['-c']); // use the cli debugger
diff --git a/client/wskdb.js b/client/wskdb.js
index 7e1853c..685339a 100644
--- a/client/wskdb.js
+++ b/client/wskdb.js
@@ -17,6 +17,8 @@
var argv = require('argv'),
repl = require('./lib/repl').repl,
colors = require('colors'),
+ events = require('events'),
+ eventBus = new events.EventEmitter(),
WebSocket = require('ws'),
debugNodeJS = require('./lib/debug-nodejs').debug,
expandHomeDir = require('expand-home-dir'),
@@ -82,7 +84,7 @@
});
- repl(wskprops);
+ repl(wskprops, eventBus);
});
ws.on('close', function() {
@@ -125,7 +127,7 @@
if (message.onDone_trigger) {
if (message.action && message.action.exec && message.action.exec.kind.indexOf('nodejs') >= 0) {
- debugNodeJS(message, ws, { trigger: message.onDone_trigger }, done, commandLineOptions);
+ debugNodeJS(message, ws, { trigger: message.onDone_trigger }, done, commandLineOptions, eventBus);
} else {
console.error('Unable to complete invocation: no action code to debug');
circuitBreaker();