Skip to content

Commit

Permalink
Test mode, bug fixing, automatic linting
Browse files Browse the repository at this point in the history
  • Loading branch information
pierotofy committed Sep 25, 2016
1 parent 3230c4b commit 36ffae3
Show file tree
Hide file tree
Showing 14 changed files with 391 additions and 245 deletions.
16 changes: 16 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = function(grunt) {

require('time-grunt')(grunt);

grunt.initConfig({
jshint: {
options: {
jshintrc: ".jshintrc"
},
all: ['Gruntfile.js', 'libs/**/*.js', 'docs/**/*.js', 'index.js', 'config.js']
}
});

grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('default', ['jshint']);
};
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ http://www.buildsucceeded.com/2015/solved-pm2-startup-at-boot-time-centos-7-red-

You can monitor the process using `pm2 status`.

### Test Mode

If you want to make a contribution, but don't want to setup OpenDroneMap, or perhaps you are working on a Windows machine, or if you want to run automated tests, you can turn test mode on:

```
node index.js --test
```

While in test mode all calls to OpenDroneMap's code will be simulated (see the /tests directory for the mock data that is returned).

### Test Images

You can find some test drone images [here](https://github.com/dakotabenjamin/odm_data).
Expand Down
19 changes: 10 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ let morgan = require('morgan');
let TaskManager = require('./libs/TaskManager');
let Task = require('./libs/Task');
let odmOptions = require('./libs/odmOptions');
let Directories = require('./libs/Directories');

let winstonStream = {
write: function(message, encoding){
Expand All @@ -51,14 +52,14 @@ app.use('/swagger.json', express.static('docs/swagger.json'));
let upload = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => {
let path = `tmp/${req.id}/`;
fs.exists(path, exists => {
let dstPath = path.join("tmp", req.id);
fs.exists(dstPath, exists => {
if (!exists){
fs.mkdir(path, undefined, () => {
cb(null, path);
fs.mkdir(dstPath, undefined, () => {
cb(null, dstPath);
});
}else{
cb(null, path);
cb(null, dstPath);
}
});
},
Expand Down Expand Up @@ -115,10 +116,10 @@ let server;
app.post('/task/new', addRequestId, upload.array('images'), (req, res) => {
if (req.files.length === 0) res.json({error: "Need at least 1 file."});
else{
let srcPath = `tmp/${req.id}`;
let destPath = `data/${req.id}`;
let destImagesPath = `${destPath}/images`;
let destGpcPath = `${destPath}/gpc`;
let srcPath = path.join("tmp", req.id);
let destPath = path.join(Directories.data, req.id);
let destImagesPath = path.join(destPath, "images");
let destGpcPath = path.join(destPath, "gpc");

async.series([
cb => {
Expand Down
28 changes: 28 additions & 0 deletions libs/Directories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Node-OpenDroneMap Node.js App and REST API to access OpenDroneMap.
Copyright (C) 2016 Node-OpenDroneMap Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
let config = require('../config');
let path = require('path');

class Directories{
static get data(){
return !config.test ? "data" : path.join("tests", "data");
}
}

module.exports = Directories;
27 changes: 17 additions & 10 deletions libs/Task.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";

let config = require('../config');
let async = require('async');
let assert = require('assert');
let logger = require('./logger');
Expand All @@ -26,6 +27,7 @@ let rmdir = require('rimraf');
let odmRunner = require('./odmRunner');
let archiver = require('archiver');
let os = require('os');
let Directories = require('./Directories');

let statusCodes = require('./statusCodes');

Expand Down Expand Up @@ -99,25 +101,25 @@ module.exports = class Task{
// Get path where images are stored for this task
// (relative to nodejs process CWD)
getImagesFolderPath(){
return `${this.getProjectFolderPath()}/images`;
return path.join(this.getProjectFolderPath(), "images");
}

// Get path where GPC file(s) are stored
// (relative to nodejs process CWD)
getGpcFolderPath(){
return `${this.getProjectFolderPath()}/gpc`;
return path.join(this.getProjectFolderPath(), "gpc");
}

// Get path of project (where all images and assets folder are contained)
// (relative to nodejs process CWD)
getProjectFolderPath(){
return `data/${this.uuid}`;
return path.join(Directories.data, this.uuid);
}

// Get the path of the archive where all assets
// outputted by this task are stored.
getAssetsArchivePath(){
return `${this.getProjectFolderPath()}/all.zip`;
return path.join(this.getProjectFolderPath(), "all.zip");
}

// Deletes files and folders related to this task
Expand Down Expand Up @@ -207,16 +209,21 @@ module.exports = class Task{

archive.on('error', err => {
this.setStatus(statusCodes.FAILED);
logger.error(`Could not archive .zip file: ${err.message}`);
finished(err);
});

archive.pipe(output);
archive
.directory(`${this.getProjectFolderPath()}/odm_orthophoto`, 'odm_orthophoto')
.directory(`${this.getProjectFolderPath()}/odm_georeferencing`, 'odm_georeferencing')
.directory(`${this.getProjectFolderPath()}/odm_texturing`, 'odm_texturing')
.directory(`${this.getProjectFolderPath()}/odm_meshing`, 'odm_meshing')
.finalize();
['odm_orthophoto', 'odm_georeferencing', 'odm_texturing', 'odm_meshing'].forEach(folderToArchive => {
let sourcePath = !config.test ?
this.getProjectFolderPath() :
path.join("tests", "processing_results");

archive.directory(
path.join(sourcePath, folderToArchive),
folderToArchive);
});
archive.finalize();
};

if (this.status.code === statusCodes.QUEUED){
Expand Down
8 changes: 4 additions & 4 deletions libs/TaskManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ let Task = require('./Task');
let statusCodes = require('./statusCodes');
let async = require('async');
let schedule = require('node-schedule');
let Directories = require('./Directories');

const DATA_DIR = "data";
const TASKS_DUMP_FILE = `${DATA_DIR}/tasks.json`;
const TASKS_DUMP_FILE = path.join(Directories.data, "tasks.json");
const CLEANUP_TASKS_IF_OLDER_THAN = 1000 * 60 * 60 * 24 * config.cleanupTasksAfter; // days

module.exports = class TaskManager{
Expand Down Expand Up @@ -85,11 +85,11 @@ module.exports = class TaskManager{
removeOrphanedDirectories(done){
logger.info("Checking for orphaned directories to be removed...");

fs.readdir(DATA_DIR, (err, entries) => {
fs.readdir(Directories.data, (err, entries) => {
if (err) done(err);
else{
async.eachSeries(entries, (entry, cb) => {
let dirPath = path.join(DATA_DIR, entry);
let dirPath = path.join(Directories.data, entry);
if (fs.statSync(dirPath).isDirectory() &&
entry.match(/^[\w\d]+\-[\w\d]+\-[\w\d]+\-[\w\d]+\-[\w\d]+$/) &&
!this.tasks[entry]){
Expand Down
2 changes: 1 addition & 1 deletion libs/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ let path = require('path');
// Configure custom File transport to write plain text messages
let logPath = ( config.logger.logDirectory ?
config.logger.logDirectory :
`${__dirname}/../` );
path.join(__dirname, "..") );

// Check that log file directory can be written to
try {
Expand Down
1 change: 1 addition & 0 deletions libs/odmOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ module.exports = {
// Scan through all possible options
for (let odmOption of odmOptions){
// Was this option selected by the user?
/*jshint loopfunc: true */
let opt = options.find(o => o.name === odmOption.name);
if (opt){
try{
Expand Down
28 changes: 17 additions & 11 deletions libs/odmRunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module.exports = {
run: function(options, done, outputReceived){
assert(options["project-path"] !== undefined, "project-path must be defined");

let command = [`${config.odm_path}/run.py`];
let command = [path.join(config.odm_path, "run.py")];
for (var name in options){
let value = options[name];

Expand All @@ -48,8 +48,18 @@ module.exports = {
if (config.test){
logger.info("Test mode is on, command will not execute");

// TODO: simulate test output
done(null, 0, null);
let outputTestFile = path.join("..", "tests", "odm_output.txt");
fs.readFile(path.resolve(__dirname, outputTestFile), 'utf8', (err, text) => {
if (!err){
let lines = text.split("\n");
lines.forEach(line => outputReceived(line));

done(null, 0, null);
}else{
logger.warn(`Error: ${err.message}`);
done(err);
}
});

return; // Skip rest
}
Expand All @@ -71,22 +81,18 @@ module.exports = {
// In test mode, we don't call ODM,
// instead we return a mock
if (config.test){
let optionsTestFile = "../tests/odm_options.json";
let optionsTestFile = path.join("..", "tests", "odm_options.json");
fs.readFile(path.resolve(__dirname, optionsTestFile), 'utf8', (err, json) => {
if (!err){
try{
let options = JSON.parse(json);

// We also mark each description with "TEST" (to make sure we know this is not real data)
options.forEach(option => { option.help = "## TEST ##" + (option.help !== undefined ? ` ${option.help}` : ""); });

done(null, options);
}catch(e){
console.log(`Invalid test options ${optionsTestFile}: ${err.message}`);
logger.warn(`Invalid test options ${optionsTestFile}: ${err.message}`);
done(e);
}
}else{
console.log(`Error: ${err.message}`);
logger.warn(`Error: ${err.message}`);
done(err);
}
});
Expand All @@ -95,7 +101,7 @@ module.exports = {
}

// Launch
let childProcess = spawn("python", [`${__dirname}/../helpers/odmOptionsToJson.py`,
let childProcess = spawn("python", [path.join(__dirname, "..", "helpers", "odmOptionsToJson.py"),
"--project-path", config.odm_path]);
let output = [];

Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
"winston": "^2.2.0"
},
"devDependencies": {
"nodemon": "^1.9.2"
"grunt": "^1.0.1",
"grunt-contrib-jshint": "^1.0.0",
"nodemon": "^1.9.2",
"time-grunt": "^1.4.0"
}
}
4 changes: 2 additions & 2 deletions public/js/fileinput.js
Original file line number Diff line number Diff line change
Expand Up @@ -2216,9 +2216,9 @@
}
if (!self.showPreview) {
self.addToStack(file);
setTimeout(function () {
// setTimeout(function () {
readFile(i + 1);
}, 100);
// }, 100);
self._raise('fileloaded', [file, previewId, i, reader]);
return;
}
Expand Down
3 changes: 1 addition & 2 deletions public/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,7 @@ $(function(){
$("#btnUpload").removeAttr('disabled')
.val(btnUploadLabel);
})
.on('filebatchuploaderror', function(e, data, msg){
});
.on('filebatchuploaderror', console.warn);

// Load options
function Option(properties){
Expand Down
Loading

0 comments on commit 36ffae3

Please sign in to comment.