diff options
62 files changed, 6304 insertions, 14 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2633aca4d..f6068120d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -504,12 +504,22 @@ class ApplicationController < ActionController::Base default = MySociety::Config.get('ISO_COUNTRY_CODE', '') country = "" if !gaze.empty? - country = open("#{gaze}/gaze-rest?f=get_country_from_ip;ip=#{request.remote_ip}").read.strip + country = quietly_try_to_open("#{gaze}/gaze-rest?f=get_country_from_ip;ip=#{request.remote_ip}") end country = default if country.empty? return country end + def quietly_try_to_open(url) + begin + result = open(url).read.strip + rescue OpenURI::HTTPError, SocketError + logger.warn("Unable to open third-party URL #{url}") + result = "" + end + return result + end + # URL generating functions are needed by all controllers (for redirects), # views (for links) and mailers (for use in emails), so include them into # all of all. diff --git a/app/controllers/general_controller.rb b/app/controllers/general_controller.rb index 6cdfb9d5f..d28f4deec 100644 --- a/app/controllers/general_controller.rb +++ b/app/controllers/general_controller.rb @@ -71,14 +71,15 @@ class GeneralController < ApplicationController medium_cache @feed_autodetect = [] @feed_url = "#{MySociety::Config.get('BLOG_FEED', '')}?lang=#{self.locale_from_params()}" + @blog_items = [] if not @feed_url.empty? - content = open(@feed_url).read - @data = XmlSimple.xml_in(content) - @channel = @data['channel'][0] - @blog_items = @channel['item'] - @feed_autodetect = [{:url => @feed_url, :title => "#{site_name} blog"}] - else - @blog_items = [] + content = quietly_try_to_open(@feed_url) + if !content.empty? + @data = XmlSimple.xml_in(content) + @channel = @data['channel'][0] + @blog_items = @channel['item'] + @feed_autodetect = [{:url => @feed_url, :title => "#{site_name} blog"}] + end end @twitter_user = MySociety::Config.get('TWITTER_USERNAME', '') end diff --git a/config/environments/test.rb b/config/environments/test.rb index 8058487ad..8d6041ad9 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -18,6 +18,7 @@ config.action_controller.perform_caching = false # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test config.gem 'rspec-rails', :version => '>= 1.3.3', :lib => false unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails')) +config.gem 'fakeweb', :version => '>=1.3.0' # Disable request forgery protection in test environment config.action_controller.allow_forgery_protection = false diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 875d7d224..1d6802940 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -1,10 +1,25 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'fakeweb' -describe ApplicationController, "when authenticating user" do - integrate_views - fixtures :users - -# it "blah" do -# end +describe ApplicationController, "when accessing third party services" do + it "should fail silently if the country_from_ip domain doesn't exist" do + config = MySociety::Config.load_default() + config['GAZE_URL'] = 'http://12123sdf14qsd.com' + country = self.controller.send :country_from_ip + country.should == config['ISO_COUNTRY_CODE'] + end + it "should fail silently if the country_from_ip service doesn't exist" do + config = MySociety::Config.load_default() + config['GAZE_URL'] = 'http://www.google.com' + country = self.controller.send :country_from_ip + country.should == config['ISO_COUNTRY_CODE'] + end + it "should fail silently if the country_from_ip service returns an error" do + FakeWeb.register_uri(:get, %r|.*|, :body => "Error", :status => ["500", "Error"]) + config = MySociety::Config.load_default() + config['GAZE_URL'] = 'http://500.com' + country = self.controller.send :country_from_ip + country.should == config['ISO_COUNTRY_CODE'] + end end diff --git a/spec/controllers/general_controller_spec.rb b/spec/controllers/general_controller_spec.rb index 40a676d61..ad5578800 100644 --- a/spec/controllers/general_controller_spec.rb +++ b/spec/controllers/general_controller_spec.rb @@ -1,4 +1,14 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'fakeweb' + +describe GeneralController, "when trying to show the blog" do + it "should fail silently if the blog is returning an error" do + FakeWeb.register_uri(:get, %r|.*|, :body => "Error", :status => ["500", "Error"]) + get :blog + response.status.should == "200 OK" + assigns[:blog_items].count.should == 0 + end +end describe GeneralController, "when searching" do integrate_views diff --git a/vendor/gems/fakeweb-1.3.0/.gitignore b/vendor/gems/fakeweb-1.3.0/.gitignore new file mode 100644 index 000000000..63be0c5de --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/.gitignore @@ -0,0 +1,7 @@ +/doc +/rdoc +/html +/coverage +/pkg +/.idea +*.rbc diff --git a/vendor/gems/fakeweb-1.3.0/.specification b/vendor/gems/fakeweb-1.3.0/.specification new file mode 100644 index 000000000..b69e9d545 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/.specification @@ -0,0 +1,135 @@ +--- !ruby/object:Gem::Specification +name: fakeweb +version: !ruby/object:Gem::Version + hash: 27 + prerelease: + segments: + - 1 + - 3 + - 0 + version: 1.3.0 +platform: ruby +authors: +- Chris Kampmeier +- Blaine Cook +autorequire: +bindir: bin +cert_chain: [] + +date: 2010-08-22 00:00:00 +01:00 +default_executable: +dependencies: +- !ruby/object:Gem::Dependency + name: mocha + prerelease: false + requirement: &id001 !ruby/object:Gem::Requirement + none: false + requirements: + - - ">=" + - !ruby/object:Gem::Version + hash: 49 + segments: + - 0 + - 9 + - 5 + version: 0.9.5 + type: :development + version_requirements: *id001 +description: FakeWeb is a helper for faking web requests in Ruby. It works at a global level, without modifying code or writing extensive stubs. +email: +- chris@kampers.net +- romeda@gmail.com +executables: [] + +extensions: [] + +extra_rdoc_files: [] + +files: +- test/test_allow_net_connect.rb +- test/test_deprecations.rb +- test/test_fake_authentication.rb +- test/test_fake_web.rb +- test/test_fake_web_open_uri.rb +- test/test_helper.rb +- test/test_last_request.rb +- test/test_missing_open_uri.rb +- test/test_missing_pathname.rb +- test/test_other_net_http_libraries.rb +- test/test_precedence.rb +- test/test_query_string.rb +- test/test_regexes.rb +- test/test_response_headers.rb +- test/test_trailing_slashes.rb +- test/test_utility.rb +- test/vendor/right_http_connection-1.2.4/lib/net_fix.rb +- test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb +- test/vendor/right_http_connection-1.2.4/setup.rb +- test/vendor/samuel-0.2.1/lib/samuel/net_http.rb +- test/vendor/samuel-0.2.1/lib/samuel/request.rb +- test/vendor/samuel-0.2.1/lib/samuel.rb +- test/vendor/samuel-0.2.1/test/request_test.rb +- test/vendor/samuel-0.2.1/test/samuel_test.rb +- test/vendor/samuel-0.2.1/test/test_helper.rb +- test/vendor/samuel-0.2.1/test/thread_test.rb +has_rdoc: true +homepage: http://github.com/chrisk/fakeweb +licenses: [] + +post_install_message: +rdoc_options: [] + +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + none: false + requirements: + - - ">=" + - !ruby/object:Gem::Version + hash: 3 + segments: + - 0 + version: "0" +required_rubygems_version: !ruby/object:Gem::Requirement + none: false + requirements: + - - ">=" + - !ruby/object:Gem::Version + hash: 3 + segments: + - 0 + version: "0" +requirements: [] + +rubyforge_project: fakeweb +rubygems_version: 1.6.2 +signing_key: +specification_version: 3 +summary: A tool for faking responses to HTTP requests +test_files: +- test/test_allow_net_connect.rb +- test/test_deprecations.rb +- test/test_fake_authentication.rb +- test/test_fake_web.rb +- test/test_fake_web_open_uri.rb +- test/test_helper.rb +- test/test_last_request.rb +- test/test_missing_open_uri.rb +- test/test_missing_pathname.rb +- test/test_other_net_http_libraries.rb +- test/test_precedence.rb +- test/test_query_string.rb +- test/test_regexes.rb +- test/test_response_headers.rb +- test/test_trailing_slashes.rb +- test/test_utility.rb +- test/vendor/right_http_connection-1.2.4/lib/net_fix.rb +- test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb +- test/vendor/right_http_connection-1.2.4/setup.rb +- test/vendor/samuel-0.2.1/lib/samuel/net_http.rb +- test/vendor/samuel-0.2.1/lib/samuel/request.rb +- test/vendor/samuel-0.2.1/lib/samuel.rb +- test/vendor/samuel-0.2.1/test/request_test.rb +- test/vendor/samuel-0.2.1/test/samuel_test.rb +- test/vendor/samuel-0.2.1/test/test_helper.rb +- test/vendor/samuel-0.2.1/test/thread_test.rb diff --git a/vendor/gems/fakeweb-1.3.0/CHANGELOG b/vendor/gems/fakeweb-1.3.0/CHANGELOG new file mode 100644 index 000000000..e626352f6 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/CHANGELOG @@ -0,0 +1,215 @@ +fakeweb (1.3.0) + +* improve response header registration so you can pass an array to set a header + more than once [Myron Marston] + +* fix an exception when the response's :body option was set to nil [Chris Zingel] + +* fix that stubbed requests weren't mutating the Net::HTTP request object to set + the body and content-length, like real requests do [Chris Kampmeier] + +* add FakeWeb.last_request [Chris Kampmeier] + +* assigning a String or Regexp to FakeWeb.allow_net_connect= sets a whitelist + for outbound requests [Dan Dofter, Tim Carey-Smith, Ben Woosley] + + +fakeweb (1.2.8) + +* support Pathname objects where a filename is expected [Chris Kampmeier] + +* fix compatibility with Ruby 1.9.2 [Chris Kampmeier] + +* simplify storage of FakeWeb::VERSION [Josh Peek, Woody Peterson, Ben Woosley] + + +fakeweb (1.2.7) + +* revert to sorting query params before matching requests against regexps, + instead of the 1.2.6 behavior that tried every possible order combination; + that was factorial-time, which made matching hang for requests with long query + strings [Jason Wadsworth, David Dollar, Blaine Cook] + +* print a warning when FakeWeb is loaded before RightHttpConnection or after + Samuel, other libs that patch Net::HTTP [Chris Kampmeier, Ben Brinckerhoff] + + +fakeweb (1.2.6) + +* fix that query params in a regex would have to be sorted for it to ever match + a request URI [Chris Kampmeier, Ben Hall] + +* improve regex handling so registration with an explicit port (like + /example.com:80/) matches a request that uses an implied port + (like "http://example.com/") [Chris Kampmeier, Dan Dofter] + +* refactor URI registry to reduce duplication; now about twice as fast at + handling requests [Chris Kampmeier] + +* Add FakeWeb::VERSION so you can programmatically determine what version of + FakeWeb is loaded without using RubyGems [Chris Kampmeier, Chris Wanstrath] + + +fakeweb (1.2.5) + +* fix handling of userinfo strings that contain percent-encoded unsafe + characters [Chris Kampmeier, Ken Mayer] + +* fix that exact matches against strings/URIs with the :any method had a lower + precedence than regex matches using a real HTTP method (exact matches now + always take precedence) [Chris Kampmeier] + +* change request handling to raise an exception when more than one registered + regex matches a request URI [Chris Kampmeier] + + +fakeweb (1.2.4) + +* add experimental support for matching URIs via regular expressions + [Jacqui Maher, Tiago Albineli Motta, Peter Wagene] + +* fix an exception when registering with the :response option and a string that + is the same as the name of a directory in the current path [Chris Kampmeier] + +* DEPRECATION: Calling FakeWeb.register_uri with a :string or :file option is + now deprecated. Both options have been replaced with a unified :body option, + since they supply the response body (as opposed to :response, which supplies + the full response including headers) [Chris Kampmeier] + +* add support for specifying HTTP headers as options to FakeWeb.register_uri + when using the :string or :file response types, since those methods only + specify a response body [David Michael, Chris Kampmeier] + +* DEPRECATION: Calling FakeWeb.register_uri and FakeWeb.registered_uri? without + an HTTP method as the first argument is now deprecated. To match against any + HTTP method (the pre-1.2.0 behavior), use :any [Chris Kampmeier] + + +fakeweb (1.2.3) + +* fix the #http_version of :file and :string responses, which was returning the + request URI instead of something sensible like "1.0" [Chris Kampmeier] + +* add method aliases in the Net::HTTP patch to eliminate warnings when running + with -w [Joshua Clingenpeel] + +* fix that removing the redefinition of OpenURI::HTTPError in 1.2.0 caused + :exception responses to raise when OpenURI isn't available [Chris Kampmeier] + +* fix registering an :exception response with classes that require arguments for + instantiation, like Interrupt's subclasses [Chris Kampmeier] + + +fakeweb (1.2.2) + +* fix that HTTP Digest and OAuth requests could raise URI::InvalidURIErrors + [Bill Kocik, Chris Kampmeier] + + +fakeweb (1.2.1) + +* fix that query parameters are handled correctly when registering with a URI + object [Anselmo Alves, Chris Kampmeier] + +* fix an exception when registering with the :response option and a string + containing "\0" [Jonathan Baudanza, Chris Kampmeier] + +* fix that trailing slashes were considered significant for requests to the root + of a domain [Chris Kampmeier] + +* add support for HTTP basic authentication via userinfo strings in URIs + [Michael Bleigh] + + +fakeweb (1.2.0) + +* add lib/fakeweb.rb so you can require "fakeweb" as well [Chris Kampmeier] + +* fix compatibility with Ruby 1.9.1 [Chris Kampmeier] + +* fix that newlines in file-based responses could be doubled in the response + object's body [Mark Menard, Chris Kampmeier] + +* fix unnecessary munging of the transfer-encoding header, which improves + compatibility with mechanize [Mark Menard] + +* fix a test and the RCov dependency to be compatible with JRuby [Mark Menard] + +* remove an unnecessary redefinition of OpenURI::HTTPError [Josh Nichols] + +* rearrange implementation code into separate files, one per class [Josh Nichols] + +* fix a bug where FakeWeb.response_for would raise if the request wasn't + registered [Chris Kampmeier] + +* add HTTP method support, so FakeWeb takes both the URI and method into + account for registration, requests, and responses. Backwards-compatible with + the old method signatures, which didn't have a method param. [Chris Kampmeier] + +* start work on Ruby 1.9 compatibility [Chris Kampmeier] + +* add FakeWeb.allow_net_connect= to enable/disable the pass-through to + Net::HTTP for unregistered URIs [Mislav Marohnić, Chris Kampmeier] + +* remove setup.rb, since most people use RubyGems [Mislav Marohnić] + +* fix that 'http://example.com/?' (empty query) matches a registered + 'http://example.com/', and vice-versa [Mislav Marohnić] + +* improve the test suite to not rely on an internet connection [Chris Kampmeier] + +* use `rake test` instead of `rake tests` [Josh Nichols] + +* fix an incompatibility with Ruby 1.8.6 p36 where you'd get "Errno::EINTR: + Interrupted system call" exceptions in Socket#sysread for any non-faked + request [Chris Kampmeier] + +* response rotation: you can now optionally call FakeWeb.register_uri with an + array of options hashes; these are used, in order, to respond to + repeated requests (to repeat a response more than once before rotating, use + the :times option). Once you run out of responses, further requests always + receive the last response. [Michael Shapiro] + +* add support for Net::HTTP's undocumented full-URI request style (fixes + URI::InvalidURIErrors that you might see in older libraries) [Chris Kampmeier] + +* sort query params before storing internally, so that + http://example.com/?a=1&b=2 and http://example.com/?b=2&a=1 are considered the + same URL (although this is technically incorrect, it's much more + convenient--most web apps work that way, and Net::HTTP's use of a hash to pass + query params means that the order in which FakeWeb stores them can be + unpredictable) [Chris Kampmeier] + +* add support for ports in URLs, so that http://example.com/ and + http://example.com:3000/ are not the same [Chris Kampmeier] + +* fix for non-faked SSL requests failing with "Unable to create local socket" + [Chris Kampmeier] + +* update Rakefile to fix warning about deprecated code [Chris Kampmeier] + + +fakeweb (1.1.2) + +* add required dependencies to GemSpec to ensure that tests pass in firebrigade + (http://firebrigade.seattlerb.org/) [Blaine Cook] + + +fakeweb (1.1.1) + +* fix for non-existence of :string method on File as presented by open-uri + [Blaine Cook] + +* fix for curl example test - google redirects to ccTLDs for those outside US + [Blaine Cook] + + +fakeweb (1.1.0) + +* update code to correspond to ruby 1.8.4 (breaks compatibility with ruby 1.8.2) + [Blaine Cook] + + +fakeweb (1.0.0) + + * initial import [Blaine Cook] diff --git a/vendor/gems/fakeweb-1.3.0/LICENSE.txt b/vendor/gems/fakeweb-1.3.0/LICENSE.txt new file mode 100644 index 000000000..ecae84703 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/LICENSE.txt @@ -0,0 +1,19 @@ +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. diff --git a/vendor/gems/fakeweb-1.3.0/README.rdoc b/vendor/gems/fakeweb-1.3.0/README.rdoc new file mode 100644 index 000000000..33115325b --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/README.rdoc @@ -0,0 +1,189 @@ += 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 + + gem install fakeweb + +Note: the gem was previously available as +FakeWeb+ (capital letters), but now +all versions are simply registered as +fakeweb+. If you have any old +FakeWeb+ +gems lying around, remove them: <tt>gem uninstall FakeWeb</tt> + + +== 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 +http://groups.google.com/group/fakeweb-users. + +The main source repository is http://github.com/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 <tt>register_uri</tt> 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 <tt>:any</tt> 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 <tt>FakeWeb.register_uri</tt> 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 +<tt>:times</tt> 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 <tt>FakeWeb.allow_net_connect = false</tt> 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 <tt>:body</tt> 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 http://groups.google.com/group/fakeweb-users/browse_thread/thread/44d190a6b12e4273 + for a discussion of some different options. Thanks! diff --git a/vendor/gems/fakeweb-1.3.0/Rakefile b/vendor/gems/fakeweb-1.3.0/Rakefile new file mode 100644 index 000000000..e3c5298c6 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/Rakefile @@ -0,0 +1,67 @@ +require 'rubygems' +require 'rake' + +version = '1.3.0' + +begin + require 'jeweler' + Jeweler::Tasks.new do |gem| + gem.name = "fakeweb" + gem.rubyforge_project = "fakeweb" + gem.version = version + gem.summary = "A tool for faking responses to HTTP requests" + gem.description = "FakeWeb is a helper for faking web requests in Ruby. It works at a global level, without modifying code or writing extensive stubs." + gem.email = ["chris@kampers.net", "romeda@gmail.com"] + gem.authors = ["Chris Kampmeier", "Blaine Cook"] + gem.homepage = "http://github.com/chrisk/fakeweb" + gem.add_development_dependency "mocha", ">= 0.9.5" + end +rescue LoadError + puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler" +end + + +require 'rake/testtask' +Rake::TestTask.new(:test) do |test| + test.test_files = FileList["test/**/*.rb"].exclude("test/test_helper.rb", "test/vendor") + test.libs << "test" + test.verbose = false + test.warning = true +end + +task :default => [:check_dependencies, :test] + + +begin + require 'rcov/rcovtask' + Rcov::RcovTask.new do |t| + t.test_files = FileList["test/**/*.rb"].exclude("test/test_helper.rb", "test/vendor") + t.libs << "test" + t.rcov_opts << "--sort coverage" + t.rcov_opts << "--exclude gems" + t.warning = true + end +rescue LoadError + print "rcov support disabled " + if RUBY_PLATFORM =~ /java/ + puts "(running under JRuby)" + else + puts "(install RCov to enable the `rcov` task)" + end +end + + +begin + require 'sdoc' + require 'rdoc/task' + Rake::RDocTask.new do |rdoc| + rdoc.main = "README.rdoc" + rdoc.rdoc_files.include("README.rdoc", "CHANGELOG", "LICENSE.txt", "lib/*.rb") + rdoc.title = "FakeWeb #{version} API Documentation" + rdoc.rdoc_dir = "doc" + rdoc.template = "direct" + rdoc.options << "--line-numbers" << "--show-hash" << "--charset=utf-8" + end +rescue LoadError + puts "SDoc (or a dependency) not available. Install it with: gem install sdoc" +end diff --git a/vendor/gems/fakeweb-1.3.0/fakeweb.gemspec b/vendor/gems/fakeweb-1.3.0/fakeweb.gemspec new file mode 100644 index 000000000..39b23f001 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/fakeweb.gemspec @@ -0,0 +1,126 @@ +# Generated by jeweler +# DO NOT EDIT THIS FILE DIRECTLY +# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{fakeweb} + s.version = "1.3.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Chris Kampmeier", "Blaine Cook"] + s.date = %q{2010-08-22} + s.description = %q{FakeWeb is a helper for faking web requests in Ruby. It works at a global level, without modifying code or writing extensive stubs.} + s.email = ["chris@kampers.net", "romeda@gmail.com"] + s.extra_rdoc_files = [ + "LICENSE.txt", + "README.rdoc" + ] + s.files = [ + ".autotest", + ".gitignore", + "CHANGELOG", + "LICENSE.txt", + "README.rdoc", + "Rakefile", + "fakeweb.gemspec", + "lib/fake_web.rb", + "lib/fake_web/ext/net_http.rb", + "lib/fake_web/registry.rb", + "lib/fake_web/responder.rb", + "lib/fake_web/response.rb", + "lib/fake_web/stub_socket.rb", + "lib/fake_web/utility.rb", + "lib/fakeweb.rb", + "test/fixtures/google_response_from_curl", + "test/fixtures/google_response_with_transfer_encoding", + "test/fixtures/google_response_without_transfer_encoding", + "test/fixtures/test_example.txt", + "test/fixtures/test_txt_file", + "test/test_allow_net_connect.rb", + "test/test_deprecations.rb", + "test/test_fake_authentication.rb", + "test/test_fake_web.rb", + "test/test_fake_web_open_uri.rb", + "test/test_helper.rb", + "test/test_last_request.rb", + "test/test_missing_open_uri.rb", + "test/test_missing_pathname.rb", + "test/test_other_net_http_libraries.rb", + "test/test_precedence.rb", + "test/test_query_string.rb", + "test/test_regexes.rb", + "test/test_response_headers.rb", + "test/test_trailing_slashes.rb", + "test/test_utility.rb", + "test/vendor/right_http_connection-1.2.4/History.txt", + "test/vendor/right_http_connection-1.2.4/Manifest.txt", + "test/vendor/right_http_connection-1.2.4/README.txt", + "test/vendor/right_http_connection-1.2.4/Rakefile", + "test/vendor/right_http_connection-1.2.4/lib/net_fix.rb", + "test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb", + "test/vendor/right_http_connection-1.2.4/setup.rb", + "test/vendor/samuel-0.2.1/.document", + "test/vendor/samuel-0.2.1/.gitignore", + "test/vendor/samuel-0.2.1/LICENSE", + "test/vendor/samuel-0.2.1/README.rdoc", + "test/vendor/samuel-0.2.1/Rakefile", + "test/vendor/samuel-0.2.1/VERSION", + "test/vendor/samuel-0.2.1/lib/samuel.rb", + "test/vendor/samuel-0.2.1/lib/samuel/net_http.rb", + "test/vendor/samuel-0.2.1/lib/samuel/request.rb", + "test/vendor/samuel-0.2.1/samuel.gemspec", + "test/vendor/samuel-0.2.1/test/request_test.rb", + "test/vendor/samuel-0.2.1/test/samuel_test.rb", + "test/vendor/samuel-0.2.1/test/test_helper.rb", + "test/vendor/samuel-0.2.1/test/thread_test.rb" + ] + s.homepage = %q{http://github.com/chrisk/fakeweb} + s.rdoc_options = ["--charset=UTF-8"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{fakeweb} + s.rubygems_version = %q{1.3.7} + s.summary = %q{A tool for faking responses to HTTP requests} + s.test_files = [ + "test/test_allow_net_connect.rb", + "test/test_deprecations.rb", + "test/test_fake_authentication.rb", + "test/test_fake_web.rb", + "test/test_fake_web_open_uri.rb", + "test/test_helper.rb", + "test/test_last_request.rb", + "test/test_missing_open_uri.rb", + "test/test_missing_pathname.rb", + "test/test_other_net_http_libraries.rb", + "test/test_precedence.rb", + "test/test_query_string.rb", + "test/test_regexes.rb", + "test/test_response_headers.rb", + "test/test_trailing_slashes.rb", + "test/test_utility.rb", + "test/vendor/right_http_connection-1.2.4/lib/net_fix.rb", + "test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb", + "test/vendor/right_http_connection-1.2.4/setup.rb", + "test/vendor/samuel-0.2.1/lib/samuel/net_http.rb", + "test/vendor/samuel-0.2.1/lib/samuel/request.rb", + "test/vendor/samuel-0.2.1/lib/samuel.rb", + "test/vendor/samuel-0.2.1/test/request_test.rb", + "test/vendor/samuel-0.2.1/test/samuel_test.rb", + "test/vendor/samuel-0.2.1/test/test_helper.rb", + "test/vendor/samuel-0.2.1/test/thread_test.rb" + ] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q<mocha>, [">= 0.9.5"]) + else + s.add_dependency(%q<mocha>, [">= 0.9.5"]) + end + else + s.add_dependency(%q<mocha>, [">= 0.9.5"]) + end +end + diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web.rb new file mode 100644 index 000000000..77fbdaec4 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/lib/fake_web.rb @@ -0,0 +1,215 @@ +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 <tt>FakeWeb.allow_net_connect = false</tt> 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 <tt>FakeWeb.allow_net_connect = true</tt> (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 + # <tt>FakeWeb.allow_net_connect=</tt>, 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 <tt>FakeWeb.allow_net_connect = + # false</tt> 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 + # <tt>:any</tt>, 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: + # + # <tt>:body</tt>:: + # 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, + # <tt>:string</tt> and <tt>:file</tt>, respectively. These are now deprecated.) + # <tt>:response</tt>:: + # Either a <tt>Net::HTTPResponse</tt>, an +IO+, or a +String+ which is used + # as the full response for the request. + # + # The easier way by far is to pass the <tt>:response</tt> 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 <tt>Net::HTTPResponse</tt> + # 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: + # + # <tt>:times</tt>:: + # 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 <tt>:times</tt> parameter. + # + # Two optional arguments are also accepted: + # + # <tt>:status</tt>:: + # Passing <tt>:status</tt> as a two-value array will set the response code + # and message. The defaults are <tt>200</tt> and <tt>OK</tt>, respectively. + # Example: + # FakeWeb.register_uri(:get, "http://example.com", :body => "Go away!", :status => [404, "Not Found"]) + # <tt>:exception</tt>:: + # The argument passed via <tt>:exception</tt> 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 <tt>:body</tt> 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 <tt>:any</tt> 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 diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/ext/net_http.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/ext/net_http.rb new file mode 100644 index 000000000..4ff3e9a10 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/lib/fake_web/ext/net_http.rb @@ -0,0 +1,72 @@ +require 'net/http' +require 'net/https' +require 'stringio' + +module Net #:nodoc: all + + class BufferedIO + def initialize_with_fakeweb(io, debug_output = nil) + @read_timeout = 60 + @rbuf = '' + @debug_output = debug_output + + @io = case io + when Socket, OpenSSL::SSL::SSLSocket, IO + io + when String + if !io.include?("\0") && File.exists?(io) && !File.directory?(io) + File.open(io, "r") + else + StringIO.new(io) + end + end + raise "Unable to create local socket" unless @io + 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 diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/registry.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/registry.rb new file mode 100644 index 000000000..9a4a34e68 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/lib/fake_web/registry.rb @@ -0,0 +1,127 @@ +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 diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/responder.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/responder.rb new file mode 100644 index 000000000..573fec3d4 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/lib/fake_web/responder.rb @@ -0,0 +1,122 @@ +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 + return '' if options[:body].nil? + + options[:body] = options[:body].to_s if defined?(Pathname) && options[:body].is_a?(Pathname) + + if !options[:body].include?("\0") && File.exists?(options[:body]) && !File.directory?(options[:body]) + File.read(options[:body]) + else + options[:body] + end + end + + def baked_response + return options[:response] if options[:response].is_a?(Net::HTTPResponse) + + if options[:response].is_a?(String) || (defined?(Pathname) && options[:response].is_a?(Pathname)) + socket = Net::BufferedIO.new(options[:response].to_s) + 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 + else + raise StandardError, "Handler unimplemented for response #{options[:response]}" + 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 + $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 #{caller[6]}" + end + + end +end
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/response.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/response.rb new file mode 100644 index 000000000..41ba2557b --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/lib/fake_web/response.rb @@ -0,0 +1,10 @@ +module FakeWeb + module Response #:nodoc: + + def read_body(*args, &block) + yield @body if block_given? + @body + end + + end +end
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/stub_socket.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/stub_socket.rb new file mode 100644 index 000000000..008681ca6 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/lib/fake_web/stub_socket.rb @@ -0,0 +1,15 @@ +module FakeWeb + class StubSocket #:nodoc: + + def initialize(*args) + end + + def closed? + @closed ||= true + end + + def readuntil(*args) + end + + end +end
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/utility.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/utility.rb new file mode 100644 index 000000000..bd5d7161c --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/lib/fake_web/utility.rb @@ -0,0 +1,87 @@ +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 + + uri = "#{protocol}://#{userinfo}#{net_http.address}:#{net_http.port}#{path}" + end + + # Wrapper for URI escaping that switches between URI::Parser#escape and + # URI.escape for 1.9-compatibility + def self.uri_escape(*args) + if URI.const_defined?(:Parser) + URI::Parser.new.escape(*args) + else + URI.escape(*args) + end + 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 diff --git a/vendor/gems/fakeweb-1.3.0/lib/fakeweb.rb b/vendor/gems/fakeweb-1.3.0/lib/fakeweb.rb new file mode 100644 index 000000000..6982966bf --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/lib/fakeweb.rb @@ -0,0 +1,2 @@ +# So you can require "fakeweb" instead of "fake_web" +require "fake_web"
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_from_curl b/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_from_curl new file mode 100644 index 000000000..fe2fe3945 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_from_curl @@ -0,0 +1,12 @@ +HTTP/1.1 200 OK
+Cache-Control: private, max-age=0
+Date: Sun, 01 Feb 2009 02:16:24 GMT
+Expires: -1
+Content-Type: text/html; charset=ISO-8859-1
+Set-Cookie: PREF=ID=a6d9b5f5a4056dfe:TM=1233454584:LM=1233454584:S=U9pSwSu4eQwOPenX; expires=Tue, 01-Feb-2011 02:16:24 GMT; path=/; domain=.google.com
+Server: gws
+Transfer-Encoding: chunked
+
+<html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>var _gjwl=location;function _gjuc(){var a=_gjwl.hash;if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var e=a.substring(d,b);if(e.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(e=="cad=h")return 0;c=b}_gjwl.href="search?"+a+"&cad=h";return 1}}return 0}; +window._gjuc && location.hash && _gjuc();</script><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{height:22px;padding-left:2px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbi,#gbs{background:#fff;left:0;position:absolute;top:24px;visibility:hidden;z-index:1000}#gbi{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}#gbar{float:left}}.gb2{display:block;padding:.2em .5em}a.gb1,a.gb2,a.gb3{color:#00c !important}.gb2,.gb3{text-decoration:none}a.gb2:hover{background:#36c;color:#fff !important}</style><script>window.google={kEI:"-AWFSZ6qFYuUswO9j5HIDQ",kEXPI:"17259,19547",kHL:"en"}; +google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};window.gbar={};(function(){var b=window.gbar,f,h;b.qs=function(a){var c=window.encodeURIComponent&&(document.forms[0].q||"").value;if(c)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(i,g){return(g||"&")+"q="+encodeURIComponent(c)})};function j(a,c){a.visibility=h?"hidden":"visible";a.left=c+"px"}b.tg=function(a){a=a||window.event;var c=0,i,g=window.navExtra,d=document.getElementById("gbi"),e=a.target||a.srcElement;a.cancelBubble=true;if(!f){f=document.createElement(Array.every||window.createPopup?"iframe":"div");f.frameBorder="0";f.src="#";d.parentNode.appendChild(f).id="gbs";if(g)for(i in g)d.insertBefore(g[i],d.firstChild).className="gb2";document.onclick=b.close}if(e.className!="gb3")e=e.parentNode;do c+=e.offsetLeft;while(e=e.offsetParent);j(d.style,c);f.style.width=d.offsetWidth+"px";f.style.height=d.offsetHeight+"px";j(f.style,c);h=!h};b.close=function(a){h&&b.tg(a)}})();</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo3.png'" topmargin=3 marginheight=3><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.com/imghp?hl=en&tab=wi" onclick=gbar.qs(this) class=gb1>Images</a> <a href="http://maps.google.com/maps?hl=en&tab=wl" onclick=gbar.qs(this) class=gb1>Maps</a> <a href="http://news.google.com/nwshp?hl=en&tab=wn" onclick=gbar.qs(this) class=gb1>News</a> <a href="http://www.google.com/prdhp?hl=en&tab=wf" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1" class=gb3><u>more</u> <small>▼</small></a><div id=gbi> <a href="http://video.google.com/?hl=en&tab=wv" onclick=gbar.qs(this) class=gb2>Video</a> <a href="http://groups.google.com/grphp?hl=en&tab=wg" onclick=gbar.qs(this) class=gb2>Groups</a> <a href="http://books.google.com/bkshp?hl=en&tab=wp" onclick=gbar.qs(this) class=gb2>Books</a> <a href="http://scholar.google.com/schhp?hl=en&tab=ws" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href="http://finance.google.com/finance?hl=en&tab=we" onclick=gbar.qs(this) class=gb2>Finance</a> <a href="http://blogsearch.google.com/?hl=en&tab=wb" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.youtube.com/?hl=en&tab=w1" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href="http://www.google.com/calendar/render?hl=en&tab=wc" class=gb2>Calendar</a> <a href="http://picasaweb.google.com/home?hl=en&tab=wq" onclick=gbar.qs(this) class=gb2>Photos</a> <a href="http://docs.google.com/?hl=en&tab=wo" class=gb2>Documents</a> <a href="http://www.google.com/reader/view/?hl=en&tab=wy" class=gb2>Reader</a> <a href="http://sites.google.com/?hl=en&tab=w3" class=gb2>Sites</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.google.com/intl/en/options/" class=gb2>even more »</a></div> </nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><div align=right id=guser style="font-size:84%;padding:0 0 4px" width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/Login?continue=http://www.google.com/&hl=en">Sign in</a></nobr></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ALL/images/logo.gif" width=276><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value=""><br><input name=btnG type=submit value="Google Search"><input name=btnI type=submit value="I'm Feeling Lucky"></td><td nowrap width=25%><font size=-2> <a href=/advanced_search?hl=en>Advanced Search</a><br> <a href=/preferences?hl=en>Preferences</a><br> <a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table></form><br><font size=-1>Share what you know. <a href="/aclk?sa=L&ai=CYhslHwSFSZH6LIHusAPEsc2eBfv77nqP3YC9CsHZnNkTEAEgwVRQypDftPn_____AWDJBqoECU_QbUVlfOdxZw&num=1&sig=AGiWqtwRgqw8y_kza6RGKxBrCstaXkDJ7A&q=http://knol.google.com">Write a Knol</a>.</font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a></font><p><font size=-2>©2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center></body><script>if(google.y)google.y.first=[];window.setTimeout(function(){var xjs=document.createElement('script');xjs.src='/extern_js/f/CgJlbhICdXMgACswCjgVLCswDjgELCswGDgDLA/L3N5xu59nDE.js';document.getElementsByTagName('head')[0].appendChild(xjs)},0);google.y.first.push(function(){google.ac.i(document.f,document.f.q,'','')})</script><script>function _gjp() {!(location.hash && _gjuc()) && setTimeout(_gjp, 500);}window._gjuc && _gjp();</script></html>
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_with_transfer_encoding b/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_with_transfer_encoding new file mode 100644 index 000000000..82025d36e --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_with_transfer_encoding @@ -0,0 +1,17 @@ +HTTP/1.1 200 OK +Cache-Control: private, max-age=0 +Date: Sun, 01 Feb 2009 01:54:36 GMT +Expires: -1 +Content-Type: text/html; charset=ISO-8859-1 +Set-Cookie: PREF=ID=4320bcaa30d097de:TM=1233453276:LM=1233453276:S=Eio39bg_nIabTxzL; expires=Tue, 01-Feb-2011 01:54:36 GMT; path=/; domain=.google.com +Server: gws +Transfer-Encoding: chunked + +fef +<html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>var _gjwl=location;function _gjuc(){var a=_gjwl.hash;if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var e=a.substring(d,b);if(e.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(e=="cad=h")return 0;c=b}_gjwl.href="search?"+a+"&cad=h";return 1}}return 0}; +window._gjuc && location.hash && _gjuc();</script><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{height:22px;padding-left:2px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbi,#gbs{background:#fff;left:0;position:absolute;top:24px;visibility:hidden;z-index:1000}#gbi{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}#gbar{float:left}}.gb2{display:block;padding:.2em .5em}a.gb1,a.gb2,a.gb3{color:#00c !important}.gb2,.gb3{text-decoration:none}a.gb2:hover{background:#36c;color:#fff !important}</style><script>window.google={kEI:"3ACFSYC6EKTcswOL4_nBDQ",kEXPI:"17259,19463",kHL:"en"}; +google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};window.gbar={};(function(){var b=window.gbar,f,h;b.qs=function(a){var c=window.encodeURIComponent&&(document.forms[0].q||"").value;if(c)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(i,g){return(g||"&")+"q="+encodeURIComponent(c)})};function j(a,c){a.visibility=h?"hidden":"visible";a.left=c+"px"}b.tg=function(a){a=a||window.event;var c=0,i,g=window.navExtra,d=document.getElementById("gbi"),e=a.target||a.srcElement;a.cancelBubble=true;if(!f){f=document.createElement(Array.every||window.createPopup?"iframe":"div");f.frameBorder="0";f.src="#";d.parentNode.appendChild(f).id="gbs";if(g)for(i in g)d.insertBefore(g[i],d.firstChild).className="gb2";document.onclick=b.close}if(e.className!="gb3")e=e.parentNode;do c+=e.offsetLeft;while(e=e.offsetParent);j(d.style,c);f.style.width=d.offsetWidth+"px";f.style.height=d.offsetHeight+"px";j(f.style,c);h=!h};b.close=function(a){h&&b.tg(a)}})();</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo3.png'" topmargin=3 marginheight=3><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.com/imghp?hl=en&tab=wi" onclick=gbar.qs(this) class=gb1>Images</a> <a href="http://maps.google.com/maps?hl=en&tab=wl" onclick=gbar.qs(this) class=gb1>Maps</a> <a href="http://news.google.com/nwshp?hl=en&tab=wn" onclick=gbar.qs(this) class=gb1>News</a> <a href="http://www.google.com/prdhp?hl=en&tab=wf" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1" class=gb3><u>more</u> <small>▼</small></a><div id=gbi> <a href="http://video.google.com/?hl=en&tab=wv" onclick=gbar.qs(this) class=gb2>Video</a> <a href="http://groups.google.com/grphp?hl=en&tab=wg" onclick=gbar.qs(this) class=gb2>Groups</a> <a href="http://books.google.com/bkshp?hl=en&tab=wp" onclick=gbar.qs(this) class=gb2>Books</a> <a href="http://scholar.google.com/schhp?hl=en&tab=ws" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href="http://finance.google.com/finance?hl=en&tab=we" onclick=gbar.qs(this) class=gb2>Finance</a> <a href="http://blogsearch.google.com/?hl=en&tab=wb" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.youtube.com/?hl=en&tab=w1" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href="http://www.google.com/calendar/render?hl=en&tab=wc" class=gb2>Calendar</a> <a href="http +a27 +://picasaweb.google.com/home?hl=en&tab=wq" onclick=gbar.qs(this) class=gb2>Photos</a> <a href="http://docs.google.com/?hl=en&tab=wo" class=gb2>Documents</a> <a href="http://www.google.com/reader/view/?hl=en&tab=wy" class=gb2>Reader</a> <a href="http://sites.google.com/?hl=en&tab=w3" class=gb2>Sites</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.google.com/intl/en/options/" class=gb2>even more »</a></div> </nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><div align=right id=guser style="font-size:84%;padding:0 0 4px" width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/Login?continue=http://www.google.com/&hl=en">Sign in</a></nobr></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ALL/images/logo.gif" width=276><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value=""><br><input name=btnG type=submit value="Google Search"><input name=btnI type=submit value="I'm Feeling Lucky"></td><td nowrap width=25%><font size=-2> <a href=/advanced_search?hl=en>Advanced Search</a><br> <a href=/preferences?hl=en>Preferences</a><br> <a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table></form><br><font size=-1>Share what you know. <a href="/aclk?sa=L&ai=CFL7HzwCFSZCnCJSwsQPm842HB_v77nqP3YC9CsHZnNkTEAEgwVRQypDftPn_____AWDJBqoECU_Q1sTewQNSbw&num=1&sig=AGiWqtyz-UiOD3EpsSp4k3n8A7zooeg48g&q=http://knol.google.com">Write a Knol</a>.</font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a></font><p><font size=-2>©2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center></body><script>if(google.y)google.y.first=[];window.setTimeout(function(){var xjs=document.createElement('script');xjs.src='/extern_js/f/CgJlbhICdXMgACswCjgVLCswDjgELCswGDgDLA/L3N5xu59nDE.js';document.getElementsByTagName('head')[0].appendChild(xjs)},0);google.y.first.push(function(){google.ac.i(document.f,document.f.q,'','')})</script><script>function _gjp() {!(location.hash && _gjuc()) && setTimeout(_gjp, 500);}window._gjuc && _gjp();</script></html> +0 + diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_without_transfer_encoding b/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_without_transfer_encoding new file mode 100644 index 000000000..51433c990 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_without_transfer_encoding @@ -0,0 +1,11 @@ +HTTP/1.0 200 OK +Cache-Control: private, max-age=0 +Date: Sun, 01 Feb 2009 01:55:33 GMT +Expires: -1 +Content-Type: text/html; charset=ISO-8859-1 +Set-Cookie: PREF=ID=3c140c3eb4c4f516:TM=1233453333:LM=1233453333:S=OH7sElk2hOWkb9ot; expires=Tue, 01-Feb-2011 01:55:33 GMT; path=/; domain=.google.com +Server: gws + +<html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>var _gjwl=location;function _gjuc(){var a=_gjwl.hash;if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var e=a.substring(d,b);if(e.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(e=="cad=h")return 0;c=b}_gjwl.href="search?"+a+"&cad=h";return 1}}return 0}; +window._gjuc && location.hash && _gjuc();</script><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{height:22px;padding-left:2px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbi,#gbs{background:#fff;left:0;position:absolute;top:24px;visibility:hidden;z-index:1000}#gbi{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}#gbar{float:left}}.gb2{display:block;padding:.2em .5em}a.gb1,a.gb2,a.gb3{color:#00c !important}.gb2,.gb3{text-decoration:none}a.gb2:hover{background:#36c;color:#fff !important}</style><script>window.google={kEI:"FQGFSY2rG5eSswOKpsHeDQ",kEXPI:"17259",kHL:"en"}; +google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};window.gbar={};(function(){var b=window.gbar,f,h;b.qs=function(a){var c=window.encodeURIComponent&&(document.forms[0].q||"").value;if(c)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(i,g){return(g||"&")+"q="+encodeURIComponent(c)})};function j(a,c){a.visibility=h?"hidden":"visible";a.left=c+"px"}b.tg=function(a){a=a||window.event;var c=0,i,g=window.navExtra,d=document.getElementById("gbi"),e=a.target||a.srcElement;a.cancelBubble=true;if(!f){f=document.createElement(Array.every||window.createPopup?"iframe":"div");f.frameBorder="0";f.src="#";d.parentNode.appendChild(f).id="gbs";if(g)for(i in g)d.insertBefore(g[i],d.firstChild).className="gb2";document.onclick=b.close}if(e.className!="gb3")e=e.parentNode;do c+=e.offsetLeft;while(e=e.offsetParent);j(d.style,c);f.style.width=d.offsetWidth+"px";f.style.height=d.offsetHeight+"px";j(f.style,c);h=!h};b.close=function(a){h&&b.tg(a)}})();</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo3.png'" topmargin=3 marginheight=3><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.com/imghp?hl=en&tab=wi" onclick=gbar.qs(this) class=gb1>Images</a> <a href="http://maps.google.com/maps?hl=en&tab=wl" onclick=gbar.qs(this) class=gb1>Maps</a> <a href="http://news.google.com/nwshp?hl=en&tab=wn" onclick=gbar.qs(this) class=gb1>News</a> <a href="http://www.google.com/prdhp?hl=en&tab=wf" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1" class=gb3><u>more</u> <small>▼</small></a><div id=gbi> <a href="http://video.google.com/?hl=en&tab=wv" onclick=gbar.qs(this) class=gb2>Video</a> <a href="http://groups.google.com/grphp?hl=en&tab=wg" onclick=gbar.qs(this) class=gb2>Groups</a> <a href="http://books.google.com/bkshp?hl=en&tab=wp" onclick=gbar.qs(this) class=gb2>Books</a> <a href="http://scholar.google.com/schhp?hl=en&tab=ws" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href="http://finance.google.com/finance?hl=en&tab=we" onclick=gbar.qs(this) class=gb2>Finance</a> <a href="http://blogsearch.google.com/?hl=en&tab=wb" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.youtube.com/?hl=en&tab=w1" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href="http://www.google.com/calendar/render?hl=en&tab=wc" class=gb2>Calendar</a> <a href="http://picasaweb.google.com/home?hl=en&tab=wq" onclick=gbar.qs(this) class=gb2>Photos</a> <a href="http://docs.google.com/?hl=en&tab=wo" class=gb2>Documents</a> <a href="http://www.google.com/reader/view/?hl=en&tab=wy" class=gb2>Reader</a> <a href="http://sites.google.com/?hl=en&tab=w3" class=gb2>Sites</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.google.com/intl/en/options/" class=gb2>even more »</a></div> </nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><div align=right id=guser style="font-size:84%;padding:0 0 4px" width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/Login?continue=http://www.google.com/&hl=en">Sign in</a></nobr></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ALL/images/logo.gif" width=276><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value=""><br><input name=btnG type=submit value="Google Search"><input name=btnI type=submit value="I'm Feeling Lucky"></td><td nowrap width=25%><font size=-2> <a href=/advanced_search?hl=en>Advanced Search</a><br> <a href=/preferences?hl=en>Preferences</a><br> <a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table></form><br><font size=-1>Share what you know. <a href="/aclk?sa=L&ai=ClyBp_v-EScTWD4W2tQOxoqSkB_v77nqP3YC9CsHZnNkTEAEgwVRQypDftPn_____AWDJBqoECU_QphTjHaZ5QA&num=1&sig=AGiWqtwtBqZ-zra3DJd_1chQKhKGf7lMVg&q=http://knol.google.com">Write a Knol</a>.</font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a></font><p><font size=-2>©2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center></body><script>if(google.y)google.y.first=[];window.setTimeout(function(){var xjs=document.createElement('script');xjs.src='/extern_js/f/CgJlbhICdXMgACswCjgNLCswDjgELCswGDgDLA/oTKXc0xdkmY.js';document.getElementsByTagName('head')[0].appendChild(xjs)},0);google.y.first.push(function(){google.ac.i(document.f,document.f.q,'','')})</script><script>function _gjp() {!(location.hash && _gjuc()) && setTimeout(_gjp, 500);}window._gjuc && _gjp();</script></html>
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/test_example.txt b/vendor/gems/fakeweb-1.3.0/test/fixtures/test_example.txt new file mode 100644 index 000000000..6310da9df --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/fixtures/test_example.txt @@ -0,0 +1 @@ +test example content
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/test_txt_file b/vendor/gems/fakeweb-1.3.0/test/fixtures/test_txt_file new file mode 100644 index 000000000..8cf2f17fe --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/fixtures/test_txt_file @@ -0,0 +1,3 @@ +line 1 +line 2 +line 3
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/test_allow_net_connect.rb b/vendor/gems/fakeweb-1.3.0/test/test_allow_net_connect.rb new file mode 100644 index 000000000..25f4d3d64 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_allow_net_connect.rb @@ -0,0 +1,168 @@ +require 'test_helper' + +class TestFakeWebAllowNetConnect < Test::Unit::TestCase + def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_true + FakeWeb.allow_net_connect = true + setup_expectations_for_real_apple_hot_news_request + Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) + end + + def test_raises_for_unregistered_requests_when_allow_net_connect_is_false + FakeWeb.allow_net_connect = false + assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.get(URI.parse("http://example.com/")) + end + end + + def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_the_same_string + FakeWeb.allow_net_connect = "http://images.apple.com/main/rss/hotnews/hotnews.rss" + setup_expectations_for_real_apple_hot_news_request + Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) + end + + def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_the_same_string_with_default_port + FakeWeb.allow_net_connect = "http://images.apple.com:80/main/rss/hotnews/hotnews.rss" + setup_expectations_for_real_apple_hot_news_request + Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) + end + + def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_the_same_uri + FakeWeb.allow_net_connect = URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss") + setup_expectations_for_real_apple_hot_news_request + Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) + end + + def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_a_matching_regexp + FakeWeb.allow_net_connect = %r[^http://images\.apple\.com] + setup_expectations_for_real_apple_hot_news_request + Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) + end + + def test_raises_for_unregistered_requests_when_allow_net_connect_is_a_different_string + FakeWeb.allow_net_connect = "http://example.com" + assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.get(URI.parse("http://example.com/path")) + end + end + + def test_raises_for_unregistered_requests_when_allow_net_connect_is_a_different_uri + FakeWeb.allow_net_connect = URI.parse("http://example.com") + assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.get(URI.parse("http://example.com/path")) + end + end + + def test_raises_for_unregistered_requests_when_allow_net_connect_is_a_non_matching_regexp + FakeWeb.allow_net_connect = %r[example\.net] + assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.get(URI.parse("http://example.com")) + end + end + + def test_changing_allow_net_connect_from_string_to_false_corretly_removes_whitelist + FakeWeb.allow_net_connect = "http://example.com" + FakeWeb.allow_net_connect = false + assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.get(URI.parse("http://example.com")) + end + end + + def test_changing_allow_net_connect_from_true_to_string_corretly_limits_connections + FakeWeb.allow_net_connect = true + FakeWeb.allow_net_connect = "http://example.com" + assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.get(URI.parse("http://example.net")) + end + end + + def test_exception_message_includes_unregistered_request_method_and_uri_but_no_default_port + FakeWeb.allow_net_connect = false + exception = assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.get(URI.parse("http://example.com/")) + end + assert exception.message.include?("GET http://example.com/") + + exception = assert_raise FakeWeb::NetConnectNotAllowedError do + http = Net::HTTP.new("example.com", 443) + http.use_ssl = true + http.get("/") + end + assert exception.message.include?("GET https://example.com/") + end + + def test_exception_message_includes_unregistered_request_port_when_not_default + FakeWeb.allow_net_connect = false + exception = assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.start("example.com", 8000) { |http| http.get("/") } + end + assert exception.message.include?("GET http://example.com:8000/") + + exception = assert_raise FakeWeb::NetConnectNotAllowedError do + http = Net::HTTP.new("example.com", 4433) + http.use_ssl = true + http.get("/") + end + assert exception.message.include?("GET https://example.com:4433/") + end + + def test_exception_message_includes_unregistered_request_port_when_not_default_with_path + FakeWeb.allow_net_connect = false + exception = assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.start("example.com", 8000) { |http| http.get("/test") } + end + assert exception.message.include?("GET http://example.com:8000/test") + + exception = assert_raise FakeWeb::NetConnectNotAllowedError do + http = Net::HTTP.new("example.com", 4433) + http.use_ssl = true + http.get("/test") + end + assert exception.message.include?("GET https://example.com:4433/test") + end + + def test_question_mark_method_returns_true_after_setting_allow_net_connect_to_true + FakeWeb.allow_net_connect = true + assert FakeWeb.allow_net_connect? + end + + def test_question_mark_method_returns_false_after_setting_allow_net_connect_to_false + FakeWeb.allow_net_connect = false + assert !FakeWeb.allow_net_connect? + end + + def test_question_mark_method_raises_with_no_argument_when_allow_net_connect_is_a_whitelist + FakeWeb.allow_net_connect = "http://example.com" + exception = assert_raise ArgumentError do + FakeWeb.allow_net_connect? + end + assert_equal "You must supply a URI to test", exception.message + end + + def test_question_mark_method_returns_true_when_argument_is_same_uri_as_allow_net_connect_string + FakeWeb.allow_net_connect = "http://example.com" + assert FakeWeb.allow_net_connect?("http://example.com/") + end + + def test_question_mark_method_returns_true_when_argument_matches_allow_net_connect_regexp + FakeWeb.allow_net_connect = %r[^https?://example.com/] + assert FakeWeb.allow_net_connect?("http://example.com/path") + assert FakeWeb.allow_net_connect?("https://example.com:443/") + end + + def test_question_mark_method_returns_false_when_argument_does_not_match_allow_net_connect_regexp + FakeWeb.allow_net_connect = %r[^http://example.com/] + assert !FakeWeb.allow_net_connect?("http://example.com:8080") + end +end + + +class TestFakeWebAllowNetConnectWithCleanState < Test::Unit::TestCase + # Our test_helper.rb sets allow_net_connect = false in an inherited #setup + # method. Disable that here to test the default setting. + def setup; end + def teardown; end + + def test_allow_net_connect_is_true_by_default + assert FakeWeb.allow_net_connect? + end +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_deprecations.rb b/vendor/gems/fakeweb-1.3.0/test/test_deprecations.rb new file mode 100644 index 000000000..e5b8953c5 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_deprecations.rb @@ -0,0 +1,54 @@ +require 'test_helper' + +class TestDeprecations < Test::Unit::TestCase + + def test_register_uri_without_method_argument_prints_deprecation_warning + warning = capture_stderr do + FakeWeb.register_uri("http://example.com", :body => "test") + end + assert_match %r(deprecation warning: fakeweb)i, warning + end + + def test_registered_uri_without_method_argument_prints_deprecation_warning + warning = capture_stderr do + FakeWeb.registered_uri?("http://example.com") + end + assert_match %r(deprecation warning: fakeweb)i, warning + end + + def test_response_for_without_method_argument_prints_deprecation_warning + warning = capture_stderr do + FakeWeb.response_for("http://example.com") + end + assert_match %r(deprecation warning: fakeweb)i, warning + end + + def test_register_uri_without_method_argument_prints_deprecation_warning_with_correct_caller + warning = capture_stderr do + FakeWeb.register_uri("http://example.com", :body => "test") + end + assert_match %r(Called at.*?test_deprecations\.rb)i, warning + end + + def test_register_uri_with_string_option_prints_deprecation_warning + warning = capture_stderr do + FakeWeb.register_uri(:get, "http://example.com", :string => "test") + end + assert_match %r(deprecation warning: fakeweb's :string option)i, warning + end + + def test_register_uri_with_file_option_prints_deprecation_warning + warning = capture_stderr do + FakeWeb.register_uri(:get, "http://example.com", :file => fixture_path("test_example.txt")) + end + assert_match %r(deprecation warning: fakeweb's :file option)i, warning + end + + def test_register_uri_with_string_option_prints_deprecation_warning_with_correct_caller + warning = capture_stderr do + FakeWeb.register_uri(:get, "http://example.com", :string => "test") + end + assert_match %r(Called at.*?test_deprecations\.rb)i, warning + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_fake_authentication.rb b/vendor/gems/fakeweb-1.3.0/test/test_fake_authentication.rb new file mode 100644 index 000000000..cff276441 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_fake_authentication.rb @@ -0,0 +1,92 @@ +require 'test_helper' + +class TestFakeAuthentication < Test::Unit::TestCase + + def test_register_uri_with_authentication + FakeWeb.register_uri(:get, 'http://user:pass@mock/test_example.txt', :body => "example") + assert FakeWeb.registered_uri?(:get, 'http://user:pass@mock/test_example.txt') + end + + def test_register_uri_with_authentication_doesnt_trigger_without + FakeWeb.register_uri(:get, 'http://user:pass@mock/test_example.txt', :body => "example") + assert !FakeWeb.registered_uri?(:get, 'http://mock/test_example.txt') + end + + def test_register_uri_with_authentication_doesnt_trigger_with_incorrect_credentials + FakeWeb.register_uri(:get, 'http://user:pass@mock/test_example.txt', :body => "example") + assert !FakeWeb.registered_uri?(:get, 'http://user:wrong@mock/test_example.txt') + end + + def test_unauthenticated_request + FakeWeb.register_uri(:get, 'http://mock/auth.txt', :body => 'unauthorized') + http = Net::HTTP.new('mock', 80) + req = Net::HTTP::Get.new('/auth.txt') + assert_equal 'unauthorized', http.request(req).body + end + + def test_authenticated_request + FakeWeb.register_uri(:get, 'http://user:pass@mock/auth.txt', :body => 'authorized') + http = Net::HTTP.new('mock',80) + req = Net::HTTP::Get.new('/auth.txt') + req.basic_auth 'user', 'pass' + assert_equal 'authorized', http.request(req).body + end + + def test_authenticated_request_where_only_userinfo_differs + FakeWeb.register_uri(:get, 'http://user:pass@mock/auth.txt', :body => 'first user') + FakeWeb.register_uri(:get, 'http://user2:pass@mock/auth.txt', :body => 'second user') + http = Net::HTTP.new('mock') + req = Net::HTTP::Get.new('/auth.txt') + req.basic_auth 'user2', 'pass' + assert_equal 'second user', http.request(req).body + end + + def test_basic_auth_support_is_transparent_to_oauth + FakeWeb.register_uri(:get, "http://sp.example.com/protected", :body => "secret") + + # from http://oauth.net/core/1.0/#auth_header + auth_header = <<-HEADER + OAuth realm="http://sp.example.com/", + oauth_consumer_key="0685bd9184jfhq22", + oauth_token="ad180jjd733klru7", + oauth_signature_method="HMAC-SHA1", + oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D", + oauth_timestamp="137131200", + oauth_nonce="4572616e48616d6d65724c61686176", + oauth_version="1.0" + HEADER + auth_header.gsub!(/\s+/, " ").strip! + + http = Net::HTTP.new("sp.example.com", 80) + response = nil + http.start do |request| + response = request.get("/protected", {"authorization" => auth_header}) + end + assert_equal "secret", response.body + end + + def test_basic_auth_when_userinfo_contains_allowed_unencoded_characters + FakeWeb.register_uri(:get, "http://roses&hel1o,(+$):so;longs=@example.com", :body => "authorized") + http = Net::HTTP.new("example.com") + request = Net::HTTP::Get.new("/") + request.basic_auth("roses&hel1o,(+$)", "so;longs=") + assert_equal "authorized", http.request(request).body + end + + def test_basic_auth_when_userinfo_contains_encoded_at_sign + FakeWeb.register_uri(:get, "http://user%40example.com:secret@example.com", :body => "authorized") + http = Net::HTTP.new("example.com") + request = Net::HTTP::Get.new("/") + request.basic_auth("user@example.com", "secret") + assert_equal "authorized", http.request(request).body + end + + def test_basic_auth_when_userinfo_contains_allowed_encoded_characters + FakeWeb.register_uri(:get, "http://us%20er:sec%20%2F%2Fret%3F@example.com", :body => "authorized") + http = Net::HTTP.new("example.com") + request = Net::HTTP::Get.new("/") + request.basic_auth("us er", "sec //ret?") + assert_equal "authorized", http.request(request).body + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_fake_web.rb b/vendor/gems/fakeweb-1.3.0/test/test_fake_web.rb new file mode 100644 index 000000000..c6e6b59eb --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_fake_web.rb @@ -0,0 +1,590 @@ +require 'test_helper' + +class TestFakeWeb < Test::Unit::TestCase + + def test_register_uri + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => "example") + assert FakeWeb.registered_uri?(:get, 'http://mock/test_example.txt') + end + + def test_register_uri_with_wrong_number_of_arguments + assert_raises ArgumentError do + FakeWeb.register_uri("http://example.com") + end + assert_raises ArgumentError do + FakeWeb.register_uri(:get, "http://example.com", "/example", :body => "example") + end + end + + def test_registered_uri_with_wrong_number_of_arguments + assert_raises ArgumentError do + FakeWeb.registered_uri? + end + assert_raises ArgumentError do + FakeWeb.registered_uri?(:get, "http://example.com", "/example") + end + end + + def test_response_for_with_wrong_number_of_arguments + assert_raises ArgumentError do + FakeWeb.response_for + end + assert_raises ArgumentError do + FakeWeb.response_for(:get, "http://example.com", "/example") + end + end + + def test_register_uri_without_domain_name + assert_raises URI::InvalidURIError do + FakeWeb.register_uri(:get, 'test_example2.txt', fixture_path("test_example.txt")) + end + end + + def test_register_uri_with_port_and_check_with_port + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'foo') + assert FakeWeb.registered_uri?(:get, 'http://example.com:3000/') + end + + def test_register_uri_with_port_and_check_without_port + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'foo') + assert !FakeWeb.registered_uri?(:get, 'http://example.com/') + end + + def test_register_uri_with_default_port_for_http_and_check_without_port + FakeWeb.register_uri(:get, 'http://example.com:80/', :body => 'foo') + assert FakeWeb.registered_uri?(:get, 'http://example.com/') + end + + def test_register_uri_with_default_port_for_https_and_check_without_port + FakeWeb.register_uri(:get, 'https://example.com:443/', :body => 'foo') + assert FakeWeb.registered_uri?(:get, 'https://example.com/') + end + + def test_register_uri_with_no_port_for_http_and_check_with_default_port + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo') + assert FakeWeb.registered_uri?(:get, 'http://example.com:80/') + end + + def test_register_uri_with_no_port_for_https_and_check_with_default_port + FakeWeb.register_uri(:get, 'https://example.com/', :body => 'foo') + assert FakeWeb.registered_uri?(:get, 'https://example.com:443/') + end + + def test_register_uri_with_no_port_for_https_and_check_with_443_on_http + FakeWeb.register_uri(:get, 'https://example.com/', :body => 'foo') + assert !FakeWeb.registered_uri?(:get, 'http://example.com:443/') + end + + def test_register_uri_with_no_port_for_http_and_check_with_80_on_https + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo') + assert !FakeWeb.registered_uri?(:get, 'https://example.com:80/') + end + + def test_register_uri_for_any_method_explicitly + FakeWeb.register_uri(:any, "http://example.com/rpc_endpoint", :body => "OK") + assert FakeWeb.registered_uri?(:get, "http://example.com/rpc_endpoint") + assert FakeWeb.registered_uri?(:post, "http://example.com/rpc_endpoint") + assert FakeWeb.registered_uri?(:put, "http://example.com/rpc_endpoint") + assert FakeWeb.registered_uri?(:delete, "http://example.com/rpc_endpoint") + assert FakeWeb.registered_uri?(:any, "http://example.com/rpc_endpoint") + capture_stderr do # silence deprecation warning + assert FakeWeb.registered_uri?("http://example.com/rpc_endpoint") + end + end + + def test_register_uri_for_get_method_only + FakeWeb.register_uri(:get, "http://example.com/users", :body => "User list") + assert FakeWeb.registered_uri?(:get, "http://example.com/users") + assert !FakeWeb.registered_uri?(:post, "http://example.com/users") + assert !FakeWeb.registered_uri?(:put, "http://example.com/users") + assert !FakeWeb.registered_uri?(:delete, "http://example.com/users") + assert !FakeWeb.registered_uri?(:any, "http://example.com/users") + capture_stderr do # silence deprecation warning + assert !FakeWeb.registered_uri?("http://example.com/users") + end + end + + def test_clean_registry_affects_registered_uri + FakeWeb.register_uri(:get, "http://example.com", :body => "registered") + assert FakeWeb.registered_uri?(:get, "http://example.com") + FakeWeb.clean_registry + assert !FakeWeb.registered_uri?(:get, "http://example.com") + end + + def test_clean_registry_affects_net_http_requests + FakeWeb.register_uri(:get, "http://example.com", :body => "registered") + response = Net::HTTP.start("example.com") { |query| query.get("/") } + assert_equal "registered", response.body + FakeWeb.clean_registry + assert_raise FakeWeb::NetConnectNotAllowedError do + Net::HTTP.start("example.com") { |query| query.get("/") } + end + end + + def test_response_for_with_registered_uri + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) + assert_equal 'test example content', FakeWeb.response_for(:get, 'http://mock/test_example.txt').body + end + + def test_response_for_with_unknown_uri + assert_nil FakeWeb.response_for(:get, 'http://example.com/') + end + + def test_response_for_with_put_method + FakeWeb.register_uri(:put, "http://example.com", :body => "response") + assert_equal 'response', FakeWeb.response_for(:put, "http://example.com").body + end + + def test_response_for_with_any_method_explicitly + FakeWeb.register_uri(:any, "http://example.com", :body => "response") + assert_equal 'response', FakeWeb.response_for(:get, "http://example.com").body + assert_equal 'response', FakeWeb.response_for(:any, "http://example.com").body + end + + def test_content_for_registered_uri_with_port_and_request_with_port + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'test example content') + response = Net::HTTP.start('example.com', 3000) { |http| http.get('/') } + assert_equal 'test example content', response.body + end + + def test_content_for_registered_uri_with_default_port_for_http_and_request_without_port + FakeWeb.register_uri(:get, 'http://example.com:80/', :body => 'test example content') + response = Net::HTTP.start('example.com') { |http| http.get('/') } + assert_equal 'test example content', response.body + end + + def test_content_for_registered_uri_with_no_port_for_http_and_request_with_default_port + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'test example content') + response = Net::HTTP.start('example.com', 80) { |http| http.get('/') } + assert_equal 'test example content', response.body + end + + def test_content_for_registered_uri_with_default_port_for_https_and_request_with_default_port + FakeWeb.register_uri(:get, 'https://example.com:443/', :body => 'test example content') + http = Net::HTTP.new('example.com', 443) + http.use_ssl = true + response = http.get('/') + assert_equal 'test example content', response.body + end + + def test_content_for_registered_uri_with_no_port_for_https_and_request_with_default_port + FakeWeb.register_uri(:get, 'https://example.com/', :body => 'test example content') + http = Net::HTTP.new('example.com', 443) + http.use_ssl = true + response = http.get('/') + assert_equal 'test example content', response.body + end + + def test_content_for_registered_uris_with_ports_on_same_domain_and_request_without_port + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'port 3000') + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'port 80') + response = Net::HTTP.start('example.com') { |http| http.get('/') } + assert_equal 'port 80', response.body + end + + def test_content_for_registered_uris_with_ports_on_same_domain_and_request_with_port + FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'port 3000') + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'port 80') + response = Net::HTTP.start('example.com', 3000) { |http| http.get('/') } + assert_equal 'port 3000', response.body + end + + def test_content_for_registered_uri_with_get_method_only + FakeWeb.allow_net_connect = false + FakeWeb.register_uri(:get, "http://example.com/", :body => "test example content") + http = Net::HTTP.new('example.com') + assert_equal 'test example content', http.get('/').body + assert_raises(FakeWeb::NetConnectNotAllowedError) { http.post('/', nil) } + assert_raises(FakeWeb::NetConnectNotAllowedError) { http.put('/', nil) } + assert_raises(FakeWeb::NetConnectNotAllowedError) { http.delete('/') } + end + + def test_content_for_registered_uri_with_any_method_explicitly + FakeWeb.allow_net_connect = false + FakeWeb.register_uri(:any, "http://example.com/", :body => "test example content") + http = Net::HTTP.new('example.com') + assert_equal 'test example content', http.get('/').body + assert_equal 'test example content', http.post('/', nil).body + assert_equal 'test example content', http.put('/', nil).body + assert_equal 'test example content', http.delete('/').body + end + + def test_content_for_registered_uri_with_any_method_implicitly + FakeWeb.allow_net_connect = false + capture_stderr do # silence deprecation warning + FakeWeb.register_uri("http://example.com/", :body => "test example content") + end + + http = Net::HTTP.new('example.com') + assert_equal 'test example content', http.get('/').body + assert_equal 'test example content', http.post('/', nil).body + assert_equal 'test example content', http.put('/', nil).body + assert_equal 'test example content', http.delete('/').body + end + + def test_mock_request_with_block + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) + response = Net::HTTP.start('mock') { |http| http.get('/test_example.txt') } + assert_equal 'test example content', response.body + end + + def test_request_with_registered_body_yields_the_response_body_to_a_request_block + FakeWeb.register_uri(:get, "http://example.com", :body => "content") + body = nil + Net::HTTP.start("example.com") do |http| + http.get("/") do |response_body| + body = response_body + end + end + assert_equal "content", body + end + + def test_request_with_registered_response_yields_the_response_body_to_a_request_block + fake_response = Net::HTTPOK.new('1.1', '200', 'OK') + fake_response.instance_variable_set(:@body, "content") + FakeWeb.register_uri(:get, 'http://example.com', :response => fake_response) + body = nil + Net::HTTP.start("example.com") do |http| + http.get("/") do |response_body| + body = response_body + end + end + assert_equal "content", body + end + + def test_mock_request_with_undocumented_full_uri_argument_style + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) + response = Net::HTTP.start('mock') { |query| query.get('http://mock/test_example.txt') } + assert_equal 'test example content', response.body + end + + def test_mock_request_with_undocumented_full_uri_argument_style_and_query + FakeWeb.register_uri(:get, 'http://mock/test_example.txt?a=b', :body => 'test query content') + response = Net::HTTP.start('mock') { |query| query.get('http://mock/test_example.txt?a=b') } + assert_equal 'test query content', response.body + end + + def test_mock_post + FakeWeb.register_uri(:post, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) + response = Net::HTTP.start('mock') { |query| query.post('/test_example.txt', '') } + assert_equal 'test example content', response.body + end + + def test_mock_post_with_string_as_registered_uri + FakeWeb.register_uri(:post, 'http://mock/test_string.txt', :body => 'foo') + response = Net::HTTP.start('mock') { |query| query.post('/test_string.txt', '') } + assert_equal 'foo', response.body + end + + def test_mock_post_with_body_sets_the_request_body + FakeWeb.register_uri(:post, "http://example.com/posts", :status => [201, "Created"]) + http = Net::HTTP.new("example.com") + request = Net::HTTP::Post.new("/posts") + http.request(request, "title=Test") + assert_equal "title=Test", request.body + assert_equal 10, request.content_length + end + + def test_mock_post_with_body_using_other_syntax_sets_the_request_body + FakeWeb.register_uri(:post, "http://example.com/posts", :status => [201, "Created"]) + http = Net::HTTP.new("example.com") + request = Net::HTTP::Post.new("/posts") + request.body = "title=Test" + http.request(request) + assert_equal "title=Test", request.body + assert_equal 10, request.content_length + end + + def test_real_post_with_body_sets_the_request_body + FakeWeb.allow_net_connect = true + setup_expectations_for_real_apple_hot_news_request :method => "POST", + :path => "/posts", :request_body => "title=Test" + http = Net::HTTP.new("images.apple.com") + request = Net::HTTP::Post.new("/posts") + request["Content-Type"] = "application/x-www-form-urlencoded" + http.request(request, "title=Test") + assert_equal "title=Test", request.body + assert_equal 10, request.content_length + end + + def test_mock_get_with_request_as_registered_uri + fake_response = Net::HTTPOK.new('1.1', '200', 'OK') + FakeWeb.register_uri(:get, 'http://mock/test_response', :response => fake_response) + response = Net::HTTP.start('mock') { |query| query.get('/test_response') } + assert_equal fake_response, response + end + + def test_mock_get_with_request_from_file_as_registered_uri + FakeWeb.register_uri(:get, 'http://www.google.com/', :response => fixture_path("google_response_without_transfer_encoding")) + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } + assert_equal '200', response.code + assert response.body.include?('<title>Google</title>') + end + + def test_mock_post_with_request_from_file_as_registered_uri + FakeWeb.register_uri(:post, 'http://www.google.com/', :response => fixture_path("google_response_without_transfer_encoding")) + response = Net::HTTP.start('www.google.com') { |query| query.post('/', '') } + assert_equal "200", response.code + assert response.body.include?('<title>Google</title>') + end + + def test_proxy_request + FakeWeb.register_uri(:get, 'http://www.example.com/', :body => "hello world") + FakeWeb.register_uri(:get, 'http://your.proxy.host/', :body => "lala") + + response = nil + Net::HTTP::Proxy('your.proxy.host', 8080).start('www.example.com') do |http| + response = http.get('/') + end + assert_equal "hello world", response.body + end + + def test_https_request + FakeWeb.register_uri(:get, 'https://www.example.com/', :body => "Hello World") + http = Net::HTTP.new('www.example.com', 443) + http.use_ssl = true + response = http.get('/') + assert_equal "Hello World", response.body + end + + def test_register_unimplemented_response + FakeWeb.register_uri(:get, 'http://mock/unimplemented', :response => 1) + assert_raises StandardError do + Net::HTTP.start('mock') { |q| q.get('/unimplemented') } + end + end + + def test_specifying_nil_for_body + FakeWeb.register_uri(:head, "http://example.com", :body => nil) + response = Net::HTTP.start("example.com") { |query| query.head("/") } + assert_equal "", response.body + end + + def test_real_http_request + FakeWeb.allow_net_connect = true + setup_expectations_for_real_apple_hot_news_request + + resp = nil + Net::HTTP.start('images.apple.com') do |query| + resp = query.get('/main/rss/hotnews/hotnews.rss') + end + assert resp.body.include?('Apple') + assert resp.body.include?('News') + end + + def test_real_http_request_with_undocumented_full_uri_argument_style + FakeWeb.allow_net_connect = true + setup_expectations_for_real_apple_hot_news_request(:path => 'http://images.apple.com/main/rss/hotnews/hotnews.rss') + + resp = nil + Net::HTTP.start('images.apple.com') do |query| + resp = query.get('http://images.apple.com/main/rss/hotnews/hotnews.rss') + end + assert resp.body.include?('Apple') + assert resp.body.include?('News') + end + + def test_real_https_request + FakeWeb.allow_net_connect = true + setup_expectations_for_real_apple_hot_news_request(:port => 443) + + http = Net::HTTP.new('images.apple.com', 443) + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_NONE # silence certificate warning + response = http.get('/main/rss/hotnews/hotnews.rss') + assert response.body.include?('Apple') + assert response.body.include?('News') + end + + def test_real_request_on_same_domain_as_mock + FakeWeb.allow_net_connect = true + setup_expectations_for_real_apple_hot_news_request + + FakeWeb.register_uri(:get, 'http://images.apple.com/test_string.txt', :body => 'foo') + + resp = nil + Net::HTTP.start('images.apple.com') do |query| + resp = query.get('/main/rss/hotnews/hotnews.rss') + end + assert resp.body.include?('Apple') + assert resp.body.include?('News') + end + + def test_mock_request_on_real_domain + FakeWeb.register_uri(:get, 'http://images.apple.com/test_string.txt', :body => 'foo') + resp = nil + Net::HTTP.start('images.apple.com') do |query| + resp = query.get('/test_string.txt') + end + assert_equal 'foo', resp.body + end + + def test_mock_post_that_raises_exception + FakeWeb.register_uri(:post, 'http://mock/raising_exception.txt', :exception => StandardError) + assert_raises(StandardError) do + Net::HTTP.start('mock') do |query| + query.post('/raising_exception.txt', 'some data') + end + end + end + + def test_mock_post_that_raises_an_http_error + FakeWeb.register_uri(:post, 'http://mock/raising_exception.txt', :exception => Net::HTTPError) + assert_raises(Net::HTTPError) do + Net::HTTP.start('mock') do |query| + query.post('/raising_exception.txt', '') + end + end + end + + def test_raising_an_exception_that_requires_an_argument_to_instantiate + FakeWeb.register_uri(:get, "http://example.com/timeout.txt", :exception => Timeout::Error) + assert_raises(Timeout::Error) do + Net::HTTP.get(URI.parse("http://example.com/timeout.txt")) + end + end + + def test_mock_instance_syntax + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) + response = nil + uri = URI.parse('http://mock/test_example.txt') + http = Net::HTTP.new(uri.host, uri.port) + response = http.start do + http.get(uri.path) + end + + assert_equal 'test example content', response.body + end + + def test_mock_via_nil_proxy + response = nil + proxy_address = nil + proxy_port = nil + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) + uri = URI.parse('http://mock/test_example.txt') + http = Net::HTTP::Proxy(proxy_address, proxy_port).new( + uri.host, (uri.port or 80)) + response = http.start do + http.get(uri.path) + end + + assert_equal 'test example content', response.body + end + + def test_response_type + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => "test") + response = Net::HTTP.start('mock') { |http| http.get('/test_example.txt') } + assert_kind_of Net::HTTPSuccess, response + end + + def test_mock_request_that_raises_an_http_error_with_a_specific_status + FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => Net::HTTPError, :status => ['404', 'Not Found']) + exception = assert_raises(Net::HTTPError) do + Net::HTTP.start('mock') { |http| http.get('/raising_exception.txt') } + end + assert_equal '404', exception.response.code + assert_equal 'Not Found', exception.response.msg + end + + def test_mock_rotate_responses + FakeWeb.register_uri(:get, 'http://mock/multiple_test_example.txt', + [ {:body => fixture_path("test_example.txt"), :times => 2}, + {:body => "thrice", :times => 3}, + {:body => "ever_more"} ]) + + uri = URI.parse('http://mock/multiple_test_example.txt') + 2.times { assert_equal 'test example content', Net::HTTP.get(uri) } + 3.times { assert_equal 'thrice', Net::HTTP.get(uri) } + 4.times { assert_equal 'ever_more', Net::HTTP.get(uri) } + end + + def test_mock_request_using_response_with_transfer_encoding_header_has_valid_transfer_encoding_header + FakeWeb.register_uri(:get, 'http://www.google.com/', :response => fixture_path("google_response_with_transfer_encoding")) + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } + assert_not_nil response['transfer-encoding'] + assert response['transfer-encoding'] == 'chunked' + end + + def test_mock_request_using_response_without_transfer_encoding_header_does_not_have_a_transfer_encoding_header + FakeWeb.register_uri(:get, 'http://www.google.com/', :response => fixture_path("google_response_without_transfer_encoding")) + response = nil + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } + assert !response.key?('transfer-encoding') + end + + def test_mock_request_using_response_from_curl_has_original_transfer_encoding_header + FakeWeb.register_uri(:get, 'http://www.google.com/', :response => fixture_path("google_response_from_curl")) + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } + assert_not_nil response['transfer-encoding'] + assert response['transfer-encoding'] == 'chunked' + end + + def test_txt_file_should_have_three_lines + FakeWeb.register_uri(:get, 'http://www.google.com/', :body => fixture_path("test_txt_file")) + response = Net::HTTP.start('www.google.com') { |query| query.get('/') } + assert response.body.split(/\n/).size == 3, "response has #{response.body.split(/\n/).size} lines should have 3" + end + + def test_requiring_fakeweb_instead_of_fake_web + require "fakeweb" + end + + def test_registering_with_string_containing_null_byte + # Regression test for File.exists? raising an ArgumentError ("string + # contains null byte") since :response first tries to find by filename. + # The string should be treated as a response body, instead, and an + # EOFError is raised when the byte is encountered. + FakeWeb.register_uri(:get, "http://example.com", :response => "test\0test") + assert_raise EOFError do + Net::HTTP.get(URI.parse("http://example.com")) + end + + FakeWeb.register_uri(:get, "http://example.com", :body => "test\0test") + body = Net::HTTP.get(URI.parse("http://example.com")) + assert_equal "test\0test", body + end + + def test_registering_with_string_that_is_a_directory_name + # Similar to above, but for Errno::EISDIR being raised since File.exists? + # returns true for directories + FakeWeb.register_uri(:get, "http://example.com", :response => File.dirname(__FILE__)) + assert_raise EOFError do + body = Net::HTTP.get(URI.parse("http://example.com")) + end + + FakeWeb.register_uri(:get, "http://example.com", :body => File.dirname(__FILE__)) + body = Net::HTTP.get(URI.parse("http://example.com")) + assert_equal File.dirname(__FILE__), body + end + + def test_registering_with_a_body_pointing_to_a_pathname + path = Pathname.new(fixture_path("test_example.txt")) + FakeWeb.register_uri(:get, "http://example.com", :body => path) + response = Net::HTTP.start("example.com") { |http| http.get("/") } + assert_equal "test example content", response.body + end + + def test_registering_with_a_response_pointing_to_a_pathname + path = Pathname.new(fixture_path("google_response_without_transfer_encoding")) + FakeWeb.register_uri(:get, "http://google.com", :response => path) + response = Net::HTTP.start("google.com") { |http| http.get("/") } + assert response.body.include?("<title>Google</title>") + end + + def test_http_version_from_string_response + FakeWeb.register_uri(:get, "http://example.com", :body => "example") + response = Net::HTTP.start("example.com") { |http| http.get("/") } + assert_equal "1.0", response.http_version + end + + def test_http_version_from_file_response + FakeWeb.register_uri(:get, "http://example.com", :body => fixture_path("test_example.txt")) + response = Net::HTTP.start("example.com") { |http| http.get("/") } + assert_equal "1.0", response.http_version + end + + def test_version + assert_equal "1.3.0", FakeWeb::VERSION + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_fake_web_open_uri.rb b/vendor/gems/fakeweb-1.3.0/test/test_fake_web_open_uri.rb new file mode 100644 index 000000000..699a64762 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_fake_web_open_uri.rb @@ -0,0 +1,58 @@ +require 'test_helper' + +class TestFakeWebOpenURI < Test::Unit::TestCase + + def test_content_for_registered_uri + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) + assert_equal 'test example content', FakeWeb.response_for(:get, 'http://mock/test_example.txt').body + end + + def test_mock_open + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) + assert_equal 'test example content', open('http://mock/test_example.txt').read + end + + def test_mock_open_with_string_as_registered_uri + FakeWeb.register_uri(:get, 'http://mock/test_string.txt', :body => 'foo') + assert_equal 'foo', open('http://mock/test_string.txt').string + end + + def test_real_open + FakeWeb.allow_net_connect = true + setup_expectations_for_real_apple_hot_news_request + resp = open('http://images.apple.com/main/rss/hotnews/hotnews.rss') + assert_equal "200", resp.status.first + body = resp.read + assert body.include?('Apple') + assert body.include?('News') + end + + def test_mock_open_that_raises_exception + FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => StandardError) + assert_raises(StandardError) do + open('http://mock/raising_exception.txt') + end + end + + def test_mock_open_that_raises_an_http_error + FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => OpenURI::HTTPError) + assert_raises(OpenURI::HTTPError) do + open('http://mock/raising_exception.txt') + end + end + + def test_mock_open_that_raises_an_http_error_with_a_specific_status + FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => OpenURI::HTTPError, :status => ['123', 'jodel']) + exception = assert_raises(OpenURI::HTTPError) do + open('http://mock/raising_exception.txt') + end + assert_equal '123', exception.io.code + assert_equal 'jodel', exception.io.message + end + + def test_mock_open_with_block + FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) + body = open('http://mock/test_example.txt') { |f| f.readlines } + assert_equal 'test example content', body.first + end +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_helper.rb b/vendor/gems/fakeweb-1.3.0/test/test_helper.rb new file mode 100644 index 000000000..b181391b1 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_helper.rb @@ -0,0 +1,90 @@ +require 'test/unit' +require 'open-uri' +require 'pathname' +require 'fake_web' +require 'rbconfig' +require 'rubygems' +require 'mocha' + + +# 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 + + 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 + + # 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 + else + socket = mock("TCPSocket") + Socket.expects(:===).with(socket).at_least_once.returns(true) + end + + TCPSocket.expects(:open).with(options[:host], options[:port]).returns(socket).at_least_once + 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 + + read_method = RUBY_VERSION >= "1.9.2" ? :read_nonblock : :sysread + 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 => "<title>Apple Hot News</title>" } + setup_expectations_for_real_request(defaults.merge(options)) + end + +end + +Test::Unit::TestCase.send(:include, FakeWebTestHelper) diff --git a/vendor/gems/fakeweb-1.3.0/test/test_last_request.rb b/vendor/gems/fakeweb-1.3.0/test/test_last_request.rb new file mode 100644 index 000000000..7868c83a1 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_last_request.rb @@ -0,0 +1,29 @@ +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 diff --git a/vendor/gems/fakeweb-1.3.0/test/test_missing_open_uri.rb b/vendor/gems/fakeweb-1.3.0/test/test_missing_open_uri.rb new file mode 100644 index 000000000..029ba1cab --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_missing_open_uri.rb @@ -0,0 +1,25 @@ +require 'test_helper' + +class TestMissingOpenURI < Test::Unit::TestCase + + def setup + super + @saved_open_uri = OpenURI + Object.send(:remove_const, :OpenURI) + end + + def teardown + super + Object.const_set(:OpenURI, @saved_open_uri) + end + + + def test_register_using_exception_without_open_uri + # regression test for Responder needing OpenURI::HTTPError to be defined + FakeWeb.register_uri(:get, "http://example.com/", :exception => StandardError) + assert_raises(StandardError) do + Net::HTTP.start("example.com") { |http| http.get("/") } + end + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_missing_pathname.rb b/vendor/gems/fakeweb-1.3.0/test/test_missing_pathname.rb new file mode 100644 index 000000000..ee16a0d7b --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_missing_pathname.rb @@ -0,0 +1,37 @@ +require 'test_helper' + +class TestMissingPathname < Test::Unit::TestCase + + def setup + super + @saved_pathname = Pathname + Object.send(:remove_const, :Pathname) + end + + def teardown + super + Object.const_set(:Pathname, @saved_pathname) + end + + # FakeWeb supports using Pathname objects where filenames are expected, but + # Pathname isn't required to use FakeWeb. Make sure everything still works + # when Pathname isn't in use. + + def test_register_using_body_without_pathname + FakeWeb.register_uri(:get, "http://example.com/", :body => fixture_path("test_example.txt")) + Net::HTTP.start("example.com") { |http| http.get("/") } + end + + def test_register_using_response_without_pathname + FakeWeb.register_uri(:get, "http://example.com/", :response => fixture_path("google_response_without_transfer_encoding")) + Net::HTTP.start("example.com") { |http| http.get("/") } + end + + def test_register_using_unsupported_response_without_pathname + FakeWeb.register_uri(:get, "http://example.com/", :response => 1) + assert_raise StandardError do + Net::HTTP.start("example.com") { |http| http.get("/") } + end + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_other_net_http_libraries.rb b/vendor/gems/fakeweb-1.3.0/test/test_other_net_http_libraries.rb new file mode 100644 index 000000000..af7e5e276 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_other_net_http_libraries.rb @@ -0,0 +1,36 @@ +require 'test_helper' + +class TestOtherNetHttpLibraries < Test::Unit::TestCase + + def capture_output_from_requiring(libs, additional_code = "") + requires = libs.map { |lib| "require '#{lib}'" }.join("; ") + fakeweb_dir = "#{File.dirname(__FILE__)}/../lib" + vendor_dirs = Dir["#{File.dirname(__FILE__)}/vendor/*/lib"] + load_path_opts = vendor_dirs.unshift(fakeweb_dir).map { |dir| "-I#{dir}" }.join(" ") + + `#{ruby_path} #{load_path_opts} -e "#{requires}; #{additional_code}" 2>&1` + end + + def test_requiring_samuel_before_fakeweb_prints_warning + output = capture_output_from_requiring %w(samuel fakeweb) + assert_match %r(Warning: FakeWeb was loaded after Samuel), output + end + + def test_requiring_samuel_after_fakeweb_does_not_print_warning + output = capture_output_from_requiring %w(fakeweb samuel) + assert output.empty? + end + + def test_requiring_right_http_connection_before_fakeweb_and_then_connecting_does_not_print_warning + additional_code = "Net::HTTP.start('example.com')" + output = capture_output_from_requiring %w(right_http_connection fakeweb), additional_code + assert output.empty? + end + + def test_requiring_right_http_connection_after_fakeweb_and_then_connecting_prints_warning + additional_code = "Net::HTTP.start('example.com')" + output = capture_output_from_requiring %w(fakeweb right_http_connection), additional_code + assert_match %r(Warning: RightHttpConnection was loaded after FakeWeb), output + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_precedence.rb b/vendor/gems/fakeweb-1.3.0/test/test_precedence.rb new file mode 100644 index 000000000..388b9f8a1 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_precedence.rb @@ -0,0 +1,79 @@ +require 'test_helper' + +class TestPrecedence < Test::Unit::TestCase + + def test_matching_get_strings_have_precedence_over_matching_get_regexes + FakeWeb.register_uri(:get, "http://example.com/test", :body => "string") + FakeWeb.register_uri(:get, %r|http://example\.com/test|, :body => "regex") + response = Net::HTTP.start("example.com") { |query| query.get('/test') } + assert_equal "string", response.body + end + + def test_matching_any_strings_have_precedence_over_matching_any_regexes + FakeWeb.register_uri(:any, "http://example.com/test", :body => "string") + FakeWeb.register_uri(:any, %r|http://example\.com/test|, :body => "regex") + response = Net::HTTP.start("example.com") { |query| query.get('/test') } + assert_equal "string", response.body + end + + def test_matching_get_strings_have_precedence_over_matching_any_strings + FakeWeb.register_uri(:get, "http://example.com/test", :body => "get method") + FakeWeb.register_uri(:any, "http://example.com/test", :body => "any method") + response = Net::HTTP.start("example.com") { |query| query.get('/test') } + assert_equal "get method", response.body + + # registration order should not matter + FakeWeb.register_uri(:any, "http://example.com/test2", :body => "any method") + FakeWeb.register_uri(:get, "http://example.com/test2", :body => "get method") + response = Net::HTTP.start("example.com") { |query| query.get('/test2') } + assert_equal "get method", response.body + end + + def test_matching_any_strings_have_precedence_over_matching_get_regexes + FakeWeb.register_uri(:any, "http://example.com/test", :body => "any string") + FakeWeb.register_uri(:get, %r|http://example\.com/test|, :body => "get regex") + response = Net::HTTP.start("example.com") { |query| query.get('/test') } + assert_equal "any string", response.body + end + + def test_registered_strings_and_uris_are_equivalent_so_second_takes_precedence + FakeWeb.register_uri(:get, "http://example.com/test", :body => "string") + FakeWeb.register_uri(:get, URI.parse("http://example.com/test"), :body => "uri") + response = Net::HTTP.start("example.com") { |query| query.get('/test') } + assert_equal "uri", response.body + + FakeWeb.register_uri(:get, URI.parse("http://example.com/test2"), :body => "uri") + FakeWeb.register_uri(:get, "http://example.com/test2", :body => "string") + response = Net::HTTP.start("example.com") { |query| query.get('/test2') } + assert_equal "string", response.body + end + + def test_identical_registration_replaces_previous_registration + FakeWeb.register_uri(:get, "http://example.com/test", :body => "first") + FakeWeb.register_uri(:get, "http://example.com/test", :body => "second") + response = Net::HTTP.start("example.com") { |query| query.get('/test') } + assert_equal "second", response.body + end + + def test_identical_registration_replaces_previous_registration_accounting_for_normalization + FakeWeb.register_uri(:get, "http://example.com/test?", :body => "first") + FakeWeb.register_uri(:get, "http://example.com:80/test", :body => "second") + response = Net::HTTP.start("example.com") { |query| query.get('/test') } + assert_equal "second", response.body + end + + def test_identical_registration_replaces_previous_registration_accounting_for_query_params + FakeWeb.register_uri(:get, "http://example.com/test?a=1&b=2", :body => "first") + FakeWeb.register_uri(:get, "http://example.com/test?b=2&a=1", :body => "second") + response = Net::HTTP.start("example.com") { |query| query.get('/test?a=1&b=2') } + assert_equal "second", response.body + end + + def test_identical_registration_replaces_previous_registration_with_regexes + FakeWeb.register_uri(:get, /test/, :body => "first") + FakeWeb.register_uri(:get, /test/, :body => "second") + response = Net::HTTP.start("example.com") { |query| query.get('/test') } + assert_equal "second", response.body + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_query_string.rb b/vendor/gems/fakeweb-1.3.0/test/test_query_string.rb new file mode 100644 index 000000000..11a211848 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_query_string.rb @@ -0,0 +1,45 @@ +require 'test_helper' + +class TestFakeWebQueryString < Test::Unit::TestCase + + def test_register_uri_string_with_query_params + FakeWeb.register_uri(:get, 'http://example.com/?a=1&b=1', :body => 'foo') + assert FakeWeb.registered_uri?(:get, 'http://example.com/?a=1&b=1') + + FakeWeb.register_uri(:post, URI.parse("http://example.org/?a=1&b=1"), :body => "foo") + assert FakeWeb.registered_uri?(:post, "http://example.org/?a=1&b=1") + end + + def test_register_uri_with_query_params_and_check_in_different_order + FakeWeb.register_uri(:get, 'http://example.com/?a=1&b=1', :body => 'foo') + assert FakeWeb.registered_uri?(:get, 'http://example.com/?b=1&a=1') + + FakeWeb.register_uri(:post, URI.parse('http://example.org/?a=1&b=1'), :body => 'foo') + assert FakeWeb.registered_uri?(:post, 'http://example.org/?b=1&a=1') + end + + def test_registered_uri_gets_recognized_with_empty_query_params + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo') + assert FakeWeb.registered_uri?(:get, 'http://example.com/?') + + FakeWeb.register_uri(:post, URI.parse('http://example.org/'), :body => 'foo') + assert FakeWeb.registered_uri?(:post, 'http://example.org/?') + end + + def test_register_uri_with_empty_query_params_and_check_with_none + FakeWeb.register_uri(:get, 'http://example.com/?', :body => 'foo') + assert FakeWeb.registered_uri?(:get, 'http://example.com/') + + FakeWeb.register_uri(:post, URI.parse('http://example.org/?'), :body => 'foo') + assert FakeWeb.registered_uri?(:post, 'http://example.org/') + end + + def test_registry_sort_query_params + assert_equal "a=1&b=2", FakeWeb::Registry.instance.send(:sort_query_params, "b=2&a=1") + end + + def test_registry_sort_query_params_sorts_by_value_if_keys_collide + assert_equal "a=1&a=2&b=2", FakeWeb::Registry.instance.send(:sort_query_params, "a=2&b=2&a=1") + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_regexes.rb b/vendor/gems/fakeweb-1.3.0/test/test_regexes.rb new file mode 100644 index 000000000..e2eba1db8 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_regexes.rb @@ -0,0 +1,157 @@ +require 'test_helper' + +class TestRegexes < Test::Unit::TestCase + + def test_registered_uri_with_pattern + FakeWeb.register_uri(:get, %r|http://example.com/test_example/\d+|, :body => "example") + assert FakeWeb.registered_uri?(:get, "http://example.com/test_example/25") + assert !FakeWeb.registered_uri?(:get, "http://example.com/test_example/abc") + end + + def test_response_for_with_matching_registered_uri + FakeWeb.register_uri(:get, %r|http://www.google.com|, :body => "Welcome to Google!") + assert_equal "Welcome to Google!", FakeWeb.response_for(:get, "http://www.google.com").body + end + + def test_response_for_with_matching_registered_uri_and_get_method_matching_to_any_method + FakeWeb.register_uri(:any, %r|http://www.example.com|, :body => "example") + assert_equal "example", FakeWeb.response_for(:get, "http://www.example.com").body + end + + def test_registered_uri_with_authentication_and_pattern + FakeWeb.register_uri(:get, %r|http://user:pass@mock/example\.\w+|i, :body => "example") + assert FakeWeb.registered_uri?(:get, 'http://user:pass@mock/example.txt') + end + + def test_registered_uri_with_authentication_and_pattern_handles_case_insensitivity + FakeWeb.register_uri(:get, %r|http://user:pass@mock/example\.\w+|i, :body => "example") + assert FakeWeb.registered_uri?(:get, 'http://uSeR:PAss@mock/example.txt') + end + + def test_request_with_authentication_and_pattern_handles_case_insensitivity + FakeWeb.register_uri(:get, %r|http://user:pass@mock/example\.\w+|i, :body => "example") + http = Net::HTTP.new('mock', 80) + req = Net::HTTP::Get.new('/example.txt') + req.basic_auth 'uSeR', 'PAss' + assert_equal "example", http.request(req).body + end + + def test_requesting_a_uri_that_matches_two_registered_regexes_raises_an_error + FakeWeb.register_uri(:get, %r|http://example\.com/|, :body => "first") + FakeWeb.register_uri(:get, %r|http://example\.com/a|, :body => "second") + assert_raise FakeWeb::MultipleMatchingURIsError do + Net::HTTP.start("example.com") { |query| query.get('/a') } + end + end + + def test_requesting_a_uri_that_matches_two_registered_regexes_raises_an_error_including_request_info + FakeWeb.register_uri(:get, %r|http://example\.com/|, :body => "first") + FakeWeb.register_uri(:get, %r|http://example\.com/a|, :body => "second") + begin + Net::HTTP.start("example.com") { |query| query.get('/a') } + rescue FakeWeb::MultipleMatchingURIsError => exception + end + assert exception.message.include?("GET http://example.com/a") + end + + def test_registry_does_not_find_using_mismatched_protocols_or_ports_when_registered_with_both + FakeWeb.register_uri(:get, %r|http://www.example.com:80|, :body => "example") + assert !FakeWeb.registered_uri?(:get, "https://www.example.com:80") + assert !FakeWeb.registered_uri?(:get, "http://www.example.com:443") + end + + def test_registry_finds_using_non_default_port + FakeWeb.register_uri(:get, %r|example\.com:8080|, :body => "example") + assert FakeWeb.registered_uri?(:get, "http://www.example.com:8080/path") + assert FakeWeb.registered_uri?(:get, "https://www.example.com:8080/path") + end + + def test_registry_finds_using_default_port_and_http_when_registered_with_explicit_port_80 + FakeWeb.register_uri(:get, %r|example\.com:80|, :body => "example") + assert FakeWeb.registered_uri?(:get, "http://www.example.com/path") + + # check other permutations, too + assert FakeWeb.registered_uri?(:get, "http://www.example.com:80/path") + assert FakeWeb.registered_uri?(:get, "http://www.example.com:8080/path") + assert FakeWeb.registered_uri?(:get, "https://www.example.com:80/path") + assert FakeWeb.registered_uri?(:get, "https://www.example.com:8080/path") + assert !FakeWeb.registered_uri?(:get, "https://www.example.com/path") + end + + def test_registry_finds_using_default_port_and_https_when_registered_with_explicit_port_443 + FakeWeb.register_uri(:get, %r|example\.com:443|, :body => "example") + assert FakeWeb.registered_uri?(:get, "https://www.example.com/path") + + # check other permutations, too + assert FakeWeb.registered_uri?(:get, "https://www.example.com:443/path") + assert FakeWeb.registered_uri?(:get, "https://www.example.com:44321/path") + assert FakeWeb.registered_uri?(:get, "http://www.example.com:443/path") + assert FakeWeb.registered_uri?(:get, "http://www.example.com:44321/path") + assert !FakeWeb.registered_uri?(:get, "http://www.example.com/path") + end + + def test_registry_only_finds_using_default_port_when_registered_without_if_protocol_matches + FakeWeb.register_uri(:get, %r|http://www.example.com/test|, :body => "example") + assert FakeWeb.registered_uri?(:get, "http://www.example.com:80/test") + assert !FakeWeb.registered_uri?(:get, "http://www.example.com:443/test") + assert !FakeWeb.registered_uri?(:get, "https://www.example.com:443/test") + FakeWeb.register_uri(:get, %r|https://www.example.org/test|, :body => "example") + assert FakeWeb.registered_uri?(:get, "https://www.example.org:443/test") + assert !FakeWeb.registered_uri?(:get, "https://www.example.org:80/test") + assert !FakeWeb.registered_uri?(:get, "http://www.example.org:80/test") + end + + def test_registry_matches_using_mismatched_port_when_registered_without + FakeWeb.register_uri(:get, %r|http://www.example.com|, :body => "example") + assert FakeWeb.registered_uri?(:get, "http://www.example.com:80") + assert FakeWeb.registered_uri?(:get, "http://www.example.com:443") + assert FakeWeb.registered_uri?(:get, "http://www.example.com:12345") + assert !FakeWeb.registered_uri?(:get, "https://www.example.com:443") + assert !FakeWeb.registered_uri?(:get, "https://www.example.com") + end + + def test_registry_matches_using_default_port_for_protocol_when_registered_without_protocol_or_port + FakeWeb.register_uri(:get, %r|www.example.com/home|, :body => "example") + assert FakeWeb.registered_uri?(:get, "http://www.example.com/home") + assert FakeWeb.registered_uri?(:get, "https://www.example.com/home") + assert FakeWeb.registered_uri?(:get, "http://www.example.com:80/home") + assert FakeWeb.registered_uri?(:get, "https://www.example.com:443/home") + assert !FakeWeb.registered_uri?(:get, "https://www.example.com:80/home") + assert !FakeWeb.registered_uri?(:get, "http://www.example.com:443/home") + end + + def test_registry_matches_with_query_params + FakeWeb.register_uri(:get, %r[example.com/list\?(.*&|)important=1], :body => "example") + assert FakeWeb.registered_uri?(:get, "http://example.com/list?hash=123&important=1&unimportant=2") + assert FakeWeb.registered_uri?(:get, "http://example.com/list?hash=123&important=12&unimportant=2") + assert FakeWeb.registered_uri?(:get, "http://example.com/list?important=1&unimportant=2") + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?important=2") + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?important=2&unimportant=1") + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?hash=123&important=2&unimportant=1") + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?notimportant=1&unimportant=1") + end + + def test_registry_does_not_match_when_regex_has_unsorted_query_params + FakeWeb.register_uri(:get, %r[example\.com/list\?b=2&a=1], :body => "example") + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?b=2&a=1") + assert !FakeWeb.registered_uri?(:get, "http://example.com/list?a=1&b=2") + assert !FakeWeb.registered_uri?(:get, "https://example.com:443/list?b=2&a=1") + end + + def test_registry_matches_when_regex_has_sorted_query_params + FakeWeb.register_uri(:get, %r[example\.com/list\?a=1&b=2], :body => "example") + assert FakeWeb.registered_uri?(:get, "http://example.com/list?b=2&a=1") + assert FakeWeb.registered_uri?(:get, "http://example.com/list?a=1&b=2") + assert FakeWeb.registered_uri?(:get, "https://example.com:443/list?b=2&a=1") + end + + def test_registry_matches_quickly_with_lots_of_query_params + # regression test for code that tried to calculate the permutations of the + # query params, which hangs with a large number of params + FakeWeb.register_uri(:get, %r[example.com], :body => "example") + Timeout::timeout(1) do + FakeWeb.registered_uri?(:get, "http://example.com/?a=1&b=2&c=3&d=4&e=5&f=6&g=7&h=8") + end + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_response_headers.rb b/vendor/gems/fakeweb-1.3.0/test/test_response_headers.rb new file mode 100644 index 000000000..45f3f5a99 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_response_headers.rb @@ -0,0 +1,79 @@ +require 'test_helper' + +class TestResponseHeaders < Test::Unit::TestCase + def test_content_type_when_registering_with_string_and_content_type_header_as_symbol_option + FakeWeb.register_uri(:get, "http://example.com/users.json", :body => '[{"username": "chrisk"}]', :content_type => "application/json") + response = Net::HTTP.start("example.com") { |query| query.get("/users.json") } + assert_equal '[{"username": "chrisk"}]', response.body + assert_equal "application/json", response['Content-Type'] + end + + def test_content_type_when_registering_with_string_and_content_type_header_as_string_option + FakeWeb.register_uri(:get, "http://example.com/users.json", :body => '[{"username": "chrisk"}]', 'Content-Type' => "application/json") + response = Net::HTTP.start("example.com") { |query| query.get("/users.json") } + assert_equal "application/json", response['Content-Type'] + end + + def test_content_type_when_registering_with_string_only + FakeWeb.register_uri(:get, "http://example.com/users.json", :body => '[{"username": "chrisk"}]') + response = Net::HTTP.start("example.com") { |query| query.get("/users.json") } + assert_equal '[{"username": "chrisk"}]', response.body + assert_nil response['Content-Type'] + end + + def test_cookies_when_registering_with_file_and_set_cookie_header + FakeWeb.register_uri(:get, "http://example.com/", :body => fixture_path("test_example.txt"), + :set_cookie => "user_id=1; example=yes") + response = Net::HTTP.start("example.com") { |query| query.get("/") } + assert_equal "test example content", response.body + assert_equal "user_id=1; example=yes", response['Set-Cookie'] + end + + def test_multiple_set_cookie_headers + FakeWeb.register_uri(:get, "http://example.com", :set_cookie => ["user_id=1", "example=yes"]) + response = Net::HTTP.start("example.com") { |query| query.get("/") } + assert_equal ["user_id=1", "example=yes"], response.get_fields('Set-Cookie') + assert_equal "user_id=1, example=yes", response['Set-Cookie'] + end + + def test_registering_with_baked_response_ignores_header_options + fake_response = Net::HTTPOK.new('1.1', '200', 'OK') + fake_response["Server"] = "Apache/1.3.27 (Unix)" + FakeWeb.register_uri(:get, "http://example.com/", :response => fake_response, + :server => "FakeWeb/1.2.3 (Ruby)") + response = Net::HTTP.start("example.com") { |query| query.get("/") } + assert_equal "200", response.code + assert_equal "OK", response.message + assert_equal "Apache/1.3.27 (Unix)", response["Server"] + end + + def test_headers_are_rotated_when_registering_with_response_rotation + FakeWeb.register_uri(:get, "http://example.com", + [{:body => 'test1', :expires => "Thu, 14 Jun 2009 16:00:00 GMT", + :content_type => "text/plain"}, + {:body => 'test2', :expires => "Thu, 14 Jun 2009 16:00:01 GMT"}]) + + first_response = second_response = nil + Net::HTTP.start("example.com") do |query| + first_response = query.get("/") + second_response = query.get("/") + end + assert_equal 'test1', first_response.body + assert_equal "Thu, 14 Jun 2009 16:00:00 GMT", first_response['Expires'] + assert_equal "text/plain", first_response['Content-Type'] + assert_equal 'test2', second_response.body + assert_equal "Thu, 14 Jun 2009 16:00:01 GMT", second_response['Expires'] + assert_nil second_response['Content-Type'] + end + + def test_registering_with_status_option_and_response_headers + FakeWeb.register_uri(:get, "http://example.com", :status => ["301", "Moved Permanently"], + :location => "http://www.example.com") + + response = Net::HTTP.start("example.com") { |query| query.get("/") } + assert_equal "301", response.code + assert_equal "Moved Permanently", response.message + assert_equal "http://www.example.com", response["Location"] + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_trailing_slashes.rb b/vendor/gems/fakeweb-1.3.0/test/test_trailing_slashes.rb new file mode 100644 index 000000000..564d807dc --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_trailing_slashes.rb @@ -0,0 +1,53 @@ +require 'test_helper' + +class TestFakeWebTrailingSlashes < Test::Unit::TestCase + + def test_registering_root_without_slash_and_ask_predicate_method_with_slash + FakeWeb.register_uri(:get, "http://www.example.com", :body => "root") + assert FakeWeb.registered_uri?(:get, "http://www.example.com/") + end + + def test_registering_root_without_slash_and_request + FakeWeb.register_uri(:get, "http://www.example.com", :body => "root") + response = Net::HTTP.start("www.example.com") { |query| query.get('/') } + assert_equal "root", response.body + end + + def test_registering_root_with_slash_and_ask_predicate_method_without_slash + FakeWeb.register_uri(:get, "http://www.example.com/", :body => "root") + assert FakeWeb.registered_uri?(:get, "http://www.example.com") + end + + def test_registering_root_with_slash_and_request + FakeWeb.register_uri(:get, "http://www.example.com/", :body => "root") + response = Net::HTTP.start("www.example.com") { |query| query.get('/') } + assert_equal "root", response.body + end + + def test_registering_path_without_slash_and_ask_predicate_method_with_slash + FakeWeb.register_uri(:get, "http://www.example.com/users", :body => "User list") + assert !FakeWeb.registered_uri?(:get, "http://www.example.com/users/") + end + + def test_registering_path_without_slash_and_request_with_slash + FakeWeb.allow_net_connect = false + FakeWeb.register_uri(:get, "http://www.example.com/users", :body => "User list") + assert_raise FakeWeb::NetConnectNotAllowedError do + response = Net::HTTP.start("www.example.com") { |query| query.get('/users/') } + end + end + + def test_registering_path_with_slash_and_ask_predicate_method_without_slash + FakeWeb.register_uri(:get, "http://www.example.com/users/", :body => "User list") + assert !FakeWeb.registered_uri?(:get, "http://www.example.com/users") + end + + def test_registering_path_with_slash_and_request_without_slash + FakeWeb.allow_net_connect = false + FakeWeb.register_uri(:get, "http://www.example.com/users/", :body => "User list") + assert_raise FakeWeb::NetConnectNotAllowedError do + response = Net::HTTP.start("www.example.com") { |query| query.get('/users') } + end + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_utility.rb b/vendor/gems/fakeweb-1.3.0/test/test_utility.rb new file mode 100644 index 000000000..891de875b --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/test_utility.rb @@ -0,0 +1,83 @@ +require 'test_helper' + +class TestUtility < Test::Unit::TestCase + + def test_decode_userinfo_from_header_handles_basic_auth + authorization_header = "Basic dXNlcm5hbWU6c2VjcmV0" + userinfo = FakeWeb::Utility.decode_userinfo_from_header(authorization_header) + assert_equal "username:secret", userinfo + end + + def test_encode_unsafe_chars_in_userinfo_does_not_encode_userinfo_safe_punctuation + userinfo = "user;&=+$,:secret" + assert_equal userinfo, FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) + end + + def test_encode_unsafe_chars_in_userinfo_does_not_encode_rfc_3986_unreserved_characters + userinfo = "-_.!~*'()abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:secret" + assert_equal userinfo, FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) + end + + def test_encode_unsafe_chars_in_userinfo_does_encode_other_characters + userinfo, safe_userinfo = 'us#rn@me:sec//ret?"', 'us%23rn%40me:sec%2F%2Fret%3F%22' + assert_equal safe_userinfo, FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) + end + + def test_strip_default_port_from_uri_strips_80_from_http_with_path + uri = "http://example.com:80/foo/bar" + stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) + assert_equal "http://example.com/foo/bar", stripped_uri + end + + def test_strip_default_port_from_uri_strips_80_from_http_without_path + uri = "http://example.com:80" + stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) + assert_equal "http://example.com", stripped_uri + end + + def test_strip_default_port_from_uri_strips_443_from_https_without_path + uri = "https://example.com:443" + stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) + assert_equal "https://example.com", stripped_uri + end + + def test_strip_default_port_from_uri_strips_443_from_https + uri = "https://example.com:443/foo/bar" + stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) + assert_equal "https://example.com/foo/bar", stripped_uri + end + + def test_strip_default_port_from_uri_does_not_strip_8080_from_http + uri = "http://example.com:8080/foo/bar" + assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) + end + + def test_strip_default_port_from_uri_does_not_strip_443_from_http + uri = "http://example.com:443/foo/bar" + assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) + end + + def test_strip_default_port_from_uri_does_not_strip_80_from_query_string + uri = "http://example.com/?a=:80&b=c" + assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) + end + + def test_strip_default_port_from_uri_does_not_modify_strings_that_do_not_start_with_http_or_https + uri = "httpz://example.com:80/" + assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) + end + + def test_request_uri_as_string + http = Net::HTTP.new("www.example.com", 80) + request = Net::HTTP::Get.new("/index.html") + expected = "http://www.example.com:80/index.html" + assert_equal expected, FakeWeb::Utility.request_uri_as_string(http, request) + end + + def test_uri_escape_delegates_to_uri_parser_when_available + parsing_object = URI.const_defined?(:Parser) ? URI::Parser.any_instance : URI + parsing_object.expects(:escape).with("string", /unsafe/).returns("escaped") + assert_equal "escaped", FakeWeb::Utility.uri_escape("string", /unsafe/) + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/History.txt b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/History.txt new file mode 100644 index 000000000..e06bcd0a2 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/History.txt @@ -0,0 +1,59 @@ +== 0.0.1 2007-05-15 +* 1 major enhancement: + * Initial release + +== 0.1.2 2007-06-27 + +* No major changes. + +== 0.1.3 2007-07-09 + +* No change. + +== 0.1.4 2007-08-10 + +* r1442, todd, 2007-08-07 15:45:24 + * # 373, Add support in right_http_connection for bailing out to a block while + reading the HTTP response (to support GET streaming...) + +* r1411, todd, 2007-08-03 15:14:45 + * # 373, Stream uploads (PUTs) if the source is a file, stream, or anything + read()-able + +== 1.1.0 2007-08-15 +Initial public release + +== 1.2.0 2007-10-05 + +* r1867, konstantin, 2007-10-05 06:19:45 + * # 220, (re)open connection to server if none exists or connection params + have changed + +== 1.2.1 + +* r2648, konstantin, 01-24-08 11:12:00 + * net_fix.rb moved from right_aws gem to fix the problem with uploading the streamable + objects to S3 + +* r2764, konstantin, 02-08-08 00:05:00 +03:00 + * "RightAws: incompatible Net::HTTP monkey-patch" exception is raised if our net_fix + patch was overriden (by attachment_fu for example, to avoid this load attachment_fu + before loading the right_http_connection gem). + +== 1.2.2 + +* r3524, konstantin, 2008-04-17 11:35:42 +0400 + * Fixed a problem with incorrect error handling (connection retries always failed). + +== 1.2.3 + +- Added support for setting retry & timeout parameters in the constructor +- Improve handling of data streams during upload: if there is a failure and a retry, reset + the seek pointer for the subsequent re-request + +== 1.2.4 + +* r4984, konstantin, 2008-08-11 14:49:18 +0400 + * fixed a bug: <NoMethodError: You have a nil object when you didn't expect it! + The error occurred while evaluating nil.body_stream> + diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Manifest.txt b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Manifest.txt new file mode 100644 index 000000000..20f193b21 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Manifest.txt @@ -0,0 +1,7 @@ +History.txt +Manifest.txt +README.txt +Rakefile +lib/net_fix.rb +lib/right_http_connection.rb +setup.rb diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/README.txt b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/README.txt new file mode 100644 index 000000000..46c97e57a --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/README.txt @@ -0,0 +1,54 @@ +RightScale::HttpConnection + by RightScale, Inc. + www.RightScale.com + +== DESCRIPTION: + +Rightscale::HttpConnection is a robust HTTP/S library. It implements a retry +algorithm for low-level network errors. + +== FEATURES: + +- provides put/get streaming +- does configurable retries on connect and read timeouts, DNS failures, etc. +- HTTPS certificate checking + +== SYNOPSIS: + + +== REQUIREMENTS: + +- 2/11/08: If you use RightScale::HttpConnection in conjunction with attachment_fu, the + HttpConnection gem must be included (using the require statement) AFTER + attachment_fu. + This is due to a conflict between the HttpConnection gem and another + gem required by attachment_fu. + + + +== INSTALL: + +sudo gem install right_http_connection + +== LICENSE: + +Copyright (c) 2007-2008 RightScale, Inc. + +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. diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Rakefile b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Rakefile new file mode 100644 index 000000000..0ae50977c --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Rakefile @@ -0,0 +1,103 @@ +require 'rubygems' +require 'rake' +require 'rake/clean' +require 'rake/testtask' +require 'rake/packagetask' +require 'rake/gempackagetask' +require 'rake/rdoctask' +require 'rake/contrib/rubyforgepublisher' +require 'fileutils' +require 'hoe' +include FileUtils +require File.join(File.dirname(__FILE__), 'lib', 'right_http_connection') + +AUTHOR = 'RightScale' # can also be an array of Authors +EMAIL = "rubygems@rightscale.com" +DESCRIPTION = "RightScale's robust HTTP/S connection module" +GEM_NAME = 'right_http_connection' # what ppl will type to install your gem +RUBYFORGE_PROJECT = 'rightscale' # The unix name for your project +HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org" +DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}" + +NAME = "right_http_connection" +REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil +VERS = RightHttpConnection::VERSION::STRING + (REV ? ".#{REV}" : "") +CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] +RDOC_OPTS = ['--quiet', '--title', 'right_http_connection documentation', + "--opname", "index.html", + "--line-numbers", + "--main", "README", + "--inline-source"] + +# Suppress Hoe's self-inclusion as a dependency for our Gem. This also keeps +# Rake & rubyforge out of the dependency list. Users must manually install +# these gems to run tests, etc. +# TRB 2/19/09: also do this for the extra_dev_deps array present in newer hoes. +# Older versions of RubyGems will try to install developer-dependencies as +# required runtime dependencies.... +class Hoe + def extra_deps + @extra_deps.reject do |x| + Array(x).first == 'hoe' + end + end + def extra_dev_deps + @extra_dev_deps.reject do |x| + Array(x).first == 'hoe' + end + end +end + +# Generate all the Rake tasks +# Run 'rake -T' to see list of generated tasks (from gem root directory) +hoe = Hoe.new(GEM_NAME, VERS) do |p| + p.author = AUTHOR + p.description = DESCRIPTION + p.email = EMAIL + p.summary = DESCRIPTION + p.url = HOMEPATH + p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT + p.test_globs = ["test/**/test_*.rb"] + p.clean_globs = CLEAN #An array of file patterns to delete on clean. + p.remote_rdoc_dir = "right_http_gem_doc" + + # == Optional + p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n") + #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ] + #p.spec_extras = {} # A hash of extra values to set in the gemspec. +end + + +desc 'Generate website files' +task :website_generate do + Dir['website/**/*.txt'].each do |txt| + sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} } + end +end + +desc 'Upload website files to rubyforge' +task :website_upload do + config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml"))) + host = "#{config["username"]}@rubyforge.org" + remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/" + # remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/#{GEM_NAME}" + local_dir = 'website' + sh %{rsync -av #{local_dir}/ #{host}:#{remote_dir}} +end + +desc 'Generate and upload website files' +task :website => [:website_generate, :website_upload] + +desc 'Release the website and new gem version' +task :deploy => [:check_version, :website, :release] + +task :check_version do + unless ENV['VERSION'] + puts 'Must pass a VERSION=x.y.z release version' + exit + end + unless ENV['VERSION'] == VERS + puts "Please update your version.rb to match the release version, currently #{VERS}" + exit + end +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/net_fix.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/net_fix.rb new file mode 100644 index 000000000..ad54f8a2a --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/net_fix.rb @@ -0,0 +1,160 @@ +# +# Copyright (c) 2008 RightScale Inc +# +# 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. +# +# + +# Net::HTTP and Net::HTTPGenericRequest fixes to support 100-continue on +# POST and PUT. The request must have 'expect' field set to '100-continue'. + + +module Net + + class BufferedIO #:nodoc: + # Monkey-patch Net::BufferedIO to read > 1024 bytes from the socket at a time + + # Default size (in bytes) of the max read from a socket into the user space read buffers for socket IO + DEFAULT_SOCKET_READ_SIZE = 16*1024 + + @@socket_read_size = DEFAULT_SOCKET_READ_SIZE + + def self.socket_read_size=(readsize) + if(readsize <= 0) + return + end + @@socket_read_size = readsize + end + + def self.socket_read_size?() + @@socket_read_size + end + + def rbuf_fill + timeout(@read_timeout) { + @rbuf << @io.sysread(@@socket_read_size) + } + end + end + + + #-- Net::HTTPGenericRequest -- + + class HTTPGenericRequest + # Monkey-patch Net::HTTPGenericRequest to read > 1024 bytes from the local data + # source at a time (used in streaming PUTs) + + # Default size (in bytes) of the max read from a local source (File, String, + # etc.) to the user space write buffers for socket IO. + DEFAULT_LOCAL_READ_SIZE = 16*1024 + + @@local_read_size = DEFAULT_LOCAL_READ_SIZE + + def self.local_read_size=(readsize) + if(readsize <= 0) + return + end + @@local_read_size = readsize + end + + def self.local_read_size?() + @@local_read_size + end + + def exec(sock, ver, path, send_only=nil) #:nodoc: internal use only + if @body + send_request_with_body sock, ver, path, @body, send_only + elsif @body_stream + send_request_with_body_stream sock, ver, path, @body_stream, send_only + else + write_header(sock, ver, path) + end + end + + private + + def send_request_with_body(sock, ver, path, body, send_only=nil) + self.content_length = body.length + delete 'Transfer-Encoding' + supply_default_content_type + write_header(sock, ver, path) unless send_only == :body + sock.write(body) unless send_only == :header + end + + def send_request_with_body_stream(sock, ver, path, f, send_only=nil) + unless content_length() or chunked? + raise ArgumentError, + "Content-Length not given and Transfer-Encoding is not `chunked'" + end + supply_default_content_type + write_header(sock, ver, path) unless send_only == :body + unless send_only == :header + if chunked? + while s = f.read(@@local_read_size) + sock.write(sprintf("%x\r\n", s.length) << s << "\r\n") + end + sock.write "0\r\n\r\n" + else + while s = f.read(@@local_read_size) + sock.write s + end + end + end + end + end + + + #-- Net::HTTP -- + + class HTTP + def request(req, body = nil, &block) # :yield: +response+ + unless started? + start { + req['connection'] ||= 'close' + return request(req, body, &block) + } + end + if proxy_user() + unless use_ssl? + req.proxy_basic_auth proxy_user(), proxy_pass() + end + end + # set body + req.set_body_internal body + begin_transport req + # if we expect 100-continue then send a header first + send_only = ((req.is_a?(Post)||req.is_a?(Put)) && (req['expect']=='100-continue')) ? :header : nil + req.exec @socket, @curr_http_version, edit_path(req.path), send_only + begin + res = HTTPResponse.read_new(@socket) + # if we expected 100-continue then send a body + if res.is_a?(HTTPContinue) && send_only && req['content-length'].to_i > 0 + req.exec @socket, @curr_http_version, edit_path(req.path), :body + end + end while res.kind_of?(HTTPContinue) + res.reading_body(@socket, req.response_body_permitted?) { + yield res if block_given? + } + end_transport req, res + res + end + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb new file mode 100644 index 000000000..0151ae685 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb @@ -0,0 +1,435 @@ +# +# Copyright (c) 2007-2008 RightScale Inc +# +# 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. +# + +require "net/https" +require "uri" +require "time" +require "logger" + +$:.unshift(File.dirname(__FILE__)) +require "net_fix" + + +module RightHttpConnection #:nodoc: + module VERSION #:nodoc: + MAJOR = 1 + MINOR = 2 + TINY = 4 + + STRING = [MAJOR, MINOR, TINY].join('.') + end +end + + +module Rightscale + +=begin rdoc +HttpConnection maintains a persistent HTTP connection to a remote +server. Each instance maintains its own unique connection to the +HTTP server. HttpConnection makes a best effort to receive a proper +HTTP response from the server, although it does not guarantee that +this response contains a HTTP Success code. + +On low-level errors (TCP/IP errors) HttpConnection invokes a reconnect +and retry algorithm. Note that although each HttpConnection object +has its own connection to the HTTP server, error handling is shared +across all connections to a server. For example, if there are three +connections to www.somehttpserver.com, a timeout error on one of those +connections will cause all three connections to break and reconnect. +A connection will not break and reconnect, however, unless a request +becomes active on it within a certain amount of time after the error +(as specified by HTTP_CONNECTION_RETRY_DELAY). An idle connection will not +break even if other connections to the same server experience errors. + +A HttpConnection will retry a request a certain number of times (as +defined by HTTP_CONNNECTION_RETRY_COUNT). If all the retries fail, +an exception is thrown and all HttpConnections associated with a +server enter a probationary period defined by HTTP_CONNECTION_RETRY_DELAY. +If the user makes a new request subsequent to entering probation, +the request will fail immediately with the same exception thrown +on probation entry. This is so that if the HTTP server has gone +down, not every subsequent request must wait for a connect timeout +before failing. After the probation period expires, the internal +state of the HttpConnection is reset and subsequent requests have +the full number of potential reconnects and retries available to +them. +=end + + class HttpConnection + + # Number of times to retry the request after encountering the first error + HTTP_CONNECTION_RETRY_COUNT = 3 + # Throw a Timeout::Error if a connection isn't established within this number of seconds + HTTP_CONNECTION_OPEN_TIMEOUT = 5 + # Throw a Timeout::Error if no data have been read on this connnection within this number of seconds + HTTP_CONNECTION_READ_TIMEOUT = 120 + # Length of the post-error probationary period during which all requests will fail + HTTP_CONNECTION_RETRY_DELAY = 15 + + #-------------------- + # class methods + #-------------------- + # + @@params = {} + @@params[:http_connection_retry_count] = HTTP_CONNECTION_RETRY_COUNT + @@params[:http_connection_open_timeout] = HTTP_CONNECTION_OPEN_TIMEOUT + @@params[:http_connection_read_timeout] = HTTP_CONNECTION_READ_TIMEOUT + @@params[:http_connection_retry_delay] = HTTP_CONNECTION_RETRY_DELAY + + # Query the global (class-level) parameters: + # + # :user_agent => 'www.HostName.com' # String to report as HTTP User agent + # :ca_file => 'path_to_file' # Path to a CA certification file in PEM format. The file can contain several CA certificates. If this parameter isn't set, HTTPS certs won't be verified. + # :logger => Logger object # If omitted, HttpConnection logs to STDOUT + # :exception => Exception to raise # The type of exception to raise + # # if a request repeatedly fails. RuntimeError is raised if this parameter is omitted. + # :http_connection_retry_count # by default == Rightscale::HttpConnection::HTTP_CONNECTION_RETRY_COUNT + # :http_connection_open_timeout # by default == Rightscale::HttpConnection::HTTP_CONNECTION_OPEN_TIMEOUT + # :http_connection_read_timeout # by default == Rightscale::HttpConnection::HTTP_CONNECTION_READ_TIMEOUT + # :http_connection_retry_delay # by default == Rightscale::HttpConnection::HTTP_CONNECTION_RETRY_DELAY + def self.params + @@params + end + + # Set the global (class-level) parameters + def self.params=(params) + @@params = params + end + + #------------------ + # instance methods + #------------------ + attr_accessor :http + attr_accessor :server + attr_accessor :params # see @@params + attr_accessor :logger + + # Params hash: + # :user_agent => 'www.HostName.com' # String to report as HTTP User agent + # :ca_file => 'path_to_file' # A path of a CA certification file in PEM format. The file can contain several CA certificates. + # :logger => Logger object # If omitted, HttpConnection logs to STDOUT + # :exception => Exception to raise # The type of exception to raise if a request repeatedly fails. RuntimeError is raised if this parameter is omitted. + # :http_connection_retry_count # by default == Rightscale::HttpConnection.params[:http_connection_retry_count] + # :http_connection_open_timeout # by default == Rightscale::HttpConnection.params[:http_connection_open_timeout] + # :http_connection_read_timeout # by default == Rightscale::HttpConnection.params[:http_connection_read_timeout] + # :http_connection_retry_delay # by default == Rightscale::HttpConnection.params[:http_connection_retry_delay] + # + def initialize(params={}) + @params = params + @params[:http_connection_retry_count] ||= @@params[:http_connection_retry_count] + @params[:http_connection_open_timeout] ||= @@params[:http_connection_open_timeout] + @params[:http_connection_read_timeout] ||= @@params[:http_connection_read_timeout] + @params[:http_connection_retry_delay] ||= @@params[:http_connection_retry_delay] + @http = nil + @server = nil + @logger = get_param(:logger) || + (RAILS_DEFAULT_LOGGER if defined?(RAILS_DEFAULT_LOGGER)) || + Logger.new(STDOUT) + end + + def get_param(name) + @params[name] || @@params[name] + end + + # Query for the maximum size (in bytes) of a single read from the underlying + # socket. For bulk transfer, especially over fast links, this is value is + # critical to performance. + def socket_read_size? + Net::BufferedIO.socket_read_size? + end + + # Set the maximum size (in bytes) of a single read from the underlying + # socket. For bulk transfer, especially over fast links, this is value is + # critical to performance. + def socket_read_size=(newsize) + Net::BufferedIO.socket_read_size=(newsize) + end + + # Query for the maximum size (in bytes) of a single read from local data + # sources like files. This is important, for example, in a streaming PUT of a + # large buffer. + def local_read_size? + Net::HTTPGenericRequest.local_read_size? + end + + # Set the maximum size (in bytes) of a single read from local data + # sources like files. This can be used to tune the performance of, for example, a streaming PUT of a + # large buffer. + def local_read_size=(newsize) + Net::HTTPGenericRequest.local_read_size=(newsize) + end + + private + #-------------- + # Retry state - Keep track of errors on a per-server basis + #-------------- + @@state = {} # retry state indexed by server: consecutive error count, error time, and error + @@eof = {} + + # number of consecutive errors seen for server, 0 all is ok + def error_count + @@state[@server] ? @@state[@server][:count] : 0 + end + + # time of last error for server, nil if all is ok + def error_time + @@state[@server] && @@state[@server][:time] + end + + # message for last error for server, "" if all is ok + def error_message + @@state[@server] ? @@state[@server][:message] : "" + end + + # add an error for a server + def error_add(message) + @@state[@server] = { :count => error_count+1, :time => Time.now, :message => message } + end + + # reset the error state for a server (i.e. a request succeeded) + def error_reset + @@state.delete(@server) + end + + # Error message stuff... + def banana_message + return "#{@server} temporarily unavailable: (#{error_message})" + end + + def err_header + return "#{self.class.name} :" + end + + # Adds new EOF timestamp. + # Returns the number of seconds to wait before new conection retry: + # 0.5, 1, 2, 4, 8 + def add_eof + (@@eof[@server] ||= []).unshift Time.now + 0.25 * 2 ** @@eof[@server].size + end + + # Returns first EOF timestamp or nul if have no EOFs being tracked. + def eof_time + @@eof[@server] && @@eof[@server].last + end + + # Returns true if we are receiving EOFs during last @params[:http_connection_retry_delay] seconds + # and there were no successful response from server + def raise_on_eof_exception? + @@eof[@server].blank? ? false : ( (Time.now.to_i-@params[:http_connection_retry_delay]) > @@eof[@server].last.to_i ) + end + + # Reset a list of EOFs for this server. + # This is being called when we have got an successful response from server. + def eof_reset + @@eof.delete(@server) + end + + # Detects if an object is 'streamable' - can we read from it, and can we know the size? + def setup_streaming(request) + if(request.body && request.body.respond_to?(:read)) + body = request.body + request.content_length = body.respond_to?(:lstat) ? body.lstat.size : body.size + request.body_stream = request.body + true + end + end + + def get_fileptr_offset(request_params) + request_params[:request].body.pos + rescue Exception => e + # Probably caught this because the body doesn't support the pos() method, like if it is a socket. + # Just return 0 and get on with life. + 0 + end + + def reset_fileptr_offset(request, offset = 0) + if(request.body_stream && request.body_stream.respond_to?(:pos)) + begin + request.body_stream.pos = offset + rescue Exception => e + @logger.warn("Failed file pointer reset; aborting HTTP retries." + + " -- #{err_header} #{e.inspect}") + raise e + end + end + end + + # Start a fresh connection. The object closes any existing connection and + # opens a new one. + def start(request_params) + # close the previous if exists + finish + # create new connection + @server = request_params[:server] + @port = request_params[:port] + @protocol = request_params[:protocol] + + @logger.info("Opening new #{@protocol.upcase} connection to #@server:#@port") + @http = Net::HTTP.new(@server, @port) + @http.open_timeout = @params[:http_connection_open_timeout] + @http.read_timeout = @params[:http_connection_read_timeout] + + if @protocol == 'https' + verifyCallbackProc = Proc.new{ |ok, x509_store_ctx| + code = x509_store_ctx.error + msg = x509_store_ctx.error_string + #debugger + @logger.warn("##### #{@server} certificate verify failed: #{msg}") unless code == 0 + true + } + @http.use_ssl = true + ca_file = get_param(:ca_file) + if ca_file + @http.verify_mode = OpenSSL::SSL::VERIFY_PEER + @http.verify_callback = verifyCallbackProc + @http.ca_file = ca_file + end + end + # open connection + @http.start + end + + public + +=begin rdoc + Send HTTP request to server + + request_params hash: + :server => 'www.HostName.com' # Hostname or IP address of HTTP server + :port => '80' # Port of HTTP server + :protocol => 'https' # http and https are supported on any port + :request => 'requeststring' # Fully-formed HTTP request to make + + Raises RuntimeError, Interrupt, and params[:exception] (if specified in new). + +=end + def request(request_params, &block) + # We save the offset here so that if we need to retry, we can return the file pointer to its initial position + mypos = get_fileptr_offset(request_params) + loop do + # if we are inside a delay between retries: no requests this time! + if error_count > @params[:http_connection_retry_count] && + error_time + @params[:http_connection_retry_delay] > Time.now + # store the message (otherwise it will be lost after error_reset and + # we will raise an exception with an empty text) + banana_message_text = banana_message + @logger.warn("#{err_header} re-raising same error: #{banana_message_text} " + + "-- error count: #{error_count}, error age: #{Time.now.to_i - error_time.to_i}") + exception = get_param(:exception) || RuntimeError + raise exception.new(banana_message_text) + end + + # try to connect server(if connection does not exist) and get response data + begin + request_params[:protocol] ||= (request_params[:port] == 443 ? 'https' : 'http') + + request = request_params[:request] + request['User-Agent'] = get_param(:user_agent) || '' + + # (re)open connection to server if none exists or params has changed + unless @http && + @http.started? && + @server == request_params[:server] && + @port == request_params[:port] && + @protocol == request_params[:protocol] + start(request_params) + end + + # Detect if the body is a streamable object like a file or socket. If so, stream that + # bad boy. + setup_streaming(request) + response = @http.request(request, &block) + + error_reset + eof_reset + return response + + # We treat EOF errors and the timeout/network errors differently. Both + # are tracked in different statistics blocks. Note below that EOF + # errors will sleep for a certain (exponentially increasing) period. + # Other errors don't sleep because there is already an inherent delay + # in them; connect and read timeouts (for example) have already + # 'slept'. It is still not clear which way we should treat errors + # like RST and resolution failures. For now, there is no additional + # delay for these errors although this may change in the future. + + # EOFError means the server closed the connection on us. + rescue EOFError => e + @logger.debug("#{err_header} server #{@server} closed connection") + @http = nil + + # if we have waited long enough - raise an exception... + if raise_on_eof_exception? + exception = get_param(:exception) || RuntimeError + @logger.warn("#{err_header} raising #{exception} due to permanent EOF being received from #{@server}, error age: #{Time.now.to_i - eof_time.to_i}") + raise exception.new("Permanent EOF is being received from #{@server}.") + else + # ... else just sleep a bit before new retry + sleep(add_eof) + # We will be retrying the request, so reset the file pointer + reset_fileptr_offset(request, mypos) + end + rescue Exception => e # See comment at bottom for the list of errors seen... + @http = nil + # if ctrl+c is pressed - we have to reraise exception to terminate proggy + if e.is_a?(Interrupt) && !( e.is_a?(Errno::ETIMEDOUT) || e.is_a?(Timeout::Error)) + @logger.debug( "#{err_header} request to server #{@server} interrupted by ctrl-c") + raise + elsif e.is_a?(ArgumentError) && e.message.include?('wrong number of arguments (5 for 4)') + # seems our net_fix patch was overriden... + exception = get_param(:exception) || RuntimeError + raise exception.new('incompatible Net::HTTP monkey-patch') + end + # oops - we got a banana: log it + error_add(e.message) + @logger.warn("#{err_header} request failure count: #{error_count}, exception: #{e.inspect}") + + # We will be retrying the request, so reset the file pointer + reset_fileptr_offset(request, mypos) + + end + end + end + + def finish(reason = '') + if @http && @http.started? + reason = ", reason: '#{reason}'" unless reason.blank? + @logger.info("Closing #{@http.use_ssl? ? 'HTTPS' : 'HTTP'} connection to #{@http.address}:#{@http.port}#{reason}") + @http.finish + end + end + + # Errors received during testing: + # + # #<Timeout::Error: execution expired> + # #<Errno::ETIMEDOUT: Connection timed out - connect(2)> + # #<SocketError: getaddrinfo: Name or service not known> + # #<SocketError: getaddrinfo: Temporary failure in name resolution> + # #<EOFError: end of file reached> + # #<Errno::ECONNRESET: Connection reset by peer> + # #<OpenSSL::SSL::SSLError: SSL_write:: bad write retry> + end + +end + diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/setup.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/setup.rb new file mode 100644 index 000000000..424a5f37c --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/setup.rb @@ -0,0 +1,1585 @@ +# +# setup.rb +# +# Copyright (c) 2000-2005 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU LGPL, Lesser General Public License version 2.1. +# + +unless Enumerable.method_defined?(:map) # Ruby 1.4.6 + module Enumerable + alias map collect + end +end + +unless File.respond_to?(:read) # Ruby 1.6 + def File.read(fname) + open(fname) {|f| + return f.read + } + end +end + +unless Errno.const_defined?(:ENOTEMPTY) # Windows? + module Errno + class ENOTEMPTY + # We do not raise this exception, implementation is not needed. + end + end +end + +def File.binread(fname) + open(fname, 'rb') {|f| + return f.read + } +end + +# for corrupted Windows' stat(2) +def File.dir?(path) + File.directory?((path[-1,1] == '/') ? path : path + '/') +end + + +class ConfigTable + + include Enumerable + + def initialize(rbconfig) + @rbconfig = rbconfig + @items = [] + @table = {} + # options + @install_prefix = nil + @config_opt = nil + @verbose = true + @no_harm = false + end + + attr_accessor :install_prefix + attr_accessor :config_opt + + attr_writer :verbose + + def verbose? + @verbose + end + + attr_writer :no_harm + + def no_harm? + @no_harm + end + + def [](key) + lookup(key).resolve(self) + end + + def []=(key, val) + lookup(key).set val + end + + def names + @items.map {|i| i.name } + end + + def each(&block) + @items.each(&block) + end + + def key?(name) + @table.key?(name) + end + + def lookup(name) + @table[name] or setup_rb_error "no such config item: #{name}" + end + + def add(item) + @items.push item + @table[item.name] = item + end + + def remove(name) + item = lookup(name) + @items.delete_if {|i| i.name == name } + @table.delete_if {|name, i| i.name == name } + item + end + + def load_script(path, inst = nil) + if File.file?(path) + MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path + end + end + + def savefile + '.config' + end + + def load_savefile + begin + File.foreach(savefile()) do |line| + k, v = *line.split(/=/, 2) + self[k] = v.strip + end + rescue Errno::ENOENT + setup_rb_error $!.message + "\n#{File.basename($0)} config first" + end + end + + def save + @items.each {|i| i.value } + File.open(savefile(), 'w') {|f| + @items.each do |i| + f.printf "%s=%s\n", i.name, i.value if i.value? and i.value + end + } + end + + def load_standard_entries + standard_entries(@rbconfig).each do |ent| + add ent + end + end + + def standard_entries(rbconfig) + c = rbconfig + + rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) + + major = c['MAJOR'].to_i + minor = c['MINOR'].to_i + teeny = c['TEENY'].to_i + version = "#{major}.#{minor}" + + # ruby ver. >= 1.4.4? + newpath_p = ((major >= 2) or + ((major == 1) and + ((minor >= 5) or + ((minor == 4) and (teeny >= 4))))) + + if c['rubylibdir'] + # V > 1.6.3 + libruby = "#{c['prefix']}/lib/ruby" + librubyver = c['rubylibdir'] + librubyverarch = c['archdir'] + siteruby = c['sitedir'] + siterubyver = c['sitelibdir'] + siterubyverarch = c['sitearchdir'] + elsif newpath_p + # 1.4.4 <= V <= 1.6.3 + libruby = "#{c['prefix']}/lib/ruby" + librubyver = "#{c['prefix']}/lib/ruby/#{version}" + librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" + siteruby = c['sitedir'] + siterubyver = "$siteruby/#{version}" + siterubyverarch = "$siterubyver/#{c['arch']}" + else + # V < 1.4.4 + libruby = "#{c['prefix']}/lib/ruby" + librubyver = "#{c['prefix']}/lib/ruby/#{version}" + librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" + siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" + siterubyver = siteruby + siterubyverarch = "$siterubyver/#{c['arch']}" + end + parameterize = lambda {|path| + path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') + } + + if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } + makeprog = arg.sub(/'/, '').split(/=/, 2)[1] + else + makeprog = 'make' + end + + [ + ExecItem.new('installdirs', 'std/site/home', + 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ + {|val, table| + case val + when 'std' + table['rbdir'] = '$librubyver' + table['sodir'] = '$librubyverarch' + when 'site' + table['rbdir'] = '$siterubyver' + table['sodir'] = '$siterubyverarch' + when 'home' + setup_rb_error '$HOME was not set' unless ENV['HOME'] + table['prefix'] = ENV['HOME'] + table['rbdir'] = '$libdir/ruby' + table['sodir'] = '$libdir/ruby' + end + }, + PathItem.new('prefix', 'path', c['prefix'], + 'path prefix of target environment'), + PathItem.new('bindir', 'path', parameterize.call(c['bindir']), + 'the directory for commands'), + PathItem.new('libdir', 'path', parameterize.call(c['libdir']), + 'the directory for libraries'), + PathItem.new('datadir', 'path', parameterize.call(c['datadir']), + 'the directory for shared data'), + PathItem.new('mandir', 'path', parameterize.call(c['mandir']), + 'the directory for man pages'), + PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), + 'the directory for system configuration files'), + PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), + 'the directory for local state data'), + PathItem.new('libruby', 'path', libruby, + 'the directory for ruby libraries'), + PathItem.new('librubyver', 'path', librubyver, + 'the directory for standard ruby libraries'), + PathItem.new('librubyverarch', 'path', librubyverarch, + 'the directory for standard ruby extensions'), + PathItem.new('siteruby', 'path', siteruby, + 'the directory for version-independent aux ruby libraries'), + PathItem.new('siterubyver', 'path', siterubyver, + 'the directory for aux ruby libraries'), + PathItem.new('siterubyverarch', 'path', siterubyverarch, + 'the directory for aux ruby binaries'), + PathItem.new('rbdir', 'path', '$siterubyver', + 'the directory for ruby scripts'), + PathItem.new('sodir', 'path', '$siterubyverarch', + 'the directory for ruby extentions'), + PathItem.new('rubypath', 'path', rubypath, + 'the path to set to #! line'), + ProgramItem.new('rubyprog', 'name', rubypath, + 'the ruby program using for installation'), + ProgramItem.new('makeprog', 'name', makeprog, + 'the make program to compile ruby extentions'), + SelectItem.new('shebang', 'all/ruby/never', 'ruby', + 'shebang line (#!) editing mode'), + BoolItem.new('without-ext', 'yes/no', 'no', + 'does not compile/install ruby extentions') + ] + end + private :standard_entries + + def load_multipackage_entries + multipackage_entries().each do |ent| + add ent + end + end + + def multipackage_entries + [ + PackageSelectionItem.new('with', 'name,name...', '', 'ALL', + 'package names that you want to install'), + PackageSelectionItem.new('without', 'name,name...', '', 'NONE', + 'package names that you do not want to install') + ] + end + private :multipackage_entries + + ALIASES = { + 'std-ruby' => 'librubyver', + 'stdruby' => 'librubyver', + 'rubylibdir' => 'librubyver', + 'archdir' => 'librubyverarch', + 'site-ruby-common' => 'siteruby', # For backward compatibility + 'site-ruby' => 'siterubyver', # For backward compatibility + 'bin-dir' => 'bindir', + 'bin-dir' => 'bindir', + 'rb-dir' => 'rbdir', + 'so-dir' => 'sodir', + 'data-dir' => 'datadir', + 'ruby-path' => 'rubypath', + 'ruby-prog' => 'rubyprog', + 'ruby' => 'rubyprog', + 'make-prog' => 'makeprog', + 'make' => 'makeprog' + } + + def fixup + ALIASES.each do |ali, name| + @table[ali] = @table[name] + end + @items.freeze + @table.freeze + @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ + end + + def parse_opt(opt) + m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" + m.to_a[1,2] + end + + def dllext + @rbconfig['DLEXT'] + end + + def value_config?(name) + lookup(name).value? + end + + class Item + def initialize(name, template, default, desc) + @name = name.freeze + @template = template + @value = default + @default = default + @description = desc + end + + attr_reader :name + attr_reader :description + + attr_accessor :default + alias help_default default + + def help_opt + "--#{@name}=#{@template}" + end + + def value? + true + end + + def value + @value + end + + def resolve(table) + @value.gsub(%r<\$([^/]+)>) { table[$1] } + end + + def set(val) + @value = check(val) + end + + private + + def check(val) + setup_rb_error "config: --#{name} requires argument" unless val + val + end + end + + class BoolItem < Item + def config_type + 'bool' + end + + def help_opt + "--#{@name}" + end + + private + + def check(val) + return 'yes' unless val + case val + when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' + when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' + else + setup_rb_error "config: --#{@name} accepts only yes/no for argument" + end + end + end + + class PathItem < Item + def config_type + 'path' + end + + private + + def check(path) + setup_rb_error "config: --#{@name} requires argument" unless path + path[0,1] == '$' ? path : File.expand_path(path) + end + end + + class ProgramItem < Item + def config_type + 'program' + end + end + + class SelectItem < Item + def initialize(name, selection, default, desc) + super + @ok = selection.split('/') + end + + def config_type + 'select' + end + + private + + def check(val) + unless @ok.include?(val.strip) + setup_rb_error "config: use --#{@name}=#{@template} (#{val})" + end + val.strip + end + end + + class ExecItem < Item + def initialize(name, selection, desc, &block) + super name, selection, nil, desc + @ok = selection.split('/') + @action = block + end + + def config_type + 'exec' + end + + def value? + false + end + + def resolve(table) + setup_rb_error "$#{name()} wrongly used as option value" + end + + undef set + + def evaluate(val, table) + v = val.strip.downcase + unless @ok.include?(v) + setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" + end + @action.call v, table + end + end + + class PackageSelectionItem < Item + def initialize(name, template, default, help_default, desc) + super name, template, default, desc + @help_default = help_default + end + + attr_reader :help_default + + def config_type + 'package' + end + + private + + def check(val) + unless File.dir?("packages/#{val}") + setup_rb_error "config: no such package: #{val}" + end + val + end + end + + class MetaConfigEnvironment + def initialize(config, installer) + @config = config + @installer = installer + end + + def config_names + @config.names + end + + def config?(name) + @config.key?(name) + end + + def bool_config?(name) + @config.lookup(name).config_type == 'bool' + end + + def path_config?(name) + @config.lookup(name).config_type == 'path' + end + + def value_config?(name) + @config.lookup(name).config_type != 'exec' + end + + def add_config(item) + @config.add item + end + + def add_bool_config(name, default, desc) + @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) + end + + def add_path_config(name, default, desc) + @config.add PathItem.new(name, 'path', default, desc) + end + + def set_config_default(name, default) + @config.lookup(name).default = default + end + + def remove_config(name) + @config.remove(name) + end + + # For only multipackage + def packages + raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer + @installer.packages + end + + # For only multipackage + def declare_packages(list) + raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer + @installer.packages = list + end + end + +end # class ConfigTable + + +# This module requires: #verbose?, #no_harm? +module FileOperations + + def mkdir_p(dirname, prefix = nil) + dirname = prefix + File.expand_path(dirname) if prefix + $stderr.puts "mkdir -p #{dirname}" if verbose? + return if no_harm? + + # Does not check '/', it's too abnormal. + dirs = File.expand_path(dirname).split(%r<(?=/)>) + if /\A[a-z]:\z/i =~ dirs[0] + disk = dirs.shift + dirs[0] = disk + dirs[0] + end + dirs.each_index do |idx| + path = dirs[0..idx].join('') + Dir.mkdir path unless File.dir?(path) + end + end + + def rm_f(path) + $stderr.puts "rm -f #{path}" if verbose? + return if no_harm? + force_remove_file path + end + + def rm_rf(path) + $stderr.puts "rm -rf #{path}" if verbose? + return if no_harm? + remove_tree path + end + + def remove_tree(path) + if File.symlink?(path) + remove_file path + elsif File.dir?(path) + remove_tree0 path + else + force_remove_file path + end + end + + def remove_tree0(path) + Dir.foreach(path) do |ent| + next if ent == '.' + next if ent == '..' + entpath = "#{path}/#{ent}" + if File.symlink?(entpath) + remove_file entpath + elsif File.dir?(entpath) + remove_tree0 entpath + else + force_remove_file entpath + end + end + begin + Dir.rmdir path + rescue Errno::ENOTEMPTY + # directory may not be empty + end + end + + def move_file(src, dest) + force_remove_file dest + begin + File.rename src, dest + rescue + File.open(dest, 'wb') {|f| + f.write File.binread(src) + } + File.chmod File.stat(src).mode, dest + File.unlink src + end + end + + def force_remove_file(path) + begin + remove_file path + rescue + end + end + + def remove_file(path) + File.chmod 0777, path + File.unlink path + end + + def install(from, dest, mode, prefix = nil) + $stderr.puts "install #{from} #{dest}" if verbose? + return if no_harm? + + realdest = prefix ? prefix + File.expand_path(dest) : dest + realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) + str = File.binread(from) + if diff?(str, realdest) + verbose_off { + rm_f realdest if File.exist?(realdest) + } + File.open(realdest, 'wb') {|f| + f.write str + } + File.chmod mode, realdest + + File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| + if prefix + f.puts realdest.sub(prefix, '') + else + f.puts realdest + end + } + end + end + + def diff?(new_content, path) + return true unless File.exist?(path) + new_content != File.binread(path) + end + + def command(*args) + $stderr.puts args.join(' ') if verbose? + system(*args) or raise RuntimeError, + "system(#{args.map{|a| a.inspect }.join(' ')}) failed" + end + + def ruby(*args) + command config('rubyprog'), *args + end + + def make(task = nil) + command(*[config('makeprog'), task].compact) + end + + def extdir?(dir) + File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") + end + + def files_of(dir) + Dir.open(dir) {|d| + return d.select {|ent| File.file?("#{dir}/#{ent}") } + } + end + + DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) + + def directories_of(dir) + Dir.open(dir) {|d| + return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT + } + end + +end + + +# This module requires: #srcdir_root, #objdir_root, #relpath +module HookScriptAPI + + def get_config(key) + @config[key] + end + + alias config get_config + + # obsolete: use metaconfig to change configuration + def set_config(key, val) + @config[key] = val + end + + # + # srcdir/objdir (works only in the package directory) + # + + def curr_srcdir + "#{srcdir_root()}/#{relpath()}" + end + + def curr_objdir + "#{objdir_root()}/#{relpath()}" + end + + def srcfile(path) + "#{curr_srcdir()}/#{path}" + end + + def srcexist?(path) + File.exist?(srcfile(path)) + end + + def srcdirectory?(path) + File.dir?(srcfile(path)) + end + + def srcfile?(path) + File.file?(srcfile(path)) + end + + def srcentries(path = '.') + Dir.open("#{curr_srcdir()}/#{path}") {|d| + return d.to_a - %w(. ..) + } + end + + def srcfiles(path = '.') + srcentries(path).select {|fname| + File.file?(File.join(curr_srcdir(), path, fname)) + } + end + + def srcdirectories(path = '.') + srcentries(path).select {|fname| + File.dir?(File.join(curr_srcdir(), path, fname)) + } + end + +end + + +class ToplevelInstaller + + Version = '3.4.1' + Copyright = 'Copyright (c) 2000-2005 Minero Aoki' + + TASKS = [ + [ 'all', 'do config, setup, then install' ], + [ 'config', 'saves your configurations' ], + [ 'show', 'shows current configuration' ], + [ 'setup', 'compiles ruby extentions and others' ], + [ 'install', 'installs files' ], + [ 'test', 'run all tests in test/' ], + [ 'clean', "does `make clean' for each extention" ], + [ 'distclean',"does `make distclean' for each extention" ] + ] + + def ToplevelInstaller.invoke + config = ConfigTable.new(load_rbconfig()) + config.load_standard_entries + config.load_multipackage_entries if multipackage? + config.fixup + klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) + klass.new(File.dirname($0), config).invoke + end + + def ToplevelInstaller.multipackage? + File.dir?(File.dirname($0) + '/packages') + end + + def ToplevelInstaller.load_rbconfig + if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } + ARGV.delete(arg) + load File.expand_path(arg.split(/=/, 2)[1]) + $".push 'rbconfig.rb' + else + require 'rbconfig' + end + ::Config::CONFIG + end + + def initialize(ardir_root, config) + @ardir = File.expand_path(ardir_root) + @config = config + # cache + @valid_task_re = nil + end + + def config(key) + @config[key] + end + + def inspect + "#<#{self.class} #{__id__()}>" + end + + def invoke + run_metaconfigs + case task = parsearg_global() + when nil, 'all' + parsearg_config + init_installers + exec_config + exec_setup + exec_install + else + case task + when 'config', 'test' + ; + when 'clean', 'distclean' + @config.load_savefile if File.exist?(@config.savefile) + else + @config.load_savefile + end + __send__ "parsearg_#{task}" + init_installers + __send__ "exec_#{task}" + end + end + + def run_metaconfigs + @config.load_script "#{@ardir}/metaconfig" + end + + def init_installers + @installer = Installer.new(@config, @ardir, File.expand_path('.')) + end + + # + # Hook Script API bases + # + + def srcdir_root + @ardir + end + + def objdir_root + '.' + end + + def relpath + '.' + end + + # + # Option Parsing + # + + def parsearg_global + while arg = ARGV.shift + case arg + when /\A\w+\z/ + setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) + return arg + when '-q', '--quiet' + @config.verbose = false + when '--verbose' + @config.verbose = true + when '--help' + print_usage $stdout + exit 0 + when '--version' + puts "#{File.basename($0)} version #{Version}" + exit 0 + when '--copyright' + puts Copyright + exit 0 + else + setup_rb_error "unknown global option '#{arg}'" + end + end + nil + end + + def valid_task?(t) + valid_task_re() =~ t + end + + def valid_task_re + @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ + end + + def parsearg_no_options + unless ARGV.empty? + task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) + setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" + end + end + + alias parsearg_show parsearg_no_options + alias parsearg_setup parsearg_no_options + alias parsearg_test parsearg_no_options + alias parsearg_clean parsearg_no_options + alias parsearg_distclean parsearg_no_options + + def parsearg_config + evalopt = [] + set = [] + @config.config_opt = [] + while i = ARGV.shift + if /\A--?\z/ =~ i + @config.config_opt = ARGV.dup + break + end + name, value = *@config.parse_opt(i) + if @config.value_config?(name) + @config[name] = value + else + evalopt.push [name, value] + end + set.push name + end + evalopt.each do |name, value| + @config.lookup(name).evaluate value, @config + end + # Check if configuration is valid + set.each do |n| + @config[n] if @config.value_config?(n) + end + end + + def parsearg_install + @config.no_harm = false + @config.install_prefix = '' + while a = ARGV.shift + case a + when '--no-harm' + @config.no_harm = true + when /\A--prefix=/ + path = a.split(/=/, 2)[1] + path = File.expand_path(path) unless path[0,1] == '/' + @config.install_prefix = path + else + setup_rb_error "install: unknown option #{a}" + end + end + end + + def print_usage(out) + out.puts 'Typical Installation Procedure:' + out.puts " $ ruby #{File.basename $0} config" + out.puts " $ ruby #{File.basename $0} setup" + out.puts " # ruby #{File.basename $0} install (may require root privilege)" + out.puts + out.puts 'Detailed Usage:' + out.puts " ruby #{File.basename $0} <global option>" + out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]" + + fmt = " %-24s %s\n" + out.puts + out.puts 'Global options:' + out.printf fmt, '-q,--quiet', 'suppress message outputs' + out.printf fmt, ' --verbose', 'output messages verbosely' + out.printf fmt, ' --help', 'print this message' + out.printf fmt, ' --version', 'print version and quit' + out.printf fmt, ' --copyright', 'print copyright and quit' + out.puts + out.puts 'Tasks:' + TASKS.each do |name, desc| + out.printf fmt, name, desc + end + + fmt = " %-24s %s [%s]\n" + out.puts + out.puts 'Options for CONFIG or ALL:' + @config.each do |item| + out.printf fmt, item.help_opt, item.description, item.help_default + end + out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" + out.puts + out.puts 'Options for INSTALL:' + out.printf fmt, '--no-harm', 'only display what to do if given', 'off' + out.printf fmt, '--prefix=path', 'install path prefix', '' + out.puts + end + + # + # Task Handlers + # + + def exec_config + @installer.exec_config + @config.save # must be final + end + + def exec_setup + @installer.exec_setup + end + + def exec_install + @installer.exec_install + end + + def exec_test + @installer.exec_test + end + + def exec_show + @config.each do |i| + printf "%-20s %s\n", i.name, i.value if i.value? + end + end + + def exec_clean + @installer.exec_clean + end + + def exec_distclean + @installer.exec_distclean + end + +end # class ToplevelInstaller + + +class ToplevelInstallerMulti < ToplevelInstaller + + include FileOperations + + def initialize(ardir_root, config) + super + @packages = directories_of("#{@ardir}/packages") + raise 'no package exists' if @packages.empty? + @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) + end + + def run_metaconfigs + @config.load_script "#{@ardir}/metaconfig", self + @packages.each do |name| + @config.load_script "#{@ardir}/packages/#{name}/metaconfig" + end + end + + attr_reader :packages + + def packages=(list) + raise 'package list is empty' if list.empty? + list.each do |name| + raise "directory packages/#{name} does not exist"\ + unless File.dir?("#{@ardir}/packages/#{name}") + end + @packages = list + end + + def init_installers + @installers = {} + @packages.each do |pack| + @installers[pack] = Installer.new(@config, + "#{@ardir}/packages/#{pack}", + "packages/#{pack}") + end + with = extract_selection(config('with')) + without = extract_selection(config('without')) + @selected = @installers.keys.select {|name| + (with.empty? or with.include?(name)) \ + and not without.include?(name) + } + end + + def extract_selection(list) + a = list.split(/,/) + a.each do |name| + setup_rb_error "no such package: #{name}" unless @installers.key?(name) + end + a + end + + def print_usage(f) + super + f.puts 'Inluded packages:' + f.puts ' ' + @packages.sort.join(' ') + f.puts + end + + # + # Task Handlers + # + + def exec_config + run_hook 'pre-config' + each_selected_installers {|inst| inst.exec_config } + run_hook 'post-config' + @config.save # must be final + end + + def exec_setup + run_hook 'pre-setup' + each_selected_installers {|inst| inst.exec_setup } + run_hook 'post-setup' + end + + def exec_install + run_hook 'pre-install' + each_selected_installers {|inst| inst.exec_install } + run_hook 'post-install' + end + + def exec_test + run_hook 'pre-test' + each_selected_installers {|inst| inst.exec_test } + run_hook 'post-test' + end + + def exec_clean + rm_f @config.savefile + run_hook 'pre-clean' + each_selected_installers {|inst| inst.exec_clean } + run_hook 'post-clean' + end + + def exec_distclean + rm_f @config.savefile + run_hook 'pre-distclean' + each_selected_installers {|inst| inst.exec_distclean } + run_hook 'post-distclean' + end + + # + # lib + # + + def each_selected_installers + Dir.mkdir 'packages' unless File.dir?('packages') + @selected.each do |pack| + $stderr.puts "Processing the package `#{pack}' ..." if verbose? + Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") + Dir.chdir "packages/#{pack}" + yield @installers[pack] + Dir.chdir '../..' + end + end + + def run_hook(id) + @root_installer.run_hook id + end + + # module FileOperations requires this + def verbose? + @config.verbose? + end + + # module FileOperations requires this + def no_harm? + @config.no_harm? + end + +end # class ToplevelInstallerMulti + + +class Installer + + FILETYPES = %w( bin lib ext data conf man ) + + include FileOperations + include HookScriptAPI + + def initialize(config, srcroot, objroot) + @config = config + @srcdir = File.expand_path(srcroot) + @objdir = File.expand_path(objroot) + @currdir = '.' + end + + def inspect + "#<#{self.class} #{File.basename(@srcdir)}>" + end + + def noop(rel) + end + + # + # Hook Script API base methods + # + + def srcdir_root + @srcdir + end + + def objdir_root + @objdir + end + + def relpath + @currdir + end + + # + # Config Access + # + + # module FileOperations requires this + def verbose? + @config.verbose? + end + + # module FileOperations requires this + def no_harm? + @config.no_harm? + end + + def verbose_off + begin + save, @config.verbose = @config.verbose?, false + yield + ensure + @config.verbose = save + end + end + + # + # TASK config + # + + def exec_config + exec_task_traverse 'config' + end + + alias config_dir_bin noop + alias config_dir_lib noop + + def config_dir_ext(rel) + extconf if extdir?(curr_srcdir()) + end + + alias config_dir_data noop + alias config_dir_conf noop + alias config_dir_man noop + + def extconf + ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt + end + + # + # TASK setup + # + + def exec_setup + exec_task_traverse 'setup' + end + + def setup_dir_bin(rel) + files_of(curr_srcdir()).each do |fname| + update_shebang_line "#{curr_srcdir()}/#{fname}" + end + end + + alias setup_dir_lib noop + + def setup_dir_ext(rel) + make if extdir?(curr_srcdir()) + end + + alias setup_dir_data noop + alias setup_dir_conf noop + alias setup_dir_man noop + + def update_shebang_line(path) + return if no_harm? + return if config('shebang') == 'never' + old = Shebang.load(path) + if old + $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 + new = new_shebang(old) + return if new.to_s == old.to_s + else + return unless config('shebang') == 'all' + new = Shebang.new(config('rubypath')) + end + $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? + open_atomic_writer(path) {|output| + File.open(path, 'rb') {|f| + f.gets if old # discard + output.puts new.to_s + output.print f.read + } + } + end + + def new_shebang(old) + if /\Aruby/ =~ File.basename(old.cmd) + Shebang.new(config('rubypath'), old.args) + elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' + Shebang.new(config('rubypath'), old.args[1..-1]) + else + return old unless config('shebang') == 'all' + Shebang.new(config('rubypath')) + end + end + + def open_atomic_writer(path, &block) + tmpfile = File.basename(path) + '.tmp' + begin + File.open(tmpfile, 'wb', &block) + File.rename tmpfile, File.basename(path) + ensure + File.unlink tmpfile if File.exist?(tmpfile) + end + end + + class Shebang + def Shebang.load(path) + line = nil + File.open(path) {|f| + line = f.gets + } + return nil unless /\A#!/ =~ line + parse(line) + end + + def Shebang.parse(line) + cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') + new(cmd, args) + end + + def initialize(cmd, args = []) + @cmd = cmd + @args = args + end + + attr_reader :cmd + attr_reader :args + + def to_s + "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") + end + end + + # + # TASK install + # + + def exec_install + rm_f 'InstalledFiles' + exec_task_traverse 'install' + end + + def install_dir_bin(rel) + install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 + end + + def install_dir_lib(rel) + install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 + end + + def install_dir_ext(rel) + return unless extdir?(curr_srcdir()) + install_files rubyextentions('.'), + "#{config('sodir')}/#{File.dirname(rel)}", + 0555 + end + + def install_dir_data(rel) + install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 + end + + def install_dir_conf(rel) + # FIXME: should not remove current config files + # (rename previous file to .old/.org) + install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 + end + + def install_dir_man(rel) + install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 + end + + def install_files(list, dest, mode) + mkdir_p dest, @config.install_prefix + list.each do |fname| + install fname, dest, mode, @config.install_prefix + end + end + + def libfiles + glob_reject(%w(*.y *.output), targetfiles()) + end + + def rubyextentions(dir) + ents = glob_select("*.#{@config.dllext}", targetfiles()) + if ents.empty? + setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" + end + ents + end + + def targetfiles + mapdir(existfiles() - hookfiles()) + end + + def mapdir(ents) + ents.map {|ent| + if File.exist?(ent) + then ent # objdir + else "#{curr_srcdir()}/#{ent}" # srcdir + end + } + end + + # picked up many entries from cvs-1.11.1/src/ignore.c + JUNK_FILES = %w( + core RCSLOG tags TAGS .make.state + .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb + *~ *.old *.bak *.BAK *.orig *.rej _$* *$ + + *.org *.in .* + ) + + def existfiles + glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) + end + + def hookfiles + %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| + %w( config setup install clean ).map {|t| sprintf(fmt, t) } + }.flatten + end + + def glob_select(pat, ents) + re = globs2re([pat]) + ents.select {|ent| re =~ ent } + end + + def glob_reject(pats, ents) + re = globs2re(pats) + ents.reject {|ent| re =~ ent } + end + + GLOB2REGEX = { + '.' => '\.', + '$' => '\$', + '#' => '\#', + '*' => '.*' + } + + def globs2re(pats) + /\A(?:#{ + pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') + })\z/ + end + + # + # TASK test + # + + TESTDIR = 'test' + + def exec_test + unless File.directory?('test') + $stderr.puts 'no test in this package' if verbose? + return + end + $stderr.puts 'Running tests...' if verbose? + begin + require 'test/unit' + rescue LoadError + setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' + end + runner = Test::Unit::AutoRunner.new(true) + runner.to_run << TESTDIR + runner.run + end + + # + # TASK clean + # + + def exec_clean + exec_task_traverse 'clean' + rm_f @config.savefile + rm_f 'InstalledFiles' + end + + alias clean_dir_bin noop + alias clean_dir_lib noop + alias clean_dir_data noop + alias clean_dir_conf noop + alias clean_dir_man noop + + def clean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'clean' if File.file?('Makefile') + end + + # + # TASK distclean + # + + def exec_distclean + exec_task_traverse 'distclean' + rm_f @config.savefile + rm_f 'InstalledFiles' + end + + alias distclean_dir_bin noop + alias distclean_dir_lib noop + + def distclean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'distclean' if File.file?('Makefile') + end + + alias distclean_dir_data noop + alias distclean_dir_conf noop + alias distclean_dir_man noop + + # + # Traversing + # + + def exec_task_traverse(task) + run_hook "pre-#{task}" + FILETYPES.each do |type| + if type == 'ext' and config('without-ext') == 'yes' + $stderr.puts 'skipping ext/* by user option' if verbose? + next + end + traverse task, type, "#{task}_dir_#{type}" + end + run_hook "post-#{task}" + end + + def traverse(task, rel, mid) + dive_into(rel) { + run_hook "pre-#{task}" + __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') + directories_of(curr_srcdir()).each do |d| + traverse task, "#{rel}/#{d}", mid + end + run_hook "post-#{task}" + } + end + + def dive_into(rel) + return unless File.dir?("#{@srcdir}/#{rel}") + + dir = File.basename(rel) + Dir.mkdir dir unless File.dir?(dir) + prevdir = Dir.pwd + Dir.chdir dir + $stderr.puts '---> ' + rel if verbose? + @currdir = rel + yield + Dir.chdir prevdir + $stderr.puts '<--- ' + rel if verbose? + @currdir = File.dirname(rel) + end + + def run_hook(id) + path = [ "#{curr_srcdir()}/#{id}", + "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } + return unless path + begin + instance_eval File.read(path), path, 1 + rescue + raise if $DEBUG + setup_rb_error "hook #{path} failed:\n" + $!.message + end + end + +end # class Installer + + +class SetupError < StandardError; end + +def setup_rb_error(msg) + raise SetupError, msg +end + +if $0 == __FILE__ + begin + ToplevelInstaller.invoke + rescue SetupError + raise if $DEBUG + $stderr.puts $!.message + $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." + exit 1 + end +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.document b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.document new file mode 100644 index 000000000..ecf367319 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.document @@ -0,0 +1,5 @@ +README.rdoc +lib/**/*.rb +bin/* +features/**/*.feature +LICENSE diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.gitignore b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.gitignore new file mode 100644 index 000000000..482f92bf7 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +.yardoc +/coverage +/doc +/pkg diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/LICENSE b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/LICENSE new file mode 100644 index 000000000..590bcb6fa --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/LICENSE @@ -0,0 +1,20 @@ +Copyright 2009 Chris Kampmeier + +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. diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/README.rdoc b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/README.rdoc new file mode 100644 index 000000000..cfab5434f --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/README.rdoc @@ -0,0 +1,70 @@ += Samuel + +Samuel is a gem for automatic logging of your Net::HTTP requests. It's named for +the serial diarist Mr. Pepys, who was known to reliably record events both +quotidian and remarkable. + +Should a Great Plague, Fire, or Whale befall an important external web service +you use, you'll be sure to have a tidy record of it. + +== Usage: + +When Rails is loaded, Samuel configures a few things automatically. So all you +need to do is this: + + # config/environment.rb + config.gem "samuel" + +And Samuel will automatically use Rails's logger and an ActiveRecord-like format. + +For non-Rails projects, you'll have to manually configure logging, like this: + + require 'samuel' + Samuel.logger = Logger.new('http_requests.log') + +If you don't assign a logger, Samuel will configure a default logger on +STDOUT+. + +== Configuration + +There are two ways to specify configuration options for Samuel: global and +inline. Global configs look like this: + + Samuel.config[:labels] = {"example.com" => "Example API"} + Samuel.config[:filtered_params] = :password + +You should put global configuration somewhere early-on in your program. If +you're using Rails, <tt>config/initializers/samuel.rb</tt> will do the trick. + +Alternatively, an inline configuration block temporarily overrides any global +configuration for a set of HTTP requests: + + Samuel.with_config :label => "Twitter API" do + Net::HTTP.start("twitter.com") { |http| http.get("/help/test") } + end + +Right now, there are three configuration changes you can make in either style: + +* +:labels+ - This is a hash with domain substrings as keys and log labels as + values. If a request domain includes one of the domain substrings, the + corresponding label will be used for the first part of that log entry. By + default this is set to <tt>\{"" => "HTTP"}</tt>, so that all requests are + labeled with <tt>"HTTP Request"</tt>. +* +:label+ - As an alternative to the +:labels+ hash, this is simply a string. + If set, it takes precedence over any +:labels+ (by default, it's not set). It + gets <tt>"Request"</tt> appended to it as well -- so if you want your log to + always say +Twitter API Request+ instead of the default +HTTP Request+, you + can set this to <tt>"Twitter API"</tt>. I'd recommend using this setting + globally if you're only making requests to one service, or inline if you just + need to temporarily override the global +:labels+. +* +:filtered_params+ - This works just like Rails's +filter_parameter_logging+ + method. Set it to a symbol, string, or array of them, and Samuel will filter + the value of query parameters that have any of these patterns as a substring + by replacing the value with <tt>[FILTERED]</tt> in your logs. By default, no + filtering is enabled. + +Samuel logs successful HTTP requests at the +INFO+ level; Failed requests log at +the +WARN+ level. This isn't currently configurable, but it's on the list. + +== License + +Copyright 2009 Chris Kampmeier. See +LICENSE+ for details. diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/Rakefile b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/Rakefile new file mode 100644 index 000000000..ffbe60384 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/Rakefile @@ -0,0 +1,62 @@ +require 'rubygems' +require 'rake' + +begin + require 'jeweler' + Jeweler::Tasks.new do |gem| + gem.name = "samuel" + gem.summary = %Q{An automatic logger for HTTP requests in Ruby} + gem.description = %Q{An automatic logger for HTTP requests in Ruby. Adds Net::HTTP request logging to your Rails logs, and more.} + gem.email = "chris@kampers.net" + gem.homepage = "http://github.com/chrisk/samuel" + gem.authors = ["Chris Kampmeier"] + gem.rubyforge_project = "samuel" + gem.add_development_dependency "thoughtbot-shoulda" + gem.add_development_dependency "yard" + gem.add_development_dependency "mocha" + gem.add_development_dependency "fakeweb" + end + Jeweler::GemcutterTasks.new + Jeweler::RubyforgeTasks.new do |rubyforge| + rubyforge.doc_task = "yardoc" + end +rescue LoadError + puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" +end + +require 'rake/testtask' +Rake::TestTask.new(:test) do |test| + test.libs << 'lib' << 'test' + test.pattern = 'test/**/*_test.rb' + test.verbose = false + test.warning = true +end + +begin + require 'rcov/rcovtask' + Rcov::RcovTask.new do |test| + test.libs << 'test' + test.pattern = 'test/**/*_test.rb' + test.rcov_opts << "--sort coverage" + test.rcov_opts << "--exclude gems" + test.verbose = false + test.warning = true + end +rescue LoadError + task :rcov do + abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov" + end +end + +task :test => :check_dependencies + +task :default => :test + +begin + require 'yard' + YARD::Rake::YardocTask.new +rescue LoadError + task :yardoc do + abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard" + end +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/VERSION b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/VERSION new file mode 100644 index 000000000..0c62199f1 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/VERSION @@ -0,0 +1 @@ +0.2.1 diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel.rb new file mode 100644 index 000000000..5c8fed6f6 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel.rb @@ -0,0 +1,52 @@ +require "logger" +require "net/http" +require "net/https" +require "benchmark" + +require "samuel/net_http" +require "samuel/request" + + +module Samuel + extend self + + attr_writer :config, :logger + + def logger + @logger = nil if !defined?(@logger) + return @logger if !@logger.nil? + + if defined?(RAILS_DEFAULT_LOGGER) + @logger = RAILS_DEFAULT_LOGGER + else + @logger = Logger.new(STDOUT) + end + end + + def config + Thread.current[:__samuel_config] ? Thread.current[:__samuel_config] : @config + end + + def log_request(http, request, &block) + request = Request.new(http, request, block) + request.perform_and_log! + request.response + end + + def with_config(options = {}) + original_config = config.dup + nested = !Thread.current[:__samuel_config].nil? + + Thread.current[:__samuel_config] = original_config.merge(options) + yield + Thread.current[:__samuel_config] = nested ? original_config : nil + end + + def reset_config + Thread.current[:__samuel_config] = nil + @config = {:label => nil, :labels => {"" => "HTTP"}, :filtered_params => []} + end + +end + +Samuel.reset_config diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/net_http.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/net_http.rb new file mode 100644 index 000000000..2ffadf220 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/net_http.rb @@ -0,0 +1,10 @@ +class Net::HTTP + + alias request_without_samuel request + def request(req, body = nil, &block) + Samuel.log_request(self, req) do + request_without_samuel(req, body, &block) + end + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/request.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/request.rb new file mode 100644 index 000000000..e10ecb44e --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/request.rb @@ -0,0 +1,96 @@ +module Samuel + class Request + + attr_accessor :response + + def initialize(http, request, proc) + @http, @request, @proc = http, request, proc + end + + def perform_and_log! + # If an exception is raised in the Benchmark block, it'll interrupt the + # benchmark. Instead, use an inner block to record it as the "response" + # for raising after the benchmark (and logging) is done. + @seconds = Benchmark.realtime do + begin; @response = @proc.call; rescue Exception => @response; end + end + Samuel.logger.add(log_level, log_message) + raise @response if @response.is_a?(Exception) + end + + private + + def log_message + bold = "\e[1m" + blue = "\e[34m" + underline = "\e[4m" + reset = "\e[0m" + " #{bold}#{blue}#{underline}#{label} request (#{milliseconds}ms) " + + "#{response_summary}#{reset} #{method} #{uri}" + end + + def milliseconds + (@seconds * 1000).round + end + + def uri + "#{scheme}://#{@http.address}#{port_if_not_default}#{filtered_path}" + end + + def filtered_path + path_without_query, query = @request.path.split("?") + if query + patterns = [Samuel.config[:filtered_params]].flatten + patterns.map { |pattern| + pattern_for_regex = Regexp.escape(pattern.to_s) + [/([^&]*#{pattern_for_regex}[^&=]*)=(?:[^&]+)/, '\1=[FILTERED]'] + }.each { |filter| query.gsub!(*filter) } + "#{path_without_query}?#{query}" + else + @request.path + end + end + + def scheme + @http.use_ssl? ? "https" : "http" + end + + def port_if_not_default + ssl, port = @http.use_ssl?, @http.port + if (!ssl && port == 80) || (ssl && port == 443) + "" + else + ":#{port}" + end + end + + def method + @request.method.to_s.upcase + end + + def label + return Samuel.config[:label] if Samuel.config[:label] + + pair = Samuel.config[:labels].detect { |domain, label| @http.address.include?(domain) } + pair[1] if pair + end + + def response_summary + if response.is_a?(Exception) + response.class + else + "[#{response.code} #{response.message}]" + end + end + + def log_level + error_classes = [Exception, Net::HTTPClientError, Net::HTTPServerError] + if error_classes.any? { |klass| response.is_a?(klass) } + level = Logger::WARN + else + level = Logger::INFO + end + end + + end +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/samuel.gemspec b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/samuel.gemspec new file mode 100644 index 000000000..3a3719bf8 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/samuel.gemspec @@ -0,0 +1,69 @@ +# Generated by jeweler +# DO NOT EDIT THIS FILE +# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec` +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{samuel} + s.version = "0.2.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Chris Kampmeier"] + s.date = %q{2009-09-15} + s.description = %q{An automatic logger for HTTP requests in Ruby. Adds Net::HTTP request logging to your Rails logs, and more.} + s.email = %q{chris@kampers.net} + s.extra_rdoc_files = [ + "LICENSE", + "README.rdoc" + ] + s.files = [ + ".document", + ".gitignore", + "LICENSE", + "README.rdoc", + "Rakefile", + "VERSION", + "lib/samuel.rb", + "lib/samuel/net_http.rb", + "lib/samuel/request.rb", + "samuel.gemspec", + "test/request_test.rb", + "test/samuel_test.rb", + "test/test_helper.rb", + "test/thread_test.rb" + ] + s.homepage = %q{http://github.com/chrisk/samuel} + s.rdoc_options = ["--charset=UTF-8"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{samuel} + s.rubygems_version = %q{1.3.5} + s.summary = %q{An automatic logger for HTTP requests in Ruby} + s.test_files = [ + "test/request_test.rb", + "test/samuel_test.rb", + "test/test_helper.rb", + "test/thread_test.rb" + ] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"]) + s.add_development_dependency(%q<yard>, [">= 0"]) + s.add_development_dependency(%q<mocha>, [">= 0"]) + s.add_development_dependency(%q<fakeweb>, [">= 0"]) + else + s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"]) + s.add_dependency(%q<yard>, [">= 0"]) + s.add_dependency(%q<mocha>, [">= 0"]) + s.add_dependency(%q<fakeweb>, [">= 0"]) + end + else + s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"]) + s.add_dependency(%q<yard>, [">= 0"]) + s.add_dependency(%q<mocha>, [">= 0"]) + s.add_dependency(%q<fakeweb>, [">= 0"]) + end +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/request_test.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/request_test.rb new file mode 100644 index 000000000..4e905d1ec --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/request_test.rb @@ -0,0 +1,193 @@ +require 'test_helper' + +class RequestTest < Test::Unit::TestCase + + context "making an HTTP request" do + setup { setup_test_logger + FakeWeb.clean_registry + Samuel.reset_config } + teardown { teardown_test_logger } + + context "to GET http://example.com/test, responding with a 200 in 53ms" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) + Benchmark.stubs(:realtime).yields.returns(0.053) + open "http://example.com/test" + end + + should_log_lines 1 + should_log_at_level :info + should_log_including "HTTP request" + should_log_including "(53ms)" + should_log_including "[200 OK]" + should_log_including "GET http://example.com/test" + end + + context "on a non-standard port" do + setup do + FakeWeb.register_uri(:get, "http://example.com:8080/test", :status => [200, "OK"]) + open "http://example.com:8080/test" + end + + should_log_including "GET http://example.com:8080/test" + end + + context "with SSL" do + setup do + FakeWeb.register_uri(:get, "https://example.com/test", :status => [200, "OK"]) + open "https://example.com/test" + end + + should_log_including "HTTP request" + should_log_including "GET https://example.com/test" + end + + context "with SSL on a non-standard port" do + setup do + FakeWeb.register_uri(:get, "https://example.com:80/test", :status => [200, "OK"]) + open "https://example.com:80/test" + end + + should_log_including "HTTP request" + should_log_including "GET https://example.com:80/test" + end + + context "that raises" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :exception => Errno::ECONNREFUSED) + begin + Net::HTTP.start("example.com") { |http| http.get("/test") } + rescue Errno::ECONNREFUSED => @exception + end + end + + should_log_at_level :warn + should_log_including "HTTP request" + should_log_including "GET http://example.com/test" + should_log_including "Errno::ECONNREFUSED" + should_log_including %r|\d+ms| + should_raise_exception Errno::ECONNREFUSED + end + + context "that responds with a 500-level code" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :status => [502, "Bad Gateway"]) + Net::HTTP.start("example.com") { |http| http.get("/test") } + end + + should_log_at_level :warn + end + + context "that responds with a 400-level code" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :status => [404, "Not Found"]) + Net::HTTP.start("example.com") { |http| http.get("/test") } + end + + should_log_at_level :warn + end + + context "inside a configuration block with :label => 'Example'" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) + Samuel.with_config :label => "Example" do + open "http://example.com/test" + end + end + + should_log_including "Example request" + should_have_config_afterwards_including :labels => {"" => "HTTP"}, + :label => nil + end + + context "inside a configuration block with :filter_params" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test?password=secret&username=chrisk", + :status => [200, "OK"]) + @uri = "http://example.com/test?password=secret&username=chrisk" + end + + context "=> :password" do + setup { Samuel.with_config(:filtered_params => :password) { open @uri } } + should_log_including "http://example.com/test?password=[FILTERED]&username=chrisk" + end + + context "=> :as" do + setup { Samuel.with_config(:filtered_params => :ass) { open @uri } } + should_log_including "http://example.com/test?password=[FILTERED]&username=chrisk" + end + + context "=> ['pass', 'name']" do + setup { Samuel.with_config(:filtered_params => %w(pass name)) { open @uri } } + should_log_including "http://example.com/test?password=[FILTERED]&username=[FILTERED]" + end + end + + context "with a global config including :label => 'Example'" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) + Samuel.config[:label] = "Example" + open "http://example.com/test" + end + + should_log_including "Example request" + should_have_config_afterwards_including :labels => {"" => "HTTP"}, + :label => "Example" + end + + context "with a global config including :label => 'Example' but inside config block that changes it to 'Example 2'" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) + Samuel.config[:label] = "Example" + Samuel.with_config(:label => "Example 2") { open "http://example.com/test" } + end + + should_log_including "Example 2 request" + should_have_config_afterwards_including :labels => {"" => "HTTP"}, + :label => "Example" + end + + context "inside a config block of :label => 'Example 2' nested inside a config block of :label => 'Example'" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) + Samuel.with_config :label => "Example" do + Samuel.with_config :label => "Example 2" do + open "http://example.com/test" + end + end + end + + should_log_including "Example 2 request" + should_have_config_afterwards_including :labels => {"" => "HTTP"}, + :label => nil + end + + context "wth a global config including :labels => {'example.com' => 'Example'} but inside a config block of :label => 'Example 3' nested inside a config block of :label => 'Example 2'" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) + Samuel.config[:labels] = {'example.com' => 'Example'} + Samuel.with_config :label => "Example 2" do + Samuel.with_config :label => "Example 3" do + open "http://example.com/test" + end + end + end + + should_log_including "Example 3 request" + should_have_config_afterwards_including :labels => {'example.com' => 'Example'}, + :label => nil + end + + context "with a global config including :labels => {'example.com' => 'Example API'}" do + setup do + FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) + Samuel.config[:labels] = {'example.com' => 'Example API'} + open "http://example.com/test" + end + + should_log_including "Example API request" + end + + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/samuel_test.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/samuel_test.rb new file mode 100644 index 000000000..4a3665fa6 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/samuel_test.rb @@ -0,0 +1,42 @@ +require 'test_helper' + +class SamuelTest < Test::Unit::TestCase + + context "logger configuration" do + setup do + Samuel.logger = nil + if Object.const_defined?(:RAILS_DEFAULT_LOGGER) + Object.send(:remove_const, :RAILS_DEFAULT_LOGGER) + end + end + + teardown do + Samuel.logger = nil + end + + context "when Rails's logger is available" do + setup { Object.const_set(:RAILS_DEFAULT_LOGGER, :mock_logger) } + + should "use the same logger" do + assert_equal :mock_logger, Samuel.logger + end + end + + context "when Rails's logger is not available" do + should "use a new Logger instance pointed to STDOUT" do + assert_instance_of Logger, Samuel.logger + assert_equal STDOUT, Samuel.logger.instance_variable_get(:"@logdev").dev + end + end + end + + + context ".reset_config" do + should "reset the config to default vaules" do + Samuel.config = {:foo => "bar"} + Samuel.reset_config + assert_equal({:label => nil, :labels => {"" => "HTTP"}, :filtered_params => []}, Samuel.config) + end + end + +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/test_helper.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/test_helper.rb new file mode 100644 index 000000000..2862051b9 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/test_helper.rb @@ -0,0 +1,66 @@ +require 'rubygems' +require 'test/unit' +require 'shoulda' +require 'mocha' +require 'open-uri' +require 'fakeweb' + +FakeWeb.allow_net_connect = false + +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +$LOAD_PATH.unshift(File.dirname(__FILE__)) +require 'samuel' + +class Test::Unit::TestCase + TEST_LOG_PATH = File.join(File.dirname(__FILE__), 'test.log') + + def self.should_log_lines(expected_count) + should "log #{expected_count} line#{'s' unless expected_count == 1}" do + lines = File.readlines(TEST_LOG_PATH) + assert_equal expected_count, lines.length + end + end + + def self.should_log_including(what) + should "log a line including #{what.inspect}" do + contents = File.read(TEST_LOG_PATH) + if what.is_a?(Regexp) + assert_match what, contents + else + assert contents.include?(what), + "Expected #{contents.inspect} to include #{what.inspect}" + end + end + end + + def self.should_log_at_level(level) + level = level.to_s.upcase + should "log at the #{level} level" do + assert File.read(TEST_LOG_PATH).include?(" #{level} -- :") + end + end + + def self.should_raise_exception(klass) + should "raise an #{klass} exception" do + assert @exception.is_a?(klass) + end + end + + def self.should_have_config_afterwards_including(config) + config.each_pair do |key, value| + should "continue afterwards with Samuel.config[#{key.inspect}] set to #{value.inspect}" do + assert_equal value, Samuel.config[key] + end + end + end + + def setup_test_logger + FileUtils.rm_rf TEST_LOG_PATH + FileUtils.touch TEST_LOG_PATH + Samuel.logger = Logger.new(TEST_LOG_PATH) + end + + def teardown_test_logger + FileUtils.rm_rf TEST_LOG_PATH + end +end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/thread_test.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/thread_test.rb new file mode 100644 index 000000000..d030cb973 --- /dev/null +++ b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/thread_test.rb @@ -0,0 +1,32 @@ +require 'test_helper' + +class ThreadTest < Test::Unit::TestCase + + context "when logging multiple requests at once" do + setup do + @log = StringIO.new + Samuel.logger = Logger.new(@log) + FakeWeb.register_uri(:get, /example\.com/, :status => [200, "OK"]) + threads = [] + 5.times do |i| + threads << Thread.new(i) do |n| + Samuel.with_config :label => "Example #{n}" do + Thread.pass + open "http://example.com/#{n}" + end + end + end + threads.each { |t| t.join } + @log.rewind + end + + should "not let configuration blocks interfere with eachother" do + @log.each_line do |line| + matches = %r|Example (\d+).*example\.com/(\d+)|.match(line) + assert_not_nil matches + assert_equal matches[1], matches[2] + end + end + end + +end |