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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1 -0
  3. data/LICENSE.md +29 -0
  4. data/README.md +77 -0
  5. data/Rakefile +53 -0
  6. data/lib/raktr/connection/callbacks.rb +71 -0
  7. data/lib/raktr/connection/error.rb +120 -0
  8. data/lib/raktr/connection/peer_info.rb +90 -0
  9. data/lib/raktr/connection/tls.rb +164 -0
  10. data/lib/raktr/connection.rb +339 -0
  11. data/lib/raktr/global.rb +24 -0
  12. data/lib/raktr/iterator.rb +249 -0
  13. data/lib/raktr/queue.rb +89 -0
  14. data/lib/raktr/tasks/base.rb +57 -0
  15. data/lib/raktr/tasks/delayed.rb +33 -0
  16. data/lib/raktr/tasks/one_off.rb +30 -0
  17. data/lib/raktr/tasks/periodic.rb +58 -0
  18. data/lib/raktr/tasks/persistent.rb +29 -0
  19. data/lib/raktr/tasks.rb +105 -0
  20. data/lib/raktr/version.rb +13 -0
  21. data/lib/raktr.rb +707 -0
  22. data/spec/raktr/connection/tls_spec.rb +348 -0
  23. data/spec/raktr/connection_spec.rb +74 -0
  24. data/spec/raktr/iterator_spec.rb +203 -0
  25. data/spec/raktr/queue_spec.rb +91 -0
  26. data/spec/raktr/tasks/base.rb +8 -0
  27. data/spec/raktr/tasks/delayed_spec.rb +71 -0
  28. data/spec/raktr/tasks/one_off_spec.rb +66 -0
  29. data/spec/raktr/tasks/periodic_spec.rb +57 -0
  30. data/spec/raktr/tasks/persistent_spec.rb +54 -0
  31. data/spec/raktr/tasks_spec.rb +155 -0
  32. data/spec/raktr_spec.rb +20 -0
  33. data/spec/raktr_tls_spec.rb +20 -0
  34. data/spec/spec_helper.rb +17 -0
  35. data/spec/support/fixtures/handlers/echo_client.rb +34 -0
  36. data/spec/support/fixtures/handlers/echo_client_tls.rb +10 -0
  37. data/spec/support/fixtures/handlers/echo_server.rb +12 -0
  38. data/spec/support/fixtures/handlers/echo_server_tls.rb +8 -0
  39. data/spec/support/fixtures/pems/cacert.pem +37 -0
  40. data/spec/support/fixtures/pems/client/cert.pem +37 -0
  41. data/spec/support/fixtures/pems/client/foo-cert.pem +39 -0
  42. data/spec/support/fixtures/pems/client/foo-key.pem +51 -0
  43. data/spec/support/fixtures/pems/client/key.pem +51 -0
  44. data/spec/support/fixtures/pems/server/cert.pem +37 -0
  45. data/spec/support/fixtures/pems/server/key.pem +51 -0
  46. data/spec/support/helpers/paths.rb +23 -0
  47. data/spec/support/helpers/utilities.rb +135 -0
  48. data/spec/support/lib/server_option_parser.rb +29 -0
  49. data/spec/support/lib/servers/runner.rb +13 -0
  50. data/spec/support/lib/servers.rb +133 -0
  51. data/spec/support/servers/echo.rb +14 -0
  52. data/spec/support/servers/echo_tls.rb +22 -0
  53. data/spec/support/servers/echo_unix.rb +14 -0
  54. data/spec/support/servers/echo_unix_tls.rb +22 -0
  55. data/spec/support/shared/connection.rb +696 -0
  56. data/spec/support/shared/raktr.rb +834 -0
  57. data/spec/support/shared/task.rb +21 -0
  58. metadata +140 -0
