sanford 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +1 -1
- data/README.md +41 -56
- data/Rakefile +0 -1
- data/bench/client.rb +8 -3
- data/bench/{services.rb → config.sanford} +11 -6
- data/bench/{runner.rb → report.rb} +2 -2
- data/bench/report.txt +32 -32
- data/lib/sanford/cli.rb +42 -28
- data/lib/sanford/config_file.rb +79 -0
- data/lib/sanford/{worker.rb → connection_handler.rb} +28 -20
- data/lib/sanford/error_handler.rb +7 -7
- data/lib/sanford/pid_file.rb +42 -0
- data/lib/sanford/process.rb +136 -0
- data/lib/sanford/process_signal.rb +20 -0
- data/lib/sanford/route.rb +48 -0
- data/lib/sanford/router.rb +36 -0
- data/lib/sanford/runner.rb +30 -58
- data/lib/sanford/sanford_runner.rb +19 -9
- data/lib/sanford/server.rb +211 -42
- data/lib/sanford/server_data.rb +47 -0
- data/lib/sanford/service_handler.rb +8 -46
- data/lib/sanford/template_source.rb +19 -2
- data/lib/sanford/test_runner.rb +27 -28
- data/lib/sanford/version.rb +1 -1
- data/lib/sanford.rb +1 -23
- data/sanford.gemspec +4 -5
- data/test/helper.rb +3 -20
- data/test/support/app_server.rb +142 -0
- data/test/support/config.sanford +7 -0
- data/test/support/config_invalid_run.sanford +3 -0
- data/test/support/config_no_run.sanford +0 -0
- data/test/support/fake_server_connection.rb +58 -0
- data/test/support/pid_file_spy.rb +19 -0
- data/test/support/template.erb +1 -0
- data/test/system/server_tests.rb +378 -0
- data/test/system/service_handler_tests.rb +224 -0
- data/test/unit/cli_tests.rb +187 -0
- data/test/unit/config_file_tests.rb +59 -0
- data/test/unit/connection_handler_tests.rb +254 -0
- data/test/unit/error_handler_tests.rb +30 -35
- data/test/unit/pid_file_tests.rb +70 -0
- data/test/unit/process_signal_tests.rb +61 -0
- data/test/unit/process_tests.rb +428 -0
- data/test/unit/route_tests.rb +92 -0
- data/test/unit/router_tests.rb +65 -0
- data/test/unit/runner_tests.rb +61 -15
- data/test/unit/sanford_runner_tests.rb +162 -28
- data/test/unit/sanford_tests.rb +0 -8
- data/test/unit/server_data_tests.rb +87 -0
- data/test/unit/server_tests.rb +502 -21
- data/test/unit/service_handler_tests.rb +114 -219
- data/test/unit/template_engine_tests.rb +1 -1
- data/test/unit/template_source_tests.rb +56 -16
- data/test/unit/test_runner_tests.rb +206 -0
- metadata +67 -67
- data/bench/tasks.rb +0 -41
- data/lib/sanford/config.rb +0 -28
- data/lib/sanford/host.rb +0 -129
- data/lib/sanford/host_data.rb +0 -65
- data/lib/sanford/hosts.rb +0 -38
- data/lib/sanford/manager.rb +0 -275
- data/test/support/fake_connection.rb +0 -36
- data/test/support/helpers.rb +0 -17
- data/test/support/service_handlers.rb +0 -154
- data/test/support/services.rb +0 -123
- data/test/support/simple_client.rb +0 -62
- data/test/system/request_handling_tests.rb +0 -306
- data/test/unit/config_tests.rb +0 -56
- data/test/unit/host_data_tests.rb +0 -71
- data/test/unit/host_tests.rb +0 -141
- data/test/unit/hosts_tests.rb +0 -50
- data/test/unit/manager_tests.rb +0 -195
- data/test/unit/worker_tests.rb +0 -24
@@ -0,0 +1,47 @@
|
|
1
|
+
module Sanford
|
2
|
+
|
3
|
+
class ServerData
|
4
|
+
|
5
|
+
# The server uses this to "compile" its configuration for speed. NsOptions
|
6
|
+
# is relatively slow everytime an option is read. To avoid this, we read the
|
7
|
+
# options one time here and memoize their values. This way, we don't pay the
|
8
|
+
# NsOptions overhead when reading them while handling a request.
|
9
|
+
|
10
|
+
attr_reader :name
|
11
|
+
attr_reader :ip, :port
|
12
|
+
attr_reader :pid_file
|
13
|
+
attr_reader :logger, :verbose_logging
|
14
|
+
attr_reader :receives_keep_alive
|
15
|
+
attr_reader :error_procs
|
16
|
+
attr_reader :routes
|
17
|
+
attr_reader :template_source
|
18
|
+
|
19
|
+
def initialize(args = nil)
|
20
|
+
args ||= {}
|
21
|
+
@name = args[:name]
|
22
|
+
@ip = args[:ip]
|
23
|
+
@port = args[:port]
|
24
|
+
@pid_file = args[:pid_file]
|
25
|
+
@logger = args[:logger]
|
26
|
+
@verbose_logging = !!args[:verbose_logging]
|
27
|
+
@receives_keep_alive = !!args[:receives_keep_alive]
|
28
|
+
@error_procs = args[:error_procs] || []
|
29
|
+
@routes = build_routes(args[:routes] || [])
|
30
|
+
@template_source = args[:template_source]
|
31
|
+
end
|
32
|
+
|
33
|
+
def route_for(name)
|
34
|
+
@routes[name] || raise(NotFoundError, "no service named '#{name}'")
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def build_routes(routes)
|
40
|
+
routes.inject({}){ |h, route| h.merge(route.name => route) }
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
NotFoundError = Class.new(RuntimeError)
|
46
|
+
|
47
|
+
end
|
@@ -1,22 +1,7 @@
|
|
1
|
-
require 'sanford/sanford_runner'
|
2
|
-
require 'sanford/template_source'
|
3
|
-
|
4
1
|
module Sanford
|
5
2
|
|
6
3
|
module ServiceHandler
|
7
4
|
|
8
|
-
DISALLOWED_TEMPLATE_EXTS = Sanford::TemplateSource::DISALLOWED_ENGINE_EXTS
|
9
|
-
|
10
|
-
def self.constantize(class_name)
|
11
|
-
names = class_name.to_s.split('::').reject{|name| name.empty? }
|
12
|
-
klass = names.inject(Object) do |constant, name|
|
13
|
-
constant.const_get(name)
|
14
|
-
end
|
15
|
-
klass == Object ? false : klass
|
16
|
-
rescue NameError
|
17
|
-
false
|
18
|
-
end
|
19
|
-
|
20
5
|
def self.included(klass)
|
21
6
|
klass.class_eval do
|
22
7
|
extend ClassMethods
|
@@ -31,18 +16,18 @@ module Sanford
|
|
31
16
|
end
|
32
17
|
|
33
18
|
def init
|
34
|
-
|
19
|
+
run_callback 'before_init'
|
35
20
|
self.init!
|
36
|
-
|
21
|
+
run_callback 'after_init'
|
37
22
|
end
|
38
23
|
|
39
24
|
def init!
|
40
25
|
end
|
41
26
|
|
42
27
|
def run
|
43
|
-
|
28
|
+
run_callback 'before_run'
|
44
29
|
data = self.run!
|
45
|
-
|
30
|
+
run_callback 'after_run'
|
46
31
|
[ 200, data ]
|
47
32
|
end
|
48
33
|
|
@@ -55,26 +40,19 @@ module Sanford
|
|
55
40
|
"#<#{self.class}:#{reference} @request=#{self.request.inspect}>"
|
56
41
|
end
|
57
42
|
|
58
|
-
|
43
|
+
private
|
59
44
|
|
60
45
|
# Helpers
|
61
46
|
|
62
47
|
def render(path, options = nil)
|
63
48
|
options ||= {}
|
64
|
-
|
65
|
-
|
66
|
-
self,
|
67
|
-
options['locals'] || {}
|
68
|
-
)
|
69
|
-
end
|
70
|
-
|
71
|
-
def run_handler(handler_class, params = nil)
|
72
|
-
handler_class.run(params || {}, self.logger)
|
49
|
+
source = options['source'] || @sanford_runner.template_source
|
50
|
+
source.render(path, self, options['locals'] || {})
|
73
51
|
end
|
74
52
|
|
75
53
|
def halt(*args); @sanford_runner.halt(*args); end
|
76
54
|
def request; @sanford_runner.request; end
|
77
|
-
def params;
|
55
|
+
def params; @sanford_runner.params; end
|
78
56
|
def logger; @sanford_runner.logger; end
|
79
57
|
|
80
58
|
def run_callback(callback)
|
@@ -83,26 +61,10 @@ module Sanford
|
|
83
61
|
end
|
84
62
|
end
|
85
63
|
|
86
|
-
private
|
87
|
-
|
88
|
-
def get_engine(path, source)
|
89
|
-
source.engines[File.extname(get_template(path, source))[1..-1] || '']
|
90
|
-
end
|
91
|
-
|
92
|
-
def get_template(path, source)
|
93
|
-
files = Dir.glob("#{Pathname.new(source.path).join(path.to_s)}.*")
|
94
|
-
files = files.reject{ |p| DISALLOWED_TEMPLATE_EXTS.include?(File.extname(p)) }
|
95
|
-
files.first.to_s
|
96
|
-
end
|
97
|
-
|
98
64
|
end
|
99
65
|
|
100
66
|
module ClassMethods
|
101
67
|
|
102
|
-
def run(params = nil, logger = nil)
|
103
|
-
SanfordRunner.run(self, params || {}, logger)
|
104
|
-
end
|
105
|
-
|
106
68
|
def before_callbacks; @before_callbacks ||= []; end
|
107
69
|
def after_callbacks; @after_callbacks ||= []; end
|
108
70
|
def before_init_callbacks; @before_init_callbacks ||= []; end
|
@@ -4,7 +4,7 @@ module Sanford
|
|
4
4
|
|
5
5
|
class TemplateSource
|
6
6
|
|
7
|
-
DISALLOWED_ENGINE_EXTS = [ '
|
7
|
+
DISALLOWED_ENGINE_EXTS = [ 'rb' ]
|
8
8
|
|
9
9
|
DisallowedEngineExtError = Class.new(ArgumentError)
|
10
10
|
|
@@ -17,7 +17,7 @@ module Sanford
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def engine(input_ext, engine_class, registered_opts = nil)
|
20
|
-
if DISALLOWED_ENGINE_EXTS.include?(
|
20
|
+
if DISALLOWED_ENGINE_EXTS.include?(input_ext)
|
21
21
|
raise DisallowedEngineExtError, "`#{input_ext}` is disallowed as an"\
|
22
22
|
" engine extension."
|
23
23
|
end
|
@@ -25,6 +25,23 @@ module Sanford
|
|
25
25
|
@engines[input_ext.to_s] = engine_class.new(engine_opts)
|
26
26
|
end
|
27
27
|
|
28
|
+
def render(template_path, service_handler, locals)
|
29
|
+
engine = @engines[get_template_ext(template_path)]
|
30
|
+
engine.render(template_path, service_handler, locals)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def get_template_ext(template_path)
|
36
|
+
files = Dir.glob("#{File.join(@path, template_path.to_s)}.*")
|
37
|
+
files = files.reject{ |p| !@engines.keys.include?(parse_ext(p)) }
|
38
|
+
parse_ext(files.first.to_s || '')
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_ext(template_path)
|
42
|
+
File.extname(template_path)[1..-1]
|
43
|
+
end
|
44
|
+
|
28
45
|
end
|
29
46
|
|
30
47
|
class NullTemplateSource < TemplateSource
|
data/lib/sanford/test_runner.rb
CHANGED
@@ -1,53 +1,52 @@
|
|
1
1
|
require 'sanford-protocol'
|
2
|
+
require 'sanford/logger'
|
2
3
|
require 'sanford/runner'
|
3
4
|
require 'sanford/service_handler'
|
5
|
+
require 'sanford/template_source'
|
4
6
|
|
5
7
|
module Sanford
|
6
8
|
|
7
|
-
InvalidServiceHandlerError = Class.new(
|
9
|
+
InvalidServiceHandlerError = Class.new(StandardError)
|
8
10
|
|
9
|
-
class TestRunner
|
10
|
-
include Sanford::Runner
|
11
|
+
class TestRunner < Sanford::Runner
|
11
12
|
|
12
13
|
attr_reader :response
|
13
14
|
|
14
|
-
def initialize(handler_class,
|
15
|
+
def initialize(handler_class, args = nil)
|
15
16
|
if !handler_class.include?(Sanford::ServiceHandler)
|
16
17
|
raise InvalidServiceHandlerError, "#{handler_class.inspect} is not a"\
|
17
18
|
" Sanford::ServiceHandler"
|
18
19
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
args = (args || {}).dup
|
21
|
+
@request = args.delete(:request)
|
22
|
+
@params = args.delete(:params) || {}
|
23
|
+
@logger = args.delete(:logger) || Sanford::NullLogger.new
|
24
|
+
@template_source = args.delete(:template_source) ||
|
25
|
+
Sanford::NullTemplateSource.new
|
26
|
+
|
27
|
+
super(handler_class)
|
28
|
+
args.each{ |key, value| @handler.send("#{key}=", value) }
|
29
|
+
|
30
|
+
return_value = catch(:halt){ @handler.init; nil }
|
31
|
+
@response = build_and_serialize_response{ return_value } if return_value
|
25
32
|
end
|
26
33
|
|
27
|
-
# we
|
28
|
-
#
|
29
|
-
#
|
34
|
+
# If `init` generated a response, we don't want to `run` at all. This makes
|
35
|
+
# the `TestRunner` behave similar to the `SanfordRunner`, i.e. `halt` in
|
36
|
+
# `init` stops processing where `halt` is called.
|
30
37
|
|
31
38
|
def run
|
32
|
-
@response ||=
|
33
|
-
# attempt to serialize (and then throw away) the response data
|
34
|
-
# this will error on the developer if BSON can't serialize their response
|
35
|
-
Sanford::Protocol::BsonBody.new.encode(response.to_hash)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def run!
|
40
|
-
self.handler.run
|
39
|
+
@response ||= build_and_serialize_response{ self.handler.run }
|
41
40
|
end
|
42
41
|
|
43
42
|
private
|
44
43
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
def build_and_serialize_response(&block)
|
45
|
+
build_response(&block).tap do |response|
|
46
|
+
# attempt to serialize (and then throw away) the response data
|
47
|
+
# this will error on the developer if BSON can't serialize their response
|
48
|
+
Sanford::Protocol::BsonBody.new.encode(response.to_hash) if response
|
49
|
+
end
|
51
50
|
end
|
52
51
|
|
53
52
|
end
|
data/lib/sanford/version.rb
CHANGED
data/lib/sanford.rb
CHANGED
@@ -1,29 +1,7 @@
|
|
1
1
|
require 'sanford/version'
|
2
|
-
require 'sanford/
|
3
|
-
require 'sanford/hosts'
|
4
|
-
require 'sanford/host'
|
2
|
+
require 'sanford/server'
|
5
3
|
require 'sanford/service_handler'
|
6
4
|
|
7
|
-
ENV['SANFORD_SERVICES_FILE'] ||= 'config/services'
|
8
|
-
|
9
5
|
module Sanford
|
10
6
|
|
11
|
-
def self.config; @config ||= Config.new; end
|
12
|
-
def self.configure(&block)
|
13
|
-
block.call(self.config)
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.init
|
17
|
-
@hosts ||= Sanford::Hosts.new
|
18
|
-
require self.config.services_file
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.register(host)
|
22
|
-
@hosts.add(host)
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.hosts
|
26
|
-
@hosts
|
27
|
-
end
|
28
|
-
|
29
7
|
end
|
data/sanford.gemspec
CHANGED
@@ -18,10 +18,9 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
-
gem.add_dependency("dat-tcp",
|
22
|
-
gem.add_dependency("ns-options",
|
23
|
-
gem.add_dependency("sanford-protocol",
|
21
|
+
gem.add_dependency("dat-tcp", ["~> 0.5"])
|
22
|
+
gem.add_dependency("ns-options", ["~> 1.1"])
|
23
|
+
gem.add_dependency("sanford-protocol", ["~> 0.9"])
|
24
24
|
|
25
|
-
gem.add_development_dependency("assert",
|
26
|
-
gem.add_development_dependency("assert-mocha", ["~> 1.1"])
|
25
|
+
gem.add_development_dependency("assert", ["~> 2.11"])
|
27
26
|
end
|
data/test/helper.rb
CHANGED
@@ -5,27 +5,10 @@
|
|
5
5
|
$LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
|
6
6
|
|
7
7
|
require 'pry' # require pry for debugging (`binding.pry`)
|
8
|
-
require 'assert-mocha' if defined?(Assert)
|
9
8
|
|
10
9
|
ENV['SANFORD_PROTOCOL_DEBUG'] = 'yes'
|
11
10
|
|
12
|
-
require '
|
13
|
-
|
11
|
+
require 'pathname'
|
12
|
+
ROOT_PATH = Pathname.new(File.expand_path('../..', __FILE__))
|
14
13
|
|
15
|
-
|
16
|
-
def render(path, service_handler, locals)
|
17
|
-
[path.to_s, service_handler.class.to_s, locals]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
Sanford.configure do |config|
|
21
|
-
config.services_file = File.join(ROOT, 'test/support/services')
|
22
|
-
config.set_template_source File.join(ROOT, 'test/support') do |s|
|
23
|
-
s.engine 'test', MyTestEngine
|
24
|
-
end
|
25
|
-
end
|
26
|
-
Sanford.init
|
27
|
-
|
28
|
-
require 'test/support/fake_connection'
|
29
|
-
require 'test/support/service_handlers'
|
30
|
-
require 'test/support/simple_client'
|
31
|
-
require 'test/support/helpers'
|
14
|
+
require 'test/support/factory'
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'sanford'
|
3
|
+
require 'sanford-protocol'
|
4
|
+
|
5
|
+
if !defined?(ROOT_PATH)
|
6
|
+
ROOT_PATH = Pathname.new(File.expand_path('../../..', __FILE__))
|
7
|
+
end
|
8
|
+
|
9
|
+
class AppERBEngine < Sanford::TemplateEngine
|
10
|
+
RenderScope = Struct.new(:view)
|
11
|
+
|
12
|
+
def render(path, service_handler, locals)
|
13
|
+
require 'erb'
|
14
|
+
full_path = ROOT_PATH.join("test/support/#{path}.erb")
|
15
|
+
binding = RenderScope.new(service_handler).send(:binding)
|
16
|
+
ERB.new(File.read(full_path)).result(binding)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class AppServer
|
21
|
+
include Sanford::Server
|
22
|
+
|
23
|
+
name 'app'
|
24
|
+
ip 'localhost'
|
25
|
+
port 12000
|
26
|
+
|
27
|
+
receives_keep_alive true
|
28
|
+
|
29
|
+
logger Logger.new(ROOT_PATH.join('log/app_server.log').to_s)
|
30
|
+
verbose_logging true
|
31
|
+
|
32
|
+
router do
|
33
|
+
service_handler_ns 'AppHandlers'
|
34
|
+
|
35
|
+
service 'echo', 'Echo'
|
36
|
+
service 'raise', 'Raise'
|
37
|
+
service 'bad_response', 'BadResponse'
|
38
|
+
service 'template', 'Template'
|
39
|
+
service 'halt', 'Halt'
|
40
|
+
service 'custom_error', 'CustomError'
|
41
|
+
end
|
42
|
+
|
43
|
+
build_template_source ROOT_PATH.join('test/support').to_s do |s|
|
44
|
+
s.engine 'erb', AppERBEngine
|
45
|
+
end
|
46
|
+
|
47
|
+
error do |exception, server_data, request|
|
48
|
+
if request && request.name == 'custom_error'
|
49
|
+
data = "The server on #{server_data.ip}:#{server_data.port} " \
|
50
|
+
"threw a #{exception.class}."
|
51
|
+
Sanford::Protocol::Response.new(200, data)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
module AppHandlers
|
58
|
+
|
59
|
+
class Echo
|
60
|
+
include Sanford::ServiceHandler
|
61
|
+
|
62
|
+
def run!
|
63
|
+
params['message']
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Raise
|
68
|
+
include Sanford::ServiceHandler
|
69
|
+
|
70
|
+
def run!
|
71
|
+
raise "hahaha"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class BadResponse
|
76
|
+
include Sanford::ServiceHandler
|
77
|
+
|
78
|
+
def run!
|
79
|
+
Class.new
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Template
|
84
|
+
include Sanford::ServiceHandler
|
85
|
+
|
86
|
+
attr_reader :message
|
87
|
+
|
88
|
+
def init!
|
89
|
+
@message = params['message']
|
90
|
+
end
|
91
|
+
|
92
|
+
def run!
|
93
|
+
render "template"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Halt
|
98
|
+
include Sanford::ServiceHandler
|
99
|
+
|
100
|
+
before do
|
101
|
+
halt(200, :message => "in before") if params['when'] == 'before'
|
102
|
+
end
|
103
|
+
|
104
|
+
before_init do
|
105
|
+
halt(200, :message => "in before init") if params['when'] == 'before_init'
|
106
|
+
end
|
107
|
+
|
108
|
+
def init!
|
109
|
+
halt(200, :message => "in init") if params['when'] == 'init'
|
110
|
+
end
|
111
|
+
|
112
|
+
after_init do
|
113
|
+
halt(200, :message => "in after init") if params['when'] == 'after_init'
|
114
|
+
end
|
115
|
+
|
116
|
+
before_run do
|
117
|
+
halt(200, :message => "in before run") if params['when'] == 'before_run'
|
118
|
+
end
|
119
|
+
|
120
|
+
def run!
|
121
|
+
halt(200, :message => "in run") if params['when'] == 'run'
|
122
|
+
false
|
123
|
+
end
|
124
|
+
|
125
|
+
after_run do
|
126
|
+
halt(200, :message => "in after run") if params['when'] == 'after_run'
|
127
|
+
end
|
128
|
+
|
129
|
+
after do
|
130
|
+
halt(200, :message => "in after") if params['when'] == 'after'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class CustomError
|
135
|
+
include Sanford::ServiceHandler
|
136
|
+
|
137
|
+
def run!
|
138
|
+
raise StandardError
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
File without changes
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'sanford-protocol'
|
2
|
+
|
3
|
+
class FakeServerConnection
|
4
|
+
|
5
|
+
attr_reader :request, :response
|
6
|
+
attr_reader :write_closed
|
7
|
+
attr_accessor :raise_on_write, :write_exception
|
8
|
+
attr_writer :read_data
|
9
|
+
|
10
|
+
def self.with_request(name, params = nil)
|
11
|
+
self.new.tap{ |c| c.add_request(name, params) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(read_data = nil)
|
15
|
+
@read_data = read_data
|
16
|
+
@raise_on_write = false
|
17
|
+
@write_closed = false
|
18
|
+
|
19
|
+
@write_exception = RuntimeError.new('oops')
|
20
|
+
|
21
|
+
@request = nil
|
22
|
+
@response = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_request(name, params = nil)
|
26
|
+
@request = Sanford::Protocol::Request.new(name, params || {})
|
27
|
+
@read_data = @request.to_hash
|
28
|
+
end
|
29
|
+
|
30
|
+
def read_data
|
31
|
+
@read_data || {}
|
32
|
+
end
|
33
|
+
|
34
|
+
def write_data(data = nil)
|
35
|
+
write_data!(data) if data
|
36
|
+
@write_data
|
37
|
+
end
|
38
|
+
|
39
|
+
def peek_data
|
40
|
+
@read_data ? @read_data[0] : ""
|
41
|
+
end
|
42
|
+
|
43
|
+
def close_write
|
44
|
+
@write_closed = true
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def write_data!(data)
|
50
|
+
if @raise_on_write
|
51
|
+
@raise_on_write = false
|
52
|
+
raise @write_exception
|
53
|
+
end
|
54
|
+
@response = Sanford::Protocol::Response.parse(data) rescue nil
|
55
|
+
@write_data = data
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class PIDFileSpy
|
2
|
+
|
3
|
+
attr_reader :pid, :write_called, :remove_called
|
4
|
+
|
5
|
+
def initialize(pid)
|
6
|
+
@pid = pid
|
7
|
+
@write_called = false
|
8
|
+
@remove_called = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def write
|
12
|
+
@write_called = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove
|
16
|
+
@remove_called = true
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
ERB Template Message: <%= view.message %>
|