grpc 0.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +10 -0
  5. data/.rubocop_todo.yml +52 -0
  6. data/Gemfile +4 -0
  7. data/README.md +82 -0
  8. data/Rakefile +54 -0
  9. data/bin/apis/google/protobuf/empty.rb +44 -0
  10. data/bin/apis/pubsub_demo.rb +267 -0
  11. data/bin/apis/tech/pubsub/proto/pubsub.rb +174 -0
  12. data/bin/apis/tech/pubsub/proto/pubsub_services.rb +103 -0
  13. data/bin/interop/README.md +8 -0
  14. data/bin/interop/interop_client.rb +334 -0
  15. data/bin/interop/interop_server.rb +192 -0
  16. data/bin/interop/test/cpp/interop/empty.rb +44 -0
  17. data/bin/interop/test/cpp/interop/messages.rb +89 -0
  18. data/bin/interop/test/cpp/interop/test.rb +43 -0
  19. data/bin/interop/test/cpp/interop/test_services.rb +60 -0
  20. data/bin/math.proto +80 -0
  21. data/bin/math.rb +61 -0
  22. data/bin/math_client.rb +147 -0
  23. data/bin/math_server.rb +190 -0
  24. data/bin/math_services.rb +56 -0
  25. data/bin/noproto_client.rb +108 -0
  26. data/bin/noproto_server.rb +112 -0
  27. data/ext/grpc/extconf.rb +76 -0
  28. data/ext/grpc/rb_byte_buffer.c +241 -0
  29. data/ext/grpc/rb_byte_buffer.h +54 -0
  30. data/ext/grpc/rb_call.c +569 -0
  31. data/ext/grpc/rb_call.h +59 -0
  32. data/ext/grpc/rb_channel.c +264 -0
  33. data/ext/grpc/rb_channel.h +49 -0
  34. data/ext/grpc/rb_channel_args.c +154 -0
  35. data/ext/grpc/rb_channel_args.h +52 -0
  36. data/ext/grpc/rb_completion_queue.c +185 -0
  37. data/ext/grpc/rb_completion_queue.h +50 -0
  38. data/ext/grpc/rb_credentials.c +281 -0
  39. data/ext/grpc/rb_credentials.h +50 -0
  40. data/ext/grpc/rb_event.c +361 -0
  41. data/ext/grpc/rb_event.h +53 -0
  42. data/ext/grpc/rb_grpc.c +274 -0
  43. data/ext/grpc/rb_grpc.h +74 -0
  44. data/ext/grpc/rb_metadata.c +215 -0
  45. data/ext/grpc/rb_metadata.h +53 -0
  46. data/ext/grpc/rb_server.c +278 -0
  47. data/ext/grpc/rb_server.h +50 -0
  48. data/ext/grpc/rb_server_credentials.c +210 -0
  49. data/ext/grpc/rb_server_credentials.h +50 -0
  50. data/grpc.gemspec +41 -0
  51. data/lib/grpc.rb +39 -0
  52. data/lib/grpc/core/event.rb +44 -0
  53. data/lib/grpc/core/time_consts.rb +71 -0
  54. data/lib/grpc/errors.rb +61 -0
  55. data/lib/grpc/generic/active_call.rb +536 -0
  56. data/lib/grpc/generic/bidi_call.rb +221 -0
  57. data/lib/grpc/generic/client_stub.rb +413 -0
  58. data/lib/grpc/generic/rpc_desc.rb +150 -0
  59. data/lib/grpc/generic/rpc_server.rb +404 -0
  60. data/lib/grpc/generic/service.rb +235 -0
  61. data/lib/grpc/logconfig.rb +40 -0
  62. data/lib/grpc/version.rb +33 -0
  63. data/spec/alloc_spec.rb +44 -0
  64. data/spec/byte_buffer_spec.rb +67 -0
  65. data/spec/call_spec.rb +163 -0
  66. data/spec/channel_spec.rb +181 -0
  67. data/spec/client_server_spec.rb +372 -0
  68. data/spec/completion_queue_spec.rb +74 -0
  69. data/spec/credentials_spec.rb +71 -0
  70. data/spec/event_spec.rb +53 -0
  71. data/spec/generic/active_call_spec.rb +373 -0
  72. data/spec/generic/client_stub_spec.rb +519 -0
  73. data/spec/generic/rpc_desc_spec.rb +357 -0
  74. data/spec/generic/rpc_server_pool_spec.rb +139 -0
  75. data/spec/generic/rpc_server_spec.rb +404 -0
  76. data/spec/generic/service_spec.rb +342 -0
  77. data/spec/metadata_spec.rb +64 -0
  78. data/spec/server_credentials_spec.rb +69 -0
  79. data/spec/server_spec.rb +212 -0
  80. data/spec/spec_helper.rb +51 -0
  81. data/spec/testdata/README +1 -0
  82. data/spec/testdata/ca.pem +15 -0
  83. data/spec/testdata/server1.key +16 -0
  84. data/spec/testdata/server1.pem +16 -0
  85. data/spec/time_consts_spec.rb +89 -0
  86. metadata +353 -0
