raktr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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