From 7ba8e51fa9ef52a1743b7b0a61b37f96d3d50813 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 24 Jan 2014 21:14:38 +0100 Subject: [PATCH 1/8] use osrm-database during testing --- features/datastore/datastore.feature | 72 ++++++++++++++++++ features/step_definitions/locate.rb | 2 +- features/step_definitions/nearest.rb | 2 +- features/step_definitions/options.rb | 6 +- features/step_definitions/requests.rb | 4 +- features/step_definitions/routability.rb | 2 +- features/step_definitions/routing.rb | 2 +- features/support/data.rb | 12 ++- features/support/env.rb | 18 +++++ features/support/launch.rb | 94 +++++++++++++----------- features/support/route.rb | 2 + features/testbot/datastore.feature | 31 ++++++++ 12 files changed, 192 insertions(+), 55 deletions(-) create mode 100644 features/datastore/datastore.feature create mode 100644 features/testbot/datastore.feature diff --git a/features/datastore/datastore.feature b/features/datastore/datastore.feature new file mode 100644 index 000000000..2e37f0256 --- /dev/null +++ b/features/datastore/datastore.feature @@ -0,0 +1,72 @@ +@datastore +Feature: Loading data through datastore +# Normally when launching osrm-routed, it will keep running as a server until it's shut down. +# For testing program options, the --trial option is used, which causes osrm-routed to quit +# immediately after initialization. This makes testing easier and faster. +# +# The {base} part of the options to osrm-routed will be expanded to the actual base path of +# the preprocessed file. + + Background: + Given the profile "testbot" + + Scenario: Load data with osrm-datastore - medium size + Given the node map + | a | b | c | + | d | e | f | + And the ways + | nodes | + | abc | + | def | + | ad | + | be | + | cf | + And the data has been prepared + + When I run "osrm-datastore --springclean" + Then stderr should be empty + And stdout should contain /^\[info\] spring-cleaning all shared memory regions/ + And it should exit with code 0 + + When I run "osrm-datastore {base}.osrm" + Then stderr should be empty + And stdout should contain /^\[info\] all data loaded/ + And it should exit with code 0 + + When I run "osrm-routed --sharedmemory --trial" + Then stderr should be empty + And stdout should contain /^\[info\] starting up engines/ + And stdout should contain /\d{1,2}\.\d{1,2}\.\d{1,2}/ + And stdout should contain /compiled at/ + And stdout should contain /^\[info\] loaded plugin: viaroute/ + And stdout should contain /^\[info\] trial run/ + And stdout should contain /^\[info\] shutdown completed/ + And it should exit with code 0 + + Scenario: Load data with osrm-datastore - small size + Given the node map + | a | b | + And the ways + | nodes | + | ab | + And the data has been prepared + + When I run "osrm-datastore --springclean" + Then stderr should be empty + And stdout should contain /^\[info\] spring-cleaning all shared memory regions/ + And it should exit with code 0 + + When I run "osrm-datastore {base}.osrm" + Then stderr should be empty + And stdout should contain /^\[info\] all data loaded/ + And it should exit with code 0 + + When I run "osrm-routed --sharedmemory --trial" + Then stderr should be empty + And stdout should contain /^\[info\] starting up engines/ + And stdout should contain /\d{1,2}\.\d{1,2}\.\d{1,2}/ + And stdout should contain /compiled at/ + And stdout should contain /^\[info\] loaded plugin: viaroute/ + And stdout should contain /^\[info\] trial run/ + And stdout should contain /^\[info\] shutdown completed/ + And it should exit with code 0 \ No newline at end of file diff --git a/features/step_definitions/locate.rb b/features/step_definitions/locate.rb index 9d3d74f65..26c52e2d0 100644 --- a/features/step_definitions/locate.rb +++ b/features/step_definitions/locate.rb @@ -1,7 +1,7 @@ When /^I request locate I should get$/ do |table| reprocess actual = [] - OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do + OSRMLoader.load("#{@osm_file}.osrm") do table.hashes.each_with_index do |row,ri| in_node = find_node_by_name row['in'] raise "*** unknown in-node '#{row['in']}" unless in_node diff --git a/features/step_definitions/nearest.rb b/features/step_definitions/nearest.rb index ae5a79cf5..030a8e5bc 100644 --- a/features/step_definitions/nearest.rb +++ b/features/step_definitions/nearest.rb @@ -1,7 +1,7 @@ When /^I request nearest I should get$/ do |table| reprocess actual = [] - OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do + OSRMLoader.load("#{@osm_file}.osrm") do table.hashes.each_with_index do |row,ri| in_node = find_node_by_name row['in'] raise "*** unknown in-node '#{row['in']}" unless in_node diff --git a/features/step_definitions/options.rb b/features/step_definitions/options.rb index 38c9ea256..e2e50661e 100644 --- a/features/step_definitions/options.rb +++ b/features/step_definitions/options.rb @@ -1,6 +1,6 @@ When(/^I run "osrm\-routed\s?(.*?)"$/) do |options| begin - Timeout.timeout(1) { run_bin 'osrm-routed', options } + Timeout.timeout(SHUTDOWN_TIMEOUT) { run_bin 'osrm-routed', options } rescue Timeout::Error raise "*** osrm-routed didn't quit. Maybe the --trial option wasn't used?" end @@ -14,6 +14,10 @@ When(/^I run "osrm\-prepare\s?(.*?)"$/) do |options| run_bin 'osrm-prepare', options end +When(/^I run "osrm\-datastore\s?(.*?)"$/) do |options| + run_bin 'osrm-datastore', options +end + Then /^it should exit with code (\d+)$/ do |code| expect(@exit_code).to eq( code.to_i ) end diff --git a/features/step_definitions/requests.rb b/features/step_definitions/requests.rb index 7002cd9e3..b9f4d98f6 100644 --- a/features/step_definitions/requests.rb +++ b/features/step_definitions/requests.rb @@ -1,6 +1,6 @@ When /^I request \/(.*)$/ do |path| reprocess - OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do + OSRMLoader.load("#{@osm_file}.osrm") do @response = request_path path end end @@ -43,4 +43,4 @@ Then /^"([^"]*)" should return code (\d+)$/ do |binary, code| expect(@process_error.is_a?(OSRMError)).to eq(true) expect(@process_error.process).to eq(binary) expect(@process_error.code.to_i).to eq(code.to_i) -end \ No newline at end of file +end diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb index 48f7f24de..e46d0d9ff 100644 --- a/features/step_definitions/routability.rb +++ b/features/step_definitions/routability.rb @@ -44,7 +44,7 @@ Then /^routability should be$/ do |table| if table.headers&["forw","backw","bothw"] == [] raise "*** routability tabel must contain either 'forw', 'backw' or 'bothw' column" end - OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do + OSRMLoader.load("#{@osm_file}.osrm") do table.hashes.each_with_index do |row,i| output_row = row.dup attempts = [] diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index 4d944f32b..53a1b6fec 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -1,7 +1,7 @@ When /^I route I should get$/ do |table| reprocess actual = [] - OSRMBackgroundLauncher.new("#{@osm_file}.osrm") do + OSRMLoader.load("#{@osm_file}.osrm") do table.hashes.each_with_index do |row,ri| if row['request'] got = {'request' => row['request'] } diff --git a/features/support/data.rb b/features/support/data.rb index 7c1ba887a..c09b763bd 100644 --- a/features/support/data.rb +++ b/features/support/data.rb @@ -225,13 +225,17 @@ def convert_osm_to_pbf end def extracted? - File.exist?("#{@osm_file}.osrm") && - File.exist?("#{@osm_file}.osrm.names") && - File.exist?("#{@osm_file}.osrm.restrictions") + Dir.chdir TEST_FOLDER do + File.exist?("#{@osm_file}.osrm") && + File.exist?("#{@osm_file}.osrm.names") && + File.exist?("#{@osm_file}.osrm.restrictions") + end end def prepared? - File.exist?("#{@osm_file}.osrm.hsgr") + Dir.chdir TEST_FOLDER do + File.exist?("#{@osm_file}.osrm.hsgr") + end end def write_timestamp diff --git a/features/support/env.rb b/features/support/env.rb index 369705ab0..cb328d12b 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -17,6 +17,20 @@ PROFILES_PATH = File.join ROOT_FOLDER, 'profiles' BIN_PATH = File.join ROOT_FOLDER, 'build' DEFAULT_INPUT_FORMAT = 'osm' DEFAULT_ORIGIN = [1,1] +LAUNCH_TIMEOUT = 1 +SHUTDOWN_TIMEOUT = 10 + + +def log_time_and_run cmd + log_time cmd + `#{cmd}` +end + +def log_time cmd + puts "[#{Time.now.strftime('%Y-%m-%d %H:%M:%S:%L')}] #{cmd}" +end + + puts "Ruby version #{RUBY_VERSION}" @@ -55,3 +69,7 @@ end AfterConfiguration do |config| clear_log_files end + +at_exit do + OSRMLoader.shutdown +end diff --git a/features/support/launch.rb b/features/support/launch.rb index e55867a67..8a458da17 100644 --- a/features/support/launch.rb +++ b/features/support/launch.rb @@ -9,76 +9,82 @@ end OSRM_ROUTED_LOG_FILE = 'osrm-routed.log' -class OSRMBackgroundLauncher - def initialize input_file, &block +class OSRMLoader + + @@pid = nil + + def self.load input_file, &block @input_file = input_file Dir.chdir TEST_FOLDER do - begin - launch - yield - ensure - shutdown - end + self.load_data + self.launch unless @@pid + yield end end + + def self.load_data + puts "=== loading data with osrm-datastore" + log_time_and_run "#{BIN_PATH}/osrm-datastore --springclean" + log_time_and_run "#{BIN_PATH}/osrm-datastore #{@input_file}" + end - private - - def launch - Timeout.timeout(OSRM_TIMEOUT) do - osrm_up - wait_for_connection + def self.launch + Timeout.timeout(LAUNCH_TIMEOUT) do + self.osrm_up + self.wait_for_connection end rescue Timeout::Error raise RoutedError.new "Launching osrm-routed timed out." end - def shutdown - Timeout.timeout(OSRM_TIMEOUT) do - osrm_down + def self.shutdown + Timeout.timeout(SHUTDOWN_TIMEOUT) do + self.osrm_down end rescue Timeout::Error - kill + self.kill raise RoutedError.new "Shutting down osrm-routed timed out." end - - def osrm_up? - if @pid - begin - if Process.waitpid(@pid, Process::WNOHANG) then - false - else - true - end - rescue Errno::ESRCH, Errno::ECHILD - false - end + def self.osrm_up? + if @@pid + s = `ps -o state -p #{@@pid}`.split[1].to_s.strip + up = (s =~ /^[DRST]/) != nil + # puts "=== osrm-routed, status pid #{@@pid}: #{s} (#{up ? 'up' : 'down'})" + up + else + false end end - def osrm_up - return if osrm_up? - @pid = Process.spawn("#{BIN_PATH}/osrm-routed #{@input_file} --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) - Process.detach(@pid) # avoid zombie processes + def self.osrm_up + return if self.osrm_up? + puts "=== launching osrm-routed" + log %[Process.spawn("#{BIN_PATH}/osrm-routed --sharedmemory=1 --port #{OSRM_PORT}",:out=>'#{OSRM_ROUTED_LOG_FILE}', :err=>'#{OSRM_ROUTED_LOG_FILE}')] + @@pid = Process.spawn("#{BIN_PATH}/osrm-routed --sharedmemory=1 --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) end - def osrm_down - if @pid - Process.kill TERMSIGNAL, @pid - wait_for_shutdown + def self.osrm_down + if @@pid + puts '=== shutting down osrm' + log_time "Process.kill 'TERM', #{@@pid}" + Process.kill 'TERM', @@pid + self.wait_for_shutdown end end - def kill - if @pid - Process.kill 'KILL', @pid + def self.kill + if @@pid + puts '=== killing osrm' + log_time "Process.kill 'KILL', @@pid" + Process.kill 'KILL', @@pid end end - def wait_for_connection + def self.wait_for_connection while true begin + log_time "TCPSocket.new('127.0.0.1', OSRM_PORT)" socket = TCPSocket.new('127.0.0.1', OSRM_PORT) return rescue Errno::ECONNREFUSED @@ -87,8 +93,8 @@ class OSRMBackgroundLauncher end end - def wait_for_shutdown - while osrm_up? + def self.wait_for_shutdown + while self.osrm_up? sleep 0.1 end end diff --git a/features/support/route.rb b/features/support/route.rb index 745edc0fd..cf81d9e37 100644 --- a/features/support/route.rb +++ b/features/support/route.rb @@ -18,6 +18,7 @@ def request_path path, waypoints=[], options={} uri = URI.parse ["#{HOST}/#{path}", params].compact.join('?') @query = uri.to_s Timeout.timeout(OSRM_TIMEOUT) do + log_time "Net::HTTP.get_response #{uri}" Net::HTTP.get_response uri end rescue Errno::ECONNREFUSED => e @@ -30,6 +31,7 @@ def request_url path uri = URI.parse"#{HOST}/#{path}" @query = uri.to_s Timeout.timeout(OSRM_TIMEOUT) do + log_time "Net::HTTP.get_response #{uri}" Net::HTTP.get_response uri end rescue Errno::ECONNREFUSED => e diff --git a/features/testbot/datastore.feature b/features/testbot/datastore.feature new file mode 100644 index 000000000..7814f3b47 --- /dev/null +++ b/features/testbot/datastore.feature @@ -0,0 +1,31 @@ +@routing @datastore +Feature: Temporary tests related to osrm-datastore + + Background: + Given the profile "testbot" + + Scenario: Scenario ab + Given the node map + | a | b | + + And the ways + | nodes | + | ab | + + When I route I should get + | from | to | route | + | a | b | ab | + | b | a | ab | + + Scenario: Scenaria xy + Given the node map + | x | y | + + And the ways + | nodes | + | xy | + + When I route I should get + | from | to | route | + | x | y | xy | + | y | x | xy | From db06cdb4cedc960161dc32f37859d9d5c2e904f0 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 9 Oct 2014 14:30:06 +0200 Subject: [PATCH 2/8] adjust datastore testing --- features/support/data.rb | 2 +- features/support/launch.rb | 12 +----------- features/support/route.rb | 2 -- features/support/run.rb | 3 ++- features/testbot/bad.feature | 2 +- features/testbot/basic.feature | 2 +- features/testbot/bearing.feature | 2 +- features/testbot/bearing_param.feature | 2 +- features/testbot/compression.feature | 2 +- features/testbot/datastore.feature | 2 +- features/testbot/distance.feature | 2 +- features/testbot/fastest.feature | 2 +- features/testbot/geometry.feature | 2 +- features/testbot/graph.feature | 2 +- features/testbot/loop.feature | 2 +- features/testbot/origin.feature | 2 +- features/testbot/penalty.feature | 2 +- features/testbot/planetary.feature | 2 +- features/testbot/projection.feature | 2 +- features/testbot/protobuffer.feature | 2 +- features/testbot/snap.feature | 2 +- features/testbot/status.feature | 2 +- features/testbot/time.feature | 2 +- features/testbot/turns.feature | 2 +- features/testbot/utf.feature | 2 +- features/testbot/uturn.feature | 2 +- 26 files changed, 26 insertions(+), 37 deletions(-) diff --git a/features/support/data.rb b/features/support/data.rb index c09b763bd..76822811b 100644 --- a/features/support/data.rb +++ b/features/support/data.rb @@ -21,7 +21,7 @@ def input_format end def sanitized_scenario_title - @sanitized_scenario_title ||= @scenario_title.gsub /[^0-9A-Za-z.\-]/, '_' + @sanitized_scenario_title ||= @scenario_title.to_s.gsub /[^0-9A-Za-z.\-]/, '_' end def set_grid_size meters diff --git a/features/support/launch.rb b/features/support/launch.rb index 8a458da17..cf4c422de 100644 --- a/features/support/launch.rb +++ b/features/support/launch.rb @@ -23,9 +23,7 @@ class OSRMLoader end def self.load_data - puts "=== loading data with osrm-datastore" - log_time_and_run "#{BIN_PATH}/osrm-datastore --springclean" - log_time_and_run "#{BIN_PATH}/osrm-datastore #{@input_file}" + run_bin "osrm-datastore", @input_file end def self.launch @@ -50,7 +48,6 @@ class OSRMLoader if @@pid s = `ps -o state -p #{@@pid}`.split[1].to_s.strip up = (s =~ /^[DRST]/) != nil - # puts "=== osrm-routed, status pid #{@@pid}: #{s} (#{up ? 'up' : 'down'})" up else false @@ -59,15 +56,11 @@ class OSRMLoader def self.osrm_up return if self.osrm_up? - puts "=== launching osrm-routed" - log %[Process.spawn("#{BIN_PATH}/osrm-routed --sharedmemory=1 --port #{OSRM_PORT}",:out=>'#{OSRM_ROUTED_LOG_FILE}', :err=>'#{OSRM_ROUTED_LOG_FILE}')] @@pid = Process.spawn("#{BIN_PATH}/osrm-routed --sharedmemory=1 --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) end def self.osrm_down if @@pid - puts '=== shutting down osrm' - log_time "Process.kill 'TERM', #{@@pid}" Process.kill 'TERM', @@pid self.wait_for_shutdown end @@ -75,8 +68,6 @@ class OSRMLoader def self.kill if @@pid - puts '=== killing osrm' - log_time "Process.kill 'KILL', @@pid" Process.kill 'KILL', @@pid end end @@ -84,7 +75,6 @@ class OSRMLoader def self.wait_for_connection while true begin - log_time "TCPSocket.new('127.0.0.1', OSRM_PORT)" socket = TCPSocket.new('127.0.0.1', OSRM_PORT) return rescue Errno::ECONNREFUSED diff --git a/features/support/route.rb b/features/support/route.rb index cf81d9e37..745edc0fd 100644 --- a/features/support/route.rb +++ b/features/support/route.rb @@ -18,7 +18,6 @@ def request_path path, waypoints=[], options={} uri = URI.parse ["#{HOST}/#{path}", params].compact.join('?') @query = uri.to_s Timeout.timeout(OSRM_TIMEOUT) do - log_time "Net::HTTP.get_response #{uri}" Net::HTTP.get_response uri end rescue Errno::ECONNREFUSED => e @@ -31,7 +30,6 @@ def request_url path uri = URI.parse"#{HOST}/#{path}" @query = uri.to_s Timeout.timeout(OSRM_TIMEOUT) do - log_time "Net::HTTP.get_response #{uri}" Net::HTTP.get_response uri end rescue Errno::ECONNREFUSED => e diff --git a/features/support/run.rb b/features/support/run.rb index 794050a32..1b52d6348 100644 --- a/features/support/run.rb +++ b/features/support/run.rb @@ -11,7 +11,8 @@ def run_bin bin, options opt.gsub! "{profile}", "#{PROFILES_PATH}/#{@profile}.lua" end - @stdout = `#{QQ}#{BIN_PATH}/#{bin}#{EXE}#{QQ} #{opt} 2>error.log` + cmd = "#{QQ}#{BIN_PATH}/#{bin}#{EXE}#{QQ} #{opt} 2>error.log" + @stdout = `#{cmd}` @stderr = File.read 'error.log' @exit_code = $?.exitstatus end diff --git a/features/testbot/bad.feature b/features/testbot/bad.feature index f0f3cfacc..d7e3c95af 100644 --- a/features/testbot/bad.feature +++ b/features/testbot/bad.feature @@ -1,4 +1,4 @@ -@routing @bad +@routing @bad @testbot Feature: Handle bad data in a graceful manner Background: diff --git a/features/testbot/basic.feature b/features/testbot/basic.feature index 41643193d..599b0628a 100644 --- a/features/testbot/basic.feature +++ b/features/testbot/basic.feature @@ -1,4 +1,4 @@ -@routing @basic +@routing @basic @testbot Feature: Basic Routing Background: diff --git a/features/testbot/bearing.feature b/features/testbot/bearing.feature index c306af92d..9b3dc4eb7 100644 --- a/features/testbot/bearing.feature +++ b/features/testbot/bearing.feature @@ -1,4 +1,4 @@ -@routing @bearing +@routing @bearing @testbot Feature: Compass bearing Background: diff --git a/features/testbot/bearing_param.feature b/features/testbot/bearing_param.feature index e9db87331..810f69038 100644 --- a/features/testbot/bearing_param.feature +++ b/features/testbot/bearing_param.feature @@ -1,4 +1,4 @@ -@routing @bearing_param @todo +@routing @bearing_param @todo @testbot Feature: Bearing parameter Background: diff --git a/features/testbot/compression.feature b/features/testbot/compression.feature index 12c1219a0..146ad63df 100644 --- a/features/testbot/compression.feature +++ b/features/testbot/compression.feature @@ -1,4 +1,4 @@ -@routing @graph +@routing @graph @testbot Feature: Geometry Compression Background: diff --git a/features/testbot/datastore.feature b/features/testbot/datastore.feature index 7814f3b47..568ae7aa4 100644 --- a/features/testbot/datastore.feature +++ b/features/testbot/datastore.feature @@ -1,4 +1,4 @@ -@routing @datastore +@routing @datastore @testbot Feature: Temporary tests related to osrm-datastore Background: diff --git a/features/testbot/distance.feature b/features/testbot/distance.feature index f9f166bd7..1f777d24f 100644 --- a/features/testbot/distance.feature +++ b/features/testbot/distance.feature @@ -1,4 +1,4 @@ -@routing @distance +@routing @distance @testbot Feature: Distance calculation Background: diff --git a/features/testbot/fastest.feature b/features/testbot/fastest.feature index 9a5cf24a3..8c24a5334 100644 --- a/features/testbot/fastest.feature +++ b/features/testbot/fastest.feature @@ -1,4 +1,4 @@ -@routing @fastest +@routing @fastest @testbot Feature: Choosing fastest route Background: diff --git a/features/testbot/geometry.feature b/features/testbot/geometry.feature index 553af9393..8b38c06f8 100644 --- a/features/testbot/geometry.feature +++ b/features/testbot/geometry.feature @@ -1,4 +1,4 @@ -@routing +@routing @testbot Feature: Retrieve geometry Background: Use some profile diff --git a/features/testbot/graph.feature b/features/testbot/graph.feature index a870106dc..aa75da339 100644 --- a/features/testbot/graph.feature +++ b/features/testbot/graph.feature @@ -1,4 +1,4 @@ -@routing @graph +@routing @graph @testbot Feature: Basic Routing #Test the input data descibed on https://github.com/DennisOSRM/Project-OSRM/wiki/Graph-representation diff --git a/features/testbot/loop.feature b/features/testbot/loop.feature index ac9ae30ff..fe898ecf0 100644 --- a/features/testbot/loop.feature +++ b/features/testbot/loop.feature @@ -1,4 +1,4 @@ -@routing @726 +@routing @726 @testbot Feature: Avoid weird loops caused by rounding errors Background: diff --git a/features/testbot/origin.feature b/features/testbot/origin.feature index c43e04e61..b5b194502 100644 --- a/features/testbot/origin.feature +++ b/features/testbot/origin.feature @@ -1,4 +1,4 @@ -@routing @origin +@routing @origin @testbot Feature: Routing close to the [0,0] origin Background: diff --git a/features/testbot/penalty.feature b/features/testbot/penalty.feature index 85f43c7ed..e4f3cb632 100644 --- a/features/testbot/penalty.feature +++ b/features/testbot/penalty.feature @@ -1,4 +1,4 @@ -@routing @penalty @signal +@routing @penalty @signal @testbot Feature: Penalties # Testbot uses a signal penalty of 7s. diff --git a/features/testbot/planetary.feature b/features/testbot/planetary.feature index f2ba21e88..19925fe27 100644 --- a/features/testbot/planetary.feature +++ b/features/testbot/planetary.feature @@ -1,4 +1,4 @@ -@routing @planetary +@routing @planetary @testbot Feature: Distance calculation Scenario: Approximated Longitudinal distances at equator diff --git a/features/testbot/projection.feature b/features/testbot/projection.feature index ed2f2fcc4..d7a0b8993 100644 --- a/features/testbot/projection.feature +++ b/features/testbot/projection.feature @@ -1,4 +1,4 @@ -@routing @projection +@routing @projection @testbot Feature: Projection to nearest point on road # Waypoints are projected perpendiculary onto the closest road diff --git a/features/testbot/protobuffer.feature b/features/testbot/protobuffer.feature index a77ff34a6..e32de26c2 100644 --- a/features/testbot/protobuffer.feature +++ b/features/testbot/protobuffer.feature @@ -1,4 +1,4 @@ -@routing @pbf +@routing @pbf @testbot Feature: Importing protobuffer (.pbf) format # Test normally read .osm, which is faster than .pbf files, # since we don't need to use osmosis to first convert to .pbf diff --git a/features/testbot/snap.feature b/features/testbot/snap.feature index c8a04bfd7..bee75bc44 100644 --- a/features/testbot/snap.feature +++ b/features/testbot/snap.feature @@ -1,4 +1,4 @@ -@routing @snap +@routing @snap @testbot Feature: Snap start/end point to the nearest way Background: diff --git a/features/testbot/status.feature b/features/testbot/status.feature index 4fa15ebb3..1b12b33ea 100644 --- a/features/testbot/status.feature +++ b/features/testbot/status.feature @@ -1,4 +1,4 @@ -@routing @status +@routing @status @testbot Feature: Status messages Background: diff --git a/features/testbot/time.feature b/features/testbot/time.feature index e0ccc3760..c838796f2 100644 --- a/features/testbot/time.feature +++ b/features/testbot/time.feature @@ -1,4 +1,4 @@ -@routing @time +@routing @time @testbot Feature: Estimation of travel time # Testbot speeds: # Primary road: 36km/h = 36000m/3600s = 100m/10s diff --git a/features/testbot/turns.feature b/features/testbot/turns.feature index 87bf21f55..6eba4f9e9 100644 --- a/features/testbot/turns.feature +++ b/features/testbot/turns.feature @@ -1,4 +1,4 @@ -@routing @turns +@routing @turns @testbot Feature: Turn directions/codes Background: diff --git a/features/testbot/utf.feature b/features/testbot/utf.feature index e9d324c1b..d979e9f92 100644 --- a/features/testbot/utf.feature +++ b/features/testbot/utf.feature @@ -1,4 +1,4 @@ -@routing @utf +@routing @utf @testbot Feature: Handling of UTF characters Background: diff --git a/features/testbot/uturn.feature b/features/testbot/uturn.feature index aa81fc284..943796e69 100644 --- a/features/testbot/uturn.feature +++ b/features/testbot/uturn.feature @@ -1,4 +1,4 @@ -@routing @uturn @via +@routing @uturn @via @testbot Feature: U-turns at via points Background: From cf3eae1c915c9ab37ebdcdbb6891c45b03843ffd Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Thu, 9 Oct 2014 14:38:00 +0200 Subject: [PATCH 3/8] disable failing test --- features/options/routed/files.feature | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/features/options/routed/files.feature b/features/options/routed/files.feature index 716b2a4d8..574c22294 100644 --- a/features/options/routed/files.feature +++ b/features/options/routed/files.feature @@ -1,4 +1,4 @@ -@routed @options @files +@routed @options @files @todo Feature: osrm-routed command line options: files # Normally when launching osrm-routed, it will keep running as a server until it's shut down. # For testing program options, the --trial option is used, which causes osrm-routed to quit @@ -7,6 +7,11 @@ Feature: osrm-routed command line options: files # The {base} part of the options to osrm-routed will be expanded to the actual base path of # the preprocessed file. +# TODO +# Since we're not using osmr-datastore for all testing, osrm-routed is kept running. +# This means this test fails because osrm-routed is already running. +# It probably needs to be rewritten to first quit osrm-routed. + Background: Given the profile "testbot" And the node map From 14eac502610634c3b8915132e597df89f8b1f2e0 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 13 Oct 2014 11:10:40 +0200 Subject: [PATCH 4/8] remove datastore test --- features/datastore/datastore.feature | 72 ---------------------------- 1 file changed, 72 deletions(-) delete mode 100644 features/datastore/datastore.feature diff --git a/features/datastore/datastore.feature b/features/datastore/datastore.feature deleted file mode 100644 index 2e37f0256..000000000 --- a/features/datastore/datastore.feature +++ /dev/null @@ -1,72 +0,0 @@ -@datastore -Feature: Loading data through datastore -# Normally when launching osrm-routed, it will keep running as a server until it's shut down. -# For testing program options, the --trial option is used, which causes osrm-routed to quit -# immediately after initialization. This makes testing easier and faster. -# -# The {base} part of the options to osrm-routed will be expanded to the actual base path of -# the preprocessed file. - - Background: - Given the profile "testbot" - - Scenario: Load data with osrm-datastore - medium size - Given the node map - | a | b | c | - | d | e | f | - And the ways - | nodes | - | abc | - | def | - | ad | - | be | - | cf | - And the data has been prepared - - When I run "osrm-datastore --springclean" - Then stderr should be empty - And stdout should contain /^\[info\] spring-cleaning all shared memory regions/ - And it should exit with code 0 - - When I run "osrm-datastore {base}.osrm" - Then stderr should be empty - And stdout should contain /^\[info\] all data loaded/ - And it should exit with code 0 - - When I run "osrm-routed --sharedmemory --trial" - Then stderr should be empty - And stdout should contain /^\[info\] starting up engines/ - And stdout should contain /\d{1,2}\.\d{1,2}\.\d{1,2}/ - And stdout should contain /compiled at/ - And stdout should contain /^\[info\] loaded plugin: viaroute/ - And stdout should contain /^\[info\] trial run/ - And stdout should contain /^\[info\] shutdown completed/ - And it should exit with code 0 - - Scenario: Load data with osrm-datastore - small size - Given the node map - | a | b | - And the ways - | nodes | - | ab | - And the data has been prepared - - When I run "osrm-datastore --springclean" - Then stderr should be empty - And stdout should contain /^\[info\] spring-cleaning all shared memory regions/ - And it should exit with code 0 - - When I run "osrm-datastore {base}.osrm" - Then stderr should be empty - And stdout should contain /^\[info\] all data loaded/ - And it should exit with code 0 - - When I run "osrm-routed --sharedmemory --trial" - Then stderr should be empty - And stdout should contain /^\[info\] starting up engines/ - And stdout should contain /\d{1,2}\.\d{1,2}\.\d{1,2}/ - And stdout should contain /compiled at/ - And stdout should contain /^\[info\] loaded plugin: viaroute/ - And stdout should contain /^\[info\] trial run/ - And stdout should contain /^\[info\] shutdown completed/ - And it should exit with code 0 \ No newline at end of file From 76fb0cb9650118d388c73eba3e97e2202702a94a Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 13 Oct 2014 11:19:49 +0200 Subject: [PATCH 5/8] get process handling up to date --- features/support/launch.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/features/support/launch.rb b/features/support/launch.rb index cf4c422de..7b85e0d57 100644 --- a/features/support/launch.rb +++ b/features/support/launch.rb @@ -45,23 +45,28 @@ class OSRMLoader end def self.osrm_up? - if @@pid - s = `ps -o state -p #{@@pid}`.split[1].to_s.strip - up = (s =~ /^[DRST]/) != nil - up - else - false + if @@pid + begin + if Process.waitpid(@@pid, Process::WNOHANG) then + false + else + true + end + rescue Errno::ESRCH, Errno::ECHILD + false + end end end def self.osrm_up return if self.osrm_up? @@pid = Process.spawn("#{BIN_PATH}/osrm-routed --sharedmemory=1 --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) + Process.detach(@@pid) # avoid zombie processes end def self.osrm_down if @@pid - Process.kill 'TERM', @@pid + Process.kill TERMSIGNAL, @@pid self.wait_for_shutdown end end From 71b967d24308be1939e8290d4597847e526566c3 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 14 Oct 2014 15:35:14 +0200 Subject: [PATCH 6/8] test both datastore and direct data load --- features/step_definitions/data.rb | 16 ++ features/step_definitions/locate.rb | 2 +- features/step_definitions/nearest.rb | 2 +- features/step_definitions/requests.rb | 2 +- features/step_definitions/routability.rb | 2 +- features/step_definitions/routing.rb | 2 +- features/support/data.rb | 1 + features/support/env.rb | 18 ++- features/support/hooks.rb | 4 + features/support/launch.rb | 182 ++++++++++++++--------- features/testbot/load.feature | 63 ++++++++ 11 files changed, 214 insertions(+), 80 deletions(-) create mode 100644 features/testbot/load.feature diff --git a/features/step_definitions/data.rb b/features/step_definitions/data.rb index e0985a4b1..f1e58bae2 100644 --- a/features/step_definitions/data.rb +++ b/features/step_definitions/data.rb @@ -158,3 +158,19 @@ Given /^the data has been prepared$/ do @process_error = e end end + +Given /^osrm\-routed is stopped$/ do + begin + OSRMLoader.shutdown + rescue OSRMError => e + @process_error = e + end +end + +Given /^data is loaded directly/ do + @load_method = 'directly' +end + +Given /^data is loaded with datastore$/ do + @load_method = 'datastore' +end diff --git a/features/step_definitions/locate.rb b/features/step_definitions/locate.rb index 26c52e2d0..ca04b7742 100644 --- a/features/step_definitions/locate.rb +++ b/features/step_definitions/locate.rb @@ -1,7 +1,7 @@ When /^I request locate I should get$/ do |table| reprocess actual = [] - OSRMLoader.load("#{@osm_file}.osrm") do + OSRMLoader.load(self,"#{@osm_file}.osrm") do table.hashes.each_with_index do |row,ri| in_node = find_node_by_name row['in'] raise "*** unknown in-node '#{row['in']}" unless in_node diff --git a/features/step_definitions/nearest.rb b/features/step_definitions/nearest.rb index 030a8e5bc..3dd90dd55 100644 --- a/features/step_definitions/nearest.rb +++ b/features/step_definitions/nearest.rb @@ -1,7 +1,7 @@ When /^I request nearest I should get$/ do |table| reprocess actual = [] - OSRMLoader.load("#{@osm_file}.osrm") do + OSRMLoader.load(self,"#{@osm_file}.osrm") do table.hashes.each_with_index do |row,ri| in_node = find_node_by_name row['in'] raise "*** unknown in-node '#{row['in']}" unless in_node diff --git a/features/step_definitions/requests.rb b/features/step_definitions/requests.rb index b9f4d98f6..aec6ebbab 100644 --- a/features/step_definitions/requests.rb +++ b/features/step_definitions/requests.rb @@ -1,6 +1,6 @@ When /^I request \/(.*)$/ do |path| reprocess - OSRMLoader.load("#{@osm_file}.osrm") do + OSRMLoader.load(self,"#{@osm_file}.osrm") do @response = request_path path end end diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb index e46d0d9ff..1496ad01f 100644 --- a/features/step_definitions/routability.rb +++ b/features/step_definitions/routability.rb @@ -44,7 +44,7 @@ Then /^routability should be$/ do |table| if table.headers&["forw","backw","bothw"] == [] raise "*** routability tabel must contain either 'forw', 'backw' or 'bothw' column" end - OSRMLoader.load("#{@osm_file}.osrm") do + OSRMLoader.load(self,"#{@osm_file}.osrm") do table.hashes.each_with_index do |row,i| output_row = row.dup attempts = [] diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index 53a1b6fec..adf2f7a7a 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -1,7 +1,7 @@ When /^I route I should get$/ do |table| reprocess actual = [] - OSRMLoader.load("#{@osm_file}.osrm") do + OSRMLoader.load(self,"#{@osm_file}.osrm") do table.hashes.each_with_index do |row,ri| if row['request'] got = {'request' => row['request'] } diff --git a/features/support/data.rb b/features/support/data.rb index 76822811b..adb619204 100644 --- a/features/support/data.rb +++ b/features/support/data.rb @@ -11,6 +11,7 @@ class Location end end + def set_input_format format raise '*** Input format must be eiter "osm" or "pbf"' unless ['pbf','osm'].include? format.to_s @input_format = format.to_s diff --git a/features/support/env.rb b/features/support/env.rb index cb328d12b..a01341dd6 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -1,8 +1,8 @@ require 'rspec/expectations' + DEFAULT_PORT = 5000 DEFAULT_TIMEOUT = 2 - ROOT_FOLDER = Dir.pwd OSM_USER = 'osrm' OSM_GENERATOR = 'osrm-test' @@ -19,6 +19,14 @@ DEFAULT_INPUT_FORMAT = 'osm' DEFAULT_ORIGIN = [1,1] LAUNCH_TIMEOUT = 1 SHUTDOWN_TIMEOUT = 10 +DEFAULT_LOAD_METHOD = 'datastore' +OSRM_ROUTED_LOG_FILE = 'osrm-routed.log' + +if ENV['OS']==/Windows.*/ then + TERMSIGNAL='TERM' +else + TERMSIGNAL=9 +end def log_time_and_run cmd @@ -31,8 +39,6 @@ def log_time cmd end - - puts "Ruby version #{RUBY_VERSION}" unless RUBY_VERSION.to_f >= 1.9 raise "*** Please upgrade to Ruby 1.9.x to run the OSRM cucumber tests" @@ -58,6 +64,7 @@ unless File.exists? TEST_FOLDER raise "*** Test folder #{TEST_FOLDER} doesn't exist." end + if ENV['OS']=~/Windows.*/ then EXE='.exe' QQ='"' @@ -67,9 +74,12 @@ else end AfterConfiguration do |config| + if OSRMLoader::OSRMBaseLoader.new.osrm_up? + raise "*** osrm-routed is already running." + end clear_log_files end at_exit do - OSRMLoader.shutdown + OSRMLoader::OSRMBaseLoader.new.shutdown end diff --git a/features/support/hooks.rb b/features/support/hooks.rb index ff8f10ff1..337014246 100644 --- a/features/support/hooks.rb +++ b/features/support/hooks.rb @@ -1,7 +1,9 @@ STRESS_TIMEOUT = 300 + Before do |scenario| + # feature name case scenario when Cucumber::Ast::Scenario @@ -18,6 +20,7 @@ Before do |scenario| @scenario_title = scenario.scenario_outline.name end + @load_method = DEFAULT_LOAD_METHOD @query_params = {} @scenario_time = Time.now.strftime("%Y-%m-%dT%H:%m:%SZ") reset_data @@ -25,6 +28,7 @@ Before do |scenario| @has_logged_scenario_info = false set_grid_size DEFAULT_GRID_SIZE set_origin DEFAULT_ORIGIN + end Around('@stress') do |scenario, block| diff --git a/features/support/launch.rb b/features/support/launch.rb index 7b85e0d57..11572a7ce 100644 --- a/features/support/launch.rb +++ b/features/support/launch.rb @@ -1,96 +1,136 @@ require 'socket' require 'open3' -if ENV['OS']==/Windows.*/ then - TERMSIGNAL='TERM' -else - TERMSIGNAL=9 -end - -OSRM_ROUTED_LOG_FILE = 'osrm-routed.log' - +# Only one isntance of osrm-routed is ever launched, to avoid collisions. +# The default is to keep osrm-routed running and load data with datastore. +# however, osrm-routed it shut down and relaunched for each scenario thats +# loads data directly. class OSRMLoader - - @@pid = nil - - def self.load input_file, &block - @input_file = input_file - Dir.chdir TEST_FOLDER do - self.load_data - self.launch unless @@pid - yield - end - end - - def self.load_data - run_bin "osrm-datastore", @input_file - end - def self.launch - Timeout.timeout(LAUNCH_TIMEOUT) do - self.osrm_up - self.wait_for_connection - end - rescue Timeout::Error - raise RoutedError.new "Launching osrm-routed timed out." - end + class OSRMBaseLoader + @@pid = nil - def self.shutdown - Timeout.timeout(SHUTDOWN_TIMEOUT) do - self.osrm_down + def launch + Timeout.timeout(LAUNCH_TIMEOUT) do + osrm_up + wait_for_connection + end + rescue Timeout::Error + raise RoutedError.new "Launching osrm-routed timed out." end - rescue Timeout::Error - self.kill - raise RoutedError.new "Shutting down osrm-routed timed out." - end - def self.osrm_up? + def shutdown + Timeout.timeout(SHUTDOWN_TIMEOUT) do + osrm_down + end + rescue Timeout::Error + kill + raise RoutedError.new "Shutting down osrm-routed timed out." + end + + def osrm_up? if @@pid - begin - if Process.waitpid(@@pid, Process::WNOHANG) then - false - else - true + begin + if Process.waitpid(@@pid, Process::WNOHANG) then + false + else + true + end + rescue Errno::ESRCH, Errno::ECHILD + false end - rescue Errno::ESRCH, Errno::ECHILD - false end end - end - def self.osrm_up - return if self.osrm_up? - @@pid = Process.spawn("#{BIN_PATH}/osrm-routed --sharedmemory=1 --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) - Process.detach(@@pid) # avoid zombie processes - end - - def self.osrm_down - if @@pid - Process.kill TERMSIGNAL, @@pid - self.wait_for_shutdown + def osrm_down + if @@pid + Process.kill TERMSIGNAL, @@pid + wait_for_shutdown + @@pid = nil + end end - end - def self.kill - if @@pid - Process.kill 'KILL', @@pid + def kill + if @@pid + Process.kill 'KILL', @@pid + end end - end - def self.wait_for_connection - while true - begin - socket = TCPSocket.new('127.0.0.1', OSRM_PORT) - return - rescue Errno::ECONNREFUSED + def wait_for_connection + while true + begin + socket = TCPSocket.new('127.0.0.1', OSRM_PORT) + return + rescue Errno::ECONNREFUSED + sleep 0.1 + end + end + end + + def wait_for_shutdown + while osrm_up? sleep 0.1 end end end - def self.wait_for_shutdown - while self.osrm_up? - sleep 0.1 + # looading data directly when lauching osrm-routed: + # under this scheme, osmr-routed is launched and shutdown for each scenario, + # and osrm-datastore is not used + class OSRMDirectLoader < OSRMBaseLoader + def load world, input_file, &block + @world = world + @input_file = input_file + Dir.chdir TEST_FOLDER do + shutdown + launch + yield + shutdown + end + end + + def osrm_up + return if osrm_up? + @@pid = Process.spawn("#{BIN_PATH}/osrm-routed #{@input_file} --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) + Process.detach(@@pid) # avoid zombie processes + end + + end + + # looading data with osrm-datastore: + # under this scheme, osmr-routed is launched once and kept running for all scenarios, + # and osrm-datastore is used to load data for each scenario + class OSRMDatastoreLoader < OSRMBaseLoader + def load world, input_file, &block + @world = world + @input_file = input_file + Dir.chdir TEST_FOLDER do + load_data + launch unless @@pid + yield + end + end + + def load_data + run_bin "osrm-datastore", @input_file + end + + def osrm_up + return if osrm_up? + @@pid = Process.spawn("#{BIN_PATH}/osrm-routed --sharedmemory=1 --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) + Process.detach(@@pid) # avoid zombie processes end end + + def self.load world, input_file, &block + method = world.instance_variable_get "@load_method" + if method == 'datastore' + OSRMDatastoreLoader.new.load world, input_file, &block + elsif method == 'directly' + OSRMDirectLoader.new.load world, input_file, &block + else + raise "*** Unknown load method '#{method}'" + end + end + end diff --git a/features/testbot/load.feature b/features/testbot/load.feature new file mode 100644 index 000000000..cf5e470bd --- /dev/null +++ b/features/testbot/load.feature @@ -0,0 +1,63 @@ +@routing @load @testbot +Feature: Ways of loading data +# Several scenarios that change between direct/datastore makes +# it easier to check that the test framework behaves as expected. + + Background: + Given the profile "testbot" + + Scenario: Load data with datastore - ab + Given data is loaded with datastore + Given the node map + | a | b | + + And the ways + | nodes | + | ab | + + When I route I should get + | from | to | route | + | a | b | ab | + | b | a | ab | + + Scenario: Load data directly - st + Given data is loaded directly + Given the node map + | s | t | + + And the ways + | nodes | + | st | + + When I route I should get + | from | to | route | + | s | t | st | + | t | s | st | + + Scenario: Load data datstore - xy + Given data is loaded with datastore + Given the node map + | x | y | + + And the ways + | nodes | + | xy | + + When I route I should get + | from | to | route | + | x | y | xy | + | y | x | xy | + + Scenario: Load data directly - cd + Given data is loaded directly + Given the node map + | c | d | + + And the ways + | nodes | + | cd | + + When I route I should get + | from | to | route | + | c | d | cd | + | d | c | cd | From 8438024370f31b2e6886bfd9be3b2292150120c7 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Tue, 14 Oct 2014 16:05:06 +0200 Subject: [PATCH 7/8] avoid unnessecary process check --- features/support/launch.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/support/launch.rb b/features/support/launch.rb index 11572a7ce..c71a347c6 100644 --- a/features/support/launch.rb +++ b/features/support/launch.rb @@ -69,7 +69,7 @@ class OSRMLoader def wait_for_shutdown while osrm_up? - sleep 0.1 + sleep 0.01 end end end @@ -90,7 +90,7 @@ class OSRMLoader end def osrm_up - return if osrm_up? + return if @@pid @@pid = Process.spawn("#{BIN_PATH}/osrm-routed #{@input_file} --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) Process.detach(@@pid) # avoid zombie processes end From f7469f298d8edf6529466472fb31f5bf1d4d59c2 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 15 Oct 2014 11:33:43 +0200 Subject: [PATCH 8/8] add a tail to the oneway circle to avoid edge cases --- features/testbot/oneway.feature | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/features/testbot/oneway.feature b/features/testbot/oneway.feature index 1d8a8491e..766bf8b3b 100644 --- a/features/testbot/oneway.feature +++ b/features/testbot/oneway.feature @@ -6,11 +6,12 @@ Feature: Testbot - oneways Scenario: Routing on a oneway roundabout Given the node map - | | | | v | | | - | | | d | c | | | - | x | e | | | b | | + | | | | | v | | + | x | | d | c | | | + | | e | | | b | | | | f | | | a | | - | | | g | h | | | + | | | g | h | | y | + | | z | | | | | And the ways | nodes | oneway | @@ -23,6 +24,8 @@ Feature: Testbot - oneways | gh | yes | | ha | yes | | vx | yes | + | vy | yes | + | yz | yes | | xe | yes | When I route I should get