raktr 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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1 -0
- data/LICENSE.md +29 -0
- data/README.md +77 -0
- data/Rakefile +53 -0
- data/lib/raktr/connection/callbacks.rb +71 -0
- data/lib/raktr/connection/error.rb +120 -0
- data/lib/raktr/connection/peer_info.rb +90 -0
- data/lib/raktr/connection/tls.rb +164 -0
- data/lib/raktr/connection.rb +339 -0
- data/lib/raktr/global.rb +24 -0
- data/lib/raktr/iterator.rb +249 -0
- data/lib/raktr/queue.rb +89 -0
- data/lib/raktr/tasks/base.rb +57 -0
- data/lib/raktr/tasks/delayed.rb +33 -0
- data/lib/raktr/tasks/one_off.rb +30 -0
- data/lib/raktr/tasks/periodic.rb +58 -0
- data/lib/raktr/tasks/persistent.rb +29 -0
- data/lib/raktr/tasks.rb +105 -0
- data/lib/raktr/version.rb +13 -0
- data/lib/raktr.rb +707 -0
- data/spec/raktr/connection/tls_spec.rb +348 -0
- data/spec/raktr/connection_spec.rb +74 -0
- data/spec/raktr/iterator_spec.rb +203 -0
- data/spec/raktr/queue_spec.rb +91 -0
- data/spec/raktr/tasks/base.rb +8 -0
- data/spec/raktr/tasks/delayed_spec.rb +71 -0
- data/spec/raktr/tasks/one_off_spec.rb +66 -0
- data/spec/raktr/tasks/periodic_spec.rb +57 -0
- data/spec/raktr/tasks/persistent_spec.rb +54 -0
- data/spec/raktr/tasks_spec.rb +155 -0
- data/spec/raktr_spec.rb +20 -0
- data/spec/raktr_tls_spec.rb +20 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/fixtures/handlers/echo_client.rb +34 -0
- data/spec/support/fixtures/handlers/echo_client_tls.rb +10 -0
- data/spec/support/fixtures/handlers/echo_server.rb +12 -0
- data/spec/support/fixtures/handlers/echo_server_tls.rb +8 -0
- data/spec/support/fixtures/pems/cacert.pem +37 -0
- data/spec/support/fixtures/pems/client/cert.pem +37 -0
- data/spec/support/fixtures/pems/client/foo-cert.pem +39 -0
- data/spec/support/fixtures/pems/client/foo-key.pem +51 -0
- data/spec/support/fixtures/pems/client/key.pem +51 -0
- data/spec/support/fixtures/pems/server/cert.pem +37 -0
- data/spec/support/fixtures/pems/server/key.pem +51 -0
- data/spec/support/helpers/paths.rb +23 -0
- data/spec/support/helpers/utilities.rb +135 -0
- data/spec/support/lib/server_option_parser.rb +29 -0
- data/spec/support/lib/servers/runner.rb +13 -0
- data/spec/support/lib/servers.rb +133 -0
- data/spec/support/servers/echo.rb +14 -0
- data/spec/support/servers/echo_tls.rb +22 -0
- data/spec/support/servers/echo_unix.rb +14 -0
- data/spec/support/servers/echo_unix_tls.rb +22 -0
- data/spec/support/shared/connection.rb +696 -0
- data/spec/support/shared/raktr.rb +834 -0
- data/spec/support/shared/task.rb +21 -0
- metadata +140 -0
@@ -0,0 +1,348 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TLSHandler < Raktr::Connection
|
4
|
+
include TLS
|
5
|
+
|
6
|
+
attr_reader :received_data
|
7
|
+
attr_reader :error
|
8
|
+
|
9
|
+
def initialize( options = {} )
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_close( error )
|
14
|
+
@error = error
|
15
|
+
|
16
|
+
if @options[:on_error]
|
17
|
+
@options[:on_error].call error
|
18
|
+
end
|
19
|
+
|
20
|
+
@raktr.stop
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_read( data )
|
24
|
+
(@received_data ||= '' ) << data
|
25
|
+
|
26
|
+
return if !@options[:on_read]
|
27
|
+
@options[:on_read].call data
|
28
|
+
end
|
29
|
+
|
30
|
+
def on_connect
|
31
|
+
start_tls @options
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe Raktr::Connection::TLS do
|
37
|
+
before :all do
|
38
|
+
@host, @port = Servers.start( :echo_tls )
|
39
|
+
|
40
|
+
if Raktr.supports_unix_sockets?
|
41
|
+
_, port = Servers.start( :echo_unix_tls )
|
42
|
+
@unix_socket = port_to_socket( port )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
before :each do
|
47
|
+
@accept_q = Queue.new
|
48
|
+
@accepted = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
let(:unix_socket) { unix_connect( @unix_socket ) }
|
52
|
+
let(:unix_server_socket) { unix_server( port_to_socket( Servers.available_port ) ) }
|
53
|
+
|
54
|
+
let(:echo_client) { tcp_socket }
|
55
|
+
let(:echo_client_handler) { EchoClientTLS.new }
|
56
|
+
|
57
|
+
let(:peer_client_socket) { tcp_ssl_connect( host, port ) }
|
58
|
+
let(:peer_server_socket) do
|
59
|
+
s = tcp_ssl_server( host, port )
|
60
|
+
Thread.new do
|
61
|
+
begin
|
62
|
+
@accept_q << s.accept
|
63
|
+
rescue => e
|
64
|
+
p e
|
65
|
+
end
|
66
|
+
end
|
67
|
+
s
|
68
|
+
end
|
69
|
+
let(:accepted) { @accepted ||= @accept_q.pop }
|
70
|
+
|
71
|
+
let(:client_socket) { tcp_socket }
|
72
|
+
let(:server_socket) { tcp_server( host, port ) }
|
73
|
+
|
74
|
+
let(:connection) { TLSHandler.new }
|
75
|
+
let(:server_handler) { proc { TLSHandler.new } }
|
76
|
+
let(:raktr) { Raktr.new }
|
77
|
+
|
78
|
+
let(:client_valid_ssl_options) do
|
79
|
+
{
|
80
|
+
ca: pems_path + '/cacert.pem',
|
81
|
+
private_key: pems_path + '/client/key.pem',
|
82
|
+
certificate: pems_path + '/client/cert.pem'
|
83
|
+
}
|
84
|
+
end
|
85
|
+
let(:client_invalid_ssl_options) do
|
86
|
+
{
|
87
|
+
ca: pems_path + '/cacert.pem',
|
88
|
+
private_key: pems_path + '/client/foo-key.pem',
|
89
|
+
certificate: pems_path + '/client/foo-cert.pem'
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:server_valid_ssl_options) do
|
94
|
+
{
|
95
|
+
ca: pems_path + '/cacert.pem',
|
96
|
+
private_key: pems_path + '/server/key.pem',
|
97
|
+
certificate: pems_path + '/server/cert.pem'
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
it_should_behave_like 'Raktr::Connection'
|
102
|
+
|
103
|
+
context '#start_tls' do
|
104
|
+
let(:host) { '127.0.0.1' }
|
105
|
+
let(:port) { Servers.available_port }
|
106
|
+
let(:data) { "stuff\n" }
|
107
|
+
|
108
|
+
context 'when listening for a client' do
|
109
|
+
let(:client) do
|
110
|
+
tcp_ssl_connect( host, port, client_ssl_options )
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'without requiring SSL authentication' do
|
114
|
+
let(:server_ssl_options) { {} }
|
115
|
+
|
116
|
+
context 'and no options have been provided' do
|
117
|
+
let(:client_ssl_options) { {} }
|
118
|
+
|
119
|
+
it 'connects successfully' do
|
120
|
+
received_data = nil
|
121
|
+
options = server_ssl_options.merge(
|
122
|
+
on_read: proc do |received|
|
123
|
+
received_data = received
|
124
|
+
end
|
125
|
+
)
|
126
|
+
|
127
|
+
raktr.run_in_thread
|
128
|
+
|
129
|
+
raktr.listen( host, port, TLSHandler, options )
|
130
|
+
|
131
|
+
client.write data
|
132
|
+
sleep 1
|
133
|
+
|
134
|
+
raktr.stop
|
135
|
+
raktr.wait rescue Raktr::Error::NotRunning
|
136
|
+
|
137
|
+
expect(received_data).to eq data
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'and options have been provided' do
|
142
|
+
let(:client_ssl_options) { client_valid_ssl_options }
|
143
|
+
|
144
|
+
it "passes #{Raktr::Connection::Error::SSL} to #on_error" do
|
145
|
+
error = nil
|
146
|
+
|
147
|
+
options = server_ssl_options.merge(
|
148
|
+
on_error: proc do |e|
|
149
|
+
error ||= e
|
150
|
+
end
|
151
|
+
)
|
152
|
+
|
153
|
+
raktr.run_in_thread
|
154
|
+
|
155
|
+
raktr.listen( host, port, TLSHandler, options )
|
156
|
+
|
157
|
+
client_error = nil
|
158
|
+
begin
|
159
|
+
client
|
160
|
+
rescue => e
|
161
|
+
client_error = e
|
162
|
+
end
|
163
|
+
|
164
|
+
[OpenSSL::SSL::SSLError, Errno::ECONNRESET].should include client_error.class
|
165
|
+
|
166
|
+
raktr.wait rescue Raktr::Error::NotRunning
|
167
|
+
|
168
|
+
error.should be_kind_of Raktr::Connection::Error::SSL
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'while requiring SSL authentication' do
|
174
|
+
let(:server_ssl_options) { server_valid_ssl_options }
|
175
|
+
|
176
|
+
context 'and options have been provided' do
|
177
|
+
context 'and are valid' do
|
178
|
+
let(:client_ssl_options) { client_valid_ssl_options }
|
179
|
+
|
180
|
+
it 'connects successfully' do
|
181
|
+
received_data = nil
|
182
|
+
options = server_ssl_options.merge(
|
183
|
+
on_read: proc do |received|
|
184
|
+
received_data = received
|
185
|
+
end
|
186
|
+
)
|
187
|
+
|
188
|
+
raktr.run_in_thread
|
189
|
+
|
190
|
+
raktr.listen( host, port, TLSHandler, options )
|
191
|
+
|
192
|
+
client.write data
|
193
|
+
|
194
|
+
sleep 0.1 while !received_data
|
195
|
+
received_data.should == data
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
context 'and are invalid' do
|
200
|
+
let(:client_ssl_options) { client_invalid_ssl_options }
|
201
|
+
|
202
|
+
it "passes #{Raktr::Connection::Error::SSL} to #on_error" do
|
203
|
+
error = nil
|
204
|
+
|
205
|
+
options = server_ssl_options.merge(
|
206
|
+
on_error: proc do |e|
|
207
|
+
error ||= e
|
208
|
+
end
|
209
|
+
)
|
210
|
+
|
211
|
+
raktr.run_in_thread
|
212
|
+
raktr.listen( host, port, TLSHandler, options )
|
213
|
+
|
214
|
+
client_error = nil
|
215
|
+
begin
|
216
|
+
client
|
217
|
+
rescue => e
|
218
|
+
client_error = e
|
219
|
+
end
|
220
|
+
|
221
|
+
[OpenSSL::SSL::SSLError, Errno::ECONNRESET].should include client_error.class
|
222
|
+
|
223
|
+
raktr.wait rescue Raktr::Error::NotRunning
|
224
|
+
|
225
|
+
error.should be_kind_of Raktr::Connection::Error::SSL
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
context 'and no options have been provided' do
|
231
|
+
let(:client_ssl_options) { {} }
|
232
|
+
|
233
|
+
it "passes #{Raktr::Connection::Error::SSL} to #on_error" do
|
234
|
+
error = nil
|
235
|
+
|
236
|
+
options = server_ssl_options.merge(
|
237
|
+
on_error: proc do |e|
|
238
|
+
error ||= e
|
239
|
+
end
|
240
|
+
)
|
241
|
+
|
242
|
+
raktr.run_in_thread
|
243
|
+
|
244
|
+
raktr.listen( host, port, TLSHandler, options )
|
245
|
+
|
246
|
+
client_error = nil
|
247
|
+
begin
|
248
|
+
client
|
249
|
+
rescue => e
|
250
|
+
client_error = e
|
251
|
+
end
|
252
|
+
|
253
|
+
[OpenSSL::SSL::SSLError, Errno::ECONNRESET].should include client_error.class
|
254
|
+
|
255
|
+
raktr.wait rescue Raktr::Error::NotRunning
|
256
|
+
|
257
|
+
error.should be_kind_of Raktr::Connection::Error::SSL
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context 'when connecting to a server' do
|
264
|
+
let(:server) do
|
265
|
+
s = tcp_ssl_server( host, port, server_ssl_options )
|
266
|
+
Thread.new do
|
267
|
+
begin
|
268
|
+
@accept_q << s.accept
|
269
|
+
rescue => e
|
270
|
+
# ap e
|
271
|
+
end
|
272
|
+
end
|
273
|
+
s
|
274
|
+
end
|
275
|
+
|
276
|
+
before :each do
|
277
|
+
server
|
278
|
+
end
|
279
|
+
|
280
|
+
context 'that does not require SSL authentication' do
|
281
|
+
let(:server_ssl_options) { {} }
|
282
|
+
|
283
|
+
context 'and no options have been provided' do
|
284
|
+
it 'connects successfully' do
|
285
|
+
received = nil
|
286
|
+
Thread.new do
|
287
|
+
received = accepted.gets
|
288
|
+
raktr.stop
|
289
|
+
end
|
290
|
+
|
291
|
+
raktr.run do
|
292
|
+
connection = raktr.connect( host, port, TLSHandler )
|
293
|
+
connection.write data
|
294
|
+
end
|
295
|
+
|
296
|
+
received.should == data
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context 'that requires SSL authentication' do
|
302
|
+
let(:server_ssl_options) { server_valid_ssl_options }
|
303
|
+
|
304
|
+
context 'and no options have been provided' do
|
305
|
+
it "passes #{Raktr::Connection::Error} to #on_error" do
|
306
|
+
connection = nil
|
307
|
+
raktr.run do
|
308
|
+
connection = raktr.connect( host, port, TLSHandler )
|
309
|
+
end
|
310
|
+
|
311
|
+
connection.error.should be_kind_of Raktr::Connection::Error
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context 'and options have been provided' do
|
316
|
+
context 'and are valid' do
|
317
|
+
it 'connects successfully' do
|
318
|
+
received = nil
|
319
|
+
t = Thread.new do
|
320
|
+
received = accepted.gets
|
321
|
+
raktr.stop
|
322
|
+
end
|
323
|
+
|
324
|
+
raktr.run do
|
325
|
+
connection = raktr.connect( host, port, TLSHandler, client_valid_ssl_options )
|
326
|
+
connection.write data
|
327
|
+
end
|
328
|
+
|
329
|
+
sleep 1
|
330
|
+
expect(received).to eq data
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
context 'and are invalid' do
|
335
|
+
it "passes #{Raktr::Connection::Error} to #on_error" do
|
336
|
+
connection = nil
|
337
|
+
raktr.run do
|
338
|
+
connection = raktr.connect( host, port, TLSHandler, client_invalid_ssl_options )
|
339
|
+
end
|
340
|
+
|
341
|
+
connection.error.should be_kind_of Raktr::Connection::Error
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
class Handler < Raktr::Connection
|
6
|
+
attr_reader :received_data
|
7
|
+
attr_reader :error
|
8
|
+
|
9
|
+
def initialize( options = {} )
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_close( error )
|
14
|
+
@error = error
|
15
|
+
|
16
|
+
if @options[:on_error]
|
17
|
+
@options[:on_error].call error
|
18
|
+
end
|
19
|
+
|
20
|
+
@raktr.stop
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_read( data )
|
24
|
+
(@received_data ||= '' ) << data
|
25
|
+
|
26
|
+
return if !@options[:on_read]
|
27
|
+
@options[:on_read].call data
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe Raktr::Connection do
|
33
|
+
before :all do
|
34
|
+
@host, @port = Servers.start( :echo )
|
35
|
+
|
36
|
+
if Raktr.supports_unix_sockets?
|
37
|
+
_, port = Servers.start( :echo_unix )
|
38
|
+
@unix_socket = port_to_socket( port )
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
before :each do
|
43
|
+
@accept_q = Queue.new
|
44
|
+
@accepted = nil
|
45
|
+
end
|
46
|
+
|
47
|
+
let(:unix_socket) { unix_connect( @unix_socket ) }
|
48
|
+
let(:unix_server_socket) { unix_server( port_to_socket( Servers.available_port ) ) }
|
49
|
+
|
50
|
+
let(:echo_client) { tcp_socket }
|
51
|
+
let(:echo_client_handler) { EchoClient.new }
|
52
|
+
|
53
|
+
let(:peer_client_socket) { tcp_connect( host, port ) }
|
54
|
+
let(:peer_server_socket) do
|
55
|
+
s = tcp_server( host, port )
|
56
|
+
Thread.new do
|
57
|
+
begin
|
58
|
+
@accept_q << s.accept
|
59
|
+
rescue => e
|
60
|
+
ap e
|
61
|
+
end
|
62
|
+
end
|
63
|
+
s
|
64
|
+
end
|
65
|
+
let(:accepted) { @accepted ||= @accept_q.pop }
|
66
|
+
|
67
|
+
let(:client_socket) { tcp_socket }
|
68
|
+
let(:server_socket) { tcp_server( host, port ) }
|
69
|
+
|
70
|
+
let(:connection) { Handler.new }
|
71
|
+
let(:server_handler) { proc { Handler.new } }
|
72
|
+
|
73
|
+
it_should_behave_like 'Raktr::Connection'
|
74
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Raktr::Iterator do
|
4
|
+
|
5
|
+
def get_iterator
|
6
|
+
described_class.new raktr, list, concurrency
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_raktr
|
10
|
+
Raktr.new
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:raktr) { get_raktr }
|
14
|
+
let(:list) { %w(one two three four) }
|
15
|
+
let(:concurrency) { list.size }
|
16
|
+
subject { get_iterator }
|
17
|
+
|
18
|
+
describe '#initialize' do
|
19
|
+
context 'when the list does not respond to #to_a' do
|
20
|
+
let(:list) { 'stuff' }
|
21
|
+
|
22
|
+
it "raises #{ArgumentError}" do
|
23
|
+
expect { subject }.to raise_error ArgumentError
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when the concurrency is' do
|
28
|
+
context '0' do
|
29
|
+
let(:concurrency) { 0 }
|
30
|
+
|
31
|
+
it "raises #{ArgumentError}" do
|
32
|
+
expect { subject }.to raise_error ArgumentError
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'less than 0' do
|
37
|
+
let(:concurrency) { -1 }
|
38
|
+
|
39
|
+
it "raises #{ArgumentError}" do
|
40
|
+
expect { subject }.to raise_error ArgumentError
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#raktr' do
|
47
|
+
it 'returns the associated Reactor' do
|
48
|
+
subject.raktr.should == raktr
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#concurrency' do
|
53
|
+
let(:concurrency){ 3 }
|
54
|
+
it 'returns the configured Reactor' do
|
55
|
+
subject.concurrency.should == concurrency
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#concurrency=' do
|
60
|
+
it 'sets the iterator concurrency' do
|
61
|
+
runner = proc do |concurrency|
|
62
|
+
start = nil
|
63
|
+
finish = nil
|
64
|
+
|
65
|
+
iter = described_class.new( get_raktr, list, concurrency )
|
66
|
+
iter.concurrency = concurrency
|
67
|
+
|
68
|
+
iter.raktr.run do
|
69
|
+
iter.each do |item, iterator|
|
70
|
+
start ||= Time.now
|
71
|
+
|
72
|
+
iter.raktr.delay 1 do
|
73
|
+
if item == list.last
|
74
|
+
finish = Time.now
|
75
|
+
iter.raktr.stop
|
76
|
+
end
|
77
|
+
|
78
|
+
iterator.next
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
finish - start
|
84
|
+
end
|
85
|
+
|
86
|
+
high_concurrency = list.size
|
87
|
+
low_concurrency = 1
|
88
|
+
|
89
|
+
high_concurrency_time, low_concurrency_time =
|
90
|
+
runner.call( high_concurrency ), runner.call( low_concurrency )
|
91
|
+
|
92
|
+
low_concurrency_time.should > high_concurrency_time
|
93
|
+
|
94
|
+
(low_concurrency_time - high_concurrency_time).to_i.should ==
|
95
|
+
high_concurrency - low_concurrency
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'when it is larger than the list size' do
|
99
|
+
let(:concurrency){ 30 }
|
100
|
+
|
101
|
+
it 'does stuff' do
|
102
|
+
iterated = []
|
103
|
+
|
104
|
+
raktr.run do
|
105
|
+
subject.each do |item, iterator|
|
106
|
+
iterated << item
|
107
|
+
|
108
|
+
raktr.delay 1 do
|
109
|
+
raktr.stop if item == list.last
|
110
|
+
iterator.next
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
list.should == iterated
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '#each' do
|
121
|
+
it 'iterates over the list' do
|
122
|
+
iterated = []
|
123
|
+
|
124
|
+
raktr.run do
|
125
|
+
subject.each do |item, iterator|
|
126
|
+
iterated << item
|
127
|
+
|
128
|
+
raktr.stop if item == list.last
|
129
|
+
raktr.delay 1 do
|
130
|
+
iterator.next
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
list.should == iterated
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'when an \'after\' proc has been provided' do
|
139
|
+
it 'is called when the iteration is complete' do
|
140
|
+
iterated = []
|
141
|
+
|
142
|
+
raktr.run do
|
143
|
+
subject.each(
|
144
|
+
proc do |item, iterator|
|
145
|
+
iterated << item
|
146
|
+
raktr.delay 1 do
|
147
|
+
iterator.next
|
148
|
+
end
|
149
|
+
end,
|
150
|
+
proc do
|
151
|
+
raktr.stop
|
152
|
+
end
|
153
|
+
)
|
154
|
+
end
|
155
|
+
|
156
|
+
list.should == iterated
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '#map' do
|
162
|
+
it 'collects the results of each iteration' do
|
163
|
+
results = nil
|
164
|
+
|
165
|
+
raktr.run do
|
166
|
+
subject.map(
|
167
|
+
proc do |string, iterator|
|
168
|
+
raktr.delay 1 do
|
169
|
+
iterator.return( string.size )
|
170
|
+
end
|
171
|
+
end,
|
172
|
+
proc do |res|
|
173
|
+
results = res
|
174
|
+
raktr.stop
|
175
|
+
end
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
results.should == list.map(&:size)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe '#inject' do
|
184
|
+
it 'injects the results of the iteration into the given object' do
|
185
|
+
results = nil
|
186
|
+
|
187
|
+
raktr.run do
|
188
|
+
subject.inject( {},
|
189
|
+
proc do |hash, string, iterator|
|
190
|
+
hash.merge!( string => string.size )
|
191
|
+
iterator.return( hash )
|
192
|
+
end,
|
193
|
+
proc do |res|
|
194
|
+
results = res
|
195
|
+
raktr.stop
|
196
|
+
end
|
197
|
+
)
|
198
|
+
end
|
199
|
+
|
200
|
+
results.should == list.inject({}) { |h, string| h.merge( string => string.size ) }
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Raktr::Queue do
|
4
|
+
let(:raktr) { Raktr.new }
|
5
|
+
subject { described_class.new raktr }
|
6
|
+
|
7
|
+
describe '#initialize' do
|
8
|
+
it 'sets the associated raktr' do
|
9
|
+
subject.raktr.should == raktr
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#pop' do
|
14
|
+
context 'when the queue is not empty' do
|
15
|
+
it 'passes the next item to the block' do
|
16
|
+
passed_item = nil
|
17
|
+
|
18
|
+
raktr.run do
|
19
|
+
subject << :my_item
|
20
|
+
subject.pop do |item|
|
21
|
+
passed_item = item
|
22
|
+
raktr.stop
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
passed_item.should == :my_item
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when the queue is empty' do
|
31
|
+
it 'assigns a block to handle new items' do
|
32
|
+
passed_item = nil
|
33
|
+
|
34
|
+
raktr.run do
|
35
|
+
subject.pop do |item|
|
36
|
+
passed_item = item
|
37
|
+
raktr.stop
|
38
|
+
end
|
39
|
+
|
40
|
+
subject << :my_item
|
41
|
+
end
|
42
|
+
|
43
|
+
passed_item.should == :my_item
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#empty?' do
|
49
|
+
context 'when the queue is empty' do
|
50
|
+
it 'returns true' do
|
51
|
+
subject.should be_empty
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when the queue is not empty' do
|
56
|
+
it 'returns false' do
|
57
|
+
raktr.run_block do
|
58
|
+
subject << nil
|
59
|
+
subject.should_not be_empty
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#size' do
|
66
|
+
it 'returns the queue size' do
|
67
|
+
raktr.run_block do
|
68
|
+
2.times { |i| subject << i }
|
69
|
+
subject.size.should == 2
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#num_waiting' do
|
75
|
+
context 'when no jobs are available to handle new items' do
|
76
|
+
it 'returns 0' do
|
77
|
+
subject.num_waiting.should == 0
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when there are jobs waiting to handle new items' do
|
82
|
+
it 'returns a count' do
|
83
|
+
raktr.run_block do
|
84
|
+
3.times { subject.pop{} }
|
85
|
+
subject.num_waiting.should == 3
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|