Merge branch 'cucumber'
This commit is contained in:
commit
c32e5dc586
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,3 +1,11 @@
|
|||||||
|
# Test folder #
|
||||||
|
###################
|
||||||
|
test/speedprofile.ini
|
||||||
|
test/data/*.osrm
|
||||||
|
test/data/*.osrm.*
|
||||||
|
test/data/denmark.osm.pbf
|
||||||
|
|
||||||
|
|
||||||
# Compiled source #
|
# Compiled source #
|
||||||
###################
|
###################
|
||||||
*.com
|
*.com
|
||||||
@ -6,6 +14,9 @@
|
|||||||
*.exe
|
*.exe
|
||||||
*.o
|
*.o
|
||||||
*.so
|
*.so
|
||||||
|
osrm-extract
|
||||||
|
osrm-prepare
|
||||||
|
osrm-routed
|
||||||
|
|
||||||
# Packages #
|
# Packages #
|
||||||
############
|
############
|
||||||
@ -70,4 +81,4 @@ win/*.suo
|
|||||||
win/Debug/
|
win/Debug/
|
||||||
win/Release/
|
win/Release/
|
||||||
win/bin/
|
win/bin/
|
||||||
win/bin-debug/
|
win/bin-debug/
|
||||||
|
|||||||
53
Rakefile
Normal file
53
Rakefile
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#$:.unshift(File.dirname(__FILE__) + '/../../lib')
|
||||||
|
require 'cucumber/rake/task'
|
||||||
|
|
||||||
|
Cucumber::Rake::Task.new do |t|
|
||||||
|
t.cucumber_opts = %w{--format pretty}
|
||||||
|
end
|
||||||
|
|
||||||
|
osm_data_country = 'denmark'
|
||||||
|
osm_data_area_name = 'kbh'
|
||||||
|
osm_data_area_bbox = 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376'
|
||||||
|
|
||||||
|
|
||||||
|
desc "Rebuild and run tests"
|
||||||
|
task :default => [:build, :cucumber]
|
||||||
|
|
||||||
|
desc "Build using Scons"
|
||||||
|
task :build do
|
||||||
|
system "scons"
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace :data do
|
||||||
|
desc "Download OSM data extract for Denmark, and crop test areas"
|
||||||
|
task :download do
|
||||||
|
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/osm/europe/#{osm_data_country}.osm.pbf -o test/data/#{osm_data_country}.osm.pbf"
|
||||||
|
raise "Error while cropping data." unless system "osmosis --read-pbf file=test/data/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=test/data/#{osm_data_area_name}.osm.pbf omitmetadata=true"
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Reprocess OSM data"
|
||||||
|
task :process do
|
||||||
|
Dir.chdir "test" do #we must be in the test_folder folder to use the speedprofile.ini in that folder
|
||||||
|
raise "Error while extracting data." unless system "./osrm-extract data/#{osm_data_area_name}.osm.pbf"
|
||||||
|
raise "Error while preparing data." unless system "./osrm-prepare data/#{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Delete preprocessing files"
|
||||||
|
task :clean do
|
||||||
|
File.delete *Dir.glob('test/data/*.osrm')
|
||||||
|
File.delete *Dir.glob('test/data/*.osrm.*')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Launch the routing server"
|
||||||
|
task :run do
|
||||||
|
Dir.chdir "test" do
|
||||||
|
system "./osrm-routed"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Run all test"
|
||||||
|
task :test do
|
||||||
|
puts "Test would go here..."
|
||||||
|
end
|
||||||
130
SConstruct
130
SConstruct
@ -49,49 +49,72 @@ def CheckProtobuf(context, version):
|
|||||||
context.Result(ret)
|
context.Result(ret)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
AddOption('--cxx', dest='cxx', type='string', nargs=1, action='store', metavar='STRING', help='C++ Compiler')
|
AddOption('--cxx', dest='cxx', type='string', nargs=1, action='store', metavar='STRING', help='C++ Compiler')
|
||||||
AddOption('--stxxlroot', dest='stxxlroot', type='string', nargs=1, action='store', metavar='STRING', help='root directory of STXXL')
|
AddOption('--stxxlroot', dest='stxxlroot', type='string', nargs=1, action='store', metavar='STRING', help='root directory of STXXL')
|
||||||
AddOption('--verbosity', dest='verbosity', type='string', nargs=1, action='store', metavar='STRING', help='make Scons talking')
|
AddOption('--verbosity', dest='verbosity', type='string', nargs=1, action='store', metavar='STRING', help='make Scons talking')
|
||||||
AddOption('--buildconfiguration', dest='buildconfiguration', type='string', nargs=1, action='store', metavar='STRING', help='debug or release')
|
AddOption('--buildconfiguration', dest='buildconfiguration', type='string', nargs=1, action='store', metavar='STRING', help='debug or release')
|
||||||
env = Environment(ENV = {'PATH' : os.environ['PATH']} ,COMPILER = GetOption('cxx'))
|
|
||||||
if sys.platform.startswith("freebsd"):
|
env = Environment( ENV = {'PATH' : os.environ['PATH']} ,COMPILER = GetOption('cxx'))
|
||||||
env.ParseConfig('pkg-config --cflags --libs protobuf')
|
conf = Configure(env, custom_tests = { 'CheckBoost' : CheckBoost, 'CheckProtobuf' : CheckProtobuf })
|
||||||
|
|
||||||
|
|
||||||
if GetOption('cxx') is None:
|
if GetOption('cxx') is None:
|
||||||
#default Compiler
|
#default Compiler
|
||||||
print 'Using default C++ Compiler: ', env['CXX']
|
print 'Using default C++ Compiler: ', env['CXX']
|
||||||
else:
|
else:
|
||||||
env.Replace(CXX = GetOption('cxx'))
|
env.Replace(CXX = GetOption('cxx'))
|
||||||
print 'Using user supplied C++ Compiler: ', env['CXX']
|
print 'Using user supplied C++ Compiler: ', env['CXX']
|
||||||
if GetOption('stxxlroot') is not None:
|
|
||||||
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
|
|
||||||
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
|
|
||||||
print 'STXXLROOT = ', GetOption('stxxlroot')
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
#SCons really wants to use Microsoft compiler
|
|
||||||
print "Compiling is not yet supported on Windows"
|
|
||||||
Exit(-1)
|
|
||||||
else: #Mac OS X
|
|
||||||
if sys.platform == 'darwin':
|
|
||||||
print "Compiling is experimental on Mac"
|
|
||||||
env.Append(CPPPATH = ['/opt/local/include/', '/opt/local/include/libxml2'])
|
|
||||||
env.Append(LIBPATH = ['/opt/local/lib'])
|
|
||||||
elif sys.platform.startswith('freebsd'):
|
|
||||||
env.Append(CPPPATH = ['/usr/local/include', '/usr/local/include/libxml2'])
|
|
||||||
env.Append(LIBPATH = ['/usr/local/lib'])
|
|
||||||
else:
|
|
||||||
env.Append(CPPPATH = ['/usr/include', '/usr/include/include', '/usr/include/libxml2/'])
|
|
||||||
if GetOption('buildconfiguration') == 'debug':
|
if GetOption('buildconfiguration') == 'debug':
|
||||||
env.Append(CCFLAGS = ['-Wall', '-g3', '-rdynamic'])
|
env.Append(CCFLAGS = ['-Wall', '-g3', '-rdynamic'])
|
||||||
else:
|
else:
|
||||||
env.Append(CCFLAGS = ['-O3', '-DNDEBUG', '-march=native'])
|
env.Append(CCFLAGS = ['-O3', '-DNDEBUG'])
|
||||||
#print "Compiling with: ", env['CXX']
|
|
||||||
conf = Configure(env, custom_tests = { 'CheckBoost' : CheckBoost, 'CheckProtobuf' : CheckProtobuf })
|
|
||||||
if not conf.CheckHeader('omp.h'):
|
if sys.platform == 'darwin': #Mac OS X
|
||||||
print "Compiler does not support OpenMP. Exiting"
|
env.Append(CPPPATH = ['/usr/include/libxml2'] ) #comes with os x
|
||||||
if sys.platform == 'darwin':
|
#assume dependencies are installed with homebrew, and call out get folder locations
|
||||||
print "Continuing because we are on Mac. This might be fatal."
|
import subprocess
|
||||||
else:
|
stxxl_prefix = subprocess.check_output(["brew", "--prefix", "libstxxl"]).strip()
|
||||||
|
env.Append(CPPPATH = [stxxl_prefix+"/include"] )
|
||||||
|
env.Append(LIBPATH = [stxxl_prefix+"/lib"] )
|
||||||
|
|
||||||
|
boost_prefix = subprocess.check_output(["brew", "--prefix", "boost"]).strip()
|
||||||
|
env.Append(CPPPATH = [boost_prefix+"/include"] )
|
||||||
|
env.Append(LIBPATH = [boost_prefix+"/lib"] )
|
||||||
|
|
||||||
|
#libxml2_prefix = subprocess.check_output(["brew", "--prefix", "libxml2"]).strip()
|
||||||
|
#env.Append(CPPPATH = [libxml2_prefix+"/include"] )
|
||||||
|
#env.Append(LIBPATH = [libxml2_prefix+"/lib"] )
|
||||||
|
|
||||||
|
elif sys.platform.startswith("freebsd"):
|
||||||
|
env.ParseConfig('pkg-config --cflags --libs protobuf')
|
||||||
|
env.Append(CPPPATH = ['/usr/local/include', '/usr/local/include/libxml2'])
|
||||||
|
env.Append(LIBPATH = ['/usr/local/lib'])
|
||||||
|
if GetOption('stxxlroot') is not None:
|
||||||
|
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
|
||||||
|
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
|
||||||
|
print 'STXXLROOT = ', GetOption('stxxlroot')
|
||||||
|
if GetOption('buildconfiguration') != 'debug':
|
||||||
|
env.Append(CCFLAGS = ['-march=native'])
|
||||||
|
#print "Compiling with: ", env['CXX']
|
||||||
|
env.Append(CCFLAGS = ['-fopenmp'])
|
||||||
|
env.Append(LINKFLAGS = ['-fopenmp'])
|
||||||
|
elif sys.platform == 'win32':
|
||||||
|
#SCons really wants to use Microsoft compiler
|
||||||
|
print "Compiling is not yet supported on Windows"
|
||||||
|
Exit(-1)
|
||||||
|
else:
|
||||||
|
print "Unknown platform.."
|
||||||
|
env.Append(CPPPATH = ['/usr/include', '/usr/include/include', '/usr/include/libxml2/'])
|
||||||
|
|
||||||
|
|
||||||
|
if sys.platform != 'darwin':
|
||||||
|
if not conf.CheckHeader('omp.h'):
|
||||||
|
print "Compiler does not support OpenMP. Exiting"
|
||||||
Exit(-1)
|
Exit(-1)
|
||||||
|
|
||||||
if not conf.CheckLibWithHeader('bz2', 'bzlib.h', 'CXX'):
|
if not conf.CheckLibWithHeader('bz2', 'bzlib.h', 'CXX'):
|
||||||
print "bz2 library not found. Exiting"
|
print "bz2 library not found. Exiting"
|
||||||
Exit(-1)
|
Exit(-1)
|
||||||
@ -129,9 +152,6 @@ if not conf.CheckLibWithHeader('Magick++', 'ImageMagick/Magick++.h', 'CXX'):
|
|||||||
if not (conf.CheckBoost('1.41')):
|
if not (conf.CheckBoost('1.41')):
|
||||||
print 'Boost version >= 1.41 needed'
|
print 'Boost version >= 1.41 needed'
|
||||||
Exit(-1);
|
Exit(-1);
|
||||||
if not conf.CheckLib('boost_system', language="C++"):
|
|
||||||
print "boost_system library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('boost_thread', 'boost/thread.hpp', 'CXX'):
|
if not conf.CheckLibWithHeader('boost_thread', 'boost/thread.hpp', 'CXX'):
|
||||||
if not conf.CheckLibWithHeader('boost_thread-mt', 'boost/thread.hpp', 'CXX'):
|
if not conf.CheckLibWithHeader('boost_thread-mt', 'boost/thread.hpp', 'CXX'):
|
||||||
print "boost thread library not found. Exiting"
|
print "boost thread library not found. Exiting"
|
||||||
@ -141,14 +161,21 @@ if not conf.CheckLibWithHeader('boost_thread', 'boost/thread.hpp', 'CXX'):
|
|||||||
env.Append(CCFLAGS = ' -lboost_thread-mt')
|
env.Append(CCFLAGS = ' -lboost_thread-mt')
|
||||||
env.Append(LINKFLAGS = ' -lboost_thread-mt')
|
env.Append(LINKFLAGS = ' -lboost_thread-mt')
|
||||||
if not conf.CheckLibWithHeader('boost_regex', 'boost/regex.hpp', 'CXX'):
|
if not conf.CheckLibWithHeader('boost_regex', 'boost/regex.hpp', 'CXX'):
|
||||||
print "boost/regex.hpp not found. Exiting"
|
if not conf.CheckLibWithHeader('boost_regex-mt', 'boost/regex.hpp', 'CXX'):
|
||||||
Exit(-1)
|
print "boost/regex.hpp not found. Exiting"
|
||||||
if not conf.CheckCXXHeader('boost/array.hpp'):
|
Exit(-1)
|
||||||
print "boost/thread.hpp not found. Exiting"
|
else:
|
||||||
Exit(-1)
|
print "using boost_regex -mt"
|
||||||
if not conf.CheckCXXHeader('boost/asio.hpp'):
|
env.Append(CCFLAGS = ' -lboost_regex-mt')
|
||||||
print "boost/thread.hpp not found. Exiting"
|
env.Append(LINKFLAGS = ' -lboost_regex-mt')
|
||||||
Exit(-1)
|
if not conf.CheckLib('boost_system', language="C++"):
|
||||||
|
if not conf.CheckLib('boost_system-mt', language="C++"):
|
||||||
|
print "boost_system library not found. Exiting"
|
||||||
|
Exit(-1)
|
||||||
|
else:
|
||||||
|
print "using boost -mt"
|
||||||
|
env.Append(CCFLAGS = ' -lboost_system-mt')
|
||||||
|
env.Append(LINKFLAGS = ' -lboost_system-mt')
|
||||||
if not conf.CheckCXXHeader('boost/bind.hpp'):
|
if not conf.CheckCXXHeader('boost/bind.hpp'):
|
||||||
print "boost/bind.hpp not found. Exiting"
|
print "boost/bind.hpp not found. Exiting"
|
||||||
Exit(-1)
|
Exit(-1)
|
||||||
@ -191,18 +218,27 @@ if not conf.CheckCXXHeader('boost/tuple/tuple.hpp'):
|
|||||||
if not conf.CheckCXXHeader('boost/unordered_map.hpp'):
|
if not conf.CheckCXXHeader('boost/unordered_map.hpp'):
|
||||||
print "boost thread header not found. Exiting"
|
print "boost thread header not found. Exiting"
|
||||||
Exit(-1)
|
Exit(-1)
|
||||||
|
#if os.sysconf('SC_NPROCESSORS_ONLN') > 1:
|
||||||
|
# env.Append(CCFLAGS = ' -D_GLIBCXX_PARALLEL');
|
||||||
|
if not (conf.CheckBoost('1.41')):
|
||||||
|
print 'Boost version >= 1.41 needed'
|
||||||
|
Exit(-1);
|
||||||
|
#check for protobuf 2.3.0, else rebuild proto files
|
||||||
|
if not (conf.CheckProtobuf('2.3.0')):
|
||||||
|
print 'libprotobuf version >= 2.3.0 needed'
|
||||||
|
Exit(-1);
|
||||||
|
if not (env.Detect('protoc')):
|
||||||
|
print 'protobuffer compiler not found'
|
||||||
|
|
||||||
|
|
||||||
protobld = Builder(action = 'protoc -I=DataStructures/pbf-proto --cpp_out=DataStructures/pbf-proto $SOURCE')
|
protobld = Builder(action = 'protoc -I=DataStructures/pbf-proto --cpp_out=DataStructures/pbf-proto $SOURCE')
|
||||||
env.Append(BUILDERS = {'Protobuf' : protobld})
|
env.Append(BUILDERS = {'Protobuf' : protobld})
|
||||||
env.Protobuf('DataStructures/pbf-proto/fileformat.proto')
|
env.Protobuf('DataStructures/pbf-proto/fileformat.proto')
|
||||||
env.Protobuf('DataStructures/pbf-proto/osmformat.proto')
|
env.Protobuf('DataStructures/pbf-proto/osmformat.proto')
|
||||||
env.Append(CCFLAGS = ['-fopenmp'])
|
#env.Append(LINKFLAGS = ['-lboost_system'])
|
||||||
env.Append(LINKFLAGS = ['-fopenmp'])
|
|
||||||
|
|
||||||
env.Program(target = 'osrm-extract', source = ["extractor.cpp", Glob('DataStructures/pbf-proto/*.pb.cc'), Glob('Util/*.cpp')])
|
env.Program(target = 'test/osrm-extract', source = ["extractor.cpp", 'DataStructures/pbf-proto/fileformat.pb.cc', 'DataStructures/pbf-proto/osmformat.pb.cc'])
|
||||||
env.Program(target = 'osrm-prepare', source = ["createHierarchy.cpp", 'Contractor/EdgeBasedGraphFactory.cpp', Glob('Util/SRTMLookup/*.cpp')])
|
env.Program(target = 'test/osrm-prepare', source = ["createHierarchy.cpp", 'Contractor/EdgeBasedGraphFactory.cpp'])
|
||||||
env.Append(CCFLAGS = ['-lboost_regex', '-lboost_iostreams', '-lbz2', '-lz', '-lprotobuf'])
|
env.Program(target = 'test/osrm-routed', source = ["routed.cpp", 'Descriptors/DescriptionFactory.cpp'])
|
||||||
env.Append(LINKFLAGS = ['-lboost_system'])
|
|
||||||
env.Program(target = 'osrm-routed', source = ["routed.cpp", 'Descriptors/DescriptionFactory.cpp'], CCFLAGS = ['-DROUTED'])
|
|
||||||
env = conf.Finish()
|
env = conf.Finish()
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
Threads = 4
|
|
||||||
SRTM = /opt/storage/srtm/Eurasia
|
|
||||||
@ -1 +0,0 @@
|
|||||||
Memory = 2
|
|
||||||
25
features/0_process.feature
Normal file
25
features/0_process.feature
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
@process
|
||||||
|
Feature: Preprocessing OpenStreetMap data
|
||||||
|
In order to enable efficient routing
|
||||||
|
As the OSRM server
|
||||||
|
I want to be able to preprocess OpenStreetMap data
|
||||||
|
|
||||||
|
Scenario: Processing OpenStreetMap data using bicycle profile
|
||||||
|
Given I am in the test folder
|
||||||
|
And the data file "data/kbh.osm.pbf" is present
|
||||||
|
And the "bicycle" speedprofile is used
|
||||||
|
|
||||||
|
When I run the extractor with "./osrm-extract data/kbh.osm.pbf"
|
||||||
|
Then the response should include "extracting data from input file data/kbh.osm.pbf"
|
||||||
|
And the response should include 'Using profile "bicycle"'
|
||||||
|
And the response should include "[extractor] finished"
|
||||||
|
And I should see the file "data/kbh.osrm"
|
||||||
|
And I should see the file "data/kbh.osrm.names"
|
||||||
|
And I should see the file "data/kbh.osrm.restrictions"
|
||||||
|
|
||||||
|
When I run the preprocessor with "./osrm-prepare data/kbh.osrm data/kbh.osrm.restrictions"
|
||||||
|
Then the response should include "finished preprocessing"
|
||||||
|
And I should see the file "data/kbh.osrm.hsgr"
|
||||||
|
And I should see the file "data/kbh.osrm.nodes"
|
||||||
|
And I should see the file "data/kbh.osrm.ramIndex"
|
||||||
|
And I should see the file "data/kbh.osrm.fileIndex"
|
||||||
13
features/1_launch.feature
Normal file
13
features/1_launch.feature
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@launch
|
||||||
|
Feature: Launching OSRM server
|
||||||
|
In order to handle routing request
|
||||||
|
As a user
|
||||||
|
I want to launch the OSRM server
|
||||||
|
|
||||||
|
Scenario: Launching the OSRM server
|
||||||
|
Given I am in the test folder
|
||||||
|
And the preprocessed files for "data/kbh" are present and up to date
|
||||||
|
When I start the server with "./osrm-routed"
|
||||||
|
Then a process called "osrm-routed" should be running
|
||||||
|
And I should see "running and waiting for requests" on the terminal
|
||||||
|
|
||||||
20
features/bicycle.feature
Normal file
20
features/bicycle.feature
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
@routing @bicycle
|
||||||
|
Feature: Bicycle Routing from A to B
|
||||||
|
To enable bicycle routing
|
||||||
|
OSRM should handle all relevant bicycle tags
|
||||||
|
|
||||||
|
Scenario: oneway:bicycle
|
||||||
|
When I request a route from 55.673168935147,12.563557740441 to 55.67380116846,12.563107129324&
|
||||||
|
Then I should get a route
|
||||||
|
And the route should follow "Banegårdspladsen"
|
||||||
|
And there should not be any turns
|
||||||
|
And the distance should be close to 80m
|
||||||
|
|
||||||
|
Scenario: cycleway=opposite_lane
|
||||||
|
When I request a route from 55.689126237262,12.553137305887 to 55.688666612359,12.55296564451
|
||||||
|
Then I should get a route
|
||||||
|
And the route should follow "Kapelvej"
|
||||||
|
And there should not be any turns
|
||||||
|
And the distance should be close to 50m
|
||||||
|
|
||||||
|
|
||||||
49
features/restrictions.feature
Normal file
49
features/restrictions.feature
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
@routing @restrictions
|
||||||
|
Feature: Turn restrictions
|
||||||
|
OSRM should handle turn restrictions
|
||||||
|
|
||||||
|
Scenario: No left turn when crossing a oneway street
|
||||||
|
When I request a route from 55.689741159238,12.574720202639 to 55.689741159232,12.57455927015
|
||||||
|
Then I should get a route
|
||||||
|
And the route should start at "Sølvgade"
|
||||||
|
And the route should end at "Øster Farimagsgade"
|
||||||
|
And the route should not include "Sølvgade, Øster Farimagsgade"
|
||||||
|
And no error should be reported in terminal
|
||||||
|
|
||||||
|
Scenario: No left turn at T-junction: Don't turn left from side road into main road
|
||||||
|
When I request a route from 55.66442995717,12.549384056343 to 55.664218154805,12.5502638209
|
||||||
|
Then I should get a route
|
||||||
|
And the route should start at "Sigerstedgade"
|
||||||
|
And the route should end at "Ingerslevsgade"
|
||||||
|
And the route should not include "Sigerstedgade, Ingerslevsgade"
|
||||||
|
And there should be more than 1 turn
|
||||||
|
|
||||||
|
Scenario: No left turn at T-junction: OK to turn right from side road into main road
|
||||||
|
When I request a route from 55.66442995717,12.549384056343 to 55.664060815164,12.548944174065
|
||||||
|
Then I should get a route
|
||||||
|
And the route should start at "Sigerstedgade"
|
||||||
|
And the route should end at "Ingerslevsgade"
|
||||||
|
And the route should include "Sigerstedgade, Ingerslevsgade"
|
||||||
|
And there should be 1 turn
|
||||||
|
|
||||||
|
Scenario: No left turn at T-junction: OK to go straight on main road
|
||||||
|
When I request a route from 55.66419092299,12.550333558335 to 55.664060815164,12.548944174065
|
||||||
|
Then I should get a route
|
||||||
|
And the route should stay on "Ingerslevsgade"
|
||||||
|
|
||||||
|
Scenario: No left turn at T-junction: OK to turn right from main road into side road
|
||||||
|
When I request a route from 55.664060815164,12.548944174065 to 55.66442995717,12.549384056343
|
||||||
|
Then I should get a route
|
||||||
|
And the route should start at "Ingerslevsgade"
|
||||||
|
And the route should end at "Sigerstedgade"
|
||||||
|
And the route should include "Ingerslevsgade, Sigerstedgade"
|
||||||
|
And there should be 1 turn
|
||||||
|
|
||||||
|
Scenario: No left turn at T-junction: OK to turn left from main road into side road
|
||||||
|
When I request a route from 55.664218154805,12.5502638209 to 55.66442995717,12.549384056343
|
||||||
|
Then I should get a route
|
||||||
|
And the route should start at "Ingerslevsgade"
|
||||||
|
And the route should end at "Sigerstedgade"
|
||||||
|
And the route should include "Ingerslevsgade, Sigerstedgade"
|
||||||
|
And there should be 1 turn
|
||||||
|
|
||||||
41
features/routing.feature
Normal file
41
features/routing.feature
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
@routing
|
||||||
|
Feature: Routing from A to B
|
||||||
|
In order to make it easier to navigate
|
||||||
|
As someone using the public road network
|
||||||
|
I want to be able to use OSRM to compute routes based on OpenStreetMap data
|
||||||
|
|
||||||
|
Scenario: Phantom shortcut
|
||||||
|
When I request a route from 55.662740149207,12.576105114488& to 55.665753800212,12.575547215013
|
||||||
|
Then I should get a route
|
||||||
|
And the distance should be close to 450m
|
||||||
|
|
||||||
|
Scenario: Start and stop markers should snap to closest streets
|
||||||
|
When I request a route from 55.6634,12.5724 to 55.6649,12.5742
|
||||||
|
Then I should get a route
|
||||||
|
And the route should stay on "Islands Brygge"
|
||||||
|
And the distance should be close to 200m
|
||||||
|
|
||||||
|
Scenario: Crossing roundabout at Amalienborg
|
||||||
|
When I request a route from 55.683797649183,12.593940686704 to 55.6842149924,12.592476200581
|
||||||
|
Then I should get a route
|
||||||
|
And the distance should be close to 150m
|
||||||
|
|
||||||
|
Scenario: Requesting invalid routes
|
||||||
|
When I request a route from 0,0 to 0,0
|
||||||
|
Then I should not get a route
|
||||||
|
And no error should be reported in terminal
|
||||||
|
|
||||||
|
Scenario: Dont flicker
|
||||||
|
When I request a route from 55.658833555366,12.592788454378 to 55.663871808364,12.583497282355
|
||||||
|
Then I should get a route
|
||||||
|
And the route should follow "Amagerfælledvej, Njalsgade, Artillerivej"
|
||||||
|
And no error should be reported in terminal
|
||||||
|
When I request a route from 55.658821450674,12.592466589296 to 55.663871808364,12.583497282355
|
||||||
|
Then I should get a route
|
||||||
|
And the route should follow "Kaj Munks Vej, Tom Kristensens Vej, Ørestads Boulevard, Njalsgade, Artillerivej"
|
||||||
|
And no error should be reported in terminal
|
||||||
|
When I request a route from 55.658857764739,12.592058893525 to 55.663871808364,12.583497282355
|
||||||
|
Then I should get a route
|
||||||
|
And the route should follow "Kaj Munks Vej, Tom Kristensens Vej, Ørestads Boulevard, Njalsgade, Artillerivej"
|
||||||
|
And no error should be reported in terminal
|
||||||
|
|
||||||
78
features/step_definitions/launch.rb
Normal file
78
features/step_definitions/launch.rb
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
require 'pathname'
|
||||||
|
require 'json'
|
||||||
|
require 'open4'
|
||||||
|
require "net/http"
|
||||||
|
require "uri"
|
||||||
|
|
||||||
|
$stdout.sync = true
|
||||||
|
$server_pipe = nil
|
||||||
|
$server_running = false
|
||||||
|
|
||||||
|
def read_terminal
|
||||||
|
return $server_pipe.read_nonblock 10000 rescue nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def launch cmd
|
||||||
|
$server_pipe = IO.popen(cmd)
|
||||||
|
sleep 2 # so the daemon has a chance to boot
|
||||||
|
|
||||||
|
at_exit do
|
||||||
|
Process.kill("KILL", $server_pipe.pid) # clean up the daemon when the tests finish
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Given /^I am in the test folder$/ do
|
||||||
|
@root = Pathname.new(File.dirname(__FILE__)).parent.parent.expand_path
|
||||||
|
@test_folder = "#{@root}/test"
|
||||||
|
Dir.chdir @test_folder
|
||||||
|
end
|
||||||
|
|
||||||
|
Given /^the server is configured for bike routing$/ do
|
||||||
|
pending # express the regexp above with the code you wish you had
|
||||||
|
end
|
||||||
|
|
||||||
|
Given /^the "([^"]*)" speedprofile is used$/ do |profile|
|
||||||
|
FileUtils.cp "speedprofiles/#{profile}.ini", "speedprofile.ini"
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the response should include "([^"]*)"$/ do |string|
|
||||||
|
@response.include?(string).should_not == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the response should include '([^']*)'$/ do |string|
|
||||||
|
@response.include?(string).should_not == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
Given /^the server is running$/ do
|
||||||
|
unless $server_running
|
||||||
|
step 'a process called "osrm-routed" should be running'
|
||||||
|
@server_running = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I start the server with "([^']*)"$/ do |cmd|
|
||||||
|
launch cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I stop the server$/ do
|
||||||
|
Process.kill("KILL", $server_pipe.pid)
|
||||||
|
$server_pipe = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^a process called "([^']*)" should be running$/ do |daemon|
|
||||||
|
`ps -eo command | grep #{@test_folder}/#{daemon}`.size.should > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^a process called "([^']*)" should not be running$/ do |daemon|
|
||||||
|
puts `ps -eo command | grep #{@test_folder}/#{daemon}$`
|
||||||
|
`ps -eo command | grep #{@test_folder}/#{daemon}$`.size.should == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should see "([^']*)" on the terminal$/ do |string|
|
||||||
|
out = read_terminal
|
||||||
|
out.should =~ /#{string}/
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^no error should be reported in terminal$/ do
|
||||||
|
read_terminal.should_not =~ /error/
|
||||||
|
end
|
||||||
28
features/step_definitions/processing.rb
Normal file
28
features/step_definitions/processing.rb
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
Given /^the data file "([^"]*)" is present$/ do |file|
|
||||||
|
File.exists?(file).should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I run the extractor with "([^"]*)"$/ do |cmd|
|
||||||
|
@response = `#{cmd}`
|
||||||
|
#Dir.chdir @test_folder do
|
||||||
|
# @response = IO.popen([cmd, :err=>[:child, :out]]) { |ls_io| ls_result_with_error = ls_io.read }
|
||||||
|
#end
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I run the preprocessor with "([^"]*)"$/ do |cmd|
|
||||||
|
@response = `#{cmd}`
|
||||||
|
end
|
||||||
|
|
||||||
|
Given /^the preprocessed files for "([^"]*)" are present and up to date$/ do |area|
|
||||||
|
File.exists?("#{area}.osrm").should == true
|
||||||
|
File.exists?("#{area}.osrm.names").should == true
|
||||||
|
File.exists?("#{area}.osrm.restrictions").should == true
|
||||||
|
File.exists?("#{area}.osrm.hsgr").should == true
|
||||||
|
File.exists?("#{area}.osrm.nodes").should == true
|
||||||
|
File.exists?("#{area}.osrm.ramIndex").should == true
|
||||||
|
File.exists?("#{area}.osrm.fileIndex").should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should see the file "([^"]*)"$/ do |file|
|
||||||
|
File.exists?(file).should == true
|
||||||
|
end
|
||||||
138
features/step_definitions/routing.rb
Normal file
138
features/step_definitions/routing.rb
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
|
||||||
|
def request_route a,b
|
||||||
|
uri = URI.parse "http://localhost:5000/viaroute&start=#{a}&dest=#{b}&output=json&geomformat=cmp"
|
||||||
|
Net::HTTP.get_response uri
|
||||||
|
rescue Errno::ECONNREFUSED => e
|
||||||
|
raise "NOTE: The OSRM server is not running. Start it manully, or include tests that start it."
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I request a route from (.+) to (.+)$/ do |a,b|
|
||||||
|
@response = request_route a,b
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I request a route from "([^"]*)" to "([^"]*)"$/ do |a,b|
|
||||||
|
pending
|
||||||
|
#store hash og adress => coordinate points in a file under version control
|
||||||
|
#if the adress is not found, then use nominatim to get one and store it in the file
|
||||||
|
|
||||||
|
#TODO convert a/b from adress to coordinate
|
||||||
|
#@response = request_route a,b
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should get a response/ do
|
||||||
|
@response.code.should == "200"
|
||||||
|
@response.body.should_not == nil
|
||||||
|
@response.body.should_not == ''
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^response should be valid JSON$/ do
|
||||||
|
@json = JSON.parse @response.body
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^response should be well-formed$/ do
|
||||||
|
@json['version'].class.should == Float
|
||||||
|
@json['status'].class.should == Fixnum
|
||||||
|
@json['status_message'].class.should == String
|
||||||
|
@json['route_summary'].class.should == Hash
|
||||||
|
@json['route_geometry'].class.should == String
|
||||||
|
@json['route_instructions'].class.should == Array
|
||||||
|
@json['via_points'].class.should == Array
|
||||||
|
@json['transactionId'].class.should == String
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^a route should be found$/ do
|
||||||
|
@json['status'].should == 0
|
||||||
|
@json['status_message'].should == "Found route between points"
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^no route should be found$/ do
|
||||||
|
@json['status'].should == 207
|
||||||
|
@json['status_message'].should == "Cannot find route between points"
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should get a valid response$/ do
|
||||||
|
step "I should get a response"
|
||||||
|
step "response should be valid JSON"
|
||||||
|
step "response should be well-formed"
|
||||||
|
step "no error should be reported in terminal"
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should get a route$/ do
|
||||||
|
step "I should get a valid response"
|
||||||
|
step "a route should be found"
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should not get a route$/ do
|
||||||
|
step "I should get a valid response"
|
||||||
|
step "no route should be found"
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the route should start at "([^']*)"$/ do |name|
|
||||||
|
@json['route_summary']['start_point'].should == name
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the route should end at "([^']*)"$/ do |name|
|
||||||
|
@json['route_summary']['end_point'].should == name
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^distance should be between (\d+) and (\d+)$/ do |min,max|
|
||||||
|
@json['route_summary']['total_distance'].to_i.should >= min.to_i
|
||||||
|
@json['route_summary']['total_distance'].to_i.should <= max.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the distance should be close to (\d+)m$/ do |d|
|
||||||
|
@json['route_summary']['total_distance'].to_i.should >= d.to_i*0.95
|
||||||
|
@json['route_summary']['total_distance'].to_i.should <= d.to_i/0.95
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^number of instructions should be (\d+)$/ do |n|
|
||||||
|
@json['route_instructions'].size.should == n
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^there should be 1 turn$/ do
|
||||||
|
step 'there should be 1 turns'
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^there should be (\d+) turns$/ do |n|
|
||||||
|
@json['route_instructions'].map {|t| t.first}.select {|t| t =~ /^Turn/ }.size.should == n.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^there should be more than (\d+) turn$/ do |n|
|
||||||
|
@json['route_instructions'].map {|t| t.first}.select {|t| t =~ /^Turn/ }.size.should > n.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^there should not be any turns$/ do
|
||||||
|
(@json['route_instructions'].size-1).should == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def sanitize_route route
|
||||||
|
route.split(',').map{|w| w.strip}.reject(&:empty?).join(', ')
|
||||||
|
end
|
||||||
|
|
||||||
|
def computed_route
|
||||||
|
@json['route_instructions'].map { |r| r[1] }.reject(&:empty?).join(', ')
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the route should follow "([^"]*)"$/ do |route|
|
||||||
|
computed_route.should == sanitize_route(route)
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the route should not follow "([^"]*)"$/ do |route|
|
||||||
|
computed_route.should_not == sanitize_route(route)
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the route should include "([^"]*)"$/ do |route|
|
||||||
|
sanitize_route(route).should =~ /#{computed_route}/
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the route should not include "([^"]*)"$/ do |route|
|
||||||
|
sanitize_route(route).should_not =~ /#{computed_route}/
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the route should stay on "([^"]*)"$/ do |way|
|
||||||
|
step "the route should start at \"#{way}\""
|
||||||
|
step "the route should end at \"#{way}\""
|
||||||
|
step "the route should follow \"#{way}\""
|
||||||
|
step "there should not be any turns"
|
||||||
|
end
|
||||||
|
|
||||||
10
server.ini
10
server.ini
@ -2,8 +2,8 @@ Threads = 8
|
|||||||
IP = 0.0.0.0
|
IP = 0.0.0.0
|
||||||
Port = 5000
|
Port = 5000
|
||||||
|
|
||||||
hsgrData=/opt/osm/germany.osrm.hsgr
|
hsgrData=data/kbh.osrm.hsgr
|
||||||
nodesData=/opt/osm/germany.osrm.nodes
|
nodesData=data/kbh.osrm.nodes
|
||||||
ramIndex=/opt/osm/germany.osrm.ramIndex
|
ramIndex=data/kbh.osrm.ramIndex
|
||||||
fileIndex=/opt/osm/germany.osrm.fileIndex
|
fileIndex=data/kbh.osrm.fileIndex
|
||||||
namesData=/opt/osm/germany.osrm.names
|
namesData=data/kbh.osrm.names
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
[car]
|
|
||||||
motorway = 110
|
|
||||||
motorway_link = 90
|
|
||||||
trunk = 90
|
|
||||||
trunk_link = 70
|
|
||||||
primary = 70
|
|
||||||
primary_link = 60
|
|
||||||
secondary = 60
|
|
||||||
secondary_link = 50
|
|
||||||
tertiary = 55
|
|
||||||
unclassified = 25
|
|
||||||
residential = 40
|
|
||||||
living_street = 10
|
|
||||||
service = 30
|
|
||||||
ferry = 5
|
|
||||||
pier = 5
|
|
||||||
obeyBollards = yes
|
|
||||||
obeyOneways = yes
|
|
||||||
useRestrictions = yes
|
|
||||||
accessTag = motorcar
|
|
||||||
excludeFromGrid = ferry
|
|
||||||
defaultSpeed = 50
|
|
||||||
trafficLightPenalty = 15
|
|
||||||
[bike]
|
|
||||||
trunk = 16
|
|
||||||
trunk_link = 16
|
|
||||||
primary = 16
|
|
||||||
primary_link = 16
|
|
||||||
secondary = 16
|
|
||||||
secondary_link = 16
|
|
||||||
tertiary = 16
|
|
||||||
unclassified = 16
|
|
||||||
residential = 16
|
|
||||||
living_street = 16
|
|
||||||
service = 16
|
|
||||||
track = 16
|
|
||||||
cycleway = 16
|
|
||||||
path = 16
|
|
||||||
ferry = 5
|
|
||||||
pier = 5
|
|
||||||
obeyOneways = yes
|
|
||||||
useRestrictions = no
|
|
||||||
accessTag = bicycle
|
|
||||||
excludeFromGrid = ferry
|
|
||||||
defaultSpeed = 5
|
|
||||||
trafficLightPenalty = 15
|
|
||||||
obeyBollards = no
|
|
||||||
|
|
||||||
2
test/contractor.ini
Normal file
2
test/contractor.ini
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Threads = 4
|
||||||
|
SRTM = data/srtm/Eurasia
|
||||||
BIN
test/data/kbh.osm.pbf
Normal file
BIN
test/data/kbh.osm.pbf
Normal file
Binary file not shown.
9
test/server.ini
Normal file
9
test/server.ini
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Threads = 8
|
||||||
|
IP = 0.0.0.0
|
||||||
|
Port = 5000
|
||||||
|
|
||||||
|
hsgrData=data/kbh.osrm.hsgr
|
||||||
|
nodesData=data/kbh.osrm.nodes
|
||||||
|
ramIndex=data/kbh.osrm.ramIndex
|
||||||
|
fileIndex=data/kbh.osrm.fileIndex
|
||||||
|
namesData=data/kbh.osrm.names
|
||||||
28
test/speedprofiles/bicycle.ini
Normal file
28
test/speedprofiles/bicycle.ini
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[bicycle]
|
||||||
|
cycleway = 19
|
||||||
|
trunk = 19
|
||||||
|
trunk_link = 19
|
||||||
|
primary = 19
|
||||||
|
primary_link = 19
|
||||||
|
secondary = 17
|
||||||
|
secondary_link = 17
|
||||||
|
tertiary = 15
|
||||||
|
residential = 15
|
||||||
|
unclassified = 15
|
||||||
|
living_street = 13
|
||||||
|
service = 12
|
||||||
|
track = 12
|
||||||
|
path = 12
|
||||||
|
footway = 10
|
||||||
|
pedestrian = 5
|
||||||
|
pier = 5
|
||||||
|
steps = 3
|
||||||
|
ferry = 5
|
||||||
|
obeyOneways = yes
|
||||||
|
useRestrictions = yes
|
||||||
|
accessTag = bicycle
|
||||||
|
excludeFromGrid = ferry
|
||||||
|
defaultSpeed = 17
|
||||||
|
obeyBollards = no
|
||||||
|
trafficLightPenalty = 20
|
||||||
|
|
||||||
22
test/speedprofiles/car.ini
Normal file
22
test/speedprofiles/car.ini
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[car]
|
||||||
|
motorway = 110
|
||||||
|
motorway_link = 90
|
||||||
|
trunk = 90
|
||||||
|
trunk_link = 70
|
||||||
|
primary = 70
|
||||||
|
primary_link = 60
|
||||||
|
secondary = 60
|
||||||
|
secondary_link = 50
|
||||||
|
tertiary = 55
|
||||||
|
unclassified = 25
|
||||||
|
residential = 40
|
||||||
|
living_street = 10
|
||||||
|
service = 30
|
||||||
|
ferry = 5
|
||||||
|
pier = 5
|
||||||
|
barrier = bollard
|
||||||
|
obeyOneways = yes
|
||||||
|
useRestrictions = yes
|
||||||
|
accessTag = motorcar
|
||||||
|
excludeFromGrid = ferry
|
||||||
|
defaultSpeed = 50
|
||||||
25
test/speedprofiles/ebike.ini
Normal file
25
test/speedprofiles/ebike.ini
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
[ebike]
|
||||||
|
cycleway = 25
|
||||||
|
trunk = 25
|
||||||
|
trunk_link = 25
|
||||||
|
primary = 25
|
||||||
|
primary_link = 25
|
||||||
|
secondary = 25
|
||||||
|
secondary_link = 25
|
||||||
|
tertiary = 25
|
||||||
|
unclassified = 25
|
||||||
|
residential = 25
|
||||||
|
living_street = 20
|
||||||
|
service = 20
|
||||||
|
track = 20
|
||||||
|
path = 15
|
||||||
|
ferry = 5
|
||||||
|
pier = 5
|
||||||
|
pedestrian = 5
|
||||||
|
footway = 5
|
||||||
|
steps = 3
|
||||||
|
obeyOneways = yes
|
||||||
|
useRestrictions = no
|
||||||
|
accessTag = bicycle
|
||||||
|
excludeFromGrid = ferry
|
||||||
|
defaultSpeed = 25
|
||||||
Loading…
Reference in New Issue
Block a user