ruby/test/rubygems/test_gem_dependency_installer.rb
David Rodríguez 0a62e82ac4
[rubygems/rubygems] Fix gem install sometimes compiling the wrong source files
If a previous copy of a gem is already installed, RubyGems will not
reinstall the gem but only recompile its extensions. This seems like a
good idea, but only if the gem is being installed from the registry.

If we are installing a locally built package, then the package should be
completely reinstalled and extensions compiled from the sources in the
locally built package, not from the sources in the previous
installation.

1c282d98d5
2025-06-17 15:09:34 +09:00

1279 lines
30 KiB
Ruby

# frozen_string_literal: true
require_relative "helper"
require "rubygems/dependency_installer"
require "rubygems/security"
class TestGemDependencyInstaller < Gem::TestCase
def setup
super
common_installer_setup
@gems_dir = File.join @tempdir, "gems"
@cache_dir = File.join @gemhome, "cache"
FileUtils.mkdir @gems_dir
Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new
@original_platforms = Gem.platforms
Gem.platforms = []
end
def teardown
Gem.platforms = @original_platforms
super
end
def util_setup_gems
@a1, @a1_gem = util_gem "a", "1" do |s|
s.executables << "a_bin"
end
@a1_pre, @a1_pre_gem = util_gem "a", "1.a"
@b1, @b1_gem = util_gem "b", "1" do |s|
s.add_dependency "a"
s.add_development_dependency "aa"
end
@c1, @c1_gem = util_gem "c", "1" do |s|
s.add_development_dependency "b"
end
@d1, @d1_gem = util_gem "d", "1" do |s|
s.add_development_dependency "c"
end
util_setup_spec_fetcher(@a1, @a1_pre, @b1, @d1)
end
def test_install
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "a"
end
assert_equal %w[a-1], Gem::Specification.map(&:full_name)
assert_equal [@a1], inst.installed_gems
end
def test_install_prerelease
util_setup_gems
p1a, gem = util_gem "a", "10.a"
util_setup_spec_fetcher(p1a, @a1, @a1_pre)
p1a_data = Gem.read_binary(gem)
@fetcher.data["http://gems.example.com/gems/a-10.a.gem"] = p1a_data
dep = Gem::Dependency.new "a"
inst = Gem::DependencyInstaller.new prerelease: true
inst.install dep
assert_equal %w[a-10.a], Gem::Specification.map(&:full_name)
assert_equal [p1a], inst.installed_gems
end
def test_install_prerelease_bug_990
spec_fetcher do |fetcher|
fetcher.gem "a", "1.b" do |s|
s.add_dependency "b", "~> 1.a"
end
fetcher.gem "b", "1.b" do |s|
s.add_dependency "c", ">= 1"
end
fetcher.gem "c", "1.1.b"
end
dep = Gem::Dependency.new "a"
inst = Gem::DependencyInstaller.new prerelease: true
inst.install dep
assert_equal %w[a-1.b b-1.b c-1.1.b], Gem::Specification.map(&:full_name)
end
def test_install_when_only_prerelease
p1a, gem = util_gem "p", "1.a"
util_setup_spec_fetcher(p1a)
p1a_data = Gem.read_binary(gem)
@fetcher.data["http://gems.example.com/gems/p-1.a.gem"] = p1a_data
dep = Gem::Dependency.new "p"
inst = Gem::DependencyInstaller.new
assert_raise Gem::UnsatisfiableDependencyError do
inst.install dep
end
assert_equal %w[], Gem::Specification.map(&:full_name)
assert_equal [], inst.installed_gems
end
def test_install_prerelease_skipped_when_normal_ver
util_setup_gems
util_setup_spec_fetcher(@a1, @a1_pre)
p1a_data = Gem.read_binary(@a1_gem)
@fetcher.data["http://gems.example.com/gems/a-1.gem"] = p1a_data
dep = Gem::Dependency.new "a"
inst = Gem::DependencyInstaller.new prerelease: true
inst.install dep
assert_equal %w[a-1], Gem::Specification.map(&:full_name)
assert_equal [@a1], inst.installed_gems
end
def test_install_all_dependencies
util_setup_gems
_, e1_gem = util_gem "e", "1" do |s|
s.add_dependency "b"
end
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
FileUtils.mv e1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new ignore_dependencies: true
inst.install "b"
end
assert_equal %w[b-1], inst.installed_gems.map(&:full_name),
"sanity check"
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "e"
end
assert_equal %w[a-1 e-1], inst.installed_gems.map(&:full_name)
end
def test_install_cache_dir
util_setup_gems
dir = "dir"
Dir.mkdir dir
FileUtils.mv @a1_gem, dir
FileUtils.mv @b1_gem, dir
inst = nil
Dir.chdir dir do
inst = Gem::DependencyInstaller.new cache_dir: @tempdir
inst.install "b"
end
assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
assert File.exist? File.join(@gemhome, "cache", @a1.file_name)
assert File.exist? File.join(@gemhome, "cache", @b1.file_name)
end
def test_install_dependencies_satisfied
util_setup_gems
a2, a2_gem = util_gem "a", "2"
FileUtils.rm_rf File.join(@gemhome, "gems")
Gem::Specification.reset
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv a2_gem, @tempdir # not in index
FileUtils.mv @b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "a", req("= 2")
end
assert_equal %w[a-2], inst.installed_gems.map(&:full_name),
"sanity check"
FileUtils.rm File.join(@tempdir, a2.file_name)
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "b"
end
assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name)
assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
# This asserts that if a gem's dependency is satisfied by an
# already installed gem, RubyGems doesn't installed a newer
# version
def test_install_doesnt_upgrade_installed_dependencies
util_setup_gems
a2, a2_gem = util_gem "a", "2"
a3, a3_gem = util_gem "a", "3"
util_setup_spec_fetcher @a1, a3, @b1
FileUtils.rm_rf File.join(@gemhome, "gems")
Gem::Specification.reset
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv a2_gem, @tempdir # not in index
FileUtils.mv @b1_gem, @tempdir
FileUtils.mv a3_gem, @tempdir
Dir.chdir @tempdir do
Gem::DependencyInstaller.new.install "a", req("= 2")
end
FileUtils.rm File.join(@tempdir, a2.file_name)
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "b"
end
assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name)
assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency
util_setup_gems
done_installing_ran = false
inst = nil
Gem.done_installing do |installer, specs|
done_installing_ran = true
refute_nil installer
assert_equal [@a1, @b1], specs
end
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new(build_docs_in_background: false)
inst.install "b"
end
assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
assert done_installing_ran, "post installs hook was not run"
end
def test_install_dependency_development
util_setup_gems
@aa1, @aa1_gem = util_gem "aa", "1"
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new(development: true)
inst.install "b"
end
assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency_development_deep
util_setup_gems
@aa1, @aa1_gem = util_gem "aa", "1"
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
FileUtils.mv @c1_gem, @tempdir
FileUtils.mv @d1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new(development: true)
inst.install "d"
end
assert_equal %w[a-1 aa-1 b-1 c-1 d-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency_development_shallow
util_setup_gems
@aa1, @aa1_gem = util_gem "aa", "1"
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
FileUtils.mv @c1_gem, @tempdir
FileUtils.mv @d1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new(development: true, dev_shallow: true)
inst.install "d"
end
assert_equal %w[c-1 d-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency_existing
util_setup_gems
Gem::Installer.at(@a1_gem).install
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "b"
end
assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency_existing_extension
extconf_rb = File.join @gemhome, "gems", "e-1", "extconf.rb"
FileUtils.mkdir_p File.dirname extconf_rb
File.open extconf_rb, "w" do |io|
io.write <<-EXTCONF_RB
require 'mkmf'
create_makefile 'e'
EXTCONF_RB
end
e1 = util_spec "e", "1", nil, "extconf.rb" do |s|
s.extensions << "extconf.rb"
end
e1_gem = e1.cache_file
_, f1_gem = util_gem "f", "1", "e" => nil
Gem::Installer.at(e1_gem).install
FileUtils.rm_r e1.extension_dir
FileUtils.mv e1_gem, @tempdir
FileUtils.mv f1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "f"
end
assert_equal %w[f-1], inst.installed_gems.map(&:full_name)
assert_path_exist e1.extension_dir
end
def test_install_dependency_old
_, e1_gem = util_gem "e", "1"
_, f1_gem = util_gem "f", "1", "e" => nil
_, f2_gem = util_gem "f", "2"
FileUtils.mv e1_gem, @tempdir
FileUtils.mv f1_gem, @tempdir
FileUtils.mv f2_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "f"
end
assert_equal %w[f-2], inst.installed_gems.map(&:full_name)
end
def test_install_local
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new domain: :local
inst.install "a-1.gem"
end
assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_local_prerelease
util_setup_gems
FileUtils.mv @a1_pre_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new domain: :local
inst.install "a-1.a.gem"
end
assert_equal %w[a-1.a], inst.installed_gems.map(&:full_name)
end
def test_install_local_dependency
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new domain: :local
inst.install "b-1.gem"
end
assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
end
def test_install_local_dependency_installed
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
Gem::Installer.at("a-1.gem").install
inst = Gem::DependencyInstaller.new domain: :local
inst.install "b-1.gem"
end
assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_local_dependency_no_network_for_target_gem
a1, a1_gem = util_gem "a", "1"
_, b1_gem = util_gem "b", "1" do |s|
s.add_dependency "a"
end
util_setup_spec_fetcher(a1)
a1_data = Gem.read_binary(a1_gem)
@fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data
# compact index is available
compact_index_response = Gem::Net::HTTPResponse.new "1.1", 200, "OK"
compact_index_response.uri = Gem::URI("http://gems.example.com")
@fetcher.data["http://gems.example.com/"] = compact_index_response
# but private local gem not present there
@fetcher.data["http://gems.example.com/info/b"] =
proc do
raise "should not happen"
end
FileUtils.mv b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "b-1.gem"
end
assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
end
def test_install_local_subdir
util_setup_gems
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new domain: :local
inst.install "gems/a-1.gem"
end
assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_local_with_extensions_already_installed
pend "needs investigation" if Gem.java_platform?
pend "ruby.h is not provided by ruby repo" if ruby_repo?
@spec = quick_gem "a" do |s|
s.extensions << "extconf.rb"
s.files += %w[extconf.rb a.c]
end
write_dummy_extconf "a"
c_source_path = File.join(@tempdir, "a.c")
write_file c_source_path do |io|
io.write <<-C
#include <ruby.h>
void Init_a() { }
C
end
package_path = Gem::Package.build @spec
installer = Gem::Installer.at(package_path)
# Make sure the gem is installed and backup the correct package
installer.install
package_bkp_path = "#{package_path}.bkp"
FileUtils.cp package_path, package_bkp_path
# Break the extension, rebuild it, and try to install it
write_file c_source_path do |io|
io.write "typo"
end
Gem::Package.build @spec
assert_raise Gem::Ext::BuildError do
installer.install
end
# Make sure installing the good package again still works
FileUtils.cp "#{package_path}.bkp", package_path
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new domain: :local
inst.install package_path
end
end
def test_install_minimal_deps
util_setup_gems
_, e1_gem = util_gem "e", "1" do |s|
s.add_dependency "b"
end
_, b2_gem = util_gem "b", "2" do |s|
s.add_dependency "a"
end
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
FileUtils.mv b2_gem, @tempdir
FileUtils.mv e1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new ignore_dependencies: true
inst.install "b", req("= 1")
end
assert_equal %w[b-1], inst.installed_gems.map(&:full_name),
"sanity check"
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new minimal_deps: true
inst.install "e"
end
assert_equal %w[a-1 e-1], inst.installed_gems.map(&:full_name)
end
def test_install_no_minimal_deps
util_setup_gems
_, e1_gem = util_gem "e", "1" do |s|
s.add_dependency "b"
end
_, b2_gem = util_gem "b", "2" do |s|
s.add_dependency "a"
end
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
FileUtils.mv b2_gem, @tempdir
FileUtils.mv e1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new ignore_dependencies: true
inst.install "b", req("= 1")
end
assert_equal %w[b-1], inst.installed_gems.map(&:full_name),
"sanity check"
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new minimal_deps: false
inst.install "e"
end
assert_equal %w[a-1 b-2 e-1], inst.installed_gems.map(&:full_name)
end
def test_install_no_document
util_setup_gems
done_installing_called = false
Gem.done_installing do |dep_installer, _specs|
done_installing_called = true
assert_empty dep_installer.document
end
inst = Gem::DependencyInstaller.new domain: :local, document: []
inst.install @a1_gem
assert done_installing_called
end
def test_install_env_shebang
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new env_shebang: true, wrappers: true, format_executable: false
inst.install "a"
end
env = "/\\S+/env" unless Gem.win_platform?
assert_match(/\A#!#{env} #{RbConfig::CONFIG["ruby_install_name"]}\n/,
File.read(File.join(@gemhome, "bin", "a_bin")))
end
def test_install_force
util_setup_gems
FileUtils.mv @b1_gem, @tempdir
si = util_setup_spec_fetcher @b1
@fetcher.data["http://gems.example.com/gems/yaml"] = si.to_yaml
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new force: true
inst.install "b"
end
assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_build_args
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
inst = nil
build_args = %w[--a --b="c"]
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new(build_args: build_args)
inst.install "a"
end
assert_equal build_args.join("\n"), File.read(inst.installed_gems.first.build_info_file).strip
end
def test_install_ignore_dependencies
util_setup_gems
FileUtils.mv @b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new ignore_dependencies: true
inst.install "b"
end
assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_install_dir
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = Gem::Installer.at @a1.file_name
inst.install
gemhome2 = File.join @tempdir, "gemhome2"
Dir.mkdir gemhome2
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new install_dir: gemhome2
inst.install "b"
end
assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
assert File.exist?(File.join(gemhome2, "specifications", @a1.spec_name))
assert File.exist?(File.join(gemhome2, "cache", @a1.file_name))
end
def test_install_domain_both
util_setup_gems
a1_data = nil
File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
@fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data
FileUtils.mv @b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new domain: :both
inst.install "b"
end
assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
a1, b1 = inst.installed_gems
assert_equal a1.spec_file, a1.loaded_from
assert_equal b1.spec_file, b1.loaded_from
end
def test_install_domain_both_no_network
util_setup_gems
@fetcher.data["http://gems.example.com/gems/Marshal.#{@marshal_version}"] =
proc do
raise Gem::RemoteFetcher::FetchError
end
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new domain: :both
inst.install "b"
end
assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
end
def test_install_domain_local
util_setup_gems
FileUtils.mv @b1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
e = assert_raise Gem::UnsatisfiableDependencyError do
inst = Gem::DependencyInstaller.new domain: :local
inst.install "b"
end
expected = "Unable to resolve dependency: 'b (>= 0)' requires 'a (>= 0)'"
assert_equal expected, e.message
end
assert_equal [], inst.installed_gems.map(&:full_name)
end
def test_install_domain_remote
util_setup_gems
a1_data = nil
File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
@fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data
inst = Gem::DependencyInstaller.new domain: :remote
inst.install "a"
assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_dual_repository
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = nil
gemhome2 = "#{@gemhome}2"
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new install_dir: gemhome2
inst.install "a"
end
assert_equal %w[a-1], inst.installed_gems.map(&:full_name),
"sanity check"
ENV["GEM_HOME"] = @gemhome
ENV["GEM_PATH"] = [@gemhome, gemhome2].join File::PATH_SEPARATOR
Gem.clear_paths
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "b"
end
assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_reinstall
util_setup_gems
Gem::Installer.at(@a1_gem).install
FileUtils.mv @a1_gem, @tempdir
inst = nil
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new force: true
inst.install "a"
end
assert_equal %w[a-1], Gem::Specification.map(&:full_name)
assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_dual_repository_and_done_installing_hooks
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = nil
# Make sure gem is installed to standard GEM_HOME
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new install_dir: @gemhome
inst.install "b"
end
# and also to an additional GEM_PATH
gemhome2 = "#{@gemhome}2"
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new install_dir: gemhome2
inst.install "b"
end
# Now install the local gem with the additional GEM_PATH
ENV["GEM_HOME"] = @gemhome
ENV["GEM_PATH"] = [@gemhome, gemhome2].join File::PATH_SEPARATOR
Gem.clear_paths
Gem.done_installing do |installer, specs|
refute_nil installer
assert_equal [@b1], specs
end
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
inst.install "b-1.gem"
end
assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_remote
util_setup_gems
a1_data = nil
File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
@fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data
inst = Gem::DependencyInstaller.new
Dir.chdir @tempdir do
inst.install "a"
end
assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_remote_dep
util_setup_gems
a1_data = nil
File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
@fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data
inst = Gem::DependencyInstaller.new
Dir.chdir @tempdir do
dep = Gem::Dependency.new @a1.name, @a1.version
inst.install dep
end
assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_remote_platform_newer
util_setup_gems
a2_o, a2_o_gem = util_gem "a", "2" do |s|
s.platform = Gem::Platform.new %w[cpu other_platform 1]
end
si = util_setup_spec_fetcher @a1, a2_o
@fetcher.data["http://gems.example.com/gems/yaml"] = si.to_yaml
a1_data = nil
a2_o_data = nil
File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
File.open a2_o_gem, "rb" do |fp|
a2_o_data = fp.read
end
@fetcher.data["http://gems.example.com/gems/#{@a1.file_name}"] =
a1_data
@fetcher.data["http://gems.example.com/gems/#{a2_o.file_name}"] =
a2_o_data
inst = Gem::DependencyInstaller.new domain: :remote
inst.install "a"
assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_platform_is_ignored_when_a_file_is_specified
_, a_gem = util_gem "a", "1" do |s|
s.platform = Gem::Platform.new %w[cpu other_platform 1]
end
inst = Gem::DependencyInstaller.new domain: :local
inst.install a_gem
assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map(&:full_name)
end
require "rubygems/openssl"
if Gem::HAVE_OPENSSL
def test_install_security_policy
util_setup_gems
data = File.open(@a1_gem, "rb", &:read)
@fetcher.data["http://gems.example.com/gems/a-1.gem"] = data
data = File.open(@b1_gem, "rb", &:read)
@fetcher.data["http://gems.example.com/gems/b-1.gem"] = data
policy = Gem::Security::HighSecurity
inst = Gem::DependencyInstaller.new security_policy: policy
e = assert_raise Gem::Security::Exception do
inst.install "b"
end
assert_equal "unsigned gems are not allowed by the High Security policy",
e.message
assert_equal %w[], inst.installed_gems.map(&:full_name)
end
end
# Wrappers don't work on mswin
unless Gem.win_platform?
def test_install_no_wrappers
util_setup_gems
@fetcher.data["http://gems.example.com/gems/a-1.gem"] = read_binary(@a1_gem)
inst = Gem::DependencyInstaller.new wrappers: false, format_executable: false
inst.install "a"
refute_match(/This file was generated by RubyGems./,
File.read(File.join(@gemhome, "bin", "a_bin")))
end
end
def test_install_version
util_setup_d
data = File.open(@d2_gem, "rb", &:read)
@fetcher.data["http://gems.example.com/gems/d-2.gem"] = data
data = File.open(@d1_gem, "rb", &:read)
@fetcher.data["http://gems.example.com/gems/d-1.gem"] = data
inst = Gem::DependencyInstaller.new
inst.install "d", "= 1"
assert_equal %w[d-1], inst.installed_gems.map(&:full_name)
end
def test_install_version_default
util_setup_d
data = File.open(@d2_gem, "rb", &:read)
@fetcher.data["http://gems.example.com/gems/d-2.gem"] = data
data = File.open(@d1_gem, "rb", &:read)
@fetcher.data["http://gems.example.com/gems/d-1.gem"] = data
inst = Gem::DependencyInstaller.new
inst.install "d"
assert_equal %w[d-2], inst.installed_gems.map(&:full_name)
end
def test_install_legacy_spec_with_nil_required_ruby_version
path = File.expand_path "data/null-required-ruby-version.gemspec.rz", __dir__
spec = Marshal.load Gem.read_binary(path)
def spec.validate(*args); end
util_build_gem spec
cache_file = File.join @tempdir, "gems", "#{spec.original_name}.gem"
FileUtils.mkdir_p File.dirname cache_file
FileUtils.mv spec.cache_file, cache_file
util_setup_spec_fetcher spec
data = Gem.read_binary(cache_file)
@fetcher.data["http://gems.example.com/gems/activesupport-1.0.0.gem"] = data
dep = Gem::Dependency.new "activesupport"
inst = Gem::DependencyInstaller.new
inst.install dep
assert_equal %w[activesupport-1.0.0], Gem::Specification.map(&:full_name)
end
def test_install_legacy_spec_with_nil_required_rubygems_version
path = File.expand_path "data/null-required-rubygems-version.gemspec.rz", __dir__
spec = Marshal.load Gem.read_binary(path)
def spec.validate(*args); end
util_build_gem spec
cache_file = File.join @tempdir, "gems", "#{spec.original_name}.gem"
FileUtils.mkdir_p File.dirname cache_file
FileUtils.mv spec.cache_file, cache_file
util_setup_spec_fetcher spec
data = Gem.read_binary(cache_file)
@fetcher.data["http://gems.example.com/gems/activesupport-1.0.0.gem"] = data
dep = Gem::Dependency.new "activesupport"
inst = Gem::DependencyInstaller.new
inst.install dep
assert_equal %w[activesupport-1.0.0], Gem::Specification.map(&:full_name)
end
def test_find_gems_gems_with_sources
util_setup_gems
inst = Gem::DependencyInstaller.new
dep = Gem::Dependency.new "b", ">= 0"
Gem::Specification.reset
set = Gem::Deprecate.skip_during do
inst.find_gems_with_sources(dep)
end
assert_kind_of Gem::AvailableSet, set
s = set.set.first
assert_equal @b1, s.spec
assert_equal Gem::Source.new(@gem_repo), s.source
end
def test_find_gems_with_sources_local
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
inst = Gem::DependencyInstaller.new
dep = Gem::Dependency.new "a", ">= 0"
set = nil
Dir.chdir @tempdir do
set = Gem::Deprecate.skip_during do
inst.find_gems_with_sources dep
end
end
gems = set.sorted
assert_equal 2, gems.length
remote, local = gems
assert_equal "a-1", local.spec.full_name, "local spec"
assert_equal File.join(@tempdir, @a1.file_name),
local.source.download(local.spec), "local path"
assert_equal "a-1", remote.spec.full_name, "remote spec"
assert_equal Gem::Source.new(@gem_repo), remote.source, "remote path"
end
def test_find_gems_with_sources_prerelease
util_setup_gems
installer = Gem::DependencyInstaller.new
dependency = Gem::Dependency.new("a", Gem::Requirement.default)
set = Gem::Deprecate.skip_during do
installer.find_gems_with_sources(dependency)
end
releases = set.all_specs
assert releases.any? {|s| s.name == "a" && s.version.to_s == "1" }
refute releases.any? {|s| s.name == "a" && s.version.to_s == "1.a" }
dependency.prerelease = true
set = Gem::Deprecate.skip_during do
installer.find_gems_with_sources(dependency)
end
prereleases = set.all_specs
assert_equal [@a1_pre, @a1], prereleases
end
def test_find_gems_with_sources_with_best_only_and_platform
util_setup_gems
a1_x86_mingw32, = util_gem "a", "1" do |s|
s.platform = "x86-mingw32"
end
util_setup_spec_fetcher @a1, a1_x86_mingw32
Gem.platforms << Gem::Platform.new("x86-mingw32")
installer = Gem::DependencyInstaller.new
dependency = Gem::Dependency.new("a", Gem::Requirement.default)
set = Gem::Deprecate.skip_during do
installer.find_gems_with_sources(dependency, true)
end
releases = set.all_specs
assert_equal [a1_x86_mingw32], releases
end
def test_find_gems_with_sources_with_bad_source
Gem.sources.replace ["http://not-there.nothing"]
installer = Gem::DependencyInstaller.new
dep = Gem::Dependency.new("a")
out = Gem::Deprecate.skip_during do
installer.find_gems_with_sources(dep)
end
assert out.empty?
assert_kind_of Gem::SourceFetchProblem, installer.errors.first
end
def test_resolve_dependencies
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = Gem::DependencyInstaller.new
request_set = inst.resolve_dependencies "b", req(">= 0")
requests = request_set.sorted_requests.map(&:full_name)
assert_equal %w[a-1 b-1], requests
end
def test_resolve_dependencies_ignore_dependencies
util_setup_gems
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
inst = Gem::DependencyInstaller.new ignore_dependencies: true
request_set = inst.resolve_dependencies "b", req(">= 0")
requests = request_set.sorted_requests.map(&:full_name)
assert request_set.ignore_dependencies
assert_equal %w[b-1], requests
end
def test_resolve_dependencies_local
util_setup_gems
@a2, @a2_gem = util_gem "a", "2"
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @a2_gem, @tempdir
inst = Gem::DependencyInstaller.new
request_set = inst.resolve_dependencies "a-1.gem", req(">= 0")
requests = request_set.sorted_requests.map(&:full_name)
assert_equal %w[a-1], requests
end
def util_setup_d
@d1, @d1_gem = util_gem "d", "1"
@d2, @d2_gem = util_gem "d", "2"
util_setup_spec_fetcher(@d1, @d2)
end
end