@@ -0,0 +1,696 @@
1
+ shared_examples_for 'Raktr::Connection' do
2
+ after(:each) do
3
+ next if !@raktr
4
+
5
+ if @raktr.running?
6
+ @raktr.stop
7
+ end
8
+
9
+ @raktr = nil
10
+ end
11
+
12
+ let(:host){ '127.0.0.1' }
13
+ let(:port){ Servers.available_port }
14
+ let(:raktr) { @raktr = Raktr.new }
15
+ let(:block_size) { Raktr::Connection::BLOCK_SIZE }
16
+ let(:data) { 'b' * 5 * block_size }
17
+ let(:configured) do
18
+ connection.raktr = raktr
19
+ connection.configure(
20
+ host: host,
21
+ port: port,
22
+ socket: socket,
23
+ role: role,
24
+ server_handler: server_handler
25
+ )
26
+
27
+ if role == :client
28
+ while !connection.connected?
29
+ begin
30
+ IO.select( [connection.socket], [connection.socket], nil, 0.1 )
31
+ rescue => e
32
+ ap e
33
+ break
34
+ end
35
+
36
+ connection._connect
37
+ end
38
+ end
39
+
40
+ connection
41
+ end
42
+
43
+ describe '#configure' do
44
+ let(:socket) { client_socket }
45
+ let(:role) { :client }
46
+
47
+ it 'sets #socket' do
48
+ peer_server_socket
49
+ configured.socket.to_io.should == socket
50
+ end
51
+
52
+ it 'sets #role' do
53
+ peer_server_socket
54
+ configured.role.should == :client
55
+ end
56
+
57
+ it 'attaches it to the reactor' do
58
+ # Just to initialize it.
59
+ peer_server_socket
60
+
61
+ raktr.run_block do
62
+ raktr.attach configured
63
+
64
+ c_socket, c_connection = raktr.connections.first.to_a
65
+
66
+ c_socket.to_io.should == socket
67
+ c_connection.should == connection
68
+ end
69
+ end
70
+
71
+ # it 'calls #on_connect' do
72
+ # peer_server_socket
73
+ # connection.should receive(:on_connect)
74
+ # connection.raktr = reactor
75
+ # connection.configure socket: socket, role: role
76
+ # end
77
+ end
78
+
79
+ describe '#unix?' do
80
+ context 'when using an IP socket' do
81
+ let(:connection) { echo_client_handler }
82
+ let(:role) { :client }
83
+ let(:socket) { client_socket }
84
+
85
+ it 'returns false' do
86
+ peer_server_socket
87
+ configured
88
+ configured.should_not be_unix
89
+ end
90
+ end
91
+
92
+ context 'when using UNIX-domain socket',
93
+ if: Raktr.supports_unix_sockets? do
94
+
95
+ let(:connection) { echo_client_handler }
96
+ let(:role) { :client }
97
+ let(:socket) { unix_socket }
98
+
99
+ it 'returns true' do
100
+ peer_server_socket
101
+ configured
102
+ configured.should be_unix
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '#inet?' do
108
+ context 'when using an IP socket' do
109
+ let(:connection) { echo_client_handler }
110
+ let(:role) { :client }
111
+ let(:socket) { client_socket }
112
+
113
+ it 'returns false' do
114
+ peer_server_socket
115
+ configured
116
+ configured.should be_inet
117
+ end
118
+ end
119
+
120
+ context 'when using UNIX-domain socket',
121
+ if: Raktr.supports_unix_sockets? do
122
+
123
+ let(:connection) { echo_client_handler }
124
+ let(:role) { :client }
125
+ let(:socket) { unix_socket }
126
+
127
+ it 'returns false' do
128
+ peer_server_socket
129
+ configured
130
+ configured.should_not be_inet
131
+ end
132
+ end
133
+ end
134
+
135
+ describe '#to_io' do
136
+ context 'when the connection is a server listener' do
137
+ let(:role) { :server }
138
+
139
+ context 'when using an IP socket' do
140
+ let(:socket) { server_socket }
141
+
142
+ it 'returns TCPServer' do
143
+ raktr.run_in_thread
144
+ configured
145
+
146
+ configured.to_io.should be_kind_of TCPServer
147
+ end
148
+ end
149
+
150
+ context 'when using UNIX-domain socket',
151
+ if: Raktr.supports_unix_sockets? do
152
+
153
+ let(:connection) { echo_client_handler }
154
+ let(:socket) { unix_server_socket }
155
+
156
+ it 'returns UNIXServer' do
157
+ peer_server_socket
158
+ configured.to_io.should be_instance_of UNIXServer
159
+ end
160
+ end
161
+ end
162
+
163
+ context 'when the connection is a server handler' do
164
+ let(:role) { :server }
165
+
166
+ context 'when using an IP socket' do
167
+ let(:socket) { server_socket }
168
+
169
+ it 'returns TCPSocket' do
170
+ raktr.run_in_thread
171
+ configured
172
+
173
+ Thread.new do
174
+ client = peer_client_socket
175
+ client.write( data )
176
+ end
177
+
178
+ IO.select [configured.socket]
179
+ configured.accept.to_io.should be_kind_of TCPSocket
180
+ end
181
+ end
182
+ end
183
+
184
+ context 'when the connection is a client' do
185
+ context 'when using an IP socket' do
186
+ let(:role) { :client }
187
+ let(:socket) { client_socket }
188
+
189
+ it 'returns TCPSocket' do
190
+ peer_server_socket
191
+ configured.to_io.should be_instance_of Socket
192
+ end
193
+ end
194
+
195
+ context 'when using UNIX-domain socket',
196
+ if: Raktr.supports_unix_sockets? do
197
+
198
+ let(:role) { :client }
199
+ let(:socket) { unix_socket }
200
+
201
+ it 'returns UNIXSocket' do
202
+ peer_server_socket
203
+ configured.to_io.should be_instance_of UNIXSocket
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ describe '#listener?' do
210
+ context 'when the connection is a server listener' do
211
+ let(:role) { :server }
212
+
213
+ context 'when using an IP socket' do
214
+ let(:socket) { server_socket }
215
+
216
+ it 'returns true' do
217
+ raktr.run_in_thread
218
+ configured
219
+
220
+ configured.should be_listener
221
+ end
222
+ end
223
+
224
+ context 'when using UNIX-domain socket',
225
+ if: Raktr.supports_unix_sockets? do
226
+
227
+ let(:connection) { echo_client_handler }
228
+ let(:socket) { unix_server_socket }
229
+
230
+ it 'returns true' do
231
+ peer_server_socket
232
+ configured.should be_listener
233
+ end
234
+ end
235
+ end
236
+
237
+ context 'when the connection is a server handler' do
238
+ let(:role) { :server }
239
+
240
+ context 'when using an IP socket' do
241
+ let(:socket) { server_socket }
242
+
243
+ it 'returns false' do
244
+ raktr.run_in_thread
245
+ configured
246
+
247
+ Thread.new do
248
+ client = peer_client_socket
249
+ client.write( data )
250
+ end
251
+
252
+ IO.select [configured.socket]
253
+ configured.accept.should_not be_listener
254
+ end
255
+ end
256
+ end
257
+
258
+ context 'when the connection is a client' do
259
+ context 'when using an IP socket' do
260
+ let(:role) { :client }
261
+ let(:socket) { client_socket }
262
+
263
+ it 'returns false' do
264
+ peer_server_socket
265
+ configured.should_not be_listener
266
+ end
267
+ end
268
+
269
+ context 'when using UNIX-domain socket',
270
+ if: Raktr.supports_unix_sockets? do
271
+
272
+ let(:role) { :client }
273
+ let(:socket) { unix_socket }
274
+
275
+ it 'returns false' do
276
+ peer_server_socket
277
+ configured.should_not be_listener
278
+ end
279
+ end
280
+ end
281
+ end
282
+
283
+ describe '#attach' do
284
+ let(:socket) { client_socket }
285
+ let(:role) { :client }
286
+
287
+ it 'attaches the connection to a Reactor' do
288
+ peer_server_socket
289
+ configured
290
+
291
+ raktr.run_in_thread
292
+
293
+ connection.attach( raktr ).should be_truthy
294
+ sleep 1
295
+
296
+ raktr.attached?( configured ).should be_truthy
297
+ end
298
+
299
+ it 'calls #on_attach' do
300
+ peer_server_socket
301
+ configured
302
+
303
+ raktr.run_in_thread
304
+
305
+ configured.should receive(:on_attach)
306
+ connection.attach raktr
307
+
308
+ sleep 1
309
+ end
310
+
311
+ context 'when the connection is already attached' do
312
+ context 'to the same Reactor' do
313
+ it 'does nothing' do
314
+ peer_server_socket
315
+ configured
316
+
317
+ raktr.run_in_thread
318
+
319
+ connection.attach raktr
320
+ sleep 0.1 while connection.detached?
321
+
322
+ connection.attach( raktr ).should be_falsey
323
+ end
324
+ end
325
+
326
+ context 'to a different Reactor' do
327
+ it 'detaches it first' do
328
+ peer_server_socket
329
+ configured
330
+
331
+ raktr.run_in_thread
332
+
333
+ connection.attach raktr
334
+ sleep 0.1 while connection.detached?
335
+
336
+ r = Raktr.new
337
+ r.run_in_thread
338
+
339
+ configured.should receive(:on_detach)
340
+ connection.attach( r ).should be_truthy
341
+
342
+ sleep 2
343
+
344
+ r.attached?( configured ).should be_truthy
345
+ end
346
+ end
347
+ end
348
+ end
349
+
350
+ describe '#detach' do
351
+ let(:socket) { client_socket }
352
+ let(:role) { :client }
353
+
354
+ it 'detaches the connection from the reactor' do
355
+ peer_server_socket
356
+ configured
357
+
358
+ raktr.run_in_thread
359
+
360
+ connection.attach raktr
361
+ sleep 0.1 while !connection.attached?
362
+
363
+ connection.detach
364
+ sleep 0.1 while connection.attached?
365
+
366
+ raktr.attached?( configured ).should be_falsey
367
+ end
368
+
369
+ it 'calls #on_detach' do
370
+ peer_server_socket
371
+ configured
372
+
373
+ raktr.run_in_thread
374
+
375
+ connection.attach raktr
376
+ sleep 0.1 while !connection.attached?
377
+
378
+ configured.should receive(:on_detach)
379
+ connection.detach
380
+
381
+ sleep 0.1 while connection.attached?
382
+ end
383
+ end
384
+
385
+ describe '#write' do
386
+ let(:connection) { echo_client_handler }
387
+ let(:role) { :client }
388
+ let(:socket) { client_socket }
389
+
390
+ it 'appends the given data to the send-buffer' do
391
+ peer_server_socket
392
+ raktr.run_in_thread
393
+
394
+ configured
395
+
396
+ all_read = false
397
+ received = ''
398
+
399
+ t = Thread.new do
400
+ sleep 0.1 while !accepted
401
+ received << accepted.read( data.size ) while received.size != data.size
402
+ all_read = true
403
+ end
404
+
405
+ configured.write data
406
+
407
+ # Wait for the reactor to update the buffer.
408
+ sleep 0.1 while !configured.has_outgoing_data?
409
+
410
+ while !all_read
411
+ IO.select( nil, [configured.socket], nil, 1 ) rescue IOError
412
+ next if configured._write != 0
413
+
414
+ IO.select( [configured.socket], nil, nil, 1 ) rescue IOError
415
+ end
416
+
417
+ t.join
418
+
419
+ received.should == data
420
+ end
421
+ end
422
+
423
+ describe '#accept' do
424
+ let(:socket) { server_socket }
425
+ let(:role) { :server }
426
+ let(:data) { "data\n" }
427
+
428
+ it 'accepts a new client connection' do
429
+ raktr.run_in_thread
430
+ configured
431
+
432
+ client = nil
433
+
434
+ Thread.new do
435
+ client = peer_client_socket
436
+ client.write( data )
437
+ end
438
+
439
+ IO.select [configured.socket]
440
+ server = configured.accept
441
+
442
+ server.should be_kind_of connection.class
443
+
444
+ IO.select [server.socket]
445
+
446
+ sleep 0.1 while !server.received_data
447
+ server.received_data.should == data
448
+
449
+ client.close
450
+ end
451
+ end
452
+
453
+ describe '#_read' do
454
+ context 'when the connection is a socket' do
455
+ let(:connection) { echo_client_handler }
456
+ let(:role) { :client }
457
+ let(:socket) { client_socket }
458
+
459
+ it "reads a maximum of #{Raktr::Connection::BLOCK_SIZE} bytes at a time" do
460
+ peer_server_socket
461
+ configured
462
+
463
+ Thread.new do
464
+ sleep 0.1 while !accepted
465
+ accepted.write data
466
+ accepted.flush
467
+ end
468
+
469
+ while configured.received_data.to_s.size != data.size
470
+ pre = configured.received_data.to_s.size
471
+ configured._read
472
+ (configured.received_data.to_s.size - pre).should <= block_size
473
+ end
474
+
475
+ configured.received_data.size.should == data.size
476
+ end
477
+
478
+ it 'passes the data to #on_read' do
479
+ peer_server_socket
480
+ configured
481
+
482
+ data = "test\n"
483
+
484
+ Thread.new do
485
+ sleep 0.1 while !accepted
486
+ accepted.write data
487
+ accepted.flush
488
+ end
489
+
490
+ configured._read while !configured.received_data
491
+ configured.received_data.should == data
492
+ end
493
+ end
494
+
495
+ context 'when the connection is a server' do
496
+ let(:socket) { server_socket }
497
+ let(:role) { :server }
498
+ let(:data) { "data\n" }
499
+
500
+ it 'accepts a new client connection' do
501
+ configured
502
+ raktr.run_in_thread
503
+
504
+ client = nil
505
+
506
+ q = Queue.new
507
+ Thread.new do
508
+ client = peer_client_socket
509
+ q << client.write( data )
510
+ end
511
+
512
+ IO.select [configured.socket]
513
+ server = configured._read
514
+
515
+ server.should be_kind_of connection.class
516
+
517
+ sleep 0.1 while !server.received_data
518
+ server.received_data.should == data
519
+
520
+ client.close
521
+ end
522
+ end
523
+ end
524
+
525
+ describe '#_write' do
526
+ before :each do
527
+ raktr.run_in_thread
528
+ end
529
+
530
+ let(:port) { @port }
531
+ let(:host) { @host }
532
+ let(:connection) { echo_client_handler }
533
+ let(:role) { :client }
534
+ let(:socket) { echo_client }
535
+
536
+ it "consumes the write-buffer a maximum of #{Raktr::Connection::BLOCK_SIZE} bytes at a time" do
537
+ configured.write data
538
+ sleep 0.1 while !configured.has_outgoing_data?
539
+
540
+ writes = 0
541
+ while configured.has_outgoing_data?
542
+ IO.select( nil, [configured.socket] )
543
+ if (written = configured._write) == 0
544
+ IO.select( [configured.socket], nil, nil, 1 )
545
+ next
546
+ end
547
+
548
+ written.should <= block_size
549
+ writes += 1
550
+ end
551
+
552
+ writes.should > 1
553
+ end
554
+
555
+ it 'calls #on_write' do
556
+ configured.write data
557
+ sleep 0.1 while !configured.has_outgoing_data?
558
+
559
+ writes = 0
560
+ while configured.has_outgoing_data?
561
+ IO.select( nil, [configured.socket] )
562
+
563
+ next if configured._write == 0
564
+
565
+ writes += 1
566
+ end
567
+
568
+ configured.on_write_count.should >= writes
569
+ end
570
+
571
+ context 'when the buffer is entirely consumed' do
572
+ it 'calls #on_flush' do
573
+ configured.write data
574
+ sleep 0.1 while !configured.has_outgoing_data?
575
+
576
+ while configured.has_outgoing_data?
577
+ IO.select( nil, [configured.socket] )
578
+
579
+ if configured._write == 0
580
+ IO.select( [configured.socket] )
581
+ next
582
+ end
583
+ end
584
+
585
+ configured.called_on_flush.should be_truthy
586
+ end
587
+ end
588
+ end
589
+
590
+ describe '#has_outgoing_data?' do
591
+ let(:port) { @port }
592
+ let(:host) { @host }
593
+
594
+ let(:role) { :client }
595
+ let(:socket) { echo_client }
596
+
597
+ context 'when the send-buffer is not empty' do
598
+ it 'returns true' do
599
+ raktr.run_in_thread
600
+
601
+ configured.write 'test'
602
+ sleep 0.1 while !configured.has_outgoing_data?
603
+
604
+ configured.has_outgoing_data?.should be_truthy
605
+ end
606
+ end
607
+
608
+ context 'when the send-buffer is empty' do
609
+ it 'returns false' do
610
+ configured.has_outgoing_data?.should be_falsey
611
+ end
612
+ end
613
+ end
614
+
615
+ describe '#closed?' do
616
+ let(:port) { @port }
617
+ let(:host) { @host }
618
+
619
+ let(:role) { :client }
620
+ let(:socket) { echo_client }
621
+
622
+ context 'when the connection has been closed' do
623
+ it 'returns true' do
624
+ raktr.run do
625
+ configured.close
626
+ end
627
+
628
+ configured.should be_closed
629
+ end
630
+ end
631
+
632
+ context 'when the send-buffer is empty' do
633
+ it 'returns false' do
634
+ configured.should_not be_closed
635
+ end
636
+ end
637
+ end
638
+
639
+ describe '#close_without_callback' do
640
+ let(:port) { @port }
641
+ let(:host) { @host }
642
+
643
+ let(:role) { :client }
644
+ let(:socket) { echo_client }
645
+
646
+ it 'closes the #socket' do
647
+ raktr.run_in_thread
648
+ configured.socket.should receive(:close)
649
+ configured.close_without_callback
650
+ end
651
+
652
+ it 'detaches the connection from the reactor' do
653
+ configured
654
+
655
+ raktr.run_block do
656
+ raktr.attach configured
657
+ raktr.connections.should be_any
658
+ configured.close_without_callback
659
+ raktr.connections.should be_empty
660
+ end
661
+ end
662
+
663
+ it 'does not call #on_close' do
664
+ raktr.run_in_thread
665
+ configured.should_not receive(:on_close)
666
+ configured.close_without_callback
667
+ end
668
+ end
669
+
670
+ describe '#close' do
671
+ let(:port) { @port }
672
+ let(:host) { @host }
673
+
674
+ let(:role) { :client }
675
+ let(:socket) { echo_client }
676
+
677
+ before(:each) { raktr.run_in_thread }
678
+
679
+ it 'calls #close_without_callback' do
680
+ configured.should receive(:close_without_callback)
681
+ configured.close
682
+ end
683
+
684
+ it 'calls #on_close' do
685
+ configured.should receive(:on_close)
686
+ configured.close
687
+ end
688
+
689
+ context 'when a reason is given' do
690
+ it 'is passed to #on_close' do
691
+ configured.should receive(:on_close).with(:my_reason)
692
+ configured.close :my_reason
693
+ end
694
+ end
695
+ end
696
+ end