curb 1.2.2 → 1.3.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 +4 -4
- data/Rakefile +22 -0
- data/ext/curb.c +282 -231
- data/ext/curb.h +4 -4
- data/ext/curb_easy.c +608 -215
- data/ext/curb_easy.h +5 -0
- data/ext/curb_errors.c +5 -5
- data/ext/curb_errors.h +1 -1
- data/ext/curb_macros.h +14 -14
- data/ext/curb_multi.c +612 -142
- data/ext/curb_multi.h +3 -1
- data/ext/curb_postfield.c +47 -21
- data/ext/curb_postfield.h +1 -0
- data/ext/curb_upload.c +32 -9
- data/ext/curb_upload.h +2 -0
- data/ext/extconf.rb +42 -1
- data/lib/curl/easy.rb +154 -13
- data/lib/curl/multi.rb +69 -9
- data/lib/curl.rb +193 -0
- data/tests/helper.rb +222 -36
- data/tests/leak_trace.rb +237 -0
- data/tests/tc_curl_download.rb +6 -2
- data/tests/tc_curl_easy.rb +450 -1
- data/tests/tc_curl_multi.rb +573 -59
- data/tests/tc_curl_native_coverage.rb +130 -0
- data/tests/tc_curl_postfield.rb +161 -0
- data/tests/tc_fiber_scheduler.rb +342 -7
- data/tests/tc_gc_compact.rb +178 -16
- data/tests/tc_test_server_methods.rb +110 -0
- metadata +10 -14
- data/tests/test_basic.rb +0 -29
- data/tests/test_fiber_debug.rb +0 -69
- data/tests/test_fiber_simple.rb +0 -65
- data/tests/test_real_url.rb +0 -65
- data/tests/test_simple_fiber.rb +0 -34
data/tests/tc_curl_easy.rb
CHANGED
|
@@ -32,6 +32,23 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
32
32
|
assert_match(/GET/, http.body)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
def test_resolve_clear_keeps_handle_usable
|
|
36
|
+
host = "curb.invalid"
|
|
37
|
+
url = "http://#{host}:#{TestServlet.port}#{TestServlet.path}"
|
|
38
|
+
mapping = "#{host}:#{TestServlet.port}:127.0.0.1"
|
|
39
|
+
|
|
40
|
+
http = Curl::Easy.new(url)
|
|
41
|
+
http.dns_cache_timeout = 0
|
|
42
|
+
http.resolve = [mapping]
|
|
43
|
+
http.get
|
|
44
|
+
assert_match(/GET/, http.body)
|
|
45
|
+
|
|
46
|
+
http.resolve = nil
|
|
47
|
+
http.url = TestServlet.url
|
|
48
|
+
http.get
|
|
49
|
+
assert_match(/GET/, http.body)
|
|
50
|
+
end
|
|
51
|
+
|
|
35
52
|
def test_curlopt_stderr_with_file
|
|
36
53
|
# does not work with Tempfile directly
|
|
37
54
|
path = Tempfile.new('curb_test_curlopt_stderr').path
|
|
@@ -106,6 +123,248 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
106
123
|
assert_equal "", easy.body_str.to_s
|
|
107
124
|
end
|
|
108
125
|
|
|
126
|
+
def test_perform_releases_failed_implicit_multi_without_follow_up_easy_perform
|
|
127
|
+
Curl::Easy.flush_deferred_multi_closes
|
|
128
|
+
assert_equal 0, Curl::Easy.deferred_multi_closes.length
|
|
129
|
+
|
|
130
|
+
easy, implicit_multi = capture_failed_implicit_multi_cleanup_state
|
|
131
|
+
|
|
132
|
+
assert_nil easy.multi
|
|
133
|
+
assert_equal({}, implicit_multi.requests)
|
|
134
|
+
assert_equal false, implicit_multi.instance_variable_get(:@deferred_close)
|
|
135
|
+
assert_equal 0, Curl::Easy.deferred_multi_closes.length
|
|
136
|
+
ensure
|
|
137
|
+
easy.multi = nil if defined?(easy) && easy
|
|
138
|
+
implicit_multi.close if defined?(implicit_multi) && implicit_multi
|
|
139
|
+
Curl::Easy.flush_deferred_multi_closes
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def test_deferred_multi_closes_stay_with_their_owner_thread_across_retry
|
|
143
|
+
Curl::Easy.flush_deferred_multi_closes(all_threads: true)
|
|
144
|
+
multi = deferred_close_stub_multi(failures: 1)
|
|
145
|
+
|
|
146
|
+
Curl::Easy.defer_multi_close(multi, nil)
|
|
147
|
+
|
|
148
|
+
Curl::Easy.flush_deferred_multi_closes
|
|
149
|
+
assert_equal 1, multi.close_attempts
|
|
150
|
+
assert_equal true, multi.instance_variable_get(:@deferred_close)
|
|
151
|
+
assert_equal 1, Curl::Easy.deferred_multi_closes.length
|
|
152
|
+
|
|
153
|
+
Thread.new { Curl::Easy.flush_deferred_multi_closes }.join
|
|
154
|
+
assert_equal 1, multi.close_attempts
|
|
155
|
+
assert_equal true, multi.instance_variable_get(:@deferred_close)
|
|
156
|
+
assert_equal 1, Curl::Easy.deferred_multi_closes.length
|
|
157
|
+
|
|
158
|
+
Curl::Easy.flush_deferred_multi_closes
|
|
159
|
+
assert_equal 2, multi.close_attempts
|
|
160
|
+
assert_equal true, multi.closed?
|
|
161
|
+
assert_equal false, multi.instance_variable_get(:@deferred_close)
|
|
162
|
+
assert_equal 0, Curl::Easy.deferred_multi_closes.length
|
|
163
|
+
ensure
|
|
164
|
+
Curl::Easy.flush_deferred_multi_closes(all_threads: true)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def capture_created_multis
|
|
168
|
+
created_multis = []
|
|
169
|
+
multi_singleton = class << Curl::Multi; self; end
|
|
170
|
+
|
|
171
|
+
multi_singleton.__send__(:alias_method, :__curb_test_original_new, :new)
|
|
172
|
+
multi_singleton.__send__(:define_method, :new) do |*args, &block|
|
|
173
|
+
multi = __curb_test_original_new(*args, &block)
|
|
174
|
+
created_multis << multi
|
|
175
|
+
multi
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
yield created_multis
|
|
179
|
+
ensure
|
|
180
|
+
if defined?(multi_singleton) && multi_singleton.method_defined?(:__curb_test_original_new)
|
|
181
|
+
multi_singleton.__send__(:remove_method, :new)
|
|
182
|
+
multi_singleton.__send__(:alias_method, :new, :__curb_test_original_new)
|
|
183
|
+
multi_singleton.__send__(:remove_method, :__curb_test_original_new)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def capture_failed_implicit_multi_cleanup_state
|
|
188
|
+
created_multis = nil
|
|
189
|
+
easy = nil
|
|
190
|
+
|
|
191
|
+
capture_created_multis do |captured_multis|
|
|
192
|
+
created_multis = captured_multis
|
|
193
|
+
easy = Curl::Easy.new(TestServlet.url)
|
|
194
|
+
easy.on_complete { raise "complete blew up" }
|
|
195
|
+
|
|
196
|
+
error = assert_raise(Curl::Err::AbortedByCallbackError) { easy.perform }
|
|
197
|
+
assert_equal "complete blew up", error.message
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
assert_equal 1, created_multis.length, "test should observe one implicit multi created by Easy#perform"
|
|
201
|
+
|
|
202
|
+
[easy, created_multis.first]
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def deferred_close_stub_multi(failures:)
|
|
206
|
+
Object.new.tap do |multi|
|
|
207
|
+
requests = {}
|
|
208
|
+
remaining_failures = failures
|
|
209
|
+
close_attempts = 0
|
|
210
|
+
closed = false
|
|
211
|
+
|
|
212
|
+
multi.define_singleton_method(:requests) { requests }
|
|
213
|
+
multi.define_singleton_method(:_close) do
|
|
214
|
+
close_attempts += 1
|
|
215
|
+
if remaining_failures.positive?
|
|
216
|
+
remaining_failures -= 1
|
|
217
|
+
raise "close failed"
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
closed = true
|
|
221
|
+
end
|
|
222
|
+
multi.define_singleton_method(:close_attempts) { close_attempts }
|
|
223
|
+
multi.define_singleton_method(:closed?) { closed }
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def test_perform_restores_explicit_multi_after_callback_error
|
|
228
|
+
multi = Curl::Multi.new
|
|
229
|
+
easy = Curl::Easy.new(TestServlet.url)
|
|
230
|
+
easy.multi = multi
|
|
231
|
+
easy.on_complete { raise "complete blew up" }
|
|
232
|
+
|
|
233
|
+
error = assert_raise(Curl::Err::AbortedByCallbackError) { easy.perform }
|
|
234
|
+
assert_equal "complete blew up", error.message
|
|
235
|
+
assert_same multi, easy.multi
|
|
236
|
+
assert_equal({}, multi.requests)
|
|
237
|
+
|
|
238
|
+
easy.on_complete { |_curl| }
|
|
239
|
+
easy.perform
|
|
240
|
+
|
|
241
|
+
assert_same multi, easy.multi
|
|
242
|
+
assert_equal "GET", easy.body_str
|
|
243
|
+
ensure
|
|
244
|
+
easy.multi = nil if defined?(easy) && easy && easy.multi.equal?(multi)
|
|
245
|
+
multi.close if defined?(multi) && multi
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def test_perform_restores_cached_implicit_multi_after_callback_error
|
|
249
|
+
Curl::Multi.autoclose = false
|
|
250
|
+
|
|
251
|
+
easy = Curl::Easy.new(TestServlet.url)
|
|
252
|
+
easy.perform
|
|
253
|
+
|
|
254
|
+
cached_multi = easy.multi
|
|
255
|
+
easy.on_complete { raise "complete blew up" }
|
|
256
|
+
|
|
257
|
+
error = assert_raise(Curl::Err::AbortedByCallbackError) { easy.perform }
|
|
258
|
+
assert_equal "complete blew up", error.message
|
|
259
|
+
assert_same cached_multi, easy.multi
|
|
260
|
+
assert_equal({}, cached_multi.requests)
|
|
261
|
+
|
|
262
|
+
easy.on_complete { |_curl| }
|
|
263
|
+
easy.perform
|
|
264
|
+
|
|
265
|
+
assert_same cached_multi, easy.multi
|
|
266
|
+
assert_equal "GET", easy.body_str
|
|
267
|
+
ensure
|
|
268
|
+
easy.multi = nil if defined?(easy) && easy
|
|
269
|
+
cached_multi.close if defined?(cached_multi) && cached_multi
|
|
270
|
+
Curl::Multi.autoclose = false
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def test_close_clears_explicit_idle_easy_multi_reference
|
|
274
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
275
|
+
multi = Curl::Multi.new
|
|
276
|
+
easy.multi = multi
|
|
277
|
+
|
|
278
|
+
assert_same multi, easy.multi
|
|
279
|
+
assert_equal({}, multi.requests)
|
|
280
|
+
|
|
281
|
+
multi.close
|
|
282
|
+
|
|
283
|
+
assert_nil easy.multi
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def test_close_clears_cached_idle_easy_multi_reference
|
|
287
|
+
Curl::Multi.autoclose = false
|
|
288
|
+
|
|
289
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
290
|
+
easy.perform
|
|
291
|
+
|
|
292
|
+
cached_multi = easy.multi
|
|
293
|
+
assert_not_nil cached_multi
|
|
294
|
+
assert_equal({}, cached_multi.requests)
|
|
295
|
+
|
|
296
|
+
cached_multi.close
|
|
297
|
+
|
|
298
|
+
assert_nil easy.multi
|
|
299
|
+
ensure
|
|
300
|
+
easy.multi = nil if defined?(easy) && easy
|
|
301
|
+
Curl::Multi.autoclose = false
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def test_multi_assignment_rejects_non_multi_objects
|
|
305
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
306
|
+
|
|
307
|
+
error = assert_raise(TypeError) { easy.multi = Object.new }
|
|
308
|
+
|
|
309
|
+
assert_match(/Curl::Multi/, error.message)
|
|
310
|
+
assert_nil easy.multi
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def test_perform_can_reuse_explicit_multi_when_autoclose_is_enabled
|
|
314
|
+
Curl::Multi.autoclose = true
|
|
315
|
+
|
|
316
|
+
easy = Curl::Easy.new(TestServlet.url)
|
|
317
|
+
multi = Curl::Multi.new
|
|
318
|
+
|
|
319
|
+
easy.multi = multi
|
|
320
|
+
easy.perform
|
|
321
|
+
|
|
322
|
+
assert_nil easy.multi
|
|
323
|
+
assert_equal({}, multi.requests)
|
|
324
|
+
|
|
325
|
+
easy.multi = multi
|
|
326
|
+
easy.perform
|
|
327
|
+
|
|
328
|
+
assert_nil easy.multi
|
|
329
|
+
assert_equal({}, multi.requests)
|
|
330
|
+
assert_equal "GET", easy.body_str
|
|
331
|
+
ensure
|
|
332
|
+
easy.multi = nil if defined?(easy) && easy
|
|
333
|
+
multi.close if defined?(multi) && multi
|
|
334
|
+
Curl::Multi.autoclose = false
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def test_perform_reraises_on_body_exception_for_frozen_easy
|
|
338
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
339
|
+
callback_error = Class.new(RuntimeError)
|
|
340
|
+
easy.on_body { raise callback_error, "body blew up" }
|
|
341
|
+
easy.freeze
|
|
342
|
+
|
|
343
|
+
error = assert_raise(callback_error) { easy.perform }
|
|
344
|
+
|
|
345
|
+
assert_equal "body blew up", error.message
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def test_perform_preserves_implicit_multi_when_autoclose_is_disabled
|
|
349
|
+
Curl::Multi.autoclose = false
|
|
350
|
+
|
|
351
|
+
easy = Curl::Easy.new(TestServlet.url)
|
|
352
|
+
easy.perform
|
|
353
|
+
|
|
354
|
+
first_multi = easy.multi
|
|
355
|
+
assert_not_nil first_multi
|
|
356
|
+
assert_equal({}, first_multi.requests)
|
|
357
|
+
|
|
358
|
+
easy.perform
|
|
359
|
+
|
|
360
|
+
assert_same first_multi, easy.multi
|
|
361
|
+
assert_equal "GET", easy.body_str
|
|
362
|
+
ensure
|
|
363
|
+
easy.multi = nil if defined?(easy) && easy
|
|
364
|
+
first_multi.close if defined?(first_multi) && first_multi
|
|
365
|
+
Curl::Multi.autoclose = false
|
|
366
|
+
end
|
|
367
|
+
|
|
109
368
|
def test_curlopt_stderr_fails_with_tempdir
|
|
110
369
|
Tempfile.open('curb_test_curlopt_stderr') do |tempfile|
|
|
111
370
|
easy = Curl::Easy.new(TestServlet.url)
|
|
@@ -736,6 +995,27 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
736
995
|
assert_raises(ArgumentError) { c.resolve_mode = :bad }
|
|
737
996
|
end
|
|
738
997
|
|
|
998
|
+
def test_http_version_accessors
|
|
999
|
+
c = Curl::Easy.new
|
|
1000
|
+
assert_equal Curl::HTTP_NONE, c.http_version
|
|
1001
|
+
|
|
1002
|
+
c.http_version = Curl::HTTP_1_1
|
|
1003
|
+
assert_equal Curl::HTTP_1_1, c.http_version
|
|
1004
|
+
|
|
1005
|
+
if Curl.const_defined?(:HTTP_2TLS)
|
|
1006
|
+
c.http_version = Curl::HTTP_2TLS
|
|
1007
|
+
assert_equal Curl::HTTP_2TLS, c.http_version
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
if Curl.const_defined?(:HTTP_2_PRIOR_KNOWLEDGE)
|
|
1011
|
+
c.http_version = Curl::HTTP_2_PRIOR_KNOWLEDGE
|
|
1012
|
+
assert_equal Curl::HTTP_2_PRIOR_KNOWLEDGE, c.http_version
|
|
1013
|
+
end
|
|
1014
|
+
|
|
1015
|
+
c.http_version = nil
|
|
1016
|
+
assert_equal Curl::HTTP_NONE, c.http_version
|
|
1017
|
+
end
|
|
1018
|
+
|
|
739
1019
|
def test_enable_cookies
|
|
740
1020
|
c = Curl::Easy.new
|
|
741
1021
|
assert !c.enable_cookies?
|
|
@@ -900,7 +1180,85 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
900
1180
|
|
|
901
1181
|
assert_equal "PUT\nfoo=bar&encoded%20string=val", curl.body_str
|
|
902
1182
|
end
|
|
903
|
-
|
|
1183
|
+
|
|
1184
|
+
def test_post_body_from_to_s_keeps_string_buffer_alive
|
|
1185
|
+
post_body = Object.new
|
|
1186
|
+
def post_body.to_s
|
|
1187
|
+
'foo=bar&encoded%20string=val'
|
|
1188
|
+
end
|
|
1189
|
+
|
|
1190
|
+
curl = Curl::Easy.new(TestServlet.url)
|
|
1191
|
+
curl.post_body = post_body
|
|
1192
|
+
|
|
1193
|
+
assert_equal 'foo=bar&encoded%20string=val', curl.post_body
|
|
1194
|
+
|
|
1195
|
+
GC.start
|
|
1196
|
+
GC.compact if GC.respond_to?(:compact)
|
|
1197
|
+
|
|
1198
|
+
curl.perform
|
|
1199
|
+
assert_equal "POST\nfoo=bar&encoded%20string=val", curl.body_str
|
|
1200
|
+
end
|
|
1201
|
+
|
|
1202
|
+
def test_post_body_preserves_assigned_snapshot_when_original_string_is_mutated
|
|
1203
|
+
omit('CURLOPT_COPYPOSTFIELDS is not available in this build') unless Curl.const_defined?(:CURLOPT_COPYPOSTFIELDS)
|
|
1204
|
+
|
|
1205
|
+
curl = Curl::Easy.new(TestServlet.url)
|
|
1206
|
+
post_body = String.new('alpha=1')
|
|
1207
|
+
curl.post_body = post_body
|
|
1208
|
+
|
|
1209
|
+
post_body.replace('beta=2')
|
|
1210
|
+
|
|
1211
|
+
assert_equal 'beta=2', post_body
|
|
1212
|
+
assert_equal 'alpha=1', curl.post_body
|
|
1213
|
+
|
|
1214
|
+
curl.perform
|
|
1215
|
+
|
|
1216
|
+
assert_equal "POST\nalpha=1", curl.body_str
|
|
1217
|
+
assert_equal 'alpha=1', curl.post_body
|
|
1218
|
+
end
|
|
1219
|
+
|
|
1220
|
+
def test_setopt_postfields_keeps_string_buffer_alive
|
|
1221
|
+
curl = Curl::Easy.new(TestServlet.url)
|
|
1222
|
+
curl.set(Curl::CURLOPT_POSTFIELDS, 'foo=bar&encoded%20string=val')
|
|
1223
|
+
|
|
1224
|
+
assert_equal 'foo=bar&encoded%20string=val', curl.post_body
|
|
1225
|
+
|
|
1226
|
+
GC.start
|
|
1227
|
+
GC.compact if GC.respond_to?(:compact)
|
|
1228
|
+
|
|
1229
|
+
curl.perform
|
|
1230
|
+
assert_equal "POST\nfoo=bar&encoded%20string=val", curl.body_str
|
|
1231
|
+
end
|
|
1232
|
+
|
|
1233
|
+
def test_setopt_postfields_preserves_assigned_snapshot_when_original_string_is_mutated
|
|
1234
|
+
omit('CURLOPT_COPYPOSTFIELDS is not available in this build') unless Curl.const_defined?(:CURLOPT_COPYPOSTFIELDS)
|
|
1235
|
+
|
|
1236
|
+
curl = Curl::Easy.new(TestServlet.url)
|
|
1237
|
+
post_body = String.new('alpha=1')
|
|
1238
|
+
curl.set(Curl::CURLOPT_POSTFIELDS, post_body)
|
|
1239
|
+
|
|
1240
|
+
post_body.replace('beta=2')
|
|
1241
|
+
|
|
1242
|
+
assert_equal 'beta=2', post_body
|
|
1243
|
+
assert_equal 'alpha=1', curl.post_body
|
|
1244
|
+
|
|
1245
|
+
curl.perform
|
|
1246
|
+
|
|
1247
|
+
assert_equal "POST\nalpha=1", curl.body_str
|
|
1248
|
+
assert_equal 'alpha=1', curl.post_body
|
|
1249
|
+
end
|
|
1250
|
+
|
|
1251
|
+
def test_setopt_postfields_nil_preserves_post_request
|
|
1252
|
+
curl = Curl::Easy.new(TestServlet.url)
|
|
1253
|
+
curl.set(Curl::CURLOPT_POST, true)
|
|
1254
|
+
curl.set(Curl::CURLOPT_POSTFIELDS, nil)
|
|
1255
|
+
|
|
1256
|
+
curl.perform
|
|
1257
|
+
|
|
1258
|
+
assert_nil curl.post_body
|
|
1259
|
+
assert_equal "POST\n", curl.body_str
|
|
1260
|
+
end
|
|
1261
|
+
|
|
904
1262
|
def test_form_body_remote
|
|
905
1263
|
curl = Curl::Easy.new(TestServlet.url)
|
|
906
1264
|
curl.http_post('foo=bar', 'encoded%20string=val')
|
|
@@ -930,6 +1288,19 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
930
1288
|
}
|
|
931
1289
|
end
|
|
932
1290
|
|
|
1291
|
+
def test_multipart_form_reuse_clears_previous_form
|
|
1292
|
+
curl = Curl::Easy.new(TestServlet.url)
|
|
1293
|
+
curl.multipart_form_post = true
|
|
1294
|
+
curl.http_post(Curl::PostField.content('document_id', '5'))
|
|
1295
|
+
assert_match(/document_id/, curl.body_str)
|
|
1296
|
+
|
|
1297
|
+
curl.multipart_form_post = false
|
|
1298
|
+
curl.post_body = 'foo=bar'
|
|
1299
|
+
curl.http_post
|
|
1300
|
+
|
|
1301
|
+
assert_equal "POST\nfoo=bar", curl.body_str
|
|
1302
|
+
end
|
|
1303
|
+
|
|
933
1304
|
def test_delete_remote
|
|
934
1305
|
curl = Curl::Easy.new(TestServlet.url)
|
|
935
1306
|
curl.http_delete
|
|
@@ -1293,6 +1664,84 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
1293
1664
|
end
|
|
1294
1665
|
end
|
|
1295
1666
|
|
|
1667
|
+
def test_close_in_on_progress_is_blocked
|
|
1668
|
+
curl = Curl::Easy.new(TestServlet.url)
|
|
1669
|
+
did_raise = false
|
|
1670
|
+
|
|
1671
|
+
curl.on_progress do |_dltotal, _dlnow, _ultotal, _ulnow|
|
|
1672
|
+
unless did_raise
|
|
1673
|
+
begin
|
|
1674
|
+
curl.close
|
|
1675
|
+
rescue RuntimeError
|
|
1676
|
+
did_raise = true
|
|
1677
|
+
end
|
|
1678
|
+
end
|
|
1679
|
+
true
|
|
1680
|
+
end
|
|
1681
|
+
|
|
1682
|
+
curl.perform
|
|
1683
|
+
assert did_raise
|
|
1684
|
+
end
|
|
1685
|
+
|
|
1686
|
+
def test_close_in_on_debug_is_blocked
|
|
1687
|
+
curl = Curl::Easy.new(TestServlet.url)
|
|
1688
|
+
did_raise = false
|
|
1689
|
+
|
|
1690
|
+
curl.on_debug do |_type, _data|
|
|
1691
|
+
unless did_raise
|
|
1692
|
+
begin
|
|
1693
|
+
curl.close
|
|
1694
|
+
rescue RuntimeError
|
|
1695
|
+
did_raise = true
|
|
1696
|
+
end
|
|
1697
|
+
end
|
|
1698
|
+
end
|
|
1699
|
+
|
|
1700
|
+
curl.perform
|
|
1701
|
+
assert did_raise
|
|
1702
|
+
end
|
|
1703
|
+
|
|
1704
|
+
def test_close_in_upload_read_is_blocked
|
|
1705
|
+
curl = Curl::Easy.new(TestServlet.url)
|
|
1706
|
+
|
|
1707
|
+
reader_class = Class.new do
|
|
1708
|
+
attr_reader :close_blocked
|
|
1709
|
+
|
|
1710
|
+
def initialize(curl)
|
|
1711
|
+
@curl = curl
|
|
1712
|
+
@done = false
|
|
1713
|
+
@close_blocked = false
|
|
1714
|
+
end
|
|
1715
|
+
|
|
1716
|
+
def read(_len)
|
|
1717
|
+
return nil if @done
|
|
1718
|
+
|
|
1719
|
+
@done = true
|
|
1720
|
+
begin
|
|
1721
|
+
@curl.close
|
|
1722
|
+
rescue RuntimeError
|
|
1723
|
+
@close_blocked = true
|
|
1724
|
+
end
|
|
1725
|
+
|
|
1726
|
+
'hello'
|
|
1727
|
+
end
|
|
1728
|
+
|
|
1729
|
+
def seek(_offset, _whence = SEEK_SET)
|
|
1730
|
+
0
|
|
1731
|
+
end
|
|
1732
|
+
|
|
1733
|
+
def stat
|
|
1734
|
+
Struct.new(:size).new(5)
|
|
1735
|
+
end
|
|
1736
|
+
end
|
|
1737
|
+
|
|
1738
|
+
reader = reader_class.new(curl)
|
|
1739
|
+
curl.http_put(reader)
|
|
1740
|
+
|
|
1741
|
+
assert reader.close_blocked
|
|
1742
|
+
assert_equal "PUT\nhello", curl.body_str
|
|
1743
|
+
end
|
|
1744
|
+
|
|
1296
1745
|
def test_set_unsupported_options
|
|
1297
1746
|
curl = Curl::Easy.new
|
|
1298
1747
|
assert_raises TypeError do
|