fakeweb-master/ 0000755 0001750 0001750 00000000000 12247137163 013337 5 ustar boutil boutil fakeweb-master/fakeweb.gemspec 0000644 0001750 0001750 00000005376 12247137163 016323 0 ustar boutil boutil # encoding: utf-8
Gem::Specification.new do |s|
s.name = "fakeweb"
s.rubyforge_project = "fakeweb"
s.version = "1.3.0"
s.summary = "A tool for faking responses to HTTP requests"
s.homepage = "https://github.com/chrisk/fakeweb"
s.authors = ["Chris Kampmeier", "Blaine Cook"]
s.email = ["chris@kampers.net", "romeda@gmail.com"]
s.license = "MIT"
s.description = "FakeWeb is a helper for faking web requests in " +
"Ruby. It works at a global level, without " +
"modifying code or writing extensive stubs."
root_docs = %w(CHANGELOG LICENSE.txt README.rdoc)
s.extra_rdoc_files = root_docs
s.files = Dir["lib/**/*.rb"] + root_docs
s.require_paths = ["lib"]
s.rdoc_options = ["--charset=UTF-8"]
# Mocha's README says "versions 0.10.2, 0.10.3 & 0.11.0 of the
# Mocha gem were broken. Please do not use these versions."
broken_mocha_spec = ["!= 0.11.0", "!= 0.10.3", "!= 0.10.2"]
if RUBY_VERSION <= "1.8.6"
# Mocha 0.11.1 introduced a call to #define_method with a block
# parameter (like this: define_method { |*args, &blk| ... }),
# causing a syntax error in 1.8.6. It's still there as of the
# latest release, 0.13.3. Older versions of Mocha work great,
# though; 0.9.5 is the oldest I've tested so far.
s.add_development_dependency "mocha", [">= 0.9.5", "< 0.11.1"] + broken_mocha_spec
# Rake 0.9.1 had the same issue with 1.8.6, but it was fixed for
# the next release. Later on, Rake 0.9.6 and 10.0.3 were both
# released with code using String#end_with?, which only works in
# 1.8.7+; both times, 1.8.6-compatibility was restored for the
# next release.
s.add_development_dependency "rake", [">= 0.8.7", "!= 0.9.1", "!= 0.9.6", "!= 10.0.3"]
else
# Otherwise, prefer up-to-date dev tools
s.add_development_dependency "mocha", ["~> 0.14"] + broken_mocha_spec
s.add_development_dependency "rake", ["~> 10.0"]
# ZenTest (autotest) wants at least RubyGems 1.8, which is 1.8.7+
# only, as is RDoc, the main dependency of sdoc.
s.add_development_dependency "ZenTest", ["~> 4.9"]
s.add_development_dependency "sdoc"
end
if RUBY_VERSION >= "1.9.0"
s.add_development_dependency "simplecov", ["~> 0.7"]
s.add_development_dependency "simplecov-console", ["~> 0.1"]
# SimpleCov depends on multi_json, which as of 1.7.3 prints a
# warning when the Ruby 1.9 stdlib is the only available backend.
# See https://github.com/intridea/multi_json/commit/e7438e7ba2.
s.add_development_dependency "json", ["~> 1.7"]
end
if RUBY_PLATFORM == "java"
s.add_development_dependency "jruby-openssl", ["~> 0.8"]
end
end
fakeweb-master/.gitignore 0000644 0001750 0001750 00000000110 12247137163 015317 0 ustar boutil boutil /doc
/rdoc
/html
/coverage
/log
/pkg
/.bundle
/.idea
*.rbc
Gemfile.lock
fakeweb-master/LICENSE.txt 0000644 0001750 0001750 00000002111 12247137163 015155 0 ustar boutil boutil Copyright 2006-2010 Blaine Cook, Chris Kampmeier, and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
fakeweb-master/Rakefile 0000644 0001750 0001750 00000005261 12247137163 015010 0 ustar boutil boutil require 'rubygems'
require 'rake'
task :print_header do
version_string = `rvm current`.strip
version_string = RUBY_DESCRIPTION if !$?.success?
puts "\n# Starting tests using \e[1m#{version_string}\e[0m\n\n"
end
task :check_dependencies do
begin
require "bundler"
rescue LoadError
abort "Error: FakeWeb uses Bundler to manage development dependencies,\n" +
"but it's not installed. Try `gem install bundler`.\n\n"
end
system("bundle check") || abort
end
require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
test.test_files = FileList["test/**/*.rb"].exclude("test/test_helper.rb",
"test/helpers/**/*",
"test/vendor/**/*")
test.libs << "test"
test.verbose = false
test.warning = true
# This quells a JRuby warning from SimpleCov: "tracing (e.g.
# set_trace_func) will not capture all events without --debug flag".
# This flag changes two internal options: it enables the runtime's
# "full-trace" mode, then sets its "compile mode" to OFF so that
# all code runs through the interpreter. (See test_helper.rb for
# the Java and Ruby code exposing these.)
#
# Note that --debug is unrelated to lots of similar-sounding flags
# common to many implementations (-d, -D, --debugger, etc.) and so we
# don't need to set any of those. For details, see JRuby's
# util/cli/ArgumentProcessor.java.
test.ruby_opts << "--debug" if RUBY_PLATFORM == "java"
end
Rake::Task["test"].enhance ["test:preflight"]
Rake::Task["test"].clear_comments.add_description <<-DESC.gsub(/^ /, "")
Run preflight checks, then all tests (default task).
Set COVERAGE_REPORT=1 to produce an HTML-formatted code-coverage
report during the run. It will be written to /coverage.
DESC
namespace :test do
desc "Perform all startup checks without running tests"
task :preflight => [:print_header, :check_dependencies]
end
task :default => :test
desc "Remove build/test/release artifacts"
task :clean do
paths = %w(.rbx/ coverage/ doc/ Gemfile.lock log/ pkg/)
paths.each do |path|
rm_rf File.join(File.dirname(__FILE__), path)
end
end
if RUBY_VERSION >= "1.8.7"
rdoc_options = %w(--show-hash --charset utf-8 --github)
begin
require 'sdoc'
rdoc_options += %w(--format sdoc)
rescue LoadError
end
require 'rdoc/task'
Rake::RDocTask.new do |rdoc|
rdoc.title = "FakeWeb 1.3.0 API Documentation"
rdoc.main = "README.rdoc"
rdoc.rdoc_dir = "doc"
rdoc.options += rdoc_options
rdoc.rdoc_files.include("README.rdoc", "CHANGELOG", "LICENSE.txt", "lib/*.rb")
end
else
warn "Warning: RDoc requires ruby >= 1.8.7; doc tasks disabled"
end
fakeweb-master/lib/ 0000755 0001750 0001750 00000000000 12247137163 014105 5 ustar boutil boutil fakeweb-master/lib/fake_web/ 0000755 0001750 0001750 00000000000 12247137163 015650 5 ustar boutil boutil fakeweb-master/lib/fake_web/utility.rb 0000644 0001750 0001750 00000006330 12247137163 017702 0 ustar boutil boutil module FakeWeb
module Utility #:nodoc:
def self.decode_userinfo_from_header(header)
header.sub(/^Basic /, "").unpack("m").first
end
def self.encode_unsafe_chars_in_userinfo(userinfo)
unsafe_in_userinfo = /[^#{URI::REGEXP::PATTERN::UNRESERVED};&=+$,]|^(#{URI::REGEXP::PATTERN::ESCAPED})/
userinfo.split(":").map { |part| uri_escape(part, unsafe_in_userinfo) }.join(":")
end
def self.strip_default_port_from_uri(uri)
case uri
when %r{^http://} then uri.sub(%r{:80(/|$)}, '\1')
when %r{^https://} then uri.sub(%r{:443(/|$)}, '\1')
else uri
end
end
# Returns a string with a normalized version of a Net::HTTP request's URI.
def self.request_uri_as_string(net_http, request)
protocol = net_http.use_ssl? ? "https" : "http"
path = request.path
path = URI.parse(request.path).request_uri if request.path =~ /^http/
if request["authorization"] =~ /^Basic /
userinfo = FakeWeb::Utility.decode_userinfo_from_header(request["authorization"])
userinfo = FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) + "@"
else
userinfo = ""
end
"#{protocol}://#{userinfo}#{net_http.address}:#{net_http.port}#{path}"
end
# Wrapper that falls back to URI.escape for compatibility with 1.8
def self.uri_escape(*args)
houdini = URI.const_defined?(:Parser) ? URI::Parser.new : URI
houdini.escape(*args)
end
def self.produce_side_effects_of_net_http_request(request, body)
request.set_body_internal(body)
request.content_length = request.body.length unless request.body.nil?
end
def self.puts_warning_for_net_http_around_advice_libs_if_needed
libs = {"Samuel" => defined?(Samuel)}
warnings = libs.select { |_, loaded| loaded }.map do |name, _|
<<-TEXT.gsub(/ {10}/, '')
\e[1mWarning: FakeWeb was loaded after #{name}\e[0m
* #{name}'s code is being ignored when a request is handled by FakeWeb,
because both libraries work by patching Net::HTTP.
* To fix this, just reorder your requires so that FakeWeb is before #{name}.
TEXT
end
$stderr.puts "\n" + warnings.join("\n") + "\n" if warnings.any?
end
def self.record_loaded_net_http_replacement_libs
libs = {"RightHttpConnection" => defined?(RightHttpConnection)}
@loaded_net_http_replacement_libs = libs.map { |name, loaded| name if loaded }.compact
end
def self.puts_warning_for_net_http_replacement_libs_if_needed
libs = {"RightHttpConnection" => defined?(RightHttpConnection)}
warnings = libs.select { |_, loaded| loaded }.
reject { |name, _| @loaded_net_http_replacement_libs.include?(name) }.
map do |name, _|
<<-TEXT.gsub(/ {10}/, '')
\e[1mWarning: #{name} was loaded after FakeWeb\e[0m
* FakeWeb's code is being ignored, because #{name} replaces parts of
Net::HTTP without deferring to other libraries. This will break Net::HTTP requests.
* To fix this, just reorder your requires so that #{name} is before FakeWeb.
TEXT
end
$stderr.puts "\n" + warnings.join("\n") + "\n" if warnings.any?
end
end
end
fakeweb-master/lib/fake_web/responder.rb 0000644 0001750 0001750 00000007563 12247137163 020211 0 ustar boutil boutil module FakeWeb
class Responder #:nodoc:
attr_accessor :method, :uri, :options, :times
KNOWN_OPTIONS = [:body, :exception, :response, :status].freeze
def initialize(method, uri, options, times)
self.method = method
self.uri = uri
self.options = options
self.times = times ? times : 1
if options.has_key?(:file) || options.has_key?(:string)
print_file_string_options_deprecation_warning
options[:body] = options.delete(:file) || options.delete(:string)
end
end
def response(&block)
if has_baked_response?
response = baked_response
else
code, msg = meta_information
response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
response.instance_variable_set(:@body, body)
headers_extracted_from_options.each do |name, value|
if value.respond_to?(:each)
value.each { |v| response.add_field(name, v) }
else
response[name] = value
end
end
end
response.instance_variable_set(:@read, true)
response.extend FakeWeb::Response
optionally_raise(response)
yield response if block_given?
response
end
private
def headers_extracted_from_options
options.reject {|name, _| KNOWN_OPTIONS.include?(name) }.map { |name, value|
[name.to_s.split("_").map { |segment| segment.capitalize }.join("-"), value]
}
end
def body
body = options[:body]
return nil if body.to_s == ''
body = body.to_s if defined?(Pathname) && body.is_a?(Pathname)
if !body.include?("\0") && File.exist?(body) && !File.directory?(body)
File.read(body)
else
body
end
end
def baked_response
response = options[:response]
response = response.to_s if defined?(Pathname) && response.is_a?(Pathname)
if response.is_a?(String) || response.is_a?(IO) || response.is_a?(StringIO)
socket = Net::BufferedIO.new(response)
r = Net::HTTPResponse.read_new(socket)
# Store the original transfer-encoding
saved_transfer_encoding = r.instance_eval {
@header['transfer-encoding'] if @header.key?('transfer-encoding')
}
# Read the body of response
r.instance_eval { @header['transfer-encoding'] = nil }
r.reading_body(socket, true) {}
# Delete the transfer-encoding key from r.@header if there wasn't one;
# otherwise, restore the saved_transfer_encoding
if saved_transfer_encoding.nil?
r.instance_eval { @header.delete('transfer-encoding') }
else
r.instance_eval { @header['transfer-encoding'] = saved_transfer_encoding }
end
r
elsif response.is_a?(Net::HTTPResponse)
response
else
raise ArgumentError, "Handler not implemented for response #{response.inspect}"
end
end
def has_baked_response?
options.has_key?(:response)
end
def optionally_raise(response)
return unless options.has_key?(:exception)
case options[:exception].to_s
when "Net::HTTPError", "OpenURI::HTTPError"
raise options[:exception].new('Exception from FakeWeb', response)
else
raise options[:exception].new('Exception from FakeWeb')
end
end
def meta_information
options.has_key?(:status) ? options[:status] : [200, 'OK']
end
def print_file_string_options_deprecation_warning
which = options.has_key?(:file) ? :file : :string
first_external_caller = caller.detect { |line| !line.include?("/lib/fake_web") }
$stderr.puts
$stderr.puts "Deprecation warning: FakeWeb's :#{which} option has been renamed to :body."
$stderr.puts "Just replace :#{which} with :body in your FakeWeb.register_uri calls."
$stderr.puts "Called at #{first_external_caller}"
end
end
end
fakeweb-master/lib/fake_web/ext/ 0000755 0001750 0001750 00000000000 12247137163 016450 5 ustar boutil boutil fakeweb-master/lib/fake_web/ext/net_http.rb 0000644 0001750 0001750 00000004236 12247137163 020627 0 ustar boutil boutil require 'net/http'
require 'net/https'
require 'stringio'
module Net #:nodoc: all
class BufferedIO
def initialize_with_fakeweb(*args)
initialize_without_fakeweb(*args)
case @io
when Socket, OpenSSL::SSL::SSLSocket, StringIO, IO
# usable as-is
when String
if !@io.include?("\0") && File.exist?(@io) && !File.directory?(@io)
@io = File.open(@io, "r")
else
@io = StringIO.new(@io)
end
else
raise ArgumentError, "Unable to create fake socket from #{io}"
end
end
alias_method :initialize_without_fakeweb, :initialize
alias_method :initialize, :initialize_with_fakeweb
end
class HTTP
class << self
def socket_type_with_fakeweb
FakeWeb::StubSocket
end
alias_method :socket_type_without_fakeweb, :socket_type
alias_method :socket_type, :socket_type_with_fakeweb
end
def request_with_fakeweb(request, body = nil, &block)
FakeWeb.last_request = request
uri = FakeWeb::Utility.request_uri_as_string(self, request)
method = request.method.downcase.to_sym
if FakeWeb.registered_uri?(method, uri)
@socket = Net::HTTP.socket_type.new
FakeWeb::Utility.produce_side_effects_of_net_http_request(request, body)
FakeWeb.response_for(method, uri, &block)
elsif FakeWeb.allow_net_connect?(uri)
connect_without_fakeweb
request_without_fakeweb(request, body, &block)
else
uri = FakeWeb::Utility.strip_default_port_from_uri(uri)
raise FakeWeb::NetConnectNotAllowedError,
"Real HTTP connections are disabled. Unregistered request: #{request.method} #{uri}"
end
end
alias_method :request_without_fakeweb, :request
alias_method :request, :request_with_fakeweb
def connect_with_fakeweb
unless @@alredy_checked_for_net_http_replacement_libs ||= false
FakeWeb::Utility.puts_warning_for_net_http_replacement_libs_if_needed
@@alredy_checked_for_net_http_replacement_libs = true
end
nil
end
alias_method :connect_without_fakeweb, :connect
alias_method :connect, :connect_with_fakeweb
end
end
fakeweb-master/lib/fake_web/registry.rb 0000644 0001750 0001750 00000006711 12247137163 020052 0 ustar boutil boutil module FakeWeb
class Registry #:nodoc:
include Singleton
attr_accessor :uri_map, :passthrough_uri_map
def initialize
clean_registry
end
def clean_registry
self.uri_map = Hash.new { |hash, key| hash[key] = {} }
end
def register_uri(method, uri, options)
uri_map[normalize_uri(uri)][method] = [*[options]].flatten.collect do |option|
FakeWeb::Responder.new(method, uri, option, option[:times])
end
end
def registered_uri?(method, uri)
!responders_for(method, uri).empty?
end
def response_for(method, uri, &block)
responders = responders_for(method, uri)
return nil if responders.empty?
next_responder = responders.last
responders.each do |responder|
if responder.times and responder.times > 0
responder.times -= 1
next_responder = responder
break
end
end
next_responder.response(&block)
end
def register_passthrough_uri(uri)
self.passthrough_uri_map = {normalize_uri(uri) => {:any => true}}
end
def remove_passthrough_uri
self.passthrough_uri_map = {}
end
def passthrough_uri_matches?(uri)
uri = normalize_uri(uri)
uri_map_matches(passthrough_uri_map, :any, uri, URI) ||
uri_map_matches(passthrough_uri_map, :any, uri, Regexp)
end
private
def responders_for(method, uri)
uri = normalize_uri(uri)
uri_map_matches(uri_map, method, uri, URI) ||
uri_map_matches(uri_map, :any, uri, URI) ||
uri_map_matches(uri_map, method, uri, Regexp) ||
uri_map_matches(uri_map, :any, uri, Regexp) ||
[]
end
def uri_map_matches(map, method, uri, type_to_check = URI)
uris_to_check = variations_of_uri_as_strings(uri)
matches = map.select { |registered_uri, method_hash|
registered_uri.is_a?(type_to_check) && method_hash.has_key?(method)
}.select { |registered_uri, method_hash|
if type_to_check == URI
uris_to_check.include?(registered_uri.to_s)
elsif type_to_check == Regexp
uris_to_check.any? { |u| u.match(registered_uri) }
end
}
if matches.size > 1
raise MultipleMatchingURIsError,
"More than one registered URI matched this request: #{method.to_s.upcase} #{uri}"
end
matches.map { |_, method_hash| method_hash[method] }.first
end
def variations_of_uri_as_strings(uri_object)
normalized_uri = normalize_uri(uri_object.dup)
normalized_uri_string = normalized_uri.to_s
variations = [normalized_uri_string]
# if the port is implied in the original, add a copy with an explicit port
if normalized_uri.default_port == normalized_uri.port
variations << normalized_uri_string.sub(
/#{Regexp.escape(normalized_uri.request_uri)}$/,
":#{normalized_uri.port}#{normalized_uri.request_uri}")
end
variations
end
def normalize_uri(uri)
return uri if uri.is_a?(Regexp)
normalized_uri =
case uri
when URI then uri
when String
uri = 'http://' + uri unless uri.match('^https?://')
URI.parse(uri)
end
normalized_uri.query = sort_query_params(normalized_uri.query)
normalized_uri.normalize
end
def sort_query_params(query)
if query.nil? || query.empty?
nil
else
query.split('&').sort.join('&')
end
end
end
end
fakeweb-master/lib/fake_web/stub_socket.rb 0000644 0001750 0001750 00000000430 12247137163 020517 0 ustar boutil boutil module FakeWeb
class StubSocket #:nodoc:
Net::BufferedIO.instance_methods.grep(/_timeout$/).each do |timeout|
attr_accessor timeout
end
def initialize(*args)
end
def closed?
@closed ||= true
end
def readuntil(*args)
end
end
end
fakeweb-master/lib/fake_web/response.rb 0000644 0001750 0001750 00000000214 12247137163 020030 0 ustar boutil boutil module FakeWeb
module Response #:nodoc:
def read_body(*args, &block)
yield @body if block_given?
@body
end
end
end fakeweb-master/lib/fakeweb.rb 0000644 0001750 0001750 00000000107 12247137163 016034 0 ustar boutil boutil # So you can require "fakeweb" instead of "fake_web"
require "fake_web" fakeweb-master/lib/fake_web.rb 0000644 0001750 0001750 00000020666 12247137163 016207 0 ustar boutil boutil require 'singleton'
require 'fake_web/ext/net_http'
require 'fake_web/registry'
require 'fake_web/response'
require 'fake_web/responder'
require 'fake_web/stub_socket'
require 'fake_web/utility'
FakeWeb::Utility.record_loaded_net_http_replacement_libs
FakeWeb::Utility.puts_warning_for_net_http_around_advice_libs_if_needed
module FakeWeb
# Returns the version string for the copy of FakeWeb you have loaded.
VERSION = '1.3.0'
# Resets the FakeWeb Registry. This will force all subsequent web requests to
# behave as real requests.
def self.clean_registry
Registry.instance.clean_registry
end
# Enables or disables real HTTP connections for requests that don't match
# registered URIs.
#
# If you set FakeWeb.allow_net_connect = false and subsequently try
# to make a request to a URI you haven't registered with .register_uri, a
# NetConnectNotAllowedError will be raised. This is handy when you want to
# make sure your tests are self-contained, or want to catch the scenario
# when a URI is changed in implementation code without a corresponding test
# change.
#
# When FakeWeb.allow_net_connect = true (the default), requests to
# URIs not stubbed with FakeWeb are passed through to Net::HTTP.
#
# If you assign a +String+, +URI+, or +Regexp+ object, unstubbed requests
# will be allowed if they match that value. This is useful when you want to
# allow access to a local server for integration testing, while still
# preventing your tests from using the internet.
def self.allow_net_connect=(allowed)
case allowed
when String, URI, Regexp
@allow_all_connections = false
Registry.instance.register_passthrough_uri(allowed)
else
@allow_all_connections = allowed
Registry.instance.remove_passthrough_uri
end
end
# Enable pass-through to Net::HTTP by default.
self.allow_net_connect = true
# Returns +true+ if requests to URIs not registered with FakeWeb are passed
# through to Net::HTTP for normal processing (the default). Returns +false+
# if an exception is raised for these requests.
#
# If you've assigned a +String+, +URI+, or +Regexp+ to
# FakeWeb.allow_net_connect=, you must supply a URI to check
# against that filter. Otherwise, an ArgumentError will be raised.
def self.allow_net_connect?(uri = nil)
if Registry.instance.passthrough_uri_map.any?
raise ArgumentError, "You must supply a URI to test" if uri.nil?
Registry.instance.passthrough_uri_matches?(uri)
else
@allow_all_connections
end
end
# This exception is raised if you set FakeWeb.allow_net_connect =
# false and subsequently try to make a request to a URI you haven't
# stubbed.
class NetConnectNotAllowedError < StandardError; end;
# This exception is raised if a Net::HTTP request matches more than one of
# the stubs you've registered. To fix the problem, remove a duplicate
# registration or disambiguate any regular expressions by making them more
# specific.
class MultipleMatchingURIsError < StandardError; end;
# call-seq:
# FakeWeb.register_uri(method, uri, options)
#
# Register requests using the HTTP method specified by the symbol +method+
# for +uri+ to be handled according to +options+. If you specify the method
# :any, the response will be reigstered for any request for +uri+.
# +uri+ can be a +String+, +URI+, or +Regexp+ object. +options+ must be either
# a +Hash+ or an +Array+ of +Hashes+ (see below), which must contain one of
# these two keys:
#
# :body::
# A string which is used as the body of the response. If the string refers
# to a valid filesystem path, the contents of that file will be read and used
# as the body of the response instead. (This used to be two options,
# :string and :file, respectively. These are now deprecated.)
# :response::
# Either a Net::HTTPResponse, +IO+, +StringIO+, or +String+, which
# is used as the full response for the request.
#
# The easier way by far is to pass the :response option to
# +register_uri+ as a +String+ or an (open for reads) +IO+ object which
# will be used as the complete HTTP response, including headers and body.
# If the string points to a readable file, this file will be used as the
# content for the request.
#
# To obtain a complete response document, you can use the +curl+ command,
# like so:
#
# curl -i http://example.com > response_from_example.com
#
# which can then be used in your test environment like so:
#
# FakeWeb.register_uri(:get, "http://example.com", :response => "response_from_example.com")
#
# See the Net::HTTPResponse
# documentation[http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTPResponse.html]
# for more information on creating custom response objects.
#
# +options+ may also be an +Array+ containing a list of the above-described
# +Hash+. In this case, FakeWeb will rotate through each response. You can
# optionally repeat a response more than once before rotating:
#
# :times::
# The number of times this response will be used before moving on to the
# next one. The last response will be repeated indefinitely, regardless of
# its :times parameter.
#
# Two optional arguments are also accepted:
#
# :status::
# Passing :status as a two-value array will set the response code
# and message. The defaults are 200 and OK, respectively.
# Example:
# FakeWeb.register_uri(:get, "http://example.com", :body => "Go away!", :status => [404, "Not Found"])
# :exception::
# The argument passed via :exception will be raised when the
# specified URL is requested. Any +Exception+ class is valid. Example:
# FakeWeb.register_uri(:get, "http://example.com", :exception => Net::HTTPError)
#
# If you're using the :body response type, you can pass additional
# options to specify the HTTP headers to be used in the response. Example:
#
# FakeWeb.register_uri(:get, "http://example.com/index.txt", :body => "Hello", :content_type => "text/plain")
#
# You can also pass an array of header values to include a header in the
# response more than once:
#
# FakeWeb.register_uri(:get, "http://example.com", :set_cookie => ["name=value", "example=1"])
def self.register_uri(*args)
case args.length
when 3
Registry.instance.register_uri(*args)
when 2
print_missing_http_method_deprecation_warning(*args)
Registry.instance.register_uri(:any, *args)
else
raise ArgumentError.new("wrong number of arguments (#{args.length} for 3)")
end
end
# call-seq:
# FakeWeb.response_for(method, uri)
#
# Returns the faked Net::HTTPResponse object associated with +method+ and +uri+.
def self.response_for(*args, &block) #:nodoc: :yields: response
case args.length
when 2
Registry.instance.response_for(*args, &block)
when 1
print_missing_http_method_deprecation_warning(*args)
Registry.instance.response_for(:any, *args, &block)
else
raise ArgumentError.new("wrong number of arguments (#{args.length} for 2)")
end
end
# call-seq:
# FakeWeb.registered_uri?(method, uri)
#
# Returns true if a +method+ request for +uri+ is registered with FakeWeb.
# Specify a method of :any to check against all HTTP methods.
def self.registered_uri?(*args)
case args.length
when 2
Registry.instance.registered_uri?(*args)
when 1
print_missing_http_method_deprecation_warning(*args)
Registry.instance.registered_uri?(:any, *args)
else
raise ArgumentError.new("wrong number of arguments (#{args.length} for 2)")
end
end
# Returns the request object from the last request made via Net::HTTP.
def self.last_request
@last_request
end
def self.last_request=(request) #:nodoc:
@last_request = request
end
private
def self.print_missing_http_method_deprecation_warning(*args)
method = caller.first.match(/`(.*?)'/)[1]
new_args = args.map { |a| a.inspect }.unshift(":any")
new_args.last.gsub!(/^\{|\}$/, "").gsub!("=>", " => ") if args.last.is_a?(Hash)
$stderr.puts
$stderr.puts "Deprecation warning: FakeWeb requires an HTTP method argument (or use :any). Try this:"
$stderr.puts " FakeWeb.#{method}(#{new_args.join(', ')})"
$stderr.puts "Called at #{caller[1]}"
end
end
fakeweb-master/README.rdoc 0000644 0001750 0001750 00000017015 12247137163 015151 0 ustar boutil boutil = FakeWeb
FakeWeb is a helper for faking web requests in Ruby. It works at a global
level, without modifying code or writing extensive stubs.
== Installation
* You can install the latest release from RubyGems:
gem install fakeweb
Note that the gem was previously registered as +FakeWeb+, switching
to +fakeweb+ in 2009. All releases are available under the new name.
* If your application uses Bundler, add a line like this to your Gemfile:
gem "fakeweb", "~> 1.3"
You may want to specify :group => :test and/or
:require => false, depending on how you use Bundler.
* If you're developing a gem, add a line like this to your gemspec:
spec.add_development_dependency "fakeweb", ["~> 1.3"]
== Help and discussion
RDocs for the current release are available at http://fakeweb.rubyforge.org.
There's a mailing list for questions and discussion at
https://groups.google.com/d/forum/fakeweb-users.
The main source repository is https://github.com/chrisk/fakeweb.
{}[https://travis-ci.org/chrisk/fakeweb] FakeWeb's tests run at https://travis-ci.org/chrisk/fakeweb.
== Examples
Start by requiring FakeWeb:
require 'fakeweb'
=== Registering basic string responses
FakeWeb.register_uri(:get, "http://example.com/test1", :body => "Hello World!")
Net::HTTP.get(URI.parse("http://example.com/test1"))
=> "Hello World!"
Net::HTTP.get(URI.parse("http://example.com/test2"))
=> FakeWeb is bypassed and the response from a real request is returned
You can also call register_uri with a regular expression, to match
more than one URI.
FakeWeb.register_uri(:get, %r|http://example\.com/|, :body => "Hello World!")
Net::HTTP.get(URI.parse("http://example.com/test3"))
=> "Hello World!"
=== Replaying a recorded response
page = `curl -is http://www.google.com/`
FakeWeb.register_uri(:get, "http://www.google.com/", :response => page)
Net::HTTP.get(URI.parse("http://www.google.com/"))
# => Full response, including headers
=== Adding a custom status to the response
FakeWeb.register_uri(:get, "http://example.com/", :body => "Nothing to be found 'round here",
:status => ["404", "Not Found"])
Net::HTTP.start("example.com") do |req|
response = req.get("/")
response.code # => "404"
response.message # => "Not Found"
response.body # => "Nothing to be found 'round here"
end
=== Responding to any HTTP method
FakeWeb.register_uri(:any, "http://example.com", :body => "response for any HTTP method")
If you use the :any symbol, the URI you specify will be completely
stubbed out (regardless of the HTTP method of the request). This can be useful
for RPC-style services, where the HTTP method isn't significant. (Older
versions of FakeWeb always behaved like this, and didn't accept the first
+method+ argument above; this syntax is now deprecated.)
=== Rotating responses
You can optionally call FakeWeb.register_uri with an array of options
hashes; these are used, in order, to respond to repeated requests. Once you run
out of responses, further requests always receive the last response. (You can
also send a response more than once before rotating, by specifying a
:times option for that response.)
FakeWeb.register_uri(:delete, "http://example.com/posts/1",
[{:body => "Post 1 deleted.", :status => ["200", "OK"]},
{:body => "Post not found", :status => ["404", "Not Found"]}])
Net::HTTP.start("example.com") do |req|
req.delete("/posts/1").body # => "Post 1 deleted"
req.delete("/posts/1").body # => "Post not found"
req.delete("/posts/1").body # => "Post not found"
end
=== Using HTTP basic authentication
You can fake requests that use basic authentication by adding +userinfo+ strings
to your URIs:
FakeWeb.register_uri(:get, "http://example.com/secret", :body => "Unauthorized", :status => ["401", "Unauthorized"])
FakeWeb.register_uri(:get, "http://user:pass@example.com/secret", :body => "Authorized")
Net::HTTP.start("example.com") do |http|
req = Net::HTTP::Get.new("/secret")
http.request(req) # => "Unauthorized"
req.basic_auth("user", "pass")
http.request(req) # => "Authorized"
end
=== Clearing registered URIs
The FakeWeb registry is a singleton that lasts for the duration of your program,
maintaining every fake response you register. If needed, you can clean out the
registry and remove all registered URIs:
FakeWeb.clean_registry
=== Blocking all real requests
When you're using FakeWeb to replace _all_ of your requests, it's useful to
catch when requests are made for unregistered URIs (unlike the default
behavior, which is to pass those requests through to Net::HTTP as usual).
FakeWeb.allow_net_connect = false
Net::HTTP.get(URI.parse("http://example.com/"))
=> raises FakeWeb::NetConnectNotAllowedError
FakeWeb.allow_net_connect = true
Net::HTTP.get(URI.parse("http://example.com/"))
=> FakeWeb is bypassed and the response from a real request is returned
It's recommended that you set FakeWeb.allow_net_connect = false in the
setup for your tests.
==== Allowing requests to a specific server
If you want to prevent your tests from hitting the internet while allowing
access to a specific server for integration testing, you can assign a URI or
+Regexp+ to be used as a whitelist for outbound requests:
FakeWeb.allow_net_connect = %r[^https?://localhost]
Net::HTTP.get(URI.parse("http://localhost/path")) # => allowed
Net::HTTP.get(URI.parse("http://example.com/")) # => raises FakeWeb::NetConnectNotAllowedError
=== Specifying HTTP response headers
When you register a response using the :body option, you're only
setting the body of the response. If you want to add headers to these responses,
simply add the header as an option to +register_uri+:
FakeWeb.register_uri(:get, "http://example.com/hello.txt", :body => "Hello", :content_type => "text/plain")
This sets the "Content-Type" header in the response.
=== Checking the last request
It's often useful to retrieve the last request made by your code, so you can
write tests for its content. FakeWeb keeps track of the last request, whether it
was stubbed or not:
Net::HTTP.get(URI.parse("http://example.com"))
FakeWeb.last_request # => Net::HTTP::Get request object
== More info
FakeWeb lets you decouple your test environment from live services without
modifying code or writing extensive stubs.
In addition to the conceptual advantage of having idempotent request
behaviour, FakeWeb makes tests run faster than if they were made to remote (or
even local) web servers. It also makes it possible to run tests without a
network connection or in situations where the server is behind a firewall or
has host-based access controls.
FakeWeb works with anything based on Net::HTTP--both higher-level wrappers,
like OpenURI, as well as a ton of libraries for popular web services.
== Known Issues
* Request bodies are ignored, including PUT and POST parameters. If you need
different responses for different request bodies, you need to request
different URLs, and register different responses for each. (Query strings are
fully supported, though.) We're currently considering how the API should
change to add support for request bodies in 1.3.0. Your input would be really
helpful: see https://groups.google.com/d/msg/fakeweb-users/RNGQprEuQnM/ryCiMeBD91YJ
for a discussion of some different options. Thanks!
fakeweb-master/.travis.yml 0000644 0001750 0001750 00000000341 12247137163 015446 0 ustar boutil boutil language: ruby
rvm:
- 1.8.7
- ree
- 1.9.2
- 1.9.3
- 2.0.0
- ruby-head
- jruby-18mode
- jruby-19mode
- jruby-head
- rbx
before_install: gem install bundler --conservative --version '~> 1.3' --no-prerelease
fakeweb-master/test/ 0000755 0001750 0001750 00000000000 12247137163 014316 5 ustar boutil boutil fakeweb-master/test/test_timeouts.rb 0000644 0001750 0001750 00000002304 12247137163 017552 0 ustar boutil boutil require 'test_helper'
class TestTimeouts < Test::Unit::TestCase
def test_sending_timeout_accessors_after_starting_session
# this tests an HTTPS request because #ssl_timeout= raises otherwise
FakeWeb.register_uri(:get, "https://example.com", :status => [200, "OK"])
http = Net::HTTP.new("example.com", 443)
http.use_ssl = true
http.get("/")
timeouts = []
http.methods.grep(/_timeout=/).each do |setter|
http.send(setter, 5)
getter = setter.to_s.sub(/=$/, "")
timeouts << http.send(getter)
end
assert_equal [5], timeouts.uniq
end
def test_stub_socket_always_responds_to_read_timeout
FakeWeb.register_uri(:get, "http://example.com", :status => [200, "OK"])
http = Net::HTTP.new("example.com", 80)
http.get("/")
assert_respond_to http.instance_variable_get(:@socket), :read_timeout=
end
def test_stub_socket_only_responds_to_continue_timeout_under_193_or_later
FakeWeb.register_uri(:get, "http://example.com", :status => [200, "OK"])
http = Net::HTTP.new("example.com", 80)
http.get("/")
socket = http.instance_variable_get(:@socket)
assert_equal RUBY_VERSION >= "1.9.3", socket.respond_to?(:continue_timeout=)
end
end
fakeweb-master/test/test_last_request.rb 0000644 0001750 0001750 00000002263 12247137163 020420 0 ustar boutil boutil require 'test_helper'
class TestLastRequest < Test::Unit::TestCase
def test_last_request_returns_correct_net_http_request_class
FakeWeb.register_uri(:get, "http://example.com", :status => [200, "OK"])
Net::HTTP.start("example.com") { |http| http.get("/") }
assert_instance_of Net::HTTP::Get, FakeWeb.last_request
end
def test_last_request_has_correct_method_path_and_body_for_get
FakeWeb.register_uri(:get, "http://example.com", :status => [200, "OK"])
Net::HTTP.start("example.com") { |http| http.get("/") }
assert_equal "GET", FakeWeb.last_request.method
assert_equal "/", FakeWeb.last_request.path
assert_nil FakeWeb.last_request.body
assert_nil FakeWeb.last_request.content_length
end
def test_last_request_has_correct_method_path_and_body_for_post
FakeWeb.register_uri(:post, "http://example.com/posts", :status => [201, "Created"])
Net::HTTP.start("example.com") { |http| http.post("/posts", "title=Test") }
assert_equal "POST", FakeWeb.last_request.method
assert_equal "/posts", FakeWeb.last_request.path
assert_equal "title=Test", FakeWeb.last_request.body
assert_equal 10, FakeWeb.last_request.content_length
end
end
fakeweb-master/test/test_helper.rb 0000644 0001750 0001750 00000014677 12247137163 017200 0 ustar boutil boutil require 'rubygems'
require 'bundler'
Bundler.setup
require 'helpers/start_simplecov'
require 'test/unit'
require 'open-uri'
require 'pathname'
require 'fake_web'
require 'rbconfig'
# See mocha's modifying
# https://github.com/freerange/mocha/commit/6df882d33ba785e0b43b224b7d625841d8e203be#lib/mocha/setup.rb
begin
require 'mocha/setup'
rescue LoadError
require 'mocha'
end
# Give all tests a common setup and teardown that prevents shared state
class Test::Unit::TestCase
alias setup_without_fakeweb setup
def setup
FakeWeb.clean_registry
@original_allow_net_connect = FakeWeb.allow_net_connect?
FakeWeb.allow_net_connect = false
end
alias teardown_without_fakeweb teardown
def teardown
FakeWeb.allow_net_connect = @original_allow_net_connect
end
end
module FakeWebTestHelper
BUILTIN_ASSERTIONS = Test::Unit::TestCase.instance_methods.select { |m| m.to_s =~ /^assert/ }.map { |m| m.to_sym }
# Backport assert_empty for Ruby 1.8 (it comes from MiniTest)
if !BUILTIN_ASSERTIONS.include?(:assert_empty)
def assert_empty(actual, message = nil)
message = build_message(message, "> is not empty", actual)
assert_block message do
actual.empty?
end
end
end
def fixture_path(basename)
"test/fixtures/#{basename}"
end
def capture_stderr
$stderr = StringIO.new
yield
$stderr.rewind && $stderr.read
ensure
$stderr = STDERR
end
# The path to the current ruby interpreter. Adapted from Rake's FileUtils.
def ruby_path
ext = ((RbConfig::CONFIG['ruby_install_name'] =~ /\.(com|cmd|exe|bat|rb|sh)$/) ? "" : RbConfig::CONFIG['EXEEXT'])
File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'] + ext).sub(/.*\s.*/m, '"\&"')
end
# Returns the name of the currently-running Test::Unit test method. This
# simply scans the call stack for the first method name starting with
# "test_". (TODO: is there a first-class way to retrieve this in Test::Unit?)
def current_test_name
caller.detect { |line| line =~ /:\d+:in `(test_\w+)'$/ }
$1.to_sym
end
def current_ruby_opts
ruby_opts = []
ruby_opts << "-w" if defined?($-w) && $-w
# When you start JRuby with --debug, it does this:
#
# # src/org/jruby/util/cli/ArgumentProcessor.java:371
# RubyInstanceConfig.FULL_TRACE_ENABLED = true;
# config.setCompileMode(RubyInstanceConfig.CompileMode.OFF);
#
# This checks the same settings from Rubyland. See our Rakefile for
# some background on --debug.
# TODO: is there a good way to retrieve the command-line options
# used to start JRuby? --debug doesn't seem to have an analogue of
# $-w, $-d, etc.
if RUBY_PLATFORM == "java" &&
JRuby.runtime.instance_config.class.FULL_TRACE_ENABLED &&
JRuby.runtime.instance_config.compile_mode.to_s == "OFF"
ruby_opts << "--debug"
end
ruby_opts
end
def remove_warnings_from_gems_and_stdlib(string)
code_paths = [RbConfig::CONFIG["libdir"],
File.expand_path(File.join(File.dirname(__FILE__), "vendor")),
Gem.path].flatten
splitter = string.respond_to?(:lines) ? :lines : :to_a
string.send(splitter).reject { |line|
line.strip.empty? ||
code_paths.any? { |path| line =~ /^#{Regexp.escape(path)}.+:\d+:? warning:/ }
}.join
end
# Sets several expectations (using Mocha) that a real HTTP request makes it
# past FakeWeb to the socket layer. You can use this when you need to check
# that a request isn't handled by FakeWeb.
def setup_expectations_for_real_request(options = {})
# Socket handling
if options[:port] == 443
socket = mock("SSLSocket")
OpenSSL::SSL::SSLSocket.expects(:===).with(socket).returns(true).at_least_once
OpenSSL::SSL::SSLSocket.expects(:new).with(socket, instance_of(OpenSSL::SSL::SSLContext)).returns(socket).at_least_once
socket.stubs(:sync_close=).returns(true)
socket.expects(:connect).with().at_least_once
if RUBY_VERSION >= "2.0.0" && RUBY_PLATFORM != "java"
socket.expects(:session).with().at_least_once
end
else
socket = mock("TCPSocket")
Socket.expects(:===).with(socket).at_least_once.returns(true)
end
# Net::HTTP#connect now sets TCP_NODELAY after opening the socket. See ruby-core:56158.
if RUBY_VERSION >= "2.1.0"
socket.stubs(:setsockopt).returns(0)
end
if RUBY_VERSION >= "2.0.0"
TCPSocket.expects(:open).with(options[:host], options[:port], nil, nil).returns(socket).at_least_once
else
TCPSocket.expects(:open).with(options[:host], options[:port]).returns(socket).at_least_once
end
socket.stubs(:closed?).returns(false)
socket.stubs(:close).returns(true)
# Request/response handling
request_parts = ["#{options[:method]} #{options[:path]} HTTP/1.1", "Host: #{options[:host]}"]
socket.expects(:write).with(all_of(includes(request_parts[0]), includes(request_parts[1]))).returns(100)
if !options[:request_body].nil?
socket.expects(:write).with(options[:request_body]).returns(100)
end
# MRI's Net::HTTP switched from #sysread to #read_nonblock in
# 1.9.2; although subsequent JRuby releases reported version
# numbers later than 1.9.2p0 when running in 1.9-mode, JRuby
# didn't switch until 1.7.4 (a.k.a. 1.9.3p392 in 1.9-mode):
# https://github.com/jruby/jruby/commit/d04857cb0f.
if RUBY_PLATFORM == "java" && ((RUBY_VERSION == "1.9.3" && RUBY_PATCHLEVEL >= 392) || RUBY_VERSION > "1.9.3")
read_method = :read_nonblock
elsif RUBY_PLATFORM != "java" && RUBY_VERSION >= "1.9.2"
read_method = :read_nonblock
else
read_method = :sysread
end
socket.expects(read_method).at_least_once.returns("HTTP/1.1 #{options[:response_code]} #{options[:response_message]}\nContent-Length: #{options[:response_body].length}\n\n#{options[:response_body]}").then.raises(EOFError)
end
# A helper that calls #setup_expectations_for_real_request for you, using
# defaults for our commonly used test request to images.apple.com.
def setup_expectations_for_real_apple_hot_news_request(options = {})
defaults = { :host => "images.apple.com", :port => 80, :method => "GET",
:path => "/main/rss/hotnews/hotnews.rss",
:response_code => 200, :response_message => "OK",
:response_body => "