Comparar commits
14 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 4da87b5806 | |||
| f73d9d6958 | |||
| fd96d41698 | |||
| 7ccf8dafc4 | |||
| 2ea4f71a1a | |||
| e702f5cef0 | |||
| 24d8a02fff | |||
| 1917f71856 | |||
| 81e1622621 | |||
| 2e9e5e7889 | |||
| 017223945f | |||
| 735cbd4e73 | |||
| eef307476d | |||
| ae37e17cae |
+11
-3
@@ -1,8 +1,8 @@
|
||||
[](https://img.shields.io/badge/state-beta-yellow.svg)
|
||||
[](./LICENSE)
|
||||
[](https://travis-ci.org/dfst/deepforge)
|
||||
[](https://gitter.im/dfst/deepforge?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://waffle.io/dfst/deepforge)
|
||||
[](https://travis-ci.org/deepforge-dev/deepforge)
|
||||
[](https://gitter.im/deepforge-dev/deepforge?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://waffle.io/deepforge-dev/deepforge)
|
||||
|
||||
**Notice**: DeepForge is still a work in progress and in beta! That being said, any contributions and/or feedback is greatly appreciated. If you have any questions, check out the [wiki](https://github.com/dfst/deepforge/wiki/) or drop me a line on the gitter!
|
||||
|
||||
@@ -40,6 +40,14 @@ Finally, start deepforge with `deepforge start`and navigate to [http://localhost
|
||||
|
||||
Also, be sure to check out the other available features of the `deepforge` cli; it can be used to update, manage your torch installation, uninstall deepforge and run individual components!
|
||||
|
||||
## Additional Resources
|
||||
- [Intro to DeepForge Slides](https://docs.google.com/presentation/d/10_y5O3gHXSATfjHVLJg7dOdrz-tAXNWjlxhJ5SlA0ic/edit?usp=sharing)
|
||||
- [wiki](https://github.com/deepforge-dev/deepforge/wiki) containing overview, installation, configuration and developer information
|
||||
- [Starter Kit](https://github.com/deepforge-dev/examples/tree/master/starterkit) containing example pipelines demonstrating various deepforge features
|
||||
- [Examples](https://github.com/deepforge-dev/examples)
|
||||
|
||||
- [Datamodel Developer Slides](https://docs.google.com/presentation/d/1hd3IyUlzW_TIPnzCnE-1pdz00Pw8WaIxYiOW_Hyog-M/edit#slide=id.p)
|
||||
|
||||
## Interested in contributing?
|
||||
Contributions are welcome! Either fork the project and submit some PR's or shoot me an email about getting more involved!
|
||||
|
||||
|
||||
+3
-14
@@ -6,8 +6,7 @@ var path = require('path'),
|
||||
spawn = childProcess.spawn,
|
||||
rm_rf = require('rimraf'),
|
||||
projectConfig = require(__dirname + '/../config'),
|
||||
executorSrc = path.join(__dirname, '..', 'node_modules', 'webgme', 'src',
|
||||
'server', 'middleware', 'executor', 'worker'),
|
||||
executorSrc = path.join(__dirname, '..', 'node_modules', '.bin', 'webgme-executor-worker'),
|
||||
id = Date.now(),
|
||||
workerRootPath = process.env.DEEPFORGE_WORKER_DIR || path.join(__dirname, '..', 'src', 'worker'),
|
||||
workerPath = path.join(workerRootPath, `worker_${id}`),
|
||||
@@ -60,7 +59,7 @@ var startExecutor = function() {
|
||||
|
||||
// Start the executor
|
||||
var execJob = spawn('node', [
|
||||
'node_worker.js',
|
||||
executorSrc,
|
||||
workerConfigPath,
|
||||
workerTmp
|
||||
]);
|
||||
@@ -80,14 +79,4 @@ var createConfigJson = function() {
|
||||
fs.writeFile(workerConfigPath, JSON.stringify(config), startExecutor);
|
||||
};
|
||||
|
||||
process.chdir(executorSrc);
|
||||
|
||||
fs.mkdir(workerTmp, function() {
|
||||
// npm install in this directory
|
||||
var npmInstall = spawn('npm', ['install']);
|
||||
npmInstall.stdout.pipe(process.stdout);
|
||||
npmInstall.stderr.pipe(process.stderr);
|
||||
npmInstall.on('close', function() {
|
||||
createConfigJson();
|
||||
});
|
||||
});
|
||||
fs.mkdir(workerTmp, createConfigJson);
|
||||
|
||||
+5
-4
@@ -8,18 +8,18 @@
|
||||
"start-dev": "NODE_ENV=dev node app.js",
|
||||
"local": "node ./bin/start-local.js",
|
||||
"worker": "node ./bin/start-worker.js",
|
||||
"test": "mkdir ./test-tmp; node ./node_modules/mocha/bin/mocha --recursive test",
|
||||
"watch-test": "./node_modules/nodemon/bin/nodemon.js --exec 'node ./node_modules/mocha/bin/mocha --recursive test'",
|
||||
"test": "mkdir ./test-tmp; mocha --recursive test",
|
||||
"watch-test": "nodemon --exec 'mocha --recursive test'",
|
||||
"build-nn": "node ./utils/nn-parser.js"
|
||||
},
|
||||
"version": "0.21.0",
|
||||
"version": "0.22.0",
|
||||
"dependencies": {
|
||||
"commander": "^2.9.0",
|
||||
"dotenv": "^2.0.0",
|
||||
"exists-file": "^2.1.0",
|
||||
"express": "^4.14.0",
|
||||
"lodash.difference": "^4.1.2",
|
||||
"graceful-fs": "^4.1.10",
|
||||
"lodash.difference": "^4.1.2",
|
||||
"lodash.merge": "^4.5.1",
|
||||
"mongodb": "^2.2.10",
|
||||
"nodemon": "^1.9.2",
|
||||
@@ -30,6 +30,7 @@
|
||||
"webgme-breadcrumbheader": "^2.1.1",
|
||||
"webgme-chflayout": "^2.0.0",
|
||||
"webgme-easydag": "dfst/webgme-easydag",
|
||||
"webgme-executor-worker": "^1.0.1",
|
||||
"webgme-fab": "dfst/webgme-fab",
|
||||
"webgme-simple-nodes": "^2.1.0"
|
||||
},
|
||||
|
||||
@@ -83,7 +83,9 @@ define([
|
||||
exists = {},
|
||||
i = 2;
|
||||
|
||||
children.forEach(child => exists[child.getAttribute('name')] = true);
|
||||
children
|
||||
.filter(child => child !== null)
|
||||
.forEach(child => exists[child.getAttribute('name')] = true);
|
||||
|
||||
while (exists[name]) {
|
||||
name = basename + '_' + i;
|
||||
|
||||
@@ -73,17 +73,17 @@ define([
|
||||
|
||||
classNodes = metanodes.filter(node => {
|
||||
var base = this.core.getBase(node),
|
||||
baseId = this.core.getPath(base),
|
||||
baseId,
|
||||
count = 1;
|
||||
|
||||
// Count the sets back to a class node
|
||||
while (base) {
|
||||
baseId = this.core.getPath(base);
|
||||
if (isClass[baseId]) {
|
||||
inheritanceLvl[this.core.getPath(node)] = count;
|
||||
return true;
|
||||
}
|
||||
base = this.core.getBase(base);
|
||||
baseId = this.core.getPath(base);
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ define([
|
||||
};
|
||||
|
||||
ExecuteJob.prototype.createAttributeFile = function (node, files) {
|
||||
var skip = ['code', 'stdout', 'execFiles', 'jobId', 'secret'],
|
||||
var skip = ['code', 'stdout', 'execFiles', 'jobId', 'secret', CONSTANTS.LINE_OFFSET],
|
||||
numOrBool = /^(-?\d+\.?\d*((e|e-)\d+)?|(true|false))$/,
|
||||
table;
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ requirejs([
|
||||
var checkFinished = () => {
|
||||
if (exitCode !== null && remainingImageCount === 0) {
|
||||
log('finished!');
|
||||
process.exit(exitCode);
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -201,14 +201,45 @@ requirejs([
|
||||
|
||||
// Download the large files
|
||||
var inputData = JSON.parse(fs.readFileSync('./input-data.json')),
|
||||
inputPaths = Object.keys(inputData);
|
||||
inputPaths = Object.keys(inputData),
|
||||
pid,
|
||||
job,
|
||||
cleanup;
|
||||
|
||||
// Make sure to kill the spawned process group on exit
|
||||
cleanup = function() {
|
||||
if (job) {
|
||||
pid = job.pid;
|
||||
job = null;
|
||||
log(`killing process group: ${pid}`);
|
||||
process.kill(-pid, 'SIGTERM');
|
||||
if (exitCode !== null) {
|
||||
log(`exiting w/ code ${exitCode}`);
|
||||
process.exit(exitCode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
process.on('exit', () => {
|
||||
log('received "exit" event')
|
||||
cleanup();
|
||||
});
|
||||
process.on('SIGINT', function() {
|
||||
log('received "SIGINT" event')
|
||||
cleanup();
|
||||
process.exit(130);
|
||||
});
|
||||
process.on('uncaughtException', () => {
|
||||
log('received "uncaughtException" event')
|
||||
cleanup();
|
||||
});
|
||||
|
||||
// Request the data from the blob
|
||||
prepareCache()
|
||||
.then(() => Q.all(inputPaths.map(ipath => getData(ipath, inputData[ipath]))))
|
||||
.then(() => {
|
||||
// Run 'th init.lua' and merge the stdout, stderr
|
||||
var job = spawn('th', ['init.lua']);
|
||||
job = spawn('th', ['init.lua'], {detached: true});
|
||||
job.stdout.on('data', onStdout);
|
||||
job.stderr.on('data', onStderr);
|
||||
job.on('close', code => {
|
||||
|
||||
@@ -49,6 +49,11 @@ define([
|
||||
this.LayerDict = createLayerDict(this.core, this.META);
|
||||
this.uniqueId = 2;
|
||||
this.varnames = {net: true};
|
||||
this.definitions = [
|
||||
'require \'nn\'',
|
||||
'require \'rnn\''
|
||||
];
|
||||
|
||||
return PluginBase.prototype.main.apply(this, arguments);
|
||||
};
|
||||
|
||||
@@ -71,11 +76,6 @@ define([
|
||||
result = {},
|
||||
code = '';
|
||||
|
||||
this.definitions = [
|
||||
'require \'nn\'',
|
||||
'require \'rnn\''
|
||||
];
|
||||
|
||||
// Add an index to each layer
|
||||
layers.forEach((l, index) => l[INDEX] = index);
|
||||
|
||||
|
||||
@@ -460,7 +460,7 @@ define([
|
||||
|
||||
classNodes = metanodes.filter(node => {
|
||||
var base = this.core.getBase(node),
|
||||
baseId = this.core.getPath(base),
|
||||
baseId,
|
||||
deps = [],
|
||||
name,
|
||||
count = 1;
|
||||
@@ -468,6 +468,7 @@ define([
|
||||
// Count the sets back to a class node
|
||||
while (base) {
|
||||
deps.push(this.core.getAttribute(base, 'name'));
|
||||
baseId = this.core.getPath(base);
|
||||
if (isClass[baseId]) {
|
||||
inheritanceLvl[this.core.getPath(node)] = count;
|
||||
name = this.core.getAttribute(node, 'name');
|
||||
@@ -475,7 +476,6 @@ define([
|
||||
return true;
|
||||
}
|
||||
base = this.core.getBase(base);
|
||||
baseId = this.core.getPath(base);
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/*globals define*/
|
||||
/*jshint node:true, browser:true*/
|
||||
|
||||
define([
|
||||
'plugin/GenerateArchitecture/GenerateArchitecture/GenerateArchitecture',
|
||||
'SimpleNodes/Constants',
|
||||
'text!./metadata.json',
|
||||
'q',
|
||||
'fs',
|
||||
'path',
|
||||
'child_process',
|
||||
'rimraf'
|
||||
], function (
|
||||
PluginBase,
|
||||
SimpleNodeConstants,
|
||||
pluginMetadata,
|
||||
Q,
|
||||
fs,
|
||||
path,
|
||||
childProcess,
|
||||
rm_rf
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
pluginMetadata = JSON.parse(pluginMetadata);
|
||||
|
||||
/**
|
||||
* Initializes a new instance of ValidateArchitecture.
|
||||
* @class
|
||||
* @augments {PluginBase}
|
||||
* @classdesc This class represents the plugin ValidateArchitecture.
|
||||
* @constructor
|
||||
*/
|
||||
var TMP_DIR = '/tmp',
|
||||
spawn = childProcess.spawn,
|
||||
GET_ARG_INDEX = /argument #([0-9]+) to/,
|
||||
TORCH_INSTALLED = true;
|
||||
|
||||
var ValidateArchitecture = function () {
|
||||
// Call base class' constructor.
|
||||
PluginBase.call(this);
|
||||
this.pluginMetadata = pluginMetadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* Metadata associated with the plugin. Contains id, name, version, description, icon, configStructue etc.
|
||||
* This is also available at the instance at this.pluginMetadata.
|
||||
* @type {object}
|
||||
*/
|
||||
ValidateArchitecture.metadata = pluginMetadata;
|
||||
|
||||
// Prototypical inheritance from PluginBase.
|
||||
ValidateArchitecture.prototype = Object.create(PluginBase.prototype);
|
||||
ValidateArchitecture.prototype.constructor = ValidateArchitecture;
|
||||
|
||||
ValidateArchitecture.prototype.main = function (callback) {
|
||||
var name = this.core.getAttribute(this.activeNode, 'name');
|
||||
|
||||
this._callback = callback;
|
||||
// make the tmp dir
|
||||
this._tmpFileId = path.join(TMP_DIR, `${name}_${Date.now()}`);
|
||||
fs.mkdir(this._tmpFileId, err => {
|
||||
if (err) throw err;
|
||||
return PluginBase.prototype.main.call(this, callback);
|
||||
});
|
||||
};
|
||||
|
||||
ValidateArchitecture.prototype.createOutputFiles = function (tree) {
|
||||
var layers = tree[SimpleNodeConstants.CHILDREN],
|
||||
tests = [],
|
||||
id;
|
||||
|
||||
if (!TORCH_INSTALLED) {
|
||||
return this.validationFinished();
|
||||
}
|
||||
|
||||
// Generate code for each layer
|
||||
this.layerName = {};
|
||||
for (var i = layers.length; i--;) {
|
||||
id = layers[i][SimpleNodeConstants.NODE_PATH];
|
||||
this.layerName[id] = layers[i].name;
|
||||
tests.push([id, this.createLayerTestCode(layers[i])]);
|
||||
}
|
||||
|
||||
// Run each code snippet
|
||||
this.validateLayers(tests)
|
||||
.then(errors => this.validationFinished(errors))
|
||||
.fail(err => this.logger.error(`validation failed: ${err}`));
|
||||
};
|
||||
|
||||
ValidateArchitecture.prototype.validationFinished = function (errors) {
|
||||
if (!TORCH_INSTALLED) {
|
||||
this.logger.warn('Torch is not installed. Architecture validation is not supported.');
|
||||
} else {
|
||||
this.logger.info(`found ${errors.length} validation errors`);
|
||||
}
|
||||
|
||||
this.createMessage(null, {
|
||||
errors: TORCH_INSTALLED ? errors : null
|
||||
});
|
||||
this.result.setSuccess(true);
|
||||
this._callback(null, this.result);
|
||||
};
|
||||
|
||||
ValidateArchitecture.prototype.createLayerTestCode = function (layer) {
|
||||
var customLayerDefs = this.genLayerDefinitions([layer]);
|
||||
|
||||
return this.definitions.concat([
|
||||
customLayerDefs,
|
||||
this.createLayer(layer)
|
||||
]).join('\n');
|
||||
};
|
||||
|
||||
ValidateArchitecture.prototype.validateLayers = function (layerTests) {
|
||||
return Q.all(layerTests.map(layer => this.validateLayer(layer[0], layer[1])))
|
||||
.then(results => Q.nfcall(rm_rf, this._tmpFileId)
|
||||
.then(() => results.filter(result => !!result))
|
||||
);
|
||||
};
|
||||
|
||||
ValidateArchitecture.prototype.validateLayer = function (id, code) {
|
||||
var deferred = Q.defer(),
|
||||
tmpPath = path.join(this._tmpFileId, id.replace(/[^a-zA-Z\d]+/g, '_'));
|
||||
|
||||
if (!TORCH_INSTALLED) {
|
||||
deferred.resolve(null);
|
||||
} else {
|
||||
// Write to a temp file
|
||||
fs.writeFile(tmpPath, code, err => {
|
||||
var job,
|
||||
stderr = '',
|
||||
stdout = '';
|
||||
|
||||
if (err) {
|
||||
return deferred.reject(`Could not create tmp file at ${tmpPath}: ${err}`);
|
||||
}
|
||||
// Run the file
|
||||
job = spawn('th', [tmpPath]);
|
||||
job.stderr.on('data', data => stderr += data.toString());
|
||||
job.stdout.on('data', data => stdout += data.toString());
|
||||
job.on('error', err => {
|
||||
if (err.code === 'ENOENT') {
|
||||
TORCH_INSTALLED = false;
|
||||
}
|
||||
});
|
||||
job.on('close', code => {
|
||||
if (code === 0) {
|
||||
deferred.resolve(null);
|
||||
} else {
|
||||
// If it errored, clean the error and return it
|
||||
deferred.resolve(this.parseError(id, stderr));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
ValidateArchitecture.prototype.parseError = function (id, stderr) {
|
||||
var msg = stderr
|
||||
.split('\n').shift() // first line
|
||||
.replace(/^[^:]*: /, '') // remove the file path
|
||||
.replace(/ at [^ ]*\)/, ')') // remove last line number
|
||||
.replace(/ to '\?'/, ''); // remove unknown symbol
|
||||
|
||||
// convert 'bad argument #[num]' to the argument name
|
||||
if (msg.indexOf('bad argument') === 0) {
|
||||
var layerName = this.layerName[id],
|
||||
args = this.LayerDict[layerName].args,
|
||||
argIndex = +(stderr.match(GET_ARG_INDEX)[1]),
|
||||
argName = args[argIndex-1].name;
|
||||
|
||||
// FIXME: This is not the correct index...
|
||||
// This is the index for the incorrect argument passed to the
|
||||
// tensor...
|
||||
msg = msg.replace(`#${argIndex}`, `"${argName}"`);
|
||||
}
|
||||
|
||||
return {
|
||||
id: id,
|
||||
msg: msg
|
||||
};
|
||||
};
|
||||
|
||||
ValidateArchitecture.prototype._saveOutput = function () {};
|
||||
|
||||
// for testing
|
||||
ValidateArchitecture.prototype.setTorchInstalled = function (value) {
|
||||
TORCH_INSTALLED = !!value;
|
||||
};
|
||||
|
||||
return ValidateArchitecture;
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "ValidateArchitecture",
|
||||
"name": "ValidateArchitecture",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
"class": "glyphicon glyphicon-cog",
|
||||
"src": ""
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
"disableBrowserSideExecution": true,
|
||||
"writeAccessRequired": false,
|
||||
"configStructure": []
|
||||
}
|
||||
Arquivo binário não exibido.
@@ -7,14 +7,16 @@ define([
|
||||
'deepforge/viz/panels/ThumbnailControl',
|
||||
'js/NodePropertyNames',
|
||||
'js/Utils/ComponentSettings',
|
||||
'underscore'
|
||||
'underscore',
|
||||
'q'
|
||||
], function (
|
||||
Constants,
|
||||
DeepForge,
|
||||
ThumbnailControl,
|
||||
nodePropertyNames,
|
||||
ComponentSettings,
|
||||
_
|
||||
_,
|
||||
Q
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
@@ -36,6 +38,7 @@ define([
|
||||
ThumbnailControl.call(this, options);
|
||||
this._config = DEFAULT_CONFIG;
|
||||
ComponentSettings.resolveWithWebGMEGlobal(this._config, this.getComponentId());
|
||||
this.validateLayers = _.debounce(() => this.validateArchitecture(), 500);
|
||||
};
|
||||
|
||||
_.extend(ArchEditorControl.prototype, ThumbnailControl.prototype);
|
||||
@@ -248,5 +251,28 @@ define([
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
ArchEditorControl.prototype._eventCallback = function() {
|
||||
ThumbnailControl.prototype._eventCallback.apply(this, arguments);
|
||||
this.validateLayers();
|
||||
};
|
||||
|
||||
ArchEditorControl.prototype.validateArchitecture = function() {
|
||||
var pluginId = 'ValidateArchitecture',
|
||||
context = this._client.getCurrentPluginContext(pluginId);
|
||||
|
||||
this._logger.info('about to validate arch');
|
||||
// Run the plugin in the browser (set namespace)
|
||||
context.managerConfig.namespace = 'nn';
|
||||
context.pluginConfig = {};
|
||||
Q.ninvoke(this._client, 'runServerPlugin', pluginId, context)
|
||||
.then(res => {
|
||||
var results = res.messages[0].message;
|
||||
if (results.errors !== null) {
|
||||
this._widget.displayErrors(results.errors);
|
||||
}
|
||||
})
|
||||
.fail(err => this._logger.warn(`Validation failed: ${err}`));
|
||||
};
|
||||
|
||||
return ArchEditorControl;
|
||||
});
|
||||
|
||||
@@ -42,6 +42,7 @@ define([
|
||||
}
|
||||
ThumbnailWidget.apply(this, arguments);
|
||||
this._emptyMsg = 'Click to add a new layer';
|
||||
this.hasError = {};
|
||||
};
|
||||
|
||||
_.extend(ArchEditorWidget.prototype, ThumbnailWidget.prototype);
|
||||
@@ -223,5 +224,28 @@ define([
|
||||
.then(selected => this.insertLayer(selected.node.id, item.id));
|
||||
};
|
||||
|
||||
ArchEditorWidget.prototype.displayErrors = function(errors) {
|
||||
// For each of the errors, highlight the given nodes
|
||||
var oldErrored = Object.keys(this.hasError),
|
||||
currentErrored = errors.map(err => err.id),
|
||||
newErrored = _.difference(currentErrored, oldErrored),
|
||||
fixedLayers = _.difference(oldErrored, currentErrored);
|
||||
|
||||
this._logger.info('updating displayed errors to', currentErrored);
|
||||
this.hasError = {};
|
||||
newErrored.forEach(id => {
|
||||
if (this.items[id]) {
|
||||
this.items[id].decorator.highlight('red');
|
||||
this.hasError[id] = true;
|
||||
}
|
||||
});
|
||||
|
||||
fixedLayers.forEach(id => {
|
||||
if (this.items[id]) {
|
||||
this.items[id].clear();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return ArchEditorWidget;
|
||||
});
|
||||
|
||||
@@ -86,6 +86,7 @@ define([
|
||||
} else {
|
||||
this.deleteNode(item.id);
|
||||
}
|
||||
this.selectionManager.deselect();
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
+49
-48
@@ -1,58 +1,59 @@
|
||||
var mockery = require('mockery'),
|
||||
assert = require('assert'),
|
||||
path = require('path'),
|
||||
nop = () => {},
|
||||
cli;
|
||||
describe('cli', function() {
|
||||
var mockery = require('mockery'),
|
||||
assert = require('assert'),
|
||||
path = require('path'),
|
||||
nop = () => {},
|
||||
cli;
|
||||
|
||||
var callRegister = {
|
||||
childProcess: {
|
||||
execSync: []
|
||||
}
|
||||
};
|
||||
|
||||
var mocks = {
|
||||
childProcess: {},
|
||||
rimraf: {}
|
||||
};
|
||||
|
||||
var childProcess = {
|
||||
execSync: function(cmd) {
|
||||
callRegister.childProcess.execSync.push(cmd);
|
||||
if (mocks.childProcess.execSync) {
|
||||
return mocks.childProcess.execSync.apply(this, arguments);
|
||||
var callRegister = {
|
||||
childProcess: {
|
||||
execSync: []
|
||||
}
|
||||
},
|
||||
spawnSync: function(cmd) {
|
||||
if (cmd === 'luarocks') {
|
||||
};
|
||||
|
||||
var mocks = {
|
||||
childProcess: {},
|
||||
rimraf: {}
|
||||
};
|
||||
|
||||
var childProcess = {
|
||||
execSync: function(cmd) {
|
||||
callRegister.childProcess.execSync.push(cmd);
|
||||
if (mocks.childProcess.execSync) {
|
||||
return mocks.childProcess.execSync.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
spawnSync: function(cmd) {
|
||||
if (cmd === 'luarocks') {
|
||||
return {
|
||||
stdout: 'rnn'
|
||||
};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
spawn: function() {
|
||||
if (mocks.childProcess.spawn) {
|
||||
mocks.childProcess.spawn.apply(this, arguments);
|
||||
}
|
||||
return {
|
||||
stdout: 'rnn'
|
||||
on: () => {},
|
||||
stdout: {
|
||||
on: () => {}
|
||||
},
|
||||
stderr: {
|
||||
on: () => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
spawn: function() {
|
||||
if (mocks.childProcess.spawn) {
|
||||
mocks.childProcess.spawn.apply(this, arguments);
|
||||
};
|
||||
var rimraf = {};
|
||||
rimraf.sync = function() {
|
||||
if (mocks.rimraf.sync) {
|
||||
mocks.rimraf.sync.apply(this, arguments);
|
||||
}
|
||||
return {
|
||||
on: () => {},
|
||||
stdout: {
|
||||
on: () => {}
|
||||
},
|
||||
stderr: {
|
||||
on: () => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
var rimraf = {};
|
||||
rimraf.sync = function() {
|
||||
if (mocks.rimraf.sync) {
|
||||
mocks.rimraf.sync.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
describe('cli', function() {
|
||||
before(function() {
|
||||
// create the mocks
|
||||
mockery.enable({
|
||||
|
||||
@@ -5,6 +5,7 @@ describe('GenerateExecFile', function () {
|
||||
var testFixture = require('../../globals'),
|
||||
lua = require('../../../src/common/lua'),
|
||||
path = testFixture.path,
|
||||
assert = require('assert'),
|
||||
SEED_DIR = path.join(testFixture.DF_SEED_DIR, 'devProject'),
|
||||
gmeConfig = testFixture.getGmeConfig(),
|
||||
expect = testFixture.expect,
|
||||
@@ -139,19 +140,23 @@ describe('GenerateExecFile', function () {
|
||||
expect(data).to.equal(saveData);
|
||||
done();
|
||||
});
|
||||
torch.set('class', (name) => {
|
||||
var cntr = context._G,
|
||||
classes,
|
||||
newClass = lua.newContext()._G;
|
||||
torch.set('class', name => {
|
||||
try {
|
||||
var cntr = context._G,
|
||||
classes,
|
||||
newClass = lua.newContext()._G;
|
||||
|
||||
if (name.includes('.')) {
|
||||
classes = name.split('.');
|
||||
name = classes.pop();
|
||||
for (var i = 0; i < classes.length; i++) {
|
||||
cntr = cntr.get(classes[i]);
|
||||
if (name.includes('.')) {
|
||||
classes = name.split('.');
|
||||
name = classes.pop();
|
||||
for (var i = 0; i < classes.length; i++) {
|
||||
cntr = cntr.get(classes[i]) || cntr;
|
||||
}
|
||||
}
|
||||
cntr.set(name, newClass);
|
||||
} catch(e) {
|
||||
assert(!e, `Failed defining class ${name}: ${e}`);
|
||||
}
|
||||
cntr.set(name, newClass);
|
||||
return newClass;
|
||||
});
|
||||
context._G.set('torch', torch);
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/*jshint node:true, mocha:true*/
|
||||
|
||||
'use strict';
|
||||
var testFixture = require('../../globals');
|
||||
|
||||
describe('ValidateArchitecture', function () {
|
||||
var gmeConfig = testFixture.getGmeConfig(),
|
||||
expect = testFixture.expect,
|
||||
fs = require('fs'),
|
||||
rm_rf = require('rimraf'),
|
||||
mockery = require('mockery'),
|
||||
logger = testFixture.logger.fork('ValidateArchitecture'),
|
||||
PluginCliManager = testFixture.WebGME.PluginCliManager,
|
||||
manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
projectName = 'testProject',
|
||||
pluginName = 'ValidateArchitecture',
|
||||
project,
|
||||
gmeAuth,
|
||||
storage,
|
||||
commitHash;
|
||||
|
||||
before(function (done) {
|
||||
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
|
||||
.then(function (gmeAuth_) {
|
||||
gmeAuth = gmeAuth_;
|
||||
// This uses in memory storage. Use testFixture.getMongoStorage to persist test to database.
|
||||
storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth);
|
||||
return storage.openDatabase();
|
||||
})
|
||||
.then(function () {
|
||||
var importParam = {
|
||||
projectSeed: testFixture.path.join(testFixture.DF_SEED_DIR, 'devProject', 'devProject.webgmex'),
|
||||
projectName: projectName,
|
||||
branchName: 'master',
|
||||
logger: logger,
|
||||
gmeConfig: gmeConfig
|
||||
};
|
||||
|
||||
return testFixture.importProject(storage, importParam);
|
||||
})
|
||||
.then(function (importResult) {
|
||||
project = importResult.project;
|
||||
commitHash = importResult.commitHash;
|
||||
return project.createBranch('test', commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
storage.closeDatabase()
|
||||
.then(function () {
|
||||
return gmeAuth.unload();
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
var plugin,
|
||||
preparePlugin = function(done) {
|
||||
var context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
namespace: 'nn',
|
||||
branchName: 'test',
|
||||
activeNode: '/4/n' // "simple broken" architecture
|
||||
};
|
||||
|
||||
return manager.initializePlugin(pluginName)
|
||||
.then(plugin_ => {
|
||||
plugin = plugin_;
|
||||
plugin.setTorchInstalled(true);
|
||||
return manager.configurePlugin(plugin, {}, context);
|
||||
})
|
||||
.nodeify(done);
|
||||
};
|
||||
// check that each layer is validated
|
||||
describe('simple broken test case', function() {
|
||||
beforeEach(preparePlugin);
|
||||
|
||||
it('should validate each layer', function(done) {
|
||||
var validated = {};
|
||||
|
||||
plugin.validateLayer = id => {
|
||||
validated[id] = true;
|
||||
};
|
||||
plugin.main(err => {
|
||||
expect(err).to.equal(null);
|
||||
expect(Object.keys(validated).length).to.equal(5);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should make tmp dir', function(done) {
|
||||
var oldMkdir = fs.mkdir;
|
||||
fs.mkdir = (dir, cb) => {
|
||||
expect(dir).to.equal(plugin._tmpFileId);
|
||||
return oldMkdir(dir, cb);
|
||||
};
|
||||
plugin.main(() => {
|
||||
fs.mkdir = oldMkdir;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should rm tmp dir', function(done) {
|
||||
mockery.enable({
|
||||
warnOnReplace: false,
|
||||
warnOnUnregistered: false
|
||||
});
|
||||
mockery.registerMock('rimraf', (dir, cb) => {
|
||||
expect(dir).to.equal(plugin._tmpFileId);
|
||||
return rm_rf(dir, cb);
|
||||
});
|
||||
plugin.main(() => {
|
||||
mockery.disable();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// check that errors are returned in the message
|
||||
it('should return two error messages', function(done) {
|
||||
plugin.validateLayer = (id, code) => {
|
||||
if (code.indexOf('Linear()') === -1) {
|
||||
return null;
|
||||
} else { // error!
|
||||
return {
|
||||
id: id,
|
||||
msg: 'invalid args'
|
||||
};
|
||||
}
|
||||
};
|
||||
plugin.main((err, result) => {
|
||||
var invalidLayers = result.messages[0].message.errors.map(msg => msg.id);
|
||||
expect(result.messages[0]).to.not.equal(undefined);
|
||||
expect(invalidLayers.length).to.equal(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('w/o torch support', function() {
|
||||
before(function(done) {
|
||||
preparePlugin(() => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return "null" for messages', function(done) {
|
||||
plugin.setTorchInstalled(false);
|
||||
plugin.main((err, result) => {
|
||||
var errors = result.messages[0].message.errors;
|
||||
expect(errors).to.equal(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('custom layer test case', function() {
|
||||
beforeEach(done => {
|
||||
var context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
namespace: 'nn',
|
||||
branchName: 'test',
|
||||
activeNode: '/4/5' // "simple broken" architecture
|
||||
};
|
||||
|
||||
return manager.initializePlugin(pluginName)
|
||||
.then(plugin_ => {
|
||||
plugin = plugin_;
|
||||
return manager.configurePlugin(plugin, {}, context);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should add custom layer def to test code', function(done) {
|
||||
plugin.validateLayer = (id, code) => {
|
||||
expect(code.indexOf('torch.class')).to.not.equal(-1);
|
||||
return null;
|
||||
};
|
||||
plugin.main(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -52,6 +52,10 @@
|
||||
"UpdateLibrarySeed": {
|
||||
"src": "src/plugins/UpdateLibrarySeed",
|
||||
"test": "test/plugins/UpdateLibrarySeed"
|
||||
},
|
||||
"ValidateArchitecture": {
|
||||
"src": "src/plugins/ValidateArchitecture",
|
||||
"test": "test/plugins/ValidateArchitecture"
|
||||
}
|
||||
},
|
||||
"layouts": {
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário