Skip to content

Commit

Permalink
test install script added
Browse files Browse the repository at this point in the history
  • Loading branch information
asaccool committed Jul 18, 2019
1 parent deb656c commit 6b82d79
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 1 deletion.
28 changes: 28 additions & 0 deletions psknode/tests/basic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const path = require('path');

const tir = require(path.resolve(path.join(__dirname, "util/tir.js")));
const assert = require('double-check').assert;

const domain = 'local';
const agent = 'exampleAgent';
const agents = [agent];

const swarm = {
echo: {
say: function(input) {
this.return('Echo ' + input);
}
}
};

assert.callback('Basic Test', (finished) => {
tir.addDomain(domain, agents, swarm);

tir.launch(3000, () => {
tir.interact(domain, agent).startSwarm("echo", "say", "Hello").onReturn(result => {
assert.equal("Echo Hello", result);
finished();
tir.tearDown(0);
});
});
}, 2000);
271 changes: 271 additions & 0 deletions psknode/tests/util/tir.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
/**
* Test Integration Runner
*
* This API abstracts the setup, initialization and
* the internal butchery for PSKY.
*
*/

const path = require('path');

const __dName = __dirname;
require(path.resolve(path.join(__dName, "../../bundles/pskruntime.js")));
require(path.resolve(path.join(__dName, "../../bundles/psknode.js")));
require(path.resolve(path.join(__dName, "../../bundles/consoleTools.js")));

const os = require('os');
const fs = require('fs');
const interact = require('interact');

const child_process = require('child_process');
const pskdb = require('pskdb');

const createKey = function(name) {
let parsed = '' + name;
parsed.replace(/^[A-Za-z0-9 ]+/g, ' ');
return parsed
.split(' ')
.map((word, idx) =>
idx === 0
? word.toLocaleLowerCase()
: word.substr(0, 1).toLocaleUpperCase() + word.toLowerCase().substr(1)
)
.join('');
};

