sanford 0.8.0 → 0.9.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.
- checksums.yaml +7 -0
- data/Gemfile +1 -0
- data/lib/sanford/cli.rb +1 -270
- data/lib/sanford/host.rb +12 -14
- data/lib/sanford/host_data.rb +7 -7
- data/lib/sanford/manager.rb +275 -0
- data/lib/sanford/runner.rb +39 -32
- data/lib/sanford/server.rb +1 -0
- data/lib/sanford/service_handler.rb +54 -41
- data/lib/sanford/test_helpers.rb +19 -0
- data/lib/sanford/test_runner.rb +17 -12
- data/lib/sanford/version.rb +1 -1
- data/lib/sanford.rb +19 -17
- data/sanford.gemspec +5 -5
- data/test/support/service_handlers.rb +69 -43
- data/test/support/services.rb +2 -2
- data/test/support/simple_client.rb +2 -2
- data/test/system/request_handling_tests.rb +2 -2
- data/test/unit/error_handler_tests.rb +13 -12
- data/test/unit/host_data_tests.rb +26 -14
- data/test/unit/host_tests.rb +105 -16
- data/test/unit/manager_tests.rb +103 -50
- data/test/unit/runner_tests.rb +6 -3
- data/test/unit/sanford_tests.rb +70 -0
- data/test/unit/server_tests.rb +8 -6
- data/test/unit/service_handler_tests.rb +179 -68
- data/test/unit/worker_tests.rb +6 -5
- metadata +32 -74
- data/test/unit/config_tests.rb +0 -12
- data/test/unit/host_configuration_tests.rb +0 -37
- data/test/unit/hosts_tests.rb +0 -56
- data/test/unit/manager_pid_file_tests.rb +0 -60
data/lib/sanford/runner.rb
CHANGED
@@ -7,48 +7,55 @@ module Sanford
|
|
7
7
|
|
8
8
|
ResponseArgs = Struct.new(:status, :data)
|
9
9
|
|
10
|
-
attr_reader :handler_class, :request, :logger
|
11
|
-
|
12
10
|
def self.included(klass)
|
13
|
-
klass.class_eval
|
11
|
+
klass.class_eval do
|
12
|
+
extend ClassMethods
|
13
|
+
include InstanceMethods
|
14
|
+
end
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
-
@handler_class, @request = handler_class, request
|
18
|
-
@logger = logger || Sanford.config.logger
|
19
|
-
@handler = @handler_class.new(self)
|
20
|
-
self.init
|
21
|
-
end
|
17
|
+
module InstanceMethods
|
22
18
|
|
23
|
-
|
24
|
-
self.init!
|
25
|
-
end
|
19
|
+
attr_reader :handler_class, :request, :logger
|
26
20
|
|
27
|
-
|
28
|
-
|
21
|
+
def initialize(handler_class, request, logger = nil)
|
22
|
+
@handler_class, @request = handler_class, request
|
23
|
+
@logger = logger || Sanford.config.logger
|
24
|
+
@handler = @handler_class.new(self)
|
25
|
+
self.init
|
26
|
+
end
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
28
|
+
def init
|
29
|
+
self.init!
|
30
|
+
end
|
34
31
|
|
35
|
-
|
36
|
-
|
37
|
-
end
|
32
|
+
def init!
|
33
|
+
end
|
38
34
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
def run
|
36
|
+
response_args = catch_halt{ self.run!(@handler) }
|
37
|
+
Sanford::Protocol::Response.new(response_args.status, response_args.data)
|
38
|
+
end
|
43
39
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
40
|
+
def run!
|
41
|
+
raise NotImplementedError
|
42
|
+
end
|
43
|
+
|
44
|
+
# It's best to keep what `halt` and `catch_halt` return in the same format.
|
45
|
+
# Currently this is a `ResponseArgs` object. This is so no matter how the
|
46
|
+
# block returns (either by throwing or running normally), you get the same
|
47
|
+
# thing kind of object.
|
48
|
+
|
49
|
+
def halt(status, options = nil)
|
50
|
+
options = OpenStruct.new(options || {})
|
51
|
+
response_status = [ status, options.message ]
|
52
|
+
throw :halt, ResponseArgs.new(response_status, options.data)
|
53
|
+
end
|
54
|
+
|
55
|
+
def catch_halt(&block)
|
56
|
+
catch(:halt){ ResponseArgs.new(*block.call) }
|
57
|
+
end
|
49
58
|
|
50
|
-
def catch_halt(&block)
|
51
|
-
catch(:halt){ ResponseArgs.new(*block.call) }
|
52
59
|
end
|
53
60
|
|
54
61
|
module ClassMethods
|
data/lib/sanford/server.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'sanford-protocol'
|
2
|
-
require 'sanford/runner'
|
3
|
-
|
4
1
|
module Sanford
|
5
2
|
|
6
3
|
module ServiceHandler
|
@@ -18,58 +15,60 @@ module Sanford
|
|
18
15
|
def self.included(klass)
|
19
16
|
klass.class_eval do
|
20
17
|
extend ClassMethods
|
18
|
+
include InstanceMethods
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
24
|
-
|
25
|
-
@sanford_runner = runner
|
26
|
-
end
|
22
|
+
module InstanceMethods
|
27
23
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
self.run_callback 'after_init'
|
32
|
-
end
|
24
|
+
def initialize(runner)
|
25
|
+
@sanford_runner = runner
|
26
|
+
end
|
33
27
|
|
34
|
-
|
35
|
-
|
28
|
+
def init
|
29
|
+
self.run_callback 'before_init'
|
30
|
+
self.init!
|
31
|
+
self.run_callback 'after_init'
|
32
|
+
end
|
36
33
|
|
37
|
-
|
38
|
-
|
39
|
-
data = self.run!
|
40
|
-
self.run_callback 'after_run'
|
41
|
-
[ 200, data ]
|
42
|
-
end
|
34
|
+
def init!
|
35
|
+
end
|
43
36
|
|
44
|
-
|
45
|
-
|
46
|
-
|
37
|
+
def run
|
38
|
+
self.run_callback 'before_run'
|
39
|
+
data = self.run!
|
40
|
+
self.run_callback 'after_run'
|
41
|
+
[ 200, data ]
|
42
|
+
end
|
47
43
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
44
|
+
def run!
|
45
|
+
raise NotImplementedError
|
46
|
+
end
|
52
47
|
|
53
|
-
|
48
|
+
def inspect
|
49
|
+
reference = '0x0%x' % (self.object_id << 1)
|
50
|
+
"#<#{self.class}:#{reference} @request=#{self.request.inspect}>"
|
51
|
+
end
|
54
52
|
|
55
|
-
|
56
|
-
def after_init; end
|
57
|
-
def before_run; end
|
58
|
-
def after_run; end
|
53
|
+
protected
|
59
54
|
|
60
|
-
|
55
|
+
# Helpers
|
61
56
|
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
def run_handler(handler_class, params = nil)
|
58
|
+
handler_class.run(params || {}, self.logger)
|
59
|
+
end
|
60
|
+
|
61
|
+
def halt(*args); @sanford_runner.halt(*args); end
|
62
|
+
def request; @sanford_runner.request; end
|
63
|
+
def params; self.request.params; end
|
64
|
+
def logger; @sanford_runner.logger; end
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
def run_callback(callback)
|
67
|
+
(self.class.send("#{callback}_callbacks") || []).each do |callback|
|
68
|
+
self.instance_eval(&callback)
|
69
|
+
end
|
70
|
+
end
|
70
71
|
|
71
|
-
def run_callback(callback)
|
72
|
-
self.send(callback.to_s)
|
73
72
|
end
|
74
73
|
|
75
74
|
module ClassMethods
|
@@ -78,6 +77,20 @@ module Sanford
|
|
78
77
|
Sanford.config.runner.run(self, params || {}, logger)
|
79
78
|
end
|
80
79
|
|
80
|
+
def before_init_callbacks; @before_init_callbacks ||= []; end
|
81
|
+
def after_init_callbacks; @after_init_callbacks ||= []; end
|
82
|
+
def before_run_callbacks; @before_run_callbacks ||= []; end
|
83
|
+
def after_run_callbacks; @after_run_callbacks ||= []; end
|
84
|
+
|
85
|
+
def before_init(&block); self.before_init_callbacks << block; end
|
86
|
+
def after_init(&block); self.after_init_callbacks << block; end
|
87
|
+
def before_run(&block); self.before_run_callbacks << block; end
|
88
|
+
def after_run(&block); self.after_run_callbacks << block; end
|
89
|
+
def prepend_before_init(&block); self.before_init_callbacks.unshift(block); end
|
90
|
+
def prepend_after_init(&block); self.after_init_callbacks.unshift(block); end
|
91
|
+
def prepend_before_run(&block); self.before_run_callbacks.unshift(block); end
|
92
|
+
def prepend_after_run(&block); self.after_run_callbacks.unshift(block); end
|
93
|
+
|
81
94
|
end
|
82
95
|
|
83
96
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'sanford/test_runner'
|
2
|
+
|
3
|
+
module Sanford
|
4
|
+
|
5
|
+
module TestHelpers
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def test_runner(handler_class, args = nil)
|
10
|
+
TestRunner.new(handler_class, args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_handler(handler_class, args = nil)
|
14
|
+
test_runner(handler_class, args).handler
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/lib/sanford/test_runner.rb
CHANGED
@@ -1,14 +1,24 @@
|
|
1
1
|
require 'sanford-protocol'
|
2
|
-
|
3
2
|
require 'sanford/runner'
|
3
|
+
require 'sanford/service_handler'
|
4
4
|
|
5
5
|
module Sanford
|
6
6
|
|
7
|
+
InvalidServiceHandlerError = Class.new(RuntimeError)
|
8
|
+
|
7
9
|
class TestRunner
|
8
10
|
include Sanford::Runner
|
9
11
|
|
10
12
|
attr_reader :handler, :response
|
11
13
|
|
14
|
+
def initialize(handler_class, *args)
|
15
|
+
if !handler_class.include?(Sanford::ServiceHandler)
|
16
|
+
raise InvalidServiceHandlerError, "#{handler_class.inspect} is not a"\
|
17
|
+
" Sanford::ServiceHandler"
|
18
|
+
end
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
12
22
|
def init!
|
13
23
|
if !@request.kind_of?(Sanford::Protocol::Request)
|
14
24
|
@request = test_request(@request)
|
@@ -21,28 +31,23 @@ module Sanford
|
|
21
31
|
# want to `run` at all.
|
22
32
|
|
23
33
|
def run
|
24
|
-
@response ||= build_response
|
34
|
+
@response ||= build_response(catch_halt{ @handler.run }).tap do |response|
|
35
|
+
# attempt to serialize (and then throw away) the response data
|
36
|
+
# this will error on the developer if BSON can't serialize their response
|
37
|
+
Sanford::Protocol::BsonBody.new.encode(response.to_hash)
|
38
|
+
end
|
25
39
|
end
|
26
40
|
|
27
41
|
protected
|
28
42
|
|
29
43
|
def test_request(params)
|
30
|
-
Sanford::Protocol::Request.new('name', params)
|
44
|
+
Sanford::Protocol::Request.new('name', params || {})
|
31
45
|
end
|
32
46
|
|
33
47
|
def build_response(response_args)
|
34
48
|
Sanford::Protocol::Response.new(response_args.status, response_args.data) if response_args
|
35
49
|
end
|
36
50
|
|
37
|
-
module Helpers
|
38
|
-
module_function
|
39
|
-
|
40
|
-
def test_runner(handler_class, params = nil, logger = nil)
|
41
|
-
TestRunner.new(handler_class, params || {}, logger)
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
51
|
end
|
47
52
|
|
48
53
|
end
|
data/lib/sanford/version.rb
CHANGED
data/lib/sanford.rb
CHANGED
@@ -13,14 +13,6 @@ ENV['SANFORD_SERVICES_FILE'] ||= 'config/services'
|
|
13
13
|
|
14
14
|
module Sanford
|
15
15
|
|
16
|
-
def self.register(host)
|
17
|
-
@hosts.add(host)
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.hosts
|
21
|
-
@hosts
|
22
|
-
end
|
23
|
-
|
24
16
|
def self.config
|
25
17
|
Sanford::Config
|
26
18
|
end
|
@@ -35,6 +27,14 @@ module Sanford
|
|
35
27
|
require self.config.services_file
|
36
28
|
end
|
37
29
|
|
30
|
+
def self.register(host)
|
31
|
+
@hosts.add(host)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.hosts
|
35
|
+
@hosts
|
36
|
+
end
|
37
|
+
|
38
38
|
module Config
|
39
39
|
include NsOptions::Proxy
|
40
40
|
option :services_file, Pathname, :default => ENV['SANFORD_SERVICES_FILE']
|
@@ -48,12 +48,22 @@ module Sanford
|
|
48
48
|
@set = Set.new(values)
|
49
49
|
end
|
50
50
|
|
51
|
+
def method_missing(method, *args, &block)
|
52
|
+
@set.send(method, *args, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
def respond_to?(method)
|
56
|
+
super || @set.respond_to?(method)
|
57
|
+
end
|
58
|
+
|
51
59
|
# We want class names to take precedence over a configured name, so that if
|
52
60
|
# a user specifies a specific class, they always get it
|
53
61
|
def find(name)
|
54
|
-
|
62
|
+
find_by_class_name(name) || find_by_name(name)
|
55
63
|
end
|
56
64
|
|
65
|
+
private
|
66
|
+
|
57
67
|
def find_by_class_name(class_name)
|
58
68
|
@set.detect{|host_class| host_class.to_s == class_name.to_s }
|
59
69
|
end
|
@@ -62,14 +72,6 @@ module Sanford
|
|
62
72
|
@set.detect{|host_class| host_class.name == name.to_s }
|
63
73
|
end
|
64
74
|
|
65
|
-
def method_missing(method, *args, &block)
|
66
|
-
@set.send(method, *args, &block)
|
67
|
-
end
|
68
|
-
|
69
|
-
def respond_to?(method)
|
70
|
-
super || @set.respond_to?(method)
|
71
|
-
end
|
72
|
-
|
73
75
|
end
|
74
76
|
|
75
77
|
end
|
data/sanford.gemspec
CHANGED
@@ -18,10 +18,10 @@ 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", ["~>0.4"])
|
22
|
-
gem.add_dependency("ns-options", ["~>1.
|
23
|
-
gem.add_dependency("sanford-protocol", ["~>0.
|
21
|
+
gem.add_dependency("dat-tcp", ["~> 0.4"])
|
22
|
+
gem.add_dependency("ns-options", ["~> 1.1"])
|
23
|
+
gem.add_dependency("sanford-protocol", ["~> 0.7"])
|
24
24
|
|
25
|
-
gem.add_development_dependency("assert", ["~>2.
|
26
|
-
gem.add_development_dependency("assert-mocha", ["~>1.
|
25
|
+
gem.add_development_dependency("assert", ["~> 2.10"])
|
26
|
+
gem.add_development_dependency("assert-mocha", ["~> 1.1"])
|
27
27
|
end
|
@@ -1,71 +1,80 @@
|
|
1
|
-
class
|
1
|
+
class BasicServiceHandler
|
2
2
|
include Sanford::ServiceHandler
|
3
3
|
|
4
|
+
def run!
|
5
|
+
{ 'name' => 'Joe Test', 'email' => "joe.test@example.com" }
|
6
|
+
end
|
7
|
+
|
4
8
|
end
|
5
9
|
|
6
|
-
class
|
10
|
+
class SerializeErrorServiceHandler
|
7
11
|
include Sanford::ServiceHandler
|
8
12
|
|
13
|
+
# return data that fails BSON serialization
|
14
|
+
# BSON errors if it is sent date/datetime values
|
9
15
|
def run!
|
10
|
-
{ '
|
16
|
+
{ 'date' => Date.today,
|
17
|
+
'datetime' => DateTime.now
|
18
|
+
}
|
11
19
|
end
|
12
20
|
|
13
21
|
end
|
14
22
|
|
15
|
-
|
16
|
-
include Sanford::ServiceHandler
|
23
|
+
module CallbackServiceHandler
|
17
24
|
|
18
|
-
|
19
|
-
|
25
|
+
def self.included(receiver)
|
26
|
+
receiver.class_eval do
|
27
|
+
attr_reader :before_init_called, :init_bang_called, :after_init_called
|
28
|
+
attr_reader :before_run_called, :run_bang_called, :after_run_called
|
29
|
+
attr_reader :second_before_init_called, :second_after_run_called
|
20
30
|
|
21
|
-
|
22
|
-
|
23
|
-
|
31
|
+
before_init do
|
32
|
+
@before_init_called = true
|
33
|
+
end
|
34
|
+
before_init do
|
35
|
+
@second_before_init_called = true
|
36
|
+
end
|
24
37
|
|
25
|
-
|
26
|
-
|
27
|
-
|
38
|
+
after_init do
|
39
|
+
@after_init_called = true
|
40
|
+
end
|
41
|
+
|
42
|
+
before_run do
|
43
|
+
@before_run_called = true
|
44
|
+
end
|
45
|
+
|
46
|
+
after_run do
|
47
|
+
@after_run_called = true
|
48
|
+
end
|
49
|
+
after_run do
|
50
|
+
@second_after_run_called = true
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
28
54
|
|
29
|
-
def after_init
|
30
|
-
@after_init_called = true
|
31
55
|
end
|
32
56
|
|
33
|
-
def
|
34
|
-
@
|
57
|
+
def init!
|
58
|
+
@init_bang_called = true
|
35
59
|
end
|
36
60
|
|
37
61
|
def run!
|
38
62
|
@run_bang_called = true
|
39
63
|
end
|
40
64
|
|
41
|
-
def after_run
|
42
|
-
@after_run_called = true
|
43
|
-
end
|
44
|
-
|
45
65
|
end
|
46
66
|
|
47
|
-
class
|
67
|
+
class FlagServiceHandler
|
48
68
|
include Sanford::ServiceHandler
|
69
|
+
include CallbackServiceHandler
|
49
70
|
|
50
|
-
def run!
|
51
|
-
response = run_handler(HaltServiceHandler, 'code' => 200, 'data' => 'RunOtherHandler')
|
52
|
-
response.data
|
53
|
-
end
|
54
71
|
end
|
55
72
|
|
56
|
-
class
|
73
|
+
class HaltingBehaviorServiceHandler
|
57
74
|
include Sanford::ServiceHandler
|
75
|
+
include CallbackServiceHandler
|
58
76
|
|
59
|
-
|
60
|
-
halt params['code'], :message => params['message'], :data => params['data']
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
class HaltingBehaviorServiceHandler < FlagServiceHandler
|
66
|
-
|
67
|
-
def before_init
|
68
|
-
super
|
77
|
+
before_init do
|
69
78
|
halt_when('before_init')
|
70
79
|
end
|
71
80
|
|
@@ -74,13 +83,11 @@ class HaltingBehaviorServiceHandler < FlagServiceHandler
|
|
74
83
|
halt_when('init!')
|
75
84
|
end
|
76
85
|
|
77
|
-
|
78
|
-
super
|
86
|
+
after_init do
|
79
87
|
halt_when('after_init')
|
80
88
|
end
|
81
89
|
|
82
|
-
|
83
|
-
super
|
90
|
+
before_run do
|
84
91
|
halt_when('before_run')
|
85
92
|
end
|
86
93
|
|
@@ -89,8 +96,7 @@ class HaltingBehaviorServiceHandler < FlagServiceHandler
|
|
89
96
|
halt_when('run!')
|
90
97
|
end
|
91
98
|
|
92
|
-
|
93
|
-
super
|
99
|
+
after_run do
|
94
100
|
halt_when('after_run')
|
95
101
|
end
|
96
102
|
|
@@ -110,3 +116,23 @@ class HaltingBehaviorServiceHandler < FlagServiceHandler
|
|
110
116
|
end
|
111
117
|
|
112
118
|
end
|
119
|
+
|
120
|
+
class RunOtherHandler
|
121
|
+
include Sanford::ServiceHandler
|
122
|
+
|
123
|
+
def run!
|
124
|
+
response = run_handler(HaltServiceHandler, 'code' => 200, 'data' => 'RunOtherHandler')
|
125
|
+
response.data
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class HaltServiceHandler
|
130
|
+
include Sanford::ServiceHandler
|
131
|
+
|
132
|
+
def run!
|
133
|
+
halt params['code'], :message => params['message'], :data => params['data']
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
class InvalidServiceHandler; end
|
data/test/support/services.rb
CHANGED
@@ -26,7 +26,7 @@ class TestHost
|
|
26
26
|
|
27
27
|
service_handler_ns 'TestHost'
|
28
28
|
|
29
|
-
service
|
29
|
+
service :echo, 'Echo'
|
30
30
|
service 'bad', 'Bad'
|
31
31
|
service 'multiply', 'Multiply'
|
32
32
|
service 'halt_it', '::TestHost::HaltIt'
|
@@ -76,7 +76,7 @@ class TestHost
|
|
76
76
|
class Authorized
|
77
77
|
include Sanford::ServiceHandler
|
78
78
|
|
79
|
-
|
79
|
+
before_run do
|
80
80
|
halt 401, :message => "Not authorized"
|
81
81
|
end
|
82
82
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'sanford-protocol/
|
1
|
+
require 'sanford-protocol/fake_socket'
|
2
2
|
|
3
3
|
class SimpleClient
|
4
4
|
|
@@ -56,7 +56,7 @@ class SimpleClient
|
|
56
56
|
protected
|
57
57
|
|
58
58
|
def call_using_fake_socket(method, *args)
|
59
|
-
self.call(Sanford::Protocol::
|
59
|
+
self.call(Sanford::Protocol::FakeSocket.send(method, *args).in)
|
60
60
|
end
|
61
61
|
|
62
62
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'assert'
|
2
|
-
require 'sanford-protocol/
|
2
|
+
require 'sanford-protocol/fake_socket'
|
3
3
|
|
4
4
|
# These tests are intended as a high level test against Sanford's server. They
|
5
5
|
# use fake and real connections to test how Sanford behaves.
|
@@ -197,7 +197,7 @@ class RequestHandlingTests < Assert::Context
|
|
197
197
|
:keep_alive => true
|
198
198
|
})
|
199
199
|
@server.on_run
|
200
|
-
@socket = Sanford::Protocol::
|
200
|
+
@socket = Sanford::Protocol::FakeSocket.new
|
201
201
|
@fake_connection = FakeProtocolConnection.new(@socket)
|
202
202
|
Sanford::Protocol::Connection.stubs(:new).with(@socket).returns(@fake_connection)
|
203
203
|
end
|