1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/test/rubygems/gemutilities.rb

581 lines
15 KiB
Ruby
Raw Normal View History

#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
at_exit { $SAFE = 1 }
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
if RUBY_VERSION > '1.9' then
Gem::QuickLoader.load_full_rubygems_library
else
require 'rubygems'
end
require 'fileutils'
begin
gem 'minitest', '>= 1.3.1'
require 'minitest/unit'
rescue Gem::LoadError
warn "Install minitest gem >= 1.3.1"
raise
end
require 'tmpdir'
require 'uri'
require 'rubygems/package'
require 'rubygems/test_utilities'
require 'pp'
begin
gem 'rdoc'
rescue Gem::LoadError
end
require 'rdoc/rdoc'
require File.join(File.expand_path(File.dirname(__FILE__)), 'mockgemui')
module Gem
def self.searcher=(searcher)
MUTEX.synchronize do @searcher = searcher end
end
def self.source_index=(si)
@@source_index = si
end
def self.win_platform=(val)
@@win_platform = val
end
module DefaultUserInteraction
@ui = MockGemUi.new
end
end
class RubyGemTestCase < MiniTest::Unit::TestCase
include Gem::DefaultUserInteraction
undef_method :default_test if instance_methods.include? 'default_test' or
instance_methods.include? :default_test
def setup
super
@ui = MockGemUi.new
tmpdir = nil
Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end # HACK OSX /private/tmp
@tempdir = File.join tmpdir, "test_rubygems_#{$$}"
@tempdir.untaint
@gemhome = File.join @tempdir, "gemhome"
@gemcache = File.join(@gemhome, "source_cache")
@usrcache = File.join(@gemhome, ".gem", "user_cache")
@latest_usrcache = File.join(@gemhome, ".gem", "latest_user_cache")
@userhome = File.join @tempdir, 'userhome'
Gem.ensure_gem_subdirectories @gemhome
@orig_ENV_HOME = ENV['HOME']
ENV['HOME'] = @userhome
Gem.instance_variable_set :@user_home, nil
FileUtils.mkdir_p @gemhome
FileUtils.mkdir_p @userhome
ENV['GEMCACHE'] = @usrcache
Gem.use_paths(@gemhome)
Gem.loaded_specs.clear
Gem.configuration.verbose = true
Gem.configuration.update_sources = true
@gem_repo = "http://gems.example.com/"
@uri = URI.parse @gem_repo
Gem.sources.replace [@gem_repo]
Gem::SpecFetcher.fetcher = nil
@orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
Gem::ConfigMap[:BASERUBY] = Gem::ConfigMap[:ruby_install_name]
@orig_arch = Gem::ConfigMap[:arch]
if win_platform?
util_set_arch 'i386-mswin32'
else
util_set_arch 'i686-darwin8.10.1'
end
@marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
@private_key = File.expand_path File.join(File.dirname(__FILE__),
'private_key.pem')
@public_cert = File.expand_path File.join(File.dirname(__FILE__),
'public_cert.pem')
Gem.post_install_hooks.clear
Gem.post_uninstall_hooks.clear
Gem.pre_install_hooks.clear
Gem.pre_uninstall_hooks.clear
Gem.post_install do |installer|
@post_install_hook_arg = installer
end
Gem.post_uninstall do |uninstaller|
@post_uninstall_hook_arg = uninstaller
end
Gem.pre_install do |installer|
@pre_install_hook_arg = installer
end
Gem.pre_uninstall do |uninstaller|
@pre_uninstall_hook_arg = uninstaller
end
end
def teardown
Gem::ConfigMap[:BASERUBY] = @orig_BASERUBY
Gem::ConfigMap[:arch] = @orig_arch
if defined? Gem::RemoteFetcher then
Gem::RemoteFetcher.fetcher = nil
end
FileUtils.rm_rf @tempdir
ENV.delete 'GEMCACHE'
ENV.delete 'GEM_HOME'
ENV.delete 'GEM_PATH'
Gem.clear_paths
if @orig_ENV_HOME then
ENV['HOME'] = @orig_ENV_HOME
else
ENV.delete 'HOME'
end
end
def install_gem gem
require 'rubygems/installer'
use_ui MockGemUi.new do
Dir.chdir @tempdir do
Gem::Builder.new(gem).build
end
end
gem = File.join(@tempdir, "#{gem.full_name}.gem").untaint
Gem::Installer.new(gem, :wrappers => true).install
end
def mu_pp(obj)
s = ''
s = PP.pp obj, s
s = s.force_encoding(Encoding.default_external) if defined? Encoding
s.chomp
end
def prep_cache_files(lc)
@usr_si ||= Gem::SourceIndex.new
@usr_sice ||= Gem::SourceInfoCacheEntry.new @usr_si, 0
@sys_si ||= Gem::SourceIndex.new
@sys_sice ||= Gem::SourceInfoCacheEntry.new @sys_si, 0
latest_si = Gem::SourceIndex.new
latest_si.add_specs(*@sys_si.latest_specs)
latest_sys_sice = Gem::SourceInfoCacheEntry.new latest_si, 0
latest_si = Gem::SourceIndex.new
latest_si.add_specs(*@usr_si.latest_specs)
latest_usr_sice = Gem::SourceInfoCacheEntry.new latest_si, 0
[ [lc.system_cache_file, @sys_sice],
[lc.latest_system_cache_file, latest_sys_sice],
[lc.user_cache_file, @usr_sice],
[lc.latest_user_cache_file, latest_usr_sice],
].each do |filename, data|
FileUtils.mkdir_p File.dirname(filename).untaint
open filename.dup.untaint, 'wb' do |f|
f.write Marshal.dump({ @gem_repo => data })
end
end
end
def read_cache(path)
open path.dup.untaint, 'rb' do |io|
Marshal.load io.read
end
end
def read_binary(path)
Gem.read_binary path
end
def write_file(path)
path = File.join(@gemhome, path)
dir = File.dirname path
FileUtils.mkdir_p dir
open path, 'wb' do |io|
yield io
end
path
end
def quick_gem(gemname, version='2')
require 'rubygems/specification'
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = gemname
s.version = version
s.author = 'A User'
s.email = 'example@example.com'
s.homepage = 'http://example.com'
s.has_rdoc = true
s.summary = "this is a summary"
s.description = "This is a test description"
yield(s) if block_given?
end
path = File.join "specifications", "#{spec.full_name}.gemspec"
written_path = write_file path do |io|
io.write(spec.to_ruby)
end
spec.loaded_from = written_path
Gem.source_index.add_spec spec
return spec
end
def util_build_gem(spec)
dir = File.join(@gemhome, 'gems', spec.full_name)
FileUtils.mkdir_p dir
Dir.chdir dir do
spec.files.each do |file|
next if File.exist? file
FileUtils.mkdir_p File.dirname(file)
File.open file, 'w' do |fp| fp.puts "# #{file}" end
end
use_ui MockGemUi.new do
Gem::Builder.new(spec).build
end
FileUtils.mv "#{spec.full_name}.gem",
File.join(@gemhome, 'cache', "#{spec.original_name}.gem")
end
end
def util_clear_gems
FileUtils.rm_r File.join(@gemhome, 'gems')
FileUtils.rm_r File.join(@gemhome, 'specifications')
Gem.source_index.refresh!
end
def util_gem(name, version, &block)
spec = quick_gem(name, version, &block)
util_build_gem spec
cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
FileUtils.mv File.join(@gemhome, 'cache', "#{spec.original_name}.gem"),
cache_file
FileUtils.rm File.join(@gemhome, 'specifications',
"#{spec.full_name}.gemspec")
spec.loaded_from = nil
spec.loaded = false
[spec, cache_file]
end
def util_gzip(data)
out = StringIO.new
Zlib::GzipWriter.wrap out do |io|
io.write data
end
out.string
end
def util_make_gems(prerelease = false)
@a1 = quick_gem 'a', '1' do |s|
s.files = %w[lib/code.rb]
s.require_paths = %w[lib]
s.date = Gem::Specification::TODAY - 86400
s.homepage = 'http://a.example.com'
s.email = %w[example@example.com example2@example.com]
s.authors = %w[Example Example2]
s.description = <<-DESC
This line is really, really long. So long, in fact, that it is more than eighty characters long! The purpose of this line is for testing wrapping behavior because sometimes people don't wrap their text to eighty characters. Without the wrapping, the text might not look good in the RSS feed.
Also, a list:
* An entry that's actually kind of sort
* an entry that's really long, which will probably get wrapped funny. That's ok, somebody wasn't thinking straight when they made it more than eighty characters.
DESC
end
init = proc do |s|
s.files = %w[lib/code.rb]
s.require_paths = %w[lib]
end
@a2 = quick_gem('a', '2', &init)
@a3a = quick_gem('a', '3.a', &init)
@a_evil9 = quick_gem('a_evil', '9', &init)
@b2 = quick_gem('b', '2', &init)
@c1_2 = quick_gem('c', '1.2', &init)
@pl1 = quick_gem 'pl', '1' do |s| # l for legacy
s.files = %w[lib/code.rb]
s.require_paths = %w[lib]
s.platform = Gem::Platform.new 'i386-linux'
s.instance_variable_set :@original_platform, 'i386-linux'
end
if prerelease
@a2_pre = quick_gem('a', '2.a', &init)
write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb]) do
end
util_build_gem @a2_pre
end
write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) do end
write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) do end
write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) do end
write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) do end
write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) do end
write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) do end
[@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1].each do |spec|
util_build_gem spec
end
FileUtils.rm_r File.join(@gemhome, 'gems', @pl1.original_name)
Gem.source_index = nil
end
##
# Set the platform to +arch+
def util_set_arch(arch)
Gem::ConfigMap[:arch] = arch
platform = Gem::Platform.new arch
Gem.instance_variable_set :@platforms, nil
Gem::Platform.instance_variable_set :@local, nil
platform
end
def util_setup_fake_fetcher(prerelease = false)
require 'zlib'
require 'socket'
require 'rubygems/remote_fetcher'
@fetcher = Gem::FakeFetcher.new
util_make_gems(prerelease)
@all_gems = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2].sort
@all_gem_names = @all_gems.map { |gem| gem.full_name }
gem_names = [@a1.full_name, @a2.full_name, @a3a.full_name, @b2.full_name]
@gem_names = gem_names.sort.join("\n")
@source_index = Gem::SourceIndex.new
@source_index.add_spec @a1
@source_index.add_spec @a2
@source_index.add_spec @a3a
@source_index.add_spec @a_evil9
@source_index.add_spec @c1_2
@source_index.add_spec @a2_pre if prerelease
Gem::RemoteFetcher.fetcher = @fetcher
end
def util_setup_source_info_cache(*specs)
require 'rubygems/source_info_cache'
require 'rubygems/source_info_cache_entry'
specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten]
si = Gem::SourceIndex.new specs
sice = Gem::SourceInfoCacheEntry.new si, 0
sic = Gem::SourceInfoCache.new
sic.set_cache_data( { @gem_repo => sice } )
sic.update
sic.write_cache
sic.reset_cache_data
Gem::SourceInfoCache.instance_variable_set :@cache, sic
si
end
def util_setup_spec_fetcher(*specs)
specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten]
si = Gem::SourceIndex.new specs
spec_fetcher = Gem::SpecFetcher.fetcher
spec_fetcher.specs[@uri] = []
si.gems.sort_by { |_, spec| spec }.each do |_, spec|
spec_tuple = [spec.name, spec.version, spec.original_platform]
spec_fetcher.specs[@uri] << spec_tuple
end
spec_fetcher.latest_specs[@uri] = []
si.latest_specs.sort.each do |spec|
spec_tuple = [spec.name, spec.version, spec.original_platform]
spec_fetcher.latest_specs[@uri] << spec_tuple
end
spec_fetcher.prerelease_specs[@uri] = []
si.prerelease_specs.sort.each do |spec|
spec_tuple = [spec.name, spec.version, spec.original_platform]
spec_fetcher.prerelease_specs[@uri] << spec_tuple
end
(si.gems.merge si.prerelease_gems).sort_by { |_,spec| spec }.each do |_, spec|
path = "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{spec.original_name}.gemspec.rz"
data = Marshal.dump spec
data_deflate = Zlib::Deflate.deflate data
@fetcher.data[path] = data_deflate
end
si
end
def util_zip(data)
Zlib::Deflate.deflate data
end
def self.win_platform?
Gem.win_platform?
end
def win_platform?
Gem.win_platform?
end
# Returns whether or not we're on a version of Ruby built with VC++ (or
# Borland) versus Cygwin, Mingw, etc.
#
def self.vc_windows?
RUBY_PLATFORM.match('mswin')
end
# Returns whether or not we're on a version of Ruby built with VC++ (or
# Borland) versus Cygwin, Mingw, etc.
#
def vc_windows?
RUBY_PLATFORM.match('mswin')
end
# Returns the make command for the current platform. For versions of Ruby
# built on MS Windows with VC++ or Borland it will return 'nmake'. On all
# other platforms, including Cygwin, it will return 'make'.
#
def self.make_command
vc_windows? ? 'nmake' : 'make'
end
# Returns the make command for the current platform. For versions of Ruby
# built on MS Windows with VC++ or Borland it will return 'nmake'. On all
# other platforms, including Cygwin, it will return 'make'.
#
def make_command
vc_windows? ? 'nmake' : 'make'
end
# Returns whether or not the nmake command could be found.
#
def nmake_found?
system('nmake /? 1>NUL 2>&1')
end
# NOTE Allow tests to use a random (but controlled) port number instead of
# a hardcoded one. This helps CI tools when running parallels builds on
# the same builder slave.
def self.process_based_port
@@process_based_port ||= 8000 + $$ % 1000
end
def process_based_port
self.class.process_based_port
end
def build_rake_in
gem_ruby = Gem.ruby
ruby = @@ruby
Gem.module_eval {@ruby = ruby}
env_rake = ENV["rake"]
ENV["rake"] = @@rake
yield @@rake
ensure
Gem.module_eval {@ruby = gem_ruby}
if env_rake
ENV["rake"] = env_rake
else
ENV.delete("rake")
end
end
def self.rubybin
if ruby = ENV["RUBY"]
return ruby
end
ruby = "ruby"
rubyexe = ruby+".exe"
3.times do
if File.exist? ruby and File.executable? ruby and !File.directory? ruby
return File.expand_path(ruby)
end
if File.exist? rubyexe and File.executable? rubyexe
return File.expand_path(rubyexe)
end
ruby = File.join("..", ruby)
end
begin
require "rbconfig"
File.join(
RbConfig::CONFIG["bindir"],
RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]
)
rescue LoadError
"ruby"
end
end
@@ruby = rubybin
env_rake = ENV['rake']
ruby19_rake = File.expand_path("../../../bin/rake", __FILE__)
@@rake = if env_rake then
ENV["rake"]
elsif File.exist? ruby19_rake then
@@ruby + " " + ruby19_rake
else
'rake'
end
end
MiniTest::Unit.autorun