test/unit/server_tests.rb in sanford-0.15.1 vs test/unit/server_tests.rb in sanford-0.16.0
- old
+ new
@@ -1,13 +1,12 @@
require 'assert'
require 'sanford/server'
require 'dat-tcp/server_spy'
+require 'much-plugin'
require 'ns-options/assert_macros'
require 'sanford/route'
-require 'sanford-protocol/fake_connection'
-require 'test/support/fake_server_connection'
module Sanford::Server
class UnitTests < Assert::Context
desc "Sanford::Server"
@@ -19,16 +18,21 @@
subject{ @server_class }
should have_imeths :configuration
should have_imeths :name, :ip, :port, :pid_file
should have_imeths :receives_keep_alive
+ should have_imeths :worker_class, :worker_params
+ should have_imeths :num_workers, :workers
should have_imeths :verbose_logging, :logger
+ should have_imeths :shutdown_timeout
should have_imeths :init, :error
- should have_imeths :on_worker_start, :on_worker_shutdown
- should have_imeths :on_worker_sleep, :on_worker_wakeup
should have_imeths :router, :template_source
+ should "use much-plugin" do
+ assert_includes MuchPlugin, Sanford::Server
+ end
+
should "know its configuration" do
config = subject.configuration
assert_instance_of Configuration, config
assert_same config, subject.configuration
end
@@ -55,22 +59,50 @@
end
should "allow reading/writing its configuration pid file" do
new_pid_file = Factory.string
subject.pid_file(new_pid_file)
- expected = Pathname.new(new_pid_file)
- assert_equal expected, subject.configuration.pid_file
- assert_equal expected, subject.pid_file
+ exp = Pathname.new(new_pid_file)
+ assert_equal exp, subject.configuration.pid_file
+ assert_equal exp, subject.pid_file
end
should "allow reading/writing its configuration receives keep alive" do
new_keep_alive = Factory.boolean
subject.receives_keep_alive(new_keep_alive)
assert_equal new_keep_alive, subject.configuration.receives_keep_alive
assert_equal new_keep_alive, subject.receives_keep_alive
end
+ should "allow reading/writing its configuration worker class" do
+ new_worker_class = Class.new
+ subject.worker_class(new_worker_class)
+ assert_equal new_worker_class, subject.configuration.worker_class
+ assert_equal new_worker_class, subject.worker_class
+ end
+
+ should "allow reading/writing its configuration worker params" do
+ new_worker_params = { Factory.string => Factory.string }
+ subject.worker_params(new_worker_params)
+ assert_equal new_worker_params, subject.configuration.worker_params
+ assert_equal new_worker_params, subject.worker_params
+ end
+
+ should "allow reading/writing its configuration num workers" do
+ new_num_workers = Factory.integer
+ subject.num_workers(new_num_workers)
+ assert_equal new_num_workers, subject.configuration.num_workers
+ assert_equal new_num_workers, subject.num_workers
+ end
+
+ should "alias workers as num workers" do
+ new_workers = Factory.integer
+ subject.workers(new_workers)
+ assert_equal new_workers, subject.configuration.num_workers
+ assert_equal new_workers, subject.workers
+ end
+
should "allow reading/writing its configuration verbose logging" do
new_verbose = Factory.boolean
subject.verbose_logging(new_verbose)
assert_equal new_verbose, subject.configuration.verbose_logging
assert_equal new_verbose, subject.verbose_logging
@@ -81,10 +113,17 @@
subject.logger(new_logger)
assert_equal new_logger, subject.configuration.logger
assert_equal new_logger, subject.logger
end
+ should "allow reading/writing its configuration shutdown timeout" do
+ new_shutdown_timeout = Factory.integer
+ subject.shutdown_timeout(new_shutdown_timeout)
+ assert_equal new_shutdown_timeout, subject.configuration.shutdown_timeout
+ assert_equal new_shutdown_timeout, subject.shutdown_timeout
+ end
+
should "allow adding init procs to its configuration" do
new_init_proc = proc{ Factory.string }
subject.init(&new_init_proc)
assert_includes new_init_proc, subject.configuration.init_procs
end
@@ -93,26 +132,10 @@
new_error_proc = proc{ Factory.string }
subject.error(&new_error_proc)
assert_includes new_error_proc, subject.configuration.error_procs
end
- should "allow reading/writing its configuration worker procs" do
- p = proc{}
-
- subject.on_worker_start(&p)
- assert_equal [p], subject.configuration.worker_start_procs
-
- subject.on_worker_shutdown(&p)
- assert_equal [p], subject.configuration.worker_shutdown_procs
-
- subject.on_worker_sleep(&p)
- assert_equal [p], subject.configuration.worker_sleep_procs
-
- subject.on_worker_wakeup(&p)
- assert_equal [p], subject.configuration.worker_wakeup_procs
- end
-
should "allow reading/writing its configuration router" do
new_router = Factory.string
subject.router(new_router)
assert_equal new_router, subject.configuration.router
assert_equal new_router, subject.router
@@ -140,32 +163,24 @@
desc "when init"
setup do
@server_class.name Factory.string
@server_class.ip Factory.string
@server_class.port Factory.integer
+ @server_class.num_workers Factory.integer
+ @server_class.worker_params(Factory.string => Factory.string)
+ @server_class.shutdown_timeout Factory.integer
@error_procs = Factory.integer(3).times.map{ proc{} }
@error_procs.each{ |p| @server_class.error(&p) }
- @start_procs = Factory.integer(3).times.map{ proc{} }
- @shutdown_procs = Factory.integer(3).times.map{ proc{} }
- @sleep_procs = Factory.integer(3).times.map{ proc{} }
- @wakeup_procs = Factory.integer(3).times.map{ proc{} }
- @start_procs.each { |p| @server_class.on_worker_start(&p) }
- @shutdown_procs.each { |p| @server_class.on_worker_shutdown(&p) }
- @sleep_procs.each { |p| @server_class.on_worker_sleep(&p) }
- @wakeup_procs.each { |p| @server_class.on_worker_wakeup(&p) }
-
@server_class.router do
service Factory.string, TestHandler.to_s
end
- @dat_tcp_server_spy = nil
- Assert.stub(DatTCP::Server, :new) do |&block|
- @dat_tcp_server_spy = DatTCP::ServerSpy.new
- @dat_tcp_server_spy.serve_proc = block
- @dat_tcp_server_spy
+ @dtcp_spy = nil
+ Assert.stub(DatTCP::Server, :new) do |*args|
+ @dtcp_spy = DatTCP::ServerSpy.new(*args)
end
@server = @server_class.new
end
subject{ @server }
@@ -182,38 +197,40 @@
assert_true subject.class.configuration.valid?
end
should "know its server data" do
configuration = subject.class.configuration
- sd = subject.server_data
+ data = subject.server_data
- assert_instance_of Sanford::ServerData, sd
- assert_equal configuration.name, sd.name
- assert_equal configuration.ip, sd.ip
- assert_equal configuration.port, sd.port
- assert_equal configuration.verbose_logging, sd.verbose_logging
- assert_equal configuration.receives_keep_alive, sd.receives_keep_alive
- assert_equal configuration.error_procs, sd.error_procs
- assert_equal configuration.worker_start_procs, sd.worker_start_procs
- assert_equal configuration.worker_shutdown_procs, sd.worker_shutdown_procs
- assert_equal configuration.worker_sleep_procs, sd.worker_sleep_procs
- assert_equal configuration.worker_wakeup_procs, sd.worker_wakeup_procs
- assert_equal configuration.routes, sd.routes.values
+ assert_instance_of Sanford::ServerData, data
+ assert_equal configuration.name, data.name
+ assert_equal configuration.ip, data.ip
+ assert_equal configuration.port, data.port
+ assert_equal configuration.worker_class, data.worker_class
+ assert_equal configuration.worker_params, data.worker_params
+ assert_equal configuration.verbose_logging, data.verbose_logging
+ assert_equal configuration.receives_keep_alive, data.receives_keep_alive
+ assert_equal configuration.error_procs, data.error_procs
+ assert_equal configuration.routes, data.routes.values
- assert_instance_of configuration.logger.class, sd.logger
+ assert_instance_of configuration.logger.class, data.logger
end
should "know its dat tcp server" do
- assert_not_nil @dat_tcp_server_spy
- assert_not_nil @dat_tcp_server_spy.serve_proc
+ data = subject.server_data
- assert_equal @start_procs, @dat_tcp_server_spy.worker_start_procs
- assert_equal @shutdown_procs, @dat_tcp_server_spy.worker_shutdown_procs
- assert_equal @sleep_procs, @dat_tcp_server_spy.worker_sleep_procs
- assert_equal @wakeup_procs, @dat_tcp_server_spy.worker_wakeup_procs
+ assert_not_nil @dtcp_spy
+ assert_equal data.worker_class, @dtcp_spy.worker_class
+ assert_equal data.num_workers, @dtcp_spy.num_workers
+ assert_equal data.dtcp_logger, @dtcp_spy.logger
+ assert_equal data.shutdown_timeout, @dtcp_spy.shutdown_timeout
+ exp = data.worker_params.merge({
+ :sanford_server_data => data
+ })
+ assert_equal exp, @dtcp_spy.worker_params
- assert_equal @dat_tcp_server_spy, subject.dat_tcp_server
+ assert_equal @dtcp_spy, subject.dat_tcp_server
end
should "demeter its server data" do
assert_equal subject.server_data.name, subject.name
assert_equal subject.server_data.ip, subject.configured_ip
@@ -227,17 +244,17 @@
assert_equal subject.server_data.template_source, subject.template_source
end
should "call listen on its dat tcp server using `listen`" do
subject.listen
- assert_true @dat_tcp_server_spy.listen_called
+ assert_true @dtcp_spy.listen_called
end
should "use its configured ip and port by default when listening" do
subject.listen
- assert_equal subject.server_data.ip, @dat_tcp_server_spy.ip
- assert_equal subject.server_data.port, @dat_tcp_server_spy.port
+ assert_equal subject.server_data.ip, @dtcp_spy.ip
+ assert_equal subject.server_data.port, @dtcp_spy.port
end
should "write its ip and port back to its server data" do
ip = Factory.string
port = Factory.integer
@@ -249,64 +266,64 @@
end
should "pass any args to its dat tcp server using `listen`" do
ip, port = Factory.string, Factory.integer
subject.listen(ip, port)
- assert_equal ip, @dat_tcp_server_spy.ip
- assert_equal port, @dat_tcp_server_spy.port
+ assert_equal ip, @dtcp_spy.ip
+ assert_equal port, @dtcp_spy.port
file_descriptor = Factory.integer
subject.listen(file_descriptor)
- assert_equal file_descriptor, @dat_tcp_server_spy.file_descriptor
+ assert_equal file_descriptor, @dtcp_spy.file_descriptor
end
should "know its ip, port and file descriptor" do
- assert_equal @dat_tcp_server_spy.ip, subject.ip
- assert_equal @dat_tcp_server_spy.port, subject.port
+ assert_equal @dtcp_spy.ip, subject.ip
+ assert_equal @dtcp_spy.port, subject.port
subject.listen
- assert_equal @dat_tcp_server_spy.ip, subject.ip
- assert_equal @dat_tcp_server_spy.port, subject.port
+ assert_equal @dtcp_spy.ip, subject.ip
+ assert_equal @dtcp_spy.port, subject.port
- assert_equal @dat_tcp_server_spy.file_descriptor, subject.file_descriptor
+ assert_equal @dtcp_spy.file_descriptor, subject.file_descriptor
subject.listen(Factory.integer)
- assert_equal @dat_tcp_server_spy.file_descriptor, subject.file_descriptor
+ assert_equal @dtcp_spy.file_descriptor, subject.file_descriptor
end
should "call start on its dat tcp server using `start`" do
- client_fds = [ Factory.integer ]
+ client_fds = [Factory.integer]
subject.start(client_fds)
- assert_true @dat_tcp_server_spy.start_called
- assert_equal client_fds, @dat_tcp_server_spy.client_file_descriptors
+ assert_true @dtcp_spy.start_called
+ assert_equal client_fds, @dtcp_spy.client_file_descriptors
end
should "know its client file descriptors" do
- expected = @dat_tcp_server_spy.client_file_descriptors
- assert_equal expected, subject.client_file_descriptors
- subject.start([ Factory.integer ])
- expected = @dat_tcp_server_spy.client_file_descriptors
- assert_equal expected, subject.client_file_descriptors
+ exp = @dtcp_spy.client_file_descriptors
+ assert_equal exp, subject.client_file_descriptors
+ subject.start([Factory.integer])
+ exp = @dtcp_spy.client_file_descriptors
+ assert_equal exp, subject.client_file_descriptors
end
should "call pause on its dat tcp server using `pause`" do
wait = Factory.boolean
subject.pause(wait)
- assert_true @dat_tcp_server_spy.pause_called
- assert_equal wait, @dat_tcp_server_spy.waiting_for_pause
+ assert_true @dtcp_spy.pause_called
+ assert_equal wait, @dtcp_spy.waiting_for_pause
end
should "call stop on its dat tcp server using `stop`" do
wait = Factory.boolean
subject.stop(wait)
- assert_true @dat_tcp_server_spy.stop_called
- assert_equal wait, @dat_tcp_server_spy.waiting_for_stop
+ assert_true @dtcp_spy.stop_called
+ assert_equal wait, @dtcp_spy.waiting_for_stop
end
should "call halt on its dat tcp server using `halt`" do
wait = Factory.boolean
subject.halt(wait)
- assert_true @dat_tcp_server_spy.halt_called
- assert_equal wait, @dat_tcp_server_spy.waiting_for_halt
+ assert_true @dtcp_spy.halt_called
+ assert_equal wait, @dtcp_spy.waiting_for_halt
end
should "know if its been paused" do
assert_false subject.paused?
subject.listen
@@ -321,121 +338,25 @@
class ConfigureTCPServerTests < InitTests
desc "configuring its tcp server"
setup do
@tcp_server = TCPServerSpy.new
- Assert.stub(@dat_tcp_server_spy, :listen) do |*args, &block|
+ Assert.stub(@dtcp_spy, :listen) do |*args, &block|
@configure_tcp_server_proc = block
end
@server.listen
@configure_tcp_server_proc.call(@tcp_server)
end
subject{ @tcp_server }
should "set the TCP_NODELAY option" do
- expected = [ ::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true ]
- assert_includes expected, @tcp_server.set_socket_option_calls
+ exp = [ ::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true ]
+ assert_includes exp, @tcp_server.set_socket_option_calls
end
end
- class ServeTests < InitTests
- desc "serve"
- setup do
- @socket = Factory.binary
-
- @connection = FakeServerConnection.new
- Assert.stub(Connection, :new).with(@socket){ @connection }
-
- @connection_handler_spy = ConnectionHandlerSpy.new
- Assert.stub(Sanford::ConnectionHandler, :new).tap do |s|
- s.with(@server.server_data, @connection){ @connection_handler_spy }
- end
-
- @serve_proc = @dat_tcp_server_spy.serve_proc
- end
- subject{ @serve_proc }
-
- should "run a connection_handler when called with a socket" do
- Assert.stub(@server.server_data, :receives_keep_alive){ false }
- @connection.read_data = Factory.boolean
- assert_false @connection_handler_spy.run_called
- subject.call(@socket)
- assert_true @connection_handler_spy.run_called
- end
-
- should "not run a keep-alive connection when configured to receive them" do
- Assert.stub(@server.server_data, :receives_keep_alive){ true }
- @connection.read_data = nil # nothing to read makes it a keep-alive
- assert_false @connection_handler_spy.run_called
- subject.call(@socket)
- assert_false @connection_handler_spy.run_called
- end
-
- should "run a keep-alive connection when configured to receive them" do
- Assert.stub(@server.server_data, :receives_keep_alive){ false }
- @connection.read_data = nil # nothing to read makes it a keep-alive
- assert_false @connection_handler_spy.run_called
- subject.call(@socket)
- assert_true @connection_handler_spy.run_called
- end
-
- end
-
- class ConnectionTests < UnitTests
- desc "Connection"
- setup do
- fake_socket = Factory.string
- @protocol_conn = Sanford::Protocol::FakeConnection.new(Factory.binary)
- Assert.stub(Sanford::Protocol::Connection, :new).with(fake_socket) do
- @protocol_conn
- end
- @connection = Connection.new(fake_socket)
- end
- subject{ @connection }
-
- should have_imeths :read_data, :write_data, :peek_data
- should have_imeths :close_write
-
- should "default its timeout" do
- assert_equal 1.0, subject.timeout
- end
-
- should "allowing reading from the protocol connection" do
- result = subject.read_data
- assert_equal @protocol_conn.read_data, result
- assert_equal @protocol_conn.read_timeout, subject.timeout
- end
-
- should "allowing writing to the protocol connection" do
- data = Factory.binary
- subject.write_data(data)
- assert_equal @protocol_conn.write_data, data
- end
-
- should "allowing peeking from the protocol connection" do
- result = subject.peek_data
- assert_equal @protocol_conn.peek_data, result
- assert_equal @protocol_conn.peek_timeout, subject.timeout
- end
-
- should "allow closing the write stream on the protocol connection" do
- assert_false @protocol_conn.closed_write
- subject.close_write
- assert_true @protocol_conn.closed_write
- end
-
- end
-
- class TCPCorkTests < UnitTests
- desc "TCPCork"
- subject{ TCPCork }
-
- should have_imeths :apply, :remove
-
- end
-
class ConfigurationTests < UnitTests
include NsOptions::AssertMacros
desc "Configuration"
setup do
@@ -450,21 +371,25 @@
should have_options :name, :ip, :port, :pid_file
should have_options :receives_keep_alive
should have_options :verbose_logging, :logger
should have_options :template_source
should have_accessors :init_procs, :error_procs
+ should have_accessors :worker_class, :worker_params, :num_workers
+ should have_accessors :shutdown_timeout
should have_accessors :router
- should have_readers :worker_start_procs, :worker_shutdown_procs
- should have_readers :worker_sleep_procs, :worker_wakeup_procs
should have_imeths :routes
should have_imeths :to_hash
should have_imeths :valid?, :validate!
should "be an ns-options proxy" do
assert_includes NsOptions::Proxy, subject.class
end
+ should "know its default num workers" do
+ assert_equal 4, Configuration::DEFAULT_NUM_WORKERS
+ end
+
should "default its options" do
config = Configuration.new
assert_nil config.name
assert_equal '0.0.0.0', config.ip
assert_nil config.port
@@ -474,18 +399,19 @@
assert_true config.verbose_logging
assert_instance_of Sanford::NullLogger, config.logger
assert_instance_of Sanford::NullTemplateSource, config.template_source
+ assert_equal DefaultWorker, config.worker_class
+ assert_nil config.worker_params
+ assert_equal Configuration::DEFAULT_NUM_WORKERS, config.num_workers
+
+ assert_nil config.shutdown_timeout
+
assert_equal [], config.init_procs
assert_equal [], config.error_procs
- assert_equal [], subject.worker_start_procs
- assert_equal [], subject.worker_shutdown_procs
- assert_equal [], subject.worker_sleep_procs
- assert_equal [], subject.worker_wakeup_procs
-
assert_instance_of Sanford::Router, config.router
assert_empty config.router.routes
end
should "not be valid by default" do
@@ -498,18 +424,18 @@
assert_equal subject.router.routes, subject.routes
end
should "include its procs and router/routes in its `to_hash`" do
config_hash = subject.to_hash
- assert_equal subject.init_procs, config_hash[:init_procs]
- assert_equal subject.error_procs, config_hash[:error_procs]
- assert_equal subject.worker_start_procs, config_hash[:worker_start_procs]
- assert_equal subject.worker_shutdown_procs, config_hash[:worker_shutdown_procs]
- assert_equal subject.worker_sleep_procs, config_hash[:worker_sleep_procs]
- assert_equal subject.worker_wakeup_procs, config_hash[:worker_wakeup_procs]
- assert_equal subject.router, config_hash[:router]
- assert_equal subject.routes, config_hash[:routes]
+ assert_equal subject.worker_class, config_hash[:worker_class]
+ assert_equal subject.worker_params, config_hash[:worker_params]
+ assert_equal subject.num_workers, config_hash[:num_workers]
+ assert_equal subject.shutdown_timeout, config_hash[:shutdown_timeout]
+ assert_equal subject.init_procs, config_hash[:init_procs]
+ assert_equal subject.error_procs, config_hash[:error_procs]
+ assert_equal subject.router, config_hash[:router]
+ assert_equal subject.routes, config_hash[:routes]
end
should "call its init procs when validated" do
called = false
subject.init_procs << proc{ called = true }
@@ -531,10 +457,18 @@
subject.port = Factory.integer
assert_nothing_raised{ subject.validate! }
end
+ should "validate its worker class when validated" do
+ subject.worker_class = Module.new
+ assert_raises(InvalidError){ subject.validate! }
+
+ subject.worker_class = Class.new
+ assert_raises(InvalidError){ subject.validate! }
+ end
+
should "validate its routes when validated" do
subject.router.service(Factory.string, TestHandler.to_s)
subject.routes.each{ |route| assert_nil route.handler_class }
subject.validate!
subject.routes.each{ |route| assert_not_nil route.handler_class }
@@ -566,21 +500,9 @@
@set_socket_option_calls = []
end
def setsockopt(*args)
@set_socket_option_calls << args
- end
- end
-
- class ConnectionHandlerSpy
- attr_reader :run_called
-
- def initialize
- @run_called = false
- end
-
- def run
- @run_called = true
end
end
end