const rmDeep = folder => {
if (fs.existsSync(folder)) {
fs.readdirSync(folder).forEach(file => {
const curPath = path.join(folder, file);
if (fs.lstatSync(curPath).isDirectory()) {
rmDeep(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(folder);
}
};

const createConstitution = (prefix, describer, options) => {
let opts = Object.assign(
{
nl: '\n',
semi: ';',
tab: ' '
},
options
);

const file = path.join(prefix, 'constitution.js');
const contents = Object.keys(describer)
.reduce((c, name) => {
let line = "$$.swarms.describe('" + name + "', {";
line += Object.keys(describer[name])
.reduce((f, prop) => {
if (typeof describer[name][prop] === 'object') {
f.push(opts.nl + opts.tab + prop + ': ' + JSON.stringify(describer[name][prop]));
} else {
f.push(opts.nl + opts.tab + prop + ': ' + describer[name][prop].toString());
}
return f;
}, [])
.join(',');
line += opts.nl + '})' + opts.semi;
c.push(line);
return c;
}, [])
.join(opts.nl);
fs.writeFileSync(file, contents);
return file;
};

const Tir = function() {
const domainConfigs = {};
const rootFolder = fs.mkdtempSync(path.join(os.tmpdir(), 'psk_'));

let testerNode = null;

/**
* Adds a domain to the configuration, in a fluent way.
* Does not launch anything, just stores the configuration.
*
* @param string domain The name of the domain
* @param array agents The agents to be inserted
* @param object|string constitution The swarm describer, either as an object or as a string file path
* @returns this
*/
this.addDomain = (domain, agents, constitution) => {
let workspace = path.join(rootFolder, 'nodes', createKey(domain));
let domainConfig = {
name: domain,
agents,
constitution,
workspace: workspace,
conf: path.join(workspace, 'conf'),
inbound: path.join(workspace, 'inbound'),
outbound: path.join(workspace, 'outbound')
};
domainConfigs[domain] = domainConfig;
return this;
};

this.createConstitution = createConstitution;

/**
* Launches all the configured domains.
*
* @param integer tearDownAfter The number of miliseconds the TIR will tear down, even if the test fails. If missing, you must call tearDown
* @param function callable The callback
*/
this.launch = (tearDownAfter, callable) => {
if (callable === undefined && tearDownAfter.call) {
callable = tearDownAfter;
tearDownAfter = null;
}

if (testerNode !== null) {
throw new Error('Test node already launched!');
return;
}
console.info('[TIR] setting working folder root', rootFolder);

const confFolder = path.join(rootFolder, 'conf');

console.info('[TIR] pskdb on', confFolder);
pskdb.startDB(confFolder);

fs.mkdirSync(path.join(rootFolder, 'nodes'));

console.info('[TIR] start building nodes...');
Object.keys(domainConfigs).forEach(name => {
const domainConfig = domainConfigs[name];
this.buildDomainConfiguration(domainConfig);
});

testerNode = child_process.spawn(
'node',
[path.resolve(path.join(__dName, "../../core/launcher.js")), confFolder, rootFolder],
{ stdio: 'inherit' }
);

setTimeout(() => {
if (tearDownAfter !== null) {
setTimeout(() => this.tearDown(1), tearDownAfter);
}
callable();
}, 10);
};

/**
* Builds the config for a node.
*
* @param object domainConfig The domain configuration stored by addDomain
*/
this.buildDomainConfiguration = domainConfig => {
console.info('[TIR] domain ' + domainConfig.name + ' in workspace', domainConfig.workspace);
console.info('[TIR] domain ' + domainConfig.name + ' inbound', domainConfig.inbound);

fs.mkdirSync(domainConfig.workspace);

let constitutionFile = domainConfig.constitution;
if (typeof domainConfig.constitution !== 'string') {
constitutionFile = createConstitution(domainConfig.workspace, domainConfig.constitution);
}

let transaction = $$.blockchain.beginTransaction({});
let domain = transaction.lookup('DomainReference', domainConfig.name);
domain.init('system', domainConfig.name);
domain.setWorkspace(domainConfig.workspace);
domain.setConstitution(constitutionFile);
domain.addLocalInterface('local', domainConfig.inbound);
console.log('>>DOMAIN<<', domainConfig.name, domain.localInterfaces);
try {
transaction.add(domain);
$$.blockchain.commit(transaction);
} catch (err) {
console.log('Got an error', err);
}

if (
domainConfig.agents &&
Array.isArray(domainConfig.agents) &&
domainConfig.agents.length > 0
) {
let domainBlockChain = pskdb.createDBHandler(domainConfig.conf);
console.info('[TIR] domain ' + domainConfig.name + ' starting agents...');

domainConfig.agents.forEach(agentName => {
console.info('[TIR] domain ' + domainConfig.name + ' agent', agentName);
let trans = domainBlockChain.beginTransaction({});
let agent = trans.lookup('Agent', agentName);
trans.add(agent);
domainBlockChain.commit(trans);
});
}
};
this.getDomainConfig = domainName => {
return domainConfigs[domainName];
};
/**
* Interacts with an agent of a domain.
*
* @param string domain The name of the domain
* @param string agent The name of the agent
* @returns swarm
*/
this.interact = (domain, agent) => {
const domainConfig = domainConfigs[domain];
if (domainConfig === undefined) {
throw new Error(
'Could not find domain ' + domain + ' in ' + Object.keys(domainConfigs).join(', ')
);
} else {
var returnChannel = path.join(
domainConfig.outbound,
Math.random()
.toString(36)
.substr(2, 9)
);
try {
fs.mkdirSync(domainConfig.outbound);
} catch (err) {
//dir allready exists
}
console.info(
'[TIR] Interacting with ' + domainConfig.name + '/' + agent + ' on',
returnChannel
);
return interact.createNodeInteractionSpace(agent, domainConfig.inbound, returnChannel);
}
};

/**
* Tears down all the nodes
*
* @param exitStatus The exit status, to exit the process.
*/
this.tearDown = exitStatus => {
console.info('[TIR] Tearing down...');
if (testerNode) {
console.info('[TIR] Killing node', testerNode.pid);
process.kill(testerNode.pid);
testerNode = null;
}
setTimeout(() => {
try {
console.info('[TIR] Removing temporary folder', rootFolder);
rmDeep(rootFolder);
console.info('[TIR] Temporary folder removed', rootFolder);
} catch (e) {
//just avoid to display error on console
}

if (exitStatus !== undefined) {
process.exit(exitStatus);
}
}, 100);
};
};

module.exports = new Tir();
3 changes: 2 additions & 1 deletion tests/installTest.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
//run to test that the installation is working
const path = require('path');

require(path.resolve(path.join(__dirname, "../psknode/tests/basic.js")));

0 comments on commit 6b82d79

Please sign in to comment.