[rubygems/rubygems] Add specs for gem exec

https://github.com/rubygems/rubygems/commit/3078e5834e
This commit is contained in:
Samuel Giddins 2023-01-25 18:49:02 -08:00 коммит произвёл git
Родитель cbe14cc8e6
Коммит d81be0609b
2 изменённых файлов: 483 добавлений и 2 удалений

Просмотреть файл

@ -34,6 +34,7 @@ class Gem::Commands::ExecCommand < Gem::Command
"--version '#{Gem::Requirement.default}'"
end
# TODO(segiddins): add a proper description!
def description # :nodoc:
<<-EOF
EOF
@ -76,7 +77,22 @@ class Gem::Commands::ExecCommand < Gem::Command
options[:executable], gem_version = extract_gem_name_and_version(options[:args].shift)
options[:gem_name] ||= options[:executable]
options[:version] = gem_version if gem_version
if gem_version
if options[:version].none?
options[:version] = Gem::Requirement.new(gem_version)
else
options[:version].concat [gem_version]
end
end
if options[:prerelease] && !options[:version].prerelease?
if options[:version].none?
options[:version] = Gem::Requirement.default_prerelease
else
options[:version].concat [Gem::Requirement.default_prerelease]
end
end
end
def check_executable
@ -100,7 +116,7 @@ class Gem::Commands::ExecCommand < Gem::Command
def install_if_needed
activate!
rescue Gem::MissingSpecError
verbose "#{dependency_to_s} not available locally"
verbose "#{Gem::Dependency.new(options[:gem_name], options[:version])} not available locally, installing from remote"
install
activate!
end
@ -133,6 +149,8 @@ class Gem::Commands::ExecCommand < Gem::Command
def activate!
gem(options[:gem_name], options[:version])
Gem.finish_resolve
verbose "activated #{options[:gem_name]} (#{Gem.loaded_specs[options[:gem_name]].version})"
end
def load!

Просмотреть файл

