rjr 0.18.2 → 0.19.1

Sign up to get free protection for your applications and to get access to all the features.
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