diff options
author | Jeremy Evans <code@jeremyevans.net> | 2020-01-28 13:27:46 -0800 |
---|---|---|
committer | Samuel Williams <samuel.williams@oriontransfer.co.nz> | 2020-01-30 12:26:19 +1300 |
commit | eab436ef186d4a4163e76396ebad7840237a7052 (patch) | |
tree | fdd821bb746190476cd9ce56a3d7ecfda4e8743e | |
parent | 6dc17991b3ed870a42c30583514bca04af25db86 (diff) | |
download | rack-eab436ef186d4a4163e76396ebad7840237a7052.tar.gz |
Add covering tests for Rack::Server
Fixes a bug when in invalid handler is used and -h is also used.
That now prints appropriate help. Previously, you got a backtrace.
-rw-r--r-- | lib/rack/server.rb | 5 | ||||
-rw-r--r-- | test/load/rack-test-a.rb | 0 | ||||
-rw-r--r-- | test/load/rack-test-b.rb | 0 | ||||
-rw-r--r-- | test/spec_server.rb | 239 |
4 files changed, 241 insertions, 3 deletions
diff --git a/lib/rack/server.rb b/lib/rack/server.rb index b7107ed5..c1f2f5ca 100644 --- a/lib/rack/server.rb +++ b/lib/rack/server.rb @@ -141,7 +141,7 @@ module Rack return "" if !has_options end info.join("\n") - rescue NameError + rescue NameError, LoadError return "Warning: Could not find handler specified (#{options[:server] || 'default'}) to determine handler-specific options" end end @@ -423,7 +423,10 @@ module Rack end def daemonize_app + # Cannot be covered as it forks + # :nocov: Process.daemon + # :nocov: end def write_pid diff --git a/test/load/rack-test-a.rb b/test/load/rack-test-a.rb new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/load/rack-test-a.rb diff --git a/test/load/rack-test-b.rb b/test/load/rack-test-b.rb new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/load/rack-test-b.rb diff --git a/test/spec_server.rb b/test/spec_server.rb index ed7d435b..dab51199 100644 --- a/test/spec_server.rb +++ b/test/spec_server.rb @@ -98,11 +98,17 @@ describe Rack::Server do end it "get options from ARGV" do - SPEC_ARGV[0..-1] = ['--debug', '-sthin', '--env', 'production'] + SPEC_ARGV[0..-1] = ['--debug', '-sthin', '--env', 'production', '-w', '-q', '-o', '127.0.0.1', '-O', 'NAME=VALUE', '-ONAME2', '-D'] server = Rack::Server.new server.options[:debug].must_equal true server.options[:server].must_equal 'thin' server.options[:environment].must_equal 'production' + server.options[:warn].must_equal true + server.options[:quiet].must_equal true + server.options[:Host].must_equal '127.0.0.1' + server.options[:NAME].must_equal 'VALUE' + server.options[:NAME2].must_equal true + server.options[:daemonize].must_equal true end it "only override non-passed options from parsed .ru file" do @@ -117,6 +123,227 @@ describe Rack::Server do server.options[:Port].must_equal '2929' end + def test_options_server(*args) + SPEC_ARGV[0..-1] = args + output = String.new + server = Class.new(Rack::Server) do + define_method(:opt_parser) do + Class.new(Rack::Server::Options) do + define_method(:puts) do |*args| + output << args.join("\n") << "\n" + end + alias warn puts + alias abort puts + define_method(:exit) do + output << "exited" + end + end.new + end + end.new + output + end + + it "support -h option to get help" do + test_options_server('-scgi', '-h').must_match(/\AUsage: rackup.*Ruby options:.*Rack options.*Profiling options.*Common options.*exited\z/m) + end + + it "support -h option to get handler-specific help" do + cgi = Rack::Handler.get('cgi') + begin + def cgi.valid_options; {"FOO=BAR"=>"BAZ"} end + test_options_server('-scgi', '-h').must_match(/\AUsage: rackup.*Ruby options:.*Rack options.*Profiling options.*Common options.*Server-specific options for Rack::Handler::CGI.*-O +FOO=BAR +BAZ.*exited\z/m) + ensure + cgi.singleton_class.send(:remove_method, :valid_options) + end + end + + it "support -h option to display warning for invalid handler" do + test_options_server('-sbanana', '-h').must_match(/\AUsage: rackup.*Ruby options:.*Rack options.*Profiling options.*Common options.*Warning: Could not find handler specified \(banana\) to determine handler-specific options.*exited\z/m) + end + + it "support -v option to get version" do + test_options_server('-v').must_match(/\ARack \d\.\d \(Release: \d+\.\d+\.\d+\)\nexited\z/) + end + + it "warn for invalid --profile-mode option" do + test_options_server('--profile-mode', 'foo').must_match(/\Ainvalid option: --profile-mode unknown profile mode: foo.*Usage: rackup/m) + end + + it "warn for invalid options" do + test_options_server('--banana').must_match(/\Ainvalid option: --banana.*Usage: rackup/m) + end + + it "support -b option to specify inline rackup config" do + SPEC_ARGV[0..-1] = ['-scgi', '-E', 'production', '-b', 'use Rack::ContentLength; run ->(env){[200, {}, []]}'] + server = Rack::Server.new + def (server.server).run(app, **) app end + s, h, b = server.start.call({}) + s.must_equal 200 + h.must_equal 'Content-Length' => '0' + body = String.new + b.each do |s| + body << s + end + body.must_equal '' + end + + it "support -e option to evaluate ruby code" do + SPEC_ARGV[0..-1] = ['-scgi', '-e', 'Object::XYZ = 2'] + begin + server = Rack::Server.new + Object::XYZ.must_equal 2 + ensure + Object.send(:remove_const, :XYZ) + end + end + + it "abort if config file does not exist" do + SPEC_ARGV[0..-1] = ['-scgi'] + server = Rack::Server.new + def server.abort(s) throw :abort, s end + message = catch(:abort) do + server.start + end + message.must_match(/\Aconfiguration .*config\.ru not found/) + end + + it "support -I option to change the load path and -r to require" do + SPEC_ARGV[0..-1] = ['-scgi', '-Ifoo/bar', '-Itest/load', '-rrack-test-a', '-rrack-test-b'] + begin + server = Rack::Server.new + def (server.server).run(*) end + def server.handle_profiling(*) end + def server.app(*) end + server.start + $LOAD_PATH.must_include('foo/bar') + $LOAD_PATH.must_include('test/load') + $LOADED_FEATURES.must_include(File.join(Dir.pwd, "test/load/rack-test-a.rb")) + $LOADED_FEATURES.must_include(File.join(Dir.pwd, "test/load/rack-test-b.rb")) + ensure + $LOAD_PATH.delete('foo/bar') + $LOAD_PATH.delete('test/load') + $LOADED_FEATURES.delete(File.join(Dir.pwd, "test/load/rack-test-a.rb")) + $LOADED_FEATURES.delete(File.join(Dir.pwd, "test/load/rack-test-b.rb")) + end + end + + it "support -w option to warn and -d option to debug" do + SPEC_ARGV[0..-1] = ['-scgi', '-d', '-w'] + warn = $-w + debug = $DEBUG + begin + server = Rack::Server.new + def (server.server).run(*) end + def server.handle_profiling(*) end + def server.app(*) end + def server.p(*) end + def server.pp(*) end + def server.require(*) end + server.start + $-w.must_equal true + $DEBUG.must_equal true + ensure + $-w = warn + $DEBUG = debug + end + end + + if RUBY_ENGINE == "ruby" + it "support --heap option for heap profiling" do + begin + require 'objspace' + rescue LoadError + else + begin + SPEC_ARGV[0..-1] = ['-scgi', '--heap', 'test-heapfile', '-E', 'production', '-b', 'run ->(env){[200, {}, []]}'] + server = Rack::Server.new + def (server.server).run(*) end + def server.exit; throw :exit end + catch :exit do + server.start + end + File.file?('test-heapfile').must_equal true + ensure + File.delete 'test-heapfile' + end + end + end + + it "support --profile-mode option for stackprof profiling" do + begin + require 'objspace' + rescue LoadError + else + begin + SPEC_ARGV[0..-1] = ['-scgi', '--profile', 'test-profile', '--profile-mode', 'cpu', '-E', 'production', '-b', 'run ->(env){[200, {}, []]}'] + server = Rack::Server.new + def (server.server).run(*) end + def server.puts(*) end + def server.exit; throw :exit end + catch :exit do + server.start + end + File.file?('test-profile').must_equal true + ensure + File.delete 'test-profile' + end + end + end + + it "support --profile-mode option for stackprof profiling without --profile option" do + begin + require 'stackprof' + rescue LoadError + else + begin + SPEC_ARGV[0..-1] = ['-scgi', '--profile-mode', 'cpu', '-E', 'production', '-b', 'run ->(env){[200, {}, []]}'] + server = Rack::Server.new + def (server.server).run(*) end + filename = nil + server.define_singleton_method(:make_profile_name) do |fname, &block| + super(fname) do |fn| + filename = fn + block.call(filename) + end + end + def server.puts(*) end + def server.exit; throw :exit end + catch :exit do + server.start + end + File.file?(filename).must_equal true + ensure + File.delete filename + end + end + end + end + + it "support exit for INT signal when server does not respond to shutdown" do + SPEC_ARGV[0..-1] = ['-scgi'] + server = Rack::Server.new + def (server.server).run(*) end + def server.handle_profiling(*) end + def server.app(*) end + exited = false + server.define_singleton_method(:exit) do + exited = true + end + server.start + exited.must_equal false + Process.kill(:INT, $$) + exited.must_equal true + end + + it "support support Server.start for starting" do + SPEC_ARGV[0..-1] = ['-scgi'] + c = Class.new(Rack::Server) do + def start(*) [self.class, :started] end + end + c.start.must_equal [c, :started] + end + + it "run a server" do pidfile = Tempfile.open('pidfile') { |f| break f } FileUtils.rm pidfile.path @@ -208,7 +435,15 @@ describe Rack::Server do server.send(:pidfile_process_status).must_equal :not_owned end - it "not write pid file when it is created after check" do + it "rewrite pid file when it does not reference a running process" do + pidfile = Tempfile.open('pidfile') { |f| break f }.path + server = Rack::Server.new(pid: pidfile) + ::File.open(pidfile, 'w') { } + server.send(:write_pid) + ::File.read(pidfile).to_i.must_equal $$ + end + + it "not write pid file when it references a running process" do pidfile = Tempfile.open('pidfile') { |f| break f }.path ::File.delete(pidfile) server = Rack::Server.new(pid: pidfile) |