@ -0,0 +1,463 @@
# frozen_string_literal: true
require_relative "helper"
require "rubygems/commands/exec_command"
class TestGemCommandsExecCommand < Gem::TestCase
def setup
super
common_installer_setup
@cmd = Gem::Commands::ExecCommand.new
@orig_args = Gem::Command.build_args
common_installer_setup
end
def teardown
super
common_installer_teardown
Gem::Command.build_args = @orig_args
end
def test_error_with_no_arguments
e = assert_raise Gem::CommandLineError do
@cmd.invoke
end
assert_equal "Please specify an executable to run (e.g. gem exec COMMAND)",
e.message
end
def test_error_with_no_executable
e = assert_raise Gem::CommandLineError do
@cmd.invoke "--verbose", "--gem", "GEM", "--version", "< 10", "--conservative"
end
assert_equal "Please specify an executable to run (e.g. gem exec COMMAND)",
e.message
end
def test_full_option_parsing
@cmd.when_invoked do |options|
assert_equal options, {
args: ["install", "--no-color", "--help", "--verbose"],
executable: "pod",
:explicit_prerelease => false,
gem_name: "cocoapods",
prerelease: false,
:version => Gem::Requirement.new(["> 1", "< 1.3"]),
build_args: nil,
}
end
@cmd.invoke "--gem", "cocoapods", "-v", "> 1", "--version", "< 1.3", "--verbose", "--", "pod", "install", "--no-color", "--help", "--verbose"
end
def test_single_arg_parsing
@cmd.when_invoked do |options|
assert_equal options, {
args: [],
executable: "rails",
gem_name: "rails",
:version => Gem::Requirement.new([">= 0"]),
build_args: nil,
}
end
@cmd.invoke "rails"
end
def test_single_arg_parsing_with_version
@cmd.when_invoked do |options|
assert_equal options, {
args: [],
executable: "rails",
gem_name: "rails",
:version => Gem::Requirement.new(["= 7.1"]),
build_args: nil,
}
end
@cmd.invoke "rails:7.1"
end
def test_gem_without_executable
spec_fetcher do |fetcher|
fetcher.gem "a", 2
end
util_clear_gems
use_ui @ui do
e = assert_raise Gem::MockGemUi::TermError, @ui.error do
@cmd.invoke "a:2"
end
assert_equal 1, e.exit_code
assert_equal "ERROR: Failed to load executable `a`, are you sure the gem `a` contains it?\n", @ui.error
end
end
def test_gem_with_executable
spec_fetcher do |fetcher|
fetcher.gem "a", 2 do |s|
s.executables = %w[a]
s.files = %w[bin/a lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
f << "Gem.ui.say #{s.original_name.dump}"
end
end
end
util_clear_gems
use_ui @ui do
@cmd.invoke "a:2"
assert_equal "a-2\n", @ui.output
end
end
def test_gem_with_other_executable_name
spec_fetcher do |fetcher|
fetcher.gem "a", 2 do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump}"
end
end
end
util_clear_gems
use_ui @ui do
@cmd.invoke "a:2"
assert_equal "a-2\n", @ui.output
end
end
def test_gem_with_executable_error
spec_fetcher do |fetcher|
fetcher.gem "a", 2 do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "raise #{s.original_name.dump}"
end
end
end
util_clear_gems
use_ui @ui do
e = assert_raise RuntimeError do
@cmd.invoke "a:2"
end
assert_equal "a-2", e.message
assert_empty @ui.error
end
end
def test_gem_with_multiple_executables_one_match
spec_fetcher do |fetcher|
fetcher.gem "a", 2 do |s|
s.executables = %w[foo a]
s.files = %w[bin/foo bin/a lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
util_clear_gems
use_ui @ui do
@cmd.invoke "a:2"
assert_equal "a-2 a\n", @ui.output
end
end
def test_gem_with_multiple_executables_no_match
spec_fetcher do |fetcher|
fetcher.gem "a", 2 do |s|
s.executables = %w[foo bar]
s.files = %w[bin/foo bin/bar lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
write_file File.join(*%W[gems #{s.original_name} bin bar]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
util_clear_gems
use_ui @ui do
@cmd.invoke "a:2"
assert_equal "a-2 foo\n", @ui.output
end
end
def test_gem_dependency_contains_executable
spec_fetcher do |fetcher|
fetcher.gem "a", 2 do |s|
s.executables = %w[]
s.files = %w[lib/a.rb]
s.add_dependency "b"
end
fetcher.gem "b", 2 do |s|
s.executables = %w[a]
s.files = %w[bin/a lib/b.rb]
write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
util_clear_gems
use_ui @ui do
@cmd.invoke "a:2"
assert_equal "b-2 a\n", @ui.output
end
end
def test_gem_dependency_contains_other_executable
spec_fetcher do |fetcher|
fetcher.gem "a", 2 do |s|
s.executables = %w[]
s.files = %w[lib/a.rb]
s.add_dependency "b"
end
fetcher.gem "b", 2 do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/b.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
util_clear_gems
use_ui @ui do
e = assert_raise Gem::MockGemUi::TermError do
@cmd.invoke "a:2"
end
assert_equal 1, e.exit_code
assert_equal <<~ERR, @ui.error
ERROR: Failed to load executable `a`, are you sure the gem `a` contains it?
ERR
end
end
def test_other_gem_contains_executable
spec_fetcher do |fetcher|
fetcher.gem "a", 2 do |s|
s.executables = %w[]
s.files = %w[lib/a.rb]
end
fetcher.gem "b", 2 do |s|
s.executables = %w[a]
s.files = %w[bin/a lib/b.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
util_clear_gems
use_ui @ui do
e = assert_raise Gem::MockGemUi::TermError do
@cmd.invoke "a:2"
end
assert_equal 1, e.exit_code
assert_equal <<~ERR, @ui.error
ERROR: Failed to load executable `a`, are you sure the gem `a` contains it?
ERR
end
end
def test_missing_gem
spec_fetcher do |fetcher|
end
use_ui @ui do
e = assert_raise Gem::MockGemUi::TermError do
@cmd.invoke "a"
end
assert_equal 2, e.exit_code
assert_equal <<~ERR, @ui.error
ERROR: Could not find a valid gem 'a' (>= 0) in any repository
ERR
end
end
def test_version_mismatch
spec_fetcher do |fetcher|
fetcher.gem "a", 1
end
util_clear_gems
use_ui @ui do
e = assert_raise Gem::MockGemUi::TermError do
@cmd.invoke "a:2"
end
assert_equal 2, e.exit_code
assert_equal <<~ERR, @ui.error
ERROR: Could not find a valid gem 'a' (= 2) in any repository
ERROR: Possible alternatives: a
ERR
end
end
def test_pre_argument
spec_fetcher do |fetcher|
fetcher.gem "a", 1 do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
fetcher.gem "a", "1.1.a" do |s|
s.executables = %w[foo ]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
util_clear_gems
use_ui @ui do
@cmd.invoke "--pre", "a"
assert_equal "a-1.1.a foo\n", @ui.output
end
end
def test_pre_version_option
spec_fetcher do |fetcher|
fetcher.gem "a", 1 do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
fetcher.gem "a", "1.1.a" do |s|
s.executables = %w[foo ]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
util_clear_gems
use_ui @ui do
@cmd.invoke "-v", ">= 0.a", "a"
assert_equal "a-1.1.a foo\n", @ui.output
end
end
def test_conservative_missing_gem
spec_fetcher do |fetcher|
fetcher.gem "a", 1 do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
util_clear_gems
use_ui @ui do
e = assert_raise Gem::MockGemUi::TermError do
@cmd.invoke "--verbose", "--conservative", "a:2"
end
assert_equal 2, e.exit_code
assert_include @ui.output, "a (= 2) not available locally"
assert_equal <<~ERROR, @ui.error
ERROR: Could not find a valid gem 'a' (= 2) in any repository
ERROR: Possible alternatives: a
ERROR
end
end
def test_conservative
spec_fetcher do |fetcher|
fetcher.gem "a", 1 do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
util_clear_gems
use_ui @ui do
@cmd.invoke "--verbose", "--conservative", "a"
assert_include @ui.output, "a (>= 0) not available locally"
assert_include @ui.output, "a-1 foo"
end
@ui.outs.truncate(0)
spec_fetcher do |fetcher|
fetcher.gem "a", 1 do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
fetcher.gem "a", 2 do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
end
end
end
use_ui @ui do
@cmd.invoke "--verbose", "--conservative", "a"
assert_not_include @ui.output, "a (>= 0) not available locally"
assert_include @ui.output, "a-1 foo"
end
end
end