rjr 0.19.1 → 0.19.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,31 +16,64 @@ class JSONParser
16
16
  # Returns the message and remaining portion of the data string,
17
17
  # if message is found, else nil
18
18
  #
19
- # TODO efficiency can probably be optimized in the case closing '}'
20
- # hasn't arrived yet
21
- #
22
- # FIXME if uneven brackets appears in string data (such as in params)
23
- # this will break, detect when in string and ignore in counts
19
+ # TODO efficiency can probably be optimized in the case of multiple calls
20
+ # to this when the case closing '}' hasn't arrived yet
24
21
  def self.extract_json_from(data)
25
22
  return nil if data.nil? || data.empty?
23
+ # start at beginning of data, find opening quote
26
24
  start = 0
27
25
  start += 1 until start == data.length || data[start].chr == '{'
28
- on = mi = 0
26
+
27
+ escaped = false
28
+ in_quotes = false
29
+ quote_char = nil
30
+ open_brackets = mark = 0
31
+
32
+ # iterate over data stream
29
33
  start.upto(data.length - 1).each { |i|
30
- if data[i].chr == '{'
31
- on += 1
32
- elsif data[i].chr == '}'
33
- on -= 1
34
+
35
+ # toggle escaped flag in case of '\' or '\\'
36
+ if in_quotes && data[i].chr == '\\'
37
+ escaped = !escaped
38
+
39
+ else
40
+ # ignore escaped chars
41
+ if !escaped
42
+
43
+ # ignore brackets in quotes
44
+ if !in_quotes
45
+ if data[i].chr == '{'
46
+ open_brackets += 1
47
+
48
+ elsif data[i].chr == '}'
49
+ open_brackets -= 1
50
+ end
51
+ end
52
+
53
+ # track opening quote
54
+ if data[i].chr == "'" || data[i].chr == '"'
55
+ if !in_quotes
56
+ in_quotes = true
57
+ quote_char = data[i]
58
+ elsif quote_char == data[i]
59
+ in_quotes = false
60
+ end
61
+ end
62
+ end
63
+
64
+ escaped = false
34
65
  end
35
66
 
36
- if on == 0
37
- mi = i
67
+
68
+ # finish at end of one json message
69
+ if open_brackets == 0
70
+ mark = i
38
71
  break
39
72
  end
40
73
  }
41
74
 
42
- return nil if mi == 0
43
- return data[start..mi], data[(mi+1)..-1]
75
+ return nil if mark == 0
76
+ return data[start..mark], data[(mark+1)..-1]
44
77
  end
45
78
 
46
79
  # Return bool indicating if json class is invalid in context
@@ -52,15 +52,17 @@ class Logger
52
52
  def self.method_missing(method_id, *args)
53
53
  _instantiate_logger
54
54
  @logger_mutex.synchronize {
55
+ # TODO option to indent & prepend configurable prefix to extra log lines after first entry
55
56
  args = args.first if args.first.is_a?(Array)
57
+ shouldnt_log = args.any? { |a| @filters.any? { |f| !f.call a } }
56
58
  args.each { |a|
57
59
  # run highlights / filters against output before
58
60
  # sending formatted output to logger
59
61
  # TODO allow user to customize highlight mechanism/text
60
62
  na = @highlights.any? { |h| h.call a } ?
61
63
  "\e[1m\e[31m#{a}\e[0m\e[0m" : a
62
- @logger.send(method_id, na) if @filters.all? { |f| f.call a }
63
- }
64
+ @logger.send(method_id, na)
65
+ } unless shouldnt_log
64
66
  }
65
67
  end
66
68
 
data/lib/rjr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RJR
2
- VERSION = '0.19.1'
2
+ VERSION = '0.19.2'
3
3
  end
data/specs/args_spec.rb CHANGED
@@ -115,14 +115,14 @@ module RJR
115
115
  context "arguments includes tag" do
116
116
  it "returns true" do
117
117
  a = Arguments.new :args => ['with_id', 42]
118
- a.specifies?('with_id').should be_true
118
+ a.specifies?('with_id').should be_truthy
119
119
  end
120
120
  end
121
121
 
122
122
  context "arguments does not include tag" do
123
123
  it "returns false" do
124
124
  a = Arguments.new :args => ['with_id', 42]
125
- a.specifies?('with_name').should be_false
125
+ a.specifies?('with_name').should be_falsey
126
126
  end
