ghazel-curb 0.6.2.3 → 0.7.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +8 -1
- data/Rakefile +20 -1
- data/ext/curb.c +34 -0
- data/ext/curb.h +6 -4
- data/ext/curb_easy.c +627 -181
- data/ext/curb_easy.h +28 -2
- data/ext/curb_errors.c +2 -0
- data/ext/curb_errors.h +1 -0
- data/ext/curb_macros.h +1 -1
- data/ext/curb_multi.c +155 -59
- data/ext/curb_postfield.c +61 -49
- data/ext/curb_upload.c +2 -2
- data/ext/extconf.rb +7 -2
- data/lib/curb.rb +94 -5
- data/tests/bug_curb_easy_post_with_string_no_content_length_header.rb +83 -0
- data/tests/bug_multi_segfault.rb +6 -2
- data/tests/bug_postfields_crash.rb +26 -0
- data/tests/bug_postfields_crash2.rb +57 -0
- data/tests/bugtests.rb +9 -0
- data/tests/helper.rb +21 -7
- data/tests/mem_check.rb +65 -0
- data/tests/tc_curl_download.rb +44 -1
- data/tests/tc_curl_easy.rb +181 -11
- data/tests/tc_curl_multi.rb +36 -3
- data/tests/tc_curl_postfield.rb +3 -1
- data/tests/timeout.rb +100 -0
- data/tests/timeout_server.rb +33 -0
- metadata +44 -5
data/lib/curb.rb
CHANGED
@@ -26,16 +26,24 @@ module Curl
|
|
26
26
|
def download(url, filename = url.split(/\?/).first.split(/\//).last, &blk)
|
27
27
|
curl = Curl::Easy.new(url, &blk)
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
output = if filename.is_a? IO
|
30
|
+
filename.binmode if filename.respond_to?(:binmode)
|
31
|
+
filename
|
32
|
+
else
|
33
|
+
File.open(filename, 'wb')
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
old_on_body = curl.on_body do |data|
|
31
38
|
result = old_on_body ? old_on_body.call(data) : data.length
|
32
39
|
output << data if result == data.length
|
33
40
|
result
|
34
41
|
end
|
35
|
-
|
36
42
|
curl.perform
|
37
|
-
|
38
|
-
|
43
|
+
ensure
|
44
|
+
output.close rescue IOError
|
45
|
+
end
|
46
|
+
|
39
47
|
return curl
|
40
48
|
end
|
41
49
|
end
|
@@ -142,6 +150,7 @@ module Curl
|
|
142
150
|
m = Curl::Multi.new
|
143
151
|
# configure the multi handle
|
144
152
|
multi_options.each { |k,v| m.send("#{k}=", v) }
|
153
|
+
callbacks = [:on_progress,:on_debug,:on_failure,:on_success,:on_body,:on_header]
|
145
154
|
|
146
155
|
urls_with_config.each do|conf|
|
147
156
|
c = conf.dup # avoid being destructive to input
|
@@ -151,6 +160,12 @@ module Curl
|
|
151
160
|
|
152
161
|
easy = Curl::Easy.new(url)
|
153
162
|
|
163
|
+
# assign callbacks
|
164
|
+
callbacks.each do |cb|
|
165
|
+
cbproc = c.delete(cb)
|
166
|
+
easy.send(cb,&cbproc) if cbproc
|
167
|
+
end
|
168
|
+
|
154
169
|
case method
|
155
170
|
when :post
|
156
171
|
fields = c.delete(:post_fields)
|
@@ -181,6 +196,80 @@ module Curl
|
|
181
196
|
end
|
182
197
|
m.perform
|
183
198
|
end
|
199
|
+
|
200
|
+
# call-seq:
|
201
|
+
#
|
202
|
+
# Curl::Multi.download(['http://example.com/p/a/t/h/file1.txt','http://example.com/p/a/t/h/file2.txt']){|c|}
|
203
|
+
#
|
204
|
+
# will create 2 new files file1.txt and file2.txt
|
205
|
+
#
|
206
|
+
# 2 files will be opened, and remain open until the call completes
|
207
|
+
#
|
208
|
+
# when using the :post or :put method, urls should be a hash, including the individual post fields per post
|
209
|
+
#
|
210
|
+
def download(urls,easy_options={},multi_options={},download_paths=nil,&blk)
|
211
|
+
errors = []
|
212
|
+
procs = []
|
213
|
+
files = []
|
214
|
+
urls_with_config = []
|
215
|
+
url_to_download_paths = {}
|
216
|
+
|
217
|
+
urls.each_with_index do|urlcfg,i|
|
218
|
+
if urlcfg.is_a?(Hash)
|
219
|
+
url = url[:url]
|
220
|
+
else
|
221
|
+
url = urlcfg
|
222
|
+
end
|
223
|
+
|
224
|
+
if download_paths and download_paths[i]
|
225
|
+
download_path = download_paths[i]
|
226
|
+
else
|
227
|
+
download_path = File.basename(url)
|
228
|
+
end
|
229
|
+
|
230
|
+
file = lambda do|dp|
|
231
|
+
file = File.open(dp,"wb")
|
232
|
+
procs << (lambda {|data| file.write data; data.size })
|
233
|
+
files << file
|
234
|
+
file
|
235
|
+
end.call(download_path)
|
236
|
+
|
237
|
+
if urlcfg.is_a?(Hash)
|
238
|
+
urls_with_config << urlcfg.merge({:on_body => procs.last}.merge(easy_options))
|
239
|
+
else
|
240
|
+
urls_with_config << {:url => url, :on_body => procs.last, :method => :get}.merge(easy_options)
|
241
|
+
end
|
242
|
+
url_to_download_paths[url] = {:path => download_path, :file => file} # store for later
|
243
|
+
end
|
244
|
+
|
245
|
+
if blk
|
246
|
+
# when injecting the block, ensure file is closed before yielding
|
247
|
+
Curl::Multi.http(urls_with_config, multi_options) do |c,code,method|
|
248
|
+
info = url_to_download_paths[c.url]
|
249
|
+
begin
|
250
|
+
file = info[:file]
|
251
|
+
files.reject!{|f| f == file }
|
252
|
+
file.close
|
253
|
+
rescue => e
|
254
|
+
errors << e
|
255
|
+
end
|
256
|
+
blk.call(c,info[:path])
|
257
|
+
end
|
258
|
+
else
|
259
|
+
Curl::Multi.http(urls_with_config, multi_options)
|
260
|
+
end
|
261
|
+
|
262
|
+
ensure
|
263
|
+
files.each {|f|
|
264
|
+
begin
|
265
|
+
f.close
|
266
|
+
rescue => e
|
267
|
+
errors << e
|
268
|
+
end
|
269
|
+
}
|
270
|
+
raise errors unless errors.empty?
|
271
|
+
end
|
272
|
+
|
184
273
|
end
|
185
274
|
end
|
186
275
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
=begin
|
2
|
+
From jwhitmire
|
3
|
+
Todd, I'm trying to use curb to post data to a REST url. We're using it to post support questions from our iphone app directly to tender. The post looks good to me, but curl is not adding the content-length header so I get a 411 length required response from the server.
|
4
|
+
|
5
|
+
Here's my post block, do you see anything obvious? Do I need to manually add the Content-Length header?
|
6
|
+
|
7
|
+
c = Curl::Easy.http_post(url) do |curl|
|
8
|
+
curl.headers["User-Agent"] = "Curl/Ruby"
|
9
|
+
if user
|
10
|
+
curl.headers["X-Multipass"] = user.multipass
|
11
|
+
else
|
12
|
+
curl.headers["X-Tender-Auth"] = TOKEN
|
13
|
+
end
|
14
|
+
curl.headers["Accept"] = "application/vnd.tender-v1+json"
|
15
|
+
|
16
|
+
curl.post_body = params.map{|f,k| "#{curl.escape(f)}=#{curl.escape(k)}"}.join('&')
|
17
|
+
|
18
|
+
curl.verbose = true
|
19
|
+
curl.follow_location = true
|
20
|
+
curl.enable_cookies = true
|
21
|
+
end
|
22
|
+
Any insight you care to share would be helpful. Thanks.
|
23
|
+
=end
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
25
|
+
require 'webrick'
|
26
|
+
class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
|
27
|
+
class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
|
28
|
+
|
29
|
+
class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
|
30
|
+
def test_bug_workaround
|
31
|
+
server = WEBrick::HTTPServer.new( :Port => 9999 )
|
32
|
+
server.mount_proc("/test") do|req,res|
|
33
|
+
assert_equal '15', req['Content-Length']
|
34
|
+
res.body = "hi"
|
35
|
+
res['Content-Type'] = "text/html"
|
36
|
+
end
|
37
|
+
|
38
|
+
thread = Thread.new(server) do|srv|
|
39
|
+
srv.start
|
40
|
+
end
|
41
|
+
params = {:cat => "hat", :foo => "bar"}
|
42
|
+
|
43
|
+
post_body = params.map{|f,k| "#{Curl::Easy.new.escape(f)}=#{Curl::Easy.new.escape(k)}"}.join('&')
|
44
|
+
c = Curl::Easy.http_post("http://127.0.0.1:9999/test",post_body) do |curl|
|
45
|
+
curl.headers["User-Agent"] = "Curl/Ruby"
|
46
|
+
curl.headers["X-Tender-Auth"] = "A Token"
|
47
|
+
curl.headers["Accept"] = "application/vnd.tender-v1+json"
|
48
|
+
|
49
|
+
curl.follow_location = true
|
50
|
+
curl.enable_cookies = true
|
51
|
+
end
|
52
|
+
|
53
|
+
server.shutdown
|
54
|
+
thread.join
|
55
|
+
end
|
56
|
+
def test_bug
|
57
|
+
server = WEBrick::HTTPServer.new( :Port => 9999 )
|
58
|
+
server.mount_proc("/test") do|req,res|
|
59
|
+
assert_equal '15', req['Content-Length']
|
60
|
+
res.body = "hi"
|
61
|
+
res['Content-Type'] = "text/html"
|
62
|
+
end
|
63
|
+
|
64
|
+
thread = Thread.new(server) do|srv|
|
65
|
+
srv.start
|
66
|
+
end
|
67
|
+
params = {:cat => "hat", :foo => "bar"}
|
68
|
+
|
69
|
+
c = Curl::Easy.http_post("http://127.0.0.1:9999/test") do |curl|
|
70
|
+
curl.headers["User-Agent"] = "Curl/Ruby"
|
71
|
+
curl.headers["X-Tender-Auth"] = "A Token"
|
72
|
+
curl.headers["Accept"] = "application/vnd.tender-v1+json"
|
73
|
+
|
74
|
+
curl.post_body = params.map{|f,k| "#{curl.escape(f)}=#{curl.escape(k)}"}.join('&')
|
75
|
+
|
76
|
+
curl.follow_location = true
|
77
|
+
curl.enable_cookies = true
|
78
|
+
end
|
79
|
+
|
80
|
+
server.shutdown
|
81
|
+
thread.join
|
82
|
+
end
|
83
|
+
end
|
data/tests/bug_multi_segfault.rb
CHANGED
@@ -6,5 +6,9 @@
|
|
6
6
|
$:.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','ext'))
|
7
7
|
$:.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','lib'))
|
8
8
|
require 'curb'
|
9
|
-
|
10
|
-
|
9
|
+
|
10
|
+
class BugMultiSegfault < Test::Unit::TestCase
|
11
|
+
def test_bug
|
12
|
+
multi = Curl::Multi.new
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# From GICodeWarrior:
|
2
|
+
#
|
3
|
+
# $ ruby crash_curb.rb
|
4
|
+
# crash_curb.rb:7: [BUG] Segmentation fault
|
5
|
+
# ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]
|
6
|
+
#
|
7
|
+
# Aborted
|
8
|
+
# crash_curb.rb:
|
9
|
+
# #!/usr/bin/ruby
|
10
|
+
# require 'rubygems'
|
11
|
+
# require 'curb'
|
12
|
+
#
|
13
|
+
# curl = Curl::Easy.new('http://example.com/')
|
14
|
+
# curl.multipart_form_post = true
|
15
|
+
# curl.http_post(Curl::PostField.file('test', 'test.xml'){'example data'})
|
16
|
+
# Ubuntu 9.10
|
17
|
+
# curb gem version 0.6.2.1
|
18
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
19
|
+
|
20
|
+
class BugPostFieldsCrash < Test::Unit::TestCase
|
21
|
+
def test_crash
|
22
|
+
curl = Curl::Easy.new('http://example.com/')
|
23
|
+
curl.multipart_form_post = true
|
24
|
+
curl.http_post(Curl::PostField.file('test', 'test.xml'){'example data'})
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Not sure if this is an IRB bug, but thought you guys should know.
|
2
|
+
#
|
3
|
+
# ** My Ruby version: ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]
|
4
|
+
# ** Version of Rubygems: 1.3.5
|
5
|
+
# ** Version of the Curb gem: 0.6.6.0
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# Transcript of IRB session:
|
9
|
+
# ------------------------------------------------------------------------------------------------------------------
|
10
|
+
# irb(main):001:0> a = {
|
11
|
+
# irb(main):002:1* :type => :pie,
|
12
|
+
# irb(main):003:1* :series => {
|
13
|
+
# irb(main):004:2* :names => [:a,:b],
|
14
|
+
# irb(main):005:2* :values => [70,30],
|
15
|
+
# irb(main):006:2* :colors => [:red,:green]
|
16
|
+
# irb(main):007:2> },
|
17
|
+
# irb(main):008:1* :output_format => :png
|
18
|
+
# irb(main):009:1> }
|
19
|
+
# => {:type=>:pie, :output_format=>:png, :series=>{:names=>[:a, :b], :values=>[70, 30], :colors=>[:red, :green]}}
|
20
|
+
# irb(main):010:0> post = []
|
21
|
+
# => []
|
22
|
+
# irb(main):011:0> require 'rubygems'
|
23
|
+
# => true
|
24
|
+
# irb(main):012:0> require 'curb'
|
25
|
+
# => true
|
26
|
+
# irb(main):013:0> include Curl
|
27
|
+
# => Object
|
28
|
+
# irb(main):014:0> a.each_pair do |k,v|
|
29
|
+
# irb(main):015:1* post << PostField.content(k,v)
|
30
|
+
# irb(main):016:1> end
|
31
|
+
# => {:type=>:pie, :output_format=>:png, :series=>{:names=>[:a, :b], :values=>[70, 30], :colors=>[:red, :green]}}
|
32
|
+
# irb(main):017:0> post
|
33
|
+
# /usr/lib/ruby/1.8/irb.rb:302: [BUG] Segmentation fault
|
34
|
+
# ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]
|
35
|
+
#
|
36
|
+
# Aborted
|
37
|
+
# ------------------------------------------------------------------------------------------------------------------
|
38
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
39
|
+
|
40
|
+
class BugPostFieldsCrash2 < Test::Unit::TestCase
|
41
|
+
def test_crash
|
42
|
+
a = {
|
43
|
+
:type => :pie,
|
44
|
+
:series => {
|
45
|
+
:names => [:a,:b],
|
46
|
+
:values => [70,30],
|
47
|
+
:colors => [:red,:green]
|
48
|
+
},
|
49
|
+
:output_format => :png
|
50
|
+
}
|
51
|
+
post = []
|
52
|
+
a.each_pair do |k,v|
|
53
|
+
post << Curl::PostField.content(k,v)
|
54
|
+
end
|
55
|
+
post.inspect
|
56
|
+
end
|
57
|
+
end
|
data/tests/bugtests.rb
ADDED
data/tests/helper.rb
CHANGED
@@ -11,6 +11,7 @@ $:.unshift($EXTDIR)
|
|
11
11
|
|
12
12
|
require 'curb'
|
13
13
|
require 'test/unit'
|
14
|
+
require 'fileutils'
|
14
15
|
|
15
16
|
$TEST_URL = "file://#{URI.escape(File.expand_path(__FILE__).tr('\\','/').tr(':','|'))}"
|
16
17
|
|
@@ -73,14 +74,18 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
73
74
|
end
|
74
75
|
|
75
76
|
def do_POST(req,res)
|
76
|
-
if req.
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
77
|
+
if req.query['filename'].nil?
|
78
|
+
if req.body
|
79
|
+
params = {}
|
80
|
+
req.body.split('&').map{|s| k,v=s.split('='); params[k] = v }
|
81
|
+
end
|
82
|
+
if params and params['s'] == '500'
|
83
|
+
res.status = 500
|
84
|
+
else
|
85
|
+
respond_with("POST\n#{req.body}",req,res)
|
86
|
+
end
|
82
87
|
else
|
83
|
-
respond_with(
|
88
|
+
respond_with(req.query['filename'],req,res)
|
84
89
|
end
|
85
90
|
end
|
86
91
|
|
@@ -93,6 +98,14 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
93
98
|
respond_with(:DELETE,req,res)
|
94
99
|
end
|
95
100
|
|
101
|
+
def do_PURGE(req,res)
|
102
|
+
respond_with(:PURGE,req,res)
|
103
|
+
end
|
104
|
+
|
105
|
+
def do_COPY(req,res)
|
106
|
+
respond_with(:COPY,req,res)
|
107
|
+
end
|
108
|
+
|
96
109
|
end
|
97
110
|
|
98
111
|
module TestServerMethods
|
@@ -165,5 +178,6 @@ module TestServerMethods
|
|
165
178
|
at_exit{exit_code.call}
|
166
179
|
|
167
180
|
end
|
181
|
+
rescue Errno::EADDRINUSE
|
168
182
|
end
|
169
183
|
end
|
data/tests/mem_check.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
+
#require 'rubygems'
|
3
|
+
#require 'rmem'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Run some tests to measure the memory usage of curb, these tests require fork and ps
|
7
|
+
#
|
8
|
+
class TestCurbMemory < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_easy_memory
|
11
|
+
easy_avg, easy_std = measure_object_memory(Curl::Easy)
|
12
|
+
printf "Easy average: %.2f kilobytes +/- %.2f kilobytes\n", easy_avg.to_f, easy_std.to_f
|
13
|
+
|
14
|
+
multi_avg, multi_std = measure_object_memory(Curl::Multi)
|
15
|
+
printf "Multi average: %.2f kilobytes +/- %.2f kilobytes\n", multi_avg.to_f, multi_std.to_f
|
16
|
+
|
17
|
+
# now that we have the average size of an easy handle lets see how much a multi request consumes with 10 requests
|
18
|
+
end
|
19
|
+
|
20
|
+
def c_avg(report)
|
21
|
+
sum = 0
|
22
|
+
report.each {|r| sum += r.last }
|
23
|
+
(sum.to_f / report.size)
|
24
|
+
end
|
25
|
+
|
26
|
+
def c_std(report,avg)
|
27
|
+
var = 0
|
28
|
+
report.each {|r| var += (r.last-avg)*(r.last-avg) }
|
29
|
+
Math.sqrt(var / (report.size-1))
|
30
|
+
end
|
31
|
+
|
32
|
+
def measure_object_memory(klass)
|
33
|
+
report = []
|
34
|
+
200.times do
|
35
|
+
res = mem_check do
|
36
|
+
obj = klass.new
|
37
|
+
end
|
38
|
+
report << res
|
39
|
+
end
|
40
|
+
avg = c_avg(report)
|
41
|
+
std = c_std(report,avg)
|
42
|
+
[avg,std]
|
43
|
+
end
|
44
|
+
|
45
|
+
def mem_check
|
46
|
+
# see: http://gist.github.com/264060 for inspiration of ps command line
|
47
|
+
rd, wr = IO.pipe
|
48
|
+
memory_usage = `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
|
49
|
+
fork do
|
50
|
+
before = `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
|
51
|
+
rd.close
|
52
|
+
yield
|
53
|
+
after = `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
|
54
|
+
wr.write((after - before))
|
55
|
+
wr.flush
|
56
|
+
wr.close
|
57
|
+
end
|
58
|
+
wr.close
|
59
|
+
total = rd.read.to_i
|
60
|
+
rd.close
|
61
|
+
Process.wait
|
62
|
+
# return the delta and the total
|
63
|
+
[memory_usage, total]
|
64
|
+
end
|
65
|
+
end
|
data/tests/tc_curl_download.rb
CHANGED
@@ -7,7 +7,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
|
|
7
7
|
server_setup
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
10
|
+
def test_download_url_to_file_via_string
|
11
11
|
dl_url = "http://127.0.0.1:9129/ext/curb_easy.c"
|
12
12
|
dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
|
13
13
|
|
@@ -18,6 +18,49 @@ class TestCurbCurlDownload < Test::Unit::TestCase
|
|
18
18
|
File.unlink(dl_path) if File.exist?(dl_path)
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_download_url_to_file_via_file_io
|
22
|
+
dl_url = "http://127.0.0.1:9129/ext/curb_easy.c"
|
23
|
+
dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
|
24
|
+
io = File.open(dl_path, 'wb')
|
25
|
+
|
26
|
+
curb = Curl::Easy.download(dl_url, io)
|
27
|
+
assert io.closed?
|
28
|
+
assert File.exist?(dl_path)
|
29
|
+
assert_equal File.read(File.join(File.dirname(__FILE__), '..','ext','curb_easy.c')), File.read(dl_path)
|
30
|
+
ensure
|
31
|
+
File.unlink(dl_path) if File.exist?(dl_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_download_url_to_file_via_io
|
35
|
+
dl_url = "http://127.0.0.1:9129/ext/curb_easy.c"
|
36
|
+
dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
|
37
|
+
reader, writer = IO.pipe
|
38
|
+
|
39
|
+
# Write to local file
|
40
|
+
fork do
|
41
|
+
begin
|
42
|
+
writer.close
|
43
|
+
File.open(dl_path, 'wb') { |file| file << reader.read }
|
44
|
+
ensure
|
45
|
+
reader.close rescue IOError # if the stream has already been closed
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Download remote source
|
50
|
+
begin
|
51
|
+
reader.close
|
52
|
+
curb = Curl::Easy.download(dl_url, writer)
|
53
|
+
Process.wait
|
54
|
+
ensure
|
55
|
+
writer.close rescue IOError # if the stream has already been closed, which occurs in Easy::download
|
56
|
+
end
|
57
|
+
|
58
|
+
assert File.exist?(dl_path)
|
59
|
+
assert_equal File.read(File.join(File.dirname(__FILE__), '..','ext','curb_easy.c')), File.read(dl_path)
|
60
|
+
ensure
|
61
|
+
File.unlink(dl_path) if File.exist?(dl_path)
|
62
|
+
end
|
63
|
+
|
21
64
|
def test_download_bad_url_gives_404
|
22
65
|
dl_url = "http://127.0.0.1:9129/this_file_does_not_exist.html"
|
23
66
|
dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
|