@@ -0,0 +1,357 @@
1
+ # Copyright 2015, Google Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are
6
+ # met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above
11
+ # copyright notice, this list of conditions and the following disclaimer
12
+ # in the documentation and/or other materials provided with the
13
+ # distribution.
14
+ # * Neither the name of Google Inc. nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ require 'grpc'
31
+ require 'grpc/generic/rpc_desc'
32
+
33
+ describe GRPC::RpcDesc do
34
+ RpcDesc = GRPC::RpcDesc
35
+ Stream = RpcDesc::Stream
36
+ OK = GRPC::Core::StatusCodes::OK
37
+ INTERNAL = GRPC::Core::StatusCodes::INTERNAL
38
+ UNKNOWN = GRPC::Core::StatusCodes::UNKNOWN
39
+ CallError = GRPC::Core::CallError
40
+ EventError = GRPC::Core::EventError
41
+
42
+ before(:each) do
43
+ @request_response = RpcDesc.new('rr', Object.new, Object.new, 'encode',
44
+ 'decode')
45
+ @client_streamer = RpcDesc.new('cs', Stream.new(Object.new), Object.new,
46
+ 'encode', 'decode')
47
+ @server_streamer = RpcDesc.new('ss', Object.new, Stream.new(Object.new),
48
+ 'encode', 'decode')
49
+ @bidi_streamer = RpcDesc.new('ss', Stream.new(Object.new),
50
+ Stream.new(Object.new), 'encode', 'decode')
51
+ @bs_code = INTERNAL
52
+ @no_reason = 'no reason given'
53
+ @ok_response = Object.new
54
+ end
55
+
56
+ describe '#run_server_method' do
57
+ describe 'for request responses' do
58
+ before(:each) do
59
+ @call = double('active_call')
60
+ allow(@call).to receive(:single_req_view).and_return(@call)
61
+ allow(@call).to receive(:gc)
62
+ end
63
+
64
+ it 'sends the specified status if BadStatus is raised' do
65
+ expect(@call).to receive(:remote_read).once.and_return(Object.new)
66
+ expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK')
67
+ @request_response.run_server_method(@call, method(:bad_status))
68
+ end
69
+
70
+ it 'sends status UNKNOWN if other StandardErrors are raised' do
71
+ expect(@call).to receive(:remote_read).once.and_return(Object.new)
72
+ expect(@call).to receive(:send_status) .once.with(UNKNOWN, @no_reason)
73
+ @request_response.run_server_method(@call, method(:other_error))
74
+ end
75
+
76
+ it 'absorbs EventError with no further action' do
77
+ expect(@call).to receive(:remote_read).once.and_raise(EventError)
78
+ blk = proc do
79
+ @request_response.run_server_method(@call, method(:fake_reqresp))
80
+ end
81
+ expect(&blk).to_not raise_error
82
+ end
83
+
84
+ it 'absorbs CallError with no further action' do
85
+ expect(@call).to receive(:remote_read).once.and_raise(CallError)
86
+ blk = proc do
87
+ @request_response.run_server_method(@call, method(:fake_reqresp))
88
+ end
89
+ expect(&blk).to_not raise_error
90
+ end
91
+
92
+ it 'sends a response and closes the stream if there no errors' do
93
+ req = Object.new
94
+ expect(@call).to receive(:remote_read).once.and_return(req)
95
+ expect(@call).to receive(:remote_send).once.with(@ok_response)
96
+ expect(@call).to receive(:send_status).once.with(OK, 'OK')
97
+ @request_response.run_server_method(@call, method(:fake_reqresp))
98
+ end
99
+ end
100
+
101
+ describe 'for client streamers' do
102
+ before(:each) do
103
+ @call = double('active_call')
104
+ allow(@call).to receive(:multi_req_view).and_return(@call)
105
+ allow(@call).to receive(:gc)
106
+ end
107
+
108
+ it 'sends the specified status if BadStatus is raised' do
109
+ expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK')
110
+ @client_streamer.run_server_method(@call, method(:bad_status_alt))
111
+ end
112
+
113
+ it 'sends status UNKNOWN if other StandardErrors are raised' do
114
+ expect(@call).to receive(:send_status) .once.with(UNKNOWN, @no_reason)
115
+ @client_streamer.run_server_method(@call, method(:other_error_alt))
116
+ end
117
+
118
+ it 'absorbs EventError with no further action' do
119
+ expect(@call).to receive(:remote_send).once.and_raise(EventError)
120
+ blk = proc do
121
+ @client_streamer.run_server_method(@call, method(:fake_clstream))
122
+ end
123
+ expect(&blk).to_not raise_error
124
+ end
125
+
126
+ it 'absorbs CallError with no further action' do
127
+ expect(@call).to receive(:remote_send).once.and_raise(CallError)
128
+ blk = proc do
129
+ @client_streamer.run_server_method(@call, method(:fake_clstream))
130
+ end
131
+ expect(&blk).to_not raise_error
132
+ end
133
+
134
+ it 'sends a response and closes the stream if there no errors' do
135
+ expect(@call).to receive(:remote_send).once.with(@ok_response)
136
+ expect(@call).to receive(:send_status).once.with(OK, 'OK')
137
+ @client_streamer.run_server_method(@call, method(:fake_clstream))
138
+ end
139
+ end
140
+
141
+ describe 'for server streaming' do
142
+ before(:each) do
143
+ @call = double('active_call')
144
+ allow(@call).to receive(:single_req_view).and_return(@call)
145
+ allow(@call).to receive(:gc)
146
+ end
147
+
148
+ it 'sends the specified status if BadStatus is raised' do
149
+ expect(@call).to receive(:remote_read).once.and_return(Object.new)
150
+ expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK')
151
+ @server_streamer.run_server_method(@call, method(:bad_status))
152
+ end
153
+
154
+ it 'sends status UNKNOWN if other StandardErrors are raised' do
155
+ expect(@call).to receive(:remote_read).once.and_return(Object.new)
156
+ expect(@call).to receive(:send_status) .once.with(UNKNOWN, @no_reason)
157
+ @server_streamer.run_server_method(@call, method(:other_error))
158
+ end
159
+
160
+ it 'absorbs EventError with no further action' do
161
+ expect(@call).to receive(:remote_read).once.and_raise(EventError)
162
+ blk = proc do
163
+ @server_streamer.run_server_method(@call, method(:fake_svstream))
164
+ end
165
+ expect(&blk).to_not raise_error
166
+ end
167
+
168
+ it 'absorbs CallError with no further action' do
169
+ expect(@call).to receive(:remote_read).once.and_raise(CallError)
170
+ blk = proc do
171
+ @server_streamer.run_server_method(@call, method(:fake_svstream))
172
+ end
173
+ expect(&blk).to_not raise_error
174
+ end
175
+
176
+ it 'sends a response and closes the stream if there no errors' do
177
+ req = Object.new
178
+ expect(@call).to receive(:remote_read).once.and_return(req)
179
+ expect(@call).to receive(:remote_send).twice.with(@ok_response)
180
+ expect(@call).to receive(:send_status).once.with(OK, 'OK')
181
+ @server_streamer.run_server_method(@call, method(:fake_svstream))
182
+ end
183
+ end
184
+
185
+ describe 'for bidi streamers' do
186
+ before(:each) do
187
+ @call = double('active_call')
188
+ enq_th, rwl_th = double('enqueue_th'), ('read_write_loop_th')
189
+ allow(enq_th).to receive(:join)
190
+ allow(rwl_th).to receive(:join)
191
+ allow(@call).to receive(:gc)
192
+ end
193
+
194
+ it 'sends the specified status if BadStatus is raised' do
195
+ e = GRPC::BadStatus.new(@bs_code, 'NOK')
196
+ expect(@call).to receive(:run_server_bidi).and_raise(e)
197
+ expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK')
198
+ @bidi_streamer.run_server_method(@call, method(:bad_status_alt))
199
+ end
200
+
201
+ it 'sends status UNKNOWN if other StandardErrors are raised' do
202
+ expect(@call).to receive(:run_server_bidi).and_raise(StandardError)
203
+ expect(@call).to receive(:send_status).once.with(UNKNOWN, @no_reason)
204
+ @bidi_streamer.run_server_method(@call, method(:other_error_alt))
205
+ end
206
+
207
+ it 'closes the stream if there no errors' do
208
+ expect(@call).to receive(:run_server_bidi)
209
+ expect(@call).to receive(:send_status).once.with(OK, 'OK')
210
+ @bidi_streamer.run_server_method(@call, method(:fake_bidistream))
211
+ end
212
+ end
213
+ end
214
+
215
+ describe '#assert_arity_matches' do
216
+ def no_arg
217
+ end
218
+
219
+ def fake_clstream(_arg)
220
+ end
221
+
222
+ def fake_svstream(_arg1, _arg2)
223
+ end
224
+
225
+ it 'raises when a request_response does not have 2 args' do
226
+ [:fake_clstream, :no_arg].each do |mth|
227
+ blk = proc do
228
+ @request_response.assert_arity_matches(method(mth))
229
+ end
230
+ expect(&blk).to raise_error
231
+ end
232
+ end
233
+
234
+ it 'passes when a request_response has 2 args' do
235
+ blk = proc do
236
+ @request_response.assert_arity_matches(method(:fake_svstream))
237
+ end
238
+ expect(&blk).to_not raise_error
239
+ end
240
+
241
+ it 'raises when a server_streamer does not have 2 args' do
242
+ [:fake_clstream, :no_arg].each do |mth|
243
+ blk = proc do
244
+ @server_streamer.assert_arity_matches(method(mth))
245
+ end
246
+ expect(&blk).to raise_error
247
+ end
248
+ end
249
+
250
+ it 'passes when a server_streamer has 2 args' do
251
+ blk = proc do
252
+ @server_streamer.assert_arity_matches(method(:fake_svstream))
253
+ end
254
+ expect(&blk).to_not raise_error
255
+ end
256
+
257
+ it 'raises when a client streamer does not have 1 arg' do
258
+ [:fake_svstream, :no_arg].each do |mth|
259
+ blk = proc do
260
+ @client_streamer.assert_arity_matches(method(mth))
261
+ end
262
+ expect(&blk).to raise_error
263
+ end
264
+ end
265
+
266
+ it 'passes when a client_streamer has 1 arg' do
267
+ blk = proc do
268
+ @client_streamer.assert_arity_matches(method(:fake_clstream))
269
+ end
270
+ expect(&blk).to_not raise_error
271
+ end
272
+
273
+ it 'raises when a bidi streamer does not have 1 arg' do
274
+ [:fake_svstream, :no_arg].each do |mth|
275
+ blk = proc do
276
+ @bidi_streamer.assert_arity_matches(method(mth))
277
+ end
278
+ expect(&blk).to raise_error
279
+ end
280
+ end
281
+
282
+ it 'passes when a bidi streamer has 1 arg' do
283
+ blk = proc do
284
+ @bidi_streamer.assert_arity_matches(method(:fake_clstream))
285
+ end
286
+ expect(&blk).to_not raise_error
287
+ end
288
+ end
289
+
290
+ describe '#request_response?' do
291
+ it 'is true only input and output are both not Streams' do
292
+ expect(@request_response.request_response?).to be(true)
293
+ expect(@client_streamer.request_response?).to be(false)
294
+ expect(@bidi_streamer.request_response?).to be(false)
295
+ expect(@server_streamer.request_response?).to be(false)
296
+ end
297
+ end
298
+
299
+ describe '#client_streamer?' do
300
+ it 'is true only when input is a Stream and output is not a Stream' do
301
+ expect(@client_streamer.client_streamer?).to be(true)
302
+ expect(@request_response.client_streamer?).to be(false)
303
+ expect(@server_streamer.client_streamer?).to be(false)
304
+ expect(@bidi_streamer.client_streamer?).to be(false)
305
+ end
306
+ end
307
+
308
+ describe '#server_streamer?' do
309
+ it 'is true only when output is a Stream and input is not a Stream' do
310
+ expect(@server_streamer.server_streamer?).to be(true)
311
+ expect(@client_streamer.server_streamer?).to be(false)
312
+ expect(@request_response.server_streamer?).to be(false)
313
+ expect(@bidi_streamer.server_streamer?).to be(false)
314
+ end
315
+ end
316
+
317
+ describe '#bidi_streamer?' do
318
+ it 'is true only when output is a Stream and input is a Stream' do
319
+ expect(@bidi_streamer.bidi_streamer?).to be(true)
320
+ expect(@server_streamer.bidi_streamer?).to be(false)
321
+ expect(@client_streamer.bidi_streamer?).to be(false)
322
+ expect(@request_response.bidi_streamer?).to be(false)
323
+ end
324
+ end
325
+
326
+ def fake_reqresp(_req, _call)
327
+ @ok_response
328
+ end
329
+
330
+ def fake_clstream(_call)
331
+ @ok_response
332
+ end
333
+
334
+ def fake_svstream(_req, _call)
335
+ [@ok_response, @ok_response]
336
+ end
337
+
338
+ def fake_bidistream(an_array)
339
+ an_array
340
+ end
341
+
342
+ def bad_status(_req, _call)
343
+ fail GRPC::BadStatus.new(@bs_code, 'NOK')
344
+ end
345
+
346
+ def other_error(_req, _call)
347
+ fail(ArgumentError, 'other error')
348
+ end
349
+
350
+ def bad_status_alt(_call)
351
+ fail GRPC::BadStatus.new(@bs_code, 'NOK')
352
+ end
353
+
354
+ def other_error_alt(_call)
355
+ fail(ArgumentError, 'other error')
356
+ end
357
+ end
@@ -0,0 +1,139 @@
1
+ # Copyright 2015, Google Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are
6
+ # met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above
11
+ # copyright notice, this list of conditions and the following disclaimer
12
+ # in the documentation and/or other materials provided with the
13
+ # distribution.
14
+ # * Neither the name of Google Inc. nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ require 'grpc'
31
+ require 'xray/thread_dump_signal_handler'
32
+
33
+ Pool = GRPC::RpcServer::Pool
34
+
35
+ describe Pool do
36
+ describe '#new' do
37
+ it 'raises if a non-positive size is used' do
38
+ expect { Pool.new(0) }.to raise_error
39
+ expect { Pool.new(-1) }.to raise_error
40
+ expect { Pool.new(Object.new) }.to raise_error
41
+ end
42
+
43
+ it 'is constructed OK with a positive size' do
44
+ expect { Pool.new(1) }.not_to raise_error
45
+ end
46
+ end
47
+
48
+ describe '#jobs_waiting' do
49
+ it 'at start, it is zero' do
50
+ p = Pool.new(1)
51
+ expect(p.jobs_waiting).to be(0)
52
+ end
53
+
54
+ it 'it increases, with each scheduled job if the pool is not running' do
55
+ p = Pool.new(1)
56
+ job = proc {}
57
+ expect(p.jobs_waiting).to be(0)
58
+ 5.times do |i|
59
+ p.schedule(&job)
60
+ expect(p.jobs_waiting).to be(i + 1)
61
+ end
62
+ end
63
+
64
+ it 'it decreases as jobs are run' do
65
+ p = Pool.new(1)
66
+ job = proc {}
67
+ expect(p.jobs_waiting).to be(0)
68
+ 3.times do
69
+ p.schedule(&job)
70
+ end
71
+ p.start
72
+ sleep 2
73
+ expect(p.jobs_waiting).to be(0)
74
+ end
75
+ end
76
+
77
+ describe '#schedule' do
78
+ it 'throws if the pool is already stopped' do
79
+ p = Pool.new(1)
80
+ p.stop
81
+ job = proc {}
82
+ expect { p.schedule(&job) }.to raise_error
83
+ end
84
+
85
+ it 'adds jobs that get run by the pool' do
86
+ p = Pool.new(1)
87
+ p.start
88
+ o, q = Object.new, Queue.new
89
+ job = proc { q.push(o) }
90
+ p.schedule(&job)
91
+ expect(q.pop).to be(o)
92
+ p.stop
93
+ end
94
+ end
95
+
96
+ describe '#stop' do
97
+ it 'works when there are no scheduled tasks' do
98
+ p = Pool.new(1)
99
+ expect { p.stop }.not_to raise_error
100
+ end
101
+
102
+ it 'stops jobs when there are long running jobs' do
103
+ p = Pool.new(1)
104
+ p.start
105
+ o, q = Object.new, Queue.new
106
+ job = proc do
107
+ sleep(5) # long running
108
+ q.push(o)
109
+ end
110
+ p.schedule(&job)
111
+ sleep(1) # should ensure the long job gets scheduled
112
+ expect { p.stop }.not_to raise_error
113
+ end
114
+ end
115
+
116
+ describe '#start' do
117
+ it 'runs pre-scheduled jobs' do
118
+ p = Pool.new(2)
119
+ o, q = Object.new, Queue.new
120
+ n = 5 # arbitrary
121
+ n.times { p.schedule(o, &q.method(:push)) }
122
+ p.start
123
+ n.times { expect(q.pop).to be(o) }
124
+ p.stop
125
+ end
126
+
127
+ it 'runs jobs as they are scheduled ' do
128
+ p = Pool.new(2)
129
+ o, q = Object.new, Queue.new
130
+ p.start
131
+ n = 5 # arbitrary
132
+ n.times do
133
+ p.schedule(o, &q.method(:push))
134
+ expect(q.pop).to be(o)
135
+ end
136
+ p.stop
137
+ end
138
+ end
139
+ end