127
127
  end
128
128
  end
@@ -167,14 +167,14 @@ module RJR
167
167
  d = Dispatcher.new
168
168
  cb = proc {}
169
169
  d.handle 'foobar', cb
170
- d.handles?('foobar').should be_true
170
+ d.handles?('foobar').should be_truthy
171
171
  end
172
172
  end
173
173
 
174
174
  context "dispatcher does not have handler" do
175
175
  it "returns false" do
176
176
  d = Dispatcher.new
177
- d.handles?('foobar').should be_false
177
+ d.handles?('foobar').should be_falsey
178
178
  end
179
179
  end
180
180
  end
@@ -245,14 +245,14 @@ module RJR
245
245
  d.dispatch :rjr_method => 'foobar'
246
246
  end
247
247
 
248
- it "extends request w/ method environment" do
248
+ it "sets request environment" do
249
249
  d = Dispatcher.new
250
250
  d.env 'foobar', 'fooenv'
251
251
  d.handle 'foobar', proc {}
252
252
 
253
253
  r = Request.new
254
254
  Request.should_receive(:new).and_return(r)
255
- r.should_receive(:extend).with('fooenv')
255
+ r.should_receive(:set_env).with('fooenv')
256
256
  d.dispatch :rjr_method => 'foobar'
257
257
  end
258
258
 
@@ -337,7 +337,7 @@ module RJR
337
337
  h = proc {}
338
338
  d.handle('foobar', h)
339
339
  d.handlers['foobar'].should == h
340
- d.handles?('foobar').should be_true
340
+ d.handles?('foobar').should be_truthy
341
341
  end
342
342
 
343
343
  it "should set handler from block param" do
@@ -345,7 +345,7 @@ module RJR
345
345
  h = proc {}
346
346
  d.handle('foobar', &h)
347
347
  d.handlers['foobar'].should == h
348
- d.handles?('foobar').should be_true
348
+ d.handles?('foobar').should be_truthy
349
349
  end
350
350
 
351
351
  it "should register handler for multiple methods" do
@@ -354,8 +354,8 @@ module RJR
354
354
  d.handle(['foobar', 'barfoo'], &h)
355
355
  d.handlers['foobar'].should == h
356
356
  d.handlers['barfoo'].should == h
357
- d.handles?('foobar').should be_true
358
- d.handles?('barfoo').should be_true
357
+ d.handles?('foobar').should be_truthy
358
+ d.handles?('barfoo').should be_truthy
359
359
  end
360
360
  end
361
361
 
@@ -376,7 +376,7 @@ module RJR
376
376
  d.handle('foobar', &h)
377
377
 
378
378
  d.dispatch :rjr_method => 'foobar'
379
- invoked.should be_true
379
+ invoked.should be_truthy
380
380
  end
381
381
 
382
382
  it "should pass params to handler" do
@@ -14,7 +14,7 @@ module RJR
14
14
  describe "#start" do
15
15
  it "should start the reactor" do
16
16
  @em.start
17
- @em.reactor_running?.should be_true
17
+ @em.reactor_running?.should be_truthy
18
18
  ['sleep', 'run'].should include(@em.reactor_thread.status)
19
19
  end
20
20
 
@@ -33,7 +33,7 @@ module RJR
33
33
 
34
34
  @em.halt
35
35
  @em.join
36
- @em.reactor_running?.should be_false
36
+ @em.reactor_running?.should be_falsey
37
37
  @em.reactor_thread.should be_nil
38
38
  end
39
39
  end
@@ -65,7 +65,7 @@ module RJR
65
65
  m.synchronize { c.wait m, 0.5 }
66
66
  end
67
67
  end
68
- invoked.should be_true
68
+ invoked.should be_truthy
69
69
  end
70
70
 
71
71
  end
@@ -59,13 +59,13 @@ module RJR
59
59
 
60
60
  context "handler exists" do
61
61
  it "returns true" do
62
- HandlesMethodsTest.has_handler_for?(:handle).should be_true
62
+ HandlesMethodsTest.has_handler_for?(:handle).should be_truthy
63
63
  end
64
64
  end
65
65
 
66
66
  context "handler does not exist" do
67
67
  it "returns false" do
68
- HandlesMethodsTest.has_handler_for?(:foobar).should be_false
68
+ HandlesMethodsTest.has_handler_for?(:foobar).should be_falsey
69
69
  end
