diff options
author | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-16 18:49:26 +0900 |
---|---|---|
committer | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-30 00:39:06 +0900 |
commit | fcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch) | |
tree | 64cb17de3f41a2b6fef2368028fbd00349946994 /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.rb | 383 |
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 + |