ione 1.2.2 → 1.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/ione/byte_buffer.rb +11 -3
- data/lib/ione/future.rb +67 -51
- data/lib/ione/io/acceptor.rb +1 -0
- data/lib/ione/io/base_connection.rb +2 -0
- data/lib/ione/io/connection.rb +1 -0
- data/lib/ione/io/io_reactor.rb +8 -7
- data/lib/ione/io/ssl_connection.rb +1 -0
- data/lib/ione/version.rb +1 -1
- data/spec/integration/io_spec.rb +3 -3
- data/spec/integration/ssl_spec.rb +7 -2
- data/spec/ione/byte_buffer_spec.rb +51 -37
- data/spec/ione/future_spec.rb +76 -65
- data/spec/ione/heap_spec.rb +18 -18
- data/spec/ione/io/acceptor_spec.rb +5 -5
- data/spec/ione/io/connection_common.rb +2 -2
- data/spec/ione/io/io_reactor_spec.rb +34 -18
- data/spec/ione/io/ssl_acceptor_spec.rb +3 -3
- data/spec/ione/io/ssl_connection_spec.rb +3 -3
- data/spec/spec_helper.rb +4 -0
- data/spec/support/fake_server.rb +1 -0
- metadata +14 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9c062de288365ad9e47516ad7b9d3ab028ab9449964c88675c0b913657a8ef07
|
4
|
+
data.tar.gz: f349d422d1df3001a9c5fb5df55c329ed60cebc9dad20ddf1a97f52883c53093
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4523ab1052502a8da1879f73481f8326b260b478d71c7e9d882b264e2c274092ae0801a43c5884492ea06fd69dd3ac02ab184ef309dbcf1cf5b8d441f37e8bd6
|
7
|
+
data.tar.gz: 1e5d1c7f51593988a2270ec4c6b74cd61d72a1dd2c6a69d5c6f4b2053052aa4ee3bd52375c4e419d423110bd70994350662a61850907570db47ea45c24a7575b
|
data/lib/ione/byte_buffer.rb
CHANGED
@@ -179,10 +179,12 @@ module Ione
|
|
179
179
|
swap_buffers
|
180
180
|
end
|
181
181
|
read_buffer_length = @read_buffer.bytesize
|
182
|
-
if start_index
|
182
|
+
if start_index + substring.bytesize <= read_buffer_length - @offset && (index = @read_buffer.index(substring, @offset + start_index))
|
183
183
|
index - @offset
|
184
|
-
elsif
|
185
|
-
|
184
|
+
elsif start_index + substring.bytesize <= read_buffer_length - @offset + @write_buffer.bytesize
|
185
|
+
merge_read_buffer
|
186
|
+
start_index = read_buffer_length - substring.bytesize if read_buffer_length - substring.bytesize > start_index
|
187
|
+
@read_buffer.index(substring, start_index)
|
186
188
|
else
|
187
189
|
nil
|
188
190
|
end
|
@@ -298,5 +300,11 @@ module Ione
|
|
298
300
|
@read_buffer = @write_buffer
|
299
301
|
@write_buffer = ''
|
300
302
|
end
|
303
|
+
|
304
|
+
def merge_read_buffer
|
305
|
+
@read_buffer = @read_buffer[@offset, @read_buffer.length - @offset] << @write_buffer
|
306
|
+
@write_buffer = ''
|
307
|
+
@offset = 0
|
308
|
+
end
|
301
309
|
end
|
302
310
|
end
|
data/lib/ione/future.rb
CHANGED
@@ -209,6 +209,8 @@ module Ione
|
|
209
209
|
end
|
210
210
|
if futures.count == 0
|
211
211
|
resolved([])
|
212
|
+
elsif (failed = futures.find { |f| f.respond_to?(:failed?) && f.failed? })
|
213
|
+
failed
|
212
214
|
else
|
213
215
|
CombinedFuture.new(futures)
|
214
216
|
end
|
@@ -231,6 +233,7 @@ module Ione
|
|
231
233
|
if futures.size == 1 && (fs = futures.first).is_a?(Enumerable)
|
232
234
|
*futures = *fs
|
233
235
|
end
|
236
|
+
futures.reject! { |f| f.respond_to?(:resolved?) && f.resolved? }
|
234
237
|
if futures.count == 0
|
235
238
|
ResolvedFuture::NIL
|
236
239
|
elsif futures.count == 1
|
@@ -262,7 +265,9 @@ module Ione
|
|
262
265
|
futures = fs
|
263
266
|
end
|
264
267
|
if futures.count == 0
|
265
|
-
|
268
|
+
ResolvedFuture::NIL
|
269
|
+
elsif (done = futures.find { |f| f.respond_to?(:resolved?) && f.resolved? })
|
270
|
+
done
|
266
271
|
else
|
267
272
|
FirstFuture.new(futures)
|
268
273
|
end
|
@@ -594,6 +599,8 @@ module Ione
|
|
594
599
|
@lock = Mutex.new
|
595
600
|
@state = PENDING_STATE
|
596
601
|
@listeners = []
|
602
|
+
@value = nil
|
603
|
+
@error = nil
|
597
604
|
end
|
598
605
|
|
599
606
|
# Registers a listener that will be called when this future completes,
|
@@ -854,9 +861,9 @@ module Ione
|
|
854
861
|
looping = more = true
|
855
862
|
while more
|
856
863
|
more = false
|
857
|
-
@futures.pop.on_complete do |
|
858
|
-
if
|
859
|
-
await_next(
|
864
|
+
@futures.pop.on_complete do |value, error|
|
865
|
+
if error || @futures.empty? || !looping || !Thread.current.equal?(outer)
|
866
|
+
await_next(value, error)
|
860
867
|
else
|
861
868
|
more = true
|
862
869
|
end
|
@@ -874,64 +881,56 @@ module Ione
|
|
874
881
|
def initialize(futures, initial_value, reducer)
|
875
882
|
super()
|
876
883
|
@futures = Array(futures)
|
877
|
-
@
|
878
|
-
@initial_value = initial_value
|
879
|
-
@accumulator = initial_value.nil? ? NO_INITIAL_VALUE : initial_value
|
884
|
+
@initial_value = initial_value.nil? ? NO_INITIAL_VALUE : initial_value
|
880
885
|
@reducer = reducer
|
881
886
|
end
|
882
|
-
|
883
|
-
private
|
884
|
-
|
885
|
-
def reduce_one(value)
|
886
|
-
unless failed?
|
887
|
-
@lock.lock
|
888
|
-
begin
|
889
|
-
if @accumulator.equal?(NO_INITIAL_VALUE)
|
890
|
-
@accumulator = value
|
891
|
-
else
|
892
|
-
@accumulator = @reducer.call(@accumulator, value)
|
893
|
-
end
|
894
|
-
@remaining -= 1
|
895
|
-
rescue => e
|
896
|
-
@lock.unlock
|
897
|
-
fail(e)
|
898
|
-
else
|
899
|
-
@lock.unlock
|
900
|
-
end
|
901
|
-
unless failed?
|
902
|
-
if @remaining == 0
|
903
|
-
resolve(@accumulator)
|
904
|
-
:done
|
905
|
-
else
|
906
|
-
:continue
|
907
|
-
end
|
908
|
-
end
|
909
|
-
end
|
910
|
-
end
|
911
887
|
end
|
912
888
|
|
913
889
|
# @private
|
914
890
|
class OrderedReducingFuture < ReducingFuture
|
915
891
|
def initialize(futures, initial_value, reducer)
|
916
892
|
super
|
917
|
-
if @
|
918
|
-
|
893
|
+
if @futures.empty?
|
894
|
+
resolve(@initial_value.equal?(NO_INITIAL_VALUE) ? nil : @initial_value)
|
895
|
+
elsif @initial_value.equal?(NO_INITIAL_VALUE)
|
896
|
+
@futures.shift.on_complete(&method(:reduce_next))
|
919
897
|
else
|
920
|
-
|
898
|
+
reduce_next(@initial_value, nil)
|
921
899
|
end
|
922
900
|
end
|
923
901
|
|
924
902
|
private
|
925
903
|
|
926
|
-
def reduce_next(
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
904
|
+
def reduce_next(accumulator, e)
|
905
|
+
if e
|
906
|
+
@futures = nil
|
907
|
+
fail(e)
|
908
|
+
elsif @futures.empty?
|
909
|
+
@futures = nil
|
910
|
+
resolve(accumulator)
|
911
|
+
else
|
912
|
+
outer = Thread.current
|
913
|
+
looping = more = true
|
914
|
+
while more
|
915
|
+
more = false
|
916
|
+
@futures.shift.on_complete do |v, ee|
|
917
|
+
if ee
|
918
|
+
reduce_next(nil, ee)
|
919
|
+
else
|
920
|
+
begin
|
921
|
+
accumulator = @reducer.call(accumulator, v)
|
922
|
+
if @futures.empty? || !looping || !Thread.current.equal?(outer)
|
923
|
+
reduce_next(accumulator, nil)
|
924
|
+
else
|
925
|
+
more = true
|
926
|
+
end
|
927
|
+
rescue => eee
|
928
|
+
reduce_next(nil, eee)
|
929
|
+
end
|
930
|
+
end
|
933
931
|
end
|
934
932
|
end
|
933
|
+
looping = false
|
935
934
|
end
|
936
935
|
end
|
937
936
|
end
|
@@ -940,20 +939,37 @@ module Ione
|
|
940
939
|
class UnorderedReducingFuture < ReducingFuture
|
941
940
|
def initialize(futures, initial_value, reducer)
|
942
941
|
super
|
943
|
-
if @
|
944
|
-
|
942
|
+
if @futures.empty?
|
943
|
+
resolve(@initial_value.equal?(NO_INITIAL_VALUE) ? nil : @initial_value)
|
944
|
+
else
|
945
|
+
accumulator = @initial_value
|
946
|
+
remaining = @futures.size
|
947
|
+
@futures.each do |f|
|
945
948
|
f.on_complete do |v, e|
|
946
949
|
unless failed?
|
947
950
|
if e
|
948
951
|
fail(e)
|
949
952
|
else
|
950
|
-
|
953
|
+
done = false
|
954
|
+
@lock.lock
|
955
|
+
begin
|
956
|
+
accumulator = accumulator.equal?(NO_INITIAL_VALUE) ? v : @reducer.call(accumulator, v)
|
957
|
+
remaining -= 1
|
958
|
+
done = (remaining == 0)
|
959
|
+
rescue => ee
|
960
|
+
@lock.unlock
|
961
|
+
fail(ee)
|
962
|
+
else
|
963
|
+
@lock.unlock
|
964
|
+
end
|
965
|
+
if done
|
966
|
+
@futures = nil
|
967
|
+
resolve(accumulator)
|
968
|
+
end
|
951
969
|
end
|
952
970
|
end
|
953
971
|
end
|
954
972
|
end
|
955
|
-
else
|
956
|
-
resolve(@initial_value)
|
957
973
|
end
|
958
974
|
end
|
959
975
|
end
|
data/lib/ione/io/acceptor.rb
CHANGED
@@ -15,10 +15,12 @@ module Ione
|
|
15
15
|
def initialize(host, port, unblocker)
|
16
16
|
@host = host
|
17
17
|
@port = port
|
18
|
+
@io = nil
|
18
19
|
@unblocker = unblocker
|
19
20
|
@state = CONNECTING_STATE
|
20
21
|
@writable = false
|
21
22
|
@lock = Mutex.new
|
23
|
+
@data_listener = nil
|
22
24
|
@write_buffer = ByteBuffer.new
|
23
25
|
@closed_promise = Promise.new
|
24
26
|
end
|
data/lib/ione/io/connection.rb
CHANGED
data/lib/ione/io/io_reactor.rb
CHANGED
@@ -95,8 +95,9 @@ module Ione
|
|
95
95
|
@clock = options[:clock] || Time
|
96
96
|
@state = PENDING_STATE
|
97
97
|
@error_listeners = []
|
98
|
+
@unblocker = nil
|
98
99
|
@io_loop = IoLoopBody.new(@options)
|
99
|
-
@scheduler = Scheduler.new
|
100
|
+
@scheduler = Scheduler.new(@options)
|
100
101
|
@lock = Mutex.new
|
101
102
|
end
|
102
103
|
|
@@ -124,7 +125,7 @@ module Ione
|
|
124
125
|
# after {#stop} has been called, but false when the future returned by
|
125
126
|
# {#stop} completes.
|
126
127
|
def running?
|
127
|
-
@state == RUNNING_STATE
|
128
|
+
(state = @state) == RUNNING_STATE || state == STOPPING_STATE
|
128
129
|
end
|
129
130
|
|
130
131
|
# Starts the reactor. This will spawn a background thread that will manage
|
@@ -570,8 +571,8 @@ module Ione
|
|
570
571
|
ensure
|
571
572
|
@lock.unlock
|
572
573
|
end
|
573
|
-
timers.each do |
|
574
|
-
|
574
|
+
timers.each do |t|
|
575
|
+
t.fail(CancelledError.new)
|
575
576
|
end
|
576
577
|
nil
|
577
578
|
end
|
@@ -592,8 +593,8 @@ module Ione
|
|
592
593
|
ensure
|
593
594
|
@lock.unlock
|
594
595
|
end
|
595
|
-
expired_timers.each do |
|
596
|
-
|
596
|
+
expired_timers.each do |t|
|
597
|
+
t.fulfill
|
597
598
|
end
|
598
599
|
end
|
599
600
|
end
|
@@ -604,4 +605,4 @@ module Ione
|
|
604
605
|
end
|
605
606
|
end
|
606
607
|
end
|
607
|
-
end
|
608
|
+
end
|
data/lib/ione/version.rb
CHANGED
data/spec/integration/io_spec.rb
CHANGED
@@ -37,7 +37,7 @@ describe 'An IO reactor' do
|
|
37
37
|
fake_server.await_connects(1)
|
38
38
|
fake_server.broadcast('hello world')
|
39
39
|
await { protocol_handler.data.bytesize > 0 }
|
40
|
-
protocol_handler.data.should
|
40
|
+
protocol_handler.data.should eq('hello world')
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'receives data on multiple connections' do
|
@@ -45,7 +45,7 @@ describe 'An IO reactor' do
|
|
45
45
|
fake_server.await_connects(10)
|
46
46
|
fake_server.broadcast('hello world')
|
47
47
|
await { protocol_handlers.all? { |c| c.data.bytesize > 0 } }
|
48
|
-
protocol_handlers.sample.data.should
|
48
|
+
protocol_handlers.sample.data.should eq('hello world')
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -81,7 +81,7 @@ describe 'An IO reactor' do
|
|
81
81
|
socket = TCPSocket.new(ENV['SERVER_HOST'], port)
|
82
82
|
socket.puts('HELLO')
|
83
83
|
result = socket.read(5)
|
84
|
-
result.should
|
84
|
+
result.should eq('HELLO')
|
85
85
|
socket.close
|
86
86
|
end
|
87
87
|
end
|
@@ -49,6 +49,7 @@ describe 'SSL' do
|
|
49
49
|
ssl_context = OpenSSL::SSL::SSLContext.new
|
50
50
|
ssl_context.key = OpenSSL::PKey::RSA.new(ssl_key)
|
51
51
|
ssl_context.cert = OpenSSL::X509::Certificate.new(ssl_cert)
|
52
|
+
ssl_context.tmp_dh_callback = proc { SslSpec::DH_PARAMS }
|
52
53
|
|
53
54
|
f = io_reactor.start
|
54
55
|
f = f.flat_map do
|
@@ -80,8 +81,8 @@ describe 'SSL' do
|
|
80
81
|
end
|
81
82
|
client.write('hello world')
|
82
83
|
response_received.future.value
|
83
|
-
server_received_data.to_s.should
|
84
|
-
client_received_data.to_s.should
|
84
|
+
server_received_data.to_s.should eq('hello world')
|
85
|
+
client_received_data.to_s.should eq('dlrow olleh')
|
85
86
|
end
|
86
87
|
|
87
88
|
it 'fails to send a message when not using encryption' do
|
@@ -95,3 +96,7 @@ describe 'SSL' do
|
|
95
96
|
client.should be_closed
|
96
97
|
end
|
97
98
|
end
|
99
|
+
|
100
|
+
module SslSpec
|
101
|
+
DH_PARAMS = OpenSSL::PKey::DH.new(File.read(File.expand_path('../../resources/dh.pem', __FILE__)))
|
102
|
+
end
|
@@ -15,28 +15,28 @@ module Ione
|
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'can be initialized with bytes' do
|
18
|
-
described_class.new('hello').length.should
|
18
|
+
described_class.new('hello').length.should eq(5)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
describe '#length/#size/#bytesize' do
|
23
23
|
it 'returns the number of bytes in the buffer' do
|
24
24
|
buffer << 'foo'
|
25
|
-
buffer.length.should
|
25
|
+
buffer.length.should eq(3)
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'is zero initially' do
|
29
|
-
buffer.length.should
|
29
|
+
buffer.length.should eq(0)
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'is aliased as #size' do
|
33
33
|
buffer << 'foo'
|
34
|
-
buffer.size.should
|
34
|
+
buffer.size.should eq(3)
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'is aliased as #bytesize' do
|
38
38
|
buffer << 'foo'
|
39
|
-
buffer.bytesize.should
|
39
|
+
buffer.bytesize.should eq(3)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -67,19 +67,19 @@ module Ione
|
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'stores its bytes as binary' do
|
70
|
-
buffer.append('hällö').length.should
|
71
|
-
buffer.to_s.encoding.should
|
70
|
+
buffer.append('hällö').length.should eq(7)
|
71
|
+
buffer.to_s.encoding.should eq(::Encoding::BINARY)
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'handles appending with multibyte strings' do
|
75
75
|
buffer.append('hello')
|
76
76
|
buffer.append('würld')
|
77
|
-
buffer.to_s.should
|
77
|
+
buffer.to_s.should eq('hellowürld'.force_encoding(::Encoding::BINARY))
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'handles appending with another byte buffer' do
|
81
81
|
buffer.append('hello ').append(ByteBuffer.new('world'))
|
82
|
-
buffer.to_s.should
|
82
|
+
buffer.to_s.should eq('hello world')
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -105,7 +105,7 @@ module Ione
|
|
105
105
|
b2 = described_class.new
|
106
106
|
b1.append('foo')
|
107
107
|
b2.append('foo')
|
108
|
-
b1.should
|
108
|
+
b1.should eq(b2)
|
109
109
|
end
|
110
110
|
|
111
111
|
it 'is equal to another buffer when both are empty' do
|
@@ -121,7 +121,7 @@ module Ione
|
|
121
121
|
b2 = described_class.new
|
122
122
|
b1.append('foo')
|
123
123
|
b2.append('foo')
|
124
|
-
b1.hash.should
|
124
|
+
b1.hash.should eq(b2.hash)
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'is not equal to the hash code of another buffer with other contents' do
|
@@ -135,26 +135,26 @@ module Ione
|
|
135
135
|
it 'is equal to the hash code of another buffer when both are empty' do
|
136
136
|
b1 = described_class.new
|
137
137
|
b2 = described_class.new
|
138
|
-
b1.hash.should
|
138
|
+
b1.hash.should eq(b2.hash)
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
142
|
describe '#to_s' do
|
143
143
|
it 'returns the bytes' do
|
144
|
-
buffer.append('hello world').to_s.should
|
144
|
+
buffer.append('hello world').to_s.should eq('hello world')
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
148
|
describe '#to_str' do
|
149
149
|
it 'returns the bytes' do
|
150
|
-
buffer.append('hello world').to_str.should
|
150
|
+
buffer.append('hello world').to_str.should eq('hello world')
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
154
|
describe '#inspect' do
|
155
155
|
it 'returns the bytes wrapped in ByteBuffer(...)' do
|
156
156
|
buffer.append("\xca\xfe")
|
157
|
-
buffer.inspect.should
|
157
|
+
buffer.inspect.should eq('#<Ione::ByteBuffer: "\xCA\xFE">')
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
@@ -162,12 +162,12 @@ module Ione
|
|
162
162
|
it 'discards the specified number of bytes from the front of the buffer' do
|
163
163
|
buffer.append('hello world')
|
164
164
|
buffer.discard(4)
|
165
|
-
buffer.should
|
165
|
+
buffer.should eq(ByteBuffer.new('o world'))
|
166
166
|
end
|
167
167
|
|
168
168
|
it 'returns the byte buffer' do
|
169
169
|
buffer.append('hello world')
|
170
|
-
buffer.discard(4).should
|
170
|
+
buffer.discard(4).should eq(ByteBuffer.new('o world'))
|
171
171
|
end
|
172
172
|
|
173
173
|
it 'raises an error if the number of bytes in the buffer is fewer than the number to discard' do
|
@@ -185,14 +185,14 @@ module Ione
|
|
185
185
|
describe '#read' do
|
186
186
|
it 'returns the specified number of bytes, as a string' do
|
187
187
|
buffer.append('hello')
|
188
|
-
buffer.read(4).should
|
188
|
+
buffer.read(4).should eq('hell')
|
189
189
|
end
|
190
190
|
|
191
191
|
it 'removes the bytes from the buffer' do
|
192
192
|
buffer.append('hello')
|
193
193
|
buffer.read(3)
|
194
|
-
buffer.should
|
195
|
-
buffer.read(2).should
|
194
|
+
buffer.should eq(ByteBuffer.new('lo'))
|
195
|
+
buffer.read(2).should eq('lo')
|
196
196
|
end
|
197
197
|
|
198
198
|
it 'raises an error if there are not enough bytes' do
|
@@ -208,22 +208,22 @@ module Ione
|
|
208
208
|
|
209
209
|
it 'returns a string with binary encoding' do
|
210
210
|
buffer.append('hello')
|
211
|
-
buffer.read(4).encoding.should
|
211
|
+
buffer.read(4).encoding.should eq(::Encoding::BINARY)
|
212
212
|
buffer.append('∆')
|
213
|
-
buffer.read(2).encoding.should
|
213
|
+
buffer.read(2).encoding.should eq(::Encoding::BINARY)
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
217
|
describe '#read_int' do
|
218
218
|
it 'returns the first four bytes interpreted as an int' do
|
219
219
|
buffer.append("\xca\xfe\xba\xbe\x01")
|
220
|
-
buffer.read_int.should
|
220
|
+
buffer.read_int.should eq(0xcafebabe)
|
221
221
|
end
|
222
222
|
|
223
223
|
it 'removes the bytes from the buffer' do
|
224
224
|
buffer.append("\xca\xfe\xba\xbe\x01")
|
225
225
|
buffer.read_int
|
226
|
-
buffer.should
|
226
|
+
buffer.should eq(ByteBuffer.new("\x01"))
|
227
227
|
end
|
228
228
|
|
229
229
|
it 'raises an error if there are not enough bytes' do
|
@@ -235,13 +235,13 @@ module Ione
|
|
235
235
|
describe '#read_short' do
|
236
236
|
it 'returns the first two bytes interpreted as a short' do
|
237
237
|
buffer.append("\xca\xfe\x01")
|
238
|
-
buffer.read_short.should
|
238
|
+
buffer.read_short.should eq(0xcafe)
|
239
239
|
end
|
240
240
|
|
241
241
|
it 'removes the bytes from the buffer' do
|
242
242
|
buffer.append("\xca\xfe\x01")
|
243
243
|
buffer.read_short
|
244
|
-
buffer.should
|
244
|
+
buffer.should eq(ByteBuffer.new("\x01"))
|
245
245
|
end
|
246
246
|
|
247
247
|
it 'raises an error if there are not enough bytes' do
|
@@ -253,14 +253,14 @@ module Ione
|
|
253
253
|
describe '#read_byte' do
|
254
254
|
it 'returns the first bytes interpreted as an int' do
|
255
255
|
buffer.append("\x10\x01")
|
256
|
-
buffer.read_byte.should
|
257
|
-
buffer.read_byte.should
|
256
|
+
buffer.read_byte.should eq(0x10)
|
257
|
+
buffer.read_byte.should eq(0x01)
|
258
258
|
end
|
259
259
|
|
260
260
|
it 'removes the byte from the buffer' do
|
261
261
|
buffer.append("\x10\x01")
|
262
262
|
buffer.read_byte
|
263
|
-
buffer.should
|
263
|
+
buffer.should eq(ByteBuffer.new("\x01"))
|
264
264
|
end
|
265
265
|
|
266
266
|
it 'raises an error if there are no bytes' do
|
@@ -269,8 +269,8 @@ module Ione
|
|
269
269
|
|
270
270
|
it 'can interpret the byte as signed' do
|
271
271
|
buffer.append("\x81\x02")
|
272
|
-
buffer.read_byte(true).should
|
273
|
-
buffer.read_byte(true).should
|
272
|
+
buffer.read_byte(true).should eq(-127)
|
273
|
+
buffer.read_byte(true).should eq(2)
|
274
274
|
end
|
275
275
|
end
|
276
276
|
|
@@ -278,14 +278,14 @@ module Ione
|
|
278
278
|
it 'changes the bytes at the specified location' do
|
279
279
|
buffer.append('foo bar')
|
280
280
|
buffer.update(4, 'baz')
|
281
|
-
buffer.to_s.should
|
281
|
+
buffer.to_s.should eq('foo baz')
|
282
282
|
end
|
283
283
|
|
284
284
|
it 'handles updates after a read' do
|
285
285
|
buffer.append('foo bar')
|
286
286
|
buffer.read(1)
|
287
287
|
buffer.update(3, 'baz')
|
288
|
-
buffer.to_s.should
|
288
|
+
buffer.to_s.should eq('oo baz')
|
289
289
|
end
|
290
290
|
|
291
291
|
it 'handles updates after multiple reads and appends' do
|
@@ -295,7 +295,7 @@ module Ione
|
|
295
295
|
buffer.update(4, 'baz')
|
296
296
|
buffer.append('yyyy')
|
297
297
|
buffer.read(1)
|
298
|
-
buffer.to_s.should
|
298
|
+
buffer.to_s.should eq('o bbazyyyy')
|
299
299
|
end
|
300
300
|
|
301
301
|
it 'returns itself' do
|
@@ -335,12 +335,12 @@ module Ione
|
|
335
335
|
describe '#index' do
|
336
336
|
it 'returns the first index of the specified substring' do
|
337
337
|
buffer.append('fizz buzz')
|
338
|
-
buffer.index('zz').should
|
338
|
+
buffer.index('zz').should eq(2)
|
339
339
|
end
|
340
340
|
|
341
341
|
it 'returns the first index of the specified substring, after the specified index' do
|
342
342
|
buffer.append('fizz buzz')
|
343
|
-
buffer.index('zz', 3).should
|
343
|
+
buffer.index('zz', 3).should eq(7)
|
344
344
|
end
|
345
345
|
|
346
346
|
it 'returns nil when the substring is not found' do
|
@@ -352,7 +352,21 @@ module Ione
|
|
352
352
|
buffer.append('foo bar')
|
353
353
|
buffer.read(1)
|
354
354
|
buffer.append(' baz baz')
|
355
|
-
buffer.index('baz', 8).should
|
355
|
+
buffer.index('baz', 8).should eq(11)
|
356
|
+
end
|
357
|
+
|
358
|
+
it 'returns the first index when the matching substring spans the read and write buffer' do
|
359
|
+
buffer.append('foo bar')
|
360
|
+
buffer.read(1)
|
361
|
+
buffer.append('bar barbar')
|
362
|
+
buffer.index('barbar', 0).should eq(3)
|
363
|
+
end
|
364
|
+
|
365
|
+
it 'returns nil when the substring does not fit in the search space' do
|
366
|
+
buffer.append('foo')
|
367
|
+
buffer.read(1)
|
368
|
+
buffer.append('bar')
|
369
|
+
buffer.index('bar', 3).should be_nil
|
356
370
|
end
|
357
371
|
end
|
358
372
|
|