70
70
  end
71
71
  end
@@ -1,4 +1,5 @@
1
1
  require 'rjr/util/json_parser'
2
+ require 'rjr/core_ext'
2
3
 
3
4
  module RJR
4
5
  describe JSONParser do
@@ -13,6 +14,31 @@ describe JSONParser do
13
14
  complete = "#{json}remaining"
14
15
  JSONParser.extract_json_from(complete).should == [json, 'remaining']
15
16
  end
17
+
18
+ it "handles brackets in quoted data" do
19
+ json = '{"foo":"val{"}'
20
+ JSONParser.extract_json_from(json).should == [json, '']
21
+ end
22
+
23
+ it "handles nested quotes" do
24
+ json = '{"foo":"val\'{\'"}'
25
+ JSONParser.extract_json_from(json).should == [json, '']
26
+ end
27
+
28
+ it "handles uneven quotes" do
29
+ json = '{"foo":"val\'"}'
30
+ JSONParser.extract_json_from(json).should == [json, '']
31
+ end
32
+
33
+ it "handles escaped quotes" do
34
+ json = '{"foo":"val\\""}'
35
+ JSONParser.extract_json_from(json).should == [json, '']
36
+ end
37
+
38
+ it "handles escaped chars" do
39
+ json = '{"foo":"val\\\\"}'
40
+ JSONParser.extract_json_from(json).should == [json, '']
41
+ end
16
42
  end
17
43
 
18
44
  describe "#invalid_json_class?" do
@@ -32,14 +58,14 @@ describe JSONParser do
32
58
  context "class not on permitted classes list" do
33
59
  it "returns true" do
34
60
  Class.should_receive(:permitted_json_classes).and_return([])
35
- JSONParser.invalid_json_class?('foobar').should be_true
61
+ JSONParser.invalid_json_class?('foobar').should be_truthy
36
62
  end
37
63
  end
38
64
 
39
65
  context "class on permitted classes list" do
40
66
  it "returns false" do
41
67
  Class.should_receive(:permitted_json_classes).and_return(['foobar'])
42
- JSONParser.invalid_json_class?('foobar').should be_false
68
+ JSONParser.invalid_json_class?('foobar').should be_falsey
43
69
  end
44
70
  end
45
71
  end
@@ -51,13 +77,13 @@ describe JSONParser do
51
77
 
52
78
  context "class not on ruby heirarchy" do
53
79
  it "returns true" do
54
- JSONParser.invalid_json_class?('Foobar').should be_true
80
+ JSONParser.invalid_json_class?('Foobar').should be_truthy
55
81
  end
56
82
  end
57
83
 
58
84
  context "class on ruby heirarchy" do
59
85
  it "returns false" do
60
- JSONParser.invalid_json_class?('Integer').should be_false
86
+ JSONParser.invalid_json_class?('Integer').should be_falsey
61
87
  end
62
88
  end
63
89
  end
@@ -0,0 +1,58 @@
1
+ require 'rjr/common'
2
+ require 'rjr/messages/intermediate'
3
+
4
+ module RJR
5
+ module Messages
6
+ describe Intermediate do
7
+ describe "#keys" do
8
+ it "returns extracted data keys" do
9
+ msg = Intermediate.new :data => {:foo => :bar, :mo => :money}
10
+ msg.keys.should == [:foo, :mo]
11
+ end
12
+ end
13
+
14
+ describe "#[]" do
15
+ it "returns value from extracted data" do
16
+ msg = Intermediate.new :data => {'foo' => 'bar'}
17
+ msg['foo'].should == 'bar'
18
+ msg[:foo].should == 'bar'
19
+ end
20
+ end
21
+
22
+ describe "#has?" do
23
+ context "data has key" do
24
+ it "returns true" do
25
+ msg = Intermediate.new :data => {'foo' => 'bar'}
26
+ msg.has?('foo').should be_truthy
27
+ end
28
+ end
29
+
30
+ context "data does not have key" do
31
+ it "returns false" do
32
+ msg = Intermediate.new
33
+ msg.has?('foo').should be_falsey
34
+ end
35
+ end
36
+ end
37
+
38
+ describe "::parse" do
39
+ it "returns new intermediate instance with original message and parsed data" do
40
+ json = '{"foo":"bar"}'
41
+ msg = Intermediate.parse json
42
+ msg.json.should == json
43
+ msg.data.should == {"foo" => "bar"}
44
+ end
45
+
46
+ describe "error parsing json" do
47
+ it "propagates err" do
48
+ json = '{"foo":"bar"}'
49
+ JSONParser.should_receive(:parse).with(json).and_raise(RuntimeError)
50
+ lambda {
51
+ Intermediate.parse json
52
+ }.should raise_error(RuntimeError)
53
+ end
54
+ end
55
+ end
56
+ end # describe Intermediate
57
+ end # module Messages
58
+ end # module RJR
@@ -1,4 +1,5 @@
1
1
  require 'rjr/messages/notification'
