rubarb 0.2.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.
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'rubarb/id'
3
+
4
+ include Rubarb
5
+
6
+ describe Id do
7
+
8
+ before(:each) do
9
+ @id = Id.new
10
+ end
11
+
12
+ it "starts generator at 00000001" do
13
+ @id.next.should == "00000001"
14
+ end
15
+
16
+ it "increments counter by 1 when next is called" do
17
+ @id.next
18
+ @id.next.should == "00000002"
19
+ end
20
+
21
+ it "resets counter to one if id is 99999999" do
22
+ @id.instance_eval{ @id = 99999999 }
23
+ @id.next
24
+ @id.next.should == "00000001"
25
+ end
26
+ end
@@ -0,0 +1,79 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ require "rubarb/incoming_connection"
4
+ require "rubarb/remote_call"
5
+ require "rubarb/default"
6
+
7
+ describe Rubarb::IncomingConnection do
8
+ include Rubarb::RemoteCall
9
+ include Rubarb::IncomingConnection
10
+ attr_reader :api
11
+
12
+ class TestApi
13
+ attr_accessor :dodo
14
+ def amethod(responder, dodo)
15
+ @dodo = dodo
16
+ end
17
+ def ==(rhs)
18
+ end
19
+ end
20
+
21
+ before(:each) do
22
+ @api = TestApi.new
23
+ @insecure_methods = Rubarb::Default::INSECURE_METHODS
24
+ end
25
+
26
+ it "should receive message" do
27
+ receive_message(marshal_call("00000001", :amethod, "goo"))
28
+ @api.dodo.should == "goo"
29
+ end
30
+
31
+ it "should receive reply with exception when a non-existent method is called" do
32
+ should_receive(:reply).with do |id, exception|
33
+ id.should == "0"
34
+ exception.message.include?("undefined method").should == true
35
+ end
36
+ receive_message(marshal_call("00000001", :not_a_method, "foo"))
37
+ @api.should_not_receive(:send)
38
+ end
39
+
40
+ def blocks_method_in_receive_message(method)
41
+ @method = method
42
+ should_receive(:reply).with do |id, exception|
43
+ id.should == "0"
44
+ exception.message.should == "Remote client attempts to call method #{@method}, but was denied."
45
+ end
46
+ receive_message(marshal_call("00000001", method, "foo"))
47
+ @api.should_not_receive(:send)
48
+ end
49
+
50
+ it "blocks :== in receive_message" do
51
+ blocks_method_in_receive_message(:==)
52
+ end
53
+
54
+ it "blocks any insecure method in receive_message" do
55
+ Rubarb::Default::INSECURE_METHODS.each do |method|
56
+ blocks_method_in_receive_message(method)
57
+ end
58
+ end
59
+
60
+ it "receives message with id, method, and *args" do
61
+ message = marshal_call("00000001", :amethod, "foo")
62
+ receive_message(message)
63
+ @api.dodo.should == "foo"
64
+ end
65
+
66
+ it "replies message with id and args" do
67
+ message = marshal_call("00000001", :amethod, "foo")
68
+ receive_message(message)
69
+ self.should_receive(:send_message).with(marshal_call(["00000001", "result"]))
70
+ reply("00000001", "result")
71
+ end
72
+
73
+ it "replies message with id 00000002 and args" do
74
+ message = marshal_call("00000002", :amethod, "foo")
75
+ receive_message(message)
76
+ self.should_receive(:send_message).with(marshal_call(["00000002", "result"]))
77
+ reply("00000002", "result")
78
+ end
79
+ end
@@ -0,0 +1,174 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ require 'rubarb/server'
4
+ require 'rubarb/connection'
5
+
6
+ describe "Server to Client communication and response" do
7
+
8
+ class TestClientApi
9
+ def name(responder)
10
+ responder.reply("Doug")
11
+ end
12
+ end
13
+
14
+ before(:each) do
15
+ @reactor = start_reactor
16
+ @server_api = mock("server")
17
+ @client_api = TestClientApi.new
18
+
19
+ @server = Rubarb::Server.new("127.0.0.1", 9441, @server_api)
20
+ @connection = Rubarb::Connection.new("127.0.0.1", 9441, @client_api)
21
+ end
22
+
23
+ after(:each) do
24
+ stop_reactor(@reactor)
25
+ end
26
+
27
+ it "should communicate with the client" do
28
+ @callback_called = false
29
+
30
+ @server.start do |new_client|
31
+ new_client.name do|result|
32
+ result.should == "Doug"
33
+ @callback_called = true
34
+ end
35
+ end
36
+
37
+ @connection.start
38
+
39
+ wait_for {@callback_called}
40
+
41
+ end
42
+
43
+ end
44
+
45
+ describe "Client to Server communication and response" do
46
+ class TestReply
47
+ attr_reader :message
48
+
49
+ def initialize(name)
50
+ @message = "How are you #{name}, my friend?"
51
+ end
52
+ end
53
+
54
+ class TestServerApi
55
+ attr_reader :hi_called
56
+ def hi(responder)
57
+ responder.reply("how are you?")
58
+ @hi_called = true
59
+ end
60
+
61
+ def hello(responder, name)
62
+ responder.reply("how are you #{name}?")
63
+ end
64
+
65
+ def hello_friend(responder, name)
66
+ responder.reply(TestReply.new(name))
67
+ end
68
+
69
+ attr_reader :conn_id
70
+ def save_id(responder)
71
+ @conn_id = responder.conn_id
72
+ responder.reply(nil)
73
+ end
74
+ end
75
+
76
+ before(:each) do
77
+ @reactor = start_reactor
78
+ @server_api = TestServerApi.new
79
+ @client_api = mock("client")
80
+
81
+ @server = Rubarb::Server.new("127.0.0.1", 9441, @server_api)
82
+ @connection = Rubarb::Connection.new("127.0.0.1", 9441, @client_api)
83
+ end
84
+
85
+ after(:each) do
86
+ stop_reactor(@reactor)
87
+ end
88
+
89
+ it "without a callback" do
90
+ @server.start
91
+
92
+ @connection.start do
93
+ @connection.hi
94
+ end
95
+
96
+ wait_for {@server_api.hi_called}
97
+ end
98
+
99
+ it "without parameters" do
100
+ @callback_called = false
101
+ @server.start
102
+
103
+ @connection.start do
104
+ @connection.hi do |response|
105
+ response.should == "how are you?"
106
+ @callback_called = true
107
+ end
108
+ end
109
+
110
+ wait_for {@callback_called}
111
+ end
112
+
113
+ it "with parameters" do
114
+ @callback_called = false
115
+ @server.start
116
+ @connection.start do
117
+ @connection.hello("Doug") do |response|
118
+ @callback_called = true
119
+ response.should == "how are you Doug?"
120
+ end
121
+ end
122
+ wait_for {@callback_called}
123
+ end
124
+
125
+ it "with complex response" do
126
+ @callback_called = false
127
+ @server.start
128
+ @connection.start do
129
+ @connection.hello_friend("Doug") do |response|
130
+ @callback_called = true
131
+ response.message.should == "How are you Doug, my friend?"
132
+ end
133
+ end
134
+
135
+ wait_for {@callback_called}
136
+ end
137
+
138
+ it "can get connection id on connection" do
139
+ @callback_called = false
140
+ @new_connection_id = nil
141
+ @server.start do |new_connection|
142
+ @new_connection_id = new_connection.conn_id
143
+ end
144
+
145
+ @connection.start do
146
+ @connection.save_id do |response|
147
+ @callback_called = true
148
+ end
149
+ end
150
+
151
+ wait_for {@callback_called}
152
+ @server_api.conn_id.should == @new_connection_id
153
+ end
154
+
155
+ it "should close from server side" do
156
+ @server_side_client_proxy = nil
157
+ @server.start do |new_connection|
158
+ @server_side_client_proxy = new_connection
159
+ end
160
+
161
+ @connection.errback do
162
+ @client_side_closed = true
163
+ end
164
+ @connection.start
165
+
166
+ wait_for {!@server_side_client_proxy.nil?}
167
+ @server_side_client_proxy.stop
168
+
169
+ wait_for {@client_side_closed}
170
+ @client_side_closed.should == true
171
+
172
+ end
173
+
174
+ end
@@ -0,0 +1,103 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ require "rubarb/outgoing_connection"
4
+ require "rubarb/remote_call"
5
+
6
+ describe Rubarb::OutgoingConnection do
7
+ include Rubarb::RemoteCall
8
+ include Rubarb::OutgoingConnection
9
+
10
+ before(:each) do
11
+ @callback = {}
12
+ set_id("00000001")
13
+ end
14
+
15
+ def set_id(id)
16
+ id_generator = mock("id")
17
+ id_generator.stub!(:next).and_return(id)
18
+ @msg_id_generator = id_generator
19
+ end
20
+
21
+ it "sets callback" do
22
+ block = Proc.new { puts "Hello" }
23
+ self.should_receive(:send_message)
24
+ remote_call(:amethod, "asdf", &block)
25
+ @callback["00000001"].should == block
26
+ end
27
+
28
+ it "executes callback block when receive_message is called" do
29
+ block = Proc.new do |v|
30
+ @value = v
31
+ end
32
+ should_receive(:send_message)
33
+ remote_call(:amethod, "asdf", &block)
34
+ receive_message(marshal_call("00000001", "value"))
35
+ @value.should == "value"
36
+ end
37
+
38
+ it "does not execute callback block when receive_message is called with an exception" do
39
+ block = Proc.new { puts "Hello" }
40
+ should_receive(:send_message)
41
+ remote_call(:amethod, "asdf", &block)
42
+ should_receive(:call_errbacks)
43
+ @callback.should_not_receive(:call)
44
+ receive_message(marshal_call("00000001", Exception.new))
45
+ end
46
+
47
+ it "saves error message when receive_message is called with an exception" do
48
+ exception = Exception.new("Hello")
49
+ error = nil
50
+ @errbacks = [Proc.new { |e| error = e }]
51
+ block = Proc.new { puts "Hello" }
52
+
53
+ should_receive(:send_message)
54
+ remote_call(:amethod, "asdf", &block)
55
+ stub!(:call_errbacks).and_return(@errbacks.first.call(exception))
56
+ @callback.stub!(:call)
57
+
58
+ receive_message(marshal_call("00000001", exception))
59
+
60
+ error.class.should == Exception
61
+ error.message.should == (exception.message)
62
+ end
63
+
64
+ it "has a message id argument for marshal_call" do
65
+ block = Proc.new { puts "Hello" }
66
+ should_receive(:marshal_call).with("00000001", :amethod, "asdf")
67
+ self.should_receive(:send_message)
68
+ remote_call(:amethod, "asdf", &block)
69
+ end
70
+
71
+ it "generates a message id" do
72
+ set_id("00000002")
73
+ block = Proc.new { puts "Hello" }
74
+ should_receive(:marshal_call).with("00000002", :amethod, "asdf")
75
+ should_receive(:send_message)
76
+ remote_call(:amethod, "asdf", &block)
77
+ end
78
+
79
+ it "pushes callback block to callback hash with id as key" do
80
+ @callback = {}
81
+ set_id("00000001")
82
+ block = Proc.new { puts "Hello" }
83
+ stub!(:send_message)
84
+ remote_call(:amethod, "asdf", &block)
85
+ @callback["00000001"].should == block
86
+ end
87
+
88
+ it "calls the corresponding block with given id" do
89
+ block = mock("block")
90
+ block.should_receive(:call).with("asdf")
91
+ @callback = { "00000002" => block }
92
+ receive_message(marshal_call("00000002", "asdf"))
93
+ end
94
+
95
+ it "removes callback from hash after call" do
96
+ block = mock("block")
97
+ block.should_receive(:call).with("asdf")
98
+ @callback = { "00000002" => block }
99
+ receive_message(marshal_call("00000002", "asdf"))
100
+ @callback.should have(0).items
101
+ end
102
+
103
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ require 'rubarb/remote_call'
4
+ describe Rubarb::RemoteCall do
5
+ include Rubarb::RemoteCall
6
+
7
+ it "should marshal a call" do
8
+ identity_test(:foo, "barr", "none")
9
+ end
10
+
11
+ it "should marshal with no args" do
12
+ identity_test(:food)
13
+ end
14
+
15
+ it "should work with multiple return values" do
16
+ serialized = marshal_call(:eat, "potatos", "carrots")
17
+ recovered_method, arg1, arg2 = unmarshal_call(serialized)
18
+ recovered_method.should == :eat
19
+ arg1.should == "potatos"
20
+ arg2.should == "carrots"
21
+ end
22
+
23
+ class Wine
24
+ attr_accessor :age, :content
25
+ def initialize(age, content)
26
+ @age = age
27
+ @content = content
28
+ end
29
+
30
+ def ==(other)
31
+ return false unless self.age == other.age
32
+ return false unless self.content == other.content
33
+ return true
34
+ end
35
+ end
36
+
37
+ it "should handle complexy objects" do
38
+ identity_test(:make_grapes, Wine.new(15, 0.15), "grapes")
39
+ end
40
+
41
+ def identity_test(method, *args)
42
+ serialized = marshal_call(method, *args)
43
+ recovered_method, *recovered_args = unmarshal_call(serialized)
44
+ recovered_method.should == method
45
+ recovered_args.should == args
46
+ end
47
+
48
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require "rubarb/responder"
3
+ require "rubarb/incoming_connection"
4
+ require "rubarb/server"
5
+
6
+ include Rubarb
7
+
8
+ class MockHandler
9
+ include Listener
10
+ include IncomingConnection
11
+ end
12
+
13
+ describe Responder do
14
+ before(:each) do
15
+ @responder = Responder.new(MockHandler.new, "00000001")
16
+ end
17
+
18
+ it "sets id on initialize" do
19
+ @responder.message_id.should == "00000001"
20
+ end
21
+
22
+ it "sets handler on initialize" do
23
+ @responder.handler.class.should == MockHandler
24
+ end
25
+
26
+ it "calls handler#reply with stored message_id" do
27
+ @responder.handler.should_receive(:reply).with("00000001", "Hello Doug")
28
+ @responder.reply("Hello Doug")
29
+ end
30
+
31
+ it "calls handler's conn_id" do
32
+ @responder.handler.should_receive(:conn_id)
33
+ @responder.conn_id
34
+ end
35
+ end