ethon 0.5.12 → 0.6.0
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 +15 -0
- data/.gitignore +7 -0
- data/.rspec +3 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -1
- data/Guardfile +9 -0
- data/ethon.gemspec +26 -0
- data/lib/ethon/curl.rb +0 -12
- data/lib/ethon/curls/constants.rb +6 -22
- data/lib/ethon/curls/functions.rb +38 -41
- data/lib/ethon/curls/infos.rb +19 -0
- data/lib/ethon/curls/options.rb +416 -219
- data/lib/ethon/curls/settings.rb +1 -0
- data/lib/ethon/easy.rb +12 -18
- data/lib/ethon/easy/callbacks.rb +40 -6
- data/lib/ethon/easy/debug_info.rb +46 -0
- data/lib/ethon/easy/mirror.rb +39 -0
- data/lib/ethon/easy/options.rb +17 -1235
- data/lib/ethon/easy/queryable.rb +6 -8
- data/lib/ethon/easy/response_callbacks.rb +1 -1
- data/lib/ethon/version.rb +1 -1
- data/profile/benchmarks.rb +137 -0
- data/profile/memory_leaks.rb +113 -0
- data/profile/perf_spec_helper.rb +36 -0
- data/profile/support/memory_test_helpers.rb +75 -0
- data/profile/support/os_memory_leak_tracker.rb +47 -0
- data/profile/support/ruby_object_leak_tracker.rb +48 -0
- data/spec/ethon/curl_spec.rb +27 -0
- data/spec/ethon/easy/callbacks_spec.rb +31 -0
- data/spec/ethon/easy/debug_info_spec.rb +52 -0
- data/spec/ethon/easy/form_spec.rb +76 -0
- data/spec/ethon/easy/header_spec.rb +78 -0
- data/spec/ethon/easy/http/custom_spec.rb +176 -0
- data/spec/ethon/easy/http/delete_spec.rb +20 -0
- data/spec/ethon/easy/http/get_spec.rb +89 -0
- data/spec/ethon/easy/http/head_spec.rb +79 -0
- data/spec/ethon/easy/http/options_spec.rb +50 -0
- data/spec/ethon/easy/http/patch_spec.rb +50 -0
- data/spec/ethon/easy/http/post_spec.rb +220 -0
- data/spec/ethon/easy/http/put_spec.rb +124 -0
- data/spec/ethon/easy/http_spec.rb +44 -0
- data/spec/ethon/easy/informations_spec.rb +82 -0
- data/spec/ethon/easy/mirror_spec.rb +39 -0
- data/spec/ethon/easy/operations_spec.rb +251 -0
- data/spec/ethon/easy/options_spec.rb +135 -0
- data/spec/ethon/easy/queryable_spec.rb +188 -0
- data/spec/ethon/easy/response_callbacks_spec.rb +50 -0
- data/spec/ethon/easy/util_spec.rb +27 -0
- data/spec/ethon/easy_spec.rb +105 -0
- data/spec/ethon/libc_spec.rb +13 -0
- data/spec/ethon/loggable_spec.rb +21 -0
- data/spec/ethon/multi/operations_spec.rb +297 -0
- data/spec/ethon/multi/options_spec.rb +70 -0
- data/spec/ethon/multi/stack_spec.rb +79 -0
- data/spec/ethon/multi_spec.rb +21 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/localhost_server.rb +94 -0
- data/spec/support/server.rb +114 -0
- metadata +91 -31
- data/lib/ethon/curls/auth_types.rb +0 -25
- data/lib/ethon/curls/http_versions.rb +0 -22
- data/lib/ethon/curls/postredir.rb +0 -15
- data/lib/ethon/curls/protocols.rb +0 -36
- data/lib/ethon/curls/proxy_types.rb +0 -25
- data/lib/ethon/curls/ssl_versions.rb +0 -23
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ethon::Easy::Options do
|
4
|
+
let(:easy) { Ethon::Easy.new }
|
5
|
+
|
6
|
+
[
|
7
|
+
:accept_encoding, :cainfo, :capath, :connecttimeout, :connecttimeout_ms, :cookie,
|
8
|
+
:cookiejar, :cookiefile, :copypostfields, :customrequest, :dns_cache_timeout,
|
9
|
+
:followlocation, :forbid_reuse, :http_version, :httpauth, :httpget, :httppost,
|
10
|
+
:infilesize, :interface, :keypasswd, :maxredirs, :nobody, :nosignal,
|
11
|
+
:postfieldsize, :postredir, :protocols, :proxy, :proxyauth, :proxyport, :proxytype,
|
12
|
+
:proxyuserpwd, :readdata, :readfunction, :redir_protocols, :ssl_verifyhost,
|
13
|
+
:ssl_verifypeer, :sslcert, :sslcerttype, :sslkey, :sslkeytype, :sslversion,
|
14
|
+
:timeout, :timeout_ms, :unrestricted_auth, :upload, :url, :useragent,
|
15
|
+
:userpwd, :verbose
|
16
|
+
].each do |name|
|
17
|
+
describe "#{name}=" do
|
18
|
+
it "responds_to" do
|
19
|
+
expect(easy).to respond_to("#{name}=")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "sets option" do
|
23
|
+
Ethon::Easy.any_instance.should_receive(:set_callbacks)
|
24
|
+
Ethon::Curl.should_receive(:set_option).with do |option, _, _|
|
25
|
+
expect(option).to be(name)
|
26
|
+
end
|
27
|
+
value = case name
|
28
|
+
when :http_version
|
29
|
+
:httpv1_0
|
30
|
+
when :httpauth
|
31
|
+
:basic
|
32
|
+
when :protocols, :redir_protocols
|
33
|
+
:http
|
34
|
+
when :postredir
|
35
|
+
:post_301
|
36
|
+
when :proxytype
|
37
|
+
:http
|
38
|
+
when :sslversion
|
39
|
+
:default
|
40
|
+
when :httppost
|
41
|
+
FFI::Pointer::NULL
|
42
|
+
else
|
43
|
+
1
|
44
|
+
end
|
45
|
+
easy.method("#{name}=").call(value)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#httppost=" do
|
51
|
+
it "raises unless given a FFI::Pointer" do
|
52
|
+
expect{ easy.httppost = 1 }.to raise_error(Ethon::Errors::InvalidValue)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when requesting" do
|
57
|
+
let(:url) { "localhost:3001" }
|
58
|
+
let(:timeout) { nil }
|
59
|
+
let(:timeout_ms) { nil }
|
60
|
+
let(:connecttimeout) { nil }
|
61
|
+
let(:connecttimeout_ms) { nil }
|
62
|
+
let(:userpwd) { nil }
|
63
|
+
|
64
|
+
before do
|
65
|
+
easy.url = url
|
66
|
+
easy.timeout = timeout
|
67
|
+
easy.timeout_ms = timeout_ms
|
68
|
+
easy.connecttimeout = connecttimeout
|
69
|
+
easy.connecttimeout_ms = connecttimeout_ms
|
70
|
+
easy.userpwd = userpwd
|
71
|
+
easy.perform
|
72
|
+
end
|
73
|
+
|
74
|
+
context "when userpwd" do
|
75
|
+
context "when contains /" do
|
76
|
+
let(:url) { "localhost:3001/auth_basic/test/te%2Fst" }
|
77
|
+
let(:userpwd) { "test:te/st" }
|
78
|
+
|
79
|
+
it "works" do
|
80
|
+
expect(easy.response_code).to eq(200)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when timeout" do
|
86
|
+
let(:timeout) { 1 }
|
87
|
+
|
88
|
+
context "when request takes longer" do
|
89
|
+
let(:url) { "localhost:3001?delay=2" }
|
90
|
+
|
91
|
+
it "times out" do
|
92
|
+
expect(easy.return_code).to eq(:operation_timedout)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when connecttimeout" do
|
98
|
+
let(:connecttimeout) { 1 }
|
99
|
+
|
100
|
+
context "when cannot connect" do
|
101
|
+
let(:url) { "localhost:3002" }
|
102
|
+
|
103
|
+
it "times out" do
|
104
|
+
expect(easy.return_code).to eq(:couldnt_connect)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
if Ethon::Curl.version.match("c-ares")
|
110
|
+
context "when timeout_ms" do
|
111
|
+
let(:timeout_ms) { 900 }
|
112
|
+
|
113
|
+
context "when request takes longer" do
|
114
|
+
let(:url) { "localhost:3001?delay=1" }
|
115
|
+
|
116
|
+
it "times out" do
|
117
|
+
expect(easy.return_code).to eq(:operation_timedout)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when connecttimeout_ms" do
|
123
|
+
let(:connecttimeout_ms) { 1 }
|
124
|
+
|
125
|
+
context "when cannot connect" do
|
126
|
+
let(:url) { "localhost:3002" }
|
127
|
+
|
128
|
+
it "times out" do
|
129
|
+
expect(easy.return_code).to eq(:couldnt_connect)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Ethon::Easy::Queryable do
|
5
|
+
let(:hash) { {} }
|
6
|
+
let!(:easy) { Ethon::Easy.new }
|
7
|
+
let(:params) { Ethon::Easy::Params.new(easy, hash) }
|
8
|
+
|
9
|
+
describe "#to_s" do
|
10
|
+
context "when query_pairs empty" do
|
11
|
+
before { params.instance_variable_set(:@query_pairs, []) }
|
12
|
+
|
13
|
+
it "returns empty string" do
|
14
|
+
expect(params.to_s).to eq("")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when query_pairs not empty" do
|
19
|
+
context "when escape" do
|
20
|
+
before do
|
21
|
+
params.escape = true
|
22
|
+
end
|
23
|
+
|
24
|
+
{
|
25
|
+
'!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28',
|
26
|
+
')' => '%29', ';' => '%3B', ':' => '%3A', '@' => '%40',
|
27
|
+
'&' => '%26', '=' => '%3D', '+' => '%2B', '$' => '%24',
|
28
|
+
',' => '%2C', '/' => '%2F', '?' => '%3F', '#' => '%23',
|
29
|
+
'[' => '%5B', ']' => '%5D',
|
30
|
+
|
31
|
+
'<' => '%3C', '>' => '%3E', '"' => '%22', '{' => '%7B',
|
32
|
+
'}' => '%7D', '|' => '%7C', '\\' => '%5C', '`' => '%60',
|
33
|
+
'^' => '%5E', '%' => '%25', ' ' => '%20', "\0" => '%00',
|
34
|
+
|
35
|
+
'まつもと' => '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8',
|
36
|
+
}.each do |value, percent|
|
37
|
+
it "turns #{value.inspect} into #{percent}" do
|
38
|
+
params.instance_variable_set(:@query_pairs, [[:a, value]])
|
39
|
+
expect(params.to_s).to eq("a=#{percent}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
{
|
44
|
+
'.' => '%2E', '-' => '%2D', '_' => '%5F', '~' => '%7E',
|
45
|
+
}.each do |value, percent|
|
46
|
+
it "leaves #{value.inspect} instead of turning into #{percent}" do
|
47
|
+
params.instance_variable_set(:@query_pairs, [[:a, value]])
|
48
|
+
expect(params.to_s).to eq("a=#{value}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when no escape" do
|
54
|
+
before { params.instance_variable_set(:@query_pairs, [[:a, 1], [:b, 2]]) }
|
55
|
+
|
56
|
+
it "returns concatenated query string" do
|
57
|
+
expect(params.to_s).to eq("a=1&b=2")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when query_pairs contains a string" do
|
63
|
+
before { params.instance_variable_set(:@query_pairs, ["{a: 1}"]) }
|
64
|
+
|
65
|
+
it "returns correct string" do
|
66
|
+
expect(params.to_s).to eq("{a: 1}")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#build_query_pairs" do
|
72
|
+
let(:pairs) { params.method(:build_query_pairs).call(hash) }
|
73
|
+
|
74
|
+
context "when params is empty" do
|
75
|
+
it "returns empty array" do
|
76
|
+
expect(pairs).to eq([])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "when params is string" do
|
81
|
+
let(:hash) { "{a: 1}" }
|
82
|
+
|
83
|
+
it "wraps it in an array" do
|
84
|
+
expect(pairs).to eq([hash])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when params is simple hash" do
|
89
|
+
let(:hash) { {:a => 1, :b => 2} }
|
90
|
+
|
91
|
+
it "transforms" do
|
92
|
+
expect(pairs).to include([:a, 1])
|
93
|
+
expect(pairs).to include([:b, 2])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when params is a nested hash" do
|
98
|
+
let(:hash) { {:a => 1, :b => {:c => 2}} }
|
99
|
+
|
100
|
+
it "transforms" do
|
101
|
+
expect(pairs).to include([:a, 1])
|
102
|
+
expect(pairs).to include(["b[c]", 2])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when params contains an array" do
|
107
|
+
let(:hash) { {:a => 1, :b => [2, 3]} }
|
108
|
+
|
109
|
+
it "transforms" do
|
110
|
+
expect(pairs).to include([:a, 1])
|
111
|
+
expect(pairs).to include(["b[0]", 2])
|
112
|
+
expect(pairs).to include(["b[1]", 3])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "when params contains something nested in an array" do
|
117
|
+
context "when string" do
|
118
|
+
let(:hash) { {:a => {:b => ["hello", "world"]}} }
|
119
|
+
|
120
|
+
it "transforms" do
|
121
|
+
expect(pairs).to eq([["a[b][0]", "hello"], ["a[b][1]", "world"]])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "when hash" do
|
126
|
+
let(:hash) { {:a => {:b => [{:c =>1}, {:d => 2}]}} }
|
127
|
+
|
128
|
+
it "transforms" do
|
129
|
+
expect(pairs).to eq([["a[b][0][c]", 1], ["a[b][1][d]", 2]])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "when file" do
|
134
|
+
let(:file) { Tempfile.new("fubar") }
|
135
|
+
let(:file_info) { params.method(:file_info).call(file) }
|
136
|
+
let(:hash) { {:a => {:b => [file]}} }
|
137
|
+
|
138
|
+
it "transforms" do
|
139
|
+
expect(pairs).to eq([["a[b][0]", file_info]])
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
context "when params contains file" do
|
146
|
+
let(:file) { Tempfile.new("fubar") }
|
147
|
+
let(:file_info) { params.method(:file_info).call(file) }
|
148
|
+
let(:hash) { {:a => 1, :b => file} }
|
149
|
+
|
150
|
+
it "transforms" do
|
151
|
+
expect(pairs).to include([:a, 1])
|
152
|
+
expect(pairs).to include([:b, file_info])
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "when params key contains a null byte" do
|
157
|
+
let(:hash) { {:a => "1\0" } }
|
158
|
+
|
159
|
+
it "preserves" do
|
160
|
+
expect(pairs).to eq([[:a, "1\0"]])
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "when params value contains a null byte" do
|
165
|
+
let(:hash) { {"a\0" => 1 } }
|
166
|
+
|
167
|
+
it "preserves" do
|
168
|
+
expect(pairs).to eq([["a\0", 1]])
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "#empty?" do
|
174
|
+
context "when params empty" do
|
175
|
+
it "returns true" do
|
176
|
+
expect(params.empty?).to be_true
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context "when params not empty" do
|
181
|
+
let(:hash) { {:a => 1} }
|
182
|
+
|
183
|
+
it "returns false" do
|
184
|
+
expect(params.empty?).to be_false
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ethon::Easy::ResponseCallbacks do
|
4
|
+
let(:easy) { Ethon::Easy.new }
|
5
|
+
|
6
|
+
describe "#on_complete" do
|
7
|
+
it "responds" do
|
8
|
+
expect(easy).to respond_to(:on_complete)
|
9
|
+
end
|
10
|
+
|
11
|
+
context "when no block given" do
|
12
|
+
it "returns @on_complete" do
|
13
|
+
expect(easy.on_complete).to eq([])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when block given" do
|
18
|
+
it "stores" do
|
19
|
+
easy.on_complete { p 1 }
|
20
|
+
expect(easy.instance_variable_get(:@on_complete)).to have(1).items
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when multiple blocks given" do
|
25
|
+
it "stores" do
|
26
|
+
easy.on_complete { p 1 }
|
27
|
+
easy.on_complete { p 2 }
|
28
|
+
expect(easy.instance_variable_get(:@on_complete)).to have(2).items
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#complete" do
|
34
|
+
before do
|
35
|
+
easy.on_complete {|r| String.new(r.url) }
|
36
|
+
end
|
37
|
+
|
38
|
+
it "executes blocks and passes self" do
|
39
|
+
String.should_receive(:new).with(easy.url)
|
40
|
+
easy.complete
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when @on_complete nil" do
|
44
|
+
it "doesn't raise" do
|
45
|
+
easy.instance_variable_set(:@on_complete, nil)
|
46
|
+
expect{ easy.complete }.to_not raise_error(NoMethodError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ethon::Easy::Util do
|
4
|
+
class Dummy
|
5
|
+
include Ethon::Easy::Util
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:klass) { Dummy.new }
|
9
|
+
|
10
|
+
describe "escape_zero_byte" do
|
11
|
+
context "when value has no zero byte" do
|
12
|
+
let(:value) { "hello world" }
|
13
|
+
|
14
|
+
it "returns same value" do
|
15
|
+
expect(klass.escape_zero_byte(value)).to be(value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when value has zero byte" do
|
20
|
+
let(:value) { "hello \0world" }
|
21
|
+
|
22
|
+
it "returns escaped" do
|
23
|
+
expect(klass.escape_zero_byte(value)).to eq("hello \\0world")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ethon::Easy do
|
4
|
+
let(:easy) { Ethon::Easy.new }
|
5
|
+
|
6
|
+
describe ".new" do
|
7
|
+
it "inits curl" do
|
8
|
+
Ethon::Curl.should_receive(:init)
|
9
|
+
easy
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when options are empty" do
|
13
|
+
it "sets only callbacks" do
|
14
|
+
Ethon::Easy.any_instance.should_receive(:set_callbacks)
|
15
|
+
Ethon::Easy.should_receive(:set_option).never
|
16
|
+
easy
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when options not empty" do
|
21
|
+
context "when followlocation is set" do
|
22
|
+
let(:options) { { :followlocation => true } }
|
23
|
+
let(:easy) { Ethon::Easy.new(options) }
|
24
|
+
|
25
|
+
it "sets followlocation" do
|
26
|
+
Ethon::Easy.any_instance.should_receive(:set_callbacks)
|
27
|
+
Ethon::Curl.should_receive(:set_option).with do |option, value, _|
|
28
|
+
expect(option).to be(:followlocation)
|
29
|
+
expect(value).to be(true)
|
30
|
+
end
|
31
|
+
easy
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#set_attributes" do
|
38
|
+
context "when options are empty" do
|
39
|
+
it "sets only callbacks" do
|
40
|
+
Ethon::Easy.any_instance.should_receive(:set_callbacks)
|
41
|
+
Ethon::Easy.should_receive(:set_option).never
|
42
|
+
easy
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when options aren't empty" do
|
47
|
+
context "when valid key" do
|
48
|
+
it "sets" do
|
49
|
+
easy.should_receive(:verbose=).with(true)
|
50
|
+
easy.set_attributes({:verbose => true})
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when invalid key" do
|
55
|
+
it "raises invalid option error" do
|
56
|
+
expect{ easy.set_attributes({:fubar => 1}) }.to raise_error(Ethon::Errors::InvalidOption)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#reset" do
|
63
|
+
before { easy.url = "www.example.com" }
|
64
|
+
|
65
|
+
it "resets url" do
|
66
|
+
easy.reset
|
67
|
+
expect(easy.url).to be_nil
|
68
|
+
end
|
69
|
+
|
70
|
+
it "resets hash" do
|
71
|
+
easy.reset
|
72
|
+
expect(easy.instance_variable_get(:@hash)).to be_nil
|
73
|
+
end
|
74
|
+
|
75
|
+
it "resets easy handle" do
|
76
|
+
Ethon::Curl.should_receive(:easy_reset)
|
77
|
+
easy.reset
|
78
|
+
end
|
79
|
+
|
80
|
+
it "resets on_complete" do
|
81
|
+
easy.on_complete { p 1 }
|
82
|
+
easy.reset
|
83
|
+
expect(easy.on_complete).to be_empty
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#mirror" do
|
88
|
+
it "returns a Mirror" do
|
89
|
+
expect(easy.mirror).to be_a(Ethon::Easy::Mirror)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "builds from easy" do
|
93
|
+
Ethon::Easy::Mirror.should_receive(:from_easy).with(easy)
|
94
|
+
easy.mirror
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#log_inspect" do
|
99
|
+
[ :url, :response_code, :return_code, :total_time ].each do |name|
|
100
|
+
it "contains #{name}" do
|
101
|
+
expect(easy.log_inspect).to match name.to_s
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|