rjr 0.18.2 → 0.19.1
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 +4 -4
- data/Rakefile +2 -0
- data/bin/rjr-client +16 -9
- data/bin/rjr-server +2 -1
- data/examples/client.rb +21 -19
- data/examples/server.rb +1 -1
- data/examples/structured_server.rb +1 -0
- data/examples/tcp.rb +1 -0
- data/lib/rjr/common.rb +1 -226
- data/lib/rjr/core_ext.rb +63 -0
- data/lib/rjr/dispatcher.rb +75 -219
- data/lib/rjr/messages.rb +8 -0
- data/lib/rjr/messages/compressed.rb +264 -0
- data/lib/rjr/messages/notification.rb +95 -0
- data/lib/rjr/messages/request.rb +99 -0
- data/lib/rjr/messages/response.rb +128 -0
- data/lib/rjr/node.rb +100 -97
- data/lib/rjr/node_callback.rb +43 -0
- data/lib/rjr/nodes/amqp.rb +12 -11
- data/lib/rjr/nodes/easy.rb +4 -4
- data/lib/rjr/nodes/local.rb +13 -12
- data/lib/rjr/nodes/multi.rb +1 -1
- data/lib/rjr/nodes/tcp.rb +15 -13
- data/lib/rjr/nodes/template.rb +4 -4
- data/lib/rjr/nodes/unix.rb +15 -13
- data/lib/rjr/nodes/web.rb +15 -14
- data/lib/rjr/nodes/ws.rb +12 -11
- data/lib/rjr/request.rb +128 -0
- data/lib/rjr/result.rb +75 -0
- data/lib/rjr/util/args.rb +145 -0
- data/lib/rjr/{em_adapter.rb → util/em_adapter.rb} +0 -0
- data/lib/rjr/util/handles_methods.rb +115 -0
- data/lib/rjr/util/has_messages.rb +50 -0
- data/lib/rjr/{inspect.rb → util/inspect.rb} +1 -1
- data/lib/rjr/util/json_parser.rb +101 -0
- data/lib/rjr/util/logger.rb +128 -0
- data/lib/rjr/{thread_pool.rb → util/thread_pool.rb} +2 -0
- data/lib/rjr/version.rb +1 -1
- data/site/jrw.js +1 -1
- data/specs/args_spec.rb +144 -0
- data/specs/dispatcher_spec.rb +399 -211
- data/specs/em_adapter_spec.rb +31 -18
- data/specs/handles_methods_spec.rb +154 -0
- data/specs/has_messages_spec.rb +54 -0
- data/specs/inspect_spec.rb +1 -1
- data/specs/json_parser_spec.rb +169 -0
- data/specs/messages/notification_spec.rb +59 -0
- data/specs/messages/request_spec.rb +66 -0
- data/specs/messages/response_spec.rb +94 -0
- data/specs/node_callbacks_spec.rb +47 -0
- data/specs/node_spec.rb +465 -56
- data/specs/request_spec.rb +147 -0
- data/specs/result_spec.rb +144 -0
- data/specs/thread_pool_spec.rb +1 -1
- metadata +41 -11
- data/lib/rjr/errors.rb +0 -23
- data/lib/rjr/message.rb +0 -351
- data/lib/rjr/semaphore.rb +0 -58
- data/specs/message_spec.rb +0 -229
data/specs/em_adapter_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'thread'
|
2
|
-
require 'rjr/em_adapter'
|
2
|
+
require 'rjr/util/em_adapter'
|
3
3
|
|
4
4
|
module RJR
|
5
5
|
describe EMAdapter do
|
@@ -11,30 +11,43 @@ module RJR
|
|
11
11
|
@em.halt.join
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
describe "#start" do
|
15
|
+
it "should start the reactor" do
|
16
|
+
@em.start
|
17
|
+
@em.reactor_running?.should be_true
|
18
|
+
['sleep', 'run'].should include(@em.reactor_thread.status)
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
it "should only start the reactor once" do
|
22
|
+
@em.start
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
ot = @em.reactor_thread
|
25
|
+
@em.start
|
26
|
+
@em.reactor_thread.should == ot
|
27
|
+
end
|
26
28
|
end
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
+
describe "#stop" do
|
31
|
+
it "should halt the reactor" do
|
32
|
+
@em.start
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
34
|
+
@em.halt
|
35
|
+
@em.join
|
36
|
+
@em.reactor_running?.should be_false
|
37
|
+
@em.reactor_thread.should be_nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#join" do
|
42
|
+
it "joins reactor thread" do
|
43
|
+
th = Object.new
|
44
|
+
th.should_receive(:join).twice # XXX also called in after block above
|
45
|
+
@em.instance_variable_set(:@reactor_thread, th)
|
46
|
+
@em.join
|
47
|
+
end
|
35
48
|
end
|
36
49
|
|
37
|
-
it "should
|
50
|
+
it "should forward all messages to eventmachine" do
|
38
51
|
@em.start
|
39
52
|
|
40
53
|
invoked = false
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'rjr/util/handles_methods'
|
2
|
+
require 'rjr/dispatcher'
|
3
|
+
|
4
|
+
module RJR
|
5
|
+
class HandlesMethodsTest
|
6
|
+
include HandlesMethods
|
7
|
+
|
8
|
+
jr_method :method1
|
9
|
+
jr_method :method2, :method3
|
10
|
+
|
11
|
+
jr_method :method4, :custom
|
12
|
+
jr_method :method5, :method6, :custom
|
13
|
+
|
14
|
+
def custom
|
15
|
+
@foo
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe HandlesMethods do
|
20
|
+
before(:each) do
|
21
|
+
@handlers = HandlesMethodsTest.jr_handlers
|
22
|
+
HandlesMethodsTest.jr_handlers = Hash[@handlers] if !!@handlers
|
23
|
+
end
|
24
|
+
|
25
|
+
after(:each) do
|
26
|
+
HandlesMethodsTest.jr_handlers = @handlers
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#extract_handler_method" do
|
30
|
+
context "args.last is a class method" do
|
31
|
+
it "returns args.last" do
|
32
|
+
result = HandlesMethodsTest.extract_handler_method([:method1, :custom])
|
33
|
+
result[0].should == :custom
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns argument list with args.last removed" do
|
37
|
+
result = HandlesMethodsTest.extract_handler_method([:method1, :custom])
|
38
|
+
result[1].should == [:method1]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "args.last is not a class method" do
|
43
|
+
it "returns :handle" do
|
44
|
+
result = HandlesMethodsTest.extract_handler_method([:method1])
|
45
|
+
result[0].should == :handle
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns argument list" do
|
49
|
+
result = HandlesMethodsTest.extract_handler_method([:method1])
|
50
|
+
result[1].should == [:method1]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#has_handler_for?" do
|
56
|
+
before(:each) do
|
57
|
+
HandlesMethodsTest.jr_handlers = {:handle => proc{}}
|
58
|
+
end
|
59
|
+
|
60
|
+
context "handler exists" do
|
61
|
+
it "returns true" do
|
62
|
+
HandlesMethodsTest.has_handler_for?(:handle).should be_true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "handler does not exist" do
|
67
|
+
it "returns false" do
|
68
|
+
HandlesMethodsTest.has_handler_for?(:foobar).should be_false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#handler_for" do
|
74
|
+
before(:each) do
|
75
|
+
HandlesMethodsTest.jr_handlers = {:custom => 'foobar'}
|
76
|
+
end
|
77
|
+
|
78
|
+
it "returns handler" do
|
79
|
+
HandlesMethodsTest.handler_for(:custom).should == 'foobar'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#create_handler_for" do
|
84
|
+
it "store handler proc in handler registry" do
|
85
|
+
HandlesMethodsTest.create_handler_for(:foobar)
|
86
|
+
HandlesMethodsTest.jr_handlers[:foobar].should be_an_instance_of(Proc)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "returns handler proc" do
|
90
|
+
HandlesMethodsTest.create_handler_for(:foobar).should ==
|
91
|
+
HandlesMethodsTest.jr_handlers[:foobar]
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "handler" do
|
95
|
+
it "instantiates handler class" do
|
96
|
+
HandlesMethodsTest.should_receive(:new).and_call_original
|
97
|
+
HandlesMethodsTest.create_handler_for(:custom).call
|
98
|
+
end
|
99
|
+
|
100
|
+
it "sets local instance_variables on instance" do
|
101
|
+
@foo = 'bar'
|
102
|
+
inst = HandlesMethodsTest.new
|
103
|
+
HandlesMethodsTest.should_receive(:new).and_return(inst)
|
104
|
+
instance_exec &HandlesMethodsTest.create_handler_for(:custom)
|
105
|
+
inst.instance_variable_get(:@foo).should == 'bar'
|
106
|
+
end
|
107
|
+
|
108
|
+
it "invokes handler method with args" do
|
109
|
+
inst = HandlesMethodsTest.new
|
110
|
+
HandlesMethodsTest.should_receive(:new).twice.and_return(inst)
|
111
|
+
inst.should_receive(:custom).twice.with(42)
|
112
|
+
HandlesMethodsTest.create_handler_for(:custom).call 42
|
113
|
+
HandlesMethodsTest.jr_handlers[:custom].call 42
|
114
|
+
end
|
115
|
+
|
116
|
+
it "returns handler return value" do
|
117
|
+
@foo = 'bar'
|
118
|
+
instance_exec(&HandlesMethodsTest.create_handler_for(:custom)).should == @foo
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "#jr_method" do
|
124
|
+
it "registers json-rpc methods for later evaluation" do
|
125
|
+
args = HandlesMethodsTest.instance_variable_get(:@jr_method_args)
|
126
|
+
args.should == [[:method1], [:method2, :method3],
|
127
|
+
[:method4, :custom], [:method5, :method6, :custom]]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#dispatch_to" do
|
132
|
+
it "registers json-rpc method with new handler" do
|
133
|
+
d = Dispatcher.new
|
134
|
+
HandlesMethodsTest.jr_handlers.should be_nil
|
135
|
+
HandlesMethodsTest.dispatch_to(d)
|
136
|
+
HandlesMethodsTest.jr_handlers.size.should == 2
|
137
|
+
HandlesMethodsTest.jr_handlers[:handle].should be_an_instance_of(Proc)
|
138
|
+
HandlesMethodsTest.jr_handlers[:custom].should be_an_instance_of(Proc)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "registers local json rpc methods with dispatcher" do
|
142
|
+
d = Dispatcher.new
|
143
|
+
HandlesMethodsTest.dispatch_to(d)
|
144
|
+
|
145
|
+
d.handler_for('method1').should == HandlesMethodsTest.jr_handlers[:handle]
|
146
|
+
d.handler_for('method2').should == HandlesMethodsTest.jr_handlers[:handle]
|
147
|
+
d.handler_for('method3').should == HandlesMethodsTest.jr_handlers[:handle]
|
148
|
+
d.handler_for('method4').should == HandlesMethodsTest.jr_handlers[:custom]
|
149
|
+
d.handler_for('method5').should == HandlesMethodsTest.jr_handlers[:custom]
|
150
|
+
d.handler_for('method6').should == HandlesMethodsTest.jr_handlers[:custom]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rjr/util/has_messages'
|
2
|
+
|
3
|
+
module RJR
|
4
|
+
class HasMessagesTest
|
5
|
+
include HasMessages
|
6
|
+
end
|
7
|
+
|
8
|
+
describe HasMessages do
|
9
|
+
after(:each) do
|
10
|
+
HasMessagesTest.clear_messages
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#define_message" do
|
14
|
+
it "defines new message" do
|
15
|
+
HasMessagesTest.new.define_message('foobar') { 'barfoo' }
|
16
|
+
HasMessagesTest.message('foobar').should == 'barfoo'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "::message" do
|
21
|
+
it "sets/gets message" do
|
22
|
+
HasMessagesTest.message('foobar', 'barfoo')
|
23
|
+
HasMessagesTest.message('foobar').should == 'barfoo'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "::clear_messages" do
|
28
|
+
it "clears messages" do
|
29
|
+
HasMessagesTest.message('foobar', 'barfoo')
|
30
|
+
HasMessagesTest.clear_messages
|
31
|
+
HasMessagesTest.message('foobar').should be_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#rand_message" do
|
36
|
+
it "returns random message" do
|
37
|
+
msg1 = {}
|
38
|
+
msg2 = {}
|
39
|
+
HasMessagesTest.message('foobar', msg1)
|
40
|
+
HasMessagesTest.message('barfoo', msg2)
|
41
|
+
HasMessagesTest.should_receive(:rand).and_return(1)
|
42
|
+
HasMessagesTest.rand_message.should == msg2
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns random message matching specified transport" do
|
46
|
+
tcpm = {:transports => ['tcp']}
|
47
|
+
amqpm = {:transports => ['amqp']}
|
48
|
+
HasMessagesTest.message('foobar', tcpm)
|
49
|
+
HasMessagesTest.message('barfoo', amqpm)
|
50
|
+
HasMessagesTest.rand_message('tcp').should == tcpm
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end # describe HasMessages
|
54
|
+
end # module RJR
|
data/specs/inspect_spec.rb
CHANGED
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'rjr/util/json_parser'
|
2
|
+
|
3
|
+
module RJR
|
4
|
+
describe JSONParser do
|
5
|
+
describe "#extract_json_from" do
|
6
|
+
it "returns first json object from string" do
|
7
|
+
json = '{"foo":"bar"}'
|
8
|
+
JSONParser.extract_json_from(json).should == [json, '']
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns remaining portion of string" do
|
12
|
+
json = '{"foo":"bar"}'
|
13
|
+
complete = "#{json}remaining"
|
14
|
+
JSONParser.extract_json_from(complete).should == [json, 'remaining']
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#invalid_json_class?" do
|
19
|
+
before(:each) do
|
20
|
+
@orig_whitelist = Class.whitelist_json_classes
|
21
|
+
end
|
22
|
+
|
23
|
+
after(:each) do
|
24
|
+
Class.whitelist_json_classes = @orig_whitelist
|
25
|
+
end
|
26
|
+
|
27
|
+
context "json class whitelisting enabled" do
|
28
|
+
before(:each) do
|
29
|
+
Class.whitelist_json_classes = true
|
30
|
+
end
|
31
|
+
|
32
|
+
context "class not on permitted classes list" do
|
33
|
+
it "returns true" do
|
34
|
+
Class.should_receive(:permitted_json_classes).and_return([])
|
35
|
+
JSONParser.invalid_json_class?('foobar').should be_true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "class on permitted classes list" do
|
40
|
+
it "returns false" do
|
41
|
+
Class.should_receive(:permitted_json_classes).and_return(['foobar'])
|
42
|
+
JSONParser.invalid_json_class?('foobar').should be_false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "json class whitelisting not enabled" do
|
48
|
+
before(:each) do
|
49
|
+
Class.whitelist_json_classes = false
|
50
|
+
end
|
51
|
+
|
52
|
+
context "class not on ruby heirarchy" do
|
53
|
+
it "returns true" do
|
54
|
+
JSONParser.invalid_json_class?('Foobar').should be_true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "class on ruby heirarchy" do
|
59
|
+
it "returns false" do
|
60
|
+
JSONParser.invalid_json_class?('Integer').should be_false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#validate_json_hash" do
|
67
|
+
context "a hash key is the JSON.create_id and value is invalid class" do
|
68
|
+
it "raises argument error" do
|
69
|
+
hash = {JSON.create_id => 'foobar'}
|
70
|
+
JSONParser.should_receive(:invalid_json_class?).
|
71
|
+
with('foobar').and_return(true)
|
72
|
+
lambda{
|
73
|
+
JSONParser.validate_json_hash(hash)
|
74
|
+
}.should raise_error(ArgumentError)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "a value is an array" do
|
79
|
+
it "validates json array" do
|
80
|
+
arr = []
|
81
|
+
hash = {'foobar' => arr}
|
82
|
+
JSONParser.should_receive(:validate_json_array).with(arr)
|
83
|
+
JSONParser.validate_json_hash(hash)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "a value is a hash" do
|
88
|
+
it "validates json hash" do
|
89
|
+
inner = {}
|
90
|
+
hash = {'foobar' => inner}
|
91
|
+
JSONParser.should_receive(:validate_json_hash).with(hash).and_call_original
|
92
|
+
JSONParser.should_receive(:validate_json_hash).with(inner)
|
93
|
+
JSONParser.validate_json_hash(hash)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#validate_json_array" do
|
99
|
+
context "a value is an array" do
|
100
|
+
it "validates json array" do
|
101
|
+
inner = []
|
102
|
+
array = [inner]
|
103
|
+
JSONParser.should_receive(:validate_json_array).with(array).and_call_original
|
104
|
+
JSONParser.should_receive(:validate_json_array).with(inner)
|
105
|
+
JSONParser.validate_json_array(array)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "a value is a hash" do
|
110
|
+
it "validates json hash" do
|
111
|
+
inner = {}
|
112
|
+
array = [inner]
|
113
|
+
JSONParser.should_receive(:validate_json_hash).with(inner)
|
114
|
+
JSONParser.validate_json_array(array)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "#parse" do
|
120
|
+
before(:each) do
|
121
|
+
@json = '{"foo":"bar"}'
|
122
|
+
end
|
123
|
+
|
124
|
+
it "safely parses json" do
|
125
|
+
JSON.should_receive(:parse).
|
126
|
+
with(@json, :create_additions => false).and_call_original
|
127
|
+
JSON.should_receive(:parse).once
|
128
|
+
JSONParser.parse(@json)
|
129
|
+
end
|
130
|
+
|
131
|
+
context "json is an array" do
|
132
|
+
it "validates json array" do
|
133
|
+
arr = []
|
134
|
+
JSON.should_receive(:parse).and_return(arr)
|
135
|
+
JSON.should_receive(:parse).once
|
136
|
+
JSONParser.should_receive(:validate_json_array).with(arr)
|
137
|
+
JSONParser.parse(@json)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context "json is a hash" do
|
142
|
+
it "validates json hash" do
|
143
|
+
hash = {}
|
144
|
+
JSON.should_receive(:parse).and_return(hash)
|
145
|
+
JSON.should_receive(:parse).once
|
146
|
+
JSONParser.should_receive(:validate_json_hash).with(hash)
|
147
|
+
JSONParser.parse(@json)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context "json is not a array/hash" do
|
152
|
+
it "returns value" do
|
153
|
+
JSON.should_receive(:parse).and_return(42)
|
154
|
+
JSONParser.parse(@json).should == 42
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
it "parses json, creating classes" do
|
159
|
+
njs = {}
|
160
|
+
JSON.should_receive(:parse).
|
161
|
+
with(@json, :create_additions => false).and_call_original
|
162
|
+
JSON.should_receive(:parse).
|
163
|
+
with(@json, :create_additions => true).
|
164
|
+
and_return(njs)
|
165
|
+
JSONParser.parse(@json).should == njs
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end # describe JSONParser
|
169
|
+
end # module RJR
|