2
+ require 'rjr/messages/intermediate'
2
3
 
3
4
  module RJR
4
5
  module Messages
@@ -16,9 +17,9 @@ module Messages
16
17
  it "should return bool indicating if string is a notification msg"
17
18
 
18
19
  it "should produce valid json" do
19
- msg = Notification.new :method => 'test',
20
- :args => ['a', 1],
21
- :headers => {:h => 2}
20
+ msg = Notification.new :method => 'test',
21
+ :args => ['a', 1],
22
+ :headers => {:h => 2}
22
23
 
23
24
  msg_string = msg.to_s
24
25
  msg_string.should include('"h":2')
@@ -31,8 +32,10 @@ module Messages
31
32
  it "should parse notification message string" do
32
33
  msg_string = '{"jsonrpc": "2.0", ' +
33
34
  '"method": "test", "params": ["a", 1]}'
34
- msg = Notification.new :message => msg_string
35
- msg.json_message.should == msg_string
35
+ inter = Intermediate.parse msg_string
36
+
37
+ msg = Notification.new :message => inter
38
+ msg.message.should == inter
36
39
  msg.jr_method.should == 'test'
37
40
  msg.jr_args.should =~ ['a', 1]
38
41
  end
@@ -41,19 +44,15 @@ module Messages
41
44
  msg_string = '{"jsonrpc": "2.0", ' +
42
45
  '"method": "test", "params": ["a", 1], ' +
43
46
  '"h": 2}'
44
- msg = Notification.new :message => msg_string, :headers => {'f' => 'g'}
45
- msg.json_message.should == msg_string
47
+ inter = Intermediate.parse msg_string
48
+
49
+ msg = Notification.new :message => inter, :headers => {'f' => 'g'}
50
+ msg.message.should == inter
46
51
  msg.headers.should have_key 'h'
47
52
  msg.headers.should have_key 'f'
48
53
  msg.headers['h'].should == 2
49
54
  msg.headers['f'].should == 'g'
50
55
  end
51
-
52
- it "should fail if parsing invalid message string" do
53
- lambda {
54
- msg = Notification.new :message => 'foobar'
55
- }.should raise_error JSON::ParserError
56
- end
57
56
  end # describe Notification
58
57
  end # module Messages
59
58
  end # module RJR
@@ -1,13 +1,15 @@
1
1
  require 'rjr/common'
2
2
  require 'rjr/messages/request'
3
+ require 'rjr/messages/intermediate'
3
4
 
4
5
  module RJR
5
6
  module Messages
6
7
  describe Request do
7
8
  it "should accept request parameters" do
8
- msg = Request.new :method => 'test',
9
- :args => ['a', 1],
10
- :headers => {:h => 2}
9
+ msg = Request.new :method => 'test',
10
+ :args => ['a', 1],
11
+ :headers => {:h => 2}
12
+
11
13
  msg.jr_method.should == "test"
12
14
  msg.jr_args.should =~ ['a', 1]
13
15
  msg.headers.should have_key(:h)
@@ -18,9 +20,9 @@ module Messages
18
20
  it "should return bool indicating if string is a request msg"
19
21
 
20
22
  it "should produce valid json" do
21
- msg = Request.new :method => 'test',
22
- :args => ['a', 1],
23
- :headers => {:h => 2}
23
+ msg = Request.new :method => 'test',
24
+ :args => ['a', 1],
25
+ :headers => {:h => 2}
24
26
 
25
27
  msg_string = msg.to_s
26
28
  msg_string.should include('"h":2')
@@ -35,8 +37,10 @@ module Messages
35
37
  msg_string = '{"jsonrpc": "2.0", ' +
36
38
  '"id": "' + msg_uuid + '", ' +
37
39
  '"method": "test", "params": ["a", 1]}'
