diff --git a/features/step_definitions/errors.rb b/features/step_definitions/errors.rb index 554e07857..398d81d45 100644 --- a/features/step_definitions/errors.rb +++ b/features/step_definitions/errors.rb @@ -1,7 +1,6 @@ When /^I preprocess data$/ do begin - osrm_kill reprocess rescue OSRMError => e @process_error = e diff --git a/features/step_definitions/requests.rb b/features/step_definitions/requests.rb index df26ff29e..6b8045d36 100644 --- a/features/step_definitions/requests.rb +++ b/features/step_definitions/requests.rb @@ -1,5 +1,4 @@ When /^I request \/(.*)$/ do |path| - osrm_kill reprocess OSRMLauncher.new do @response = request_path path diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index eebb5211e..8ed4e6739 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -134,7 +134,6 @@ Then /^"([^"]*)" should be returned$/ do |route| end Then /^routability should be$/ do |table| - osrm_kill build_ways_from_table table reprocess actual = [] @@ -176,7 +175,6 @@ Then /^routability should be$/ do |table| end When /^I route I should get$/ do |table| - osrm_kill reprocess actual = [] OSRMLauncher.new do @@ -265,3 +263,11 @@ When /^I route I should get$/ do |table| end table.routing_diff! actual end + +When /^I route (\d+) times I should get$/ do |n,table| + ok = true + n.to_i.times do + ok = false unless step "I route I should get", table + end + ok +end \ No newline at end of file diff --git a/features/stress/launch.feature b/features/stress/launch.feature new file mode 100644 index 000000000..752a405be --- /dev/null +++ b/features/stress/launch.feature @@ -0,0 +1,34 @@ +@stress @launch +Feature: Launching and shutting down + + Background: + Given the speedprofile "testbot" + + Scenario: Repeated launch and shutdown + Given a grid size of 10000 meters + Given the node map + | h | a | b | + | g | x | c | + | f | e | d | + + And the ways + | nodes | highway | + | xa | primary | + | xb | primary | + | xc | primary | + | xd | primary | + | xe | primary | + | xf | primary | + | xg | primary | + | xh | primary | + + When I route 100 times I should get + | from | to | route | + | x | a | xa | + | x | b | xb | + | x | c | xc | + | x | d | xd | + | x | e | xe | + | x | f | xf | + | x | g | xg | + | x | h | xh | \ No newline at end of file diff --git a/features/support/config.rb b/features/support/config.rb index f5d9efc03..24b76cb7a 100644 --- a/features/support/config.rb +++ b/features/support/config.rb @@ -15,7 +15,7 @@ def write_server_ini s=<<-EOF Threads = 1 IP = 0.0.0.0 -Port = 5000 +Port = #{OSRM_PORT} hsgrData=#{@osm_file}.osrm.hsgr nodesData=#{@osm_file}.osrm.nodes diff --git a/features/support/env.rb b/features/support/env.rb index 9fb7ec8d1..faf1c82f5 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -1 +1,11 @@ -require 'rspec/expectations' \ No newline at end of file +require 'rspec/expectations' + +DEFAULT_PORT = 5000 + +if ENV["OSRM_PORT"] + OSRM_PORT = ENV["OSRM_PORT"].to_i + puts "Port set to #{OSRM_PORT}" +else + OSRM_PORT = DEFAULT_PORT + puts "Using default port #{OSRM_PORT}" +end \ No newline at end of file diff --git a/features/support/hooks.rb b/features/support/hooks.rb index 30579c52b..41f9b3d79 100644 --- a/features/support/hooks.rb +++ b/features/support/hooks.rb @@ -1,3 +1,6 @@ + +STRESS_TIMEOUT = 300 + Before do |scenario| @scenario_title = scenario.title @scenario_time = Time.now.strftime("%Y-%m-%dT%H:%m:%SZ") @@ -7,12 +10,11 @@ Before do |scenario| set_grid_size DEFAULT_GRID_SIZE end -Around('@routing') do |scenario, block| - Timeout.timeout(10) do +Around('@stress') do |scenario, block| + Timeout.timeout(STRESS_TIMEOUT) do block.call end end After do - osrm_kill end diff --git a/features/support/launch.rb b/features/support/launch.rb index d125985ac..7706ca0ea 100644 --- a/features/support/launch.rb +++ b/features/support/launch.rb @@ -1,71 +1,83 @@ require 'socket' require 'sys/proctable' +LAUNCH_TIMEOUT = 5 +SHUTDOWN_TIMEOUT = 5 + class OSRMLauncher def initialize &block Dir.chdir TEST_FOLDER do - osrm_up - yield - osrm_down - end - end -end - -def each_process name, &block - Sys::ProcTable.ps do |process| - if process.comm.strip == name.strip - yield process.pid.to_i, process.state.strip + begin + begin + Timeout.timeout(LAUNCH_TIMEOUT) do + osrm_up + wait_for_connection + end + rescue Timeout::Error + raise "*** Launching osrm-routed timed out." + end + yield + ensure + begin + Timeout.timeout(SHUTDOWN_TIMEOUT) do + osrm_down + end + rescue Timeout::Error + raise "*** Shutting down osrm-routed timed out." + end + end end end end def osrm_up? - find_pid('osrm-routed') != nil -end - -def find_pid name - each_process(name) { |pid,state| return pid.to_i } - return nil + if @pipe + begin + Process.getpgid @pipe.pid + true + rescue Errno::ESRCH + false + end + else + false + end end def osrm_up return if osrm_up? - pipe = IO.popen('../osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log') - timeout = 5 - (timeout*10).times do + #exec avoids popen running osrm-routed inside a shell + #if the cmd is run inside a shell, popen returns the pid for the shell, and if we try to kill it, + #the child process is orphaned, and we can't terminate it. + @pipe = IO.popen('exec ../osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log') +end + +def osrm_down + if @pipe + Process.kill 'TERM', @pipe.pid + wait_for_shutdown + @pipe = nil + end +end + +def kill + if @pipe + Process.kill 'KILL', @pipe.pid + end +end + +def wait_for_connection + while true begin - socket = TCPSocket.new('localhost', 5000) - socket.puts 'ping' + socket = TCPSocket.new('localhost', OSRM_PORT) + return rescue Errno::ECONNREFUSED sleep 0.1 end end - sleep 0.1 end -def osrm_down - each_process('osrm-routed') { |pid,state| Process.kill 'TERM', pid } - each_process('osrm-prepare') { |pid,state| Process.kill 'TERM', pid } - each_process('osrm-extract') { |pid,state| Process.kill 'TERM', pid } - wait_for_shutdown 'osrm-routed' - wait_for_shutdown 'osrm-prepare' - wait_for_shutdown 'osrm-extract' -end - -def osrm_kill - each_process('osrm-routed') { |pid,state| Process.kill 'KILL', pid } - each_process('osrm-prepare') { |pid,state| Process.kill 'KILL', pid } - each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid } - wait_for_shutdown 'osrm-routed' - wait_for_shutdown 'osrm-prepare' - wait_for_shutdown 'osrm-extract' -end - -def wait_for_shutdown name - timeout = 10 - (timeout*10).times do - return if find_pid(name) == nil +def wait_for_shutdown + while osrm_up? sleep 0.1 end - raise "*** Could not terminate #{name}." end diff --git a/features/support/request.rb b/features/support/request.rb index 6d4cd1288..8aeac53db 100644 --- a/features/support/request.rb +++ b/features/support/request.rb @@ -1,12 +1,15 @@ require 'net/http' -HOST = 'http://localhost:5000' +HOST = "http://localhost:#{OSRM_PORT}" +REQUEST_TIMEOUT = 1 def request_path path @query = path log path uri = URI.parse "#{HOST}/#{path}" - Net::HTTP.get_response uri + Timeout.timeout(REQUEST_TIMEOUT) do + Net::HTTP.get_response uri + end rescue Errno::ECONNREFUSED => e raise "*** osrm-routed is not running." rescue Timeout::Error