From a60ed5c78ab78dbd602f9c0a282f3ee43943a7cc Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Sun, 29 Jan 2012 12:50:29 +0100 Subject: [PATCH] cucumber test using tables --- .gitignore | 2 + Rakefile | 62 +++++++- createHierarchy.cpp | 2 +- features/basic.feature | 73 ++++++++++ features/bicycle.feature | 15 -- features/{routing.feature => kbh.feature} | 8 +- features/oneways.feature | 96 +++++++++++++ features/other.feature | 65 +++++++++ features/outlines.feature | 25 ++++ features/restrictions.feature | 63 +++------ features/step_definitions/launch.rb | 28 +++- features/step_definitions/processing.rb | 56 ++++++++ features/step_definitions/routing.rb | 83 +++++++++-- features/step_definitions/test_data.rb | 165 ++++++++++++++++++++++ test/extractor.ini | 1 + test/server.ini | 10 +- test/speedprofiles/default.ini | 9 ++ 17 files changed, 677 insertions(+), 86 deletions(-) create mode 100644 features/basic.feature rename features/{routing.feature => kbh.feature} (89%) create mode 100644 features/oneways.feature create mode 100644 features/other.feature create mode 100644 features/outlines.feature create mode 100644 features/step_definitions/test_data.rb create mode 100644 test/extractor.ini create mode 100644 test/speedprofiles/default.ini diff --git a/.gitignore b/.gitignore index 9a799a881..c8687aed3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ test/data/*.osrm test/data/*.osrm.* test/data/denmark.osm.pbf test/data/regh.osm.pbf +test/data/test.osm +test/data/test.osm.pbf # Compiled source # ################### diff --git a/Rakefile b/Rakefile index 93a3f3c8a..bc9514e3f 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +require 'OSM/StreamParser' + #$:.unshift(File.dirname(__FILE__) + '/../../lib') require 'cucumber/rake/task' @@ -6,13 +8,14 @@ Cucumber::Rake::Task.new do |t| end areas = { + :test => {}, :kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' }, :frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' }, :regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' }, :dk => { :country => 'denmark', :bbox => nil }, :skaane => { :counry => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' } } -osm_data_area_name = ENV['area'].to_s.to_sym || :kbh +osm_data_area_name = ENV['area'] ? ENV['area'].to_s.to_sym : :test raise "Unknown data area." unless areas[osm_data_area_name] osm_data_country = areas[osm_data_area_name][:country] osm_data_area_bbox = areas[osm_data_area_name][:bbox] @@ -27,7 +30,7 @@ task :build do end namespace :data do - desc "Download OSM data extract for Denmark, and crop test areas" + desc "Download OSM data" 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" if osm_data_area_bbox @@ -35,6 +38,7 @@ namespace :data do end end + desc "Crop OSM data" task :crop do if osm_data_area_bbox 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" @@ -45,7 +49,17 @@ namespace :data do 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" + puts raise "Error while preparing data." unless system "./osrm-prepare data/#{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions" + puts + end + end + + desc "Convert test file to protobuffer format" + task :protofy do + Dir.chdir "test" do + system "osmosis --read-xml data/test.osm --write-pbf data/test.osm.pbf omitmetadata=true" + puts end end @@ -54,6 +68,7 @@ namespace :data do File.delete *Dir.glob('test/data/*.osrm') File.delete *Dir.glob('test/data/*.osrm.*') end + end desc "Launch the routing server" @@ -65,5 +80,46 @@ end desc "Run all test" task :test do - puts "Test would go here..." + system "cucumber --tags @syn" + puts end + +desc "Prepare test data" +task :prep => ['data:protofy', 'data:process'] do +end + + + + +class OSMTestParserCallbacks < OSM::Callbacks + attr_accessor :locations + + def initialize + @locations = {} + end + def node(node) + puts node + @locations[node.name] = [node.lat,node.lon] + end + + def way(way) + puts way + end + + def relation(relation) + puts relation + end +end + + +task :read do + Dir.chdir "test" do + file = 'data/test.osm' + callbacks = OSMTestParserCallbacks.new + parser = OSM::StreamParser.new(:filename => file, :callbacks => callbacks) + parser.parse + puts callbacks.locations + end +end + + diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 17b6e37ed..cd3e69657 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -79,7 +79,7 @@ int main (int argc, char *argv[]) { INFO("Loading SRTM from/to " << SRTM_ROOT); omp_set_num_threads(numberOfThreads); - INFO("preprocessing data from input file " << argv[2] << " using STL " + INFO("preprocessing data from input file " << argv[1] << " using STL " #ifdef _GLIBCXX_PARALLEL "parallel (GCC)" #else diff --git a/features/basic.feature b/features/basic.feature new file mode 100644 index 000000000..860801130 --- /dev/null +++ b/features/basic.feature @@ -0,0 +1,73 @@ +@routing @basic +Feature: Basic Routing + + Scenario: Smallest possible datasat + Given the nodes + | a | b | + + And the ways + | nodes | + | ab | + + When I route I should get + | from | to | route | + | a | b | ab | + | b | a | ba | + + Scenario: Connected ways + Given the nodes + | a | | c | + | | b | | + + And the ways + | nodes | + | ab | + | bc | + + When I route I should get + | from | to | route | + | a | c | abc | + | c | a | cba | + | a | b | ab | + | b | a | ba | + | b | c | bc | + | c | b | cb | + + Scenario: Unconnected ways + Given the nodes + | a | b | + | c | d | + + And the ways + | nodes | + | ab | + | cd | + + When I route I should get + | from | to | route | + | a | b | ab | + | b | a | ba | + | c | d | cd | + | d | c | dc | + | a | c | | + | c | a | | + | b | d | | + | d | c | | + | a | d | | + | d | a | | + + Scenario: Pick the fastest way type + Given the nodes + | a | s | + | p | b | + + And the ways + | nodes | highway | + | apb | primary | + | asb | secondary | + + When I route I should get + | from | to | route | + | a | b | apb | + | b | a | bpa | + diff --git a/features/bicycle.feature b/features/bicycle.feature index a15b86456..4c041cda8 100644 --- a/features/bicycle.feature +++ b/features/bicycle.feature @@ -3,18 +3,3 @@ 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 - - diff --git a/features/routing.feature b/features/kbh.feature similarity index 89% rename from features/routing.feature rename to features/kbh.feature index 0179bc7dd..2dbd53f11 100644 --- a/features/routing.feature +++ b/features/kbh.feature @@ -1,8 +1,5 @@ @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 +Feature: Real-world routing test in the Copenhagen area Scenario: Phantom shortcut When I request a route from 55.662740149207,12.576105114488& to 55.665753800212,12.575547215013 @@ -19,7 +16,7 @@ Feature: Routing from A to B 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 @@ -38,4 +35,3 @@ Feature: Routing from A to B 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 - \ No newline at end of file diff --git a/features/oneways.feature b/features/oneways.feature new file mode 100644 index 000000000..ea4cd5b6e --- /dev/null +++ b/features/oneways.feature @@ -0,0 +1,96 @@ +@routing @oneways +Feature: Oneway streets + Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing + + Scenario: Implied oneways + Then routability should be + | highway | junction | forw | backw | + | motorway | | x | x | + | motorway_link | | x | | + | trunk | | x | x | + | trunk_link | | x | | + | primary | roundabout | x | | + + Scenario: Overriding implied oneways + Then routability should be + | highway | junction | oneway | forw | backw | + | motorway_link | | no | x | x | + | trunk_link | | no | x | x | + | primary | roundabout | no | x | x | + | motorway_link | | -1 | | x | + | trunk_link | | -1 | | x | + | primary | roundabout | -1 | | x | + + Scenario: Handle various oneway tag values + Then routability should be + | highway | oneway | forw | backw | + | primary | | x | x | + | primary | nonsense | x | x | + | primary | no | x | x | + | primary | false | x | x | + | primary | 0 | x | x | + | primary | yes | x | | + | primary | true | x | | + | primary | 1 | x | | + | primary | -1 | | x | + + Scenario: Disabling oneways in speedprofile + Given the speedprofile + | obeyOneways | no | + + Then routability should be + | highway | junction | oneway | forw | backw | + | primary | | yes | x | x | + | primary | | true | x | x | + | primary | | 1 | x | x | + | primary | | -1 | x | x | + | motorway_link | | | x | x | + | trunk_link | | | x | x | + | primary | roundabout | | x | x | + + Scenario: Oneways and bicycles + Given the speedprofile + | accessTag | bicycle | + + Then routability should be + | highway | junction | oneway | oneway:bicycle | forw | backw | + | primary | | | yes | x | | + | primary | | yes | yes | x | | + | primary | | no | yes | x | | + | primary | | -1 | yes | x | | + | motorway | | | yes | x | | + | motorway_link | | | yes | x | | + | primary | roundabout | | yes | x | | + | primary | | | no | x | x | + | primary | | yes | no | x | x | + | primary | | no | no | x | x | + | primary | | -1 | no | x | x | + | motorway | | | no | x | x | + | motorway_link | | | no | x | x | + | primary | roundabout | | no | x | x | + | primary | | | -1 | | x | + | primary | | yes | -1 | | x | + | primary | | no | -1 | | x | + | primary | | -1 | -1 | | x | + | motorway | | | -1 | | x | + | motorway_link | | | -1 | | x | + | primary | roundabout | | -1 | | x | + + Scenario: Cars should not be affected by bicycle tags + Given the speedprofile + | accessTag | motorcar | + + Then routability should be + | highway | junction | oneway | oneway:bicycle | forw | backw | + | primary | | yes | yes | x | | + | primary | | yes | no | x | | + | primary | | yes | -1 | x | | + | primary | | no | yes | x | x | + | primary | | no | no | x | x | + | primary | | no | -1 | x | x | + | primary | | -1 | yes | | x | + | primary | | -1 | no | | x | + | primary | | -1 | -1 | | x | + | primary | roundabout | | yes | x | | + | primary | roundabout | | no | x | | + | primary | roundabout | | -1 | x | | diff --git a/features/other.feature b/features/other.feature new file mode 100644 index 000000000..2b2cd636f --- /dev/null +++ b/features/other.feature @@ -0,0 +1,65 @@ +@other +Feature: Other stuff + +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 + + + +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 + + diff --git a/features/outlines.feature b/features/outlines.feature new file mode 100644 index 000000000..1255bd50b --- /dev/null +++ b/features/outlines.feature @@ -0,0 +1,25 @@ +@outlines +Feature: Outlines + Scenario outlines is another way to test routes... not sure which method is best? + + Scenario Outline: ways + Given the nodes + | a | | c | + | | b | | + + And the ways + | nodes | + | ab | + | bc | + + When I route I between "" and "" + Then I should get the route "" + + Examples: + | from | to | route | + | a | c | abc | + | c | a | cba | + | a | b | ab | + | b | a | ba | + | b | c | bc | + | c | b | cb | diff --git a/features/restrictions.feature b/features/restrictions.feature index 3e832f409..4ecef9654 100644 --- a/features/restrictions.feature +++ b/features/restrictions.feature @@ -1,49 +1,28 @@ @routing @restrictions Feature: Turn restrictions - OSRM should handle turn restrictions + OSRM should handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction -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 + Given the nodes + | a | j | b | + | | s | | -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 + And the ways + | nodes | + | aj | + | jb | + | sj | -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" + And the relations + | from | to | via | restriction | + | sj | ja | j | no_left_turn | -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 + When I route I should get + | from | to | route | + | a | b | ajb | + | a | s | ajs | + | b | a | bja | + | b | s | bjs | + | s | a | | + | s | b | sjb | diff --git a/features/step_definitions/launch.rb b/features/step_definitions/launch.rb index d79c24ca9..c3895cf52 100644 --- a/features/step_definitions/launch.rb +++ b/features/step_definitions/launch.rb @@ -12,12 +12,26 @@ def read_terminal return $server_pipe.read_nonblock 10000 rescue nil end -def launch cmd +def running? + `ps -eo command | grep #{@test_folder}/osrm-running$`.size != 0 +end + +def launch cmd = "./osrm-routed" $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 + if $server_pipe + Process.kill("KILL", $server_pipe.pid) # clean up the daemon when the tests finish + end + end +end + +def kill + if $server_pipe + Process.kill("KILL", $server_pipe.pid) + $server_pipe = nil + sleep 2 # so the daemon has a chance to quit end end @@ -55,19 +69,23 @@ When /^I start the server with "([^']*)"$/ do |cmd| end When /^I stop the server$/ do - Process.kill("KILL", $server_pipe.pid) - $server_pipe = nil + kill end Then /^a process called "([^']*)" should be running$/ do |daemon| + #puts `ps -eo command | grep #{@test_folder}/#{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 /^a process called "([^']*)" is not running$/ do |daemon| + step "a process called \"#{daemon}\" should not be running" +end + + Then /^I should see "([^']*)" on the terminal$/ do |string| out = read_terminal out.should =~ /#{string}/ diff --git a/features/step_definitions/processing.rb b/features/step_definitions/processing.rb index 0d92db87b..d2f40f3dd 100644 --- a/features/step_definitions/processing.rb +++ b/features/step_definitions/processing.rb @@ -1,3 +1,48 @@ +require 'OSM/StreamParser' + +class OSMTestParserCallbacks < OSM::Callbacks + @@locations = nil + + def self.locations + if @@locations + @@locations + else + #parse the test file, so we can later reference nodes and ways by name in tests + @@locations = {} + file = 'test/data/test.osm' + callbacks = OSMTestParserCallbacks.new + parser = OSM::StreamParser.new(:filename => file, :callbacks => callbacks) + parser.parse + puts @@locations + end + end + + def node(node) + @@locations[node.name] = [node.lat,node.lon] + end + + def way(way) + end + + def relation(relation) + end +end + + +Given /^the OSM file contains$/ do |string| + file = 'data/test.osm' + File.open( file, 'w') {|f| f.write(string) } + + #convert from .osm to .osm.pbf, which is the format osrm reads + system "osmosis --read-xml data/test.osm --write-pbf data/test.osm.pbf omitmetadata=true" +end + +Given /^the speedprofile contains$/ do |string| + File.open( 'speedprofile.ini', 'w') {|f| f.write(string) } +end + + + Given /^the data file "([^"]*)" is present$/ do |file| File.exists?(file).should == true end @@ -26,3 +71,14 @@ end Then /^I should see the file "([^"]*)"$/ do |file| File.exists?(file).should == true end + +When /^preprocessed files for "([^"]*)" has been removed$/ do |file| + FileUtils.rm_r Dir["#{file}.*"], :secure => true +end + + +Given /^the speed profile$/ do |table| + table.hashes.each do |hash| + #Whatever you need to do + end +end \ No newline at end of file diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index bb41400c4..ab349367f 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -1,24 +1,29 @@ def request_route a,b uri = URI.parse "http://localhost:5000/viaroute&start=#{a}&dest=#{b}&output=json&geomformat=cmp" + #puts "routing: #{uri}" 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." + raise "*** osrm-routed is not running." +rescue Timeout::Error + raise "*** osrm-routed didn't respond." end -When /^I request a route from (.+) to (.+)$/ do |a,b| +When /^I request a route from ([^"]+) to ([^"]+)$/ do |a,b| @response = request_route a,b + #puts @response.body + #@response 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 + locations = OSMTestParserCallbacks.locations + raise "Locations hash is empty. To reference nodes by name, please preprocess the test file earlier in the test." unless locations + raise "Unknown node: #{a}" unless locations[a] + raise "Unknown node: #{b}" unless locations[b] + @response = request_route "#{locations[a][0]},#{locations[a][1]}", "#{locations[b][0]},#{locations[b][1]}" end + Then /^I should get a response/ do @response.code.should == "200" @response.body.should_not == nil @@ -54,12 +59,13 @@ 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" + #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" + puts @response.body end Then /^I should not get a route$/ do @@ -136,3 +142,62 @@ Then /^the route should stay on "([^"]*)"$/ do |way| step "there should not be any turns" end +def parse_response response + if response.code == "200" && response.body.empty? == false + json = JSON.parse response.body + puts response.body + if json['status'] == 0 + route = json['route_instructions'].map { |r| r[1] }.reject(&:empty?).join(', ') + if route.empty? + "Empty route: #{json['route_instructions']}" + else + route + end + elsif json['status'] == 207 + nil #no route found + else + "Status: #{json['status']}" + end + else + "HTTP: #{response.code}" + end +end + + +When /^I route I should get$/ do |table| + actual = [] + reprocess_if_needed + Dir.chdir 'test' do + launch + table.hashes.each do |row| + from_node = @name_node_hash[ row['from'] ] + to_node = @name_node_hash[ row['to'] ] + route = parse_response( request_route("#{from_node.lon},#{from_node.lat}", "#{to_node.lat},#{to_node.lat}") ) + actual << { 'from' => row['from'].dup, 'to' => row['to'].dup, 'route' => route } + end + kill + end + table.diff! actual + end + +When /^I route on tagged ways I should get $/ do |table| + pending +end + + +When /^I speak I should get$/ do |table| + actual = [['one','two','three']] + table.hashes.each do |row| + actual << [ row['one'].dup, row['two'].dup, 'xx' ] + end + table.diff! actual +end + +When /^I route I between "([^"]*)" and "([^"]*)"$/ do |from, to| +end + +Then /^I should get the route "([^"]*)"$/ do |route| + route.should == "xx" +end + + \ No newline at end of file diff --git a/features/step_definitions/test_data.rb b/features/step_definitions/test_data.rb new file mode 100644 index 000000000..b947e8401 --- /dev/null +++ b/features/step_definitions/test_data.rb @@ -0,0 +1,165 @@ +require 'OSM/objects' #osmlib gem +require 'OSM/Database' +require 'builder' + +OSM_USER = 'osrm' +OSM_TIMESTAMP = '2012-01-01T00:00:00Z' +OSM_GENERATOR = 'osrm-test' +OSM_UID = 1 +TEST_FOLDER = 'test' +DATA_FOLDER = 'data' +OSM_FILE = 'test' +LOG_FILE = 'test.log' + +ORIGIN = [1,1] +ZOOM = 0.001 + +def must_reprocess + @must_reprocess = true +end + +def must_reprocess? + @must_reprocess ||= true +end + +def reprocess_if_needed + if must_reprocess? + raise "*** osrm-routed is running. Please stop it before running tests." if running? + #puts "Reprocessing: #{@osm_db.nodes.size} nodes, #{@name_way_hash.size} ways, #{@relations.size} relations... " + + Dir.chdir TEST_FOLDER do + write_speedprofile + write_osm + reprocess + end + @must_reprocess = false + end +end + +def reprocess + file = "#{DATA_FOLDER}/#{OSM_FILE}" + raise "*** osrm-extract failed. Please see test.log for more info." unless system "./osrm-extract #{file}.osm.pbf 1>>#{LOG_FILE} 2>>#{LOG_FILE}" + raise "*** osrm-prepare failed. Please see test.log for more info." unless system "./osrm-prepare #{file}.osrm #{file}.restrictions 1>>#{LOG_FILE} 2>>#{LOG_FILE}" +end + +def find_node_by_name s + name_node_hash[s.to_s] +end + +def find_way_by_name s + name_way_hash[s.to_s] || name_way_hash[s.to_s.reverse] +end + +def reset_data + osm_db.clear + name_node_hash.clear + name_way_hash.clear + must_reprocess + reset_speedprofile + $stdout.flush + Dir.chdir "#{TEST_FOLDER}" do + clear_log + clear_data_files + end +end + +def clear_data_files + File.delete *Dir.glob("#{DATA_FOLDER}/test.*") +end + +def clear_log + File.delete *Dir.glob("*.log") +end + +def speedprofile + @speedprofile ||= reset_speedprofile +end + +def reset_speedprofile + @speedprofile = {} + s = File.read 'test/speedprofiles/default.ini' + s.scan /(.*)=(.*)/ do |option| + @speedprofile[option[0].strip] = option[1].strip + end +end + +def dump_speedprofile + "[default]\n" + @speedprofile.map { |k,v| "\t#{k} = #{v}" }.join("\n") +end + +def write_speedprofile + File.open( 'speedprofile.ini', 'w') {|f| f.write( dump_speedprofile ) } +end + +def osm_db + @osm_db ||= OSM::Database.new +end + +def name_node_hash + @name_node_hash ||= {} +end + +def name_way_hash + @name_way_hash ||= {} +end + +def write_osm + xml = '' + doc = Builder::XmlMarkup.new :indent => 2, :target => xml + doc.instruct! + osm_db.to_xml doc, OSM_GENERATOR + + #write .oms file + file = "#{DATA_FOLDER}/#{OSM_FILE}" + File.open( "#{file}.osm", 'w') {|f| f.write(xml) } + + #convert from .osm to .osm.pbf, which is the format osrm reads + #convert. redirect stdout and stderr to a log file avoid output in the cucumber console + unless system "osmosis --read-xml #{file}.osm --write-pbf #{file}.osm.pbf omitmetadata=true 1>>#{LOG_FILE} 2>>#{LOG_FILE}" + raise "Failed to convert to proto buffer format. Please see #{file}.log for more info." + end +end + + +Given /^the nodes$/ do |table| + reset_data + table.raw.each_with_index do |row,ri| + row.each_with_index do |name,ci| + unless name.empty? + node = OSM::Node.new nil, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+ci*ZOOM, ORIGIN[1]-ri*ZOOM + node << { :name => name } + node.uid = OSM_UID + osm_db << node + name_node_hash[name] = node + end + end + end +end + +Given /^the ways$/ do |table| + must_reprocess + table.hashes.each do |row| + name = row.delete 'nodes' + way = OSM::Way.new nil, OSM_USER, OSM_TIMESTAMP + defaults = { 'highway' => 'primary' } + way << defaults.merge( 'name' => name ).merge(row) + way.uid = OSM_UID + name.each_char { |c| way << find_node_by_name(c) } + osm_db << way + name_way_hash[name] = way + end +end + +Given /^the relations$/ do |table| + must_reprocess + table.hashes.each do |row| + relation = OSM::Relation.new nil, OSM_USER, OSM_TIMESTAMP + relation << { :type => :restriction, :restriction => 'no_left_turn' } + relation << OSM::Member.new( 'way', find_way_by_name(row['from']).id, 'from' ) + relation << OSM::Member.new( 'way', find_way_by_name(row['to']).id, 'to' ) + relation << OSM::Member.new( 'node', find_node_by_name(row['via']).id, 'via' ) + relation.uid = OSM_UID + osm_db << relation + end +end + diff --git a/test/extractor.ini b/test/extractor.ini new file mode 100644 index 000000000..aa6ba2e30 --- /dev/null +++ b/test/extractor.ini @@ -0,0 +1 @@ +Memory = 1 \ No newline at end of file diff --git a/test/server.ini b/test/server.ini index 2a6d1dac5..b43aa11a5 100644 --- a/test/server.ini +++ b/test/server.ini @@ -2,8 +2,8 @@ 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 +hsgrData=data/test.osrm.hsgr +nodesData=data/test.osrm.nodes +ramIndex=data/test.osrm.ramIndex +fileIndex=data/test.osrm.fileIndex +namesData=data/test.osrm.names diff --git a/test/speedprofiles/default.ini b/test/speedprofiles/default.ini new file mode 100644 index 000000000..aa8befd33 --- /dev/null +++ b/test/speedprofiles/default.ini @@ -0,0 +1,9 @@ +[bicycle] + primary = 15 + obeyOneways = yes + useRestrictions = yes + accessTag = bicycle + excludeFromGrid = ferry + defaultSpeed = 15 + obeyBollards = no + trafficLightPenalty = 10 \ No newline at end of file