38
- msg = Request.new :message => msg_string
39
- msg.json_message.should == msg_string
40
+ inter = Intermediate.parse msg_string
41
+
42
+ msg = Request.new :message => inter
43
+ msg.message.should == inter
40
44
  msg.jr_method.should == 'test'
41
45
  msg.jr_args.should =~ ['a', 1]
42
46
  msg.msg_id.should == msg_uuid
@@ -48,19 +52,15 @@ module Messages
48
52
  '"id": "' + msg_uuid + '", ' +
49
53
  '"method": "test", "params": ["a", 1], ' +
50
54
  '"h": 2}'
51
- msg = Request.new :message => msg_string, :headers => {'f' => 'g'}
52
- msg.json_message.should == msg_string
55
+ inter = Intermediate.parse msg_string
56
+
57
+ msg = Request.new :message => inter, :headers => {'f' => 'g'}
58
+ msg.message.should == inter
53
59
  msg.headers.should have_key 'h'
54
60
  msg.headers.should have_key 'f'
55
61
  msg.headers['h'].should == 2
56
62
  msg.headers['f'].should == 'g'
57
63
  end
58
-
59
- it "should fail if parsing invalid message string" do
60
- lambda {
61
- msg = Request.new :message => 'foobar'
62
- }.should raise_error JSON::ParserError
63
- end
64
64
  end # describe Request
65
65
  end # module Messages
66
66
  end # module RJR
@@ -1,6 +1,7 @@
1
1
  require 'rjr/common'
2
2
  require 'rjr/result'
3
3
  require 'rjr/messages/response'
4
+ require 'rjr/messages/intermediate'
4
5
 
5
6
  module RJR
6
7
  module Messages
@@ -21,8 +22,8 @@ module Messages
21
22
  it "should produce valid result response json" do
22
23
  msg_id = gen_uuid
23
24
  msg = Response.new :id => msg_id,
24
- :result => RJR::Result.new(:result => 'success'),
25
- :headers => {:h => 2}
25
+ :result => RJR::Result.new(:result => 'success'),
26
+ :headers => {:h => 2}
26
27
  msg_string = msg.to_s
27
28
  msg_string.should include('"id":"'+msg_id+'"')
28
29
  msg_string.should include('"result":"success"')
@@ -52,8 +53,10 @@ module Messages
52
53
  msg_id = gen_uuid
53
54
  msg_string = '{"id":"' + msg_id + '", ' +
54
55
  '"result":"success","jsonrpc":"2.0"}'
55
- msg = Response.new :message => msg_string
56
- msg.json_message.should == msg_string
56
+ inter = Intermediate.parse msg_string
57
+
58
+ msg = Response.new :message => inter
59
+ msg.message.should == inter
57
60
  msg.msg_id.should == msg_id
58
61
  msg.result.success.should == true
59
62
  msg.result.failed.should == false
@@ -64,8 +67,10 @@ module Messages
64
67
  msg_id = gen_uuid
65
68
  msg_string = '{"id":"' + msg_id + '", ' +
66
69
  '"error":{"code":404,"message":"not found","class":"ArgumentError"}, "jsonrpc":"2.0"}'
67
- msg = Response.new :message => msg_string
68
- msg.json_message.should == msg_string
70
+ inter = Intermediate.parse msg_string
71
+
72
+ msg = Response.new :message => inter
73
+ msg.message.should == inter
69
74
  msg.msg_id.should == msg_id
70
75
  msg.result.success.should == false
71
76
  msg.result.failed.should == true
@@ -78,17 +83,13 @@ module Messages
78
83
  msg_id = gen_uuid
79
84
  msg_string = '{"id":"' + msg_id + '", ' +
80
85
  '"result":"success","h":2,"jsonrpc":"2.0"}'
81
- msg = Response.new :message => msg_string
82
- msg.json_message.should == msg_string
86
+ inter = Intermediate.parse msg_string
87
+
88
+ msg = Response.new :message => inter
89
+ msg.message.should == inter
83
90
  msg.headers.should have_key 'h'
84
91
  msg.headers['h'].should == 2
85
92
  end
86
-
87
- it "should fail if parsing invalid message string" do
88
- lambda {
89
- msg = Response.new :message => 'foobar'
90
- }.should raise_error JSON::ParserError
91
- end
92
93
  end # describe Response
93
94
  end # module Messages
94
95
  end # module RJR