summaryrefslogtreecommitdiff
path: root/jni/ruby/lib/rubygems/test_utilities.rb
diff options
context:
space:
mode:
authorJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-16 18:49:26 +0900
committerJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-30 00:39:06 +0900
commitfcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch)
tree64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/lib/rubygems/test_utilities.rb
Fresh start
Diffstat (limited to 'jni/ruby/lib/rubygems/test_utilities.rb')
-rw-r--r--jni/ruby/lib/rubygems/test_utilities.rb383
1 files changed, 383 insertions, 0 deletions
diff --git a/jni/ruby/lib/rubygems/test_utilities.rb b/jni/ruby/lib/rubygems/test_utilities.rb
new file mode 100644
index 0000000..25786e6
--- /dev/null
+++ b/jni/ruby/lib/rubygems/test_utilities.rb
@@ -0,0 +1,383 @@
+require 'tempfile'
+require 'rubygems'
+require 'rubygems/remote_fetcher'
+
+##
+# A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP
+# requests when testing code that uses RubyGems.
+#
+# Example:
+#
+# @fetcher = Gem::FakeFetcher.new
+# @fetcher.data['http://gems.example.com/yaml'] = source_index.to_yaml
+# Gem::RemoteFetcher.fetcher = @fetcher
+#
+# # invoke RubyGems code
+#
+# paths = @fetcher.paths
+# assert_equal 'http://gems.example.com/yaml', paths.shift
+# assert paths.empty?, paths.join(', ')
+#
+# See RubyGems' tests for more examples of FakeFetcher.
+
+class Gem::FakeFetcher
+
+ attr_reader :data
+ attr_reader :last_request
+ attr_reader :api_endpoints
+ attr_accessor :paths
+
+ def initialize
+ @data = {}
+ @paths = []
+ @api_endpoints = {}
+ end
+
+ def api_endpoint(uri)
+ @api_endpoints[uri] || uri
+ end
+
+ def find_data(path)
+ return File.read path.path if URI === path and 'file' == path.scheme
+
+ if URI === path and "URI::#{path.scheme.upcase}" != path.class.name then
+ raise ArgumentError,
+ "mismatch for scheme #{path.scheme} and class #{path.class}"
+ end
+
+ path = path.to_s
+ @paths << path
+ raise ArgumentError, 'need full URI' unless path =~ %r'^https?://'
+
+ unless @data.key? path then
+ raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
+ end
+
+ @data[path]
+ end
+
+ def fetch_path path, mtime = nil, head = false
+ data = find_data(path)
+
+ if data.respond_to?(:call) then
+ data.call
+ else
+ if path.to_s =~ /gz$/ and not data.nil? and not data.empty? then
+ data = Gem.gunzip data
+ end
+
+ data
+ end
+ end
+
+ def cache_update_path uri, path = nil, update = true
+ if data = fetch_path(uri)
+ open(path, 'wb') { |io| io.write data } if path and update
+ data
+ else
+ Gem.read_binary(path) if path
+ end
+ end
+
+ # Thanks, FakeWeb!
+ def open_uri_or_path(path)
+ data = find_data(path)
+ body, code, msg = data
+
+ response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
+ response.instance_variable_set(:@body, body)
+ response.instance_variable_set(:@read, true)
+ response
+ end
+
+ def request(uri, request_class, last_modified = nil)
+ data = find_data(uri)
+ body, code, msg = data
+
+ @last_request = request_class.new uri.request_uri
+ yield @last_request if block_given?
+
+ response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
+ response.instance_variable_set(:@body, body)
+ response.instance_variable_set(:@read, true)
+ response
+ end
+
+ def pretty_print q # :nodoc:
+ q.group 2, '[FakeFetcher', ']' do
+ q.breakable
+ q.text 'URIs:'
+
+ q.breakable
+ q.pp @data.keys
+
+ unless @api_endpoints.empty? then
+ q.breakable
+ q.text 'API endpoints:'
+
+ q.breakable
+ q.pp @api_endpoints.keys
+ end
+ end
+ end
+
+ def fetch_size(path)
+ path = path.to_s
+ @paths << path
+
+ raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
+
+ unless @data.key? path then
+ raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
+ end
+
+ data = @data[path]
+
+ data.respond_to?(:call) ? data.call : data.length
+ end
+
+ def download spec, source_uri, install_dir = Gem.dir
+ name = File.basename spec.cache_file
+ path = if Dir.pwd == install_dir then # see fetch_command
+ install_dir
+ else
+ File.join install_dir, "cache"
+ end
+
+ path = File.join path, name
+
+ if source_uri =~ /^http/ then
+ File.open(path, "wb") do |f|
+ f.write fetch_path(File.join(source_uri, "gems", name))
+ end
+ else
+ FileUtils.cp source_uri, path
+ end
+
+ path
+ end
+
+ def download_to_cache dependency
+ found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dependency
+
+ return if found.empty?
+
+ spec, source = found.first
+
+ download spec, source.uri.to_s
+ end
+
+end
+
+# :stopdoc:
+class Gem::RemoteFetcher
+
+ def self.fetcher=(fetcher)
+ @fetcher = fetcher
+ end
+
+end
+# :startdoc:
+
+##
+# The SpecFetcherSetup allows easy setup of a remote source in RubyGems tests:
+#
+# spec_fetcher do |f|
+# f.gem 'a', 1
+# f.spec 'a', 2
+# f.gem 'b', 1' 'a' => '~> 1.0'
+# f.clear
+# end
+#
+# The above declaration creates two gems, a-1 and b-1, with a dependency from
+# b to a. The declaration creates an additional spec a-2, but no gem for it
+# (so it cannot be installed).
+#
+# After the gems are created they are removed from Gem.dir.
+
+class Gem::TestCase::SpecFetcherSetup
+
+ ##
+ # Executes a SpecFetcher setup block. Yields an instance then creates the
+ # gems and specifications defined in the instance.
+
+ def self.declare test, repository
+ setup = new test, repository
+
+ yield setup
+
+ setup.execute
+ end
+
+ def initialize test, repository # :nodoc:
+ @test = test
+ @repository = repository
+
+ @gems = {}
+ @installed = []
+ @operations = []
+ end
+
+ ##
+ # Removes any created gems or specifications from Gem.dir (the default
+ # install location).
+
+ def clear
+ @operations << [:clear]
+ end
+
+ ##
+ # Returns a Hash of created Specification full names and the corresponding
+ # Specification.
+
+ def created_specs
+ created = {}
+
+ @gems.keys.each do |spec|
+ created[spec.full_name] = spec
+ end
+
+ created
+ end
+
+ ##
+ # Creates any defined gems or specifications
+
+ def execute # :nodoc:
+ execute_operations
+
+ setup_fetcher
+
+ created_specs
+ end
+
+ def execute_operations # :nodoc:
+ @operations.each do |operation, *arguments|
+ case operation
+ when :clear then
+ @test.util_clear_gems
+ @installed.clear
+ when :gem then
+ spec, gem = @test.util_gem(*arguments, &arguments.pop)
+
+ write_spec spec
+
+ @gems[spec] = gem
+ @installed << spec
+ when :spec then
+ spec = @test.util_spec(*arguments, &arguments.pop)
+
+ write_spec spec
+
+ @gems[spec] = nil
+ @installed << spec
+ end
+ end
+ end
+
+ ##
+ # Creates a gem with +name+, +version+ and +deps+. The created gem can be
+ # downloaded and installed.
+ #
+ # The specification will be yielded before gem creation for customization,
+ # but only the block or the dependencies may be set, not both.
+
+ def gem name, version, dependencies = nil, &block
+ @operations << [:gem, name, version, dependencies, block]
+ end
+
+ ##
+ # Creates a legacy platform spec with the name 'pl' and version 1
+
+ def legacy_platform
+ spec 'pl', 1 do |s|
+ s.platform = Gem::Platform.new 'i386-linux'
+ s.instance_variable_set :@original_platform, 'i386-linux'
+ end
+ end
+
+ def setup_fetcher # :nodoc:
+ require 'zlib'
+ require 'socket'
+ require 'rubygems/remote_fetcher'
+
+ unless @test.fetcher then
+ @test.fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @test.fetcher
+ end
+
+ Gem::Specification.reset
+
+ begin
+ gem_repo, @test.gem_repo = @test.gem_repo, @repository
+ @test.uri = URI @repository
+
+ @test.util_setup_spec_fetcher(*@gems.keys)
+ ensure
+ @test.gem_repo = gem_repo
+ @test.uri = URI gem_repo
+ end
+
+ # This works around util_setup_spec_fetcher adding all created gems to the
+ # installed set.
+ Gem::Specification.reset
+ Gem::Specification.add_specs(*@installed)
+
+ @gems.each do |spec, gem|
+ next unless gem
+
+ @test.fetcher.data["#{@repository}gems/#{spec.file_name}"] =
+ Gem.read_binary(gem)
+
+ FileUtils.cp gem, spec.cache_file
+ end
+ end
+
+ ##
+ # Creates a spec with +name+, +version+ and +deps+. The created gem can be
+ # downloaded and installed.
+ #
+ # The specification will be yielded before creation for customization,
+ # but only the block or the dependencies may be set, not both.
+
+ def spec name, version, dependencies = nil, &block
+ @operations << [:spec, name, version, dependencies, block]
+ end
+
+ def write_spec spec # :nodoc:
+ open spec.spec_file, 'w' do |io|
+ io.write spec.to_ruby_for_cache
+ end
+ end
+
+end
+
+##
+# A StringIO duck-typed class that uses Tempfile instead of String as the
+# backing store.
+#
+# This is available when rubygems/test_utilities is required.
+#--
+# This class was added to flush out problems in Rubinius' IO implementation.
+
+class TempIO < Tempfile
+
+ ##
+ # Creates a new TempIO that will be initialized to contain +string+.
+
+ def initialize(string = '')
+ super "TempIO"
+ binmode
+ write string
+ rewind
+ end
+
+ ##
+ # The content of the TempIO as a String.
+
+ def string
+ flush
+ Gem.read_binary path
+ end
+end
+