1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/spec/bundler/install/gems/standalone_spec.rb
David Rodríguez a782d76fbe [rubygems/rubygems] Fix pending Bundler specs
When testing under the ruby/ruby setup, mkmf.rb needs to the `$extout`
global variable set properly.

This is because, in this particular case, the `ruby.h` header needed to
compile extensions is constructed from
`$(extout)/include($arch)/ruby/config.h` but `$extout` is not set by
default.

I tried to fix this in mkmf.rb itself but I couldn't figure it. But
setting it externally to workaround the issue fixes the specs, so I'll
start with that. Also setting it externally causes issues when running
specs upstream against Ruby 2.3 (I guess because of some difference with
Ruby 2.3 mkmf.rb implementation). So I'm avoiding doing it on Ruby 2.3 to
woraround that.

https://github.com/rubygems/rubygems/commit/d782984585
2022-06-26 11:16:11 +09:00

463 lines
14 KiB
Ruby

# frozen_string_literal: true
RSpec.shared_examples "bundle install --standalone" do
shared_examples "common functionality" do
it "still makes the gems available to normal bundler" do
args = expected_gems.map {|k, v| "#{k} #{v}" }
expect(the_bundle).to include_gems(*args)
end
it "still makes system gems unavailable to normal bundler" do
system_gems "rack-1.0.0"
expect(the_bundle).to_not include_gems("rack")
end
it "generates a bundle/bundler/setup.rb" do
expect(bundled_app("bundle/bundler/setup.rb")).to exist
end
it "makes the gems available without bundler" do
testrb = String.new <<-RUBY
$:.unshift File.expand_path("bundle")
require "bundler/setup"
RUBY
expected_gems.each do |k, _|
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
ruby testrb
expect(out).to eq(expected_gems.values.join("\n"))
end
it "makes the gems available without bundler nor rubygems" do
testrb = String.new <<-RUBY
$:.unshift File.expand_path("bundle")
require "bundler/setup"
RUBY
expected_gems.each do |k, _|
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
sys_exec %(#{Gem.ruby} --disable-gems -w -e #{testrb.shellescape})
expect(out).to eq(expected_gems.values.join("\n"))
end
it "makes the gems available without bundler via Kernel.require" do
testrb = String.new <<-RUBY
$:.unshift File.expand_path("bundle")
require "bundler/setup"
RUBY
expected_gems.each do |k, _|
testrb << "\nKernel.require \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
ruby testrb
expect(out).to eq(expected_gems.values.join("\n"))
end
it "makes system gems unavailable without bundler" do
system_gems "rack-1.0.0"
testrb = String.new <<-RUBY
$:.unshift File.expand_path("bundle")
require "bundler/setup"
begin
require "rack"
rescue LoadError
puts "LoadError"
end
RUBY
ruby testrb
expect(out).to eq("LoadError")
end
it "works on a different system" do
begin
FileUtils.mv(bundled_app, "#{bundled_app}2")
rescue Errno::ENOTEMPTY
puts "Couldn't rename test app since the target folder has these files: #{Dir.glob("#{bundled_app}2/*")}"
raise
end
testrb = String.new <<-RUBY
$:.unshift File.expand_path("bundle")
require "bundler/setup"
RUBY
expected_gems.each do |k, _|
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
ruby testrb, :dir => "#{bundled_app}2"
expect(out).to eq(expected_gems.values.join("\n"))
end
end
describe "with simple gems" do
before do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
G
bundle "config set --local path #{bundled_app("bundle")}"
bundle :install, :standalone => true, :dir => cwd
end
let(:expected_gems) do
{
"actionpack" => "2.3.2",
"rails" => "2.3.2",
}
end
include_examples "common functionality"
end
describe "with default gems and a lockfile", :ruby_repo do
before do
skip "does not work on rubygems versions where `--install_dir` doesn't respect --default" unless Gem::Installer.for_spec(loaded_gemspec, :install_dir => "/foo").default_spec_file == "/foo/specifications/default/bundler-#{Bundler::VERSION}.gemspec" # Since rubygems 3.2.0.rc.2
skip "does not work on old rubies because the realworld gems that need to be installed don't support them" if RUBY_VERSION < "2.7.0"
if Gem.win_platform? && RUBY_VERSION < "3.1.0"
default_fiddle_version = ruby "require 'fiddle'; puts Gem.loaded_specs['fiddle'].version"
realworld_system_gems "fiddle --version #{default_fiddle_version}"
end
realworld_system_gems "tsort --version 0.1.0"
necessary_system_gems = ["optparse --version 0.1.1", "psych --version 3.3.2", "logger --version 1.4.3", "etc --version 1.2.0", "stringio --version 3.0.1"]
necessary_system_gems += ["shellwords --version 0.1.0", "base64 --version 0.1.0", "resolv --version 0.2.1"] if Gem.rubygems_version < Gem::Version.new("3.3.a")
necessary_system_gems += ["yaml --version 0.1.1"] if Gem.rubygems_version < Gem::Version.new("3.4.a")
realworld_system_gems(*necessary_system_gems, :path => scoped_gem_path(bundled_app("bundle")))
build_gem "foo", "1.0.0", :to_system => true, :default => true do |s|
s.add_dependency "bar"
end
build_gem "bar", "1.0.0", :to_system => true, :default => true
build_repo4 do
build_gem "foo", "1.0.0" do |s|
s.add_dependency "bar"
end
build_gem "bar", "1.0.0"
end
gemfile <<-G
source "https://gem.repo4"
gem "foo"
G
bundle "lock", :dir => cwd, :artifice => "compact_index"
end
it "works and points to the vendored copies, not to the default copies" do
bundle "config set --local path #{bundled_app("bundle")}"
bundle :install, :standalone => true, :dir => cwd, :artifice => "compact_index", :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") }
expect(load_path_lines).to eq [
'$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/bar-1.0.0/lib")',
'$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/foo-1.0.0/lib")',
]
end
end
describe "with Gemfiles using path sources and resulting bundle moved to a folder hierarchy with different nesting" do
before do
build_lib "minitest", "1.0.0", :path => lib_path("minitest")
Dir.mkdir bundled_app("app")
gemfile bundled_app("app/Gemfile"), <<-G
source "#{file_uri_for(gem_repo1)}"
gem "minitest", :path => "#{lib_path("minitest")}"
G
bundle "install", :standalone => true, :dir => bundled_app("app")
Dir.mkdir tmp("one_more_level")
FileUtils.mv bundled_app, tmp("one_more_level")
end
it "also works" do
ruby <<-RUBY, :dir => tmp("one_more_level/bundled_app/app")
require "./bundle/bundler/setup"
require "minitest"
puts MINITEST
RUBY
expect(out).to eq("1.0.0")
expect(err).to be_empty
end
end
describe "with gems with native extension" do
before do
bundle "config set --local path #{bundled_app("bundle")}"
install_gemfile <<-G, :standalone => true, :dir => cwd
source "#{file_uri_for(gem_repo1)}"
gem "very_simple_binary"
G
end
it "generates a bundle/bundler/setup.rb with the proper paths" do
expected_path = bundled_app("bundle/bundler/setup.rb")
script_content = File.read(expected_path)
expect(script_content).to include("def self.ruby_api_version")
expect(script_content).to include("def self.extension_api_version")
extension_line = script_content.each_line.find {|line| line.include? "/extensions/" }.strip
platform = Gem::Platform.local
expect(extension_line).to start_with '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/extensions/'
expect(extension_line).to end_with platform.to_s + '/#{Gem.extension_api_version}/very_simple_binary-1.0")'
end
end
describe "with gem that has an invalid gemspec" do
before do
build_git "bar", :gemspec => false do |s|
s.write "lib/bar/version.rb", %(BAR_VERSION = '1.0')
s.write "bar.gemspec", <<-G
lib = File.expand_path('lib/', __dir__)
$:.unshift lib unless $:.include?(lib)
require 'bar/version'
Gem::Specification.new do |s|
s.name = 'bar'
s.version = BAR_VERSION
s.summary = 'Bar'
s.files = Dir["lib/**/*.rb"]
s.author = 'Anonymous'
s.require_path = [1,2]
end
G
end
bundle "config set --local path #{bundled_app("bundle")}"
install_gemfile <<-G, :standalone => true, :dir => cwd, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
end
it "outputs a helpful error message" do
expect(err).to include("You have one or more invalid gemspecs that need to be fixed.")
expect(err).to include("bar 1.0 has an invalid gemspec")
end
end
describe "with a combination of gems and git repos" do
before do
build_git "devise", "1.0"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
gem "devise", :git => "#{lib_path("devise-1.0")}"
G
bundle "config set --local path #{bundled_app("bundle")}"
bundle :install, :standalone => true, :dir => cwd
end
let(:expected_gems) do
{
"actionpack" => "2.3.2",
"devise" => "1.0",
"rails" => "2.3.2",
}
end
include_examples "common functionality"
end
describe "with groups" do
before do
build_git "devise", "1.0"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
group :test do
gem "rspec"
gem "rack-test"
end
G
bundle "config set --local path #{bundled_app("bundle")}"
bundle :install, :standalone => true, :dir => cwd
end
let(:expected_gems) do
{
"actionpack" => "2.3.2",
"rails" => "2.3.2",
}
end
include_examples "common functionality"
it "allows creating a standalone file with limited groups" do
bundle "config set --local path #{bundled_app("bundle")}"
bundle :install, :standalone => "default", :dir => cwd
load_error_ruby <<-RUBY, "spec"
$:.unshift File.expand_path("bundle")
require "bundler/setup"
require "actionpack"
puts ACTIONPACK
require "spec"
RUBY
expect(out).to eq("2.3.2")
expect(err).to eq("ZOMG LOAD ERROR")
end
it "allows `without` configuration to limit the groups used in a standalone" do
bundle "config set --local path #{bundled_app("bundle")}"
bundle "config set --local without test"
bundle :install, :standalone => true, :dir => cwd
load_error_ruby <<-RUBY, "spec"
$:.unshift File.expand_path("bundle")
require "bundler/setup"
require "actionpack"
puts ACTIONPACK
require "spec"
RUBY
expect(out).to eq("2.3.2")
expect(err).to eq("ZOMG LOAD ERROR")
end
it "allows `path` configuration to change the location of the standalone bundle" do
bundle "config set --local path path/to/bundle"
bundle "install", :standalone => true, :dir => cwd
ruby <<-RUBY
$:.unshift File.expand_path("path/to/bundle")
require "bundler/setup"
require "actionpack"
puts ACTIONPACK
RUBY
expect(out).to eq("2.3.2")
end
it "allows `without` to limit the groups used in a standalone" do
bundle "config set --local without test"
bundle :install, :dir => cwd
bundle "config set --local path #{bundled_app("bundle")}"
bundle :install, :standalone => true, :dir => cwd
load_error_ruby <<-RUBY, "spec"
$:.unshift File.expand_path("bundle")
require "bundler/setup"
require "actionpack"
puts ACTIONPACK
require "spec"
RUBY
expect(out).to eq("2.3.2")
expect(err).to eq("ZOMG LOAD ERROR")
end
end
describe "with gemcutter's dependency API" do
let(:source_uri) { "http://localgemserver.test" }
describe "simple gems" do
before do
gemfile <<-G
source "#{source_uri}"
gem "rails"
G
bundle "config set --local path #{bundled_app("bundle")}"
bundle :install, :standalone => true, :artifice => "endpoint", :dir => cwd
end
let(:expected_gems) do
{
"actionpack" => "2.3.2",
"rails" => "2.3.2",
}
end
include_examples "common functionality"
end
end
describe "with --binstubs", :bundler => "< 3" do
before do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
G
bundle "config set --local path #{bundled_app("bundle")}"
bundle :install, :standalone => true, :binstubs => true, :dir => cwd
end
let(:expected_gems) do
{
"actionpack" => "2.3.2",
"rails" => "2.3.2",
}
end
include_examples "common functionality"
it "creates stubs that use the standalone load path" do
expect(sys_exec("bin/rails -v").chomp).to eql "2.3.2"
end
it "creates stubs that can be executed from anywhere" do
require "tmpdir"
sys_exec(%(#{bundled_app("bin/rails")} -v), :dir => Dir.tmpdir)
expect(out).to eq("2.3.2")
end
it "creates stubs that can be symlinked" do
skip "symlinks unsupported" if Gem.win_platform?
symlink_dir = tmp("symlink")
FileUtils.mkdir_p(symlink_dir)
symlink = File.join(symlink_dir, "rails")
File.symlink(bundled_app("bin/rails"), symlink)
sys_exec("#{symlink} -v")
expect(out).to eq("2.3.2")
end
it "creates stubs with the correct load path" do
extension_line = File.read(bundled_app("bin/rails")).each_line.find {|line| line.include? "$:.unshift" }.strip
expect(extension_line).to eq %($:.unshift File.expand_path "../bundle", __dir__)
end
end
end
RSpec.describe "bundle install --standalone" do
let(:cwd) { bundled_app }
include_examples("bundle install --standalone")
end
RSpec.describe "bundle install --standalone run in a subdirectory" do
let(:cwd) { bundled_app("bob").tap(&:mkpath) }
include_examples("bundle install --standalone")
end