ethon 0.5.12 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +11 -0
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +1 -1
  7. data/Guardfile +9 -0
  8. data/ethon.gemspec +26 -0
  9. data/lib/ethon/curl.rb +0 -12
  10. data/lib/ethon/curls/constants.rb +6 -22
  11. data/lib/ethon/curls/functions.rb +38 -41
  12. data/lib/ethon/curls/infos.rb +19 -0
  13. data/lib/ethon/curls/options.rb +416 -219
  14. data/lib/ethon/curls/settings.rb +1 -0
  15. data/lib/ethon/easy.rb +12 -18
  16. data/lib/ethon/easy/callbacks.rb +40 -6
  17. data/lib/ethon/easy/debug_info.rb +46 -0
  18. data/lib/ethon/easy/mirror.rb +39 -0
  19. data/lib/ethon/easy/options.rb +17 -1235
  20. data/lib/ethon/easy/queryable.rb +6 -8
  21. data/lib/ethon/easy/response_callbacks.rb +1 -1
  22. data/lib/ethon/version.rb +1 -1
  23. data/profile/benchmarks.rb +137 -0
  24. data/profile/memory_leaks.rb +113 -0
  25. data/profile/perf_spec_helper.rb +36 -0
  26. data/profile/support/memory_test_helpers.rb +75 -0
  27. data/profile/support/os_memory_leak_tracker.rb +47 -0
  28. data/profile/support/ruby_object_leak_tracker.rb +48 -0
  29. data/spec/ethon/curl_spec.rb +27 -0
  30. data/spec/ethon/easy/callbacks_spec.rb +31 -0
  31. data/spec/ethon/easy/debug_info_spec.rb +52 -0
  32. data/spec/ethon/easy/form_spec.rb +76 -0
  33. data/spec/ethon/easy/header_spec.rb +78 -0
  34. data/spec/ethon/easy/http/custom_spec.rb +176 -0
  35. data/spec/ethon/easy/http/delete_spec.rb +20 -0
  36. data/spec/ethon/easy/http/get_spec.rb +89 -0
  37. data/spec/ethon/easy/http/head_spec.rb +79 -0
  38. data/spec/ethon/easy/http/options_spec.rb +50 -0
  39. data/spec/ethon/easy/http/patch_spec.rb +50 -0
  40. data/spec/ethon/easy/http/post_spec.rb +220 -0
  41. data/spec/ethon/easy/http/put_spec.rb +124 -0
  42. data/spec/ethon/easy/http_spec.rb +44 -0
  43. data/spec/ethon/easy/informations_spec.rb +82 -0
  44. data/spec/ethon/easy/mirror_spec.rb +39 -0
  45. data/spec/ethon/easy/operations_spec.rb +251 -0
  46. data/spec/ethon/easy/options_spec.rb +135 -0
  47. data/spec/ethon/easy/queryable_spec.rb +188 -0
  48. data/spec/ethon/easy/response_callbacks_spec.rb +50 -0
  49. data/spec/ethon/easy/util_spec.rb +27 -0
  50. data/spec/ethon/easy_spec.rb +105 -0
  51. data/spec/ethon/libc_spec.rb +13 -0
  52. data/spec/ethon/loggable_spec.rb +21 -0
  53. data/spec/ethon/multi/operations_spec.rb +297 -0
  54. data/spec/ethon/multi/options_spec.rb +70 -0
  55. data/spec/ethon/multi/stack_spec.rb +79 -0
  56. data/spec/ethon/multi_spec.rb +21 -0
  57. data/spec/spec_helper.rb +27 -0
  58. data/spec/support/localhost_server.rb +94 -0
  59. data/spec/support/server.rb +114 -0
  60. metadata +91 -31
  61. data/lib/ethon/curls/auth_types.rb +0 -25
  62. data/lib/ethon/curls/http_versions.rb +0 -22
  63. data/lib/ethon/curls/postredir.rb +0 -15
  64. data/lib/ethon/curls/protocols.rb +0 -36
  65. data/lib/ethon/curls/proxy_types.rb +0 -25
  66. data/lib/ethon/curls/ssl_versions.rb +0 -23
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ethon::Easy::Http::Put do
4
+ let(:easy) { Ethon::Easy.new }
5
+ let(:url) { "http://localhost:3001/" }
6
+ let(:params) { nil }
7
+ let(:form) { nil }
8
+ let(:put) { described_class.new(url, {:params => params, :body => form}) }
9
+
10
+ describe "#setup" do
11
+ context "when nothing" do
12
+ it "sets url" do
13
+ put.setup(easy)
14
+ expect(easy.url).to eq(url)
15
+ end
16
+
17
+ it "sets upload" do
18
+ easy.should_receive(:upload=).with(true)
19
+ put.setup(easy)
20
+ end
21
+
22
+ it "sets infilesize" do
23
+ easy.should_receive(:infilesize=).with(0)
24
+ put.setup(easy)
25
+ end
26
+
27
+ context "when requesting" do
28
+ it "makes a put request" do
29
+ put.setup(easy)
30
+ easy.perform
31
+ expect(easy.response_body).to include('"REQUEST_METHOD":"PUT"')
32
+ end
33
+ end
34
+ end
35
+
36
+ context "when params" do
37
+ let(:params) { {:a => "1&"} }
38
+
39
+ it "attaches escaped to url" do
40
+ put.setup(easy)
41
+ expect(easy.url).to eq("#{url}?a=1%26")
42
+ end
43
+
44
+ it "sets upload" do
45
+ easy.should_receive(:upload=).with(true)
46
+ put.setup(easy)
47
+ end
48
+
49
+ it "sets infilesize" do
50
+ easy.should_receive(:infilesize=).with(0)
51
+ put.setup(easy)
52
+ end
53
+
54
+ context "when requesting" do
55
+ before do
56
+ put.setup(easy)
57
+ easy.perform
58
+ end
59
+
60
+ it "makes a put request" do
61
+ expect(easy.response_body).to include('"REQUEST_METHOD":"PUT"')
62
+ end
63
+ end
64
+ end
65
+
66
+ context "when body" do
67
+ let(:form) { {:a => "1&b=2"} }
68
+
69
+ it "sets infilesize" do
70
+ easy.should_receive(:infilesize=).with(11)
71
+ put.setup(easy)
72
+ end
73
+
74
+ it "sets readfunction" do
75
+ easy.should_receive(:readfunction)
76
+ put.setup(easy)
77
+ end
78
+
79
+ it "sets upload" do
80
+ easy.should_receive(:upload=).with(true)
81
+ put.setup(easy)
82
+ end
83
+
84
+ context "when requesting" do
85
+ context "sending string body" do
86
+ before do
87
+ easy.headers = { 'Expect' => '' }
88
+ put.setup(easy)
89
+ easy.perform
90
+ end
91
+
92
+ it "makes a put request" do
93
+ expect(easy.response_body).to include('"REQUEST_METHOD":"PUT"')
94
+ end
95
+
96
+ it "submits a body" do
97
+ expect(easy.response_body).to include('"body":"a=1%26b%3D2"')
98
+ end
99
+ end
100
+
101
+ context "when injecting a file as body" do
102
+ let(:file) { File.open(__FILE__) }
103
+ let(:easy) do
104
+ e = Ethon::Easy.new(:url => url, :upload => true)
105
+ e.set_read_callback(file)
106
+ e.infilesize = File.size(file.path)
107
+ e
108
+ end
109
+
110
+ before do
111
+ easy.headers = { 'Expect' => '' }
112
+ easy.perform
113
+ end
114
+
115
+ it "submits file" do
116
+ expect(easy.response_body).to include("injecting")
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ context "when params and body"
123
+ end
124
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ethon::Easy::Http do
4
+ let(:easy) { Ethon::Easy.new }
5
+
6
+ describe "#http_request" do
7
+ let(:url) { "http://localhost:3001/" }
8
+ let(:action_name) { :get }
9
+ let(:options) { {} }
10
+
11
+ let(:get) { double(:setup) }
12
+ let(:get_class) { Ethon::Easy::Http::Get }
13
+
14
+ it "instanciates action" do
15
+ get.should_receive(:setup)
16
+ get_class.should_receive(:new).and_return(get)
17
+ easy.http_request(url, action_name, options)
18
+ end
19
+
20
+ context "when requesting" do
21
+ [ :get, :post, :put, :delete, :head, :patch, :options ].map do |action|
22
+ it "returns ok" do
23
+ easy.http_request(url, action, options)
24
+ easy.perform
25
+ expect(easy.return_code).to be(:ok)
26
+ end
27
+
28
+ unless action == :head
29
+ it "makes a #{action.to_s.upcase} request" do
30
+ easy.http_request(url, action, options)
31
+ easy.perform
32
+ expect(easy.response_body).to include("\"REQUEST_METHOD\":\"#{action.to_s.upcase}\"")
33
+ end
34
+ end
35
+ end
36
+
37
+ it "makes requests with custom HTTP verbs" do
38
+ easy.http_request(url, :purge, options)
39
+ easy.perform
40
+ expect(easy.response_body).to include(%{"REQUEST_METHOD":"PURGE"})
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ethon::Easy::Informations do
4
+ let(:easy) { Ethon::Easy.new }
5
+
6
+ before do
7
+ easy.url = "http://localhost:3001"
8
+ easy.perform
9
+ end
10
+
11
+ describe "#httpauth_avail" do
12
+ it "returns" do
13
+ expect(easy.httpauth_avail).to be
14
+ end
15
+ end
16
+
17
+ describe "#total_time" do
18
+ it "returns float" do
19
+ expect(easy.total_time).to be_a(Float)
20
+ end
21
+ end
22
+
23
+ describe "#starttransfer_time" do
24
+ it "returns float" do
25
+ expect(easy.starttransfer_time).to be_a(Float)
26
+ end
27
+ end
28
+
29
+ describe "#appconnect_time" do
30
+ it "returns float" do
31
+ expect(easy.appconnect_time).to be_a(Float)
32
+ end
33
+ end
34
+
35
+ describe "#pretransfer_time" do
36
+ it "returns float" do
37
+ expect(easy.pretransfer_time).to be_a(Float)
38
+ end
39
+ end
40
+
41
+ describe "#connect_time" do
42
+ it "returns float" do
43
+ expect(easy.connect_time).to be_a(Float)
44
+ end
45
+ end
46
+
47
+ describe "#namelookup_time" do
48
+ it "returns float" do
49
+ expect(easy.namelookup_time).to be_a(Float)
50
+ end
51
+ end
52
+
53
+ describe "#effective_url" do
54
+ it "returns url" do
55
+ expect(easy.effective_url).to match(/^http:\/\/localhost:3001\/?/)
56
+ end
57
+ end
58
+
59
+ describe "#primary_ip" do
60
+ it "returns localhost" do
61
+ expect(easy.primary_ip).to match(/::1|127\.0\.0\.1/)
62
+ end
63
+ end
64
+
65
+ describe "#response_code" do
66
+ it "returns 200" do
67
+ expect(easy.response_code).to eq(200)
68
+ end
69
+ end
70
+
71
+ describe "#redirect_count" do
72
+ it "returns 0" do
73
+ expect(easy.redirect_count).to eq(0)
74
+ end
75
+ end
76
+
77
+ describe "#supports_zlib?" do
78
+ it "returns true" do
79
+ expect(easy.supports_zlib?).to be_true
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ethon::Easy::Mirror do
4
+ let(:options) { nil }
5
+ let(:mirror) { described_class.new(options) }
6
+
7
+ describe ".informations_to_mirror" do
8
+ [
9
+ :return_code, :response_code, :response_body, :response_headers,
10
+ :total_time, :starttransfer_time, :appconnect_time,
11
+ :pretransfer_time, :connect_time, :namelookup_time,
12
+ :effective_url, :primary_ip, :redirect_count, :debug_info
13
+ ].each do |name|
14
+ it "contains #{name}" do
15
+ expect(described_class.informations_to_mirror).to include(name)
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "#to_hash" do
21
+ let(:options) { {:return_code => 1} }
22
+
23
+ it "returns mirror as hash" do
24
+ expect(mirror.to_hash).to eq(options)
25
+ end
26
+ end
27
+
28
+ describe "#log_informations" do
29
+ let(:options) { {:return_code => 1} }
30
+
31
+ it "returns hash" do
32
+ expect(mirror.log_informations).to be_a(Hash)
33
+ end
34
+
35
+ it "includes return code" do
36
+ expect(mirror.log_informations).to include(options)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,251 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ethon::Easy::Operations do
4
+ let(:easy) { Ethon::Easy.new }
5
+
6
+ describe "#handle" do
7
+ it "returns a pointer" do
8
+ expect(easy.handle).to be_a(FFI::Pointer)
9
+ end
10
+ end
11
+
12
+
13
+ describe "#perform" do
14
+ let(:url) { nil }
15
+ let(:timeout) { nil }
16
+ let(:connect_timeout) { nil }
17
+ let(:follow_location) { nil }
18
+ let(:max_redirs) { nil }
19
+ let(:user_pwd) { nil }
20
+ let(:http_auth) { nil }
21
+ let(:headers) { nil }
22
+ let(:protocols) { nil }
23
+ let(:redir_protocols) { nil }
24
+ let(:username) { nil }
25
+ let(:password) { nil }
26
+
27
+ before do
28
+ easy.url = url
29
+ easy.timeout = timeout
30
+ easy.connecttimeout = connect_timeout
31
+ easy.followlocation = follow_location
32
+ easy.maxredirs = max_redirs
33
+ easy.httpauth = http_auth
34
+ easy.headers = headers
35
+ easy.protocols = protocols
36
+ easy.redir_protocols = redir_protocols
37
+
38
+ if user_pwd
39
+ easy.userpwd = user_pwd
40
+ else
41
+ easy.username = username
42
+ easy.password = password
43
+ end
44
+
45
+ easy.perform
46
+ end
47
+
48
+ it "calls Curl.easy_perform" do
49
+ Ethon::Curl.should_receive(:easy_perform)
50
+ easy.perform
51
+ end
52
+
53
+ context "when url" do
54
+ let(:url) { "http://localhost:3001/" }
55
+
56
+ it "returns ok" do
57
+ expect(easy.return_code).to eq(:ok)
58
+ end
59
+
60
+ it "sets response body" do
61
+ expect(easy.response_body).to be
62
+ end
63
+
64
+ it "sets response headers" do
65
+ expect(easy.response_headers).to be
66
+ end
67
+
68
+ context "when request timed out" do
69
+ let(:url) { "http://localhost:3001/?delay=1" }
70
+ let(:timeout) { 1 }
71
+
72
+ it "returns operation_timedout" do
73
+ expect(easy.return_code).to eq(:operation_timedout)
74
+ end
75
+ end
76
+
77
+ context "when connection timed out" do
78
+ let(:url) { "http://localhost:3009" }
79
+ let(:connect_timeout) { 1 }
80
+
81
+ it "returns couldnt_connect" do
82
+ expect(easy.return_code).to eq(:couldnt_connect)
83
+ end
84
+ end
85
+
86
+ context "when no follow location" do
87
+ let(:url) { "http://localhost:3001/redirect" }
88
+ let(:follow_location) { false }
89
+
90
+ it "doesn't follow" do
91
+ expect(easy.response_code).to eq(302)
92
+ end
93
+ end
94
+
95
+ context "when follow location" do
96
+ let(:url) { "http://localhost:3001/redirect" }
97
+ let(:follow_location) { true }
98
+
99
+ it "follows" do
100
+ expect(easy.response_code).to eq(200)
101
+ end
102
+
103
+ context "when infinite redirect loop" do
104
+ let(:url) { "http://localhost:3001/bad_redirect" }
105
+ let(:max_redirs) { 5 }
106
+
107
+ context "when max redirect set" do
108
+ it "follows only x times" do
109
+ expect(easy.response_code).to eq(302)
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ context "when user agent" do
116
+ let(:headers) { { 'User-Agent' => 'Ethon' } }
117
+
118
+ it "sets" do
119
+ expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"')
120
+ end
121
+ end
122
+ end
123
+
124
+ context "when auth url" do
125
+ before { easy.url = url }
126
+
127
+ context "when basic auth" do
128
+ let(:url) { "http://localhost:3001/auth_basic/username/password" }
129
+
130
+ context "when no user_pwd" do
131
+ it "returns 401" do
132
+ expect(easy.response_code).to eq(401)
133
+ end
134
+ end
135
+
136
+ context "when invalid user_pwd" do
137
+ let(:user_pwd) { "invalid:invalid" }
138
+
139
+ it "returns 401" do
140
+ expect(easy.response_code).to eq(401)
141
+ end
142
+ end
143
+
144
+ context "when valid user_pwd" do
145
+ let(:user_pwd) { "username:password" }
146
+
147
+ it "returns 200" do
148
+ expect(easy.response_code).to eq(200)
149
+ end
150
+ end
151
+
152
+ context "when user and password" do
153
+ let(:username) { "username" }
154
+ let(:password) { "password" }
155
+
156
+ it "returns 200" do
157
+ expect(easy.response_code).to eq(200)
158
+ end
159
+ end
160
+ end
161
+
162
+ context "when ntlm" do
163
+ let(:url) { "http://localhost:3001/auth_ntlm" }
164
+ let(:http_auth) { :ntlm }
165
+
166
+ context "when no user_pwd" do
167
+ it "returns 401" do
168
+ expect(easy.response_code).to eq(401)
169
+ end
170
+ end
171
+
172
+ context "when user_pwd" do
173
+ let(:user_pwd) { "username:password" }
174
+
175
+ it "returns 200" do
176
+ expect(easy.response_code).to eq(200)
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ context "when protocols" do
183
+ context "when asking for a allowed url" do
184
+ let(:url) { "http://localhost:3001" }
185
+ let(:protocols) { :http }
186
+
187
+ it "returns ok" do
188
+ expect(easy.return_code).to be(:ok)
189
+ end
190
+ end
191
+
192
+ context "when asking for a not allowed url" do
193
+ let(:url) { "http://localhost:3001" }
194
+ let(:protocols) { :https }
195
+
196
+ it "returns unsupported_protocol" do
197
+ expect(easy.return_code).to be(:unsupported_protocol)
198
+ end
199
+ end
200
+ end
201
+
202
+ context "when multiple protocols" do
203
+ context "when asking for a allowed url" do
204
+ let(:protocols) { [:http, :https] }
205
+
206
+ context "when http" do
207
+ let(:url) { "http://localhost:3001" }
208
+
209
+ it "returns ok for http" do
210
+ expect(easy.return_code).to be(:ok)
211
+ end
212
+ end
213
+
214
+ context "when https" do
215
+ let(:url) { "https://localhost:3001" }
216
+
217
+ it "returns ssl_connect_error for https" do
218
+ expect(easy.return_code).to be(:ssl_connect_error)
219
+ end
220
+ end
221
+ end
222
+
223
+ context "when asking for a not allowed url" do
224
+ let(:url) { "ssh://localhost" }
225
+ let(:protocols) { [:https, :http] }
226
+
227
+ it "returns unsupported_protocol" do
228
+ expect(easy.return_code).to be(:unsupported_protocol)
229
+ end
230
+ end
231
+ end
232
+
233
+ context "when redir_protocols" do
234
+ context "when redirecting to a not allowed url" do
235
+ let(:url) { "http://localhost:3001/redirect" }
236
+ let(:follow_location) { true }
237
+ let(:redir_protocols) { :https }
238
+
239
+ it "returns unsupported_protocol" do
240
+ expect(easy.return_code).to be(:unsupported_protocol)
241
+ end
242
+ end
243
+ end
244
+
245
+ context "when no url" do
246
+ it "returns url_malformat" do
247
+ expect(easy.perform).to eq(:url_malformat)
248
+ end
249
+ end
250
+ end
251
+ end