green 0.0.1 → 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,417 @@
1
+ # based on https://github.com/igrigorik/em-synchrony/pull/127
2
+
3
+ require 'spec_helper'
4
+ require 'green/socket'
5
+ require 'green/group'
6
+ require 'green/event'
7
+ describe Green::TCPSocket do
8
+ describe '.new' do
9
+ describe 'to an open TCP port on an resolvable host' do
10
+ it 'succeeds' do
11
+ Green.spawn do
12
+ s = Green::TCPServer.new '127.0.0.1', 12345
13
+ s.accept
14
+ s.close
15
+ end
16
+ Green.spawn do
17
+ s = Green::TCPSocket.new '127.0.0.1', 12345
18
+ s.close
19
+ end.join
20
+ end
21
+ end
22
+
23
+ describe 'to an unresolvable host' do
24
+ it 'raises SocketError' do
25
+ proc {
26
+ Green::TCPSocket.new 'xxxyyyzzz', 12345
27
+ }.must_raise SocketError
28
+ end
29
+ end
30
+
31
+ describe 'to a closed TCP port' do
32
+ it 'raises Errno::ECONNREFUSED' do
33
+ proc {
34
+ Green::TCPSocket.new '127.0.0.1', 12345
35
+ }.must_raise Errno::ECONNREFUSED
36
+ end
37
+ end
38
+ end
39
+
40
+ def in_connect(&blk)
41
+ server = Green::TCPServer.new '127.0.0.1', 12345
42
+ s = nil
43
+ client = nil
44
+ g = Green::Group.new
45
+ g.spawn do
46
+ s = server.accept
47
+ s.write '1234'
48
+ end
49
+ g.spawn do
50
+ client = Green::TCPSocket.new '127.0.0.1', 12345
51
+ end
52
+ g.join
53
+ blk.call s, client
54
+ ensure
55
+ s.close rescue nil
56
+ client.close rescue nil
57
+ server.close rescue nil
58
+ end
59
+
60
+ describe '#closed?' do
61
+ describe 'after calling #close' do
62
+ it 'returns true' do
63
+ in_connect do |s, c|
64
+ c.close
65
+ c.closed?.must_equal true
66
+ end
67
+ end
68
+ end
69
+ describe 'after the peer has closed the connection' do
70
+ describe 'when we\'ve not yet read EOF' do
71
+ it 'returns false' do
72
+ in_connect do |s, c|
73
+ s.close
74
+ c.read(2).size.must_equal 2
75
+ c.closed?.must_equal false
76
+ end
77
+ end
78
+ end
79
+ describe 'when we\'ve read EOF' do
80
+ it 'returns false' do
81
+ in_connect do |s, c|
82
+ s.close
83
+ c.read(10).size.must_equal 4
84
+ c.read(10).must_equal nil
85
+ c.closed?.must_equal false
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ describe '#read' do
93
+ describe 'with a length argument' do
94
+ describe 'with a possitive length argument' do
95
+ describe 'when the connection is open' do
96
+ describe 'with greater or equal than the requested data buffered' do
97
+ it 'returns the requested data and no more' do
98
+ in_connect do |s, c|
99
+ c.read(2).size.must_equal 2
100
+ c.read(1).size.must_equal 1
101
+ end
102
+ end
103
+ end
104
+ describe 'with less than the requested data buffered' do
105
+ it 'blocks' do
106
+ in_connect do |s, c|
107
+ blocked = true
108
+ g = Green.spawn { blocked.must_equal true; s.close }
109
+ res = c.read(10)
110
+ blocked = false
111
+ g.join
112
+ end
113
+ end
114
+ end
115
+ end
116
+ describe 'when the peer has closed the connection' do
117
+ describe 'with no data buffered' do
118
+ it 'returns nil' do
119
+ in_connect do |s, c|
120
+ s.close
121
+ c.read(4).size.must_equal 4
122
+ c.read(1).must_equal nil
123
+ end
124
+ end
125
+ end
126
+ describe 'with less than the requested data buffered' do
127
+ it 'returns the buffered data' do
128
+ in_connect do |s, c|
129
+ s.close
130
+ c.read(50).size.must_equal 4
131
+ end
132
+ end
133
+ end
134
+ describe 'with greater or equal than the requested data buffered' do
135
+ it 'returns the requested data and no more' do
136
+ in_connect do |s, c|
137
+ c.read(2).size.must_equal 2
138
+ end
139
+ end
140
+ end
141
+ end
142
+ describe 'when we closed the connection' do
143
+ it 'raises IOError' do
144
+ in_connect do |s, c|
145
+ c.close
146
+ proc {
147
+ c.read(4)
148
+ }.must_raise IOError
149
+ end
150
+ end
151
+ end
152
+ end
153
+ describe 'with a negative length argument' do
154
+ it 'raises ArgumentError' do
155
+ in_connect do |s, c|
156
+ proc {
157
+ c.read(-10)
158
+ }.must_raise ArgumentError
159
+ end
160
+ end
161
+ end
162
+ describe 'with a zero length argument' do
163
+ describe 'when the connection is open' do
164
+ it 'returns an empty string' do
165
+ in_connect do |s, c|
166
+ c.read(0).must_equal ""
167
+ end
168
+ end
169
+ end
170
+ describe 'when the peer has closed the connection' do
171
+ it 'returns an empty string' do
172
+ in_connect do |s, c|
173
+ s.close
174
+ c.read(0).must_equal ""
175
+ end
176
+ end
177
+ end
178
+ describe 'when we closed the connection' do
179
+ it 'raises IOError' do
180
+ in_connect do |s, c|
181
+ c.close
182
+ proc {
183
+ c.read(0)
184
+ }.must_raise IOError
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
190
+ describe 'without a length argument' do
191
+ describe 'when the connection is open' do
192
+ it 'blocks until the peer closes the connection and returns all data sent' do
193
+ in_connect do |s, c|
194
+ blocked = true
195
+ Green.hub.timer(0.01) { blocked.must_equal true; s.close }
196
+ c.read(10).must_equal '1234'
197
+ blocked = false
198
+ end
199
+ end
200
+ end
201
+ describe 'when the peer has closed the connection' do
202
+ describe 'with no data buffered' do
203
+ it 'returns an empty string' do
204
+ in_connect do |s, c|
205
+ s.close
206
+ c.read
207
+ c.read.must_equal ""
208
+ end
209
+ end
210
+ end
211
+ describe 'with data buffered' do
212
+ it 'returns the buffered data' do
213
+ in_connect do |s, c|
214
+ s.close
215
+ c.read.must_equal "1234"
216
+ end
217
+ end
218
+ end
219
+ end
220
+ describe 'when we closed the connection' do
221
+ it 'raises IOError' do
222
+ in_connect do |s, c|
223
+ c.close
224
+ proc {
225
+ c.read
226
+ }.must_raise IOError
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
232
+
233
+ describe '#recv' do
234
+ describe 'with a length argument' do
235
+ describe 'with a positive length argument' do
236
+ describe 'when the connection is open' do
237
+ describe 'with greater or equal than the requested data buffered' do
238
+ it 'returns the requested data and no more' do
239
+ in_connect do |s, c|
240
+ c.recv(2).size.must_equal 2
241
+ c.recv(1).size.must_equal 1
242
+ end
243
+ end
244
+ end
245
+ describe 'with less than the requested data buffered' do
246
+ it 'return the buffered data' do
247
+ in_connect do |s, c|
248
+ c.recv(50).size.must_equal 4
249
+ end
250
+ end
251
+ end
252
+ describe 'with no buffered data' do
253
+ it 'blocks' do
254
+ in_connect do |s, c|
255
+ c.recv(10)
256
+ blocked = true
257
+ g = Green.spawn do
258
+ blocked.must_equal true
259
+ s.close
260
+ end
261
+ c.recv(10)
262
+ blocked = false
263
+ g.join
264
+ end
265
+ end
266
+ end
267
+ end
268
+ describe 'when the peer has closed the connection' do
269
+ describe 'with no data buffered' do
270
+ it 'returns an empty string' do
271
+ in_connect do |s, c|
272
+ s.close
273
+ c.read(4).size.must_equal 4
274
+ c.recv(1).must_equal ""
275
+ end
276
+ end
277
+ end
278
+ describe 'with less than the requested data buffered' do
279
+ it 'returns the buffered data' do
280
+ in_connect do |s, c|
281
+ s.close
282
+ c.recv(50).size.must_equal 4
283
+ end
284
+ end
285
+ end
286
+ describe 'with greater or equal than the requested data buffered' do
287
+ it 'returns the requested data and no more' do
288
+ in_connect do |s, c|
289
+ s.close
290
+ c.recv(2).size.must_equal 2
291
+ end
292
+ end
293
+ end
294
+ end
295
+ describe 'when we closed the connection' do
296
+ it 'raises IOError' do
297
+ in_connect do |s, c|
298
+ c.close
299
+ proc {
300
+ res = c.recv(4)
301
+ }.must_raise IOError
302
+ end
303
+ end
304
+ end
305
+ end
306
+ describe 'with a negative length argument' do
307
+ it 'raises ArgumentError' do
308
+ in_connect do |s, c|
309
+ proc {
310
+ c.recv(-10)
311
+ }.must_raise ArgumentError
312
+ end
313
+ end
314
+ end
315
+ describe 'with a zero length argument' do
316
+ describe 'when the connection is open' do
317
+ it 'returns an empty string' do
318
+ in_connect do |s, c|
319
+ c.recv(0).must_equal ""
320
+ end
321
+ end
322
+ end
323
+ describe 'when the peer has closed the connection' do
324
+ it 'returns an empty string' do
325
+ in_connect do |s, c|
326
+ s.close
327
+ c.recv(0).must_equal ""
328
+ end
329
+ end
330
+ end
331
+ describe 'when we closed the connection' do
332
+ it 'raises IOError' do
333
+ in_connect do |s, c|
334
+ c.close
335
+ proc {
336
+ c.recv(0)
337
+ }.must_raise IOError
338
+ end
339
+ end
340
+ end
341
+ end
342
+ end
343
+ describe 'without a length argument' do
344
+ it 'raises ArgumentError' do
345
+ in_connect do |s, c|
346
+ proc {
347
+ c.recv()
348
+ }.must_raise ArgumentError
349
+ end
350
+ end
351
+ end
352
+ end
353
+
354
+ describe '#write' do
355
+ describe 'when the peer has closed the connection' do
356
+ it 'raises Errno::EPIPE' do
357
+ in_connect do |s, c|
358
+ s.close
359
+ Green.spawn do
360
+ Green.sleep 0.01
361
+ proc {
362
+ c.write 100000.times.to_a * '' # on small chunks it can not raise exception
363
+ }.must_raise Errno::EPIPE, Errno::ECONNRESET, Errno::EBADF
364
+ end.join
365
+ end
366
+ end
367
+ end
368
+ describe 'when we closed the connection' do
369
+ it 'raises IOError' do
370
+ in_connect do |s, c|
371
+ c.close
372
+ proc {
373
+ c.write("foo")
374
+ }.must_raise IOError
375
+ end
376
+ end
377
+ end
378
+ end
379
+
380
+ describe '#send' do
381
+ describe 'when the peer has closed the connection' do
382
+ it 'raises Errno::EPIPE' do
383
+ in_connect do |s, c|
384
+ s.close
385
+ Green.spawn do
386
+ Green.sleep 0.01
387
+ proc {
388
+ c.send 100000.times.to_a * '', 0
389
+ }.must_raise Errno::EPIPE, Errno::ECONNRESET, Errno::EBADF
390
+ end.join
391
+ end
392
+ end
393
+ end
394
+
395
+ describe 'when we closed the connection' do
396
+ it 'raises IOError' do
397
+ in_connect do |s, c|
398
+ c.close
399
+ proc {
400
+ c.send "foo", 0
401
+ }.must_raise IOError
402
+ end
403
+ end
404
+ end
405
+
406
+ describe 'without a flags argument' do
407
+ it 'raises ArgumentError' do
408
+ in_connect do |s, c|
409
+ proc {
410
+ c.send 'foo'
411
+ }.must_raise ArgumentError
412
+ end
413
+ end
414
+ end
415
+ end
416
+
417
+ end
@@ -0,0 +1,121 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "spec_helper"
3
+ require 'green/zmq'
4
+ require 'green/group'
5
+
6
+ describe ZMQ::Socket do
7
+
8
+ describe "simple case" do
9
+ before do
10
+ @ctx = ZMQ::Context.new
11
+ @rep = @ctx.socket(ZMQ::REP)
12
+ @req = @ctx.socket(ZMQ::REQ)
13
+ @rep.bind('inproc://test')
14
+ @req.connect('inproc://test')
15
+ end
16
+
17
+ after do
18
+ @req.close
19
+ @rep.close
20
+ @ctx.terminate
21
+ end
22
+
23
+ it "works" do
24
+ @req.send_string 'hello'
25
+ Green.spawn do
26
+ str = ''
27
+ @rep.recv_string(str)
28
+ str.must_equal 'hello'
29
+ end.join
30
+ end
31
+ end
32
+
33
+ # describe "complex topology" do
34
+ # let(:router_endpoint) { "tcp://127.0.0.1:12345" }
35
+ # let(:dealer_endpoint) { "tcp://127.0.0.1:12346" }
36
+ # before do
37
+ # @ctx = ZMQ::Context.new
38
+ # @router = @ctx.socket ZMQ::ROUTER
39
+ # @dealer = @ctx.socket ZMQ::DEALER
40
+ # @router.bind(router_endpoint)
41
+ # @dealer.bind(dealer_endpoint)
42
+ # @router_green = Green.spawn do
43
+ # begin
44
+ # strings = []
45
+ # while (@router.recv_strings(strings) == 0)
46
+ # @dealer.send_strings strings
47
+ # strings = []
48
+ # end
49
+ # ensure
50
+ # @router.close
51
+ # end
52
+ # end
53
+ # @dealer_green = Green.spawn do
54
+ # begin
55
+ # strings = []
56
+ # while (@dealer.recv_strings(strings) == 0)
57
+ # @router.send_strings strings
58
+ # strings = []
59
+ # end
60
+ # ensure
61
+ # @dealer.close
62
+ # end
63
+ # end
64
+ # end
65
+
66
+ # def spawn_workers
67
+ # @workers_ctx = ZMQ::Context.new
68
+ # @workers = Green::Group.new
69
+ # 10.times.map do
70
+ # @workers.spawn do
71
+ # begin
72
+ # s = @workers_ctx.socket ZMQ::REP
73
+ # s.connect dealer_endpoint
74
+ # strings = []
75
+ # while (s.recv_strings(strings) == 0)
76
+ # s.send_string((strings.first.to_i + 1).to_s)
77
+ # strings = []
78
+ # end
79
+ # ensure
80
+ # s.close
81
+ # end
82
+ # end
83
+ # end
84
+ # end
85
+
86
+ # it "should increment numbers" do
87
+ # ctx = ZMQ::Context.new
88
+ # clients = Green::Group.new
89
+ # 5.times do
90
+ # clients.spawn do
91
+ # s = ctx.socket ZMQ::REQ
92
+ # s.connect router_endpoint
93
+ # i = 0
94
+ # str = ''
95
+ # 10.times do
96
+ # s.send_string i.to_s
97
+ # s.recv_string str
98
+ # i = str.to_i
99
+ # end
100
+ # s.close
101
+ # i.must_equal 10
102
+ # end
103
+ # end
104
+ # Green.spawn do
105
+ # Green.sleep 1
106
+ # spawn_workers
107
+ # end
108
+ # clients.join
109
+ # ctx.terminate
110
+ # end
111
+
112
+ # after do
113
+ # @workers.kill
114
+ # @router_green.kill
115
+ # @dealer_green.kill
116
+ # # @ctx.terminate # FIXME
117
+ # # @workers_ctx.terminate
118
+ # end
119
+ # end
120
+ end
121
+
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Green do
4
+ describe ".spawn" do
5
+ it "should spawn greens" do
6
+ g = Green.spawn do
7
+ :hello
8
+ end
9
+ g.join.must_equal :hello
10
+ end
11
+ end
12
+
13
+ describe "sleep" do
14
+ it "should set sleep" do
15
+ t = Time.now
16
+ Green.spawn do
17
+ Green.sleep 0.1
18
+ end.join
19
+ (Time.now - t).must_be :>, 0.1
20
+ end
21
+ end
22
+
23
+ describe "timeouts" do
24
+ it "should set timeout" do
25
+ t = Time.now
26
+ Green.spawn do
27
+ begin
28
+ Green.timeout(0.01) do
29
+ Green.sleep 0.1
30
+ end
31
+ rescue Timeout::Error
32
+ end
33
+ end.join
34
+ (Time.now - t).must_be :<, 0.1
35
+ end
36
+ end
37
+ end
data/spec/helpers.rb ADDED
File without changes
@@ -0,0 +1,32 @@
1
+ require 'bundler'
2
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
3
+ Bundler.setup
4
+
5
+ require 'minitest/spec'
6
+ require 'minitest/autorun'
7
+ require 'minitest/reporters'
8
+
9
+ require 'helpers'
10
+
11
+ require 'green'
12
+
13
+ MiniTest::Unit.runner = MiniTest::SuiteRunner.new
14
+ MiniTest::Unit.runner.reporters << MiniTest::Reporters::SpecReporter.new
15
+
16
+
17
+ # class MiniTest::Spec
18
+ # def teardown
19
+ # g = Green.current
20
+ # Green.hub.callback { g.switch }
21
+ # Green.hub.switch
22
+ # puts "Callback: #{Green.hub.callbacks.size}; Timers: #{Green.hub.timers.size}; Cancels: #{Green.hub.cancel_timers.size}"
23
+ # puts Green.hub.callbacks.inspect
24
+ # end
25
+ # end
26
+
27
+ # at_exit {
28
+ # loop do
29
+ # MiniTest::Unit.new.run
30
+ # break if MiniTest::Unit.runner.errors != 0
31
+ # end
32
+ # }