Skip to content
This repository has been archived by the owner on May 16, 2021. It is now read-only.

Add Sinatra::Runner For Managing Sinatra Servers #122

Merged
merged 8 commits into from
Jul 21, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions lib/sinatra/runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
require 'open-uri'
require 'net/http'
require 'timeout'

# Helps you spinning up and shutting down your own sinatra app. This is especially helpful for running
# real network tests against a sinatra backend.
#
# The backend server could look like the following (in test/server.rb).
#
# require "sinatra"
#
# get "/" do
# "Cheers from test server"
# end
#
# get "/ping" do
# "1"
# end
#
# Note that you need to implement a ping action for internal use.
#
# Next, you need to write your runner.
#
# require 'sinatra/runner'
#
# class Runner < Sinatra::Runner
# def app_file
# File.expand_path("../server.rb", __FILE__)
# end
# end
#
# Override Runner#app_file, #command, #port, #protocol and #ping_path for customization.
#
# Whereever you need this test backend, here's how you manage it. The following example assumes you
# have a test in your app that needs to be run against your test backend.
#
# runner = ServerRunner.new
# runner.run
#
# # ..tests against localhost:4567 here..
#
# runner.kill
#
# For an example, check https://github.com/apotonick/roar/blob/master/test/test_helper.rb
module Sinatra
class Runner
def app_file
File.expand_path("../server.rb", __FILE__)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be configurable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, by overriding this method.

end

def run
#puts command
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can remove the puts

@pipe = start
@started = Time.now
warn "#{server} up and running on port #{port}" if ping
end

def kill
return unless pipe
Process.kill("KILL", pipe.pid)
rescue NotImplementedError
system "kill -9 #{pipe.pid}"
rescue Errno::ESRCH
end

def get(url)
Timeout.timeout(1) { get_url("#{protocol}://127.0.0.1:#{port}#{url}") }
end

def log
@log ||= ""
loop { @log << pipe.read_nonblock(1) }
rescue Exception
@log
end

private
attr_accessor :pipe

def start
IO.popen(command)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did the JRuby implementation go?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end

def command # to be overwritten
"bundle exec ruby #{app_file} -p #{port} -e production"
end

def ping(timeout=30)
loop do
return if alive?
if Time.now - @started > timeout
$stderr.puts command, log
fail "timeout"
else
sleep 0.1
end
end
end

def alive?
3.times { get(ping_path) }
true
rescue Errno::ECONNREFUSED, Errno::ECONNRESET, EOFError, SystemCallError, OpenURI::HTTPError, Timeout::Error
false
end

def ping_path # to be overwritten
'/ping'
end

def port # to be overwritten
4567
end

def protocol
"http"
end

def get_url(url)
uri = URI.parse(url)

return uri.read unless protocol == "https"
get_https_url(uri)
end

def get_https_url(uri)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri.request_uri)
http.request(request).body
end
end
end