dkubb-fakeweb 1.1.2.6

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.
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rcov/rcovtask'
5
+
6
+ task :default => :test
7
+
8
+ desc "Run All Tests"
9
+ Rake::TestTask.new :test do |test|
10
+ test.test_files = ["test/**/*.rb"]
11
+ test.verbose = true
12
+ end
13
+
14
+ desc "Generate Documentation"
15
+ Rake::RDocTask.new do |rdoc|
16
+ rdoc.main = "README.rdoc"
17
+ rdoc.rdoc_dir = "doc"
18
+ rdoc.rdoc_files.include("README.rdoc", "CHANGELOG", "LICENSE.txt", "lib/*.rb")
19
+ rdoc.title = "FakeWeb API Documentation"
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.options << '--charset' << 'utf-8'
22
+ end
23
+
24
+ Rcov::RcovTask.new do |t|
25
+ t.test_files = FileList['test/**/test*.rb']
26
+ t.rcov_opts << "--sort coverage"
27
+ t.rcov_opts << "--exclude gems"
28
+ t.rcov_opts << "--no-validator-links"
29
+ end
30
+
31
+ desc %{Update ".manifest" with the latest list of project filenames. Respect\
32
+ .gitignore by excluding everything that git ignores. Update `files` and\
33
+ `test_files` arrays in "*.gemspec" file if it's present.}
34
+ task :manifest do
35
+ list = Dir['**/*'].sort
36
+ spec_file = Dir['*.gemspec'].first
37
+ list -= [spec_file] if spec_file
38
+
39
+ File.read('.gitignore').each_line do |glob|
40
+ glob = glob.chomp.sub(/^\//, '')
41
+ list -= Dir[glob]
42
+ list -= Dir["#{glob}/**/*"] if File.directory?(glob) and !File.symlink?(glob)
43
+ puts "excluding #{glob}"
44
+ end
45
+
46
+ if spec_file
47
+ spec = File.read spec_file
48
+ spec.gsub! /^(\s* s.(test_)?files \s* = \s* )( \[ [^\]]* \] | %w\( [^)]* \) )/mx do
49
+ assignment = $1
50
+ bunch = $2 ? list.grep(/^test\//) : list
51
+ '%s%%w(%s)' % [assignment, bunch.join(' ')]
52
+ end
53
+
54
+ File.open(spec_file, 'w') {|f| f << spec }
55
+ end
56
+ File.open('.manifest', 'w') {|f| f << list.join("\n") }
57
+ end
@@ -0,0 +1,67 @@
1
+ # FakeWeb - Ruby Helper for Faking Web Requests
2
+ # Copyright 2006 Blaine Cook <romeda@gmail.com>.
3
+ #
4
+ # FakeWeb is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # FakeWeb is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with FakeWeb; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
+
18
+ require 'rubygems'
19
+ gem 'httpclient', '>=2.1.2'
20
+ require 'httpclient'
21
+
22
+ class HTTPClient
23
+
24
+ LIBRARY_IDENTIFIER = :httpclient
25
+ FakeWeb.register_client_library(LIBRARY_IDENTIFIER)
26
+
27
+ alias :original_httpclient_do_get_block :do_get_block
28
+
29
+ def self.socket_type
30
+ FakeWeb::SocketDelegator
31
+ end
32
+
33
+ def do_get_block(req, proxy, conn, &block)
34
+ method = req.header.request_method.downcase.to_sym
35
+ uri = req.header.request_uri
36
+
37
+ if FakeWeb.registered_uri?(method, uri)
38
+ message = FakeWeb.response_for(method, LIBRARY_IDENTIFIER, uri, &block)
39
+ conn.push(message)
40
+ elsif FakeWeb.allow_net_connect?
41
+ original_httpclient_do_get_block(req, proxy, conn, &block)
42
+ else
43
+ raise FakeWeb::NetConnectNotAllowedError,
44
+ "Real HTTP connections are disabled. Unregistered request: #{req.header.request_method} #{uri}"
45
+ end
46
+ end
47
+
48
+ =begin
49
+ # Do we want this? I'd imagine it'd make unregistered urls unhappy...
50
+
51
+ # Make sure there's no chance of a connection being made
52
+ class Session
53
+ def query(req)
54
+ end
55
+ end
56
+ =end
57
+
58
+ end
59
+
60
+ # A uniform way to get fake content, for testing.
61
+ module HTTP
62
+ class Message
63
+ def get_content
64
+ self.body.content
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,67 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'stringio'
4
+
5
+ module Net #:nodoc: all
6
+
7
+ class BufferedIO
8
+ def initialize(io, debug_output = nil)
9
+ @read_timeout = 60
10
+ @rbuf = ''
11
+ @debug_output = debug_output
12
+
13
+ @io = case io
14
+ when Socket, OpenSSL::SSL::SSLSocket, IO
15
+ io
16
+ when String
17
+ File.exists?(io) ? File.open(io, "r") : StringIO.new(io)
18
+ end
19
+ raise "Unable to create local socket" unless @io
20
+ end
21
+ end
22
+
23
+
24
+ class HTTP
25
+
26
+ LIBRARY_IDENTIFIER = :net_http
27
+ FakeWeb.register_client_library(LIBRARY_IDENTIFIER)
28
+
29
+ def self.socket_type
30
+ FakeWeb::SocketDelegator
31
+ end
32
+
33
+ alias :original_net_http_request :request
34
+ alias :original_net_http_connect :connect
35
+
36
+ def request(request, body = nil, &block)
37
+ protocol = use_ssl ? "https" : "http"
38
+
39
+ path = request.path
40
+ path = URI.parse(request.path).request_uri if request.path =~ /^http/
41
+
42
+ uri = "#{protocol}://#{self.address}:#{self.port}#{path}"
43
+ method = request.method.downcase.to_sym
44
+
45
+ if FakeWeb.registered_uri?(method, uri)
46
+ @socket = Net::HTTP.socket_type.new
47
+ FakeWeb.response_for(method, LIBRARY_IDENTIFIER, uri, &block)
48
+ elsif FakeWeb.allow_net_connect?
49
+ original_net_http_connect
50
+ original_net_http_request(request, body, &block)
51
+ else
52
+ raise FakeWeb::NetConnectNotAllowedError,
53
+ "Real HTTP connections are disabled. Unregistered request: #{request.method} #{uri}"
54
+ end
55
+ end
56
+
57
+ def connect
58
+ end
59
+ end
60
+
61
+ # A uniform way to get fake content, for testing.
62
+ class HTTPResponse
63
+ def get_content
64
+ self.body
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,348 @@
1
+ module FakeWeb
2
+ CLIENT_LIBRARIES = []
3
+ def self.register_client_library(library_identifier)
4
+ CLIENT_LIBRARIES << library_identifier
5
+ end
6
+ end
7
+
8
+ require File.expand_path(File.join(File.dirname(__FILE__), 'fake_net_http'))
9
+ require File.expand_path(File.join(File.dirname(__FILE__), 'fake_httpclient'))
10
+ require 'singleton'
11
+
12
+ module OpenURI #:nodoc: all
13
+ class HTTPError < StandardError; end;
14
+ end
15
+
16
+ module FakeWeb
17
+
18
+
19
+ # Resets the FakeWeb Registry. This will force all subsequent web requests to
20
+ # behave as real requests.
21
+ def self.clean_registry
22
+ Registry.instance.clean_registry
23
+ end
24
+
25
+ # Enables or disables real HTTP connections for requests that don't match
26
+ # registered URIs.
27
+ #
28
+ # If you set <tt>FakeWeb.allow_net_connect = false</tt> and subsequently try
29
+ # to make a request to a URI you haven't registered with #register_uri, a
30
+ # NetConnectNotAllowedError will be raised. This is handy when you want to
31
+ # make sure your tests are self-contained, or want to catch the scenario
32
+ # when a URI is changed in implementation code without a corresponding test
33
+ # change.
34
+ #
35
+ # When <tt>FakeWeb.allow_net_connect = true</tt> (the default), requests to
36
+ # URIs not stubbed with FakeWeb are passed through to Net::HTTP.
37
+ def self.allow_net_connect=(allowed)
38
+ @allow_net_connect = allowed
39
+ end
40
+
41
+ # Enable pass-through to Net::HTTP by default.
42
+ self.allow_net_connect = true
43
+
44
+ # Returns +true+ if requests to URIs not registered with FakeWeb are passed
45
+ # through to Net::HTTP for normal processing (the default). Returns +false+
46
+ # if an exception is raised for these requests.
47
+ def self.allow_net_connect?
48
+ @allow_net_connect
49
+ end
50
+
51
+ # This exception is raised if you set <tt>FakeWeb.allow_net_connect =
52
+ # false</tt> and subsequently try to make a request to a URI you haven't
53
+ # stubbed.
54
+ class NetConnectNotAllowedError < StandardError; end;
55
+
56
+ # call-seq:
57
+ # FakeWeb.register_uri(method, uri, options)
58
+ # FakeWeb.register_uri(uri, options)
59
+ #
60
+ # Register requests using the HTTP method specified by the symbol +method+ for
61
+ # +uri+ to be handled according to +options+. If no +method+ is specified, or
62
+ # you explicitly specify <tt>:any</tt>, the response will be reigstered for
63
+ # any request for +uri+. +uri+ can be a +String+ or a +URI+ object. +options+
64
+ # must be either a +Hash+ or an +Array+ of +Hashes+ (see below) that must
65
+ # contain any one of the following keys:
66
+ #
67
+ # <tt>:string</tt>::
68
+ # Takes a +String+ argument that is returned as the body of the response.
69
+ # FakeWeb.register_uri(:get, 'http://example.com/', :string => "Hello World!")
70
+ # <tt>:file</tt>::
71
+ # Takes a valid filesystem path to a file that is slurped and returned as
72
+ # the body of the response.
73
+ # FakeWeb.register_uri(:post, 'http://example.com/', :file => "/tmp/my_response_body.txt")
74
+ # <tt>:response</tt>::
75
+ # Either an <tt>Net::HTTPResponse</tt>, an +IO+ or a +String+.
76
+ #
77
+ # The easier way by far is to pass the <tt>:response</tt> option to
78
+ # +register_uri+ as a +String+ or an (open for reads) +IO+ object which
79
+ # will be used as the complete HTTP response, including headers and body.
80
+ # If the string points to a readable file, this file will be used as the
81
+ # content for the request.
82
+ #
83
+ # To obtain a complete response document, you can use the +curl+ command,
84
+ # like so:
85
+ #
86
+ # curl -i http://www.example.com/ > response_for_www.example.com
87
+ #
88
+ # which can then be used in your test environment like so:
89
+ #
90
+ # FakeWeb.register_uri(:get, 'http://www.example.com/', :response => 'response_for_www.example.com')
91
+ #
92
+ # See the <tt>Net::HTTPResponse</tt>
93
+ # documentation[http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTPResponse.html]
94
+ # for more information on creating custom response objects.
95
+ #
96
+ # +options+ may also be an +Array+ containing a list of the above-described +Hash+.
97
+ # In this case, FakeWeb will rotate through each provided response, you may optionally
98
+ # provide:
99
+ #
100
+ # <tt>:times</tt>::
101
+ # The number of times this response will be used. Decremented by one each time it's called.
102
+ # FakeWeb will use the final provided request indefinitely, regardless of its :times parameter.
103
+ #
104
+ # Two optional arguments are also accepted:
105
+ #
106
+ # <tt>:status</tt>::
107
+ # Passing <tt>:status</tt> as a two-value array will set the response code
108
+ # and message. The defaults are <tt>200</tt> and <tt>OK</tt>, respectively.
109
+ # Example:
110
+ # FakeWeb.register_uri('http://www.example.com/', :response => "Go away!", :status => [ 404, "Not Found" ])
111
+ # <tt>:exception</tt>::
112
+ # The argument passed via <tt>:exception</tt> will be raised when the
113
+ # specified URL is requested. Any +Exception+ class is valid. Example:
114
+ # FakeWeb.register_uri('http://www.example.com/', :exception => Net::HTTPError)
115
+ #
116
+ def self.register_uri(*args)
117
+ method = :any
118
+ case args.length
119
+ when 3 then method, uri, options = *args
120
+ when 2 then uri, options = *args
121
+ else raise ArgumentError.new("wrong number of arguments (#{args.length} for method = :any, uri, options)")
122
+ end
123
+ Registry.instance.register_uri(method, uri, options)
124
+ end
125
+
126
+ # call-seq:
127
+ # FakeWeb.response_for(method, uri, client_library)
128
+ # FakeWeb.response_for(uri, client_library)
129
+ #
130
+ # When using Net::HTTP
131
+ # Returns the faked Net::HTTPResponse object associated with +uri+.
132
+ # When using HTTPClient
133
+ # Returns the faked HTTP::Message object associated with +uri+.
134
+ def self.response_for(*args, &block) #:nodoc: :yields: response
135
+ method = :any
136
+ case args.length
137
+ when 3 then method, client_library, uri = *args
138
+ when 2 then client_library, uri = *args
139
+ else raise ArgumentError.new("wrong number of arguments (#{args.length} for method = :any, uri)")
140
+ end
141
+ Registry.instance.response_for(method, uri, client_library, &block)
142
+ end
143
+
144
+ # call-seq:
145
+ # FakeWeb.registered_uri?(method, uri)
146
+ # FakeWeb.registered_uri?(uri)
147
+ #
148
+ # Returns true if +uri+ is registered with FakeWeb. You can optionally
149
+ # specify +method+ to limit the search to a certain HTTP method (or use
150
+ # <tt>:any</tt> to explicitly check against any method).
151
+ def self.registered_uri?(*args)
152
+ method = :any
153
+ case args.length
154
+ when 2 then method, uri = *args
155
+ when 1 then uri = *args
156
+ else raise ArgumentError.new("wrong number of arguments (#{args.length} for method = :any, uri)")
157
+ end
158
+ Registry.instance.registered_uri?(method, uri)
159
+ end
160
+
161
+ class Registry #:nodoc:
162
+ include Singleton
163
+
164
+ attr_accessor :uri_map
165
+
166
+ def initialize
167
+ clean_registry
168
+ end
169
+
170
+ def clean_registry
171
+ self.uri_map = Hash.new { |hash, key| hash[key] = Hash.new(&hash.default_proc) }
172
+ end
173
+
174
+ def register_uri(method, uri, options)
175
+ uri_map[normalize_uri(uri)][method] = [*[options]].flatten.collect { |option|
176
+ FakeWeb::Responder.new(method, uri, option, option[:times])
177
+ }
178
+ end
179
+
180
+ def registered_uri?(method, uri)
181
+ normalized_uri = normalize_uri(uri)
182
+ uri_map[normalized_uri].has_key?(method) || uri_map[normalized_uri].has_key?(:any)
183
+ end
184
+
185
+ def registered_uri(method, uri)
186
+ uri = normalize_uri(uri)
187
+ registered = registered_uri?(method, uri)
188
+ if registered && uri_map[uri].has_key?(method)
189
+ uri_map[uri][method]
190
+ elsif registered
191
+ uri_map[uri][:any]
192
+ else
193
+ nil
194
+ end
195
+ end
196
+
197
+ def response_for(method, uri, client_library, &block)
198
+ responses = registered_uri(method, uri)
199
+ return nil if responses.nil?
200
+
201
+ next_response = responses.last
202
+ responses.each { |response|
203
+ if response.times and response.times > 0
204
+ response.times -= 1
205
+ next_response = response
206
+ break
207
+ end
208
+ }
209
+
210
+ return next_response.response(client_library, &block)
211
+ end
212
+
213
+ private
214
+
215
+ def normalize_uri(uri)
216
+ case uri
217
+ when URI then uri
218
+ else
219
+ uri = 'http://' + uri unless uri.match('^https?://')
220
+ parsed_uri = URI.parse(uri)
221
+ parsed_uri.query = sort_query_params(parsed_uri.query)
222
+ parsed_uri
223
+ end
224
+ end
225
+
226
+ def sort_query_params(query)
227
+ return nil if query.nil? or query.empty?
228
+ query.split('&').sort.join('&')
229
+ end
230
+ end
231
+
232
+ module Response #:nodoc:
233
+ def read_body(*args, &block)
234
+ yield @body if block_given?
235
+ @body
236
+ end
237
+ end
238
+
239
+ class Responder #:nodoc:
240
+
241
+ attr_accessor :method, :uri, :options, :times
242
+
243
+ def initialize(method, uri, options, times)
244
+ self.method = method
245
+ self.uri = uri
246
+ self.options = options
247
+ self.times = times ? times : 1
248
+ end
249
+
250
+ def response(client_library, &block)
251
+ if has_baked_response?
252
+ response = baked_response
253
+ else
254
+ case client_library
255
+ when :net_http
256
+ code, msg = meta_information
257
+ response = Net::HTTPResponse.send(:response_class, code.to_s).new(uri, code.to_s, msg)
258
+ response.instance_variable_set(:@body, content)
259
+ when :httpclient
260
+ response = HTTP::Message.new_response(content)
261
+ end
262
+ end
263
+ case client_library
264
+ when :net_http
265
+ response.instance_variable_set(:@read, true)
266
+ response.extend FakeWeb::Response
267
+ end
268
+
269
+ optionally_raise(response)
270
+
271
+ yield response if block_given?
272
+
273
+ response
274
+ end
275
+
276
+ private
277
+
278
+ def content
279
+ [ :file, :string ].each do |map_option|
280
+ next unless options.has_key?(map_option)
281
+ return self.send("#{map_option}_response", options[map_option])
282
+ end
283
+
284
+ return ''
285
+ end
286
+
287
+ def file_response(path)
288
+ IO.readlines(path).join("\n")
289
+ end
290
+
291
+ def string_response(string)
292
+ string
293
+ end
294
+
295
+ def baked_response
296
+ resp = case options[:response]
297
+ when Net::HTTPResponse then options[:response]
298
+ when String
299
+ socket = Net::BufferedIO.new(options[:response])
300
+ r = Net::HTTPResponse.read_new(socket)
301
+ r.instance_eval { @header['transfer-encoding'] = nil }
302
+ r.reading_body(socket, true) {}
303
+ r
304
+ else raise StandardError, "Handler unimplemented for response #{options[:response]}"
305
+ end
306
+ end
307
+
308
+ def has_baked_response?
309
+ options.has_key?(:response)
310
+ end
311
+
312
+ def optionally_raise(response)
313
+ return unless options.has_key?(:exception)
314
+ ex_alloc = options[:exception].allocate
315
+ ex_instance = case ex_alloc
316
+ when Net::HTTPError, OpenURI::HTTPError
317
+ options[:exception].new('Exception from FakeWeb', response)
318
+ else options[:exception].new
319
+ end
320
+ raise ex_instance
321
+ end
322
+
323
+ def meta_information
324
+ if options.has_key?(:status); options[:status]
325
+ else; [ 200, 'OK' ]
326
+ end
327
+ end
328
+ end
329
+
330
+ class SocketDelegator #:nodoc:
331
+
332
+ def initialize(delegate=nil)
333
+ @delegate = nil
334
+ end
335
+
336
+ def method_missing(method, *args, &block)
337
+ return @delegate.send(method, *args, &block) if @delegate
338
+ return self.send("my_#{method}", *args, &block)
339
+ end
340
+
341
+ def my_closed?
342
+ @closed ||= true
343
+ end
344
+
345
+ def my_readuntil(*args)
346
+ end
347
+ end
348
+ end