Close GH-2795: Rewrite cucumber test caching (and support logic). Fixes #2745
This commit is contained in:
parent
8522cddd61
commit
7d124ce54d
10
cucumber.js
10
cucumber.js
@ -1,10 +1,8 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
default: '--require features --tags ~@stress --tags ~@todo',
|
default: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions',
|
||||||
verify: '--require features --tags ~@todo --tags ~@bug --tags ~@stress -f progress',
|
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
|
||||||
jenkins: '--require features --tags ~@todo --tags ~@bug --tags ~@stress --tags ~@options -f progress',
|
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
|
||||||
bugs: '--require features --tags @bug',
|
all: '--strict --require features/support --require features/step_definitions'
|
||||||
todo: '--require features --tags @todo',
|
|
||||||
all: '--require features'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ Feature: Traffic - speeds
|
|||||||
| fb | primary |
|
| fb | primary |
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
Given the extract extra arguments "--generate-edge-lookup"
|
||||||
Given the contract extra arguments "--segment-speed-file speeds.csv"
|
Given the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
Given the speed file
|
Given the speed file
|
||||||
"""
|
"""
|
||||||
1,2,0
|
1,2,0
|
||||||
@ -69,7 +69,7 @@ Feature: Traffic - speeds
|
|||||||
| fb | primary |
|
| fb | primary |
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
Given the extract extra arguments "--generate-edge-lookup"
|
||||||
Given the contract extra arguments "--segment-speed-file speeds.csv"
|
Given the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
Given the speed file
|
Given the speed file
|
||||||
"""
|
"""
|
||||||
1,2,0
|
1,2,0
|
||||||
@ -112,7 +112,6 @@ Feature: Traffic - speeds
|
|||||||
| fb | primary |
|
| fb | primary |
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
Given the extract extra arguments "--generate-edge-lookup"
|
||||||
Given the contract extra arguments "--segment-speed-file speeds.csv"
|
|
||||||
Given the speed file
|
Given the speed file
|
||||||
"""
|
"""
|
||||||
1,2,-10
|
1,2,-10
|
||||||
@ -123,6 +122,6 @@ Feature: Traffic - speeds
|
|||||||
4,1,-5
|
4,1,-5
|
||||||
"""
|
"""
|
||||||
And the data has been extracted
|
And the data has been extracted
|
||||||
When I run "osrm-contract --segment-speed-file speeds.csv {extracted_base}.osrm"
|
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
||||||
And stderr should contain "malformed"
|
And stderr should contain "malformed"
|
||||||
And it should exit with code not 0
|
And it should exit with an error
|
||||||
|
@ -58,7 +58,7 @@ Feature: Traffic - turn penalties
|
|||||||
8,11,12,23
|
8,11,12,23
|
||||||
1,4,5,-0.2
|
1,4,5,-0.2
|
||||||
"""
|
"""
|
||||||
And the contract extra arguments "--turn-penalty-file penalties.csv"
|
And the contract extra arguments "--turn-penalty-file {penalties_file}"
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | speed | time |
|
| from | to | route | speed | time |
|
||||||
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
|
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
|
||||||
@ -81,7 +81,7 @@ Feature: Traffic - turn penalties
|
|||||||
# double left - hdc penalty ever so slightly higher than imn; forces all the way around
|
# double left - hdc penalty ever so slightly higher than imn; forces all the way around
|
||||||
|
|
||||||
Scenario: Too-negative penalty clamps, but does not fail
|
Scenario: Too-negative penalty clamps, but does not fail
|
||||||
Given the contract extra arguments "--turn-penalty-file penalties.csv"
|
Given the contract extra arguments "--turn-penalty-file {penalties_file}"
|
||||||
And the profile "testbot"
|
And the profile "testbot"
|
||||||
And the turn penalty file
|
And the turn penalty file
|
||||||
"""
|
"""
|
||||||
|
@ -422,7 +422,7 @@ Feature: Turn Lane Guidance
|
|||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,e | main,main,main,main | depart,use lane straight,continue right,arrive | ,left:false straight:false straight:false straight:false straight:true straight:true right:false,straight:false straight:false right:false right:true right:true, |
|
| a,e | main,main,main,main | depart,use lane straight,continue right,arrive | ,left:false straight:false straight:false straight:false straight:true straight:true right:false,straight:false straight:false right:false right:true right:true, |
|
||||||
|
|
||||||
@anticipate @todo @bug @2661
|
@anticipate @todo @2661
|
||||||
Scenario: Anticipate with lanes in roundabout: roundabouts as the unit of anticipation
|
Scenario: Anticipate with lanes in roundabout: roundabouts as the unit of anticipation
|
||||||
Given the node map
|
Given the node map
|
||||||
| | | e | | |
|
| | | e | | |
|
||||||
@ -667,7 +667,7 @@ Feature: Turn Lane Guidance
|
|||||||
| a,f | abc,bdeh,feg,feg | depart,turn right,turn right,arrive | ,none:false none:false right:false right:true,left:false none:false none:false right:true, |
|
| a,f | abc,bdeh,feg,feg | depart,turn right,turn right,arrive | ,none:false none:false right:false right:true,left:false none:false none:false right:true, |
|
||||||
|
|
||||||
@anticipate
|
@anticipate
|
||||||
Scenario: Tripple Right keeping Left
|
Scenario: Triple Right keeping Left
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | | | | b | | i |
|
| a | | | | b | | i |
|
||||||
| | | | | | | |
|
| | | | | | | |
|
||||||
|
@ -620,7 +620,7 @@ Feature: Turn Lane Guidance
|
|||||||
| a,d | hwy,hwy | depart,arrive | , |
|
| a,d | hwy,hwy | depart,arrive | , |
|
||||||
| a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
|
| a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
|
||||||
|
|
||||||
@bug @todo
|
@todo
|
||||||
Scenario: Turning Off Ramp
|
Scenario: Turning Off Ramp
|
||||||
Given the node map
|
Given the node map
|
||||||
| | a | |
|
| | a | |
|
||||||
|
31
features/lib/hash.js
Normal file
31
features/lib/hash.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const d3 = require('d3-queue');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
hashOfFiles: (paths, cb) => {
|
||||||
|
let queue = d3.queue();
|
||||||
|
for (let i = 0; i < paths.length; ++i) {
|
||||||
|
queue.defer(fs.readFile, paths[i]);
|
||||||
|
}
|
||||||
|
queue.awaitAll((err, results) => {
|
||||||
|
if (err) return cb(err);
|
||||||
|
let checksum = crypto.createHash('md5');
|
||||||
|
for (let i = 0; i < results.length; ++i) {
|
||||||
|
checksum.update(results[i]);
|
||||||
|
}
|
||||||
|
cb(null, checksum.digest('hex'));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
hashOfFile: (path, cb) => {
|
||||||
|
fs.readFile(path, (err, result) => {
|
||||||
|
if (err) return cb(err);
|
||||||
|
let checksum = crypto.createHash('md5');
|
||||||
|
checksum.update(result);
|
||||||
|
cb(null, checksum.digest('hex'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
@ -1,11 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var builder = require('xmlbuilder');
|
const builder = require('xmlbuilder');
|
||||||
|
const ensureDecimal = require('./utils').ensureDecimal;
|
||||||
var ensureDecimal = (i) => {
|
|
||||||
if (parseInt(i) === i) return i.toFixed(1);
|
|
||||||
else return i;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DB {
|
class DB {
|
||||||
constructor () {
|
constructor () {
|
169
features/lib/osrm_loader.js
Normal file
169
features/lib/osrm_loader.js
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const util = require('util');
|
||||||
|
const Timeout = require('node-timeout');
|
||||||
|
const tryConnect = require('../lib/try_connect');
|
||||||
|
const errorReason = require('./utils').errorReason;
|
||||||
|
|
||||||
|
class OSRMBaseLoader{
|
||||||
|
constructor (scope) {
|
||||||
|
this.scope = scope;
|
||||||
|
this.child = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
launch (callback) {
|
||||||
|
var limit = Timeout(this.scope.TIMEOUT, { err: new Error('*** Launching osrm-routed timed out.') });
|
||||||
|
|
||||||
|
var runLaunch = (cb) => {
|
||||||
|
this.osrmUp(() => { this.waitForConnection(cb); });
|
||||||
|
};
|
||||||
|
|
||||||
|
runLaunch(limit((e) => { if (e) callback(e); else callback(); }));
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown (callback) {
|
||||||
|
if (!this.osrmIsRunning()) return callback();
|
||||||
|
|
||||||
|
var limit = Timeout(this.scope.TIMEOUT, { err: new Error('*** Shutting down osrm-routed timed out.')});
|
||||||
|
|
||||||
|
this.osrmDown(limit(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
osrmIsRunning () {
|
||||||
|
return this.child && !this.child.killed;
|
||||||
|
}
|
||||||
|
|
||||||
|
osrmDown (callback) {
|
||||||
|
if (this.osrmIsRunning()) {
|
||||||
|
this.child.on('exit', (code, signal) => {callback();});
|
||||||
|
this.child.kill();
|
||||||
|
} else callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForConnection (callback) {
|
||||||
|
var retryCount = 0;
|
||||||
|
let retry = (err) => {
|
||||||
|
if (err) {
|
||||||
|
if (retryCount < 10) {
|
||||||
|
retryCount++;
|
||||||
|
setTimeout(() => { tryConnect(this.scope.OSRM_PORT, retry); }, 10);
|
||||||
|
} else {
|
||||||
|
callback(new Error("Could not connect to osrm-routed after ten retries."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tryConnect(this.scope.OSRM_PORT, retry);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OSRMDirectLoader extends OSRMBaseLoader {
|
||||||
|
constructor (scope) {
|
||||||
|
super(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
load (inputFile, callback) {
|
||||||
|
this.inputFile = inputFile;
|
||||||
|
this.shutdown(() => {
|
||||||
|
this.launch(callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
osrmUp (callback) {
|
||||||
|
if (this.osrmIsRunning()) return callback(new Error("osrm-routed already running!"));
|
||||||
|
|
||||||
|
this.child = this.scope.runBin('osrm-routed', util.format("%s -p %d", this.inputFile, this.scope.OSRM_PORT), this.scope.environment, (err) => {
|
||||||
|
if (err) {
|
||||||
|
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OSRMDatastoreLoader extends OSRMBaseLoader {
|
||||||
|
constructor (scope) {
|
||||||
|
super(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
load (inputFile, callback) {
|
||||||
|
this.inputFile = inputFile;
|
||||||
|
|
||||||
|
this.loadData((err) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
if (!this.osrmIsRunning()) this.launch(callback);
|
||||||
|
else {
|
||||||
|
this.scope.setupOutputLog(this.child, fs.createWriteStream(this.scope.scenarioLogFile, {'flags': 'a'}));
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadData (callback) {
|
||||||
|
this.scope.runBin('osrm-datastore', this.inputFile, this.scope.environment, (err) => {
|
||||||
|
if (err) return callback(new Error('*** osrm-datastore exited with ' + err.code + ': ' + err));
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
osrmUp (callback) {
|
||||||
|
if (this.osrmIsRunning()) return callback();
|
||||||
|
|
||||||
|
this.child = this.scope.runBin('osrm-routed', util.format('--shared-memory=1 -p %d', this.scope.OSRM_PORT), this.scope.environment, (err) => {
|
||||||
|
if (err) {
|
||||||
|
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// we call the callback here, becuase we don't want to wait for the child process to finish
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OSRMLoader {
|
||||||
|
constructor (scope) {
|
||||||
|
this.scope = scope;
|
||||||
|
this.sharedLoader = new OSRMDatastoreLoader(this.scope);
|
||||||
|
this.directLoader = new OSRMDirectLoader(this.scope);
|
||||||
|
this.method = scope.DEFAULT_LOAD_METHOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
load (inputFile, callback) {
|
||||||
|
if (this.method === 'datastore') {
|
||||||
|
this.directLoader.shutdown((err) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
this.loader = this.sharedLoader;
|
||||||
|
this.sharedLoader.load(inputFile, callback);
|
||||||
|
});
|
||||||
|
} else if (this.method === 'directly') {
|
||||||
|
this.sharedLoader.shutdown((err) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
this.loader = this.directLoader;
|
||||||
|
this.directLoader.load(inputFile, callback);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
callback(new Error('*** Unknown load method ' + method));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoadMethod (method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown (callback) {
|
||||||
|
if (!this.loader) return callback();
|
||||||
|
|
||||||
|
this.loader.shutdown(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
up () {
|
||||||
|
return this.loader ? this.loader.osrmIsRunning() : false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = OSRMLoader;
|
54
features/lib/table_diff.js
Normal file
54
features/lib/table_diff.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var util = require('util');
|
||||||
|
var path = require('path');
|
||||||
|
var fs = require('fs');
|
||||||
|
var chalk = require('chalk');
|
||||||
|
|
||||||
|
var unescapeStr = (str) => str.replace(/\\\|/g, '\|').replace(/\\\\/g, '\\');
|
||||||
|
|
||||||
|
module.exports = function (expected, actual) {
|
||||||
|
let headers = expected.raw()[0];
|
||||||
|
let expected_keys = expected.hashes();
|
||||||
|
let diff = [];
|
||||||
|
let hasErrors = false;
|
||||||
|
|
||||||
|
var good = 0, bad = 0;
|
||||||
|
|
||||||
|
expected_keys.forEach((row, i) => {
|
||||||
|
var rowError = false;
|
||||||
|
|
||||||
|
for (var j in row) {
|
||||||
|
if (unescapeStr(row[j]) != actual[i][j]) {
|
||||||
|
rowError = true;
|
||||||
|
hasErrors = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rowError) {
|
||||||
|
bad++;
|
||||||
|
diff.push(Object.assign({}, row, {c_status: 'undefined'}));
|
||||||
|
diff.push(Object.assign({}, actual[i], {c_status: 'comment'}));
|
||||||
|
} else {
|
||||||
|
good++;
|
||||||
|
diff.push(row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!hasErrors) return null;
|
||||||
|
|
||||||
|
var s = ['Tables were not identical:'];
|
||||||
|
s.push(headers.map(key => ' ' + key).join(' | '));
|
||||||
|
diff.forEach((row) => {
|
||||||
|
var rowString = '| ';
|
||||||
|
headers.forEach((header) => {
|
||||||
|
if (!row.c_status) rowString += chalk.green(' ' + row[header] + ' | ');
|
||||||
|
else if (row.c_status === 'undefined') rowString += chalk.yellow('(-) ' + row[header] + ' | ');
|
||||||
|
else rowString += chalk.red('(+) ' + row[header] + ' | ');
|
||||||
|
});
|
||||||
|
s.push(rowString);
|
||||||
|
});
|
||||||
|
|
||||||
|
return s.join('\n') + '\nTODO this is a temp workaround waiting for https://github.com/cucumber/cucumber-js/issues/534';
|
||||||
|
};
|
13
features/lib/try_connect.js
Normal file
13
features/lib/try_connect.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const net = require('net');
|
||||||
|
const Timeout = require('node-timeout');
|
||||||
|
|
||||||
|
module.exports = function tryConnect(port, callback) {
|
||||||
|
net.connect({ port: port, host: '127.0.0.1' })
|
||||||
|
.on('connect', () => { callback(); })
|
||||||
|
.on('error', () => {
|
||||||
|
callback(new Error('Could not connect.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
17
features/lib/utils.js
Normal file
17
features/lib/utils.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const util = require('util');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
ensureDecimal: (i) => {
|
||||||
|
if (parseInt(i) === i) return i.toFixed(1);
|
||||||
|
else return i;
|
||||||
|
},
|
||||||
|
|
||||||
|
errorReason: (err) => {
|
||||||
|
return err.signal ?
|
||||||
|
util.format('killed by signal %s', err.signal) :
|
||||||
|
util.format('exited with code %d', err.code);
|
||||||
|
}
|
||||||
|
};
|
@ -1,8 +1,7 @@
|
|||||||
@prepare @options @files
|
@prepare @options @files
|
||||||
Feature: osrm-contract command line options: datasources
|
Feature: osrm-contract command line options: datasources
|
||||||
# expansions:
|
# expansions:
|
||||||
# {extracted_base} => path to current extracted input file
|
# {processed_file} => path to .osrm file
|
||||||
# {profile} => path to current profile script
|
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
@ -24,7 +23,6 @@ Feature: osrm-contract command line options: datasources
|
|||||||
And the data has been extracted
|
And the data has been extracted
|
||||||
|
|
||||||
Scenario: osrm-contract - Passing base file
|
Scenario: osrm-contract - Passing base file
|
||||||
When I run "osrm-contract --segment-speed-file speeds.csv {extracted_base}.osrm"
|
When I run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
||||||
Then stderr should be empty
|
Then datasource names should contain "lua profile,25_osrmcontract_passing_base_file_speeds"
|
||||||
And datasource names should contain "lua profile,speeds"
|
And it should exit successfully
|
||||||
And it should exit with code 0
|
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
@prepare @options @files
|
@prepare @options @files
|
||||||
Feature: osrm-contract command line options: files
|
Feature: osrm-contract command line options: files
|
||||||
# expansions:
|
|
||||||
# {extracted_base} => path to current extracted input file
|
|
||||||
# {profile} => path to current profile script
|
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
And the node map
|
And the node map
|
||||||
@ -14,12 +10,11 @@ Feature: osrm-contract command line options: files
|
|||||||
And the data has been extracted
|
And the data has been extracted
|
||||||
|
|
||||||
Scenario: osrm-contract - Passing base file
|
Scenario: osrm-contract - Passing base file
|
||||||
When I run "osrm-contract {extracted_base}.osrm"
|
When I run "osrm-contract {processed_file}"
|
||||||
Then stderr should be empty
|
Then it should exit successfully
|
||||||
And it should exit with code 0
|
|
||||||
|
|
||||||
Scenario: osrm-contract - Missing input file
|
Scenario: osrm-contract - Missing input file
|
||||||
When I run "osrm-contract over-the-rainbow.osrm"
|
When I try to run "osrm-contract over-the-rainbow.osrm"
|
||||||
And stderr should contain "over-the-rainbow.osrm"
|
And stderr should contain "over-the-rainbow.osrm"
|
||||||
And stderr should contain "not found"
|
And stderr should contain "not found"
|
||||||
And it should exit with code 1
|
And it should exit with an error
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
Feature: osrm-contract command line options: help
|
Feature: osrm-contract command line options: help
|
||||||
|
|
||||||
Scenario: osrm-contract - Help should be shown when no options are passed
|
Scenario: osrm-contract - Help should be shown when no options are passed
|
||||||
When I run "osrm-contract"
|
When I try to run "osrm-contract"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain "osrm-contract <input.osrm> [options]:"
|
And stdout should contain "osrm-contract <input.osrm> [options]:"
|
||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
@ -13,7 +13,7 @@ Feature: osrm-contract command line options: help
|
|||||||
And stdout should contain "--core"
|
And stdout should contain "--core"
|
||||||
And stdout should contain "--level-cache"
|
And stdout should contain "--level-cache"
|
||||||
And stdout should contain "--segment-speed-file"
|
And stdout should contain "--segment-speed-file"
|
||||||
And it should exit with code 1
|
And it should exit with an error
|
||||||
|
|
||||||
Scenario: osrm-contract - Help, short
|
Scenario: osrm-contract - Help, short
|
||||||
When I run "osrm-contract -h"
|
When I run "osrm-contract -h"
|
||||||
@ -27,7 +27,7 @@ Feature: osrm-contract command line options: help
|
|||||||
And stdout should contain "--core"
|
And stdout should contain "--core"
|
||||||
And stdout should contain "--level-cache"
|
And stdout should contain "--level-cache"
|
||||||
And stdout should contain "--segment-speed-file"
|
And stdout should contain "--segment-speed-file"
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
|
||||||
Scenario: osrm-contract - Help, long
|
Scenario: osrm-contract - Help, long
|
||||||
When I run "osrm-contract --help"
|
When I run "osrm-contract --help"
|
||||||
@ -41,4 +41,4 @@ Feature: osrm-contract command line options: help
|
|||||||
And stdout should contain "--core"
|
And stdout should contain "--core"
|
||||||
And stdout should contain "--level-cache"
|
And stdout should contain "--level-cache"
|
||||||
And stdout should contain "--segment-speed-file"
|
And stdout should contain "--segment-speed-file"
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
@ -5,8 +5,8 @@ Feature: osrm-contract command line options: invalid options
|
|||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: osrm-contract - Non-existing option
|
Scenario: osrm-contract - Non-existing option
|
||||||
When I run "osrm-contract --fly-me-to-the-moon"
|
When I try to run "osrm-contract --fly-me-to-the-moon"
|
||||||
Then stdout should be empty
|
Then stdout should be empty
|
||||||
And stderr should contain "option"
|
And stderr should contain "option"
|
||||||
And stderr should contain "fly-me-to-the-moon"
|
And stderr should contain "fly-me-to-the-moon"
|
||||||
And it should exit with code 1
|
And it should exit with an error
|
||||||
|
@ -12,11 +12,11 @@ Feature: osrm-contract command line options: version
|
|||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
|
||||||
Scenario: osrm-contract - Version, long
|
Scenario: osrm-contract - Version, long
|
||||||
When I run "osrm-contract --version"
|
When I run "osrm-contract --version"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
@ -14,17 +14,15 @@ Feature: osrm-extract command line options: files
|
|||||||
And the data has been saved to disk
|
And the data has been saved to disk
|
||||||
|
|
||||||
Scenario: osrm-extract - Passing base file
|
Scenario: osrm-extract - Passing base file
|
||||||
When I run "osrm-extract {osm_base}.osm --profile {profile}"
|
When I run "osrm-extract {osm_file} --profile {profile_file}"
|
||||||
Then stderr should be empty
|
Then it should exit successfully
|
||||||
And it should exit with code 0
|
|
||||||
|
|
||||||
Scenario: osrm-extract - Order of options should not matter
|
Scenario: osrm-extract - Order of options should not matter
|
||||||
When I run "osrm-extract --profile {profile} {osm_base}.osm"
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
Then stderr should be empty
|
Then it should exit successfully
|
||||||
And it should exit with code 0
|
|
||||||
|
|
||||||
Scenario: osrm-extract - Missing input file
|
Scenario: osrm-extract - Missing input file
|
||||||
When I run "osrm-extract over-the-rainbow.osrm --profile {profile}"
|
When I try to run "osrm-extract over-the-rainbow.osrm --profile {profile_file}"
|
||||||
And stderr should contain "over-the-rainbow.osrm"
|
And stderr should contain "over-the-rainbow.osrm"
|
||||||
And stderr should contain "not found"
|
And stderr should contain "not found"
|
||||||
And it should exit with code 1
|
And it should exit with an error
|
||||||
|
@ -16,7 +16,7 @@ Feature: osrm-extract command line options: help
|
|||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--generate-edge-lookup"
|
And stdout should contain "--generate-edge-lookup"
|
||||||
And stdout should contain "--small-component-size"
|
And stdout should contain "--small-component-size"
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
|
||||||
Scenario: osrm-extract - Help, short
|
Scenario: osrm-extract - Help, short
|
||||||
When I run "osrm-extract -h"
|
When I run "osrm-extract -h"
|
||||||
@ -30,7 +30,7 @@ Feature: osrm-extract command line options: help
|
|||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--generate-edge-lookup"
|
And stdout should contain "--generate-edge-lookup"
|
||||||
And stdout should contain "--small-component-size"
|
And stdout should contain "--small-component-size"
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
|
||||||
Scenario: osrm-extract - Help, long
|
Scenario: osrm-extract - Help, long
|
||||||
When I run "osrm-extract --help"
|
When I run "osrm-extract --help"
|
||||||
@ -44,4 +44,4 @@ Feature: osrm-extract command line options: help
|
|||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--generate-edge-lookup"
|
And stdout should contain "--generate-edge-lookup"
|
||||||
And stdout should contain "--small-component-size"
|
And stdout should contain "--small-component-size"
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
@ -5,8 +5,8 @@ Feature: osrm-extract command line options: invalid options
|
|||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: osrm-extract - Non-existing option
|
Scenario: osrm-extract - Non-existing option
|
||||||
When I run "osrm-extract --fly-me-to-the-moon"
|
When I try to run "osrm-extract --fly-me-to-the-moon"
|
||||||
Then stdout should be empty
|
Then stdout should be empty
|
||||||
And stderr should contain "option"
|
And stderr should contain "option"
|
||||||
And stderr should contain "fly-me-to-the-moon"
|
And stderr should contain "fly-me-to-the-moon"
|
||||||
And it should exit with code 1
|
And it should exit with an error
|
||||||
|
@ -12,11 +12,11 @@ Feature: osrm-extract command line options: version
|
|||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
|
||||||
Scenario: osrm-extract - Version, long
|
Scenario: osrm-extract - Version, long
|
||||||
When I run "osrm-extract --version"
|
When I run "osrm-extract --version"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
@ -29,4 +29,4 @@ Feature: osrm-routed command line options: files
|
|||||||
And stdout should contain /^\[info\] loaded plugin: viaroute/
|
And stdout should contain /^\[info\] loaded plugin: viaroute/
|
||||||
And stdout should contain /^\[info\] trial run/
|
And stdout should contain /^\[info\] trial run/
|
||||||
And stdout should contain /^\[info\] shutdown completed/
|
And stdout should contain /^\[info\] shutdown completed/
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
@ -21,7 +21,7 @@ Feature: osrm-routed command line options: help
|
|||||||
And stdout should contain "--max-trip-size"
|
And stdout should contain "--max-trip-size"
|
||||||
And stdout should contain "--max-table-size"
|
And stdout should contain "--max-table-size"
|
||||||
And stdout should contain "--max-matching-size"
|
And stdout should contain "--max-matching-size"
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
|
||||||
Scenario: osrm-routed - Help, short
|
Scenario: osrm-routed - Help, short
|
||||||
When I run "osrm-routed -h"
|
When I run "osrm-routed -h"
|
||||||
@ -40,7 +40,7 @@ Feature: osrm-routed command line options: help
|
|||||||
And stdout should contain "--max-trip-size"
|
And stdout should contain "--max-trip-size"
|
||||||
And stdout should contain "--max-table-size"
|
And stdout should contain "--max-table-size"
|
||||||
And stdout should contain "--max-matching-size"
|
And stdout should contain "--max-matching-size"
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
|
||||||
Scenario: osrm-routed - Help, long
|
Scenario: osrm-routed - Help, long
|
||||||
When I run "osrm-routed --help"
|
When I run "osrm-routed --help"
|
||||||
@ -59,4 +59,4 @@ Feature: osrm-routed command line options: help
|
|||||||
And stdout should contain "--max-table-size"
|
And stdout should contain "--max-table-size"
|
||||||
And stdout should contain "--max-table-size"
|
And stdout should contain "--max-table-size"
|
||||||
And stdout should contain "--max-matching-size"
|
And stdout should contain "--max-matching-size"
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
@ -5,14 +5,14 @@ Feature: osrm-routed command line options: invalid options
|
|||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: osrm-routed - Non-existing option
|
Scenario: osrm-routed - Non-existing option
|
||||||
When I run "osrm-routed --fly-me-to-the-moon"
|
When I try to run "osrm-routed --fly-me-to-the-moon"
|
||||||
Then stdout should be empty
|
Then stdout should be empty
|
||||||
And stderr should contain "unrecognised"
|
And stderr should contain "unrecognised"
|
||||||
And stderr should contain "fly-me-to-the-moon"
|
And stderr should contain "fly-me-to-the-moon"
|
||||||
And it should exit with code 1
|
And it should exit with an error
|
||||||
|
|
||||||
Scenario: osrm-routed - Missing file
|
Scenario: osrm-routed - Missing file
|
||||||
When I run "osrm-routed over-the-rainbow.osrm"
|
When I try to run "osrm-routed over-the-rainbow.osrm"
|
||||||
Then stderr should contain "over-the-rainbow.osrm"
|
Then stderr should contain "over-the-rainbow.osrm"
|
||||||
And stderr should contain "not found"
|
And stderr should contain "not found"
|
||||||
And it should exit with code 1
|
And it should exit with an error
|
||||||
|
@ -12,11 +12,11 @@ Feature: osrm-routed command line options: version
|
|||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
|
||||||
Scenario: osrm-routed - Version, long
|
Scenario: osrm-routed - Version, long
|
||||||
When I run "osrm-routed --version"
|
When I run "osrm-routed --version"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
And it should exit with code 0
|
And it should exit successfully
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
@raster @extract
|
@raster @extract
|
||||||
Feature: osrm-extract with a profile containing raster source
|
Feature: osrm-extract with a profile containing raster source
|
||||||
# expansions:
|
|
||||||
# {osm_base} => path to current input file
|
|
||||||
# {profile} => path to current profile script
|
|
||||||
|
|
||||||
Scenario: osrm-extract on a valid profile
|
Scenario: osrm-extract on a valid profile
|
||||||
Given the profile "rasterbot"
|
Given the profile "rasterbot"
|
||||||
And the node map
|
And the node map
|
||||||
@ -11,8 +7,15 @@ Feature: osrm-extract with a profile containing raster source
|
|||||||
And the ways
|
And the ways
|
||||||
| nodes |
|
| nodes |
|
||||||
| ab |
|
| ab |
|
||||||
|
And the raster source
|
||||||
|
"""
|
||||||
|
0 0 0 0
|
||||||
|
0 0 0 250
|
||||||
|
0 0 250 500
|
||||||
|
0 0 0 250
|
||||||
|
0 0 0 0
|
||||||
|
"""
|
||||||
And the data has been saved to disk
|
And the data has been saved to disk
|
||||||
When I run "osrm-extract {osm_base}.osm -p {profile}"
|
When I run "osrm-extract {osm_file} -p {profile_file}"
|
||||||
Then stderr should be empty
|
Then stdout should contain "source loader"
|
||||||
And stdout should contain "source loader"
|
And it should exit successfully
|
||||||
And it should exit with code 0
|
|
||||||
|
@ -32,8 +32,8 @@ Feature: Raster - weights
|
|||||||
|
|
||||||
Scenario: Weighting not based on raster sources
|
Scenario: Weighting not based on raster sources
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
When I run "osrm-extract {osm_base}.osm -p {profile}"
|
When I run "osrm-extract {osm_file} -p {profile_file}"
|
||||||
And I run "osrm-contract {osm_base}.osm"
|
And I run "osrm-contract {processed_file}"
|
||||||
And I route I should get
|
And I route I should get
|
||||||
| from | to | route | speed |
|
| from | to | route | speed |
|
||||||
| a | b | ab,ab | 36 km/h |
|
| a | b | ab,ab | 36 km/h |
|
||||||
@ -44,9 +44,9 @@ Feature: Raster - weights
|
|||||||
|
|
||||||
Scenario: Weighting based on raster sources
|
Scenario: Weighting based on raster sources
|
||||||
Given the profile "rasterbot"
|
Given the profile "rasterbot"
|
||||||
When I run "osrm-extract {osm_base}.osm -p {profile}"
|
When I run "osrm-extract {osm_file} -p {profile_file}"
|
||||||
Then stdout should contain "evaluating segment"
|
Then stdout should contain "evaluating segment"
|
||||||
And I run "osrm-contract {osm_base}.osm"
|
And I run "osrm-contract {processed_file}"
|
||||||
And I route I should get
|
And I route I should get
|
||||||
| from | to | route | speed |
|
| from | to | route | speed |
|
||||||
| a | b | ab,ab | 8 km/h |
|
| a | b | ab,ab | 8 km/h |
|
||||||
@ -62,9 +62,9 @@ Feature: Raster - weights
|
|||||||
|
|
||||||
Scenario: Weighting based on raster sources
|
Scenario: Weighting based on raster sources
|
||||||
Given the profile "rasterbotinterp"
|
Given the profile "rasterbotinterp"
|
||||||
When I run "osrm-extract {osm_base}.osm -p {profile}"
|
When I run "osrm-extract {osm_file} -p {profile_file}"
|
||||||
Then stdout should contain "evaluating segment"
|
Then stdout should contain "evaluating segment"
|
||||||
And I run "osrm-contract {osm_base}.osm"
|
And I run "osrm-contract {processed_file}"
|
||||||
And I route I should get
|
And I route I should get
|
||||||
| from | to | route | speed |
|
| from | to | route | speed |
|
||||||
| a | b | ab,ab | 8 km/h |
|
| a | b | ab,ab | 8 km/h |
|
||||||
|
@ -2,19 +2,23 @@ var util = require('util');
|
|||||||
var path = require('path');
|
var path = require('path');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var d3 = require('d3-queue');
|
var d3 = require('d3-queue');
|
||||||
var OSM = require('../support/build_osm');
|
var OSM = require('../lib/osm');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.Given(/^the profile "([^"]*)"$/, (profile, callback) => {
|
this.Given(/^the profile "([^"]*)"$/, (profile, callback) => {
|
||||||
this.setProfile(profile, callback);
|
this.profile = profile;
|
||||||
|
this.profileFile = path.join(this.PROFILES_PATH, this.profile + '.lua');
|
||||||
|
callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the extract extra arguments "(.*?)"$/, (args, callback) => {
|
this.Given(/^the extract extra arguments "(.*?)"$/, (args, callback) => {
|
||||||
this.setExtractArgs(args, callback);
|
this.extractArgs = this.expandOptions(args);
|
||||||
|
callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the contract extra arguments "(.*?)"$/, (args, callback) => {
|
this.Given(/^the contract extra arguments "(.*?)"$/, (args, callback) => {
|
||||||
this.setContractArgs(args, callback);
|
this.contractArgs = this.expandOptions(args);
|
||||||
|
callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^a grid size of ([0-9.]+) meters$/, (meters, callback) => {
|
this.Given(/^a grid size of ([0-9.]+) meters$/, (meters, callback) => {
|
||||||
@ -228,58 +232,46 @@ module.exports = function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the raster source$/, (data, callback) => {
|
this.Given(/^the raster source$/, (data, callback) => {
|
||||||
this.updateFingerprintExtract(data);
|
// TODO: Don't overwrite if it exists
|
||||||
fs.writeFile(path.resolve(this.TEST_FOLDER, 'rastersource.asc'), data, callback);
|
fs.writeFile(this.rasterCacheFile, data, callback);
|
||||||
|
// we need this to pass it to the profiles
|
||||||
|
this.environment = Object.assign({OSRM_RASTER_SOURCE: this.rasterCacheFile}, this.environment);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the speed file$/, (data, callback) => {
|
this.Given(/^the speed file$/, (data, callback) => {
|
||||||
this.updateFingerprintContract(data);
|
// TODO: Don't overwrite if it exists
|
||||||
fs.writeFile(path.resolve(this.TEST_FOLDER, 'speeds.csv'), data, callback);
|
fs.writeFile(this.speedsCacheFile, data, callback);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the turn penalty file$/, (data, callback) => {
|
this.Given(/^the turn penalty file$/, (data, callback) => {
|
||||||
this.updateFingerprintContract(data);
|
// TODO: Don't overwrite if it exists
|
||||||
fs.writeFile(path.resolve(this.TEST_FOLDER, 'penalties.csv'), data, callback);
|
fs.writeFile(this.penaltiesCacheFile, data, callback);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the data has been saved to disk$/, (callback) => {
|
this.Given(/^the data has been saved to disk$/, (callback) => {
|
||||||
try {
|
this.reprocess(callback);
|
||||||
this.reprocess(callback);
|
|
||||||
} catch(e) {
|
|
||||||
this.processError = e;
|
|
||||||
callback(e);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the data has been extracted$/, (callback) => {
|
this.Given(/^the data has been extracted$/, (callback) => {
|
||||||
this.osmData.populate(() => {
|
this.reprocess(callback);
|
||||||
this.writeAndExtract((err) => {
|
|
||||||
if (err) this.processError = err;
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the data has been contracted$/, (callback) => {
|
this.Given(/^the data has been contracted$/, (callback) => {
|
||||||
this.reprocess((err) => {
|
this.reprocess(callback);
|
||||||
if (err) this.processError = err;
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^osrm\-routed is stopped$/, (callback) => {
|
this.Given(/^osrm\-routed is stopped$/, (callback) => {
|
||||||
this.OSRMLoader.shutdown((err) => {
|
this.OSRMLoader.shutdown(callback);
|
||||||
if (err) this.processError = err;
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^data is loaded directly/, () => {
|
this.Given(/^data is loaded directly/, (callback) => {
|
||||||
this.loadMethod = 'directly';
|
this.osrmLoader.setLoadMethod('directly');
|
||||||
|
callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^data is loaded with datastore$/, () => {
|
this.Given(/^data is loaded with datastore$/, (callback) => {
|
||||||
this.loadMethod = 'datastore';
|
this.osrmLoader.setLoadMethod('datastore');
|
||||||
|
callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the HTTP method "([^"]*)"$/, (method, callback) => {
|
this.Given(/^the HTTP method "([^"]*)"$/, (method, callback) => {
|
||||||
|
@ -53,8 +53,6 @@ module.exports = function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var testRow = (row, ri, cb) => {
|
var testRow = (row, ri, cb) => {
|
||||||
var ok = true;
|
|
||||||
|
|
||||||
for (var k in result[ri]) {
|
for (var k in result[ri]) {
|
||||||
if (this.FuzzyMatch.match(result[ri][k], row[k])) {
|
if (this.FuzzyMatch.match(result[ri][k], row[k])) {
|
||||||
result[ri][k] = row[k];
|
result[ri][k] = row[k];
|
||||||
@ -62,15 +60,9 @@ module.exports = function () {
|
|||||||
result[ri][k] = '';
|
result[ri][k] = '';
|
||||||
} else {
|
} else {
|
||||||
result[ri][k] = result[ri][k].toString();
|
result[ri][k] = result[ri][k].toString();
|
||||||
ok = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
var failed = { attempt: 'distance_matrix', query: this.query, response: response };
|
|
||||||
this.logFail(row, result[ri], [failed]);
|
|
||||||
}
|
|
||||||
|
|
||||||
result[ri][''] = row[''];
|
result[ri][''] = row[''];
|
||||||
cb(null, result[ri]);
|
cb(null, result[ri]);
|
||||||
};
|
};
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
var util = require('util');
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
this.Before((scenario, callback) => {
|
|
||||||
this.scenarioTitle = scenario.getName();
|
|
||||||
|
|
||||||
this.loadMethod = this.DEFAULT_LOAD_METHOD;
|
|
||||||
this.queryParams = {};
|
|
||||||
var d = new Date();
|
|
||||||
this.scenarioTime = util.format('%d-%d-%dT%s:%s:%sZ', d.getFullYear(), d.getMonth()+1, d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds());
|
|
||||||
this.resetData();
|
|
||||||
this.hasLoggedPreprocessInfo = false;
|
|
||||||
this.hasLoggedScenarioInfo = false;
|
|
||||||
this.setGridSize(this.DEFAULT_GRID_SIZE);
|
|
||||||
this.setOrigin(this.DEFAULT_ORIGIN);
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
};
|
|
@ -157,7 +157,6 @@ module.exports = function () {
|
|||||||
} else {
|
} else {
|
||||||
got.matchings = encodedResult;
|
got.matchings = encodedResult;
|
||||||
row.matchings = extendedTarget;
|
row.matchings = extendedTarget;
|
||||||
this.logFail(row, got, { matching: { query: this.query, response: res } });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cb(null, got);
|
cb(null, got);
|
||||||
|
@ -22,24 +22,16 @@ module.exports = function () {
|
|||||||
|
|
||||||
var got = { in: row.in, out: row.out };
|
var got = { in: row.in, out: row.out };
|
||||||
|
|
||||||
var ok = true;
|
|
||||||
|
|
||||||
Object.keys(row).forEach((key) => {
|
Object.keys(row).forEach((key) => {
|
||||||
if (key === 'out') {
|
if (key === 'out') {
|
||||||
if (this.FuzzyMatch.matchLocation(coord, outNode)) {
|
if (this.FuzzyMatch.matchLocation(coord, outNode)) {
|
||||||
got[key] = row[key];
|
got[key] = row[key];
|
||||||
} else {
|
} else {
|
||||||
row[key] = util.format('%s [%d,%d]', row[key], outNode.lat, outNode.lon);
|
row[key] = util.format('%s [%d,%d]', row[key], outNode.lat, outNode.lon);
|
||||||
ok = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
var failed = { attempt: 'nearest', query: this.query, response: response };
|
|
||||||
this.logFail(row, got, [failed]);
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(null, got);
|
cb(null, got);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2,36 +2,58 @@ var assert = require('assert');
|
|||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.When(/^I run "osrm\-routed\s?(.*?)"$/, { timeout: this.TIMEOUT }, (options, callback) => {
|
this.resetOptionsOutput = () => {
|
||||||
this.runBin('osrm-routed', options, () => {
|
this.stdout = null;
|
||||||
callback();
|
this.stderr = null;
|
||||||
|
this.exitCode = null;
|
||||||
|
this.termSignal = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.runAndSafeOutput = (binary, options, callback) => {
|
||||||
|
this.runBin(binary, this.expandOptions(options), this.environment, (err, stdout, stderr) => {
|
||||||
|
this.stdout = stdout;
|
||||||
|
this.stderr = stderr;
|
||||||
|
this.exitCode = err && err.code || 0;
|
||||||
|
this.termSignal = err && err.signal || '';
|
||||||
|
callback(err);
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.When(/^I run "osrm\-routed\s?(.*?)"$/, { timeout: this.TIMEOUT }, (options, callback) => {
|
||||||
|
this.runAndSafeOutput('osrm-routed', options, callback);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.When(/^I run "osrm\-extract\s?(.*?)"$/, (options, callback) => {
|
this.When(/^I run "osrm\-extract\s?(.*?)"$/, (options, callback) => {
|
||||||
this.runBin('osrm-extract', options, () => {
|
this.runAndSafeOutput('osrm-extract', options, callback);
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.When(/^I run "osrm\-contract\s?(.*?)"$/, (options, callback) => {
|
this.When(/^I run "osrm\-contract\s?(.*?)"$/, (options, callback) => {
|
||||||
this.runBin('osrm-contract', options, () => {
|
this.runAndSafeOutput('osrm-contract', options, callback);
|
||||||
callback();
|
});
|
||||||
});
|
|
||||||
|
this.When(/^I try to run "osrm\-routed\s?(.*?)"$/, (options, callback) => {
|
||||||
|
this.runAndSafeOutput('osrm-routed', options, () => { callback(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
this.When(/^I try to run "osrm\-extract\s?(.*?)"$/, (options, callback) => {
|
||||||
|
this.runAndSafeOutput('osrm-extract', options, () => { callback(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
this.When(/^I try to run "osrm\-contract\s?(.*?)"$/, (options, callback) => {
|
||||||
|
this.runAndSafeOutput('osrm-contract', options, () => { callback(); });
|
||||||
});
|
});
|
||||||
|
|
||||||
this.When(/^I run "osrm\-datastore\s?(.*?)"$/, (options, callback) => {
|
this.When(/^I run "osrm\-datastore\s?(.*?)"$/, (options, callback) => {
|
||||||
this.runBin('osrm-datastore', options, () => {
|
this.runAndSafeOutput('osrm-datastore', options, callback);
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Then(/^it should exit with code (\d+)$/, (code) => {
|
this.Then(/^it should exit successfully$/, () => {
|
||||||
assert.equal(this.exitCode, parseInt(code));
|
assert.equal(this.exitCode, 0);
|
||||||
|
assert.equal(this.termSignal, '');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Then(/^it should exit with code not (\d+)$/, (code) => {
|
this.Then(/^it should exit with an error$/, () => {
|
||||||
assert.notEqual(this.exitCode, parseInt(code));
|
assert.ok(this.exitCode !== 0 || this.termSignal);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Then(/^stdout should contain "(.*?)"$/, (str) => {
|
this.Then(/^stdout should contain "(.*?)"$/, (str) => {
|
||||||
@ -65,7 +87,7 @@ module.exports = function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.Then(/^datasource names should contain "(.+)"$/, (expectedData) => {
|
this.Then(/^datasource names should contain "(.+)"$/, (expectedData) => {
|
||||||
var actualData = fs.readFileSync(this.osmData.extractedFile + '.osrm.datasource_names', {encoding:'UTF-8'}).trim().split('\n').join(',');
|
var actualData = fs.readFileSync(this.processedCacheFile + '.datasource_names', {encoding:'UTF-8'}).trim().split('\n').join(',');
|
||||||
assert.equal(actualData, expectedData);
|
assert.equal(actualData, expectedData);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ module.exports = function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.Then(/^"([^"]*)" should return code (\d+)$/, (binary, code) => {
|
this.Then(/^"([^"]*)" should return code (\d+)$/, (binary, code) => {
|
||||||
assert.ok(this.processError instanceof this.OSRMError);
|
assert.ok(this.processError instanceof Error);
|
||||||
assert.equal(this.processError.process, binary);
|
assert.equal(this.processError.process, binary);
|
||||||
assert.equal(parseInt(this.processError.code), parseInt(code));
|
assert.equal(parseInt(this.processError.code), parseInt(code));
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,7 @@ module.exports = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.reprocessAndLoadData((e) => {
|
this.reprocessAndLoadData((e) => {
|
||||||
if (e) callback(e);
|
if (e) return callback(e);
|
||||||
var testRow = (row, i, cb) => {
|
var testRow = (row, i, cb) => {
|
||||||
var outputRow = row;
|
var outputRow = row;
|
||||||
|
|
||||||
@ -41,10 +41,6 @@ module.exports = function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (outputRow != row) {
|
|
||||||
this.logFail(row, outputRow, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(null, outputRow);
|
cb(null, outputRow);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -116,7 +112,7 @@ module.exports = function () {
|
|||||||
sq.defer(parseRes, key);
|
sq.defer(parseRes, key);
|
||||||
});
|
});
|
||||||
|
|
||||||
sq.awaitAll(() => { cb(null, result); });
|
sq.awaitAll((err) => { cb(err, result); });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -85,23 +85,14 @@ module.exports = function () {
|
|||||||
} else {
|
} else {
|
||||||
got.trips = encodedResult;
|
got.trips = encodedResult;
|
||||||
got.trips = extendedTarget;
|
got.trips = extendedTarget;
|
||||||
this.logFail(row, got, { trip: { query: this.query, response: res }});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = true;
|
|
||||||
|
|
||||||
for (var key in row) {
|
for (var key in row) {
|
||||||
if (this.FuzzyMatch.match(got[key], row[key])) {
|
if (this.FuzzyMatch.match(got[key], row[key])) {
|
||||||
got[key] = row[key];
|
got[key] = row[key];
|
||||||
} else {
|
|
||||||
ok = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
this.logFail(row, got, { trip: { query: this.query, response: res }});
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(null, got);
|
cb(null, got);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
184
features/support/cache.js
Normal file
184
features/support/cache.js
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const d3 = require('d3-queue');
|
||||||
|
const fs = require('fs');
|
||||||
|
const util = require('util');
|
||||||
|
const path = require('path');
|
||||||
|
const mkdirp = require('mkdirp');
|
||||||
|
const hash = require('../lib/hash');
|
||||||
|
const rimraf = require('rimraf');
|
||||||
|
|
||||||
|
module.exports = function() {
|
||||||
|
this.initializeCache = (callback) => {
|
||||||
|
this.getOSRMHash((err, osrmHash) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
this.osrmHash = osrmHash;
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// computes all paths for every feature
|
||||||
|
this.setupFeatures = (features, callback) => {
|
||||||
|
this.featureIDs = {};
|
||||||
|
this.featureCacheDirectories = {};
|
||||||
|
this.featureProcessedCacheDirectories = {};
|
||||||
|
let queue = d3.queue();
|
||||||
|
|
||||||
|
function initializeFeature(feature, callback) {
|
||||||
|
let uri = feature.getUri();
|
||||||
|
|
||||||
|
// setup cache for feature data
|
||||||
|
hash.hashOfFile(uri, (err, hash) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
|
// shorten uri to be realtive to 'features/'
|
||||||
|
let featurePath = path.relative(path.resolve('./features'), uri);
|
||||||
|
// bicycle/bollards/{HASH}/
|
||||||
|
let featureID = path.join(featurePath, hash);
|
||||||
|
let featureCacheDirectory = this.getFeatureCacheDirectory(featureID);
|
||||||
|
let featureProcessedCacheDirectory = this.getFeatureProcessedCacheDirectory(featureCacheDirectory, this.osrmHash);
|
||||||
|
this.featureIDs[uri] = featureID;
|
||||||
|
this.featureCacheDirectories[uri] = featureCacheDirectory;
|
||||||
|
this.featureProcessedCacheDirectories[uri] = featureProcessedCacheDirectory;
|
||||||
|
|
||||||
|
d3.queue(1)
|
||||||
|
.defer(mkdirp, featureProcessedCacheDirectory)
|
||||||
|
.defer(this.cleanupFeatureCache.bind(this), featureCacheDirectory, hash)
|
||||||
|
.defer(this.cleanupProcessedFeatureCache.bind(this), featureProcessedCacheDirectory, this.osrmHash)
|
||||||
|
.awaitAll(callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < features.length; ++i) {
|
||||||
|
queue.defer(initializeFeature.bind(this), features[i]);
|
||||||
|
}
|
||||||
|
queue.awaitAll(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.cleanupProcessedFeatureCache = (directory, osrmHash, callback) => {
|
||||||
|
let parentPath = path.resolve(path.join(directory, '..'));
|
||||||
|
fs.readdir(parentPath, (err, files) => {
|
||||||
|
let q = d3.queue();
|
||||||
|
function runStats(path, callback) {
|
||||||
|
fs.stat(path, (err, stat) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
callback(null, {file: path, stat: stat});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
files.map(f => { q.defer(runStats, path.join(parentPath, f)); });
|
||||||
|
q.awaitAll((err, results) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
let q = d3.queue();
|
||||||
|
results.forEach(r => {
|
||||||
|
if (r.stat.isDirectory() && r.file.search(osrmHash) < 0) {
|
||||||
|
q.defer(rimraf, r.file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
q.awaitAll(callback);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.cleanupFeatureCache = (directory, featureHash, callback) => {
|
||||||
|
let parentPath = path.resolve(path.join(directory, '..'));
|
||||||
|
fs.readdir(parentPath, (err, files) => {
|
||||||
|
let q = d3.queue();
|
||||||
|
files.filter(name => { return name !== featureHash;})
|
||||||
|
.map((f) => { q.defer(rimraf, path.join(parentPath, f)); });
|
||||||
|
q.awaitAll(callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setupFeatureCache = (feature) => {
|
||||||
|
let uri = feature.getUri();
|
||||||
|
this.featureID = this.featureIDs[uri];
|
||||||
|
this.featureCacheDirectory = this.featureCacheDirectories[uri];
|
||||||
|
this.featureProcessedCacheDirectory = this.featureProcessedCacheDirectories[uri];
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setupScenarioCache = (scenarioID) => {
|
||||||
|
this.scenarioCacheFile = this.getScenarioCacheFile(this.featureCacheDirectory, scenarioID);
|
||||||
|
this.processedCacheFile = this.getProcessedCacheFile(this.featureProcessedCacheDirectory, scenarioID);
|
||||||
|
this.inputCacheFile = this.getInputCacheFile(this.featureProcessedCacheDirectory, scenarioID);
|
||||||
|
this.rasterCacheFile = this.getRasterCacheFile(this.featureProcessedCacheDirectory, scenarioID);
|
||||||
|
this.speedsCacheFile = this.getSpeedsCacheFile(this.featureProcessedCacheDirectory, scenarioID);
|
||||||
|
this.penaltiesCacheFile = this.getPenaltiesCacheFile(this.featureProcessedCacheDirectory, scenarioID);
|
||||||
|
};
|
||||||
|
|
||||||
|
// returns a hash of all OSRM code side dependencies
|
||||||
|
this.getOSRMHash = (callback) => {
|
||||||
|
let dependencies = [
|
||||||
|
this.OSRM_EXTRACT_PATH,
|
||||||
|
this.OSRM_CONTRACT_PATH,
|
||||||
|
this.LIB_OSRM_EXTRACT_PATH,
|
||||||
|
this.LIB_OSRM_CONTRACT_PATH
|
||||||
|
];
|
||||||
|
|
||||||
|
var addLuaFiles = (directory, callback) => {
|
||||||
|
fs.readdir(path.normalize(directory), (err, files) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
|
var luaFiles = files.filter(f => !!f.match(/\.lua$/)).map(f => path.normalize(directory + '/' + f));
|
||||||
|
Array.prototype.push.apply(dependencies, luaFiles);
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Note: we need a serialized queue here to ensure that the order of the files
|
||||||
|
// passed is stable. Otherwise the hash will not be stable
|
||||||
|
d3.queue(1)
|
||||||
|
.defer(addLuaFiles, this.PROFILES_PATH)
|
||||||
|
.defer(addLuaFiles, this.PROFILES_PATH + '/lib')
|
||||||
|
.awaitAll(hash.hashOfFiles.bind(hash, dependencies, callback));
|
||||||
|
};
|
||||||
|
|
||||||
|
// test/cache/bicycle/bollards/{HASH}/
|
||||||
|
this.getFeatureCacheDirectory = (featureID) => {
|
||||||
|
return path.join(this.CACHE_PATH, featureID);
|
||||||
|
};
|
||||||
|
|
||||||
|
// converts the scenario titles in file prefixes
|
||||||
|
this.getScenarioID = (scenario) => {
|
||||||
|
let name = scenario.getName().toLowerCase().replace(/[\/\-'=,\(\)]/g, '').replace(/\s/g, '_').replace(/__/g, '_').replace(/\.\./g, '.');
|
||||||
|
return util.format('%d_%s', scenario.getLine(), name);
|
||||||
|
};
|
||||||
|
|
||||||
|
// test/cache/{feature_path}/{feature_hash}/{scenario}_raster.asc
|
||||||
|
this.getRasterCacheFile = (featureCacheDirectory, scenarioID) => {
|
||||||
|
return path.join(featureCacheDirectory, scenarioID) + '_raster.asc';
|
||||||
|
};
|
||||||
|
|
||||||
|
// test/cache/{feature_path}/{feature_hash}/{scenario}_speeds.csv
|
||||||
|
this.getSpeedsCacheFile = (featureCacheDirectory, scenarioID) => {
|
||||||
|
return path.join(featureCacheDirectory, scenarioID) + '_speeds.csv';
|
||||||
|
};
|
||||||
|
|
||||||
|
// test/cache/{feature_path}/{feature_hash}/{scenario}_penalties.csv
|
||||||
|
this.getPenaltiesCacheFile = (featureCacheDirectory, scenarioID) => {
|
||||||
|
return path.join(featureCacheDirectory, scenarioID) + '_penalties.csv';
|
||||||
|
};
|
||||||
|
|
||||||
|
// test/cache/{feature_path}/{feature_hash}/{scenario}.osm
|
||||||
|
this.getScenarioCacheFile = (featureCacheDirectory, scenarioID) => {
|
||||||
|
return path.join(featureCacheDirectory, scenarioID) + '.osm';
|
||||||
|
};
|
||||||
|
|
||||||
|
// test/cache/{feature_path}/{feature_hash}/{osrm_hash}/
|
||||||
|
this.getFeatureProcessedCacheDirectory = (featureCacheDirectory, osrmHash) => {
|
||||||
|
return path.join(featureCacheDirectory, osrmHash);
|
||||||
|
};
|
||||||
|
|
||||||
|
// test/cache/{feature_path}/{feature_hash}/{osrm_hash}/{scenario}.osrm
|
||||||
|
this.getProcessedCacheFile = (featureProcessedCacheDirectory, scenarioID) => {
|
||||||
|
return path.join(featureProcessedCacheDirectory, scenarioID) + '.osrm';
|
||||||
|
};
|
||||||
|
|
||||||
|
// test/cache/{feature_path}/{feature_hash}/{osrm_hash}/{scenario}.osm
|
||||||
|
this.getInputCacheFile = (featureProcessedCacheDirectory, scenarioID) => {
|
||||||
|
return path.join(featureProcessedCacheDirectory, scenarioID) + '.osm';
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
@ -1,127 +0,0 @@
|
|||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
var util = require('util');
|
|
||||||
var d3 = require('d3-queue');
|
|
||||||
var OSM = require('./build_osm');
|
|
||||||
var classes = require('./data_classes');
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
this.initializeOptions = (callback) => {
|
|
||||||
this.profile = this.profile || this.DEFAULT_SPEEDPROFILE;
|
|
||||||
|
|
||||||
this.OSMDB = this.OSMDB || new OSM.DB();
|
|
||||||
|
|
||||||
this.nameNodeHash = this.nameNodeHash || {};
|
|
||||||
|
|
||||||
this.locationHash = this.locationHash || {};
|
|
||||||
|
|
||||||
this.nameWayHash = this.nameWayHash || {};
|
|
||||||
|
|
||||||
this.osmData = new classes.osmData(this);
|
|
||||||
|
|
||||||
this.OSRMLoader = this._OSRMLoader();
|
|
||||||
|
|
||||||
this.PREPROCESS_LOG_FILE = path.resolve(this.TEST_FOLDER, 'preprocessing.log');
|
|
||||||
|
|
||||||
this.LOG_FILE = path.resolve(this.TEST_FOLDER, 'fail.log');
|
|
||||||
|
|
||||||
this.HOST = 'http://127.0.0.1:' + this.OSRM_PORT;
|
|
||||||
|
|
||||||
this.DESTINATION_REACHED = 15; // OSRM instruction code
|
|
||||||
|
|
||||||
this.shortcutsHash = this.shortcutsHash || {};
|
|
||||||
|
|
||||||
var hashLuaLib = (cb) => {
|
|
||||||
fs.readdir(path.normalize(this.PROFILES_PATH + '/lib/'), (err, files) => {
|
|
||||||
if (err) cb(err);
|
|
||||||
var luaFiles = files.filter(f => !!f.match(/\.lua$/)).map(f => path.normalize(this.PROFILES_PATH + '/lib/' + f));
|
|
||||||
this.hashOfFiles(luaFiles, hash => {
|
|
||||||
this.luaLibHash = hash;
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var hashProfile = (cb) => {
|
|
||||||
this.hashProfile((hash) => {
|
|
||||||
this.profileHash = hash;
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var hashExtract = (cb) => {
|
|
||||||
var files = [ util.format('%s/osrm-extract%s', this.BIN_PATH, this.EXE),
|
|
||||||
util.format('%s/libosrm_extract%s', this.BIN_PATH, this.LIB) ];
|
|
||||||
this.hashOfFiles(files, (hash) => {
|
|
||||||
this.binExtractHash = hash;
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var hashContract = (cb) => {
|
|
||||||
var files = [ util.format('%s/osrm-contract%s', this.BIN_PATH, this.EXE),
|
|
||||||
util.format('%s/libosrm_contract%s', this.BIN_PATH, this.LIB) ];
|
|
||||||
this.hashOfFiles(files, (hash) => {
|
|
||||||
this.binContractHash = hash;
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var hashRouted = (cb) => {
|
|
||||||
var files = [ util.format('%s/osrm-routed%s', this.BIN_PATH, this.EXE),
|
|
||||||
util.format('%s/libosrm%s', this.BIN_PATH, this.LIB) ];
|
|
||||||
this.hashOfFiles(files, (hash) => {
|
|
||||||
this.binRoutedHash = hash;
|
|
||||||
this.fingerprintRoute = this.hashString(this.binRoutedHash);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
d3.queue()
|
|
||||||
.defer(hashLuaLib)
|
|
||||||
.defer(hashProfile)
|
|
||||||
.defer(hashExtract)
|
|
||||||
.defer(hashContract)
|
|
||||||
.defer(hashRouted)
|
|
||||||
.awaitAll(() => {
|
|
||||||
this.AfterConfiguration(() => {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.updateFingerprintExtract = (str) => {
|
|
||||||
this.fingerprintExtract = this.hashString([this.fingerprintExtract, str].join('-'));
|
|
||||||
};
|
|
||||||
|
|
||||||
this.updateFingerprintContract = (str) => {
|
|
||||||
this.fingerprintContract = this.hashString([this.fingerprintContract, str].join('-'));
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setProfile = (profile, cb) => {
|
|
||||||
var lastProfile = this.profile;
|
|
||||||
if (profile !== lastProfile) {
|
|
||||||
this.profile = profile;
|
|
||||||
this.hashProfile((hash) => {
|
|
||||||
this.profileHash = hash;
|
|
||||||
this.updateFingerprintExtract(this.profileHash);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.updateFingerprintExtract(this.profileHash);
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setExtractArgs = (args, callback) => {
|
|
||||||
this.extractArgs = args;
|
|
||||||
this.updateFingerprintExtract(args);
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setContractArgs = (args, callback) => {
|
|
||||||
this.contractArgs = args;
|
|
||||||
this.updateFingerprintContract(args);
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,11 +1,14 @@
|
|||||||
var fs = require('fs');
|
'use strict';
|
||||||
var path = require('path');
|
|
||||||
var util = require('util');
|
|
||||||
var exec = require('child_process').exec;
|
|
||||||
var d3 = require('d3-queue');
|
|
||||||
|
|
||||||
var OSM = require('./build_osm');
|
const fs = require('fs');
|
||||||
var classes = require('./data_classes');
|
const util = require('util');
|
||||||
|
const d3 = require('d3-queue');
|
||||||
|
|
||||||
|
const OSM = require('../lib/osm');
|
||||||
|
const classes = require('./data_classes');
|
||||||
|
const tableDiff = require('../lib/table_diff');
|
||||||
|
const ensureDecimal = require('../lib/utils').ensureDecimal;
|
||||||
|
const errorReason = require('../lib/utils').errorReason;
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.setGridSize = (meters) => {
|
this.setGridSize = (meters) => {
|
||||||
@ -94,13 +97,8 @@ module.exports = function () {
|
|||||||
q.awaitAll(callback);
|
q.awaitAll(callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.ensureDecimal = (i) => {
|
|
||||||
if (parseInt(i) === i) return i.toFixed(1);
|
|
||||||
else return i;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.tableCoordToLonLat = (ci, ri) => {
|
this.tableCoordToLonLat = (ci, ri) => {
|
||||||
return [this.origin[0] + ci * this.zoom, this.origin[1] - ri * this.zoom].map(this.ensureDecimal);
|
return [this.origin[0] + ci * this.zoom, this.origin[1] - ri * this.zoom].map(ensureDecimal);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addOSMNode = (name, lon, lat, id) => {
|
this.addOSMNode = (name, lon, lat, id) => {
|
||||||
@ -132,10 +130,6 @@ module.exports = function () {
|
|||||||
return this.nameWayHash[s.toString()] || this.nameWayHash[s.toString().split('').reverse().join('')];
|
return this.nameWayHash[s.toString()] || this.nameWayHash[s.toString().split('').reverse().join('')];
|
||||||
};
|
};
|
||||||
|
|
||||||
this.resetData = () => {
|
|
||||||
this.resetOSM();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.makeOSMId = () => {
|
this.makeOSMId = () => {
|
||||||
this.osmID = this.osmID + 1;
|
this.osmID = this.osmID + 1;
|
||||||
return this.osmID;
|
return this.osmID;
|
||||||
@ -143,206 +137,88 @@ module.exports = function () {
|
|||||||
|
|
||||||
this.resetOSM = () => {
|
this.resetOSM = () => {
|
||||||
this.OSMDB.clear();
|
this.OSMDB.clear();
|
||||||
this.osmData.reset();
|
|
||||||
this.nameNodeHash = {};
|
this.nameNodeHash = {};
|
||||||
this.locationHash = {};
|
this.locationHash = {};
|
||||||
|
this.shortcutsHash = {};
|
||||||
this.nameWayHash = {};
|
this.nameWayHash = {};
|
||||||
this.osmID = 0;
|
this.osmID = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.writeOSM = (callback) => {
|
this.writeOSM = (callback) => {
|
||||||
fs.exists(this.DATA_FOLDER, (exists) => {
|
fs.exists(this.scenarioCacheFile, (exists) => {
|
||||||
var mkDirFn = exists ? (cb) => { cb(); } : fs.mkdir.bind(fs.mkdir, this.DATA_FOLDER);
|
if (exists) callback();
|
||||||
mkDirFn((err) => {
|
else {
|
||||||
if (err) return callback(err);
|
this.OSMDB.toXML((xml) => {
|
||||||
var osmPath = path.resolve(this.DATA_FOLDER, util.format('%s.osm', this.osmData.osmFile));
|
fs.writeFile(this.scenarioCacheFile, xml, callback);
|
||||||
fs.exists(osmPath, (exists) => {
|
|
||||||
if (!exists) fs.writeFile(osmPath, this.osmData.str, callback);
|
|
||||||
else callback();
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.isExtracted = (callback) => {
|
|
||||||
fs.exists(util.format('%s.osrm', this.osmData.extractedFile), (core) => {
|
|
||||||
if (!core) return callback(false);
|
|
||||||
fs.exists(util.format('%s.osrm.names', this.osmData.extractedFile), (names) => {
|
|
||||||
if (!names) return callback(false);
|
|
||||||
fs.exists(util.format('%s.osrm.restrictions', this.osmData.extractedFile), (restrictions) => {
|
|
||||||
return callback(restrictions);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.isContracted = (callback) => {
|
|
||||||
fs.exists(util.format('%s.osrm.hsgr', this.osmData.contractedFile), callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.writeTimestamp = (callback) => {
|
|
||||||
fs.writeFile(util.format('%s.osrm.timestamp', this.osmData.contractedFile), this.OSM_TIMESTAMP, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.writeInputData = (callback) => {
|
|
||||||
this.writeOSM((err) => {
|
|
||||||
if (err) return callback(err);
|
|
||||||
this.writeTimestamp(callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.extractData = (callback) => {
|
|
||||||
this.logPreprocessInfo();
|
|
||||||
this.log(util.format('== Extracting %s.osm...', this.osmData.osmFile), 'preprocess');
|
|
||||||
var cmd = util.format('%s/osrm-extract %s.osm %s --profile %s/%s.lua >>%s 2>&1',
|
|
||||||
this.BIN_PATH, this.osmData.osmFile, this.extractArgs || '', this.PROFILES_PATH, this.profile, this.PREPROCESS_LOG_FILE);
|
|
||||||
this.log(cmd);
|
|
||||||
process.chdir(this.TEST_FOLDER);
|
|
||||||
exec(cmd, (err) => {
|
|
||||||
if (err) {
|
|
||||||
this.log(util.format('*** Exited with code %d', err.code), 'preprocess');
|
|
||||||
process.chdir('../');
|
|
||||||
return callback(this.ExtractError(err.code, util.format('osrm-extract exited with code %d', err.code)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var q = d3.queue();
|
|
||||||
|
|
||||||
var rename = (file, cb) => {
|
|
||||||
this.log(util.format('Renaming %s.%s to %s.%s', this.osmData.osmFile, file, this.osmData.extractedFile, file), 'preprocess');
|
|
||||||
fs.rename([this.osmData.osmFile, file].join('.'), [this.osmData.extractedFile, file].join('.'), (err) => {
|
|
||||||
if (err) return cb(this.FileError(null, 'failed to rename data file after extracting'));
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var renameIfExists = (file, cb) => {
|
|
||||||
fs.stat([this.osmData.osmFile, file].join('.'), (doesNotExistErr, exists) => {
|
|
||||||
if (exists) rename(file, cb);
|
|
||||||
else cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
['osrm', 'osrm.ebg', 'osrm.edges', 'osrm.enw', 'osrm.fileIndex', 'osrm.geometry', 'osrm.icd',
|
|
||||||
'osrm.names', 'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions', 'osrm.tld', 'osrm.tls'].forEach(file => {
|
|
||||||
q.defer(rename, file);
|
|
||||||
});
|
|
||||||
|
|
||||||
['osrm.edge_penalties', 'osrm.edge_segment_lookup'].forEach(file => {
|
|
||||||
q.defer(renameIfExists, file);
|
|
||||||
});
|
|
||||||
|
|
||||||
q.awaitAll((err) => {
|
|
||||||
this.log('Finished extracting ' + this.osmData.extractedFile, 'preprocess');
|
|
||||||
process.chdir('../');
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.contractData = (callback) => {
|
this.linkOSM = (callback) => {
|
||||||
this.logPreprocessInfo();
|
fs.exists(this.inputCacheFile, (exists) => {
|
||||||
this.log(util.format('== Contracting %s.osm...', this.osmData.extractedFile), 'preprocess');
|
if (exists) callback();
|
||||||
var cmd = util.format('%s/osrm-contract %s %s.osrm >>%s 2>&1',
|
else {
|
||||||
this.BIN_PATH, this.contractArgs || '', this.osmData.extractedFile, this.PREPROCESS_LOG_FILE);
|
fs.link(this.scenarioCacheFile, this.inputCacheFile, callback);
|
||||||
this.log(cmd);
|
|
||||||
process.chdir(this.TEST_FOLDER);
|
|
||||||
exec(cmd, (err) => {
|
|
||||||
if (err) {
|
|
||||||
this.log(util.format('*** Exited with code %d', err.code), 'preprocess');
|
|
||||||
process.chdir('../');
|
|
||||||
return callback(this.ContractError(err.code, util.format('osrm-contract exited with code %d', err.code)));
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var rename = (file, cb) => {
|
this.extractData = (p, callback) => {
|
||||||
this.log(util.format('Renaming %s.%s to %s.%s', this.osmData.extractedFile, file, this.osmData.contractedFile, file), 'preprocess');
|
let stamp = p.processedCacheFile + '.extract';
|
||||||
fs.rename([this.osmData.extractedFile, file].join('.'), [this.osmData.contractedFile, file].join('.'), (err) => {
|
fs.exists(stamp, (exists) => {
|
||||||
if (err) return cb(this.FileError(null, 'failed to rename data file after contracting.'));
|
if (exists) return callback();
|
||||||
cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var renameIfExists = (file, cb) => {
|
this.runBin('osrm-extract', util.format('%s --profile %s %s', p.extractArgs, p.profileFile, p.inputCacheFile), p.environment, (err) => {
|
||||||
fs.stat([this.osmData.extractedFile, file].join('.'), (doesNotExistErr, exists) => {
|
if (err) {
|
||||||
if (exists) rename(file, cb);
|
return callback(new Error(util.format('osrm-extract %s: %s', errorReason(err), err.cmd)));
|
||||||
else cb();
|
}
|
||||||
});
|
fs.writeFile(stamp, 'ok', callback);
|
||||||
};
|
|
||||||
|
|
||||||
var copy = (file, cb) => {
|
|
||||||
this.log(util.format('Copying %s.%s to %s.%s', this.osmData.extractedFile, file, this.osmData.contractedFile, file), 'preprocess');
|
|
||||||
fs.createReadStream([this.osmData.extractedFile, file].join('.'))
|
|
||||||
.pipe(fs.createWriteStream([this.osmData.contractedFile, file].join('.'))
|
|
||||||
.on('finish', cb)
|
|
||||||
)
|
|
||||||
.on('error', () => {
|
|
||||||
return cb(this.FileError(null, 'failed to copy data after contracting.'));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var q = d3.queue();
|
|
||||||
|
|
||||||
['osrm', 'osrm.core', 'osrm.datasource_indexes', 'osrm.datasource_names', 'osrm.ebg','osrm.edges',
|
|
||||||
'osrm.enw', 'osrm.fileIndex', 'osrm.geometry', 'osrm.hsgr', 'osrm.icd','osrm.level', 'osrm.names',
|
|
||||||
'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions', 'osrm.tld', 'osrm.tls'].forEach((file) => {
|
|
||||||
q.defer(rename, file);
|
|
||||||
});
|
|
||||||
|
|
||||||
['osrm.edge_penalties', 'osrm.edge_segment_lookup'].forEach(file => {
|
|
||||||
q.defer(renameIfExists, file);
|
|
||||||
});
|
|
||||||
|
|
||||||
[].forEach((file) => {
|
|
||||||
q.defer(copy, file);
|
|
||||||
});
|
|
||||||
|
|
||||||
q.awaitAll((err) => {
|
|
||||||
this.log('Finished contracting ' + this.osmData.contractedFile, 'preprocess');
|
|
||||||
process.chdir('../');
|
|
||||||
callback(err);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var noop = (cb) => cb();
|
this.contractData = (p, callback) => {
|
||||||
|
let stamp = p.processedCacheFile + '.contract';
|
||||||
|
fs.exists(stamp, (exists) => {
|
||||||
|
if (exists) return callback();
|
||||||
|
|
||||||
|
this.runBin('osrm-contract', util.format('%s %s', p.contractArgs, p.processedCacheFile), p.environment, (err) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(new Error(util.format('osrm-contract %s: %s', errorReason(err), err)));
|
||||||
|
}
|
||||||
|
fs.writeFile(stamp, 'ok', callback);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.extractAndContract = (callback) => {
|
||||||
|
// a shallow copy of scenario parameters to avoid data inconsistency
|
||||||
|
// if a cucumber timeout occurs during deferred jobs
|
||||||
|
let p = {extractArgs: this.extractArgs, contractArgs: this.contractArgs,
|
||||||
|
profileFile: this.profileFile, inputCacheFile: this.inputCacheFile,
|
||||||
|
processedCacheFile: this.processedCacheFile, environment: this.environment};
|
||||||
|
let queue = d3.queue(1);
|
||||||
|
queue.defer(this.extractData.bind(this), p);
|
||||||
|
queue.defer(this.contractData.bind(this), p);
|
||||||
|
queue.awaitAll(callback);
|
||||||
|
};
|
||||||
|
|
||||||
this.reprocess = (callback) => {
|
this.reprocess = (callback) => {
|
||||||
this.osmData.populate(() => {
|
let queue = d3.queue(1);
|
||||||
this.isContracted((isContracted) => {
|
queue.defer(this.writeOSM.bind(this));
|
||||||
if (!isContracted) {
|
queue.defer(this.linkOSM.bind(this));
|
||||||
this.writeAndExtract((e) => {
|
queue.defer(this.extractAndContract.bind(this));
|
||||||
if (e) return callback(e);
|
queue.awaitAll(callback);
|
||||||
this.contractData((e) => {
|
|
||||||
if (e) return callback(e);
|
|
||||||
this.logPreprocessDone();
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.log('Already contracted ' + this.osmData.contractedFile, 'preprocess');
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.writeAndExtract = (callback) => {
|
|
||||||
this.writeInputData((e) => {
|
|
||||||
if (e) return callback(e);
|
|
||||||
this.isExtracted((isExtracted) => {
|
|
||||||
var extractFn = isExtracted ? noop : this.extractData;
|
|
||||||
if (isExtracted) this.log('Already extracted ' + this.osmData.extractedFile, 'preprocess');
|
|
||||||
extractFn((e) => {
|
|
||||||
callback(e);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.reprocessAndLoadData = (callback) => {
|
this.reprocessAndLoadData = (callback) => {
|
||||||
this.reprocess((e) => {
|
let queue = d3.queue(1);
|
||||||
if (e) return callback(e);
|
queue.defer(this.writeOSM.bind(this));
|
||||||
this.OSRMLoader.load(util.format('%s.osrm', this.osmData.contractedFile), callback);
|
queue.defer(this.linkOSM.bind(this));
|
||||||
});
|
queue.defer(this.extractAndContract.bind(this));
|
||||||
|
queue.defer(this.osrmLoader.load.bind(this.osrmLoader), this.processedCacheFile);
|
||||||
|
queue.awaitAll(callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.processRowsAndDiff = (table, fn, callback) => {
|
this.processRowsAndDiff = (table, fn, callback) => {
|
||||||
@ -352,7 +228,9 @@ module.exports = function () {
|
|||||||
|
|
||||||
q.awaitAll((err, actual) => {
|
q.awaitAll((err, actual) => {
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
this.diffTables(table, actual, {}, callback);
|
let diff = tableDiff(table, actual);
|
||||||
|
if (diff) callback(new Error(diff));
|
||||||
|
else callback();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var util = require('util');
|
const util = require('util');
|
||||||
var path = require('path');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Location: class {
|
Location: class {
|
||||||
@ -11,43 +10,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
osmData: class {
|
|
||||||
constructor (scope) {
|
|
||||||
this.scope = scope;
|
|
||||||
this.str = null;
|
|
||||||
this.hash = null;
|
|
||||||
this.fingerprintOSM = null;
|
|
||||||
this.osmFile = null;
|
|
||||||
this.extractedFile = null;
|
|
||||||
this.contractedFile = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
populate (callback) {
|
|
||||||
this.scope.OSMDB.toXML((str) => {
|
|
||||||
this.str = str;
|
|
||||||
|
|
||||||
this.hash = this.scope.hashString(str);
|
|
||||||
this.fingerprintOSM = this.scope.hashString(this.hash);
|
|
||||||
|
|
||||||
this.osmFile = path.resolve(this.scope.DATA_FOLDER, this.fingerprintOSM);
|
|
||||||
|
|
||||||
this.extractedFile = path.resolve([this.osmFile, this.scope.fingerprintExtract].join('_'));
|
|
||||||
this.contractedFile = path.resolve([this.osmFile, this.scope.fingerprintExtract, this.scope.fingerprintContract].join('_'));
|
|
||||||
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
reset () {
|
|
||||||
this.str = null;
|
|
||||||
this.hash = null;
|
|
||||||
this.fingerprintOSM = null;
|
|
||||||
this.osmFile = null;
|
|
||||||
this.extractedFile = null;
|
|
||||||
this.contractedFile = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
FuzzyMatch: class {
|
FuzzyMatch: class {
|
||||||
match (got, want) {
|
match (got, want) {
|
||||||
var matchPercent = want.match(/(.*)\s+~(.+)%$/),
|
var matchPercent = want.match(/(.*)\s+~(.+)%$/),
|
||||||
|
@ -1,32 +1,46 @@
|
|||||||
var path = require('path');
|
'use strict';
|
||||||
var util = require('util');
|
|
||||||
var fs = require('fs');
|
|
||||||
var exec = require('child_process').exec;
|
|
||||||
var d3 = require('d3-queue');
|
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const util = require('util');
|
||||||
|
const fs = require('fs');
|
||||||
|
const d3 = require('d3-queue');
|
||||||
|
const child_process = require('child_process');
|
||||||
|
const tryConnect = require('../lib/try_connect');
|
||||||
|
|
||||||
|
// Sets up all constants that are valid for all features
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.initializeEnv = (callback) => {
|
this.initializeEnv = (callback) => {
|
||||||
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
|
|
||||||
this.TIMEOUT = process.env.CUCUMBER_TIMEOUT && parseInt(process.env.CUCUMBER_TIMEOUT) || 5000;
|
this.TIMEOUT = process.env.CUCUMBER_TIMEOUT && parseInt(process.env.CUCUMBER_TIMEOUT) || 5000;
|
||||||
|
// set cucumber default timeout
|
||||||
this.setDefaultTimeout(this.TIMEOUT);
|
this.setDefaultTimeout(this.TIMEOUT);
|
||||||
this.ROOT_FOLDER = process.cwd();
|
this.ROOT_PATH = process.cwd();
|
||||||
|
|
||||||
|
this.TEST_PATH = path.resolve(this.ROOT_PATH, 'test');
|
||||||
|
this.CACHE_PATH = path.resolve(this.TEST_PATH, 'cache');
|
||||||
|
this.LOGS_PATH = path.resolve(this.TEST_PATH, 'logs');
|
||||||
|
|
||||||
|
this.PROFILES_PATH = path.resolve(this.ROOT_PATH, 'profiles');
|
||||||
|
this.FIXTURES_PATH = path.resolve(this.ROOT_PATH, 'unit_tests/fixtures');
|
||||||
|
this.BIN_PATH = process.env.OSRM_BUILD_DIR && process.env.OSRM_BUILD_DIR || path.resolve(this.ROOT_PATH, 'build');
|
||||||
|
var stxxl_config = path.resolve(this.ROOT_PATH, 'test/.stxxl');
|
||||||
|
if (!fs.existsSync(stxxl_config)) {
|
||||||
|
return callback(new Error('*** '+stxxl_config+ 'does not exist'));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.DEFAULT_ENVIRONMENT = Object.assign({STXXLCFG: stxxl_config}, process.env);
|
||||||
|
this.DEFAULT_PROFILE = 'bicycle';
|
||||||
|
this.DEFAULT_INPUT_FORMAT = 'osm';
|
||||||
|
this.DEFAULT_LOAD_METHOD = 'datastore';
|
||||||
|
this.DEFAULT_ORIGIN = [1,1];
|
||||||
this.OSM_USER = 'osrm';
|
this.OSM_USER = 'osrm';
|
||||||
this.OSM_GENERATOR = 'osrm-test';
|
this.OSM_GENERATOR = 'osrm-test';
|
||||||
this.OSM_UID = 1;
|
this.OSM_UID = 1;
|
||||||
this.TEST_FOLDER = path.resolve(this.ROOT_FOLDER, 'test');
|
|
||||||
this.DATA_FOLDER = path.resolve(this.TEST_FOLDER, 'cache');
|
|
||||||
this.OSM_TIMESTAMP = '2000-01-01T00:00:00Z';
|
this.OSM_TIMESTAMP = '2000-01-01T00:00:00Z';
|
||||||
this.DEFAULT_SPEEDPROFILE = 'bicycle';
|
|
||||||
this.WAY_SPACING = 100;
|
this.WAY_SPACING = 100;
|
||||||
this.DEFAULT_GRID_SIZE = 100; // meters
|
this.DEFAULT_GRID_SIZE = 100; // meters
|
||||||
this.PROFILES_PATH = path.resolve(this.ROOT_FOLDER, 'profiles');
|
|
||||||
this.FIXTURES_PATH = path.resolve(this.ROOT_FOLDER, 'unit_tests/fixtures');
|
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
|
||||||
this.BIN_PATH = process.env.OSRM_BUILD_DIR && process.env.OSRM_BUILD_DIR || path.resolve(this.ROOT_FOLDER, 'build');
|
this.HOST = 'http://127.0.0.1:' + this.OSRM_PORT;
|
||||||
this.DEFAULT_INPUT_FORMAT = 'osm';
|
|
||||||
this.DEFAULT_ORIGIN = [1,1];
|
|
||||||
this.DEFAULT_LOAD_METHOD = 'datastore';
|
|
||||||
this.OSRM_ROUTED_LOG_FILE = path.resolve(this.TEST_FOLDER, 'osrm-routed.log');
|
|
||||||
this.ERROR_LOG_FILE = path.resolve(this.TEST_FOLDER, 'error.log');
|
|
||||||
|
|
||||||
// TODO make sure this works on win
|
// TODO make sure this works on win
|
||||||
if (process.platform.match(/indows.*/)) {
|
if (process.platform.match(/indows.*/)) {
|
||||||
@ -37,36 +51,49 @@ module.exports = function () {
|
|||||||
} else {
|
} else {
|
||||||
this.TERMSIGNAL = 'SIGTERM';
|
this.TERMSIGNAL = 'SIGTERM';
|
||||||
this.EXE = '';
|
this.EXE = '';
|
||||||
this.LIB = '.so';
|
// TODO autodetect if this was build with shared or static libraries
|
||||||
|
this.LIB = process.env.BUILD_SHARED_LIBS && '.so' || '.a';
|
||||||
this.QQ = '';
|
this.QQ = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.OSRM_EXTRACT_PATH = path.resolve(util.format('%s/%s%s', this.BIN_PATH, 'osrm-extract', this.EXE));
|
||||||
|
this.OSRM_CONTRACT_PATH = path.resolve(util.format('%s/%s%s', this.BIN_PATH, 'osrm-contract', this.EXE));
|
||||||
|
this.OSRM_ROUTED_PATH = path.resolve(util.format('%s/%s%s', this.BIN_PATH, 'osrm-routed', this.EXE));
|
||||||
|
this.LIB_OSRM_EXTRACT_PATH = util.format('%s/libosrm_extract%s', this.BIN_PATH, this.LIB),
|
||||||
|
this.LIB_OSRM_CONTRACT_PATH = util.format('%s/libosrm_contract%s', this.BIN_PATH, this.LIB),
|
||||||
|
this.LIB_OSRM_PATH = util.format('%s/libosrm%s', this.BIN_PATH, this.LIB);
|
||||||
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.info(util.format('Node Version', process.version));
|
console.info(util.format('Node Version', process.version));
|
||||||
if (parseInt(process.version.match(/v(\d)/)[1]) < 4) throw new Error('*** PLease upgrade to Node 4.+ to run OSRM cucumber tests');
|
if (parseInt(process.version.match(/v(\d)/)[1]) < 4) throw new Error('*** PLease upgrade to Node 4.+ to run OSRM cucumber tests');
|
||||||
|
|
||||||
fs.exists(this.TEST_FOLDER, (exists) => {
|
fs.exists(this.TEST_PATH, (exists) => {
|
||||||
if (!exists) throw new Error(util.format('*** Test folder %s doesn\'t exist.', this.TEST_FOLDER));
|
if (exists)
|
||||||
callback();
|
return callback();
|
||||||
|
else
|
||||||
|
return callback(new Error('*** Test folder doesn\'t exist.'));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.verifyOSRMIsNotRunning = () => {
|
this.getProfilePath = (profile) => {
|
||||||
if (this.OSRMLoader.up()) {
|
return path.resolve(this.PROFILES_PATH, profile + '.lua');
|
||||||
throw new Error('*** osrm-routed is already running.');
|
};
|
||||||
}
|
|
||||||
|
this.verifyOSRMIsNotRunning = (callback) => {
|
||||||
|
tryConnect(this.OSRM_PORT, (err) => {
|
||||||
|
if (!err) return callback(new Error('*** osrm-routed is already running.'));
|
||||||
|
else callback();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.verifyExistenceOfBinaries = (callback) => {
|
this.verifyExistenceOfBinaries = (callback) => {
|
||||||
var verify = (bin, cb) => {
|
var verify = (binPath, cb) => {
|
||||||
var binPath = path.resolve(util.format('%s/%s%s', this.BIN_PATH, bin, this.EXE));
|
|
||||||
fs.exists(binPath, (exists) => {
|
fs.exists(binPath, (exists) => {
|
||||||
if (!exists) throw new Error(util.format('%s is missing. Build failed?', binPath));
|
if (!exists) return cb(new Error(util.format('%s is missing. Build failed?', binPath)));
|
||||||
var helpPath = util.format('%s --help > /dev/null 2>&1', binPath);
|
var helpPath = util.format('%s --help > /dev/null 2>&1', binPath);
|
||||||
exec(helpPath, (err) => {
|
child_process.exec(helpPath, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
this.log(util.format('*** Exited with code %d', err.code), 'preprocess');
|
return cb(new Error(util.format('*** %s exited with code %d', helpPath, err.code)));
|
||||||
throw new Error(util.format('*** %s exited with code %d', helpPath, err.code));
|
|
||||||
}
|
}
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
@ -74,23 +101,12 @@ module.exports = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var q = d3.queue();
|
var q = d3.queue();
|
||||||
['osrm-extract', 'osrm-contract', 'osrm-routed'].forEach(bin => { q.defer(verify, bin); });
|
[this.OSRM_EXTRACT_PATH, this.OSRM_CONTRACT_PATH, this.OSRM_ROUTED_PATH].forEach(bin => { q.defer(verify, bin); });
|
||||||
q.awaitAll(() => {
|
q.awaitAll(callback);
|
||||||
callback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.AfterConfiguration = (callback) => {
|
|
||||||
this.clearLogFiles(() => {
|
|
||||||
this.verifyOSRMIsNotRunning();
|
|
||||||
this.verifyExistenceOfBinaries(() => {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
process.on('exit', () => {
|
process.on('exit', () => {
|
||||||
if (this.OSRMLoader.loader) this.OSRMLoader.shutdown(() => {});
|
this.osrmLoader.shutdown(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('SIGINT', () => {
|
process.on('SIGINT', () => {
|
||||||
|
@ -1,132 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var util = require('util');
|
|
||||||
var path = require('path');
|
|
||||||
var fs = require('fs');
|
|
||||||
var chalk = require('chalk');
|
|
||||||
|
|
||||||
var OSRMError = class extends Error {
|
|
||||||
constructor (process, code, msg, log, lines) {
|
|
||||||
super(msg);
|
|
||||||
this.process = process;
|
|
||||||
this.code = code;
|
|
||||||
this.msg = msg;
|
|
||||||
this.lines = lines;
|
|
||||||
this.log = log;
|
|
||||||
}
|
|
||||||
|
|
||||||
extract (callback) {
|
|
||||||
this.logTail(this.log, this.lines, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
// toString (callback) {
|
|
||||||
// this.extract((tail) => {
|
|
||||||
// callback(util.format('*** %s\nLast %s from %s:\n%s\n', this.msg, this.lines, this.log, tail));
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
logTail (logPath, n, callback) {
|
|
||||||
var expanded = path.resolve(this.TEST_FOLDER, logPath);
|
|
||||||
fs.exists(expanded, (exists) => {
|
|
||||||
if (exists) {
|
|
||||||
fs.readFile(expanded, (err, data) => {
|
|
||||||
var lines = data.toString().trim().split('\n');
|
|
||||||
callback(lines
|
|
||||||
.slice(lines.length - n)
|
|
||||||
.map(line => util.format(' %s', line))
|
|
||||||
.join('\n'));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
callback(util.format('File %s does not exist!', expanded));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var unescapeStr = (str) => str.replace(/\\\|/g, '\|').replace(/\\\\/g, '\\');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
OSRMError: OSRMError,
|
|
||||||
|
|
||||||
FileError: class extends OSRMError {
|
|
||||||
constructor (logFile, code, msg) {
|
|
||||||
super ('fileutil', code, msg, logFile, 5);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
LaunchError: class extends OSRMError {
|
|
||||||
constructor (logFile, launchProcess, code, msg) {
|
|
||||||
super (launchProcess, code, msg, logFile, 5);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
ExtractError: class extends OSRMError {
|
|
||||||
constructor (logFile, code, msg) {
|
|
||||||
super('osrm-extract', code, msg, logFile, 3);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
ContractError: class extends OSRMError {
|
|
||||||
constructor (logFile, code, msg) {
|
|
||||||
super('osrm-contract', code, msg, logFile, 3);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
RoutedError: class extends OSRMError {
|
|
||||||
constructor (logFile, msg) {
|
|
||||||
super('osrm-routed', null, msg, logFile, 3);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
TableDiffError: class extends Error {
|
|
||||||
constructor (expected, actual) {
|
|
||||||
super();
|
|
||||||
this.headers = expected.raw()[0];
|
|
||||||
this.expected = expected.hashes();
|
|
||||||
this.actual = actual;
|
|
||||||
this.diff = [];
|
|
||||||
this.hasErrors = false;
|
|
||||||
|
|
||||||
var good = 0, bad = 0;
|
|
||||||
|
|
||||||
this.expected.forEach((row, i) => {
|
|
||||||
var rowError = false;
|
|
||||||
|
|
||||||
for (var j in row) {
|
|
||||||
if (unescapeStr(row[j]) != actual[i][j]) {
|
|
||||||
rowError = true;
|
|
||||||
this.hasErrors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rowError) {
|
|
||||||
bad++;
|
|
||||||
this.diff.push(Object.assign({}, row, {c_status: 'undefined'}));
|
|
||||||
this.diff.push(Object.assign({}, actual[i], {c_status: 'comment'}));
|
|
||||||
} else {
|
|
||||||
good++;
|
|
||||||
this.diff.push(row);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get string () {
|
|
||||||
if (!this.hasErrors) return null;
|
|
||||||
|
|
||||||
var s = ['Tables were not identical:'];
|
|
||||||
s.push(this.headers.map(key => ' ' + key).join(' | '));
|
|
||||||
this.diff.forEach((row) => {
|
|
||||||
var rowString = '| ';
|
|
||||||
this.headers.forEach((header) => {
|
|
||||||
if (!row.c_status) rowString += chalk.green(' ' + row[header] + ' | ');
|
|
||||||
else if (row.c_status === 'undefined') rowString += chalk.yellow('(-) ' + row[header] + ' | ');
|
|
||||||
else rowString += chalk.red('(+) ' + row[header] + ' | ');
|
|
||||||
});
|
|
||||||
s.push(rowString);
|
|
||||||
});
|
|
||||||
|
|
||||||
return s.join('\n') + '\nTODO this is a temp workaround waiting for https://github.com/cucumber/cucumber-js/issues/534';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,15 +0,0 @@
|
|||||||
var exceptions = require('./exception_classes');
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
this.OSRMError = exceptions.OSRMError,
|
|
||||||
|
|
||||||
this.FileError = (code, msg) => new (exceptions.FileError.bind(exceptions.FileError, this.PREPROCESS_LOG_FILE))(code, msg);
|
|
||||||
|
|
||||||
this.LaunchError = (code, launchProcess, msg) => new (exceptions.LaunchError.bind(exceptions.LaunchError, this.ERROR_LOG_FILE))(code, launchProcess, msg);
|
|
||||||
|
|
||||||
this.ExtractError = (code, msg) => new (exceptions.ExtractError.bind(exceptions.ExtractError, this.PREPROCESS_LOG_FILE))(code, msg);
|
|
||||||
|
|
||||||
this.ContractError = (code, msg) => new (exceptions.ContractError.bind(exceptions.ContractError, this.PREPROCESS_LOG_FILE))(code, msg);
|
|
||||||
|
|
||||||
this.RoutedError = (msg) => new (exceptions.RoutedError.bind(exceptions.RoutedError, this.OSRM_ROUTED_LOG_FILE))(msg);
|
|
||||||
};
|
|
@ -1,43 +0,0 @@
|
|||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
var crypto = require('crypto');
|
|
||||||
var d3 = require('d3-queue');
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
this.hashOfFiles = (paths, cb) => {
|
|
||||||
paths = Array.isArray(paths) ? paths : [paths];
|
|
||||||
var shasum = crypto.createHash('sha1'), hashedFiles = false;
|
|
||||||
|
|
||||||
var q = d3.queue(1);
|
|
||||||
|
|
||||||
var addFile = (path, cb) => {
|
|
||||||
fs.readFile(path, (err, data) => {
|
|
||||||
if (err && err.code === 'ENOENT') cb(); // ignore non-existing files
|
|
||||||
else if (err) cb(err);
|
|
||||||
else {
|
|
||||||
shasum.update(data);
|
|
||||||
hashedFiles = true;
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
paths.forEach(path => { q.defer(addFile, path); });
|
|
||||||
|
|
||||||
q.awaitAll(err => {
|
|
||||||
if (err) throw new Error('*** Error reading files:', err);
|
|
||||||
if (!hashedFiles) throw new Error('*** No files found: [' + paths.join(', ') + ']');
|
|
||||||
cb(shasum.digest('hex'));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.hashProfile = (cb) => {
|
|
||||||
this.hashOfFiles(path.resolve(this.PROFILES_PATH, this.profile + '.lua'), cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.hashString = (str) => {
|
|
||||||
return crypto.createHash('sha1').update(str).digest('hex');
|
|
||||||
};
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
@ -1,36 +1,61 @@
|
|||||||
var util = require('util');
|
'use strict';
|
||||||
|
|
||||||
|
var d3 = require('d3-queue');
|
||||||
|
var path = require('path');
|
||||||
|
var mkdirp = require('mkdirp');
|
||||||
|
var rimraf = require('rimraf');
|
||||||
|
var OSM = require('../lib/osm');
|
||||||
|
var OSRMLoader = require('../lib/osrm_loader');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.BeforeFeatures((features, callback) => {
|
this.registerHandler('BeforeFeatures', {timeout: 30000}, (features, callback) => {
|
||||||
this.pid = null;
|
this.osrmLoader = new OSRMLoader(this);
|
||||||
this.initializeEnv(() => {
|
this.OSMDB = new OSM.DB();
|
||||||
this.initializeOptions(callback);
|
|
||||||
});
|
let queue = d3.queue(1);
|
||||||
|
queue.defer(this.initializeEnv.bind(this));
|
||||||
|
queue.defer(this.verifyOSRMIsNotRunning.bind(this));
|
||||||
|
queue.defer(this.verifyExistenceOfBinaries.bind(this));
|
||||||
|
queue.defer(this.initializeCache.bind(this));
|
||||||
|
queue.defer(this.setupFeatures.bind(this, features));
|
||||||
|
queue.awaitAll(callback);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Before((scenario, callback) => {
|
this.BeforeFeature((feature, callback) => {
|
||||||
this.scenarioTitle = scenario.getName();
|
this.profile = this.DEFAULT_PROFILE;
|
||||||
|
this.profileFile = path.join(this.PROFILES_PATH, this.profile + '.lua');
|
||||||
this.loadMethod = this.DEFAULT_LOAD_METHOD;
|
this.setupFeatureCache(feature);
|
||||||
this.queryParams = {};
|
|
||||||
var d = new Date();
|
|
||||||
this.scenarioTime = util.format('%d-%d-%dT%s:%s:%sZ', d.getFullYear(), d.getMonth()+1, d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds());
|
|
||||||
this.resetData();
|
|
||||||
this.hasLoggedPreprocessInfo = false;
|
|
||||||
this.hasLoggedScenarioInfo = false;
|
|
||||||
this.setGridSize(this.DEFAULT_GRID_SIZE);
|
|
||||||
this.setOrigin(this.DEFAULT_ORIGIN);
|
|
||||||
this.fingerprintExtract = this.hashString([this.luaLibHash, this.binExtractHash].join('-'));
|
|
||||||
this.fingerprintContract = this.hashString(this.binContractHash);
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.Before((scenario, callback) => {
|
||||||
|
this.osrmLoader.setLoadMethod(this.DEFAULT_LOAD_METHOD);
|
||||||
|
this.setGridSize(this.DEFAULT_GRID_SIZE);
|
||||||
|
this.setOrigin(this.DEFAULT_ORIGIN);
|
||||||
|
this.queryParams = {};
|
||||||
|
this.extractArgs = '';
|
||||||
|
this.contractArgs = '';
|
||||||
|
this.environment = Object.assign(this.DEFAULT_ENVIRONMENT);
|
||||||
|
this.resetOSM();
|
||||||
|
|
||||||
|
this.scenarioID = this.getScenarioID(scenario);
|
||||||
|
this.setupScenarioCache(this.scenarioID);
|
||||||
|
|
||||||
|
// setup output logging
|
||||||
|
let logDir = path.join(this.LOGS_PATH, this.featureID);
|
||||||
|
this.scenarioLogFile = path.join(logDir, this.scenarioID) + '.log';
|
||||||
|
d3.queue(1)
|
||||||
|
.defer(mkdirp, logDir)
|
||||||
|
.defer(rimraf, this.scenarioLogFile)
|
||||||
|
.awaitAll(callback);
|
||||||
|
});
|
||||||
|
|
||||||
this.After((scenario, callback) => {
|
this.After((scenario, callback) => {
|
||||||
this.setExtractArgs('', () => {
|
this.resetOptionsOutput();
|
||||||
this.setContractArgs('', () => {
|
callback();
|
||||||
if (this.loadMethod === 'directly' && !!this.OSRMLoader.loader) this.OSRMLoader.shutdown(callback);
|
});
|
||||||
else callback();
|
|
||||||
});
|
this.AfterFeatures((features, callback) => {
|
||||||
});
|
callback();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -19,6 +19,9 @@ module.exports = function () {
|
|||||||
return paramString;
|
return paramString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME this needs to be simplified!
|
||||||
|
// - remove usage of node-timeout
|
||||||
|
// - replace with node's native timout mechanism
|
||||||
this.sendRequest = (baseUri, parameters, callback) => {
|
this.sendRequest = (baseUri, parameters, callback) => {
|
||||||
var limit = Timeout(this.TIMEOUT, { err: { statusCode: 408 } });
|
var limit = Timeout(this.TIMEOUT, { err: { statusCode: 408 } });
|
||||||
|
|
||||||
@ -28,9 +31,9 @@ module.exports = function () {
|
|||||||
|
|
||||||
request(this.query, (err, res, body) => {
|
request(this.query, (err, res, body) => {
|
||||||
if (err && err.code === 'ECONNREFUSED') {
|
if (err && err.code === 'ECONNREFUSED') {
|
||||||
throw new Error('*** osrm-routed is not running.');
|
return cb(new Error('*** osrm-routed is not running.'));
|
||||||
} else if (err && err.statusCode === 408) {
|
} else if (err && err.statusCode === 408) {
|
||||||
throw new Error();
|
return cb(new Error());
|
||||||
}
|
}
|
||||||
|
|
||||||
return cb(err, res, body);
|
return cb(err, res, body);
|
||||||
@ -40,11 +43,10 @@ module.exports = function () {
|
|||||||
runRequest(limit((err, res, body) => {
|
runRequest(limit((err, res, body) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err.statusCode === 408)
|
if (err.statusCode === 408)
|
||||||
return callback(this.RoutedError('*** osrm-routed did not respond'));
|
return callback(new Error('*** osrm-routed did not respond'));
|
||||||
else if (err.code === 'ECONNREFUSED')
|
else if (err.code === 'ECONNREFUSED')
|
||||||
return callback(this.RoutedError('*** osrm-routed is not running'));
|
return callback(new Error('*** osrm-routed is not running'));
|
||||||
}
|
}
|
||||||
//console.log(body+"\n");
|
|
||||||
return callback(err, res, body);
|
return callback(err, res, body);
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
var launchClasses = require('./launch_classes');
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
this._OSRMLoader = () => new (launchClasses._OSRMLoader.bind(launchClasses._OSRMLoader, this))();
|
|
||||||
};
|
|
@ -1,164 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
var spawn = require('child_process').spawn;
|
|
||||||
var util = require('util');
|
|
||||||
var net = require('net');
|
|
||||||
var Timeout = require('node-timeout');
|
|
||||||
|
|
||||||
var OSRMBaseLoader = class {
|
|
||||||
constructor (scope) {
|
|
||||||
this.scope = scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
launch (callback) {
|
|
||||||
var limit = Timeout(this.scope.TIMEOUT, { err: this.scope.RoutedError('Launching osrm-routed timed out.') });
|
|
||||||
|
|
||||||
var runLaunch = (cb) => {
|
|
||||||
this.osrmUp(() => { this.waitForConnection(cb); });
|
|
||||||
};
|
|
||||||
|
|
||||||
runLaunch(limit((e) => { if (e) callback(e); else callback(); }));
|
|
||||||
}
|
|
||||||
|
|
||||||
shutdown (callback) {
|
|
||||||
var limit = Timeout(this.scope.TIMEOUT, { err: this.scope.RoutedError('Shutting down osrm-routed timed out.')});
|
|
||||||
|
|
||||||
var runShutdown = (cb) => {
|
|
||||||
this.osrmDown(cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
runShutdown(limit((e) => { if (e) callback(e); else callback(); }));
|
|
||||||
}
|
|
||||||
|
|
||||||
osrmIsRunning () {
|
|
||||||
return !!this.scope.pid && this.child && !this.child.killed;
|
|
||||||
}
|
|
||||||
|
|
||||||
osrmDown (callback) {
|
|
||||||
if (this.scope.pid) {
|
|
||||||
process.kill(this.scope.pid, this.scope.TERMSIGNAL);
|
|
||||||
this.waitForShutdown(callback);
|
|
||||||
this.scope.pid = null;
|
|
||||||
} else callback(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
waitForConnection (callback) {
|
|
||||||
var retryCount = 0;
|
|
||||||
var connectWithRetry = () => {
|
|
||||||
net.connect({ port: this.scope.OSRM_PORT, host: '127.0.0.1' })
|
|
||||||
.on('connect', () => { callback(); })
|
|
||||||
.on('error', () => {
|
|
||||||
if (retryCount < 2) {
|
|
||||||
retryCount++;
|
|
||||||
setTimeout(connectWithRetry, 100);
|
|
||||||
} else {
|
|
||||||
callback(new Error('Could not connect to osrm-routed after three retires'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
connectWithRetry();
|
|
||||||
}
|
|
||||||
|
|
||||||
waitForShutdown (callback) {
|
|
||||||
var check = () => {
|
|
||||||
if (!this.osrmIsRunning()) return callback();
|
|
||||||
};
|
|
||||||
setTimeout(check, 100);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var OSRMDirectLoader = class extends OSRMBaseLoader {
|
|
||||||
constructor (scope) {
|
|
||||||
super(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
load (inputFile, callback) {
|
|
||||||
this.inputFile = inputFile;
|
|
||||||
this.shutdown(() => {
|
|
||||||
this.launch(callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
osrmUp (callback) {
|
|
||||||
if (this.scope.pid) return callback();
|
|
||||||
var writeToLog = (data) => {
|
|
||||||
fs.appendFile(this.scope.OSRM_ROUTED_LOG_FILE, data, (err) => { if (err) throw err; });
|
|
||||||
};
|
|
||||||
|
|
||||||
var child = spawn(util.format('%s/osrm-routed', this.scope.BIN_PATH), [this.inputFile, util.format('-p%d', this.scope.OSRM_PORT)]);
|
|
||||||
this.scope.pid = child.pid;
|
|
||||||
child.stdout.on('data', writeToLog);
|
|
||||||
child.stderr.on('data', writeToLog);
|
|
||||||
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var OSRMDatastoreLoader = class extends OSRMBaseLoader {
|
|
||||||
constructor (scope) {
|
|
||||||
super(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
load (inputFile, callback) {
|
|
||||||
this.inputFile = inputFile;
|
|
||||||
this.loadData((err) => {
|
|
||||||
if (err) return callback(err);
|
|
||||||
if (!this.scope.pid) return this.launch(callback);
|
|
||||||
else callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadData (callback) {
|
|
||||||
this.scope.runBin('osrm-datastore', this.inputFile, (err) => {
|
|
||||||
if (err) return callback(this.scope.LaunchError(this.exitCode, 'datastore', err));
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
osrmUp (callback) {
|
|
||||||
if (this.scope.pid) return callback();
|
|
||||||
var writeToLog = (data) => {
|
|
||||||
fs.appendFile(this.scope.OSRM_ROUTED_LOG_FILE, data, (err) => { if (err) throw err; });
|
|
||||||
};
|
|
||||||
|
|
||||||
var child = spawn(util.format('%s/osrm-routed', this.scope.BIN_PATH), ['--shared-memory=1', util.format('-p%d', this.scope.OSRM_PORT)]);
|
|
||||||
this.child = child;
|
|
||||||
this.scope.pid = child.pid;
|
|
||||||
child.stdout.on('data', writeToLog);
|
|
||||||
child.stderr.on('data', writeToLog);
|
|
||||||
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
_OSRMLoader: class {
|
|
||||||
constructor (scope) {
|
|
||||||
this.scope = scope;
|
|
||||||
this.loader = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
load (inputFile, callback) {
|
|
||||||
var method = this.scope.loadMethod;
|
|
||||||
if (method === 'datastore') {
|
|
||||||
this.loader = new OSRMDatastoreLoader(this.scope);
|
|
||||||
this.loader.load(inputFile, callback);
|
|
||||||
} else if (method === 'directly') {
|
|
||||||
this.loader = new OSRMDirectLoader(this.scope);
|
|
||||||
this.loader.load(inputFile, callback);
|
|
||||||
} else {
|
|
||||||
callback(new Error('*** Unknown load method ' + method));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shutdown (callback) {
|
|
||||||
this.loader.shutdown(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
up () {
|
|
||||||
return this.loader ? this.loader.osrmIsRunning() : false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,90 +0,0 @@
|
|||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
this.clearLogFiles = (callback) => {
|
|
||||||
// emptying existing files, rather than deleting and writing new ones makes it
|
|
||||||
// easier to use tail -f from the command line
|
|
||||||
fs.writeFile(this.OSRM_ROUTED_LOG_FILE, '', err => {
|
|
||||||
if (err) throw err;
|
|
||||||
fs.writeFile(this.PREPROCESS_LOG_FILE, '', err => {
|
|
||||||
if (err) throw err;
|
|
||||||
fs.writeFile(this.LOG_FILE, '', err => {
|
|
||||||
if (err) throw err;
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var log = this.log = (s, type) => {
|
|
||||||
s = s || '';
|
|
||||||
type = type || null;
|
|
||||||
var file = type === 'preprocess' ? this.PREPROCESS_LOG_FILE : this.LOG_FILE;
|
|
||||||
fs.appendFile(file, s + '\n', err => {
|
|
||||||
if (err) throw err;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.logScenarioFailInfo = () => {
|
|
||||||
if (this.hasLoggedScenarioInfo) return;
|
|
||||||
|
|
||||||
log('=========================================');
|
|
||||||
log('Failed scenario: ' + this.scenarioTitle);
|
|
||||||
log('Time: ' + this.scenarioTime);
|
|
||||||
log('Fingerprint osm stage: ' + this.osmData.fingerprintOSM);
|
|
||||||
log('Fingerprint extract stage: ' + this.fingerprintExtract);
|
|
||||||
log('Fingerprint contract stage: ' + this.fingerprintContract);
|
|
||||||
log('Fingerprint route stage: ' + this.fingerprintRoute);
|
|
||||||
log('Profile: ' + this.profile);
|
|
||||||
log();
|
|
||||||
log('```xml'); // so output can be posted directly to github comment fields
|
|
||||||
log(this.osmData.str.trim());
|
|
||||||
log('```');
|
|
||||||
log();
|
|
||||||
log();
|
|
||||||
|
|
||||||
this.hasLoggedScenarioInfo = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.logFail = (expected, got, attempts) => {
|
|
||||||
this.logScenarioFailInfo();
|
|
||||||
log('== ');
|
|
||||||
log('Expected: ' + JSON.stringify(expected));
|
|
||||||
log('Got: ' + JSON.stringify(got));
|
|
||||||
log();
|
|
||||||
['route','forw','backw'].forEach((direction) => {
|
|
||||||
if (attempts[direction]) {
|
|
||||||
log('Direction: ' + direction);
|
|
||||||
log('Query: ' + attempts[direction].query);
|
|
||||||
log('Response: ' + attempts[direction].response.body);
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.logPreprocessInfo = () => {
|
|
||||||
if (this.hasLoggedPreprocessInfo) return;
|
|
||||||
log('=========================================', 'preprocess');
|
|
||||||
log('Preprocessing data for scenario: ' + this.scenarioTitle, 'preprocess');
|
|
||||||
log('Time: ' + this.scenarioTime, 'preprocess');
|
|
||||||
log('', 'preprocess');
|
|
||||||
log('== OSM data:', 'preprocess');
|
|
||||||
log('```xml', 'preprocess'); // so output can be posted directly to github comment fields
|
|
||||||
log(this.osmData.str, 'preprocess');
|
|
||||||
log('```', 'preprocess');
|
|
||||||
log('', 'preprocess');
|
|
||||||
log('== Profile:', 'preprocess');
|
|
||||||
log(this.profile, 'preprocess');
|
|
||||||
log('', 'preprocess');
|
|
||||||
this.hasLoggedPreprocessInfo = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.logPreprocess = (str) => {
|
|
||||||
this.logPreprocessInfo();
|
|
||||||
log(str, 'preprocess');
|
|
||||||
};
|
|
||||||
|
|
||||||
this.logPreprocessDone = () => {
|
|
||||||
log('Done with preprocessing at ' + new Date(), 'preprocess');
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,7 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Timeout = require('node-timeout');
|
const Timeout = require('node-timeout');
|
||||||
var request = require('request');
|
const request = require('request');
|
||||||
|
const ensureDecimal = require('../lib/utils').ensureDecimal;
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.requestPath = (service, params, callback) => {
|
this.requestPath = (service, params, callback) => {
|
||||||
@ -42,7 +43,7 @@ module.exports = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var encodeWaypoints = (waypoints) => {
|
var encodeWaypoints = (waypoints) => {
|
||||||
return waypoints.map(w => [w.lon, w.lat].map(this.ensureDecimal).join(','));
|
return waypoints.map(w => [w.lon, w.lat].map(ensureDecimal).join(','));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.requestRoute = (waypoints, bearings, userParams, callback) => {
|
this.requestRoute = (waypoints, bearings, userParams, callback) => {
|
||||||
|
@ -1,40 +1,52 @@
|
|||||||
var fs = require('fs');
|
'use strict';
|
||||||
var util = require('util');
|
|
||||||
var exec = require('child_process').exec;
|
const fs = require('fs');
|
||||||
|
const util = require('util');
|
||||||
|
const child_process = require('child_process');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.runBin = (bin, options, callback) => {
|
// replaces placeholders for in user supplied commands
|
||||||
var opts = options.slice();
|
this.expandOptions = (options) => {
|
||||||
|
let opts = options.slice();
|
||||||
|
let table = {
|
||||||
|
'{osm_file}': this.inputCacheFile,
|
||||||
|
'{processed_file}': this.processedCacheFile,
|
||||||
|
'{profile_file}': this.profileFile,
|
||||||
|
'{rastersource_file}': this.rasterCacheFile,
|
||||||
|
'{speeds_file}': this.speedsCacheFile,
|
||||||
|
'{penalties_file}': this.penaltiesCacheFile
|
||||||
|
};
|
||||||
|
|
||||||
if (opts.match('{osm_base}')) {
|
for (let k in table) {
|
||||||
if (!this.osmData.osmFile) throw new Error('*** {osm_base} is missing');
|
opts = opts.replace(k, table[k]);
|
||||||
opts = opts.replace('{osm_base}', this.osmData.osmFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.match('{extracted_base}')) {
|
return opts;
|
||||||
if (!this.osmData.extractedFile) throw new Error('*** {extracted_base} is missing');
|
};
|
||||||
opts = opts.replace('{extracted_base}', this.osmData.extractedFile);
|
|
||||||
|
this.setupOutputLog = (process, log) => {
|
||||||
|
if (process.logFunc) {
|
||||||
|
process.stdout.removeListener('data', process.logFunc);
|
||||||
|
process.stderr.removeListener('data', process.logFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.match('{contracted_base}')) {
|
process.logFunc = (message) => { log.write(message); };
|
||||||
if (!this.osmData.contractedFile) throw new Error('*** {contracted_base} is missing');
|
process.stdout.on('data', process.logFunc);
|
||||||
opts = opts.replace('{contracted_base}', this.osmData.contractedFile);
|
process.stderr.on('data', process.logFunc);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (opts.match('{profile}')) {
|
this.runBin = (bin, options, env, callback) => {
|
||||||
opts = opts.replace('{profile}', [this.PROFILES_PATH, this.profile + '.lua'].join('/'));
|
let cmd = util.format('%s%s/%s%s%s', this.QQ, this.BIN_PATH, bin, this.EXE, this.QQ);
|
||||||
}
|
let opts = options.split(' ').filter((x) => { return x && x.length > 0; });
|
||||||
|
let log = fs.createWriteStream(this.scenarioLogFile, {'flags': 'a'});
|
||||||
var cmd = util.format('%s%s/%s%s%s %s 2>%s', this.QQ, this.BIN_PATH, bin, this.EXE, this.QQ, opts, this.ERROR_LOG_FILE);
|
log.write(util.format('*** running %s %s\n', cmd, options));
|
||||||
process.chdir(this.TEST_FOLDER);
|
// we need to set a large maxbuffer here because we have long running processes like osrm-routed
|
||||||
exec(cmd, (err, stdout, stderr) => {
|
// with lots of log output
|
||||||
this.stdout = stdout.toString();
|
let child = child_process.execFile(cmd, opts, {maxBuffer: 1024 * 1024 * 1000, env: env}, callback);
|
||||||
fs.readFile(this.ERROR_LOG_FILE, (e, data) => {
|
child.on('exit', function(code) {
|
||||||
this.stderr = data ? data.toString() : '';
|
log.end(util.format('*** %s exited with code %d\n', bin, code));
|
||||||
this.exitCode = err && err.code || 0;
|
}.bind(this));
|
||||||
process.chdir('../');
|
this.setupOutputLog(child, log);
|
||||||
callback(err, stdout, stderr);
|
return child;
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -93,7 +93,7 @@ module.exports = function () {
|
|||||||
if (headers.has('distance')) {
|
if (headers.has('distance')) {
|
||||||
if (row.distance.length) {
|
if (row.distance.length) {
|
||||||
if (!row.distance.match(/\d+m/))
|
if (!row.distance.match(/\d+m/))
|
||||||
throw new Error('*** Distance must be specified in meters. (ex: 250m)');
|
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
|
||||||
got.distance = instructions ? util.format('%dm', distance) : '';
|
got.distance = instructions ? util.format('%dm', distance) : '';
|
||||||
} else {
|
} else {
|
||||||
got.distance = '';
|
got.distance = '';
|
||||||
@ -102,7 +102,7 @@ module.exports = function () {
|
|||||||
|
|
||||||
if (headers.has('time')) {
|
if (headers.has('time')) {
|
||||||
if (!row.time.match(/\d+s/))
|
if (!row.time.match(/\d+s/))
|
||||||
throw new Error('*** Time must be specied in seconds. (ex: 60s)');
|
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
|
||||||
got.time = instructions ? util.format('%ds', time) : '';
|
got.time = instructions ? util.format('%ds', time) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ module.exports = function () {
|
|||||||
if (headers.has('speed')) {
|
if (headers.has('speed')) {
|
||||||
if (row.speed !== '' && instructions) {
|
if (row.speed !== '' && instructions) {
|
||||||
if (!row.speed.match(/\d+ km\/h/))
|
if (!row.speed.match(/\d+ km\/h/))
|
||||||
throw new Error('*** Speed must be specied in km/h. (ex: 50 km/h)');
|
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
|
||||||
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
|
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
|
||||||
got.speed = util.format('%d km/h', speed);
|
got.speed = util.format('%d km/h', speed);
|
||||||
} else {
|
} else {
|
||||||
@ -139,20 +139,12 @@ module.exports = function () {
|
|||||||
putValue('destinations', destinations);
|
putValue('destinations', destinations);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ok = true;
|
|
||||||
|
|
||||||
for (var key in row) {
|
for (var key in row) {
|
||||||
if (this.FuzzyMatch.match(got[key], row[key])) {
|
if (this.FuzzyMatch.match(got[key], row[key])) {
|
||||||
got[key] = row[key];
|
got[key] = row[key];
|
||||||
} else {
|
|
||||||
ok = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
this.logFail(row, got, { route: { query: this.query, response: res }});
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(null, got);
|
cb(null, got);
|
||||||
} else {
|
} else {
|
||||||
cb(new Error('request failed to return valid body'));
|
cb(new Error('request failed to return valid body'));
|
||||||
@ -189,11 +181,11 @@ module.exports = function () {
|
|||||||
|
|
||||||
if (row.from && row.to) {
|
if (row.from && row.to) {
|
||||||
var fromNode = this.findNodeByName(row.from);
|
var fromNode = this.findNodeByName(row.from);
|
||||||
if (!fromNode) throw new Error(util.format('*** unknown from-node "%s"'), row.from);
|
if (!fromNode) return cb(new Error(util.format('*** unknown from-node "%s"'), row.from));
|
||||||
waypoints.push(fromNode);
|
waypoints.push(fromNode);
|
||||||
|
|
||||||
var toNode = this.findNodeByName(row.to);
|
var toNode = this.findNodeByName(row.to);
|
||||||
if (!toNode) throw new Error(util.format('*** unknown to-node "%s"'), row.to);
|
if (!toNode) return cb(new Error(util.format('*** unknown to-node "%s"'), row.to));
|
||||||
waypoints.push(toNode);
|
waypoints.push(toNode);
|
||||||
|
|
||||||
got.from = row.from;
|
got.from = row.from;
|
||||||
@ -202,13 +194,13 @@ module.exports = function () {
|
|||||||
} else if (row.waypoints) {
|
} else if (row.waypoints) {
|
||||||
row.waypoints.split(',').forEach((n) => {
|
row.waypoints.split(',').forEach((n) => {
|
||||||
var node = this.findNodeByName(n.trim());
|
var node = this.findNodeByName(n.trim());
|
||||||
if (!node) throw new Error('*** unknown waypoint node "%s"', n.trim());
|
if (!node) return cb(new Error('*** unknown waypoint node "%s"', n.trim()));
|
||||||
waypoints.push(node);
|
waypoints.push(node);
|
||||||
});
|
});
|
||||||
got.waypoints = row.waypoints;
|
got.waypoints = row.waypoints;
|
||||||
this.requestRoute(waypoints, bearings, params, afterRequest);
|
this.requestRoute(waypoints, bearings, params, afterRequest);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('*** no waypoints');
|
return cb(new Error('*** no waypoints'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
var DifferentError = require('./exception_classes').TableDiffError;
|
|
||||||
|
|
||||||
module.exports = function () {
|
|
||||||
this.diffTables = (expected, actual, options, callback) => {
|
|
||||||
// this is a temp workaround while waiting for https://github.com/cucumber/cucumber-js/issues/534
|
|
||||||
|
|
||||||
var error = new DifferentError(expected, actual);
|
|
||||||
|
|
||||||
return callback(error.string);
|
|
||||||
};
|
|
||||||
};
|
|
@ -11,8 +11,8 @@ Feature: Handle bad data in a graceful manner
|
|||||||
Given the ways
|
Given the ways
|
||||||
| nodes |
|
| nodes |
|
||||||
|
|
||||||
When the data has been contracted
|
When I try to run "osrm-extract {osm_file} --profile {profile_file}"
|
||||||
Then "osrm-extract" should return code 1
|
Then it should exit with an error
|
||||||
|
|
||||||
Scenario: Only dead-end oneways
|
Scenario: Only dead-end oneways
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
@routing @testbot @bug
|
|
||||||
Feature: Known bugs
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the profile "testbot"
|
|
@ -124,7 +124,7 @@ Feature: Basic Map Matching
|
|||||||
1,2,36
|
1,2,36
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the contract extra arguments "--segment-speed-file speeds.csv"
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
|
||||||
When I match I should get
|
When I match I should get
|
||||||
| trace | matchings | annotation |
|
| trace | matchings | annotation |
|
||||||
|
@ -26,7 +26,7 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
|
|||||||
1,2,5,0,comment
|
1,2,5,0,comment
|
||||||
3,4,7,-20
|
3,4,7,-20
|
||||||
"""
|
"""
|
||||||
And the contract extra arguments "--turn-penalty-file penalties.csv"
|
And the contract extra arguments "--turn-penalty-file {penalties_file}"
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | speed | time |
|
| from | to | route | speed | time |
|
||||||
| a | e | ab,be,be | 36 km/h | 40s +-1 |
|
| a | e | ab,be,be | 36 km/h | 40s +-1 |
|
||||||
|
@ -173,7 +173,7 @@ Feature: Via points
|
|||||||
| c,d,a | abc,bd,bd,bd,abc,abc |
|
| c,d,a | abc,bd,bd,bd,abc,abc |
|
||||||
|
|
||||||
# See issue #2349
|
# See issue #2349
|
||||||
@bug @todo
|
@todo
|
||||||
Scenario: Via point at a dead end with oneway
|
Scenario: Via point at a dead end with oneway
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c |
|
| a | b | c |
|
||||||
|
@ -7,9 +7,11 @@
|
|||||||
"chalk": "^1.1.3",
|
"chalk": "^1.1.3",
|
||||||
"cucumber": "^1.2.1",
|
"cucumber": "^1.2.1",
|
||||||
"d3-queue": "^2.0.3",
|
"d3-queue": "^2.0.3",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
"node-timeout": "0.0.4",
|
"node-timeout": "0.0.4",
|
||||||
"polyline": "^0.2.0",
|
"polyline": "^0.2.0",
|
||||||
"request": "^2.69.0",
|
"request": "^2.69.0",
|
||||||
|
"rimraf": "^2.5.4",
|
||||||
"xmlbuilder": "^4.2.1"
|
"xmlbuilder": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -21,8 +21,12 @@ function way_function (way, result)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function source_function ()
|
function source_function ()
|
||||||
|
local path = os.getenv('OSRM_RASTER_SOURCE')
|
||||||
|
if not path then
|
||||||
|
path = "rastersource.asc"
|
||||||
|
end
|
||||||
raster_source = sources:load(
|
raster_source = sources:load(
|
||||||
"../test/rastersource.asc",
|
path,
|
||||||
0, -- lon_min
|
0, -- lon_min
|
||||||
0.1, -- lon_max
|
0.1, -- lon_max
|
||||||
0, -- lat_min
|
0, -- lat_min
|
||||||
|
@ -21,8 +21,12 @@ function way_function (way, result)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function source_function ()
|
function source_function ()
|
||||||
|
local path = os.getenv('OSRM_RASTER_SOURCE')
|
||||||
|
if not path then
|
||||||
|
path = "rastersource.asc"
|
||||||
|
end
|
||||||
raster_source = sources:load(
|
raster_source = sources:load(
|
||||||
"../test/rastersource.asc",
|
path,
|
||||||
0, -- lon_min
|
0, -- lon_min
|
||||||
0.1, -- lon_max
|
0.1, -- lon_max
|
||||||
0, -- lat_min
|
0, -- lat_min
|
||||||
|
Loading…
Reference in New Issue
Block a user