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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -0
  3. data/bin/rjr-client +16 -9
  4. data/bin/rjr-server +2 -1
  5. data/examples/client.rb +21 -19
  6. data/examples/server.rb +1 -1
  7. data/examples/structured_server.rb +1 -0
  8. data/examples/tcp.rb +1 -0
  9. data/lib/rjr/common.rb +1 -226
  10. data/lib/rjr/core_ext.rb +63 -0
  11. data/lib/rjr/dispatcher.rb +75 -219
  12. data/lib/rjr/messages.rb +8 -0
  13. data/lib/rjr/messages/compressed.rb +264 -0
  14. data/lib/rjr/messages/notification.rb +95 -0
  15. data/lib/rjr/messages/request.rb +99 -0
  16. data/lib/rjr/messages/response.rb +128 -0
  17. data/lib/rjr/node.rb +100 -97
  18. data/lib/rjr/node_callback.rb +43 -0
  19. data/lib/rjr/nodes/amqp.rb +12 -11
  20. data/lib/rjr/nodes/easy.rb +4 -4
  21. data/lib/rjr/nodes/local.rb +13 -12
  22. data/lib/rjr/nodes/multi.rb +1 -1
  23. data/lib/rjr/nodes/tcp.rb +15 -13
  24. data/lib/rjr/nodes/template.rb +4 -4
  25. data/lib/rjr/nodes/unix.rb +15 -13
  26. data/lib/rjr/nodes/web.rb +15 -14
  27. data/lib/rjr/nodes/ws.rb +12 -11
  28. data/lib/rjr/request.rb +128 -0
  29. data/lib/rjr/result.rb +75 -0
  30. data/lib/rjr/util/args.rb +145 -0
  31. data/lib/rjr/{em_adapter.rb → util/em_adapter.rb} +0 -0
  32. data/lib/rjr/util/handles_methods.rb +115 -0
  33. data/lib/rjr/util/has_messages.rb +50 -0
  34. data/lib/rjr/{inspect.rb → util/inspect.rb} +1 -1
  35. data/lib/rjr/util/json_parser.rb +101 -0
  36. data/lib/rjr/util/logger.rb +128 -0
  37. data/lib/rjr/{thread_pool.rb → util/thread_pool.rb} +2 -0
  38. data/lib/rjr/version.rb +1 -1
  39. data/site/jrw.js +1 -1
  40. data/specs/args_spec.rb +144 -0
  41. data/specs/dispatcher_spec.rb +399 -211
  42. data/specs/em_adapter_spec.rb +31 -18
  43. data/specs/handles_methods_spec.rb +154 -0
  44. data/specs/has_messages_spec.rb +54 -0
  45. data/specs/inspect_spec.rb +1 -1
  46. data/specs/json_parser_spec.rb +169 -0
  47. data/specs/messages/notification_spec.rb +59 -0
  48. data/specs/messages/request_spec.rb +66 -0
  49. data/specs/messages/response_spec.rb +94 -0
  50. data/specs/node_callbacks_spec.rb +47 -0
  51. data/specs/node_spec.rb +465 -56
  52. data/specs/request_spec.rb +147 -0
  53. data/specs/result_spec.rb +144 -0
  54. data/specs/thread_pool_spec.rb +1 -1
  55. metadata +41 -11
  56. data/lib/rjr/errors.rb +0 -23
  57. data/lib/rjr/message.rb +0 -351
  58. data/lib/rjr/semaphore.rb +0 -58
  59. data/specs/message_spec.rb +0 -229
@@ -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
- it "should start the reactor" do
15
- @em.start
16
- @em.reactor_running?.should be_true
17
- ['sleep', 'run'].should include(@em.reactor_thread.status)
18
- end
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
- it "should only start the reactor once" do
21
- @em.start
21
+ it "should only start the reactor once" do
22
+ @em.start
22
23
 
23
- ot = @em.reactor_thread
24
- @em.start
25
- @em.reactor_thread.should == ot
24
+ ot = @em.reactor_thread
25
+ @em.start
26
+ @em.reactor_thread.should == ot
27
+ end
26
28
  end
27
29
 
28
- it "should halt the reactor" do
29
- @em.start
30
+ describe "#stop" do
31
+ it "should halt the reactor" do
32
+ @em.start
30
33
 
31
- @em.halt
32
- @em.join
33
- @em.reactor_running?.should be_false
34
- @em.reactor_thread.should be_nil
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 dispatch all requests to eventmachine" do
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
@@ -1,5 +1,5 @@
1
+ require 'rjr/util/inspect'
1
2
  require 'rjr/dispatcher'
2
- require 'rjr/inspect'
3
3
 
4
4
  describe "#select_stats" do
5
5
  before(:each) do
@@ -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