rabx-message 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 07ba374abe002ab50743fb9c8a81b96855e27015
4
+ data.tar.gz: 363d8672a81d05b0ab1621b74da7084009b980dd
5
+ SHA512:
6
+ metadata.gz: 1e2d11ab1bb67e1033212640602abd2c82eb345bc99805d7862639a9261e49a8327d56b5faf98a5763936ef555df7db72b513fd897e829d63e50e6a6f3a0e298
7
+ data.tar.gz: 064e5b31853c42a501181b83a1aff1a8e6dbe3711c7c3ab496275e167fa63e115a6304e8e2bf24ae6351e5f5244ce137f27e24a283b48db342000369a76f8163
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ .yardoc
4
+ Gemfile.lock
5
+ doc/*
6
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
6
+ - 2.2.0
@@ -0,0 +1,4 @@
1
+ --no-private
2
+ --hide-void-return
3
+ --embed-mixin ClassMethods
4
+ --markup=markdown
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in the gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 James McKinney
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,66 @@
1
+ # RPC using Anything But XML (RABX) message parser and emitter
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rabx-message.svg)](http://badge.fury.io/rb/rabx-message)
4
+ [![Build Status](https://secure.travis-ci.org/jpmckinney/rabx-message.png)](http://travis-ci.org/jpmckinney/rabx-message)
5
+ [![Dependency Status](https://gemnasium.com/jpmckinney/rabx-message.png)](https://gemnasium.com/jpmckinney/rabx-message)
6
+ [![Coverage Status](https://coveralls.io/repos/jpmckinney/rabx-message/badge.png)](https://coveralls.io/r/jpmckinney/rabx-message)
7
+ [![Code Climate](https://codeclimate.com/github/jpmckinney/rabx-message.png)](https://codeclimate.com/github/jpmckinney/rabx-message)
8
+
9
+ The RABX specification is a [Perl module](https://github.com/mysociety/commonlib/blob/master/perllib/RABX.pm) by [mySociety](https://www.mysociety.org/).
10
+
11
+ ## Usage
12
+
13
+ ```ruby
14
+ require 'rabx/message'
15
+ ```
16
+
17
+ Dump a RABX message:
18
+
19
+ ```ruby
20
+ RABX::Message.dump('R', 'RPC.method', ['argument', 3])
21
+ # => "R1:0,10:RPC.method,L1:2,T8:argument,I1:3,"
22
+ RABX::Message.dump('S', {name: 'foo', email: 'foo@example.com'})
23
+ # => "S1:0,A1:2,T4:name,T3:foo,T5:email,T15:foo@example.com,"
24
+ RABX::Message.dump('E', 404, 'Not Found')
25
+ # => "E1:0,3:404,9:Not Found,N"
26
+ ```
27
+
28
+ Load a RABX message:
29
+
30
+ ```ruby
31
+ message = RABX::Message.load("R1:0,10:RPC.method,L1:2,T8:argument,I1:3,")
32
+ message.type # "R"
33
+ message.method # "RPC.method"
34
+ message.argumetns # ["argument", 3]
35
+
36
+ message = RABX::Message.load("S1:0,A1:2,T4:name,T3:foo,T5:email,T15:foo@example.com,")
37
+ message.type # "S"
38
+ message.value # {"name"=>"foo", "email"=>"foo@example.com"}
39
+
40
+ message = RABX::Message.load("E1:0,3:404,9:Not Found,N")
41
+ message.type # "E"
42
+ message.code # "404"
43
+ message.text # "Not Found"
44
+ message.extra # nil
45
+ ```
46
+
47
+ See the [documentation](http://www.rubydoc.info/gems/rabx-message) to see how to work with `RABX::Message` instances.
48
+
49
+ ## Notes
50
+
51
+ Generic RABX clients include:
52
+
53
+ * [Perl](https://github.com/mysociety/commonlib/blob/master/perllib/RABX.pm)
54
+ * [PHP](https://github.com/mysociety/commonlib/blob/master/phplib/rabx.php)
55
+ * [Python](https://github.com/mysociety/commonlib/blob/master/pylib/mysociety/rabx.py) (REST interface)
56
+ * [Ruby](https://github.com/mysociety/commonlib/blob/master/rblib/rabx.rb) (REST interface)
57
+ * [Command-line](https://github.com/mysociety/misc-scripts/blob/master/bin/rabx)
58
+
59
+ mySociety has scripts to convert a Perl RABX server to a server-specific client in:
60
+
61
+ * [Perl](https://github.com/mysociety/misc-scripts/blob/master/bin/rabxtopl.pl)
62
+ * [PHP](https://github.com/mysociety/misc-scripts/blob/master/bin/rabxtophp.pl)
63
+ * [Python](https://github.com/mysociety/misc-scripts/blob/master/bin/rabxresttopy.pl)
64
+ * [Ruby](https://github.com/mysociety/misc-scripts/blob/master/bin/rabxresttorb.pl)
65
+
66
+ Copyright (c) 2014 James McKinney, released under the MIT license
@@ -0,0 +1,16 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ begin
10
+ require 'yard'
11
+ YARD::Rake::YardocTask.new
12
+ rescue LoadError
13
+ task :yard do
14
+ abort 'YARD is not available. In order to run yard, you must: gem install yard'
15
+ end
16
+ end
data/USAGE ADDED
@@ -0,0 +1 @@
1
+ See README.md for full usage details.
@@ -0,0 +1 @@
1
+ E1:0,3:515,48:first byte of call string should be "R", not "D",N
@@ -0,0 +1,225 @@
1
+ require 'netstring'
2
+
3
+ module RABX
4
+ class Message
5
+ class Error < StandardError; end
6
+ class ProtocolError < Error; end
7
+ class InterfaceError < Error; end
8
+
9
+ # Dumps a RABX message.
10
+ #
11
+ # @param [String] type a message type
12
+ # @param [Array] args message contents
13
+ # @return [String] the REBX message
14
+ def self.dump(type, *args)
15
+ string = type + Netstring.dump('0')
16
+ if type == 'R'
17
+ string + Netstring.dump(args[0]) + _dump(args[1])
18
+ elsif type == 'S'
19
+ if args.size.zero?
20
+ string
21
+ else
22
+ string + _dump(args[0])
23
+ end
24
+ elsif type == 'E'
25
+ string + Netstring.dump(args[0].to_s) + Netstring.dump(args[1]) + _dump(args[2])
26
+ end
27
+ end
28
+
29
+ # Loads a RABX message.
30
+ #
31
+ # @param [String] s a RABX message
32
+ # @return [Message] a parsed message
33
+ def self.load(s)
34
+ case s[0]
35
+ when 'R'
36
+ RequestMessage.new(s)
37
+ when 'S'
38
+ SuccessMessage.new(s)
39
+ when 'E'
40
+ ErrorMessage.new(s)
41
+ else
42
+ raise ProtocolError, %(unknown RABX message type "#{s[0]}")
43
+ end
44
+ end
45
+
46
+ attr_reader :version
47
+
48
+ # @param [String] s a RABX message
49
+ def initialize(s)
50
+ if s.empty?
51
+ raise ProtocolError, 'string is too short'
52
+ end
53
+ @s = s.dup # string
54
+ @p = 1 # pointer
55
+ @size = @s.size
56
+ @version = getnetstring
57
+ parse
58
+ end
59
+
60
+ # Returns the RABX message.
61
+ #
62
+ # @return [String] the RABX message
63
+ def to_s
64
+ @s
65
+ end
66
+
67
+ # Returns the message type.
68
+ #
69
+ # @return [String] the message type
70
+ def type
71
+ @s[0]
72
+ end
73
+
74
+ # Returns whether the reader has reached the end-of-file.
75
+ #
76
+ # @return [Boolean] whether the reader has reached the end-of-file
77
+ def eof?
78
+ @p == @size
79
+ end
80
+
81
+ # Loads a netstring from the current position in the message.
82
+ #
83
+ # @return [Netstring,nil] a string, or nil if at end-of-file
84
+ def getnetstring
85
+ if eof?
86
+ nil
87
+ else
88
+ string = Netstring.load(@s[@p..-1])
89
+ @p += string.netstring.size
90
+ string
91
+ end
92
+ rescue Netstring::Error => e
93
+ raise ProtocolError, "#{e.message} in netstring starting at #{@p}"
94
+ end
95
+
96
+ # Loads a typed netstring from the current position in the message.
97
+ #
98
+ # @return the contents of the netstring, or nil if at end-of-file
99
+ def gets
100
+ if eof?
101
+ nil
102
+ else
103
+ type = @s[@p]
104
+ @p += 1
105
+
106
+ if type == 'N' # null
107
+ return nil
108
+ end
109
+
110
+ case type
111
+ when 'I' # integer
112
+ value = getnetstring.to_s
113
+ begin
114
+ Integer(value)
115
+ rescue ArgumentError
116
+ raise ProtocolError, %(expected integer, got #{value.inspect} at position #{@p - value.size - 1})
117
+ end
118
+ when 'R' # real
119
+ value = getnetstring.to_s
120
+ begin
121
+ Float(value)
122
+ rescue ArgumentError
123
+ raise ProtocolError, %(expected float, got #{value.inspect} at position #{@p - value.size - 1})
124
+ end
125
+ when 'T', 'B' # text, binary
126
+ getnetstring
127
+ when 'L' # list
128
+ value = getnetstring.to_s
129
+ begin
130
+ size = Integer(value)
131
+ rescue ArgumentError
132
+ raise ProtocolError, %(expected integer, got #{value.inspect} at position #{@p - value.size - 1})
133
+ end
134
+ array = []
135
+ size.times do |n|
136
+ if eof?
137
+ raise ProtocolError, %(expected #{size} items, got #{n} items at position #{@p})
138
+ end
139
+ array << gets
140
+ end
141
+ array
142
+ when 'A' # associative array
143
+ value = getnetstring.to_s
144
+ begin
145
+ size = Integer(value)
146
+ rescue ArgumentError
147
+ raise ProtocolError, %(expected integer, got #{value.inspect} at position #{@p - value.size - 1})
148
+ end
149
+ hash = {}
150
+ size.times do |n|
151
+ if eof?
152
+ raise ProtocolError, %(expected #{size} items, got #{n} items at position #{@p})
153
+ end
154
+ key = gets # test for repeated keys?
155
+ if eof?
156
+ raise ProtocolError, %(expected value, got end-of-file at position #{@p})
157
+ end
158
+ hash[key] = gets
159
+ end
160
+ hash
161
+ else
162
+ raise ProtocolError, %(bad type character "#{type}" at position #{@p})
163
+ end
164
+ end
165
+ end
166
+
167
+ private
168
+
169
+ def parse
170
+ # If not implemented, user can read message using `getnetstring` and `gets`.
171
+ end
172
+
173
+ def self._dump(args)
174
+ case args
175
+ when nil
176
+ 'N'
177
+ when true
178
+ 'I' + Netstring.dump('1')
179
+ when false
180
+ 'I' + Netstring.dump('0')
181
+ when Integer
182
+ 'I' + Netstring.dump(args.to_s)
183
+ when Float
184
+ 'R' + Netstring.dump(args.to_s)
185
+ when String
186
+ 'T' + Netstring.dump(args)
187
+ when Symbol
188
+ 'T' + Netstring.dump(args.to_s)
189
+ when Array
190
+ 'L' + Netstring.dump(args.size.to_s) + args.map{|arg| _dump(arg)}.join
191
+ when Hash
192
+ 'A' + Netstring.dump(args.size.to_s) + args.map{|k,v| _dump(k) + _dump(v)}.join
193
+ else
194
+ raise InterfaceError, "can't pass #{args.class} over RABX"
195
+ end
196
+ end
197
+ end
198
+
199
+ class RequestMessage < Message
200
+ attr_reader :method, :arguments
201
+
202
+ def parse
203
+ @method = getnetstring
204
+ @arguments = gets
205
+ end
206
+ end
207
+
208
+ class SuccessMessage < Message
209
+ attr_reader :value
210
+
211
+ def parse
212
+ @value = gets
213
+ end
214
+ end
215
+
216
+ class ErrorMessage < Message
217
+ attr_reader :code, :text, :extra
218
+
219
+ def parse
220
+ @code = getnetstring
221
+ @text = getnetstring
222
+ @extra = gets unless eof?
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,5 @@
1
+ module RABX
2
+ class Message
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/rabx/message/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "rabx-message"
6
+ s.version = RABX::Message::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["James McKinney"]
9
+ s.homepage = "http://github.com/jpmckinney/rabx-message"
10
+ s.summary = %q{A RPC using Anything But XML (RABX) message parser and emitter}
11
+ s.license = 'MIT'
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_runtime_dependency('netstring', '~> 0.0')
19
+
20
+ s.add_development_dependency('coveralls')
21
+ s.add_development_dependency('json', '~> 1.8') # to silence coveralls warning
22
+ s.add_development_dependency('rake')
23
+ s.add_development_dependency('rspec', '~> 3.1')
24
+ end
@@ -0,0 +1,266 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RABX::Message do
4
+ let :invalid_netstring do
5
+ RABX::Message.new('R1:0,1:x')
6
+ end
7
+
8
+ let :invalid_rabx do
9
+ RABX::Message.new('S1:0,I1:x')
10
+ end
11
+
12
+ let :n do
13
+ RABX::Message.new('S1:0,N')
14
+ end
15
+
16
+ let :i do
17
+ RABX::Message.new('S1:0,I2:34,')
18
+ end
19
+ let :invalid_i do
20
+ RABX::Message.new('S1:0,I2:xy,')
21
+ end
22
+
23
+ let :r do
24
+ RABX::Message.new('S1:0,R4:1.23,')
25
+ end
26
+ let :invalid_r do
27
+ RABX::Message.new('S1:0,R4:abcd,')
28
+ end
29
+
30
+ let :t do
31
+ RABX::Message.new('S1:0,T2:xy,')
32
+ end
33
+
34
+ let :b do
35
+ RABX::Message.new('S1:0,B2:ab,')
36
+ end
37
+
38
+ let :l do
39
+ RABX::Message.new('S1:0,L1:2,I2:34,T2:xy,')
40
+ end
41
+ let :invalid_l_size do
42
+ RABX::Message.new('S1:0,L1:x,I2:34,T2:xy,')
43
+ end
44
+ let :missing_l_item do
45
+ RABX::Message.new('S1:0,L1:2,I2:34,')
46
+ end
47
+
48
+ let :a do
49
+ RABX::Message.new('S1:0,A1:2,I2:34,T2:xy,R4:1.23,B2:ab,')
50
+ end
51
+ let :invalid_a_size do
52
+ RABX::Message.new('S1:0,A1:x,I2:34,T2:xy,R4:1.23,B2:ab,')
53
+ end
54
+ let :missing_a_item do
55
+ RABX::Message.new('S1:0,A1:2,I2:34,T2:xy,')
56
+ end
57
+ let :missing_a_value do
58
+ RABX::Message.new('S1:0,A1:2,I2:34,T2:xy,R4:1.23,')
59
+ end
60
+
61
+ let :invalid_type do
62
+ RABX::Message.new('S1:0,U1:x,')
63
+ end
64
+
65
+ let :empty_message do
66
+ 'S1:0,'
67
+ end
68
+ let :empty do
69
+ RABX::Message.new(empty_message)
70
+ end
71
+
72
+ let :request_message do
73
+ 'R1:0,6:method,L1:2,I2:34,T2:xy,'
74
+ end
75
+ let :request do
76
+ RABX::Message.new(request_message)
77
+ end
78
+
79
+ let :success_message do
80
+ 'S1:0,A1:2,I2:34,T2:xy,R4:1.23,T2:ab,'
81
+ end
82
+ let :success do
83
+ RABX::Message.new(success_message)
84
+ end
85
+
86
+ let :error_message do
87
+ "E1:0,3:404,9:Not Found,N"
88
+ end
89
+ let :error do
90
+ RABX::Message.new(error_message)
91
+ end
92
+
93
+ let :unknown_message do
94
+ 'U1:0,'
95
+ end
96
+ let :unknown do
97
+ RABX::Message.new(unknown_message)
98
+ end
99
+
100
+ describe '.dump' do
101
+ it 'should dump a RABX message' do
102
+ {
103
+ ['S'] => empty_message,
104
+ ['R', 'method', [34, 'xy']] => request_message,
105
+ ['S', {34 => 'xy', 1.23 => 'ab'}] => success_message,
106
+ ['E', 404, 'Not Found'] => error_message,
107
+ ['S', nil] => 'S1:0,N',
108
+ ['S', true] => 'S1:0,I1:1,',
109
+ ['S', false] => 'S1:0,I1:0,',
110
+ ['S', 1] => 'S1:0,I1:1,',
111
+ ['S', 1.1] => 'S1:0,R3:1.1,',
112
+ ['S', 'x'] => 'S1:0,T1:x,',
113
+ ['S', :x] => 'S1:0,T1:x,',
114
+ ['S', []] => 'S1:0,L1:0,',
115
+ ['S', {}] => 'S1:0,A1:0,',
116
+ }.each do |args,string|
117
+ expect(RABX::Message.dump(*args)).to eq(string)
118
+ end
119
+ end
120
+ end
121
+
122
+ describe '.load' do
123
+ it 'should load a RABX request message' do
124
+ message = RABX::Message.load(request_message)
125
+ expect(message.method).to eq('method')
126
+ expect(message.arguments).to eq([34, 'xy'])
127
+ end
128
+
129
+ it 'should load a RABX success message' do
130
+ message = RABX::Message.load(success_message)
131
+ expect(message.value).to eq({34 => 'xy', 1.23 => 'ab'})
132
+ end
133
+
134
+ it 'should load a RABX error message' do
135
+ message = RABX::Message.load(error_message)
136
+ expect(message.code).to eq('404')
137
+ expect(message.text).to eq('Not Found')
138
+ expect(message.extra).to eq(nil)
139
+ end
140
+
141
+ it 'should raise an error if type is unknown' do
142
+ expect{RABX::Message.load(unknown_message)}.to raise_error(RABX::Message::ProtocolError, 'unknown RABX message type "U"')
143
+ end
144
+ end
145
+
146
+ describe '#initialize' do
147
+ it 'should initialize a RABX message' do
148
+ expect{request}.to_not raise_error
149
+ end
150
+
151
+ it 'should make a copy of the string' do
152
+ expect(request.instance_variable_get(:@s)).to eq('R1:0,6:method,L1:2,I2:34,T2:xy,')
153
+ request_message.reverse!
154
+ expect(request.instance_variable_get(:@s)).to eq('R1:0,6:method,L1:2,I2:34,T2:xy,')
155
+ end
156
+
157
+ it 'should raise an error if the string is empty' do
158
+ expect{RABX::Message.new('')}.to raise_error(RABX::Message::ProtocolError, 'string is too short')
159
+ end
160
+ end
161
+
162
+ describe '#to_s' do
163
+ it 'should return the message' do
164
+ expect(request.to_s).to eq(request_message)
165
+ end
166
+ end
167
+
168
+ describe '#type' do
169
+ it 'should return the message type' do
170
+ expect(request.type).to eq('R')
171
+ expect(success.type).to eq('S')
172
+ expect(error.type).to eq('E')
173
+ end
174
+ end
175
+
176
+ describe '#eof?' do
177
+ it 'should return true only if the message has been read' do
178
+ message = RABX::Message.new('S1:0,N')
179
+ expect(message.eof?).to eq(false)
180
+ expect(message.gets).to eq(nil)
181
+ expect(message.eof?).to eq(true)
182
+ end
183
+ end
184
+
185
+ describe '#getnetstring' do
186
+ it 'should read a netstring' do
187
+ expect(error.getnetstring).to eq('404')
188
+ expect(error.getnetstring).to eq('Not Found')
189
+ end
190
+
191
+ it 'should return nil if at end of message' do
192
+ expect(empty.getnetstring).to eq(nil)
193
+ expect(empty.getnetstring).to eq(nil)
194
+ expect(empty.getnetstring).to eq(nil)
195
+ end
196
+
197
+ it 'should raise an error if the netstring is invalid' do
198
+ expect{invalid_netstring.getnetstring}.to raise_error(RABX::Message::ProtocolError)
199
+ end
200
+ end
201
+
202
+ describe '#gets' do
203
+ it 'should read a N message' do
204
+ expect(n.gets).to eq(nil)
205
+ end
206
+
207
+ it 'should read a I message' do
208
+ expect(i.gets).to eq(34)
209
+ end
210
+ it 'should raise an error if an integer is invalid' do
211
+ expect{invalid_i.gets}.to raise_error(RABX::Message::ProtocolError, 'expected integer, got "xy" at position 8')
212
+ end
213
+
214
+ it 'should read a R message' do
215
+ expect(r.gets).to eq(1.23)
216
+ end
217
+ it 'should raise an error if a float is invalid' do
218
+ expect{invalid_r.gets}.to raise_error(RABX::Message::ProtocolError, 'expected float, got "abcd" at position 8')
219
+ end
220
+
221
+ it 'should read a T message' do
222
+ expect(t.gets).to eq('xy')
223
+ end
224
+
225
+ it 'should read a B message' do
226
+ expect(b.gets).to eq('ab')
227
+ end
228
+
229
+ it 'should read a L message' do
230
+ expect(l.gets).to eq([34, 'xy'])
231
+ end
232
+ it 'should raise an error if a list size is invalid' do
233
+ expect{invalid_l_size.gets}.to raise_error(RABX::Message::ProtocolError, 'expected integer, got "x" at position 8')
234
+ end
235
+ it 'should raise an error if a list item is missing' do
236
+ expect{missing_l_item.gets}.to raise_error(RABX::Message::ProtocolError, 'expected 2 items, got 1 items at position 16')
237
+ end
238
+
239
+ it 'should read a A message' do
240
+ expect(a.gets).to eq({34 => 'xy', 1.23 => 'ab'})
241
+ end
242
+ it 'should raise an error if a hash size is invalid' do
243
+ expect{invalid_a_size.gets}.to raise_error(RABX::Message::ProtocolError, 'expected integer, got "x" at position 8')
244
+ end
245
+ it 'should raise an error if a hash item is missing' do
246
+ expect{missing_a_item.gets}.to raise_error(RABX::Message::ProtocolError, 'expected 2 items, got 1 items at position 22')
247
+ end
248
+ it 'should raise an error if a hash value is missing' do
249
+ expect{missing_a_value.gets}.to raise_error(RABX::Message::ProtocolError, 'expected value, got end-of-file at position 30')
250
+ end
251
+
252
+ it 'should raise an error if the type is invalid' do
253
+ expect{invalid_type.gets}.to raise_error(RABX::Message::ProtocolError, 'bad type character "U" at position 6')
254
+ end
255
+
256
+ it 'should return nil if at end of message' do
257
+ expect(empty.gets).to eq(nil)
258
+ expect(empty.gets).to eq(nil)
259
+ expect(empty.gets).to eq(nil)
260
+ end
261
+
262
+ it 'should raise an error if the netstring is invalid' do
263
+ expect{invalid_rabx.gets}.to raise_error(RABX::Message::ProtocolError)
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+
3
+ require 'simplecov'
4
+ require 'coveralls'
5
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
6
+ SimpleCov.start do
7
+ add_filter 'spec'
8
+ end
9
+
10
+ require 'rspec'
11
+ require File.dirname(__FILE__) + '/../lib/rabx/message'
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rabx-message
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - James McKinney
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: netstring
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: coveralls
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.1'
83
+ description:
84
+ email:
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - ".gitignore"
90
+ - ".rspec"
91
+ - ".travis.yml"
92
+ - ".yardopts"
93
+ - Gemfile
94
+ - LICENSE
95
+ - README.md
96
+ - Rakefile
97
+ - USAGE
98
+ - lib/50418
99
+ - lib/rabx/message.rb
100
+ - lib/rabx/message/version.rb
101
+ - rabx-message.gemspec
102
+ - spec/message_spec.rb
103
+ - spec/spec_helper.rb
104
+ homepage: http://github.com/jpmckinney/rabx-message
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.2.2
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: A RPC using Anything But XML (RABX) message parser and emitter
128
+ test_files:
129
+ - spec/message_spec.rb
130
+ - spec/spec_helper.rb