diff options
Diffstat (limited to 'test/rubygems')
204 files changed, 8355 insertions, 4134 deletions
diff --git a/test/rubygems/alternate_cert.pem b/test/rubygems/alternate_cert.pem index 54a34441b1..55303190f5 100644 --- a/test/rubygems/alternate_cert.pem +++ b/test/rubygems/alternate_cert.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDFjCCAf6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADAtMRIwEAYDVQQDDAlhbHRl +MIIDFjCCAf6gAwIBAgIBBDANBgkqhkiG9w0BAQsFADAtMRIwEAYDVQQDDAlhbHRl cm5hdGUxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCAXDTEyMDEwMTAwMDAwMFoY Dzk5OTkxMjMxMjM1OTU5WjAtMRIwEAYDVQQDDAlhbHRlcm5hdGUxFzAVBgoJkiaJ k/IsZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA -vZQipBa1xH3M9OonkrUYhGZeX9UHAcJhe6jJbUr/uHXkh1Tu2ERWNnblm85upqBf -jyZEnKer7uBcwwkkvmisVgC8uBECymsBxuEIw0rfiKYEnLu0B6SiWFYz3dYPS92b -BK7Vks2/kNyXUmLLGoZ3id2K0eK5C/AJ0j+p84OqPnVhylsjrZmXfIZrh7lkHhgC -IrzPefjE3pOloi/tz6fh2ktb0FYKQMfweT3Ba2TMeflG13PEOW80AD5w0THxDutG -G0zPNCDyDEoT7UU1a3B3RMHYuUxEk1GUEYWq9L6a6SMpZISWTSpCp0Ww1QB55PON -iCCn+o6vcIy46jI71dATAQIDAQABoz8wPTAcBgNVHREEFTATgRFhbHRlcm5hdGVA -ZXhhbXBsZTAdBgNVHQ4EFgQUyvn/FwcZnA7AkzPjmoooB4/tKgcwDQYJKoZIhvcN -AQEFBQADggEBAHilxCg0dmOn3hxPjWMf/tAvG/S25iAIZZPuWo71DSSsn/zPRWDZ -OkDNL7syJ7S2jjrWWCIyLxhj89ZI7Oyd3elOB2zd4RsDij1y9Gv0ZPqNoTp0Repk -aPtRRLEwk9j2C37Tv+qA2PnTLp8MA0DVkb1/yuSd03b2K/AZEHT8Jtf3WC3RqGSK -A1+M8CvPSSgPY7oveFFerpqAzfC4tlgyPZjSqBjZucEIlxBD2lA/3JQ8Ys8+0705 -j2jGMl5r1Y22nl0A0+cHGtPX3irtR8bcEAO+rpEfpHNF2APaYsCT7Frk1CtuAHYB -mEwqWPQKU5ZJOV4uu69Hw5Po2bfgyjKV+N8= +pebGm7NOnx+DtWG1xQsJBfTfwNlZvfzY61nlZccrhU6vx0AnYNiDZAG3J/gFQmYZ +9gJ98rzEwfLMCGq9R/TZM+lAEaLhzYZCu3X4QdhKxr1xZ/SFC+1f8KVuH4tLXORW +30DwayPhNxnrOvup4pWLiYuXUSZpV9CGMvPSUCW2odhMkBMKqaTTPjxoXJIcgacy +prkNgIq48cSvqWG/e/HrMRtkqvFbD5ta00uO1mlpajYYw1RRftEwktFo8vQgDBo9 +NT/EqoE72tffaDnLq6rQrVtw4Kr9fy775DjNAWXyiCBjnJgOQSXCGPsM/AEdFrh/ +LKQQv2M/M7WNevnEUgsEIwIDAQABoz8wPTAcBgNVHREEFTATgRFhbHRlcm5hdGVA +ZXhhbXBsZTAdBgNVHQ4EFgQUYPwS8g98+4Tq/8gcEK1iilkGXH4wDQYJKoZIhvcN +AQELBQADggEBABSKUFmTk53+yrVFT3TvX5iGgXudNdACQqcnknAg66Q8+wMA8WT1 +M2oZJIH4SWSKUGMYubpYuc53tTtMnR594LPidyNbxo8KXMYoNfEkZCk6hh0eKVdx +zPJSZ4fOQ4mKFCd7HrycOr4bxuGPTVQERYJ45vZnhvVJDIRMgshnQuivP3VBwXkQ +gKLTCh2ew2ZJgPi1dfqdNMMSw7k4OQtQVhwbAkHgwL1TUShAO9lHzxFHlQgssfR0 +f6c89eB035Vn9s21StjerTOlC9+v4hOO7QhvbsCcUs2wWiE1BWo1QqnVBCjGKyVE +fISkJd1Sn5j+Vx/NJ7EfZcOGGQMdxHC+c90= -----END CERTIFICATE----- diff --git a/test/rubygems/alternate_cert_32.pem b/test/rubygems/alternate_cert_32.pem index adeffda24a..e727189470 100644 --- a/test/rubygems/alternate_cert_32.pem +++ b/test/rubygems/alternate_cert_32.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDFDCCAfygAwIBAgIBBTANBgkqhkiG9w0BAQUFADAtMRIwEAYDVQQDDAlhbHRl +MIIDFDCCAfygAwIBAgIBBTANBgkqhkiG9w0BAQsFADAtMRIwEAYDVQQDDAlhbHRl cm5hdGUxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTEyMDEwMTAwMDAwMFoX DTM4MDExOTAzMTQwN1owLTESMBAGA1UEAwwJYWx0ZXJuYXRlMRcwFQYKCZImiZPy -LGQBGRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2U -IqQWtcR9zPTqJ5K1GIRmXl/VBwHCYXuoyW1K/7h15IdU7thEVjZ25ZvObqagX48m -RJynq+7gXMMJJL5orFYAvLgRAsprAcbhCMNK34imBJy7tAekolhWM93WD0vdmwSu -1ZLNv5Dcl1JiyxqGd4nditHiuQvwCdI/qfODqj51YcpbI62Zl3yGa4e5ZB4YAiK8 -z3n4xN6TpaIv7c+n4dpLW9BWCkDH8Hk9wWtkzHn5RtdzxDlvNAA+cNEx8Q7rRhtM -zzQg8gxKE+1FNWtwd0TB2LlMRJNRlBGFqvS+mukjKWSElk0qQqdFsNUAeeTzjYgg -p/qOr3CMuOoyO9XQEwECAwEAAaM/MD0wHAYDVR0RBBUwE4ERYWx0ZXJuYXRlQGV4 -YW1wbGUwHQYDVR0OBBYEFMr5/xcHGZwOwJMz45qKKAeP7SoHMA0GCSqGSIb3DQEB -BQUAA4IBAQA1Vs3lcPpqnbsdtFDgrzApZuNgtyCRbbSrshq37dem9wSI4aFjAPLx -QGgf3c+XZczK9FkR3VUHcK8yZFrCKpv9giZDvzCUOMB/HSBAzNiNbhgUC1S0THir -xFriDITPoY7mrdJlX41Ssqk6tIKZsYP63UVghy7f9wxqXJvyfJZSB9UeM+0baQVL -tGTKXmvzLw1Pc/LHTrt7jcZT9UbBsxNNy0Wk9FPPePCUUlegRjInd/sNevywzL/T -1DL0BefqF6iyWcu86Udo+eli1JDzeUsfHOL7oqJGlWhlZHRDJ1M89n5KwPg8SCx5 -TpemV2Wy0nRTzITnmggexlMibSJ0iOvC +LGQBGRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKXm +xpuzTp8fg7VhtcULCQX038DZWb382OtZ5WXHK4VOr8dAJ2DYg2QBtyf4BUJmGfYC +ffK8xMHyzAhqvUf02TPpQBGi4c2GQrt1+EHYSsa9cWf0hQvtX/Clbh+LS1zkVt9A +8Gsj4TcZ6zr7qeKVi4mLl1EmaVfQhjLz0lAltqHYTJATCqmk0z48aFySHIGnMqa5 +DYCKuPHEr6lhv3vx6zEbZKrxWw+bWtNLjtZpaWo2GMNUUX7RMJLRaPL0IAwaPTU/ +xKqBO9rX32g5y6uq0K1bcOCq/X8u++Q4zQFl8oggY5yYDkElwhj7DPwBHRa4fyyk +EL9jPzO1jXr5xFILBCMCAwEAAaM/MD0wHAYDVR0RBBUwE4ERYWx0ZXJuYXRlQGV4 +YW1wbGUwHQYDVR0OBBYEFGD8EvIPfPuE6v/IHBCtYopZBlx+MA0GCSqGSIb3DQEB +CwUAA4IBAQBJeq9kniAdddOY2r9MhRYb8/rzWL1mcCgbIzkwXCTeOyVt0nWZZwAy +arEy8ofkXt1O3Bm+59+dPORnG5WJeBGVmGDHo9HxDjm4dgTramYqgtxbthmB/pu+ +QhJ5DQg59odomoRRG7dkqacd8GMdcJVYcb3OzV3Fe5v2gtvnVPZ711APtjZ7sZUR +4XBA+ok95QFeSUYo4WIOCHh16pPtZ9ium5SZ7ChVVNj5rthr+sS+rQKjEdjG510w +UOkg8rUjEvXPGjM80/DnOvzyRJvbcCWBWWHquft3wqbjTomnQtqHne2SwRFEyfpd +JLEuY9QtEUCUy7obccN39+nT9jUOyg3B -----END CERTIFICATE----- diff --git a/test/rubygems/alternate_key.pem b/test/rubygems/alternate_key.pem index 14ca734aba..ae587b3425 100644 --- a/test/rubygems/alternate_key.pem +++ b/test/rubygems/alternate_key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/test/rubygems/bad_rake.rb b/test/rubygems/bad_rake.rb index a08aa7dacc..e15a7d4156 100644 --- a/test/rubygems/bad_rake.rb +++ b/test/rubygems/bad_rake.rb @@ -1,2 +1,3 @@ # frozen_string_literal: true + exit 1 diff --git a/test/rubygems/bundler_test_gem.rb b/test/rubygems/bundler_test_gem.rb new file mode 100644 index 0000000000..ca2980e04b --- /dev/null +++ b/test/rubygems/bundler_test_gem.rb @@ -0,0 +1,424 @@ +# frozen_string_literal: true + +require_relative "helper" + +class TestBundlerGem < Gem::TestCase + PROJECT_DIR = File.expand_path("../..", __dir__) + + def test_self_use_gemdeps + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("-") do + FileUtils.mkdir_p "detect/a/b" + FileUtils.mkdir_p "detect/a/Isolate" + + FileUtils.touch "detect/Isolate" + + begin + Dir.chdir "detect/a/b" + + Gem.use_gemdeps + + assert_equal add_bundler_full_name([]), loaded_spec_names + ensure + Dir.chdir @tempdir + end + end + end + end + + def test_self_find_files_with_gemfile + with_local_bundler_at(Gem.dir) do + cwd = File.expand_path("test/rubygems", PROJECT_DIR) + actual_load_path = $LOAD_PATH.unshift(cwd).dup + + discover_path = File.join "lib", "sff", "discover.rb" + + foo1, _ = %w[1 2].map do |version| + spec = quick_gem "sff", version do |s| + s.files << discover_path + end + + write_file(File.join("gems", spec.full_name, discover_path)) do |fp| + fp.puts "# #{spec.full_name}" + end + + spec + end + Gem.refresh + + write_file(File.join(Dir.pwd, "Gemfile")) do |fp| + fp.puts "source 'https://rubygems.org'" + fp.puts "gem '#{foo1.name}', '#{foo1.version}'" + end + Gem.use_gemdeps(File.join(Dir.pwd, "Gemfile")) + + expected = [ + File.expand_path("test/rubygems/sff/discover.rb", PROJECT_DIR), + File.join(foo1.full_gem_path, discover_path), + ].sort + + assert_equal expected, Gem.find_files("sff/discover").sort + assert_equal expected, Gem.find_files("sff/**.rb").sort, "[ruby-core:31730]" + assert_equal cwd, actual_load_path.shift + end + end + + def test_auto_activation_of_specific_gemdeps_file + with_local_bundler_at(Gem.dir) do + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + f.puts "gem 'b'" + f.puts "gem 'c'" + end + + with_rubygems_gemdeps(path) do + Gem.use_gemdeps + + assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names + end + end + end + + def test_auto_activation_of_used_gemdeps_file + with_local_bundler_at(Gem.dir) do + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + f.puts "gem 'b'" + f.puts "gem 'c'" + end + + with_rubygems_gemdeps("-") do + expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name) + + Gem.use_gemdeps + + assert_equal expected_specs, loaded_spec_names + end + end + end + + def test_looks_for_gemdeps_files_automatically_from_binstubs + path = File.join(@tempdir, "gd-tmp") + + with_local_bundler_at(path) do + a = util_spec "a", "1" do |s| + s.executables = %w[foo] + s.bindir = "exe" + end + + write_file File.join(@tempdir, "exe", "foo") do |fp| + fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" + end + + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + install_gem a, install_dir: path + install_gem b, install_dir: path + install_gem c, install_dir: path + + ENV["GEM_PATH"] = path + + with_rubygems_gemdeps("-") do + new_path = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_rubyopt = "-I#{rubygems_path} -I#{bundler_path}" + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = with_path_and_rubyopt(new_path, new_rubyopt) do + IO.popen("foo", &:read).split(/\n/) + end + + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = with_path_and_rubyopt(new_path, new_rubyopt) do + IO.popen("foo", &:read).split(/\n/) + end + + assert_equal ["b-1", "c-1"], out - out0 + end + end + end + + def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir + path = File.join(@tempdir, "gd-tmp") + + with_local_bundler_at(path) do + pend "IO.popen has issues on JRuby when passed :chdir" if Gem.java_platform? + + a = util_spec "a", "1" do |s| + s.executables = %w[foo] + s.bindir = "exe" + end + + write_file File.join(@tempdir, "exe", "foo") do |fp| + fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" + end + + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + install_gem a, install_dir: path + install_gem b, install_dir: path + install_gem c, install_dir: path + + ENV["GEM_PATH"] = path + + with_rubygems_gemdeps("-") do + Dir.mkdir "sub1" + + new_path = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_rubyopt = "-I#{rubygems_path} -I#{bundler_path}" + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = with_path_and_rubyopt(new_path, new_rubyopt) do + IO.popen("foo", chdir: "sub1", &:read).split(/\n/) + end + + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = with_path_and_rubyopt(new_path, new_rubyopt) do + IO.popen("foo", chdir: "sub1", &:read).split(/\n/) + end + + Dir.rmdir "sub1" + + assert_equal ["b-1", "c-1"], out - out0 + end + end + end + + def test_use_gemdeps + with_local_bundler_at(Gem.dir) do + gem_deps_file = "gem.deps.rb" + spec = util_spec "a", 1 + install_specs spec + + spec = Gem::Specification.find {|s| s == spec } + refute spec.activated? + + File.open gem_deps_file, "w" do |io| + io.write 'gem "a"' + end + + assert_nil Gem.gemdeps + + Gem.use_gemdeps gem_deps_file + + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + refute_nil Gem.gemdeps + end + end + + def test_use_gemdeps_ENV + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps(nil) do + spec = util_spec "a", 1 + + refute spec.activated? + + File.open "gem.deps.rb", "w" do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + refute spec.activated? + end + end + end + + def test_use_gemdeps_argument_missing + with_local_bundler_at(Gem.dir) do + e = assert_raise ArgumentError do + Gem.use_gemdeps "gem.deps.rb" + end + + assert_equal "Unable to find gem dependencies file at gem.deps.rb", + e.message + end + end + + def test_use_gemdeps_argument_missing_match_ENV + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("gem.deps.rb") do + e = assert_raise ArgumentError do + Gem.use_gemdeps "gem.deps.rb" + end + + assert_equal "Unable to find gem dependencies file at gem.deps.rb", + e.message + end + end + end + + def test_use_gemdeps_automatic + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("-") do + spec = util_spec "a", 1 + install_specs spec + spec = Gem::Specification.find {|s| s == spec } + + refute spec.activated? + + File.open "Gemfile", "w" do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + end + end + end + + def test_use_gemdeps_automatic_missing + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("-") do + Gem.use_gemdeps + + assert true # count + end + end + end + + def test_use_gemdeps_disabled + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("") do + spec = util_spec "a", 1 + + refute spec.activated? + + File.open "gem.deps.rb", "w" do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + refute spec.activated? + end + end + end + + def test_use_gemdeps_missing_gem + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("x") do + File.open "x", "w" do |io| + io.write 'gem "a"' + end + + expected = <<-EXPECTED +Could not find gem 'a' in locally installed gems. +You may need to `bundle install` to install missing gems + + EXPECTED + + Gem::Deprecate.skip_during do + actual_stdout, actual_stderr = capture_output do + Gem.use_gemdeps + end + assert_empty actual_stdout + assert_equal(expected, actual_stderr) + end + end + end + end + + def test_use_gemdeps_specific + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("x") do + spec = util_spec "a", 1 + install_specs spec + + spec = Gem::Specification.find {|s| s == spec } + refute spec.activated? + + File.open "x", "w" do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + end + end + end + + private + + def add_bundler_full_name(names) + names << "bundler-#{Bundler::VERSION}" + names.sort! + names + end + + def with_path_and_rubyopt(path_value, rubyopt_value) + path = ENV["PATH"] + ENV["PATH"] = path_value + rubyopt = ENV["RUBYOPT"] + ENV["RUBYOPT"] = rubyopt_value + + yield + ensure + ENV["PATH"] = path + ENV["RUBYOPT"] = rubyopt + end + + def with_rubygems_gemdeps(value) + rubygems_gemdeps = ENV["RUBYGEMS_GEMDEPS"] + ENV["RUBYGEMS_GEMDEPS"] = value + + yield + ensure + ENV["RUBYGEMS_GEMDEPS"] = rubygems_gemdeps + end + + def with_local_bundler_at(path) + require "bundler" + + # If bundler gemspec exists, pretend it's installed + bundler_gemspec = File.expand_path("../../bundler/bundler.gemspec", __dir__) + if File.exist?(bundler_gemspec) + target_gemspec_location = "#{path}/specifications/bundler-#{Bundler::VERSION}.gemspec" + + FileUtils.mkdir_p File.dirname(target_gemspec_location) + + File.write target_gemspec_location, Gem::Specification.load(bundler_gemspec).to_ruby_for_cache + end + + yield + ensure + Bundler.reset! + end +end diff --git a/test/rubygems/child_cert.pem b/test/rubygems/child_cert.pem index 9293cfc966..26c916cf96 100644 --- a/test/rubygems/child_cert.pem +++ b/test/rubygems/child_cert.pem @@ -1,20 +1,19 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/rubygems/child_cert_32.pem b/test/rubygems/child_cert_32.pem index 3484803a20..4e2fcf10df 100644 --- a/test/rubygems/child_cert_32.pem +++ b/test/rubygems/child_cert_32.pem @@ -1,20 +1,19 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/rubygems/child_key.pem b/test/rubygems/child_key.pem index c56d0699c8..61fdfb628e 100644 --- a/test/rubygems/child_key.pem +++ b/test/rubygems/child_key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/test/rubygems/encrypted_private_key.pem b/test/rubygems/encrypted_private_key.pem index d9667689a6..2d0022a6c0 100644 --- a/test/rubygems/encrypted_private_key.pem +++ b/test/rubygems/encrypted_private_key.pem @@ -1,30 +1,30 @@ -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED -DEK-Info: AES-256-CBC,CB6FD0B173EF450C6EE21A01DD785C1D +DEK-Info: AES-256-CBC,4851D8D265711252BA5EAD983C957412 -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 -----END RSA PRIVATE KEY----- diff --git a/test/rubygems/expired_cert.pem b/test/rubygems/expired_cert.pem index c76fe4c58f..12b8836607 100644 --- a/test/rubygems/expired_cert.pem +++ b/test/rubygems/expired_cert.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDCzCCAfOgAwIBAgIBBjANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv +MIIDCzCCAfOgAwIBAgIBBjANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTcwMDEwMTAwMDAwMFoXDTcw MDEwMTAwMDAwMFowKjEPMA0GA1UEAwwGbm9ib2R5MRcwFQYKCZImiZPyLGQBGRYH -ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdlNYcvFB6x -gpT8QcnMybVelGLUKyQL/hQPTK9J5FyqB8hEDLt2ruMwKsHU6fu/mgG+sLvHF1nq -WhZADhn6rwCfNP03025vktOZ6iJfU60vytY/f3gkiGNkP21l0hz0+Ms15f+52gk+ -sFXqwGBbDteI0x57UsHi+KAN67QuPDnthYDtwhXIA5pcdx2wH+NW8F82HEZvm1hc -pA75BDVk4vPxnpDfvPOKSYn9dWghmUtaPmqyVvs8XkDxHDfY54/D3ziPehP+zQzE -g8C07Sq/z6vLSOQ3uaYn0nBDuNE6XP3ijJ4Zvs2eJEdOMyS1H3CsnkWiePCrLtKd -w8d/F+D5bocCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD -VR0OBBYEFF9DbvaajkUl6SLjfTdepNU2AoUbMA0GCSqGSIb3DQEBBQUAA4IBAQAP -Z8vKQ1OjQCHx8MJ0gy6WN2CIjh0Uqf3fSfza3nd+K8jlJPkF7znEBZ345iCSmNwn -EPrz/OrqiId2OHW2OCJv3c9NEb7hgaTswGfdq9LmqMRVeQy57FWh2lRdjVZbquWy -IvM72hjVLqnMVisWbDxf32YghnmT37SzZKsHSXU0xUx7rVSIShnoMjLWQtIQDoqI -3isMAeKals2NNJOy0TGKJ9SspIDl/IYm9sEO1HKiuxubrdN9q+wEQdizt59sXkol -4AYga+5TN+KtsSRclAGjfKYfuRrQ85IbVsRhQIYX1ZOJtMseEhBRnIeySKV4xWsi -kXAaxX5wIyoM+S1vaKcu +ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFC3H6Q26GO +bllXTiJBeALUbouzzxaGinwZeYYhhXKWEcfA0D8k+22w/JyndeEYc29JxwjFNwxM +/DyyQplptzbM1Q5BCcLNQaQhmpOryosjWuYWW1JUDGTG3nEg0qRCrtjwVoAU++Ko +NkQboM0wFQJxkBns0J1sr+O5Ml73YzKKtdVWWvg89osxyb4wRxkEoa9a/b9/aiK7 +WoeQhF00cRKoa/eoIN8usTjzKsYudHUtEQWibD7IxWdY3nMntGf1jyLYi40lVUbL +FFytWtlZGMVKpMVIOMMCQ+ex+ExGQaJrQF5QEqPq1L/BvXgTZkv5P6CS3YjBdVC2 +/ntfos3gMhsCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD +VR0OBBYEFLEaVAlnRWACAtfO9B1gSonf51jZMA0GCSqGSIb3DQEBCwUAA4IBAQDI +x70p19RI73Y9AEfBd0Wmk7KsZQyP55kjTAdaM37crhmClkUQRrk/Y2a0pXOhsrNI +0YO7t44fJKwMu++1dxh/bllKbuOkca6ApxTb2IfhOejx3IXXWzp+C1F9pmG9q5QW +0FDt//0SFZJIqDq9N+zFiA2z0MM1L7X/r29uUgAqkU7rsytKavHXru9EGQrrkxwh +5dM5VI+pnJgk9HYpBDPwiFVd0yFelebqdlv/nnW11tVBMTkMloVYyhei5yZbWKFk +f0Aj5g94+S107oRMyzq5e6lxQcJBhmKfOXqGaz2wue3/IHnwio9dMArayug9GLEr +ycy6PubJImhM/dboDIdO -----END CERTIFICATE----- diff --git a/test/rubygems/fake_certlib/openssl.rb b/test/rubygems/fake_certlib/openssl.rb index c7f85140a1..928672c7e5 100644 --- a/test/rubygems/fake_certlib/openssl.rb +++ b/test/rubygems/fake_certlib/openssl.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + #-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. diff --git a/test/rubygems/future_cert.pem b/test/rubygems/future_cert.pem index 05d3f9ebe3..06e08bb4c6 100644 --- a/test/rubygems/future_cert.pem +++ b/test/rubygems/future_cert.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDDzCCAfegAwIBAgIBCDANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv +MIIDDzCCAfegAwIBAgIBCDANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCIYDzk5OTkxMjMxMjM1OTU5WhgP OTk5OTEyMzEyMzU5NTlaMCoxDzANBgNVBAMMBm5vYm9keTEXMBUGCgmSJomT8ixk -ARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnZTWH -LxQesYKU/EHJzMm1XpRi1CskC/4UD0yvSeRcqgfIRAy7dq7jMCrB1On7v5oBvrC7 -xxdZ6loWQA4Z+q8AnzT9N9Nub5LTmeoiX1OtL8rWP394JIhjZD9tZdIc9PjLNeX/ -udoJPrBV6sBgWw7XiNMee1LB4vigDeu0Ljw57YWA7cIVyAOaXHcdsB/jVvBfNhxG -b5tYXKQO+QQ1ZOLz8Z6Q37zzikmJ/XVoIZlLWj5qslb7PF5A8Rw32OePw984j3oT -/s0MxIPAtO0qv8+ry0jkN7mmJ9JwQ7jROlz94oyeGb7NniRHTjMktR9wrJ5Fonjw -qy7SncPHfxfg+W6HAgMBAAGjPDA6MBkGA1UdEQQSMBCBDm5vYm9keUBleGFtcGxl -MB0GA1UdDgQWBBRfQ272mo5FJeki4303XqTVNgKFGzANBgkqhkiG9w0BAQUFAAOC -AQEAM/0YoOjHEs1zdE6oG10XKdDcYn192AYhkMaITrfJUJiVUYehmcC+fa7aV5Hp -CYasFm5SawiyHwcI92GROaM97gJy7Tjpg8zcpkXg/vUA/8ItzD0UYphs5efZ9B3R -zOfxQDasTZJgg0uCxw23Bil7Anf5/KipuiU92Cc3fjpI6jWOuezGWqSqC2KGJLM+ -S59/oLqQNR67j7WBH3lHe3qbUehpNPkSrTdcLEbvspZM2udrRN9QYUUwBxD9dMlB -eC4hADgWEh5uPZO5sM2+qUdyIRa+fDUpcbTEhLQy6NceHuCNLK230DdC2xszrtNY -yNFy3B5BHgxfZeycaC4pMED0gA== +ARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRQtx+ +kNuhjm5ZV04iQXgC1G6Ls88Whop8GXmGIYVylhHHwNA/JPttsPycp3XhGHNvSccI +xTcMTPw8skKZabc2zNUOQQnCzUGkIZqTq8qLI1rmFltSVAxkxt5xINKkQq7Y8FaA +FPviqDZEG6DNMBUCcZAZ7NCdbK/juTJe92MyirXVVlr4PPaLMcm+MEcZBKGvWv2/ +f2oiu1qHkIRdNHESqGv3qCDfLrE48yrGLnR1LREFomw+yMVnWN5zJ7Rn9Y8i2IuN +JVVGyxRcrVrZWRjFSqTFSDjDAkPnsfhMRkGia0BeUBKj6tS/wb14E2ZL+T+gkt2I +wXVQtv57X6LN4DIbAgMBAAGjPDA6MBkGA1UdEQQSMBCBDm5vYm9keUBleGFtcGxl +MB0GA1UdDgQWBBSxGlQJZ0VgAgLXzvQdYEqJ3+dY2TANBgkqhkiG9w0BAQsFAAOC +AQEAATJNbSaVk8fM1uhqQnlBiQ/0TzchHADy+WmsbIbOiUAc8c29sjpCC4x0o5Gk +Zn18+BsXUjfyF6zyY4wPABZp9SCDIxvLxP2QVmbCtY2TJeKV95c4mWEnrFcCqYZ/ +je13m5iLnAu1WqVjSbFn1KamTf25pfBd9mqgQVwrdJMGoviJC18LyKJTZs7aV+Bu +tsF9fVMIP8p1Xu0Es/hBXFRwths41seqT0dYFszhwTCBC9tt85TTixWmEXpdyrov +vLFULJg4ijn9YZeKMViC6V3zgHUl9ZnMlWdFpVZ6cf7kA/1acW1ESEZnARLQhvMF +a1gof1D2Mj5k3AtQJ2TtPXytxw== -----END CERTIFICATE----- diff --git a/test/rubygems/future_cert_32.pem b/test/rubygems/future_cert_32.pem index aa74bdffbc..c023110141 100644 --- a/test/rubygems/future_cert_32.pem +++ b/test/rubygems/future_cert_32.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDCzCCAfOgAwIBAgIBCTANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv +MIIDCzCCAfOgAwIBAgIBCTANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTM4MDExOTAzMTQwN1oXDTM4 MDExOTAzMTQwN1owKjEPMA0GA1UEAwwGbm9ib2R5MRcwFQYKCZImiZPyLGQBGRYH -ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdlNYcvFB6x -gpT8QcnMybVelGLUKyQL/hQPTK9J5FyqB8hEDLt2ruMwKsHU6fu/mgG+sLvHF1nq -WhZADhn6rwCfNP03025vktOZ6iJfU60vytY/f3gkiGNkP21l0hz0+Ms15f+52gk+ -sFXqwGBbDteI0x57UsHi+KAN67QuPDnthYDtwhXIA5pcdx2wH+NW8F82HEZvm1hc -pA75BDVk4vPxnpDfvPOKSYn9dWghmUtaPmqyVvs8XkDxHDfY54/D3ziPehP+zQzE -g8C07Sq/z6vLSOQ3uaYn0nBDuNE6XP3ijJ4Zvs2eJEdOMyS1H3CsnkWiePCrLtKd -w8d/F+D5bocCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD -VR0OBBYEFF9DbvaajkUl6SLjfTdepNU2AoUbMA0GCSqGSIb3DQEBBQUAA4IBAQA6 -lip2nqmXyhz1uBDAxlNAv9nN2JPicWpRIvQ4KLNwmZKnagPWfleZ4TbLqsn723w8 -lD2VqFNX/Vj1XNuEJg8pXME+qxbMgtWxGsXC0z6k2Q3rT81QTdhXJ7nqdoe2i8y1 -423Fft2L6Dcgmx2USJwZsNy53pK9smxI9NipuRtL4W34PHHpaFsC2646daxZ2F8M -No3R9C4CtSFJDrM0XZoFiAnarbqoGCJs2q0NtcdV8D5m6xGeNShWJMLNbVx4DgsT -E90gVxVqPaqm5ytAIfdPWVUsyJBoD15jDVH5AZtkBmFRNoz60KPt3HpiRPspKWCd -tVabH2JRC0wDYRwEEMKB +ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFC3H6Q26GO +bllXTiJBeALUbouzzxaGinwZeYYhhXKWEcfA0D8k+22w/JyndeEYc29JxwjFNwxM +/DyyQplptzbM1Q5BCcLNQaQhmpOryosjWuYWW1JUDGTG3nEg0qRCrtjwVoAU++Ko +NkQboM0wFQJxkBns0J1sr+O5Ml73YzKKtdVWWvg89osxyb4wRxkEoa9a/b9/aiK7 +WoeQhF00cRKoa/eoIN8usTjzKsYudHUtEQWibD7IxWdY3nMntGf1jyLYi40lVUbL +FFytWtlZGMVKpMVIOMMCQ+ex+ExGQaJrQF5QEqPq1L/BvXgTZkv5P6CS3YjBdVC2 +/ntfos3gMhsCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD +VR0OBBYEFLEaVAlnRWACAtfO9B1gSonf51jZMA0GCSqGSIb3DQEBCwUAA4IBAQB2 +EjAxPVbDwoYehhEJEiMnMWk8GL6oo1uVwGJgCM76Yml69FVyWrre2GcSYiv+9f7K +AzE9S2uREeJuGcSV0VR0MeXoHXwQpQyBV12gCL1eQH15oxFfTi9XbVLhh5CyTKc1 +J6lYtQVpZPlLRoJN3oBq3J8PN8hWBWuhb2VIrpHXNBXAMOZ+hJM2B+EYifH6tcI5 +YK/Bw5Tes81QU4stQTLKybJzQkct02Rm7bYIM3GX/FGMMEPZE4jhnQ5btSNYVBlY +HXh6qfZVhZ8qpAy50yrlxROLa5zJSuTQ28QWh95XLzzHiHJ4Q4qZQzhcRGUQLfM3 +X6P8rtGWzXtB++CKKQIG -----END CERTIFICATE----- diff --git a/test/rubygems/good_rake.rb b/test/rubygems/good_rake.rb index 4a05ae4a13..bb0ed9fa80 100644 --- a/test/rubygems/good_rake.rb +++ b/test/rubygems/good_rake.rb @@ -1,2 +1,3 @@ # frozen_string_literal: true + exit 0 diff --git a/test/rubygems/grandchild_cert.pem b/test/rubygems/grandchild_cert.pem index dbd14bce80..c1d9887b60 100644 --- a/test/rubygems/grandchild_cert.pem +++ b/test/rubygems/grandchild_cert.pem @@ -1,20 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDNTCCAh2gAwIBAgIBDDANBgkqhkiG9w0BAQUFADApMQ4wDAYDVQQDDAVjaGls +MIIDFDCCAfygAwIBAgIBDDANBgkqhkiG9w0BAQsFADApMQ4wDAYDVQQDDAVjaGls ZDEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUwIBcNMTIwMTAxMDAwMDAwWhgPOTk5 OTEyMzEyMzU5NTlaMC4xEzARBgNVBAMMCmdyYW5kY2hpbGQxFzAVBgoJkiaJk/Is -ZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkfgy -EbzcRpXvpNA0s75R8gOVk7ENEPX5uXUElbzHbVEmHkC/NFsWZXV0vxGFfZrrnEkT -Y2kDaMMkfZX9rriRIvsZpxyqrdX87QfQTZ1ktDoytVnd+gw9A6AXB6PR7uoPymso -f/lZYJ8BWP9fIU39nogiptFqsgkpOtKSFjJfMILkcMAeBPs2B5HV5l4oLrpJ7Ns/ -0vazCXGakTByAXNKBagJWR43gh+RUQWF6Uh04VQTQ7ENGWI83088SKAPtCCcgKxr -ROHI025S7o7vEfDEqEn+gtu+4ndaLuRp+2AmF3YK8dEDiLXrrvEvG1r4+gIB/6tS -MUfkkJtBleZrDoIAgQIDAQABo2EwXzAdBgNVHREEFjAUgRJncmFuZGNoaWxkQGV4 -YW1wbGUwHQYDVR0OBBYEFAnex9R5fpiHNpHxq91rMog/PZA6MB8GA1UdIwQYMBaA -FHzVU9N7sklKBPrHElxoZ32Fg64IMA0GCSqGSIb3DQEBBQUAA4IBAQCYT10tUm9O -2xSGVmsbYv5YVrMr1Ucuq6Y+mXuTqqXuidILXZZl3LDwaYj64AhmMUqfITybGbR3 -sbWZrz2TWI2qWo+wcYDq+k0K+ys2PBavXdbjw4nVMf/9xYb2bCHK4bxxIG6rkmCw -zxYRTx+UivRf7Hw+6ZRtkHDxX/qPfMQK1PbmvK9c2VYXGN3+fRRIJqPnknN26Hv1 -gangMI7oqcaNwCvL16E/CpN8uwdJNB1LcCgjFJP7Ora+LIEJVe4eZvmuOYkYaYH2 -7u6CglItKwNjVZ5jULUfBuJqFkRiOxkVMVjChe9QvNXz/fkhW2sH05CR+TDyh4rD -ZeON5sdo9TV8 +ZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyh7u +lK+O7leQKBQzSSvhEur49Xu4sQJllkVbrVvkv2jSo68woESgljSS8jCSX0I9IJ5T +0kHzNRpiuOpfWKZx7E4cKeqW6nmV7D/B+Iy1QnJbMzUdnxp1Y+CMCK0JrLIsFBnx +ndVmiS/S817W3coqkmZqce4e33/O0qmCChGxGJZuAVQFGYI25SiYWPbysVEjwXoW +6zO0D1m8QZLYYCeDSRpxKgItBoJK+Up+bm/nsrkFvUf4kAZNLgik5zvflM3/Mjyx +zxgY2MO07YaULOlr0vZN6Wxnq2F3jkuZY8JbEOpQSDGSgU2wJ1iFH+GLvj7LsBuR +ScjL0FJ4s1EjqjjP8QIDAQABo0AwPjAdBgNVHREEFjAUgRJncmFuZGNoaWxkQGV4 +YW1wbGUwHQYDVR0OBBYEFEuKocg9sisZIWu12gxzse+7/sHfMA0GCSqGSIb3DQEB +CwUAA4IBAQAFaz3FUNzDYt/Cb++6U1PXsucAy3pKDj8bUW7slJFleNsSooIA9A5b +axpnHst1Lt6i/bmvbi8F8q/0iq4PtsZvusmwVhJkCinEUZ9inddSJdxpWSyzOww5 +at8ragidzREd9Fx62flRr3GflzqIufkKN8TDjYrB+n45ijnSxDcwZhu7m/tmP/e2 +FxqODaIO9sVrPAU7YbXb0m3p3Em7RK22d0tqy1dHhcRIR5/yMQB4MSEvQ7ytRD2x +aHAP7A4rDbkRwG+LQ/4L57RJ1kU3InqpOEQnCgpwu3xw/6Alti9TXS7sGhXL4Aav +OLsFS/1BLSJx/DSSK58Vg6JFxFh6X2NK -----END CERTIFICATE----- diff --git a/test/rubygems/grandchild_cert_32.pem b/test/rubygems/grandchild_cert_32.pem index 5077a43452..5d1ad45cb7 100644 --- a/test/rubygems/grandchild_cert_32.pem +++ b/test/rubygems/grandchild_cert_32.pem @@ -1,20 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDMzCCAhugAwIBAgIBDTANBgkqhkiG9w0BAQUFADApMQ4wDAYDVQQDDAVjaGls +MIIDEjCCAfqgAwIBAgIBDTANBgkqhkiG9w0BAQsFADApMQ4wDAYDVQQDDAVjaGls ZDEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUwHhcNMTIwMTAxMDAwMDAwWhcNMzgw MTE5MDMxNDA3WjAuMRMwEQYDVQQDDApncmFuZGNoaWxkMRcwFQYKCZImiZPyLGQB -GRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJH4MhG8 -3EaV76TQNLO+UfIDlZOxDRD1+bl1BJW8x21RJh5AvzRbFmV1dL8RhX2a65xJE2Np -A2jDJH2V/a64kSL7Gaccqq3V/O0H0E2dZLQ6MrVZ3foMPQOgFwej0e7qD8prKH/5 -WWCfAVj/XyFN/Z6IIqbRarIJKTrSkhYyXzCC5HDAHgT7NgeR1eZeKC66SezbP9L2 -swlxmpEwcgFzSgWoCVkeN4IfkVEFhelIdOFUE0OxDRliPN9PPEigD7QgnICsa0Th -yNNuUu6O7xHwxKhJ/oLbvuJ3Wi7kaftgJhd2CvHRA4i1667xLxta+PoCAf+rUjFH -5JCbQZXmaw6CAIECAwEAAaNhMF8wHQYDVR0RBBYwFIESZ3JhbmRjaGlsZEBleGFt -cGxlMB0GA1UdDgQWBBQJ3sfUeX6YhzaR8avdazKIPz2QOjAfBgNVHSMEGDAWgBR8 -1VPTe7JJSgT6xxJcaGd9hYOuCDANBgkqhkiG9w0BAQUFAAOCAQEAnIlgmwVS3BGk -cT9LxE3bbQt1WGeLLxAF5ScqkNgFm3OvIxrKPX94WRa6tjWPEeJ9rl64QMKwJ8h1 -GzNbf0DUH8nMcSJLL1J5HUqdzwysQ96HNz54RuZ3ZF8w7QD4Kv3Vvh4IIsANchSj -unVYjcDVH9lSsbqTwC+bnUxYZ1Xu530fKZ440BG1ju9vLLZu5JaSOoJWRuHNOlQF -FbYj5AIjPwMNUidzoE9sUWdRzvARwecismWkPjfM0x1AmxVMs8hA5tS2QoCEvOxt -Hl3q6k7BaC8BRENkA/XRRIqgTMoTv86OOZIMFVaTiuHyU1XUxNHKv+ybAeAlP+H7 -hM/Hqka4bQ== +GRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMoe7pSv +ju5XkCgUM0kr4RLq+PV7uLECZZZFW61b5L9o0qOvMKBEoJY0kvIwkl9CPSCeU9JB +8zUaYrjqX1imcexOHCnqlup5lew/wfiMtUJyWzM1HZ8adWPgjAitCayyLBQZ8Z3V +Zokv0vNe1t3KKpJmanHuHt9/ztKpggoRsRiWbgFUBRmCNuUomFj28rFRI8F6Fusz +tA9ZvEGS2GAng0kacSoCLQaCSvlKfm5v57K5Bb1H+JAGTS4IpOc735TN/zI8sc8Y +GNjDtO2GlCzpa9L2TelsZ6thd45LmWPCWxDqUEgxkoFNsCdYhR/hi74+y7AbkUnI +y9BSeLNRI6o4z/ECAwEAAaNAMD4wHQYDVR0RBBYwFIESZ3JhbmRjaGlsZEBleGFt +cGxlMB0GA1UdDgQWBBRLiqHIPbIrGSFrtdoMc7Hvu/7B3zANBgkqhkiG9w0BAQsF +AAOCAQEAFW6StPxdeONHUmWXUAKXNncP66aaHPAk+rQ84IvuyJKqR3UrrKdCbQLQ +LpL/lQZDkjGJSXdNHUhoB4MQsDJ8TQs2BdwDqOIvQLsZxTKZaXPfc1diFP+z/5f0 +9wbWezUateJwShDpp1RltCBmFCdibPZQUCpsgAsfqsgIWNpzhqy9dI/Upg3vECVc +c4g+EsEtiNXSbjd0kWUXCGBAeTMu4paBLVtt81fuffKJfnAKRhzrfFy0PoL3Kt2T +DkMr4MWfkMOyVlrSkvjPtW1oHVnxfZgqaE91J0Ht9qiHvekti3JDqxqcKaYuIgAL +w9HK9z5uQA2KrMvqn/jiuD8lBFsnuA== -----END CERTIFICATE----- diff --git a/test/rubygems/grandchild_key.pem b/test/rubygems/grandchild_key.pem index a9b9aef624..63635844b0 100644 --- a/test/rubygems/grandchild_key.pem +++ b/test/rubygems/grandchild_key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEpgIBAAKCAQEAkfgyEbzcRpXvpNA0s75R8gOVk7ENEPX5uXUElbzHbVEmHkC/ -NFsWZXV0vxGFfZrrnEkTY2kDaMMkfZX9rriRIvsZpxyqrdX87QfQTZ1ktDoytVnd -+gw9A6AXB6PR7uoPymsof/lZYJ8BWP9fIU39nogiptFqsgkpOtKSFjJfMILkcMAe -BPs2B5HV5l4oLrpJ7Ns/0vazCXGakTByAXNKBagJWR43gh+RUQWF6Uh04VQTQ7EN -GWI83088SKAPtCCcgKxrROHI025S7o7vEfDEqEn+gtu+4ndaLuRp+2AmF3YK8dED -iLXrrvEvG1r4+gIB/6tSMUfkkJtBleZrDoIAgQIDAQABAoIBAQCFbg4+vpfQghBM -ZPI399oqUvJwziA2h9Kdn4TwZ18Y41vnvaHKdxUS63orihWvSmTjOL1bWsv+AJuj -nO8GvroU8tlxM7glLX2FImZb/GrogGaH9bz+bB995+IFXs9xCE4k5y1fRgxYUSDH -PLC13ffe6WxbdwSD9/HTTlaxqZvv1+UWxyYD0CSwopww5YdqISkVHq2UsmszK49X -hn6zzK+DT4YA04Tbv2Go9kCYLmsgrL2/dPJulDtJhX3AckbdkodSlBAmxe7XsKEO -TEzNDGgPZyZ+MXttBnLt1vk8ZrSJWcFG+E6DMbGUZ7rz6g98bUS1LI6PiqIp5BfS -sr0cGQl9AoGBAMGj7SCp1GMo8wOJpzzSGJ4PCc/fpG9NcTBqtmoUTuvMk4frkGXJ -dSS68KB0t0EGStbUFIZuylchC7RSzXs0uOZxkgaGcJT5qXXFP0Djy3/qoQMnJ2Yl -uhD6UsetPXbozK6MPs3mh9VqSDNbf2AM034nTod3I9sV471HZLwAhQk7AoGBAMD6 -Mmvy8DEa62VDTW6P1f4b6Pi6dOiZhGbNz5Xlh5jHplSMYReQGBVmr9szrV7qytGP -ZcBhEqTc53u2mEhSmRXQflRxJ7U2m8Xl3DClhxELHNGCJ9jEY52M4ZDJkvGj5v3t -pbTbE/g3zxmAaYZCOKIzYv5bSSStNpauxdomxuFzAoGBAJFohH97qEZSELJ+YrwU -VHIUfty/Zt5BvBaMe7CK0XzWIY72gHc+4Z2UV29WVeoZTIenuEX+2ii1YvGlIDI9 -s/8wF2SY/d+Q3wTV+prCtCS5TvFsLHTTLbbkEtdoqvgo9tK3881wKF5FMjSGp867 -svFPmPO2rpEtDdgrzWQzy7LTAoGBAK077Sea3qQ2VjqBQHGQDbofs/QU7f4gUgs3 -lrIpaqBsGZSssDxGzlfn5tYQfgJHI+sbn2wjuGjnJaaZM/s4qtQ6Zi3Hpq22aAAv -aIsDDUzvfN9WyA5/vi0g2xzu10q0qBgrziWcxUB+WRu7ev9bUxvIpYVQzUhvdiGu -o05CoSahAoGBAKoCGMGKkub+LnWazPkN2BAS6LblV+JIYWRI+DSGpz0UBk4Br546 -ozZq2GsLCQYWJabJ5RE9Are6rl9AvFQXMaWywOBe3TUz7SmLIxMjWpXKiX5YIFkS -tOiEEmET4ZYS87flEmldnmeDFLHHbMLOw5S0dJa4PyFRn6j9su8d8mWw +MIIEpAIBAAKCAQEAyh7ulK+O7leQKBQzSSvhEur49Xu4sQJllkVbrVvkv2jSo68w +oESgljSS8jCSX0I9IJ5T0kHzNRpiuOpfWKZx7E4cKeqW6nmV7D/B+Iy1QnJbMzUd +nxp1Y+CMCK0JrLIsFBnxndVmiS/S817W3coqkmZqce4e33/O0qmCChGxGJZuAVQF +GYI25SiYWPbysVEjwXoW6zO0D1m8QZLYYCeDSRpxKgItBoJK+Up+bm/nsrkFvUf4 +kAZNLgik5zvflM3/MjyxzxgY2MO07YaULOlr0vZN6Wxnq2F3jkuZY8JbEOpQSDGS +gU2wJ1iFH+GLvj7LsBuRScjL0FJ4s1EjqjjP8QIDAQABAoIBACI/cwQxKiojHqtX +3ufNXlYfB//Kjr05j36SsonRqhUv3Q88umPRtRc2gda1Wbv35JUwFrpoD96F4cf8 ++Jp0G5YjlxyYIinJX9i35fVoXDdN2ru2ypXgvRbnH7tBnMPNLfBbBAiPNhBVUOyJ +e6V5odSMM4mqBEOxK5mg/MaZgFVOrNf/DEI5oFSny7duEEQAuGJadJHUJOh7al0b +lByNVNAYNkdZMgvOdoAoyEzg5tvY9ykIwXUKdMwBgSlldolLYXyAjluXOVEj32m4 +p3rEV/vs+RQFTLLWXfyVyWoMIPYaK6nNaYpB8fMHnIjga8MzBgC6Hso3HqymRdg2 +Gttp4PUCgYEA2LQL72tzhUb+a0wo7dWJ4MY0ekyA7JxrqZRTWSNuqKMoAb6IxaXe +quZcpht/430szpOOz52pEwEEKUsCMuqwHiqmO2ZiZqYJpDQet466GFnhYhmAqV/x +bOaZLVbhGjiMQCD5YbpAmXjxF8SFbkqSKlSnpjxJKD2tGNX5FFWpN4UCgYEA7sXt +Xsf0XaPbISe2gYdXMO3exHplayt7C/wqjcxMePwtSwAJD+/JrFvFSiPBKT6Ajl+M +dcJIb9+WHhjk5GJI7KU4AVpf4feu5o1QnpnSAzCUlXpldYwSUS/7LZALvABm68Iy +2gHU1Aj5DYB/4nesWVhExKrMZDAICVojS5jCJH0CgYEA10SsIo9cN4ZZ0J7cfb7F +88sRcHg1DlcowFG/JmqDT/ScFnd/CNCITL8ARGZG+eZsL1333RiiT2WQC7EeoxPu +FlmJvrIriAriwwKfjPq0tOH8eeYZoKfVfbfpbFfEz7Zi5IWdFk7eQ1cYMOMhJXng +jzp/PCzhA5+ZJ3XPtDqQGb0CgYEA1AuwPuECUfqHSw1yldt0gj5s/D3aPW+SydT6 +kYziSPti2d1BLwb7Kfch4TKZgyA/mLCgE6AjJj8AmN/wviXOr2IWt5Tj29BTYeoT +s5XVHQISoiDdY6OuTK14ukDXOvF8dVi0QkkoEdmaG/SHHb67r2ilQaaQ91R0fqGv +AJ67ox0CgYBxkRfXPCnljxrJN7Fb1fS/DE1yVNWNkLiANOlUnPwzaD+jV0miCwEG +mR1PoRBG0j4sYTp9RyVCwR1RASNPStDTF/VcSllDqI45IHToKqgfeIlApmnCu291 +km1gAveM0Ayg5mLsIfIHyOlPZRL0iuewDDkwFNtwOiR87o9BurhRow== -----END RSA PRIVATE KEY----- diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index cb0177adb2..7014843bba 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -2,45 +2,27 @@ require "rubygems" -# If bundler gemspec exists, add to stubs -bundler_gemspec = File.expand_path("../../bundler/bundler.gemspec", __dir__) -if File.exist?(bundler_gemspec) - Gem::Specification.dirs.unshift File.dirname(bundler_gemspec) - Gem::Specification.class_variable_set :@@stubs, nil - Gem::Specification.stubs - Gem::Specification.dirs.shift -end - begin gem "test-unit", "~> 3.0" rescue Gem::LoadError end -if File.exist?(bundler_gemspec) - require_relative "../../bundler/lib/bundler" -else - require "bundler" -end - require "test/unit" ENV["JARS_SKIP"] = "true" if Gem.java_platform? # avoid unnecessary and noisy `jar-dependencies` post install hook -require "rubygems/deprecate" - require "fileutils" require "pathname" require "pp" require "rubygems/package" require "shellwords" require "tmpdir" -require "uri" +require "rubygems/vendor/uri/lib/uri" require "zlib" require "benchmark" # stdlib -require "rubygems/mock_gem_ui" +require_relative "mock_gem_ui" module Gem - ## # Allows setting the gem path searcher. @@ -88,8 +70,6 @@ end # your normal set of gems is not affected. class Gem::TestCase < Test::Unit::TestCase - extend Gem::Deprecate - attr_accessor :fetcher # :nodoc: attr_accessor :gem_repo # :nodoc: @@ -125,39 +105,32 @@ class Gem::TestCase < Test::Unit::TestCase refute File.directory?(path), msg end - # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L188 - def _synchronize - yield - end - - # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L546 + # Originally copied from minitest/assertions.rb def capture_subprocess_io - _synchronize do - begin - require "tempfile" + require "tempfile" - captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err") + captured_stdout = Tempfile.new("out") + captured_stderr = Tempfile.new("err") - orig_stdout, orig_stderr = $stdout.dup, $stderr.dup - $stdout.reopen captured_stdout - $stderr.reopen captured_stderr + orig_stdout = $stdout.dup + orig_stderr = $stderr.dup + $stdout.reopen captured_stdout + $stderr.reopen captured_stderr - yield + yield - $stdout.rewind - $stderr.rewind + $stdout.rewind + $stderr.rewind - return captured_stdout.read, captured_stderr.read - ensure - $stdout.reopen orig_stdout - $stderr.reopen orig_stderr + [captured_stdout.read, captured_stderr.read] + ensure + $stdout.reopen orig_stdout + $stderr.reopen orig_stderr - orig_stdout.close - orig_stderr.close - captured_stdout.close! - captured_stderr.close! - end - end + orig_stdout.close + orig_stderr.close + captured_stdout.close! + captured_stderr.close! end ## @@ -178,6 +151,14 @@ class Gem::TestCase < Test::Unit::TestCase end ## + # Overrides the Gem.install_extension_in_lib function and restores the + # original when the block ends + # + def extension_in_lib(value = true) # :nodoc: + Gem.stub(:install_extension_in_lib, value) { yield } + end + + ## # Sets the vendordir entry in RbConfig::CONFIG to +value+ and restores the # original value when the block ends # @@ -272,18 +253,10 @@ class Gem::TestCase < Test::Unit::TestCase def assert_contains_make_command(target, output, msg = nil) if output.include?("\n") msg = build_message(msg, - "Expected output containing make command \"%s\", but was \n\nBEGIN_OF_OUTPUT\n%sEND_OF_OUTPUT" % [ - ("%s %s" % [make_command, target]).rstrip, - output, - ] - ) + format("Expected output containing make command \"%s\", but was \n\nBEGIN_OF_OUTPUT\n%sEND_OF_OUTPUT", format("%s %s", make_command, target).rstrip, output)) else msg = build_message(msg, - 'Expected make command "%s", but was "%s"' % [ - ("%s %s" % [make_command, target]).rstrip, - output, - ] - ) + format('Expected make command "%s", but was "%s"', format("%s %s", make_command, target).rstrip, output)) end assert scan_make_command_lines(output).any? {|line| @@ -310,20 +283,24 @@ class Gem::TestCase < Test::Unit::TestCase def setup @orig_hooks = {} @orig_env = ENV.to_hash - @tmp = File.expand_path("tmp") - FileUtils.mkdir_p @tmp + top_srcdir = __dir__ + "/../.." + @tmp = File.expand_path(ENV.fetch("GEM_TEST_TMPDIR", "tmp"), top_srcdir) + + FileUtils.mkdir_p(@tmp, mode: 0o700) # =rwx + @tmp = File.realpath(@tmp) @tempdir = Dir.mktmpdir("test_rubygems_", @tmp) - @tempdir.tap(&Gem::UNTAINT) ENV["GEM_VENDOR"] = nil ENV["GEMRC"] = nil ENV["XDG_CACHE_HOME"] = nil ENV["XDG_CONFIG_HOME"] = nil ENV["XDG_DATA_HOME"] = nil + ENV["XDG_STATE_HOME"] = nil ENV["SOURCE_DATE_EPOCH"] = nil ENV["BUNDLER_VERSION"] = nil + ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = "true" @current_dir = Dir.pwd @fetcher = nil @@ -334,15 +311,14 @@ class Gem::TestCase < Test::Unit::TestCase # capture output Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new - ENV["TMPDIR"] = @tempdir - - @orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE + @orig_system_wide_config_file = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE, File.join(@tempdir, "system-gemrc") @gemhome = File.join @tempdir, "gemhome" @userhome = File.join @tempdir, "userhome" + @statehome = File.join @tempdir, "statehome" ENV["GEM_SPEC_CACHE"] = File.join @tempdir, "spec_cache" @orig_ruby = if ENV["RUBY"] @@ -351,16 +327,19 @@ class Gem::TestCase < Test::Unit::TestCase ruby end - @git = ENV["GIT"] || (win_platform? ? "git.exe" : "git") + @git = ENV["GIT"] || "git#{RbConfig::CONFIG["EXEEXT"]}" Gem.ensure_gem_subdirectories @gemhome Gem.ensure_default_gem_subdirectories @gemhome - @orig_LOAD_PATH = $LOAD_PATH.dup + @orig_load_path = $LOAD_PATH.dup $LOAD_PATH.map! do |s| - expand_path = File.realpath(s) rescue File.expand_path(s) + expand_path = begin + File.realpath(s) + rescue StandardError + File.expand_path(s) + end if expand_path != s - expand_path.tap(&Gem::UNTAINT) if s.instance_variable_defined?(:@gem_prelude_index) expand_path.instance_variable_set(:@gem_prelude_index, expand_path) end @@ -373,10 +352,16 @@ class Gem::TestCase < Test::Unit::TestCase Dir.chdir @tempdir ENV["HOME"] = @userhome + # Remove "RUBY_CODESIGN", which is used by mkmf-generated Makefile to + # sign extension bundles on macOS, to avoid trying to find the specified key + # from the fake $HOME/Library/Keychains directory. + ENV.delete "RUBY_CODESIGN" Gem.instance_variable_set :@config_file, nil Gem.instance_variable_set :@user_home, nil Gem.instance_variable_set :@config_home, nil Gem.instance_variable_set :@data_home, nil + Gem.instance_variable_set :@state_home, @statehome + Gem.instance_variable_set :@state_file, nil Gem.instance_variable_set :@gemdeps, nil Gem.instance_variable_set :@env_requirements_by_name, nil Gem.send :remove_instance_variable, :@ruby_version if @@ -386,7 +371,7 @@ class Gem::TestCase < Test::Unit::TestCase ENV["GEM_PRIVATE_KEY_PASSPHRASE"] = PRIVATE_KEY_PASSPHRASE - Gem.instance_variable_set(:@default_specifications_dir, nil) + Gem.instance_variable_set(:@default_specifications_dir, File.join(@gemhome, "specifications", "default")) if Gem.java_platform? @orig_default_gem_home = RbConfig::CONFIG["default_gem_home"] RbConfig::CONFIG["default_gem_home"] = @gemhome @@ -411,7 +396,6 @@ class Gem::TestCase < Test::Unit::TestCase Gem.loaded_specs.clear Gem.instance_variable_set(:@activated_gem_paths, 0) Gem.clear_default_specs - Bundler.reset! Gem.configuration.verbose = true Gem.configuration.update_sources = true @@ -419,7 +403,7 @@ class Gem::TestCase < Test::Unit::TestCase Gem::RemoteFetcher.fetcher = Gem::FakeFetcher.new @gem_repo = "http://gems.example.com/" - @uri = URI.parse @gem_repo + @uri = Gem::URI.parse @gem_repo Gem.sources.replace [@gem_repo] Gem.searcher = nil @@ -427,7 +411,7 @@ class Gem::TestCase < Test::Unit::TestCase @orig_arch = RbConfig::CONFIG["arch"] - if win_platform? + if Gem.win_platform? util_set_arch "i386-mswin32" else util_set_arch "i686-darwin8.10.1" @@ -438,7 +422,7 @@ class Gem::TestCase < Test::Unit::TestCase end @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" - @orig_LOADED_FEATURES = $LOADED_FEATURES.dup + @orig_loaded_features = $LOADED_FEATURES.dup end ## @@ -446,14 +430,14 @@ class Gem::TestCase < Test::Unit::TestCase # tempdir def teardown - $LOAD_PATH.replace @orig_LOAD_PATH if @orig_LOAD_PATH - if @orig_LOADED_FEATURES - if @orig_LOAD_PATH - ($LOADED_FEATURES - @orig_LOADED_FEATURES).each do |feat| + $LOAD_PATH.replace @orig_load_path if @orig_load_path + if @orig_loaded_features + if @orig_load_path + ($LOADED_FEATURES - @orig_loaded_features).each do |feat| $LOADED_FEATURES.delete(feat) if feat.start_with?(@tmp) end else - $LOADED_FEATURES.replace @orig_LOADED_FEATURES + $LOADED_FEATURES.replace @orig_loaded_features end end @@ -465,13 +449,11 @@ class Gem::TestCase < Test::Unit::TestCase Dir.chdir @current_dir - FileUtils.rm_rf @tempdir - ENV.replace(@orig_env) Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE, - @orig_SYSTEM_WIDE_CONFIG_FILE + @orig_system_wide_config_file Gem.ruby = @orig_ruby if @orig_ruby @@ -487,20 +469,24 @@ class Gem::TestCase < Test::Unit::TestCase end Gem::Specification.unresolved_deps.clear - Gem::refresh + Gem.refresh @orig_hooks.each do |name, hooks| Gem.send(name).replace hooks end @back_ui.close + + FileUtils.rm_rf @tempdir + + refute_directory_exists @tempdir, "#{@tempdir} used by test #{method_name} is still in use" end def credential_setup @temp_cred = File.join(@userhome, ".gem", "credentials") FileUtils.mkdir_p File.dirname(@temp_cred) File.write @temp_cred, ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97" - File.chmod 0600, @temp_cred + File.chmod 0o600, @temp_cred end def credential_teardown @@ -548,6 +534,16 @@ class Gem::TestCase < Test::Unit::TestCase ENV["BUNDLE_GEMFILE"] = File.join(@tempdir, "Gemfile") end + def with_env(overrides, &block) + orig_env = ENV.to_h + ENV.replace(overrides) + begin + block.call + ensure + ENV.replace(orig_env) + end + end + ## # A git_gem is used with a gem dependencies file. The gem created here # has no files, just a gem specification for the given +name+ and +version+. @@ -583,10 +579,10 @@ class Gem::TestCase < Test::Unit::TestCase system @git, "add", gemspec system @git, "commit", "-a", "-m", "a non-empty commit message", "--quiet" - head = Gem::Util.popen(@git, "rev-parse", "master").strip + head = Gem::Util.popen(@git, "rev-parse", "HEAD").strip end - return name, git_spec.version, directory, head + [name, git_spec.version, directory, head] end ## @@ -599,7 +595,7 @@ class Gem::TestCase < Test::Unit::TestCase end def in_path?(executable) # :nodoc: - return true if %r{\A([A-Z]:|/)} =~ executable && File.exist?(executable) + return true if %r{\A([A-Z]:|/)}.match?(executable) && File.exist?(executable) ENV["PATH"].split(File::PATH_SEPARATOR).any? do |directory| File.exist? File.join directory, executable @@ -621,17 +617,17 @@ class Gem::TestCase < Test::Unit::TestCase end end - gem = File.join(@tempdir, File.basename(gem)).tap(&Gem::UNTAINT) + gem = File.join(@tempdir, File.basename(gem)) end - Gem::Installer.at(gem, options.merge({ :wrappers => true })).install + Gem::Installer.at(gem, options.merge({ wrappers: true })).install end ## # Builds and installs the Gem::Specification +spec+ into the user dir def install_gem_user(spec) - install_gem spec, :user_install => true + install_gem spec, user_install: true end ## @@ -643,7 +639,7 @@ class Gem::TestCase < Test::Unit::TestCase def ask_if_ok(spec) true end - end.new(spec.name, :executables => true, :user_install => true).uninstall + end.new(spec.name, executables: true, user_install: true).uninstall end ## @@ -660,7 +656,7 @@ class Gem::TestCase < Test::Unit::TestCase # Reads a Marshal file at +path+ def read_cache(path) - File.open path.dup.tap(&Gem::UNTAINT), "rb" do |io| + File.open path.dup, "rb" do |io| Marshal.load io.read end end @@ -702,11 +698,8 @@ class Gem::TestCase < Test::Unit::TestCase # Load a YAML file, the psych 3 way def load_yaml_file(file) - if Psych.respond_to?(:unsafe_load_file) - Psych.unsafe_load_file(file) - else - Psych.load_file(file) - end + require "rubygems/config_file" + Gem::ConfigFile.load_with_rubygems_config_hash(File.read(file)) end def all_spec_names @@ -747,7 +740,7 @@ class Gem::TestCase < Test::Unit::TestCase Gem::Specification.reset - return spec + spec end ## @@ -798,7 +791,7 @@ class Gem::TestCase < Test::Unit::TestCase def install_specs(*specs) specs.each do |spec| - Gem::Installer.for_spec(spec, :force => true).install + Gem::Installer.for_spec(spec, force: true).install end Gem.searcher = nil @@ -809,7 +802,7 @@ class Gem::TestCase < Test::Unit::TestCase def install_default_gems(*specs) specs.each do |spec| - installer = Gem::Installer.for_spec(spec, :install_as_default => true) + installer = Gem::Installer.for_spec(spec, install_as_default: true) installer.install Gem.register_default_spec(spec) end @@ -882,7 +875,7 @@ class Gem::TestCase < Test::Unit::TestCase FileUtils.rm spec.spec_file end - return spec + spec end ## @@ -949,7 +942,7 @@ class Gem::TestCase < Test::Unit::TestCase @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.date = Gem::Specification::TODAY - 86_400 s.homepage = "http://a.example.com" s.email = %w[example@example.com example2@example.com] s.authors = %w[Example Example2] @@ -992,15 +985,15 @@ Also, a list: util_build_gem @a2_pre end - write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) write_file File.join(*%W[gems #{@a_evil9.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@x.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@x.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb]) [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1, @x, @dep_x].each do |spec| util_build_gem spec @@ -1060,20 +1053,18 @@ Also, a list: spec_fetcher.prerelease_specs[@uri] << spec.name_tuple end - # HACK for test_download_to_cache + # HACK: for test_download_to_cache unless Gem::RemoteFetcher === @fetcher v = Gem.marshal_version - specs = all.map {|spec| spec.name_tuple } + specs = all.map(&:name_tuple) s_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic specs - latest_specs = latest.map do |spec| - spec.name_tuple - end + latest_specs = latest.map(&:name_tuple) l_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic latest_specs - prerelease_specs = prerelease.map {|spec| spec.name_tuple } + prerelease_specs = prerelease.map(&:name_tuple) p_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic prerelease_specs @fetcher.data["#{@gem_repo}specs.#{v}.gz"] = s_zip @@ -1109,12 +1100,12 @@ Also, a list: Gem.send :remove_instance_variable, :@ruby_version end - @RUBY_VERSION = RUBY_VERSION - @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) - @RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION) - @RUBY_DESCRIPTION = RUBY_DESCRIPTION - @RUBY_ENGINE = RUBY_ENGINE - @RUBY_ENGINE_VERSION = RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION) + @ruby_version = RUBY_VERSION + @ruby_patchlevel = RUBY_PATCHLEVEL + @ruby_revision = RUBY_REVISION + @ruby_description = RUBY_DESCRIPTION + @ruby_engine = RUBY_ENGINE + @ruby_engine_version = RUBY_ENGINE_VERSION util_clear_RUBY_VERSION @@ -1123,58 +1114,27 @@ Also, a list: Object.const_set :RUBY_REVISION, revision Object.const_set :RUBY_DESCRIPTION, description Object.const_set :RUBY_ENGINE, engine - Object.const_set :RUBY_ENGINE_VERSION, engine_version if engine_version + Object.const_set :RUBY_ENGINE_VERSION, engine_version end def util_restore_RUBY_VERSION util_clear_RUBY_VERSION - Object.const_set :RUBY_VERSION, @RUBY_VERSION - Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if - defined?(@RUBY_PATCHLEVEL) - Object.const_set :RUBY_REVISION, @RUBY_REVISION if - defined?(@RUBY_REVISION) - Object.const_set :RUBY_DESCRIPTION, @RUBY_DESCRIPTION - Object.const_set :RUBY_ENGINE, @RUBY_ENGINE - Object.const_set :RUBY_ENGINE_VERSION, @RUBY_ENGINE_VERSION if - defined?(@RUBY_ENGINE_VERSION) + Object.const_set :RUBY_VERSION, @ruby_version + Object.const_set :RUBY_PATCHLEVEL, @ruby_patchlevel + Object.const_set :RUBY_REVISION, @ruby_revision + Object.const_set :RUBY_DESCRIPTION, @ruby_description + Object.const_set :RUBY_ENGINE, @ruby_engine + Object.const_set :RUBY_ENGINE_VERSION, @ruby_engine_version end def util_clear_RUBY_VERSION Object.send :remove_const, :RUBY_VERSION - Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) - Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) - Object.send :remove_const, :RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION) + Object.send :remove_const, :RUBY_PATCHLEVEL + Object.send :remove_const, :RUBY_REVISION + Object.send :remove_const, :RUBY_DESCRIPTION Object.send :remove_const, :RUBY_ENGINE - Object.send :remove_const, :RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION) - end - - ## - # Is this test being run on a Windows platform? - - def self.win_platform? - Gem.win_platform? - end - - ## - # Is this test being run on a Windows platform? - - def win_platform? - Gem.win_platform? - end - - ## - # Is this test being run on a Java platform? - - def self.java_platform? - Gem.java_platform? - end - - ## - # Is this test being run on a Java platform? - - def java_platform? - Gem.java_platform? + Object.send :remove_const, :RUBY_ENGINE_VERSION end ## @@ -1186,28 +1146,25 @@ Also, a list: end ## - # Returns whether or not we're on a version of Ruby built with VC++ (or - # Borland) versus Cygwin, Mingw, etc. + # see ::vc_windows? def vc_windows? - RUBY_PLATFORM.match("mswin") + self.class.vc_windows? end ## - # Is this test being run on a ruby/ruby repository? - # + # Is this test being run on a version of Ruby built with mingw? - def ruby_repo? - !ENV["GEM_COMMAND"].nil? + def mingw_windows? + RUBY_PLATFORM.match("mingw") 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'. + # Is this test being run on a ruby/ruby repository? + # - def self.make_command - ENV["make"] || ENV["MAKE"] || (vc_windows? ? "nmake" : "make") + def ruby_repo? + !ENV["GEM_COMMAND"].nil? end ## @@ -1235,22 +1192,6 @@ Also, a list: end ## - # Allows 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 - - ## - # See ::process_based_port - - def process_based_port - self.class.process_based_port - end - - ## # Allows the proper version of +rake+ to be used for the test. def build_rake_in(good=true) @@ -1276,7 +1217,7 @@ Also, a list: ruby = ENV["RUBY"] return ruby if ruby ruby = "ruby" - rubyexe = "#{ruby}.exe" + rubyexe = "#{ruby}#{RbConfig::CONFIG["EXEEXT"]}" 3.times do if File.exist?(ruby) && File.executable?(ruby) && !File.directory?(ruby) @@ -1303,6 +1244,10 @@ Also, a list: $LOAD_PATH.find {|p| p == File.dirname($LOADED_FEATURES.find {|f| f.end_with?("/rubygems.rb") }) } end + def bundler_path + $LOAD_PATH.find {|p| p == File.dirname($LOADED_FEATURES.find {|f| f.end_with?("/bundler.rb") }) } + end + def with_clean_path_to_ruby orig_ruby = Gem.ruby @@ -1323,32 +1268,29 @@ Also, a list: end def silence_warnings - old_verbose, $VERBOSE = $VERBOSE, false + old_verbose = $VERBOSE + $VERBOSE = false yield ensure $VERBOSE = old_verbose end - class << self - # :nodoc: - ## - # Return the join path, with escaping backticks, dollars, and - # double-quotes. Unlike `shellescape`, equal-sign is not escaped. - - private + # :nodoc: + ## + # Return the join path, with escaping backticks, dollars, and + # double-quotes. Unlike `shellescape`, equal-sign is not escaped. - def escape_path(*path) - path = File.join(*path) - if %r{\A[-+:/=@,.\w]+\z} =~ path - path - else - "\"#{path.gsub(/[`$"]/, '\\&')}\"" - end + def self.escape_path(*path) + path = File.join(*path) + if %r{\A[-+:/=@,.\w]+\z}.match?(path) + path + else + "\"#{path.gsub(/[`$"]/, '\\&')}\"" end end - @@good_rake = "#{rubybin} #{escape_path(__dir__, 'good_rake.rb')}" - @@bad_rake = "#{rubybin} #{escape_path(__dir__, 'bad_rake.rb')}" + @@good_rake = "#{rubybin} #{escape_path(__dir__, "good_rake.rb")}" + @@bad_rake = "#{rubybin} #{escape_path(__dir__, "bad_rake.rb")}" ## # Construct a new Gem::Dependency. @@ -1431,12 +1373,12 @@ Also, a list: # # Yields the +specification+ to the block, if given - def vendor_gem(name = "a", version = 1) + def vendor_gem(name = "a", version = 1, &block) directory = File.join "vendor", name FileUtils.mkdir_p directory - save_gemspec name, version, directory + save_gemspec name, version, directory, &block end ## @@ -1454,7 +1396,7 @@ Also, a list: io.write vendor_spec.to_ruby end - return name, vendor_spec.version, directory + [name, vendor_spec.version, directory] end ## @@ -1534,7 +1476,11 @@ Also, a list: # <tt>test/rubygems/</tt>. def self.cert_path(cert_name) - if 32 == (Time.at(2**32) rescue 32) + if begin + Time.at(2**32) + rescue StandardError + 32 + end == 32 cert_file = "#{__dir__}/#{cert_name}_cert_32.pem" return cert_file if File.exist? cert_file @@ -1564,7 +1510,7 @@ Also, a list: # :stopdoc: # only available in RubyGems tests - PRIVATE_KEY_PASSPHRASE = "Foo bar".freeze + PRIVATE_KEY_PASSPHRASE = "Foo bar" begin PRIVATE_KEY = load_key "private" @@ -1604,7 +1550,7 @@ class Object if val_or_callable.respond_to? :call val_or_callable.call(*args, &blk) else - blk.call(*block_args) if blk + blk&.call(*block_args) val_or_callable end end diff --git a/test/rubygems/installer_test_case.rb b/test/rubygems/installer_test_case.rb index 6211cfff16..abddcbe848 100644 --- a/test/rubygems/installer_test_case.rb +++ b/test/rubygems/installer_test_case.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/installer" @@ -110,7 +111,7 @@ class Gem::InstallerTestCase < Gem::TestCase def setup_base_installer(force = true) @gem = setup_base_gem - util_installer @spec, @gemhome, false, force + util_installer @spec, @gemhome, force end ## @@ -162,7 +163,7 @@ class Gem::InstallerTestCase < Gem::TestCase @user_gem = @user_spec.cache_file - util_installer @user_spec, Gem.user_dir, :user + Gem::Installer.at @user_gem, user_install: true end ## @@ -214,18 +215,16 @@ class Gem::InstallerTestCase < Gem::TestCase end end - Gem::Installer.at @gem, :force => force + Gem::Installer.at @gem, force: force end ## - # Creates an installer for +spec+ that will install into +gem_home+. If - # +user+ is true a user-install will be performed. + # Creates an installer for +spec+ that will install into +gem_home+. - def util_installer(spec, gem_home, user=false, force=true) + def util_installer(spec, gem_home, force=true) Gem::Installer.at(spec.cache_file, - :install_dir => gem_home, - :user_install => user, - :force => force) + install_dir: gem_home, + force: force) end @@symlink_supported = nil diff --git a/test/rubygems/invalid_issuer_cert.pem b/test/rubygems/invalid_issuer_cert.pem index ea11756bb0..5cb9d22a87 100644 --- a/test/rubygems/invalid_issuer_cert.pem +++ b/test/rubygems/invalid_issuer_cert.pem @@ -1,20 +1,20 @@ -----BEGIN CERTIFICATE----- -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 +vpqxaQ== -----END CERTIFICATE----- diff --git a/test/rubygems/invalid_issuer_cert_32.pem b/test/rubygems/invalid_issuer_cert_32.pem index bb73772735..2b71179270 100644 --- a/test/rubygems/invalid_issuer_cert_32.pem +++ b/test/rubygems/invalid_issuer_cert_32.pem @@ -1,20 +1,20 @@ -----BEGIN CERTIFICATE----- -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 +Wkw= -----END CERTIFICATE----- diff --git a/test/rubygems/invalid_key.pem b/test/rubygems/invalid_key.pem index 74bedabcda..bc02147403 100644 --- a/test/rubygems/invalid_key.pem +++ b/test/rubygems/invalid_key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/test/rubygems/invalid_signer_cert.pem b/test/rubygems/invalid_signer_cert.pem index 7f8b5cc727..59364ee51b 100644 --- a/test/rubygems/invalid_signer_cert.pem +++ b/test/rubygems/invalid_signer_cert.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDEDCCAfigAwIBAgIBDjANBgkqhkiG9w0BAQUFADArMRAwDgYDVQQDDAdpbnZh +MIIDEDCCAfigAwIBAgIBDjANBgkqhkiG9w0BAQsFADArMRAwDgYDVQQDDAdpbnZh bGlkMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTAgFw0xMjAxMDEwMDAwMDBaGA85 OTk5MTIzMTIzNTk1OVowKzEQMA4GA1UEAwwHaW52YWxpZDEXMBUGCgmSJomT8ixk -ARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNMnDk -oUjigxoQ5T2d/iQFsKeygdqbP1ZS4SLGZdLgB8wgBjzSNSOOoJpWtYOxoeNvX2Hi -dFYHkU8SP60VjSdB19iPY4WiagJIjqleUZOkZCb/9JVNVUrtSAYykZleql4jXgVg -PHbhDzXXesyl+1KCnGIJhtwTA7hMuuwKllIGTo3PVlJ3eovpsFnIjLjarpevbzLw -eYKOHP64LadWNz4SwyK4XmD/bPgc2tTDadBVBZaz5y+YM2U7D/yF9ru5BdwhISgm -V2T19KGXP6W6iEtjrkPU+n7ekrUsAPvSIQMgnifWxsgWCu/EsoknxCyshim5O+Ep -kQKo6TdjyV96P4JPAgMBAAGjPTA7MBoGA1UdEQQTMBGBD2ludmFsaWRAZXhhbXBs -ZTAdBgNVHQ4EFgQUk9+Lsaj37L/MP/nHPYBAoVp52U4wDQYJKoZIhvcNAQEFBQAD -ggEBAGJurQiRw3Vb2LPUhoL9BHyPy8TY+ZXz7eZyzf72saiATkHTuainb9jvLTzf -9ZNYNnjxGNwR4QnDhlh8Vb8vHaYfQGGwiLhd5ZbKjkid/41Y9XmNh+oHCrmwGcS6 -vX4QmTTmPQRBZ2Ilckr+wb1fdpLYk0wW/JFMFdAzp1OO3kP23hYElqia6qeJGw4k -4fe9d56huHHptSJrlMTjHwaqXq6QRjfjF5Za1unCjxQMO2vNQC/dUYRaq/M0kwFN -6A2xHKukkgA9cyjVpFVpxhE3/iFz8OE1GZg7VVcT+Jzhhxaajubpe+ZtDN5rbln/ -NI4WP/ZM3cnxVrHG84G3AYRpkhc= +ARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDxGWcy +HctJtY0m3BwcFHNDC6av/iSXcC6Rq4w9+QriOwzT9DIh/pjR25ck6jGnQd36J7du +pEBSIw2bXNXrNWb7eJjaNZUnELL21RkRQ0Ctv8XWdDtBmyt9QuyCdgaGvdxfu+H+ +zXg+iyp/vklgsRzQilfN0bpkOnYhv1nVGULvJPcY6UcsCNrthMDQxE5G4Rmpo+cz +Y+2vKXD8onwcc04mfRWb1lWghDg73SKxeDXSLXl8mBEMA0S1g/50PWfcG8OCkArQ +P1FHfqzm6HI73mrtcC4ma8rpoWUcMCCmVOPmmgDWExW97W5lCp6EfWi2ryr8RJ5R +dOZB6PcXB6EuX7cPAgMBAAGjPTA7MBoGA1UdEQQTMBGBD2ludmFsaWRAZXhhbXBs +ZTAdBgNVHQ4EFgQUde3TNs2UED6K/5OjePyV3q1l4UgwDQYJKoZIhvcNAQELBQAD +ggEBACbQA7m+zqdAE1/GrJKcXnC/Ujr1tu6rGpe0uExTwySptgVieUGAOvzlLLrY +r2b/nGmK4bgHkeDPSVuC3F8NhgESvPTuXFSw+DU+1m+mhHxdpW30uSbbebgqV5Ea +GpckCZj1SEdsn/1SDauXCmkrs/MBuK49mYXv3jejX0Rp0STu1NxnU13yrKF0MtrL +fzZ/QF8bOZdg5DwtqMwhDPp72x58KpqAPN9GgdlsTiwOMGy4avds1g5KMGmkK8pK +6I58NEMCOuN4CxFK4oWD9xuD4j+wtHy/UYxqor4rn+UKYHfr5fWtAyRJ3gD8vMUu +C+Nl2vB8t4OVwS5FCcn0ZK18bPU= -----END CERTIFICATE----- diff --git a/test/rubygems/invalid_signer_cert_32.pem b/test/rubygems/invalid_signer_cert_32.pem index 657608e503..97feb8fd0a 100644 --- a/test/rubygems/invalid_signer_cert_32.pem +++ b/test/rubygems/invalid_signer_cert_32.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDDjCCAfagAwIBAgIBDzANBgkqhkiG9w0BAQUFADArMRAwDgYDVQQDDAdpbnZh +MIIDDjCCAfagAwIBAgIBDzANBgkqhkiG9w0BAQsFADArMRAwDgYDVQQDDAdpbnZh bGlkMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTAeFw0xMjAxMDEwMDAwMDBaFw0z ODAxMTkwMzE0MDdaMCsxEDAOBgNVBAMMB2ludmFsaWQxFzAVBgoJkiaJk/IsZAEZ -FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzTJw5KFI -4oMaEOU9nf4kBbCnsoHamz9WUuEixmXS4AfMIAY80jUjjqCaVrWDsaHjb19h4nRW -B5FPEj+tFY0nQdfYj2OFomoCSI6pXlGTpGQm//SVTVVK7UgGMpGZXqpeI14FYDx2 -4Q8113rMpftSgpxiCYbcEwO4TLrsCpZSBk6Nz1ZSd3qL6bBZyIy42q6Xr28y8HmC -jhz+uC2nVjc+EsMiuF5g/2z4HNrUw2nQVQWWs+cvmDNlOw/8hfa7uQXcISEoJldk -9fShlz+luohLY65D1Pp+3pK1LAD70iEDIJ4n1sbIFgrvxLKJJ8QsrIYpuTvhKZEC -qOk3Y8lfej+CTwIDAQABoz0wOzAaBgNVHREEEzARgQ9pbnZhbGlkQGV4YW1wbGUw -HQYDVR0OBBYEFJPfi7Go9+y/zD/5xz2AQKFaedlOMA0GCSqGSIb3DQEBBQUAA4IB -AQA6WW6YyykIJmVFW8Og1R3d8fbFtQarDMGN+oZrCN3Eb9Twoy36Yr/h0bZgkCEe -arB+VCD1DfEii5luZowUDr/BlIjIR2cNIMFpmQ8ZLIpVWQz/BYHrbw7CHO5df3mg -HYTKlEoUMimOEWvCYnSgzKWCgSWU/jBQQ0bcUBk2HHpdT4BnLPe/7rs+TZmwd/Dz -r80sNXQ6vqTkQS+te2hqyh62r+WeaFx7aqnFjGtwiOqMmYPr80uYOy/rX26mmfwm -vyf8JlA4uTt795Krsc4Brc+BO0bOPfDDGhRs/2tvyHhOOqBbUxQeeV5ogiAZmA31 -ZrzbFysajMrWZ+1GV8QXOcBi +FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8RlnMh3L +SbWNJtwcHBRzQwumr/4kl3AukauMPfkK4jsM0/QyIf6Y0duXJOoxp0Hd+ie3bqRA +UiMNm1zV6zVm+3iY2jWVJxCy9tUZEUNArb/F1nQ7QZsrfULsgnYGhr3cX7vh/s14 +Posqf75JYLEc0IpXzdG6ZDp2Ib9Z1RlC7yT3GOlHLAja7YTA0MRORuEZqaPnM2Pt +rylw/KJ8HHNOJn0Vm9ZVoIQ4O90isXg10i15fJgRDANEtYP+dD1n3BvDgpAK0D9R +R36s5uhyO95q7XAuJmvK6aFlHDAgplTj5poA1hMVve1uZQqehH1otq8q/ESeUXTm +Qej3FwehLl+3DwIDAQABoz0wOzAaBgNVHREEEzARgQ9pbnZhbGlkQGV4YW1wbGUw +HQYDVR0OBBYEFHXt0zbNlBA+iv+To3j8ld6tZeFIMA0GCSqGSIb3DQEBCwUAA4IB +AQBM/EjV791vKu2KQQAhd03eUXfMlvObwEj9nGtEEnSFH5i16V1m8Y5ZY7Aw+VR5 +/xJ9J2AvFG6EXclDVmkDQpo1fUVhWM/SPKD6HJWuB/eyjA30xSj+UeLmBYjdKzHt +kK+HeEaGVQaT5j8OPOW6meGriucdBWtwbhTdyZgqvwpuZwbtPpElYXwGgSijKqHI +GG6RWzeANdG/4AIChrp8CIgFfW4sbmlIZK3BAXuSvZ9A/deYqC2DAadJIoTJ9H6w +0TgYlyTidaWtCkqRBXc3qrwpc/r3wJwpgan0kJAQ2kGc5W7gYUylpoS56sFq23YX +Fmm0pRq5UZj9jKZUIwcqAoGo -----END CERTIFICATE----- diff --git a/test/rubygems/invalidchild_cert.pem b/test/rubygems/invalidchild_cert.pem index 936dc650c9..281dcce655 100644 --- a/test/rubygems/invalidchild_cert.pem +++ b/test/rubygems/invalidchild_cert.pem @@ -1,20 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDOTCCAiGgAwIBAgIBEDANBgkqhkiG9w0BAQUFADApMQ4wDAYDVQQDDAVjaGls +MIIDGDCCAgCgAwIBAgIBEDANBgkqhkiG9w0BAQsFADApMQ4wDAYDVQQDDAVjaGls ZDEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUwIBcNMTIwMTAxMDAwMDAwWhgPOTk5 OTEyMzEyMzU5NTlaMDAxFTATBgNVBAMMDGludmFsaWRjaGlsZDEXMBUGCgmSJomT -8ixkARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDl -rDAlDZwmP6Zxc4sSaOdSRRXJBmbQubxmWpqU8bXrTKCkvg1l/2U6weJIS52zW6Te -Zok7Uus5jywyeNSJ/MBHb7X5ytAPQsvLu/3WFwaVfHJzimQI4vtmx9+CDgZzipYp -ett7IF18He8DPiFur1xCn8pp0qOOV8mXL/8TpUgJfmaOJosqgFqorj5niqF52IwJ -vtur/gwpq2xpCtYaCUB/dFzzefLV37kt58S6jTmZnYf4kIdFKhhyTeGmDRf/wOz+ -kK/H/aKtpsYgzI//bo+bsuWNFceIdWrdCBr63cVs4ql7VN7p2xfn9ckEfwH6wFut -QLquA/6fRkgUFF8fxUiHAgMBAAGjYzBhMB8GA1UdEQQYMBaBFGludmFsaWRjaGls -ZEBleGFtcGxlMB0GA1UdDgQWBBSwAwFqdxjicsovAzZ1ZeSAWlnKcDAfBgNVHSME -GDAWgBR81VPTe7JJSgT6xxJcaGd9hYOuCDANBgkqhkiG9w0BAQUFAAOCAQEAYxom -7nHgbfqLiMtVwx8D6LM6P3sk3p5HwoHJU0zzFVfPA0iuhhC2vWyPoHJroq6d31DG -DpPpOeVQxTYyQ6CtD6jGUpE+0MjmRoavFnvqFH5lf4OKO0dQ8xUa9fALo7fmK0v0 -ueDlgsHw3mwoVNX2Xu/+jCTuiK2KGG3J+pxr6JNA1++gQEghFFJjM8rw1/mYrDW0 -CSCyx/LeNyYbt9xzeVgo83XNO5TCfwwh8+df52I6Hj5BDFhhkP8KOai4ejq2CmZ8 -by9ylCUXc/aiz9mzX/NzIAYLuRzkmrI+lxDbUJpG/hV7MCS/TZegjD+SUSu9EI1O -RVerg89R7kQUWZyJqg== +8ixkARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDs +dqLesclj2/6HnJLw4al4swiDFBA4W0KeOS3DXOa2k5+rNfGacKOQ/AkciUnzqLiC +9D49x/YLlnlJYeSMG57C7gixhLHHDviCneQwy8TlCpuhUXnfcpmHQO+X/c+lrVB7 +wHTPjl5yZYzLFtPa8QAEtJa83E2GrUd+JEOwTRErOcBucIRP5HbeR2aD7BVP1V+F +gaUhOZb/n2e53diQF7BZurB45DTWQ2L1R/m8VldQiWoTZluWqnCGeEwtpZJXt9kU +8y5rQcxI3p8Qx4q0ilLKsE7c/sw2wzEFWoZ4BeURnjxdvPgYeOPk4K3a34pFg7lZ +u1s9XvjChJVsD8HRnbQtAgMBAAGjQjBAMB8GA1UdEQQYMBaBFGludmFsaWRjaGls +ZEBleGFtcGxlMB0GA1UdDgQWBBS3tDKiI1oVuEkKtGux8TsEy/8iuDANBgkqhkiG +9w0BAQsFAAOCAQEAQsgdq4NZBnQRk+eNbwS4go3S+m5cPPWY7kG94kpQ3aC3nwR4 +wnICb/hd+kRCB2azTTBY8PA0SkHxIXWgRFjdEpIAekm3Xtag+lCC1q7jtDTNoHw4 +KOdfeBEF621FHL5vBvJmnRMH8f4sCjVZZE8RJcaWAK7uJJXi6gzUm3xz0UnylZNr +vA+Z+cM5pFnCfxxqXUyT0MRb47O/wqH4f5SybKpOxO3+vnzpSeN++zgdMVjA/Pl0 +0SB8VKNKXGLQrvY2S3GuRoh7OD1DhRPzUTQ8gwwBAlhw2i3i5t9ib0ujw9MUO3GR +dqn4Yco98R0+wFpY8feGhr5uJNDuIC10l5LHLQ== -----END CERTIFICATE----- diff --git a/test/rubygems/invalidchild_cert_32.pem b/test/rubygems/invalidchild_cert_32.pem index 07687eb156..87885157f8 100644 --- a/test/rubygems/invalidchild_cert_32.pem +++ b/test/rubygems/invalidchild_cert_32.pem @@ -1,20 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDNzCCAh+gAwIBAgIBETANBgkqhkiG9w0BAQUFADApMQ4wDAYDVQQDDAVjaGls +MIIDFjCCAf6gAwIBAgIBETANBgkqhkiG9w0BAQsFADApMQ4wDAYDVQQDDAVjaGls ZDEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUwHhcNMTIwMTAxMDAwMDAwWhcNMzgw MTE5MDMxNDA3WjAwMRUwEwYDVQQDDAxpbnZhbGlkY2hpbGQxFzAVBgoJkiaJk/Is -ZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5aww -JQ2cJj+mcXOLEmjnUkUVyQZm0Lm8ZlqalPG160ygpL4NZf9lOsHiSEuds1uk3maJ -O1LrOY8sMnjUifzAR2+1+crQD0LLy7v91hcGlXxyc4pkCOL7Zsffgg4Gc4qWKXrb -eyBdfB3vAz4hbq9cQp/KadKjjlfJly//E6VICX5mjiaLKoBaqK4+Z4qhediMCb7b -q/4MKatsaQrWGglAf3Rc83ny1d+5LefEuo05mZ2H+JCHRSoYck3hpg0X/8Ds/pCv -x/2irabGIMyP/26Pm7LljRXHiHVq3Qga+t3FbOKpe1Te6dsX5/XJBH8B+sBbrUC6 -rgP+n0ZIFBRfH8VIhwIDAQABo2MwYTAfBgNVHREEGDAWgRRpbnZhbGlkY2hpbGRA -ZXhhbXBsZTAdBgNVHQ4EFgQUsAMBancY4nLKLwM2dWXkgFpZynAwHwYDVR0jBBgw -FoAUfNVT03uySUoE+scSXGhnfYWDrggwDQYJKoZIhvcNAQEFBQADggEBAGK07MzH -/TJftVEgrghvEHIna0gadQUbWfrpMWxt/Vj7jsd4LvRaZEOWObMRxhtjMvMA2q3A -qKXoP1KddPkFGfAVdUsNKTKLsaMvDceZ7aN3SGEWv5IYGXtfjUEVhWj7CmpS05li -Phw9uPQVUwkkY20G2UGInRzxCYqyeW5KZIaep49KebaXCrjrV5Xy13UxgtpbmNMj -yKPvyA5u0J8TK4gQmx1Az0gujpT1KSwfMyEDrsbIqYDVMp4kF2yLlsrdmNT9Jhwj -R+M6AMhNqpLrjsklqE6TX2pCQGo+JFxCDOKQmvv5B7AhH0od46Jlwk//aIAheQQK -4rhDHEHYLCxGhrw= +ZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7Hai +3rHJY9v+h5yS8OGpeLMIgxQQOFtCnjktw1zmtpOfqzXxmnCjkPwJHIlJ86i4gvQ+ +Pcf2C5Z5SWHkjBuewu4IsYSxxw74gp3kMMvE5QqboVF533KZh0Dvl/3Ppa1Qe8B0 +z45ecmWMyxbT2vEABLSWvNxNhq1HfiRDsE0RKznAbnCET+R23kdmg+wVT9VfhYGl +ITmW/59nud3YkBewWbqweOQ01kNi9Uf5vFZXUIlqE2ZblqpwhnhMLaWSV7fZFPMu +a0HMSN6fEMeKtIpSyrBO3P7MNsMxBVqGeAXlEZ48Xbz4GHjj5OCt2t+KRYO5Wbtb +PV74woSVbA/B0Z20LQIDAQABo0IwQDAfBgNVHREEGDAWgRRpbnZhbGlkY2hpbGRA +ZXhhbXBsZTAdBgNVHQ4EFgQUt7QyoiNaFbhJCrRrsfE7BMv/IrgwDQYJKoZIhvcN +AQELBQADggEBAFPyjOoghY6Iba9+psCWC//rwLtDfZPQ3kO9hFtd4CGvalPtR103 +Oc1Dk5pxHSWDTdeQfOb75mqWuqs4ET7IUyw8yY+bKkOOhY1ldwaJhTyP/fkElnrL +prsLSpB3AdQceS1Ob2wpMaaGIPDzJlW0LG8cQNeU3SRTTdBjX5zjG6imHKG2yuJd +76PM0tl8ooslPABlYSPSLpd1PAARqxG2ekfrxZioCLknyhBtcRsl1aMWWBiG4BH9 +xZoJvEHwpOMTxMaAFXSkyMjZAoOzAn9qP6eLbwwzeuckIrZXxYBfGcC29VOPPAN4 +IPX0IUZ7/LlzzOE5iuVS/RIBRcD+qpEzSXs= -----END CERTIFICATE----- diff --git a/test/rubygems/invalidchild_key.pem b/test/rubygems/invalidchild_key.pem index 9706c9566e..1c9997150d 100644 --- a/test/rubygems/invalidchild_key.pem +++ b/test/rubygems/invalidchild_key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/test/rubygems/mock_gem_ui.rb b/test/rubygems/mock_gem_ui.rb new file mode 100644 index 0000000000..1ece78fde7 --- /dev/null +++ b/test/rubygems/mock_gem_ui.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +require "rubygems/user_interaction" + +## +# This Gem::StreamUI subclass records input and output to StringIO for +# retrieval during tests. + +class Gem::MockGemUi < Gem::StreamUI + ## + # Raised when you haven't provided enough input to your MockGemUi + + class InputEOFError < RuntimeError + def initialize(question) + super "Out of input for MockGemUi on #{question.inspect}" + end + end + + class TermError < RuntimeError + attr_reader :exit_code + + def initialize(exit_code) + super + @exit_code = exit_code + end + end + + class SystemExitException < RuntimeError; end + + module TTY + attr_accessor :tty + + def tty? + @tty = true unless defined?(@tty) + @tty + end + + def noecho + yield self + end + end + + def initialize(input = "") + require "stringio" + ins = StringIO.new input + outs = StringIO.new + errs = StringIO.new + + ins.extend TTY + outs.extend TTY + errs.extend TTY + + super ins, outs, errs, true + + @terminated = false + end + + def ask(question) + raise InputEOFError, question if @ins.eof? + + super + end + + def input + @ins.string + end + + def output + @outs.string + end + + def error + @errs.string + end + + def terminated? + @terminated + end + + def terminate_interaction(status=0) + @terminated = true + + raise TermError, status if status != 0 + raise SystemExitException + end +end diff --git a/test/rubygems/multifactor_auth_utilities.rb b/test/rubygems/multifactor_auth_utilities.rb new file mode 100644 index 0000000000..1133131a76 --- /dev/null +++ b/test/rubygems/multifactor_auth_utilities.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +## +# A MultifactorAuthFetcher is a FakeFetcher that adds paths to data for requests related to +# multi-factor authentication. +# + +require_relative "utilities" +require "json" + +class Gem::MultifactorAuthFetcher < Gem::FakeFetcher + attr_reader :host, :webauthn_url + + # GET /api/v1/webauthn_verification defaults to user does not have any security devices + def initialize(host: nil) + super() + @host = host || Gem.host + @path_token = "odow34b93t6aPCdY" + @webauthn_url = "#{@host}/webauthn_verification/#{@path_token}" + @data["#{@host}/api/v1/webauthn_verification"] = Gem::HTTPResponseFactory.create( + body: "You don't have any security devices", + code: 422, + msg: "Unprocessable Entity" + ) + end + + # given a url, return a response that requires multifactor authentication + def respond_with_require_otp(url, success_body) + response_fail = "You have enabled multifactor authentication" + + @data[url] = proc do + @call_count ||= 0 + if (@call_count += 1).odd? + Gem::HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized") + else + Gem::HTTPResponseFactory.create(body: success_body, code: 200, msg: "OK") + end + end + end + + # GET /api/v1/webauthn_verification returns a webauthn url + # GET /api/v1/webauthn_verification/:token/status.json (polling url) returns pending status + def respond_with_webauthn_url + @data["#{@host}/api/v1/webauthn_verification"] = Gem::HTTPResponseFactory.create(body: @webauthn_url, code: 200, msg: "OK") + @data["#{@host}/api/v1/webauthn_verification/#{@path_token}/status.json"] = Gem::HTTPResponseFactory.create( + body: { status: "pending", message: "Security device authentication is still pending." }.to_json, + code: 200, + msg: "OK" + ) + end + + # GET /api/v1/webauthn_verification/:token/status.json returns success status with OTP code + def respond_with_webauthn_polling(code) + @data["#{@host}/api/v1/webauthn_verification/#{@path_token}/status.json"] = Gem::HTTPResponseFactory.create( + body: { status: "success", code: code }.to_json, + code: 200, + msg: "OK" + ) + end + + # GET /api/v1/webauthn_verification/:token/status.json returns expired status + def respond_with_webauthn_polling_failure + @data["#{@host}/api/v1/webauthn_verification/#{@path_token}/status.json"] = Gem::HTTPResponseFactory.create( + body: { + status: "expired", + message: "The token in the link you used has either expired or been used already.", + }.to_json, + code: 200, + msg: "OK" + ) + end + + def webauthn_url_with_port(port) + "#{@webauthn_url}?port=#{port}" + end +end + +## +# The MockTCPServer for use in tests or to avoid real TCPServer instances to be created +# when testing code related to the WebAuthn listener. +# +# Example: +# +# server = Gem::MockTCPServer +# port = server.addr[1].to_s +# +# # this mocks waiting for a request by calling sleep +# server.accept +# +# # this mocks the server closing +# server.close + +class Gem::MockTCPServer + attr_reader :port + + def initialize(port = 5678) + @port = port + end + + def close + true + end + + def addr + ["AF_INET6", @port, "::", "::"] + end + + def accept + sleep + end +end diff --git a/test/rubygems/package/tar_test_case.rb b/test/rubygems/package/tar_test_case.rb index 6cee7f86dc..e3d812bf3f 100644 --- a/test/rubygems/package/tar_test_case.rb +++ b/test/rubygems/package/tar_test_case.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "../helper" require "rubygems/package" @@ -67,7 +68,7 @@ class Gem::Package::TarTestCase < Gem::TestCase end def calc_checksum(header) - sum = header.unpack("C*").inject {|s,a| s + a } + sum = header.sum(0) SP(Z(to_oct(sum, 6))) end @@ -90,43 +91,52 @@ class Gem::Package::TarTestCase < Gem::TestCase ASCIIZ("wheel", 32), # char gname[32]; ASCIIZ Z(to_oct(0, 7)), # char devmajor[8]; 0 padded, octal, null Z(to_oct(0, 7)), # char devminor[8]; 0 padded, octal, null - ASCIIZ(dname, 155), # char prefix[155]; ASCII + (Z unless filled) + ASCIIZ(dname, 155), # char prefix[155]; ASCII + (Z unless filled) ] h = arr.join - ret = h + "\0" * (512 - h.size) + ret = ASCIIZ(h, 512) assert_equal(512, ret.size) ret end - def tar_dir_header(name, prefix, mode, mtime) - h = header("5", name, prefix, 0, mode, mtime) + def header_with_checksum(type, fname, dname, length, mode, mtime, linkname = "") + h = header(type, fname, dname, length, mode, mtime, nil, linkname) checksum = calc_checksum(h) - header("5", name, prefix, 0, mode, mtime, checksum) + header(type, fname, dname, length, mode, mtime, checksum, linkname) + end + + def tar_dir_header(name, prefix, mode, mtime) + header_with_checksum("5", name, prefix, 0, mode, mtime) end def tar_file_header(fname, dname, mode, length, mtime) - h = header("0", fname, dname, length, mode, mtime) - checksum = calc_checksum(h) - header("0", fname, dname, length, mode, mtime, checksum) + header_with_checksum("0", fname, dname, length, mode, mtime) end - def tar_symlink_header(fname, prefix, mode, mtime, linkname) - h = header("2", fname, prefix, 0, mode, mtime, nil, linkname) - checksum = calc_checksum(h) - header("2", fname, prefix, 0, mode, mtime, checksum, linkname) + def tar_symlink_header(fname, dname, mode, mtime, linkname) + header_with_checksum("2", fname, dname, 0, mode, mtime, linkname) + end + + def tar_file_contents(content) + pad = (512 - (content.size % 512)) % 512 + content + "\0" * pad end def to_oct(n, pad_size) - "%0#{pad_size}o" % n + format("%0#{pad_size}o", n) end def util_entry(tar) - io = TempIO.new tar + io = tar.respond_to?(:read) ? tar : TempIO.new(tar) header = Gem::Package::TarHeader.from io - Gem::Package::TarReader::Entry.new header, io + Gem::Package::TarReader::Entry.open header, io + end + + def close_util_entry(entry) + entry.instance_variable_get(:@io).close! end def util_dir_entry @@ -136,4 +146,30 @@ class Gem::Package::TarTestCase < Gem::TestCase def util_symlink_entry util_entry tar_symlink_header("foo", "bar", 0, Time.now, "link") end + + def util_tar(&block) + tar_io = StringIO.new + Gem::Package::TarWriter.new(tar_io, &block) + tar_io.rewind + tar_io + end + + def util_tar_gz(&block) + tar_io = util_tar(&block) + StringIO.new util_gzip(tar_io.string) + end + + def util_gem_data_tar(spec = nil, &block) + data_tgz = util_tar_gz(&block) + util_tar do |tar| + if spec + tar.add_file "metadata.gz", 0o444 do |io| + io.write util_gzip(spec.to_yaml) + end + end + tar.add_file "data.tar.gz", 0o644 do |io| + io.write data_tgz.string + end + end + end end diff --git a/test/rubygems/packages/Bluebie-legs-0.6.2.gem b/test/rubygems/packages/Bluebie-legs-0.6.2.gem Binary files differnew file mode 100644 index 0000000000..60918f3bc5 --- /dev/null +++ b/test/rubygems/packages/Bluebie-legs-0.6.2.gem diff --git a/test/rubygems/plugin/load/rubygems_plugin.rb b/test/rubygems/plugin/load/rubygems_plugin.rb index 7cc6bef90b..21fef10bb1 100644 --- a/test/rubygems/plugin/load/rubygems_plugin.rb +++ b/test/rubygems/plugin/load/rubygems_plugin.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class TestGem TEST_PLUGIN_LOAD = :loaded end diff --git a/test/rubygems/plugin/exception/rubygems_plugin.rb b/test/rubygems/plugin/scripterror/rubygems_plugin.rb index f54e689d87..0acd55be12 100644 --- a/test/rubygems/plugin/exception/rubygems_plugin.rb +++ b/test/rubygems/plugin/scripterror/rubygems_plugin.rb @@ -1,3 +1,4 @@ # frozen_string_literal: true + TestGem::TEST_PLUGIN_EXCEPTION = :loaded -raise Exception.new("boom") +raise ScriptError.new("boom") diff --git a/test/rubygems/plugin/standarderror/rubygems_plugin.rb b/test/rubygems/plugin/standarderror/rubygems_plugin.rb index 0fcca28728..58e4080f05 100644 --- a/test/rubygems/plugin/standarderror/rubygems_plugin.rb +++ b/test/rubygems/plugin/standarderror/rubygems_plugin.rb @@ -1,3 +1,4 @@ # frozen_string_literal: true + TestGem::TEST_PLUGIN_STANDARDERROR = :loaded raise StandardError.new("boom") diff --git a/test/rubygems/private_key.pem b/test/rubygems/private_key.pem index c6ed3fc24e..4e6ce13e65 100644 --- a/test/rubygems/private_key.pem +++ b/test/rubygems/private_key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/test/rubygems/public_cert.pem b/test/rubygems/public_cert.pem index 4517de53c6..7481c26b79 100644 --- a/test/rubygems/public_cert.pem +++ b/test/rubygems/public_cert.pem @@ -1,20 +1,20 @@ -----BEGIN CERTIFICATE----- -MIIDLjCCAhagAwIBAgIBADANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv +MIIDLjCCAhagAwIBAgIBADANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCAXDTEyMDEwMTAwMDAwMFoYDzk5 OTkxMjMxMjM1OTU5WjAqMQ8wDQYDVQQDDAZub2JvZHkxFzAVBgoJkiaJk/IsZAEZ -FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp2U1hy8U -HrGClPxByczJtV6UYtQrJAv+FA9Mr0nkXKoHyEQMu3au4zAqwdTp+7+aAb6wu8cX -WepaFkAOGfqvAJ80/TfTbm+S05nqIl9TrS/K1j9/eCSIY2Q/bWXSHPT4yzXl/7na -CT6wVerAYFsO14jTHntSweL4oA3rtC48Oe2FgO3CFcgDmlx3HbAf41bwXzYcRm+b -WFykDvkENWTi8/GekN+884pJif11aCGZS1o+arJW+zxeQPEcN9jnj8PfOI96E/7N -DMSDwLTtKr/Pq8tI5De5pifScEO40Tpc/eKMnhm+zZ4kR04zJLUfcKyeRaJ48Ksu -0p3Dx38X4PluhwIDAQABo10wWzAZBgNVHREEEjAQgQ5ub2JvZHlAZXhhbXBsZTAd -BgNVHQ4EFgQUX0Nu9pqORSXpIuN9N16k1TYChRswDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQEFBQADggEBAJasznHQK7el5CY19uRM -QZSP2moi65jbESKA5CaSOK0erWfLL7k0W69Rr4RG8CQDXmtlVLzdQlEGkvJEfMLs -GumlIGDEsLZU/3tQ8lML2fMUKipv/fsyWoe6wUHyfsywYYT4WAxyKUtY6AepwN6Y -sJ6+qDWUFziSVgDnU2bBdqzIOw+ww1NtRGE3PEam+a/VL7l/a2DYcot5cvcc8RYR -6gyBXp4fvSGasM3iQp7sWdNV04H8m8+lYBLtsfuucgLDu45uEuvKL1tRcRXvtomp -rKB5y3B5qT/bcc+3b0tbOU6s7CBIdyzIflJI7GuIbZk6lZ+V8Yem+tWt1ArL3Hqf -Myk= +FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ULcfpDb +oY5uWVdOIkF4AtRui7PPFoaKfBl5hiGFcpYRx8DQPyT7bbD8nKd14Rhzb0nHCMU3 +DEz8PLJCmWm3NszVDkEJws1BpCGak6vKiyNa5hZbUlQMZMbecSDSpEKu2PBWgBT7 +4qg2RBugzTAVAnGQGezQnWyv47kyXvdjMoq11VZa+Dz2izHJvjBHGQShr1r9v39q +Irtah5CEXTRxEqhr96gg3y6xOPMqxi50dS0RBaJsPsjFZ1jecye0Z/WPItiLjSVV +RssUXK1a2VkYxUqkxUg4wwJD57H4TEZBomtAXlASo+rUv8G9eBNmS/k/oJLdiMF1 +ULb+e1+izeAyGwIDAQABo10wWzAZBgNVHREEEjAQgQ5ub2JvZHlAZXhhbXBsZTAd +BgNVHQ4EFgQUsRpUCWdFYAIC1870HWBKid/nWNkwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADggEBAAYrbeZLQujvqrzAa6NN +QsiGLSVoF+ZcySQH+rpoqcvbd8zLKz/vH+SoMM6db4OUgD8BKaeBb8dGhzz/lE8m +YUqW/La4xvf/ffW5yze51Rtr1bPw1Tjrk92nE630Unjf0ZZO0h8shTmq/WlXiEqg +cXxfbZiPP0KZkhn4ulf+RBbKKQGrLYvaVrCZcowSjLWzcfredYxElOpcgHCrL2pl +2ZAjCySqAUpYo8HTZwgY/DeeGS3V4fZ06ZDoG20cxi7t8R+AcNbEfaTMzG3oe5qN +A8+a3Qcf5M4yiJtXRNusMKeoRwLDkYRX9u76iOI5LfKTSqnUyhrUQcSYCTFO4y/V +P48= -----END CERTIFICATE----- diff --git a/test/rubygems/public_cert_32.pem b/test/rubygems/public_cert_32.pem index 0431b8ba1a..efcf7c0ed7 100644 --- a/test/rubygems/public_cert_32.pem +++ b/test/rubygems/public_cert_32.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/test/rubygems/public_key.pem b/test/rubygems/public_key.pem index 7c29dcd614..c233b35e7c 100644 --- a/test/rubygems/public_key.pem +++ b/test/rubygems/public_key.pem @@ -1,9 +1,9 @@ -----BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp2U1hy8UHrGClPxByczJ -tV6UYtQrJAv+FA9Mr0nkXKoHyEQMu3au4zAqwdTp+7+aAb6wu8cXWepaFkAOGfqv -AJ80/TfTbm+S05nqIl9TrS/K1j9/eCSIY2Q/bWXSHPT4yzXl/7naCT6wVerAYFsO -14jTHntSweL4oA3rtC48Oe2FgO3CFcgDmlx3HbAf41bwXzYcRm+bWFykDvkENWTi -8/GekN+884pJif11aCGZS1o+arJW+zxeQPEcN9jnj8PfOI96E/7NDMSDwLTtKr/P -q8tI5De5pifScEO40Tpc/eKMnhm+zZ4kR04zJLUfcKyeRaJ48Ksu0p3Dx38X4Plu -hwIDAQAB +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ULcfpDboY5uWVdOIkF4 +AtRui7PPFoaKfBl5hiGFcpYRx8DQPyT7bbD8nKd14Rhzb0nHCMU3DEz8PLJCmWm3 +NszVDkEJws1BpCGak6vKiyNa5hZbUlQMZMbecSDSpEKu2PBWgBT74qg2RBugzTAV +AnGQGezQnWyv47kyXvdjMoq11VZa+Dz2izHJvjBHGQShr1r9v39qIrtah5CEXTRx +Eqhr96gg3y6xOPMqxi50dS0RBaJsPsjFZ1jecye0Z/WPItiLjSVVRssUXK1a2VkY +xUqkxUg4wwJD57H4TEZBomtAXlASo+rUv8G9eBNmS/k/oJLdiMF1ULb+e1+izeAy +GwIDAQAB -----END PUBLIC KEY----- diff --git a/test/rubygems/rubygems/commands/crash_command.rb b/test/rubygems/rubygems/commands/crash_command.rb index 9155360e76..55df274603 100644 --- a/test/rubygems/rubygems/commands/crash_command.rb +++ b/test/rubygems/rubygems/commands/crash_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class Gem::Commands::CrashCommand < Gem::Command raise "crash" end diff --git a/test/rubygems/rubygems_plugin.rb b/test/rubygems/rubygems_plugin.rb index b538487bbf..949580f904 100644 --- a/test/rubygems/rubygems_plugin.rb +++ b/test/rubygems/rubygems_plugin.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require "rubygems/command_manager" ## diff --git a/test/rubygems/simple_gem.rb b/test/rubygems/simple_gem.rb index 0f2ea48198..3d30bade84 100644 --- a/test/rubygems/simple_gem.rb +++ b/test/rubygems/simple_gem.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true -SIMPLE_GEM = <<-GEMDATA.freeze + +SIMPLE_GEM = <<-GEMDATA MD5SUM = "989bf34a1cbecd52e0ea66b662b3a405" if $0 == __FILE__ require 'optparse' diff --git a/test/rubygems/specifications/bar-0.0.2.gemspec b/test/rubygems/specifications/bar-0.0.2.gemspec index 37b6ea45da..1f3d0161d2 100644 --- a/test/rubygems/specifications/bar-0.0.2.gemspec +++ b/test/rubygems/specifications/bar-0.0.2.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Gem::Specification.new do |s| s.name = "bar" s.version = "0.0.2" diff --git a/test/rubygems/specifications/rubyforge-0.0.1.gemspec b/test/rubygems/specifications/rubyforge-0.0.1.gemspec index e8d5030326..0421b675a0 100644 --- a/test/rubygems/specifications/rubyforge-0.0.1.gemspec +++ b/test/rubygems/specifications/rubyforge-0.0.1.gemspec @@ -1,12 +1,15 @@ +# frozen_string_literal: true + Gem::Specification.new do |s| - s.name = "rubyforge" - s.version = "0.0.1" - s.platform = "ruby" - s.require_paths = ["lib"] - s.summary = "A very bar gem" - s.authors = ["unknown"] - s.license = "MIT" - s.homepage = "http://example.com" - s.files = ["README.md"] - s.rubyforge_project = "abc" + s.name = "rubyforge" + s.version = "0.0.1" + s.platform = "ruby" + s.require_paths = ["lib"] + s.summary = "A very bar gem" + s.authors = ["unknown"] + s.license = "MIT" + s.homepage = "http://example.com" + s.files = ["README.md"] + s.rubyforge_project = "abc" + s.required_ruby_version = ">= 1.9.3" end diff --git a/test/rubygems/test_bundled_ca.rb b/test/rubygems/test_bundled_ca.rb index 3d7f616519..a737185681 100644 --- a/test/rubygems/test_bundled_ca.rb +++ b/test/rubygems/test_bundled_ca.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true + require_relative "helper" -require "net/http" +require "rubygems/vendored_net_http" require "rubygems/openssl" unless Gem::HAVE_OPENSSL @@ -14,7 +15,7 @@ require "rubygems/request" # The tested hosts are explained in detail here: https://github.com/rubygems/rubygems/commit/5e16a5428f973667cabfa07e94ff939e7a83ebd9 # -class TestBundledCA < Gem::TestCase +class TestGemBundledCA < Gem::TestCase def bundled_certificate_store store = OpenSSL::X509::Store.new @@ -27,12 +28,12 @@ class TestBundledCA < Gem::TestCase def assert_https(host) assert true - http = Net::HTTP.new(host, 443) + http = Gem::Net::HTTP.new(host, 443) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.cert_store = bundled_certificate_store http.get("/") - rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError + rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError, Gem::Net::OpenTimeout pend "#{host} seems offline, I can't tell whether ssl would work." rescue OpenSSL::SSL::SSLError => e # Only fail for certificate verification errors diff --git a/test/rubygems/test_config.rb b/test/rubygems/test_config.rb index d9e0f4dd9d..657624d526 100644 --- a/test/rubygems/test_config.rb +++ b/test/rubygems/test_config.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems" require "shellwords" -class TestConfig < Gem::TestCase +class TestGemConfig < Gem::TestCase def test_datadir util_make_gems spec = Gem::Specification.find_by_name("a") @@ -15,13 +16,13 @@ class TestConfig < Gem::TestCase path = Gem::TestCase.class_variable_get(:@@good_rake) ruby, rake = path.shellsplit assert_equal(Gem.ruby, ruby) - assert_match(/\/good_rake.rb\z/, rake) + assert_match(%r{/good_rake.rb\z}, rake) end def test_bad_rake_path_is_escaped path = Gem::TestCase.class_variable_get(:@@bad_rake) ruby, rake = path.shellsplit assert_equal(Gem.ruby, ruby) - assert_match(/\/bad_rake.rb\z/, rake) + assert_match(%r{/bad_rake.rb\z}, rake) end end diff --git a/test/rubygems/test_deprecate.rb b/test/rubygems/test_deprecate.rb index dfcf8dea11..d15de646a4 100644 --- a/test/rubygems/test_deprecate.rb +++ b/test/rubygems/test_deprecate.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/deprecate" -class TestDeprecate < Gem::TestCase +class TestGemDeprecate < Gem::TestCase def setup super @@ -28,7 +29,7 @@ class TestDeprecate < Gem::TestCase assert_equal true, Gem::Deprecate.skip Gem::Deprecate.skip = nil - assert([true,false].include? Gem::Deprecate.skip) + assert([true,false].include?(Gem::Deprecate.skip)) end def test_skip @@ -45,6 +46,7 @@ class TestDeprecate < Gem::TestCase def foo @message = "foo" end + def bar @message = "bar" end @@ -53,6 +55,7 @@ class TestDeprecate < Gem::TestCase def foo_arg(msg) @message = "foo" + msg end + def bar_arg(msg) @message = "bar" + msg end @@ -61,6 +64,7 @@ class TestDeprecate < Gem::TestCase def foo_kwarg(message:) @message = "foo" + message end + def bar_kwarg(message:) @message = "bar" + message end @@ -73,6 +77,7 @@ class TestDeprecate < Gem::TestCase def foo @message = "foo" end + def bar @message = "bar" end @@ -81,6 +86,7 @@ class TestDeprecate < Gem::TestCase def foo_arg(msg) @message = "foo" + msg end + def bar_arg(msg) @message = "bar" + msg end @@ -89,6 +95,7 @@ class TestDeprecate < Gem::TestCase def foo_kwarg(message:) @message = "foo" + message end + def bar_kwarg(message:) @message = "bar" + message end diff --git a/test/rubygems/test_exit.rb b/test/rubygems/test_exit.rb index 707150efaa..396837edad 100644 --- a/test/rubygems/test_exit.rb +++ b/test/rubygems/test_exit.rb @@ -3,7 +3,7 @@ require_relative "helper" require "rubygems" -class TestExit < Gem::TestCase +class TestGemExit < Gem::TestCase def test_exit system(*ruby_with_rubygems_in_load_path, "-e", "raise Gem::SystemExitException.new(2)") assert_equal 2, $?.exitstatus diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bbb3e6dd0a..40a473f8d6 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1,4 +1,5 @@ # coding: US-ASCII + require_relative "helper" require "rubygems" require "rubygems/command" @@ -10,7 +11,7 @@ require "rbconfig" class TestGem < Gem::TestCase PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant - PROJECT_DIR = File.expand_path("../..", __dir__).tap(&Gem::UNTAINT) + PROJECT_DIR = File.expand_path("../..", __dir__) def setup super @@ -95,9 +96,9 @@ class TestGem < Gem::TestCase gemhome2 = "#{@gemhome}2" - installed = Gem.install "a", "= 1", :install_dir => gemhome2 + installed = Gem.install "a", "= 1", install_dir: gemhome2 - assert_equal %w[a-1], installed.map {|spec| spec.full_name } + assert_equal %w[a-1], installed.map(&:full_name) assert_path_exist File.join(gemhome2, "gems", "a-1") end @@ -114,9 +115,9 @@ class TestGem < Gem::TestCase begin raise "Error" rescue StandardError - Gem.install "a", "= 1", :install_dir => gemhome2 + Gem.install "a", "= 1", install_dir: gemhome2 end - assert_equal %w[a-1], installed.map {|spec| spec.full_name } + assert_equal %w[a-1], installed.map(&:full_name) end def test_self_install_permissions @@ -131,8 +132,8 @@ class TestGem < Gem::TestCase end def test_self_install_permissions_umask_077 - umask = File.umask(077) - assert_self_install_permissions + umask = File.umask(0o077) + assert_self_install_permissions(data_mode: 0o600) ensure File.umask(umask) end @@ -150,21 +151,21 @@ class TestGem < Gem::TestCase Gem::Installer.exec_format = nil end - def assert_self_install_permissions(format_executable: false) - mask = win_platform? ? 0700 : 0777 + def assert_self_install_permissions(format_executable: false, data_mode: 0o640) + mask = Gem.win_platform? ? 0o700 : 0o777 options = { - :dir_mode => 0500, - :prog_mode => win_platform? ? 0410 : 0510, - :data_mode => 0640, - :wrappers => true, - :format_executable => format_executable, + dir_mode: 0o500, + prog_mode: Gem.win_platform? ? 0o410 : 0o510, + data_mode: data_mode, + wrappers: true, + format_executable: format_executable, } Dir.chdir @tempdir do Dir.mkdir "bin" Dir.mkdir "data" File.write "bin/foo", "#!/usr/bin/env ruby\n" - File.chmod 0755, "bin/foo" + File.chmod 0o755, "bin/foo" File.write "data/foo.txt", "blah\n" @@ -191,7 +192,7 @@ class TestGem < Gem::TestCase "gems/foo-1/data/foo.txt" => data_mode, } # add Windows script - expected["bin/#{prog_name}.bat"] = mask.to_s(8) if win_platform? + expected["bin/#{prog_name}.bat"] = mask.to_s(8) if Gem.win_platform? result = {} Dir.chdir @gemhome do expected.each_key do |n| @@ -200,7 +201,7 @@ class TestGem < Gem::TestCase end assert_equal(expected, result) ensure - File.chmod(0755, *Dir.glob(@gemhome + "/gems/**/").map {|path| path.tap(&Gem::UNTAINT) }) + File.chmod(0o755, *Dir.glob(@gemhome + "/gems/**/")) end def test_require_missing @@ -366,7 +367,7 @@ class TestGem < Gem::TestCase install_specs bundler_latest, bundler_previous File.open("Gemfile.lock", "w") do |f| - f.write <<-L.gsub(/ {8}/, "") + f.write <<~L GEM remote: https://rubygems.org/ specs: @@ -400,7 +401,7 @@ class TestGem < Gem::TestCase install_specs bundler_latest, bundler_previous File.open("Gemfile.lock", "w") do |f| - f.write <<-L.gsub(/ {8}/, "") + f.write <<~L GEM remote: https://rubygems.org/ specs: @@ -424,7 +425,7 @@ class TestGem < Gem::TestCase def test_activate_bin_path_gives_proper_error_for_bundler_when_underscore_selection_given File.open("Gemfile.lock", "w") do |f| - f.write <<-L.gsub(/ {8}/, "") + f.write <<~L GEM remote: https://rubygems.org/ specs: @@ -515,7 +516,10 @@ class TestGem < Gem::TestCase Gem.clear_paths - assert_nil Gem::Specification.send(:class_variable_get, :@@all) + with_env("GEM_HOME" => "foo", "GEM_PATH" => "bar") do + assert_equal("foo", Gem.dir) + assert_equal("bar", Gem.path.first) + end end def test_self_configuration @@ -616,25 +620,6 @@ class TestGem < Gem::TestCase assert_equal %w[https://rubygems.org/], Gem.default_sources end - def test_self_use_gemdeps - with_rubygems_gemdeps("-") do - FileUtils.mkdir_p "detect/a/b" - FileUtils.mkdir_p "detect/a/Isolate" - - FileUtils.touch "detect/Isolate" - - begin - Dir.chdir "detect/a/b" - - Gem.use_gemdeps - - assert_equal add_bundler_full_name([]), loaded_spec_names - ensure - Dir.chdir @tempdir - end - end - end - def test_self_dir assert_equal @gemhome, Gem.dir end @@ -657,13 +642,13 @@ class TestGem < Gem::TestCase FileUtils.rm_r @gemhome Gem.use_paths @gemhome - Gem.ensure_gem_subdirectories @gemhome, 0750 + Gem.ensure_gem_subdirectories @gemhome, 0o750 assert_directory_exists File.join(@gemhome, "cache") - assert_equal 0750, File::Stat.new(@gemhome).mode & 0777 - assert_equal 0750, File::Stat.new(File.join(@gemhome, "cache")).mode & 0777 - end unless win_platform? + assert_equal 0o750, File::Stat.new(@gemhome).mode & 0o777 + assert_equal 0o750, File::Stat.new(File.join(@gemhome, "cache")).mode & 0o777 + end unless Gem.win_platform? def test_self_ensure_gem_directories_safe_permissions FileUtils.rm_r @gemhome @@ -673,17 +658,21 @@ class TestGem < Gem::TestCase File.umask 0 Gem.ensure_gem_subdirectories @gemhome - assert_equal 0, File::Stat.new(@gemhome).mode & 002 - assert_equal 0, File::Stat.new(File.join(@gemhome, "cache")).mode & 002 + assert_equal 0, File::Stat.new(@gemhome).mode & 0o002 + assert_equal 0, File::Stat.new(File.join(@gemhome, "cache")).mode & 0o002 ensure File.umask old_umask - end unless win_platform? + end unless Gem.win_platform? def test_self_ensure_gem_directories_missing_parents gemdir = File.join @tempdir, "a/b/c/gemdir" - FileUtils.rm_rf File.join(@tempdir, "a") rescue nil + begin + FileUtils.rm_rf File.join(@tempdir, "a") + rescue StandardError + nil + end refute File.exist?(File.join(@tempdir, "a")), - "manually remove #{File.join @tempdir, 'a'}, tests are broken" + "manually remove #{File.join @tempdir, "a"}, tests are broken" Gem.use_paths gemdir Gem.ensure_gem_subdirectories gemdir @@ -691,37 +680,45 @@ class TestGem < Gem::TestCase assert_directory_exists util_cache_dir end - unless win_platform? || Process.uid.zero? # only for FS that support write protection + unless Gem.win_platform? || Process.uid.zero? # only for FS that support write protection def test_self_ensure_gem_directories_write_protected gemdir = File.join @tempdir, "egd" - FileUtils.rm_r gemdir rescue nil + begin + FileUtils.rm_r gemdir + rescue StandardError + nil + end refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken" FileUtils.mkdir_p gemdir - FileUtils.chmod 0400, gemdir + FileUtils.chmod 0o400, gemdir Gem.use_paths gemdir Gem.ensure_gem_subdirectories gemdir refute File.exist?(util_cache_dir) ensure - FileUtils.chmod 0600, gemdir + FileUtils.chmod 0o600, gemdir end def test_self_ensure_gem_directories_write_protected_parents parent = File.join(@tempdir, "egd") gemdir = "#{parent}/a/b/c" - FileUtils.rm_r parent rescue nil + begin + FileUtils.rm_r parent + rescue StandardError + nil + end refute File.exist?(parent), "manually remove #{parent}, tests are broken" FileUtils.mkdir_p parent - FileUtils.chmod 0400, parent + FileUtils.chmod 0o400, parent Gem.use_paths(gemdir) Gem.ensure_gem_subdirectories gemdir refute File.exist? File.join(gemdir, "gems") ensure - FileUtils.chmod 0600, parent + FileUtils.chmod 0o600, parent end def test_self_ensure_gem_directories_non_existent_paths @@ -753,7 +750,7 @@ class TestGem < Gem::TestCase s.files << discover_path end - write_file(File.join "gems", spec.full_name, discover_path) do |fp| + write_file(File.join("gems", spec.full_name, discover_path)) do |fp| fp.puts "# #{spec.full_name}" end @@ -774,42 +771,6 @@ class TestGem < Gem::TestCase assert_equal cwd, $LOAD_PATH.shift end - def test_self_find_files_with_gemfile - cwd = File.expand_path("test/rubygems", PROJECT_DIR) - actual_load_path = $LOAD_PATH.unshift(cwd).dup - - discover_path = File.join "lib", "sff", "discover.rb" - - foo1, _ = %w[1 2].map do |version| - spec = quick_gem "sff", version do |s| - s.files << discover_path - end - - write_file(File.join "gems", spec.full_name, discover_path) do |fp| - fp.puts "# #{spec.full_name}" - end - - spec - end - Gem.refresh - - write_file(File.join Dir.pwd, "Gemfile") do |fp| - fp.puts "source 'https://rubygems.org'" - fp.puts "gem '#{foo1.name}', '#{foo1.version}'" - end - Gem.use_gemdeps(File.join Dir.pwd, "Gemfile") - - expected = [ - File.expand_path("test/rubygems/sff/discover.rb", PROJECT_DIR), - File.join(foo1.full_gem_path, discover_path), - ].sort - - assert_equal expected, Gem.find_files("sff/discover").sort - assert_equal expected, Gem.find_files("sff/**.rb").sort, "[ruby-core:31730]" - ensure - assert_equal cwd, actual_load_path.shift unless Gem.java_platform? - end - def test_self_find_latest_files cwd = File.expand_path("test/rubygems", PROJECT_DIR) $LOAD_PATH.unshift cwd @@ -821,7 +782,7 @@ class TestGem < Gem::TestCase s.files << discover_path end - write_file(File.join "gems", spec.full_name, discover_path) do |fp| + write_file(File.join("gems", spec.full_name, discover_path)) do |fp| fp.puts "# #{spec.full_name}" end @@ -1019,11 +980,11 @@ class TestGem < Gem::TestCase pend "chmod not supported" if Gem.win_platform? begin - File.chmod 0444, "test" + File.chmod 0o444, "test" assert_equal ["\xCF", "\x80"], Gem.read_binary("test").chars.to_a ensure - File.chmod 0644, "test" + File.chmod 0o644, "test" end end @@ -1084,7 +1045,8 @@ class TestGem < Gem::TestCase end def test_self_ruby_api_version - orig_ruby_version, RbConfig::CONFIG["ruby_version"] = RbConfig::CONFIG["ruby_version"], "1.2.3" + orig_ruby_version = RbConfig::CONFIG["ruby_version"] + RbConfig::CONFIG["ruby_version"] = "1.2.3" Gem.instance_variable_set :@ruby_api_version, nil @@ -1107,7 +1069,7 @@ class TestGem < Gem::TestCase end def test_self_ruby_version_with_non_mri_implementations - util_set_RUBY_VERSION "2.5.0", 0, 60928, "jruby 9.2.0.0 (2.5.0) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]" + util_set_RUBY_VERSION "2.5.0", 0, 60_928, "jruby 9.2.0.0 (2.5.0) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]" assert_equal Gem::Version.new("2.5.0"), Gem.ruby_version ensure @@ -1115,7 +1077,7 @@ class TestGem < Gem::TestCase end def test_self_ruby_version_with_svn_prerelease - util_set_RUBY_VERSION "2.6.0", -1, 63539, "ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]" + util_set_RUBY_VERSION "2.6.0", -1, 63_539, "ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]" assert_equal Gem::Version.new("2.6.0.preview2"), Gem.ruby_version ensure @@ -1131,7 +1093,7 @@ class TestGem < Gem::TestCase end def test_self_ruby_version_with_non_mri_implementations_with_mri_prerelase_compatibility - util_set_RUBY_VERSION "2.6.0", -1, 63539, "weirdjruby 9.2.0.0 (2.6.0preview2) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]", "weirdjruby", "9.2.0.0" + util_set_RUBY_VERSION "2.6.0", -1, 63_539, "weirdjruby 9.2.0.0 (2.6.0preview2) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]", "weirdjruby", "9.2.0.0" assert_equal Gem::Version.new("2.6.0.preview2"), Gem.ruby_version ensure @@ -1139,7 +1101,7 @@ class TestGem < Gem::TestCase end def test_self_ruby_version_with_svn_trunk - util_set_RUBY_VERSION "1.9.2", -1, 23493, "ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]" + util_set_RUBY_VERSION "1.9.2", -1, 23_493, "ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]" assert_equal Gem::Version.new("1.9.2.dev"), Gem.ruby_version ensure @@ -1295,8 +1257,8 @@ class TestGem < Gem::TestCase Gem.try_activate "a_file" end - assert_match %r{Could not find 'b' }, e.message - assert_match %r{at: #{a.spec_file}}, e.message + assert_include(e.message, "Could not find 'b' ") + assert_include(e.message, "at: #{a.spec_file}") end def test_self_try_activate_missing_prerelease @@ -1316,13 +1278,12 @@ class TestGem < Gem::TestCase Gem.try_activate "a_file" end - assert_match %r{Could not find 'b' \(= 1.0rc1\)}, e.message + assert_match(/Could not find 'b' \(= 1.0rc1\)/, e.message) end def test_self_try_activate_missing_extensions spec = util_spec "ext", "1" do |s| s.extensions = %w[ext/extconf.rb] - s.mark_version s.installed_by_version = v("2.2") end @@ -1335,12 +1296,10 @@ class TestGem < Gem::TestCase refute Gem.try_activate "nonexistent" end - unless Gem.java_platform? - expected = "Ignoring ext-1 because its extensions are not built. " + - "Try: gem pristine ext --version 1\n" + expected = "Ignoring ext-1 because its extensions are not built. " \ + "Try: gem pristine ext --version 1\n" - assert_equal expected, err - end + assert_equal expected, err end def test_self_use_paths_with_nils @@ -1357,8 +1316,8 @@ class TestGem < Gem::TestCase def test_setting_paths_does_not_warn_about_unknown_keys stdout, stderr = capture_output do - Gem.paths = { "foo" => [], - "bar" => Object.new, + Gem.paths = { "foo" => [], + "bar" => Object.new, "GEM_HOME" => Gem.paths.home, "GEM_PATH" => "foo" } end @@ -1369,7 +1328,7 @@ class TestGem < Gem::TestCase def test_setting_paths_does_not_mutate_parameter_object Gem.paths = { "GEM_HOME" => Gem.paths.home, - "GEM_PATH" => "foo" }.freeze + "GEM_PATH" => "foo" } .freeze assert_equal ["foo", Gem.paths.home], Gem.paths.path end @@ -1421,7 +1380,7 @@ class TestGem < Gem::TestCase r.gem "b", "= 1" end - activated = Gem::Specification.map {|x| x.full_name } + activated = Gem::Specification.map(&:full_name) assert_equal %w[a-1 b-1 c-2], activated.sort end @@ -1446,7 +1405,7 @@ class TestGem < Gem::TestCase end def test_self_gunzip - input = "\x1F\x8B\b\0\xED\xA3\x1AQ\0\x03\xCBH" + + input = "\x1F\x8B\b\0\xED\xA3\x1AQ\0\x03\xCBH" \ "\xCD\xC9\xC9\a\0\x86\xA6\x106\x05\0\0\0" output = Gem::Util.gunzip input @@ -1492,6 +1451,8 @@ class TestGem < Gem::TestCase def test_load_plugins plugin_path = File.join "lib", "rubygems_plugin.rb" + foo1_plugin_path = nil + foo2_plugin_path = nil Dir.chdir @tempdir do FileUtils.mkdir_p "lib" File.open plugin_path, "w" do |fp| @@ -1501,17 +1462,22 @@ class TestGem < Gem::TestCase foo1 = util_spec "foo", "1" do |s| s.files << plugin_path end + foo1_plugin_path = File.join(foo1.gem_dir, plugin_path) install_gem foo1 foo2 = util_spec "foo", "2" do |s| s.files << plugin_path end + foo2_plugin_path = File.join(foo2.gem_dir, plugin_path) install_gem foo2 end Gem::Specification.reset + PLUGINS_LOADED.clear + $LOADED_FEATURES.delete(foo1_plugin_path) + $LOADED_FEATURES.delete(foo2_plugin_path) gem "foo" @@ -1521,6 +1487,9 @@ class TestGem < Gem::TestCase end def test_load_user_installed_plugins + @orig_gem_home = ENV["GEM_HOME"] + ENV["GEM_HOME"] = @gemhome + plugin_path = File.join "lib", "rubygems_plugin.rb" Dir.chdir @tempdir do @@ -1543,23 +1512,37 @@ class TestGem < Gem::TestCase Gem.load_plugins assert_equal %w[plugin], PLUGINS_LOADED + ensure + ENV["GEM_HOME"] = @orig_gem_home end def test_load_env_plugins with_plugin("load") { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_LOAD rescue nil + begin + assert_equal :loaded, TEST_PLUGIN_LOAD + rescue StandardError + nil + end util_remove_interrupt_command # Should attempt to cause a StandardError with_plugin("standarderror") { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_STANDARDERROR rescue nil + begin + assert_equal :loaded, TEST_PLUGIN_STANDARDERROR + rescue StandardError + nil + end util_remove_interrupt_command # Should attempt to cause an Exception - with_plugin("exception") { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_EXCEPTION rescue nil + with_plugin("scripterror") { Gem.load_env_plugins } + begin + assert_equal :loaded, TEST_PLUGIN_EXCEPTION + rescue StandardError + nil + end end def test_gem_path_ordering @@ -1571,20 +1554,20 @@ class TestGem < Gem::TestCase g = util_spec "g", "1", nil, "lib/g.rb" m = util_spec "m", "1", nil, "lib/m.rb" - install_gem g, :install_dir => Gem.dir - m0 = install_gem m, :install_dir => Gem.dir - m1 = install_gem m, :install_dir => Gem.user_dir + install_gem g, install_dir: Gem.dir + m0 = install_gem m, install_dir: Gem.dir + m1 = install_gem m, install_dir: Gem.user_dir assert_equal m0.gem_dir, File.join(Gem.dir, "gems", "m-1") assert_equal m1.gem_dir, File.join(Gem.user_dir, "gems", "m-1") tests = [ - [:dir0, [ Gem.dir, Gem.user_dir], m0], - [:dir1, [ Gem.user_dir, Gem.dir], m1], + [:dir0, [Gem.dir, Gem.user_dir], m0], + [:dir1, [Gem.user_dir, Gem.dir], m1], ] - tests.each do |_name, _paths, expected| - Gem.use_paths _paths.first, _paths + tests.each do |name, paths, expected| + Gem.use_paths paths.first, paths Gem::Specification.reset Gem.searcher = nil @@ -1594,25 +1577,25 @@ class TestGem < Gem::TestCase assert_equal \ [expected.gem_dir], Gem::Dependency.new("m","1").to_specs.map(&:gem_dir).sort, - "Wrong specs for #{_name}" + "Wrong specs for #{name}" spec = Gem::Dependency.new("m","1").to_spec assert_equal \ - File.join(_paths.first, "gems", "m-1"), + File.join(paths.first, "gems", "m-1"), spec.gem_dir, - "Wrong spec before require for #{_name}" - refute spec.activated?, "dependency already activated for #{_name}" + "Wrong spec before require for #{name}" + refute spec.activated?, "dependency already activated for #{name}" gem "m" spec = Gem::Dependency.new("m","1").to_spec - assert spec.activated?, "dependency not activated for #{_name}" + assert spec.activated?, "dependency not activated for #{name}" assert_equal \ - File.join(_paths.first, "gems", "m-1"), + File.join(paths.first, "gems", "m-1"), spec.gem_dir, - "Wrong spec after require for #{_name}" + "Wrong spec after require for #{name}" spec.instance_variable_set :@activated, false Gem.loaded_specs.delete(spec.name) @@ -1627,11 +1610,11 @@ class TestGem < Gem::TestCase g = util_spec "g", "1", nil, "lib/g.rb" m = util_spec "m", "1", nil, "lib/m.rb" - install_gem g, :install_dir => Gem.dir - install_gem m, :install_dir => Gem.dir - install_gem m, :install_dir => Gem.user_dir + install_gem g, install_dir: Gem.dir + install_gem m, install_dir: Gem.dir + install_gem m, install_dir: Gem.user_dir - Gem.use_paths Gem.dir, [ Gem.dir, Gem.user_dir] + Gem.use_paths Gem.dir, [Gem.dir, Gem.user_dir] assert_equal \ File.join(Gem.dir, "gems", "m-1"), @@ -1639,163 +1622,6 @@ class TestGem < Gem::TestCase "Wrong spec selected" end - def test_auto_activation_of_specific_gemdeps_file - a = util_spec "a", "1", nil, "lib/a.rb" - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end - - with_rubygems_gemdeps(path) do - Gem.use_gemdeps - - assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names - end - end - - def test_auto_activation_of_used_gemdeps_file - a = util_spec "a", "1", nil, "lib/a.rb" - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end - - with_rubygems_gemdeps("-") do - expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name) - - Gem.use_gemdeps - - assert_equal expected_specs, loaded_spec_names - end - end - - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) } - BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze - - def add_bundler_full_name(names) - names << BUNDLER_FULL_NAME - names.sort! - names - end - - def test_looks_for_gemdeps_files_automatically_from_binstubs - pend "Requiring bundler messes things up" if Gem.java_platform? - - a = util_spec "a", "1" do |s| - s.executables = %w[foo] - s.bindir = "exe" - end - - write_file File.join(@tempdir, "exe", "foo") do |fp| - fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" - end - - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - - path = File.join(@tempdir, "gd-tmp") - install_gem a, :install_dir => path - install_gem b, :install_dir => path - install_gem c, :install_dir => path - - ENV["GEM_PATH"] = path - - with_rubygems_gemdeps("-") do - new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) - new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", &:read).split(/\n/) - end - - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", &:read).split(/\n/) - end - - assert_equal ["b-1", "c-1"], out - out0 - end - end - - def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir - pend "Requiring bundler messes things up" if Gem.java_platform? - - a = util_spec "a", "1" do |s| - s.executables = %w[foo] - s.bindir = "exe" - end - - write_file File.join(@tempdir, "exe", "foo") do |fp| - fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" - end - - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - - path = File.join(@tempdir, "gd-tmp") - install_gem a, :install_dir => path - install_gem b, :install_dir => path - install_gem c, :install_dir => path - - ENV["GEM_PATH"] = path - - with_rubygems_gemdeps("-") do - Dir.mkdir "sub1" - - new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) - new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) - end - - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) - end - - Dir.rmdir "sub1" - - assert_equal ["b-1", "c-1"], out - out0 - end - end - def test_register_default_spec Gem.clear_default_specs @@ -1836,155 +1662,17 @@ class TestGem < Gem::TestCase assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") end - def test_use_gemdeps - gem_deps_file = "gem.deps.rb".tap(&Gem::UNTAINT) - spec = util_spec "a", 1 - install_specs spec - - spec = Gem::Specification.find {|s| s == spec } - refute spec.activated? - - File.open gem_deps_file, "w" do |io| - io.write 'gem "a"' - end - - assert_nil Gem.gemdeps - - Gem.use_gemdeps gem_deps_file - - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names - refute_nil Gem.gemdeps - end - - def test_use_gemdeps_ENV - with_rubygems_gemdeps(nil) do - spec = util_spec "a", 1 - - refute spec.activated? - - File.open "gem.deps.rb", "w" do |io| - io.write 'gem "a"' - end - - Gem.use_gemdeps - - refute spec.activated? - end - end - - def test_use_gemdeps_argument_missing - e = assert_raise ArgumentError do - Gem.use_gemdeps "gem.deps.rb" - end - - assert_equal "Unable to find gem dependencies file at gem.deps.rb", - e.message - end - - def test_use_gemdeps_argument_missing_match_ENV - with_rubygems_gemdeps("gem.deps.rb") do - e = assert_raise ArgumentError do - Gem.use_gemdeps "gem.deps.rb" - end - - assert_equal "Unable to find gem dependencies file at gem.deps.rb", - e.message - end - end - - def test_use_gemdeps_automatic - with_rubygems_gemdeps("-") do - spec = util_spec "a", 1 - install_specs spec - spec = Gem::Specification.find {|s| s == spec } - - refute spec.activated? - - File.open "Gemfile", "w" do |io| - io.write 'gem "a"' - end - - Gem.use_gemdeps - - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names - end - end - - def test_use_gemdeps_automatic_missing - with_rubygems_gemdeps("-") do - Gem.use_gemdeps - - assert true # count - end - end - - def test_use_gemdeps_disabled - with_rubygems_gemdeps("") do - spec = util_spec "a", 1 - - refute spec.activated? - - File.open "gem.deps.rb", "w" do |io| - io.write 'gem "a"' - end - - Gem.use_gemdeps - - refute spec.activated? - end - end - - def test_use_gemdeps_missing_gem - with_rubygems_gemdeps("x") do - File.open "x", "w" do |io| - io.write 'gem "a"' - end - - expected = <<-EXPECTED -Could not find gem 'a' in locally installed gems. -You may need to `bundle install` to install missing gems - - EXPECTED - - Gem::Deprecate.skip_during do - actual_stdout, actual_stderr = capture_output do - Gem.use_gemdeps - end - assert_empty actual_stdout - assert_equal(expected, actual_stderr) - end - end - end - - def test_use_gemdeps_specific - with_rubygems_gemdeps("x") do - spec = util_spec "a", 1 - install_specs spec - - spec = Gem::Specification.find {|s| s == spec } - refute spec.activated? - - File.open "x", "w" do |io| - io.write 'gem "a"' - end - - Gem.use_gemdeps - - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names - end - end - def test_operating_system_defaults operating_system_defaults = Gem.operating_system_defaults - assert operating_system_defaults != nil + assert !operating_system_defaults.nil? assert operating_system_defaults.is_a? Hash end def test_platform_defaults platform_defaults = Gem.platform_defaults - assert platform_defaults != nil + assert !platform_defaults.nil? assert platform_defaults.is_a? Hash end @@ -2006,18 +1694,42 @@ You may need to `bundle install` to install missing gems ENV["SOURCE_DATE_EPOCH"] = old_epoch end + def test_data_home_default + expected = File.join(@userhome, ".local", "share") + assert_equal expected, Gem.data_home + end + + def test_data_home_from_env + ENV["XDG_DATA_HOME"] = expected = "/test/data/home" + assert_equal expected, Gem.data_home + end + + def test_state_home_default + Gem.instance_variable_set :@state_home, nil + Gem.data_home # memoize @data_home, to demonstrate GH-6418 + expected = File.join(@userhome, ".local", "state") + assert_equal expected, Gem.state_home + end + + def test_state_home_from_env + Gem.instance_variable_set :@state_home, nil + Gem.data_home # memoize @data_home, to demonstrate GH-6418 + ENV["XDG_STATE_HOME"] = expected = "/test/state/home" + assert_equal expected, Gem.state_home + end + private def ruby_install_name(name) with_clean_path_to_ruby do - orig_RUBY_INSTALL_NAME = RbConfig::CONFIG["ruby_install_name"] + orig_ruby_install_name = RbConfig::CONFIG["ruby_install_name"] RbConfig::CONFIG["ruby_install_name"] = name begin yield ensure - if orig_RUBY_INSTALL_NAME - RbConfig::CONFIG["ruby_install_name"] = orig_RUBY_INSTALL_NAME + if orig_ruby_install_name + RbConfig::CONFIG["ruby_install_name"] = orig_ruby_install_name else RbConfig::CONFIG.delete "ruby_install_name" end @@ -2037,13 +1749,8 @@ You may need to `bundle install` to install missing gems end def redefine_method(base, method, new_result) - if RUBY_VERSION >= "2.5" - base.alias_method(method, method) - base.define_method(method) { new_result } - else - base.send(:alias_method, method, method) - base.send(:define_method, method) { new_result } - end + base.alias_method(method, method) + base.define_method(method) { new_result } end def with_plugin(path) @@ -2068,7 +1775,7 @@ You may need to `bundle install` to install missing gems # # FIXME what does this solve precisely? -ebh # - @additional.each do |dir| + @additional.each do |_dir| Gem.ensure_gem_subdirectories @gemhome end end @@ -2091,22 +1798,4 @@ You may need to `bundle install` to install missing gems def util_cache_dir File.join Gem.dir, "cache" end - - def with_path_and_rubyopt(path_value, rubyopt_value) - path, ENV["PATH"] = ENV["PATH"], path_value - rubyopt, ENV["RUBYOPT"] = ENV["RUBYOPT"], rubyopt_value - - yield - ensure - ENV["PATH"] = path - ENV["RUBYOPT"] = rubyopt - end - - def with_rubygems_gemdeps(value) - rubygems_gemdeps, ENV["RUBYGEMS_GEMDEPS"] = ENV["RUBYGEMS_GEMDEPS"], value - - yield - ensure - ENV["RUBYGEMS_GEMDEPS"] = rubygems_gemdeps - end end diff --git a/test/rubygems/test_gem_available_set.rb b/test/rubygems/test_gem_available_set.rb index 576f3f4221..7c24d25bcb 100644 --- a/test/rubygems/test_gem_available_set.rb +++ b/test/rubygems/test_gem_available_set.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/available_set" require "rubygems/security" @@ -36,12 +37,12 @@ class TestGemAvailableSet < Gem::TestCase dep = Gem::Resolver::DependencyRequest.new dep("a"), nil - assert_equal %w[a-1], set.find_all(dep).map {|spec| spec.full_name } + assert_equal %w[a-1], set.find_all(dep).map(&:full_name) dep = Gem::Resolver::DependencyRequest.new dep("a", ">= 0.a"), nil assert_equal %w[a-1 a-1.a], - set.find_all(dep).map {|spec| spec.full_name }.sort + set.find_all(dep).map(&:full_name).sort end def test_match_platform @@ -122,7 +123,7 @@ class TestGemAvailableSet < Gem::TestCase set.add a2a, @source set.add a2, @source - g = set.sorted.map {|t| t.spec } + g = set.sorted.map(&:spec) assert_equal [a3a, a2, a2a, a1, a1a], g end diff --git a/test/rubygems/test_gem_bundler_version_finder.rb b/test/rubygems/test_gem_bundler_version_finder.rb index 60e2b65047..6d88810493 100644 --- a/test/rubygems/test_gem_bundler_version_finder.rb +++ b/test/rubygems/test_gem_bundler_version_finder.rb @@ -1,12 +1,14 @@ # frozen_string_literal: true + require_relative "helper" +require "rubygems/bundler_version_finder" class TestGemBundlerVersionFinder < Gem::TestCase def setup - super - @argv = ARGV.dup @dollar_0 = $0 + super + without_any_upwards_gemfiles end @@ -77,7 +79,7 @@ class TestGemBundlerVersionFinder < Gem::TestCase end def test_deleted_directory - pend "Cannot perform this test on windows" if win_platform? + pend "Cannot perform this test on windows" if Gem.win_platform? pend "Cannot perform this test on Solaris" if RUBY_PLATFORM.include?("solaris") require "tmpdir" diff --git a/test/rubygems/test_gem_ci_detector.rb b/test/rubygems/test_gem_ci_detector.rb new file mode 100644 index 0000000000..a28ee49f4b --- /dev/null +++ b/test/rubygems/test_gem_ci_detector.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require_relative "helper" +require "rubygems" + +class TestCiDetector < Gem::TestCase + def test_ci? + with_env("FOO" => "bar") { assert_equal(false, Gem::CIDetector.ci?) } + with_env("CI" => "true") { assert_equal(true, Gem::CIDetector.ci?) } + with_env("CONTINUOUS_INTEGRATION" => "1") { assert_equal(true, Gem::CIDetector.ci?) } + with_env("RUN_ID" => "0", "TASKCLUSTER_ROOT_URL" => "2") do + assert_equal(true, Gem::CIDetector.ci?) + end + end + + def test_ci_strings + with_env("FOO" => "bar") { assert_empty(Gem::CIDetector.ci_strings) } + with_env("TRAVIS" => "true") { assert_equal(["travis"], Gem::CIDetector.ci_strings) } + with_env("CI" => "true", "CIRCLECI" => "true", "GITHUB_ACTIONS" => "true") do + assert_equal(["ci", "circle", "github"], Gem::CIDetector.ci_strings) + end + with_env("CI" => "true", "CI_NAME" => "MYCI") do + assert_equal(["ci", "myci"], Gem::CIDetector.ci_strings) + end + with_env("GITHUB_ACTIONS" => "true", "CI_NAME" => "github") do + assert_equal(["github"], Gem::CIDetector.ci_strings) + end + with_env("TASKCLUSTER_ROOT_URL" => "https://foo.bar", "DSARI" => "1", "CI_NAME" => "") do + assert_equal(["dsari", "taskcluster"], Gem::CIDetector.ci_strings) + end + end +end diff --git a/test/rubygems/test_gem_command.rb b/test/rubygems/test_gem_command.rb index 99fa89364d..3695f9488f 100644 --- a/test/rubygems/test_gem_command.rb +++ b/test/rubygems/test_gem_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/command" @@ -15,7 +16,7 @@ class TestGemCommand < Gem::TestCase @common_options = Gem::Command.common_options.dup Gem::Command.common_options.clear Gem::Command.common_options << [ - ["-x", "--exe", "Execute"], lambda do |*a| + ["-x", "--exe", "Execute"], lambda do |*_a| @xopt = true end ] @@ -55,7 +56,9 @@ class TestGemCommand < Gem::TestCase end def test_self_extra_args - verbose, $VERBOSE, separator = $VERBOSE, nil, $; + verbose = $VERBOSE + $VERBOSE = nil + separator = $; extra_args = Gem::Command.extra_args Gem::Command.extra_args = %w[--all] @@ -68,7 +71,6 @@ class TestGemCommand < Gem::TestCase Gem::Command.extra_args = "--awesome=true --verbose" assert_equal %w[--awesome=true --verbose], Gem::Command.extra_args - ensure Gem::Command.extra_args = extra_args $; = separator @@ -90,7 +92,7 @@ class TestGemCommand < Gem::TestCase options[:help] = value end - @cmd.defaults = { :help => true } + @cmd.defaults = { help: true } @cmd.when_invoked do |options| assert options[:help], "Help options should default true" @@ -100,7 +102,7 @@ class TestGemCommand < Gem::TestCase @cmd.invoke end - assert_match %r{Usage: gem doit}, @ui.output + assert_match(/Usage: gem doit/, @ui.output) end def test_invoke @@ -151,7 +153,7 @@ class TestGemCommand < Gem::TestCase done = false use_ui @ui do - @cmd.add_option("-h", "--help [COMMAND]", "Get help on COMMAND") do |value, options| + @cmd.add_option("-h", "--help [COMMAND]", "Get help on COMMAND") do |_value, options| options[:help] = true done = true end @@ -174,7 +176,7 @@ class TestGemCommand < Gem::TestCase end def test_invoke_with_options - @cmd.add_option("-h", "--help [COMMAND]", "Get help on COMMAND") do |value, options| + @cmd.add_option("-h", "--help [COMMAND]", "Get help on COMMAND") do |_value, options| options[:help] = true end @@ -186,7 +188,7 @@ class TestGemCommand < Gem::TestCase @cmd.invoke "-h" end - assert_match %r{Usage: gem doit}, @ui.output + assert_match(/Usage: gem doit/, @ui.output) end def test_add_option @@ -202,13 +204,13 @@ class TestGemCommand < Gem::TestCase end def test_option_recognition - @cmd.add_option("-h", "--help [COMMAND]", "Get help on COMMAND") do |value, options| + @cmd.add_option("-h", "--help [COMMAND]", "Get help on COMMAND") do |_value, options| options[:help] = true end - @cmd.add_option("-f", "--file FILE", "File option") do |value, options| + @cmd.add_option("-f", "--file FILE", "File option") do |_value, options| options[:help] = true end - @cmd.add_option("--silent", "Silence RubyGems output") do |value, options| + @cmd.add_option("--silent", "Silence RubyGems output") do |_value, options| options[:silent] = true end assert @cmd.handles?(["-x"]) @@ -232,11 +234,11 @@ class TestGemCommand < Gem::TestCase WARNING: The \"--test\" option has been deprecated and will be removed in Rubygems 3.1. EXPECTED - testCommand = Class.new(Gem::Command) do + test_command = Class.new(Gem::Command) do def initialize super("test", "Gem::Command instance for testing") - add_option("-t", "--test", "Test command") do |value, options| + add_option("-t", "--test", "Test command") do |_value, options| options[:test] = true end @@ -248,7 +250,7 @@ WARNING: The \"--test\" option has been deprecated and will be removed in Rubyg end end - cmd = testCommand.new + cmd = test_command.new use_ui @ui do cmd.invoke("--test") @@ -261,11 +263,11 @@ WARNING: The \"--test\" option has been deprecated and will be removed in Rubyg WARNING: The \"--test\" option has been deprecated and will be removed in future versions of Rubygems. EXPECTED - testCommand = Class.new(Gem::Command) do + test_command = Class.new(Gem::Command) do def initialize super("test", "Gem::Command instance for testing") - add_option("-t", "--test", "Test command") do |value, options| + add_option("-t", "--test", "Test command") do |_value, options| options[:test] = true end @@ -277,7 +279,7 @@ WARNING: The \"--test\" option has been deprecated and will be removed in futur end end - cmd = testCommand.new + cmd = test_command.new use_ui @ui do cmd.invoke("--test") @@ -290,11 +292,11 @@ WARNING: The \"--test\" option has been deprecated and will be removed in futur WARNING: The \"--test\" option has been deprecated and will be removed in Rubygems 3.1. Whether you set `--test` mode or not, this dummy app always runs in test mode. EXPECTED - testCommand = Class.new(Gem::Command) do + test_command = Class.new(Gem::Command) do def initialize super("test", "Gem::Command instance for testing") - add_option("-t", "--test", "Test command") do |value, options| + add_option("-t", "--test", "Test command") do |_value, options| options[:test] = true end @@ -306,7 +308,7 @@ WARNING: The \"--test\" option has been deprecated and will be removed in Rubyg end end - cmd = testCommand.new + cmd = test_command.new use_ui @ui do cmd.invoke("--test") @@ -319,11 +321,11 @@ WARNING: The \"--test\" option has been deprecated and will be removed in Rubyg WARNING: The \"--test\" option has been deprecated and will be removed in future versions of Rubygems. Whether you set `--test` mode or not, this dummy app always runs in test mode. EXPECTED - testCommand = Class.new(Gem::Command) do + test_command = Class.new(Gem::Command) do def initialize super("test", "Gem::Command instance for testing") - add_option("-t", "--test", "Test command") do |value, options| + add_option("-t", "--test", "Test command") do |_value, options| options[:test] = true end @@ -335,7 +337,7 @@ WARNING: The \"--test\" option has been deprecated and will be removed in futur end end - cmd = testCommand.new + cmd = test_command.new use_ui @ui do cmd.invoke("--test") diff --git a/test/rubygems/test_gem_command_manager.rb b/test/rubygems/test_gem_command_manager.rb index b8f35192ae..f04ec0cafa 100644 --- a/test/rubygems/test_gem_command_manager.rb +++ b/test/rubygems/test_gem_command_manager.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/command_manager" class TestGemCommandManager < Gem::TestCase - PROJECT_DIR = File.expand_path("../..", __dir__).tap(&Gem::UNTAINT) + PROJECT_DIR = File.expand_path("../..", __dir__) def setup super @@ -76,7 +77,7 @@ class TestGemCommandManager < Gem::TestCase message = "Unknown command pish".dup - if RUBY_VERSION >= "2.4" && defined?(DidYouMean::SPELL_CHECKERS) && defined?(DidYouMean::Correctable) + if defined?(DidYouMean::SPELL_CHECKERS) && defined?(DidYouMean::Correctable) message << "\nDid you mean? \"push\"" end @@ -126,6 +127,46 @@ class TestGemCommandManager < Gem::TestCase @command_manager.unregister_command :crash end + def test_process_args_with_c_flag + custom_start_point = File.join @tempdir, "nice_folder" + FileUtils.mkdir_p custom_start_point + + execution_path = nil + use_ui @ui do + @command_manager[:install].when_invoked do + execution_path = Dir.pwd + true + end + @command_manager.process_args %W[-C #{custom_start_point} install net-scp-4.0.0.gem --local] + end + + assert_equal custom_start_point, execution_path + end + + def test_process_args_with_c_flag_without_path + use_ui @ui do + assert_raise Gem::MockGemUi::TermError do + @command_manager.process_args %w[-C install net-scp-4.0.0.gem --local] + end + end + + assert_match(/install isn't a directory\./i, @ui.error) + end + + def test_process_args_with_c_flag_path_not_found + custom_start_point = File.join @tempdir, "nice_folder" + FileUtils.mkdir_p custom_start_point + custom_start_point.tr!("_", "-") + + use_ui @ui do + assert_raise Gem::MockGemUi::TermError do + @command_manager.process_args %W[-C #{custom_start_point} install net-scp-4.0.0.gem --local] + end + end + + assert_match(/#{Regexp.quote(custom_start_point)} isn't a directory\./i, @ui.error) + end + def test_process_args_bad_arg use_ui @ui do assert_raise Gem::MockGemUi::TermError do @@ -136,9 +177,9 @@ class TestGemCommandManager < Gem::TestCase assert_match(/invalid option: --bad-arg/i, @ui.error) end - # HACK move to install command test + # HACK: move to install command test def test_process_args_install - #capture all install options + # capture all install options use_ui @ui do check_options = nil @command_manager["install"].when_invoked do |options| @@ -146,7 +187,7 @@ class TestGemCommandManager < Gem::TestCase true end - #check defaults + # check defaults @command_manager.process_args %w[install] assert_equal %w[ri], check_options[:document].sort assert_equal false, check_options[:force] @@ -156,7 +197,7 @@ class TestGemCommandManager < Gem::TestCase assert_nil check_options[:install_dir] assert_nil check_options[:bin_dir] - #check settings + # check settings check_options = nil @command_manager.process_args %w[ install --force --local --document=ri,rdoc --install-dir . @@ -170,91 +211,91 @@ class TestGemCommandManager < Gem::TestCase assert_equal Dir.pwd, check_options[:install_dir] assert_equal Dir.pwd, check_options[:bin_dir] - #check remote domain + # check remote domain check_options = nil @command_manager.process_args %w[install --remote] assert_equal :remote, check_options[:domain] - #check both domain + # check both domain check_options = nil @command_manager.process_args %w[install --both] assert_equal :both, check_options[:domain] - #check both domain + # check both domain check_options = nil @command_manager.process_args %w[install --both] assert_equal :both, check_options[:domain] end end - # HACK move to uninstall command test + # HACK: move to uninstall command test def test_process_args_uninstall - #capture all uninstall options + # capture all uninstall options check_options = nil @command_manager["uninstall"].when_invoked do |options| check_options = options true end - #check defaults + # check defaults @command_manager.process_args %w[uninstall] assert_equal Gem::Requirement.default, check_options[:version] - #check settings + # check settings check_options = nil @command_manager.process_args %w[uninstall foobar --version 3.0] assert_equal "foobar", check_options[:args].first assert_equal Gem::Requirement.new("3.0"), check_options[:version] end - # HACK move to check command test + # HACK: move to check command test def test_process_args_check - #capture all check options + # capture all check options check_options = nil @command_manager["check"].when_invoked do |options| check_options = options true end - #check defaults + # check defaults @command_manager.process_args %w[check] assert_equal true, check_options[:alien] - #check settings + # check settings check_options = nil @command_manager.process_args %w[check foobar --alien] assert_equal true, check_options[:alien] end - # HACK move to build command test + # HACK: move to build command test def test_process_args_build - #capture all build options + # capture all build options check_options = nil @command_manager["build"].when_invoked do |options| check_options = options true end - #check defaults + # check defaults @command_manager.process_args %w[build] - #NOTE: Currently no defaults + # NOTE: Currently no defaults - #check settings + # check settings check_options = nil @command_manager.process_args %w[build foobar.rb] assert_equal "foobar.rb", check_options[:args].first end - # HACK move to query command test + # HACK: move to query command test def test_process_args_query - #capture all query options + # capture all query options check_options = nil @command_manager["query"].when_invoked do |options| check_options = options true end - #check defaults + # check defaults Gem::Deprecate.skip_during do @command_manager.process_args %w[query] end @@ -262,7 +303,7 @@ class TestGemCommandManager < Gem::TestCase assert_equal :local, check_options[:domain] assert_equal false, check_options[:details] - #check settings + # check settings check_options = nil Gem::Deprecate.skip_during do @command_manager.process_args %w[query --name foobar --local --details] @@ -271,14 +312,14 @@ class TestGemCommandManager < Gem::TestCase assert_equal :local, check_options[:domain] assert_equal true, check_options[:details] - #remote domain + # remote domain check_options = nil Gem::Deprecate.skip_during do @command_manager.process_args %w[query --remote] end assert_equal :remote, check_options[:domain] - #both (local/remote) domains + # both (local/remote) domains check_options = nil Gem::Deprecate.skip_during do @command_manager.process_args %w[query --both] @@ -286,20 +327,20 @@ class TestGemCommandManager < Gem::TestCase assert_equal :both, check_options[:domain] end - # HACK move to update command test + # HACK: move to update command test def test_process_args_update - #capture all update options + # capture all update options check_options = nil @command_manager["update"].when_invoked do |options| check_options = options true end - #check defaults + # check defaults @command_manager.process_args %w[update] assert_includes check_options[:document], "ri" - #check settings + # check settings check_options = nil @command_manager.process_args %w[update --force --document=ri --install-dir .] assert_includes check_options[:document], "ri" @@ -327,7 +368,32 @@ class TestGemCommandManager < Gem::TestCase end assert_equal "pew pew!\n", @ui.output - assert_match(/WARNING: foo command is deprecated. It will be removed in Rubygems [0-9]+/, @ui.error) + assert_match(/WARNING: foo command is deprecated\. It will be removed in Rubygems [0-9]+/, @ui.error) + ensure + Gem::Commands.send(:remove_const, :FooCommand) + end + + def test_deprecated_command_with_version + require "rubygems/command" + foo_command = Class.new(Gem::Command) do + extend Gem::Deprecate + + rubygems_deprecate_command("9.9.9") + + def execute + say "pew pew!" + end + end + + Gem::Commands.send(:const_set, :FooCommand, foo_command) + @command_manager.register_command(:foo, foo_command.new("foo")) + + use_ui @ui do + @command_manager.process_args(%w[foo]) + end + + assert_equal "pew pew!\n", @ui.output + assert_match(/WARNING: foo command is deprecated\. It will be removed in Rubygems 9\.9\.9/, @ui.error) ensure Gem::Commands.send(:remove_const, :FooCommand) end diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb index 1edb30f221..d44126d204 100644 --- a/test/rubygems/test_gem_commands_build_command.rb +++ b/test/rubygems/test_gem_commands_build_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/build_command" require "rubygems/package" @@ -25,8 +26,9 @@ class TestGemCommandsBuildCommand < Gem::TestCase end @gem = util_spec "some_gem" do |s| - s.license = "AGPL-3.0" + s.license = "AGPL-3.0-only" s.files = ["README.md"] + s.required_ruby_version = "2.3.0" end @cmd = Gem::Commands::BuildCommand.new @@ -41,6 +43,16 @@ class TestGemCommandsBuildCommand < Gem::TestCase assert_includes Gem.platforms, Gem::Platform.local end + def test_handle_deprecated_options + use_ui @ui do + @cmd.handle_options %w[-C ./test/dir] + end + + assert_equal "WARNING: The \"-C\" option has been deprecated and will be removed in Rubygems 4.0. " \ + "-C is a global flag now. Use `gem -C PATH build GEMSPEC_FILE [options]` instead\n", + @ui.error + end + def test_options_filename gemspec_file = File.join(@tempdir, @gem.spec_name) @@ -167,6 +179,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase def test_execute_strict_with_warnings bad_gem = util_spec "some_bad_gem" do |s| s.files = ["README.md"] + s.required_ruby_version = ">= 1.9.3" end gemspec_file = File.join(@tempdir, bad_gem.spec_name) @@ -187,8 +200,9 @@ class TestGemCommandsBuildCommand < Gem::TestCase end error = @ui.error.split "\n" - assert_equal "WARNING: licenses is empty, but is recommended. Use a license identifier from", error.shift - assert_equal "http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.", error.shift + assert_equal "WARNING: licenses is empty, but is recommended. Use an license identifier from", error.shift + assert_equal "https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,", error.shift + assert_equal "or set it to nil if you don't want to specify a license.", error.shift assert_equal "WARNING: See https://guides.rubygems.org/specification-reference/ for help", error.shift assert_equal [], error @@ -582,7 +596,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase end def test_build_signed_gem - pend "openssl is missing" unless Gem::HAVE_OPENSSL && !java_platform? + pend "openssl is missing" unless Gem::HAVE_OPENSSL && !Gem.java_platform? trust_dir = Gem::Security.trust_dir @@ -609,7 +623,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase end def test_build_signed_gem_with_cert_expiration_length_days - pend "openssl is missing" unless Gem::HAVE_OPENSSL && !java_platform? + pend "openssl is missing" unless Gem::HAVE_OPENSSL && !Gem.java_platform? gem_path = File.join Gem.user_home, ".gem" Dir.mkdir gem_path @@ -653,7 +667,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase end def test_build_auto_resign_cert - pend "openssl is missing" unless Gem::HAVE_OPENSSL && !java_platform? + pend "openssl is missing" unless Gem::HAVE_OPENSSL && !Gem.java_platform? gem_path = File.join Gem.user_home, ".gem" Dir.mkdir gem_path @@ -689,7 +703,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase output = @ui.output.split "\n" assert_equal "INFO: Your certificate has expired, trying to re-sign it...", output.shift - assert_equal "INFO: Your cert: #{tmp_expired_cert_file } has been auto re-signed with the key: #{tmp_private_key_file}", output.shift + assert_equal "INFO: Your cert: #{tmp_expired_cert_file} has been auto re-signed with the key: #{tmp_private_key_file}", output.shift assert_match(/INFO: Your expired cert will be located at: .+\Wgem-public_cert\.pem\.expired\.[0-9]+/, output.shift) end diff --git a/test/rubygems/test_gem_commands_cert_command.rb b/test/rubygems/test_gem_commands_cert_command.rb index ffcc14ffbb..c173467935 100644 --- a/test/rubygems/test_gem_commands_cert_command.rb +++ b/test/rubygems/test_gem_commands_cert_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/cert_command" @@ -46,7 +47,7 @@ class TestGemCommandsCertCommand < Gem::TestCase matches = @cmd.certificates_matching "" - # HACK OpenSSL::X509::Certificate#== is Object#==, so do this the hard way + # HACK: OpenSSL::X509::Certificate#== is Object#==, so do this the hard way match = matches.next assert_equal ALTERNATE_CERT.to_pem, match.first.to_pem assert_equal @trust_dir.cert_path(ALTERNATE_CERT), match.last @@ -128,9 +129,9 @@ Added '/CN=alternate/DC=example' output.shift assert_equal "Please repeat the passphrase for your Private Key: ", output.shift - assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}", + assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}", output.shift - assert_equal "Private Key: #{File.join @tempdir, 'gem-private_key.pem'}", + assert_equal "Private Key: #{File.join @tempdir, "gem-private_key.pem"}", output.shift assert_equal "Don't forget to move the key file to somewhere private!", @@ -160,9 +161,9 @@ Added '/CN=alternate/DC=example' output.shift assert_equal "Please repeat the passphrase for your Private Key: ", output.shift - assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}", + assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}", output.shift - assert_equal "Private Key: #{File.join @tempdir, 'gem-private_key.pem'}", + assert_equal "Private Key: #{File.join @tempdir, "gem-private_key.pem"}", output.shift assert_equal "Don't forget to move the key file to somewhere private!", @@ -220,9 +221,9 @@ Added '/CN=alternate/DC=example' output.shift assert_equal "Please repeat the passphrase for your Private Key: ", output.shift - assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}", + assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}", output.shift - assert_equal "Private Key: #{File.join @tempdir, 'gem-private_key.pem'}", + assert_equal "Private Key: #{File.join @tempdir, "gem-private_key.pem"}", output.shift assert_equal "Don't forget to move the key file to somewhere private!", @@ -283,7 +284,7 @@ Added '/CN=alternate/DC=example' output = @ui.output.split "\n" - assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}", + assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}", output.shift assert_empty output @@ -305,7 +306,7 @@ Added '/CN=alternate/DC=example' output = @ui.output.split "\n" - assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}", + assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}", output.shift assert_empty output @@ -326,7 +327,7 @@ Added '/CN=alternate/DC=example' output = @ui.output.split "\n" - assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}", + assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}", output.shift assert_empty output @@ -475,7 +476,7 @@ Removed '/CN=alternate/DC=example' def test_execute_sign path = File.join @tempdir, "cert.pem" - Gem::Security.write ALTERNATE_CERT, path, 0600 + Gem::Security.write ALTERNATE_CERT, path, 0o600 assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s @@ -497,14 +498,14 @@ Removed '/CN=alternate/DC=example' assert_equal "/CN=nobody/DC=example", cert.issuer.to_s - mask = 0100600 & (~File.umask) + mask = 0o100600 & (~File.umask) - assert_equal mask, File.stat(path).mode unless win_platform? + assert_equal mask, File.stat(path).mode unless Gem.win_platform? end def test_execute_sign_encrypted_key path = File.join @tempdir, "cert.pem" - Gem::Security.write ALTERNATE_CERT, path, 0600 + Gem::Security.write ALTERNATE_CERT, path, 0o600 assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s @@ -526,9 +527,9 @@ Removed '/CN=alternate/DC=example' assert_equal "/CN=nobody/DC=example", cert.issuer.to_s - mask = 0100600 & (~File.umask) + mask = 0o100600 & (~File.umask) - assert_equal mask, File.stat(path).mode unless win_platform? + assert_equal mask, File.stat(path).mode unless Gem.win_platform? end def test_execute_sign_default @@ -541,7 +542,7 @@ Removed '/CN=alternate/DC=example' Gem::Security.write PUBLIC_CERT, public_cert_path path = File.join @tempdir, "cert.pem" - Gem::Security.write ALTERNATE_CERT, path, 0600 + Gem::Security.write ALTERNATE_CERT, path, 0o600 assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s @@ -558,22 +559,22 @@ Removed '/CN=alternate/DC=example' assert_equal "/CN=nobody/DC=example", cert.issuer.to_s - mask = 0100600 & (~File.umask) + mask = 0o100600 & (~File.umask) - assert_equal mask, File.stat(path).mode unless win_platform? + assert_equal mask, File.stat(path).mode unless Gem.win_platform? end def test_execute_sign_default_encrypted_key FileUtils.mkdir_p File.join(Gem.user_home, ".gem") private_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem" - Gem::Security.write ENCRYPTED_PRIVATE_KEY, private_key_path, 0600, PRIVATE_KEY_PASSPHRASE + Gem::Security.write ENCRYPTED_PRIVATE_KEY, private_key_path, 0o600, PRIVATE_KEY_PASSPHRASE public_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem" Gem::Security.write PUBLIC_CERT, public_cert_path path = File.join @tempdir, "cert.pem" - Gem::Security.write ALTERNATE_CERT, path, 0600 + Gem::Security.write ALTERNATE_CERT, path, 0o600 assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s @@ -590,9 +591,9 @@ Removed '/CN=alternate/DC=example' assert_equal "/CN=nobody/DC=example", cert.issuer.to_s - mask = 0100600 & (~File.umask) + mask = 0o100600 & (~File.umask) - assert_equal mask, File.stat(path).mode unless win_platform? + assert_equal mask, File.stat(path).mode unless Gem.win_platform? end def test_execute_sign_no_cert @@ -602,7 +603,7 @@ Removed '/CN=alternate/DC=example' Gem::Security.write PRIVATE_KEY, private_key_path path = File.join @tempdir, "cert.pem" - Gem::Security.write ALTERNATE_CERT, path, 0600 + Gem::Security.write ALTERNATE_CERT, path, 0o600 assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s @@ -630,7 +631,7 @@ ERROR: --certificate not specified and ~/.gem/gem-public_cert.pem does not exis Gem::Security.write PUBLIC_CERT, public_cert_path path = File.join @tempdir, "cert.pem" - Gem::Security.write ALTERNATE_CERT, path, 0600 + Gem::Security.write ALTERNATE_CERT, path, 0o600 assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s @@ -656,7 +657,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis Dir.mkdir gem_path path = File.join @tempdir, "cert.pem" - Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0600 + Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0o600 assert_equal "/CN=nobody/DC=example", EXPIRED_PUBLIC_CERT.issuer.to_s @@ -676,8 +677,9 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis expected_path = File.join(gem_path, "#{File.basename(tmp_expired_cert_file)}.expired") + assert_include(@ui.output, "INFO: Your certificate #{tmp_expired_cert_file} has been re-signed\n") assert_match( - /INFO: Your certificate #{tmp_expired_cert_file} has been re-signed\nINFO: Your expired certificate will be located at: #{expected_path}\.[0-9]+/, + /INFO: Your expired certificate will be located at: #{Regexp.quote(expected_path)}\.[0-9]+/, @ui.output ) assert_equal "", @ui.error @@ -688,7 +690,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis Dir.mkdir gem_path path = File.join @tempdir, "cert.pem" - Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0600 + Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0o600 assert_equal "/CN=nobody/DC=example", EXPIRED_PUBLIC_CERT.issuer.to_s @@ -731,12 +733,12 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis ] assert_equal [PUBLIC_CERT.to_pem, ALTERNATE_CERT.to_pem], - @cmd.options[:add].map {|cert| cert.to_pem } + @cmd.options[:add].map(&:to_pem) assert_equal %w[nobody example], @cmd.options[:remove] assert_equal %w[nobody@example other@example], - @cmd.options[:build].map {|name| name.to_s } + @cmd.options[:build].map(&:to_s) assert_equal ["", "example"], @cmd.options[:list] end @@ -777,7 +779,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis @cmd.handle_options %W[--certificate #{bad}] end - assert_equal "invalid argument: " + + assert_equal "invalid argument: " \ "--certificate #{bad}: invalid X509 certificate", e.message end @@ -788,7 +790,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis @cmd.handle_options %W[--private-key #{nonexistent}] end - assert_equal "invalid argument: " + + assert_equal "invalid argument: " \ "--private-key #{nonexistent}: does not exist", e.message @@ -806,7 +808,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis @cmd.handle_options %W[--private-key #{PUBLIC_KEY_FILE}] end - assert_equal "invalid argument: " + + assert_equal "invalid argument: " \ "--private-key #{PUBLIC_KEY_FILE}: private key not found", e.message end diff --git a/test/rubygems/test_gem_commands_check_command.rb b/test/rubygems/test_gem_commands_check_command.rb index 9233f7b5ce..65a3093b13 100644 --- a/test/rubygems/test_gem_commands_check_command.rb +++ b/test/rubygems/test_gem_commands_check_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/check_command" diff --git a/test/rubygems/test_gem_commands_cleanup_command.rb b/test/rubygems/test_gem_commands_cleanup_command.rb index 51d59df58c..bcb8871b57 100644 --- a/test/rubygems/test_gem_commands_cleanup_command.rb +++ b/test/rubygems/test_gem_commands_cleanup_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/cleanup_command" require "rubygems/installer" @@ -165,10 +166,10 @@ class TestGemCommandsCleanupCommand < Gem::TestCase end def test_execute_all_user_no_sudo - FileUtils.chmod 0555, @gemhome + FileUtils.chmod 0o555, @gemhome @a_1_1, = util_gem "a", "1.1" - @a_1_1 = install_gem @a_1_1, :user_install => true # pick up user install path + @a_1_1 = install_gem @a_1_1, user_install: true # pick up user install path Gem::Specification.dirs = [Gem.dir, Gem.user_dir] @@ -182,8 +183,8 @@ class TestGemCommandsCleanupCommand < Gem::TestCase assert_path_exist @a_1.gem_dir assert_path_exist @a_1_1.gem_dir ensure - FileUtils.chmod 0755, @gemhome - end unless win_platform? || Process.uid.zero? + FileUtils.chmod 0o755, @gemhome + end unless Gem.win_platform? || Process.uid.zero? def test_execute_dry_run @cmd.options[:args] = %w[a] @@ -230,7 +231,7 @@ class TestGemCommandsCleanupCommand < Gem::TestCase @cmd.execute end - assert_match %r{^Skipped default gems: b-2}, @ui.output + assert_match(/^Skipped default gems: b-2/, @ui.output) assert_empty @ui.error end @@ -242,11 +243,11 @@ class TestGemCommandsCleanupCommand < Gem::TestCase e_1, = util_gem "e", "1" e_2, = util_gem "e", "2" - c_1 = install_gem c_1, :user_install => true # pick up user install path + c_1 = install_gem c_1, user_install: true # pick up user install path c_2 = install_gem c_2 d_1 = install_gem d_1 - d_2 = install_gem d_2, :user_install => true # pick up user install path + d_2 = install_gem d_2, user_install: true # pick up user install path e_1 = install_gem e_1 e_2 = install_gem e_2 @@ -269,8 +270,8 @@ class TestGemCommandsCleanupCommand < Gem::TestCase d_1, = util_gem "d", "1.0" d_2, = util_gem "d", "1.1" - c_1 = install_gem c_1, :user_install => true # pick up user install path - c_2 = install_gem c_2, :user_install => true # pick up user install path + c_1 = install_gem c_1, user_install: true # pick up user install path + c_2 = install_gem c_2, user_install: true # pick up user install path d_1 = install_gem d_1 d_2 = install_gem d_2 diff --git a/test/rubygems/test_gem_commands_contents_command.rb b/test/rubygems/test_gem_commands_contents_command.rb index 1b9da8a92e..d8e6ba3dec 100644 --- a/test/rubygems/test_gem_commands_contents_command.rb +++ b/test/rubygems/test_gem_commands_contents_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/contents_command" @@ -27,7 +28,7 @@ class TestGemCommandsContentsCommand < Gem::TestCase end assert_match %r{lib/foo\.rb}, @ui.output - assert_match %r{Rakefile}, @ui.output + assert_match(/Rakefile/, @ui.output) assert_equal "", @ui.error end @@ -43,7 +44,7 @@ class TestGemCommandsContentsCommand < Gem::TestCase assert_match %r{lib/foo\.rb}, @ui.output assert_match %r{lib/bar\.rb}, @ui.output - assert_match %r{Rakefile}, @ui.output + assert_match(/Rakefile/, @ui.output) assert_equal "", @ui.error end @@ -56,8 +57,8 @@ class TestGemCommandsContentsCommand < Gem::TestCase end end - assert_match %r{Unable to find gem 'foo' in default gem paths}, @ui.output - assert_match %r{Directories searched:}, @ui.output + assert_match(/Unable to find gem 'foo' in default gem paths/, @ui.output) + assert_match(/Directories searched:/, @ui.output) assert_equal "", @ui.error end @@ -71,7 +72,7 @@ class TestGemCommandsContentsCommand < Gem::TestCase end assert_match %r{lib/foo\.rb}, @ui.output - assert_match %r{Rakefile}, @ui.output + assert_match(/Rakefile/, @ui.output) assert_equal "", @ui.error end @@ -86,7 +87,7 @@ class TestGemCommandsContentsCommand < Gem::TestCase end assert_match %r{lib/foo\.rb}, @ui.output - refute_match %r{Rakefile}, @ui.output + refute_match(/Rakefile/, @ui.output) assert_equal "", @ui.error end @@ -147,7 +148,7 @@ class TestGemCommandsContentsCommand < Gem::TestCase assert_match %r{lib/foo\.rb}, @ui.output assert_match %r{lib/bar\.rb}, @ui.output - assert_match %r{Rakefile}, @ui.output + assert_match(/Rakefile/, @ui.output) assert_equal "", @ui.error end diff --git a/test/rubygems/test_gem_commands_dependency_command.rb b/test/rubygems/test_gem_commands_dependency_command.rb index d9571275cb..48fe2f8e8d 100644 --- a/test/rubygems/test_gem_commands_dependency_command.rb +++ b/test/rubygems/test_gem_commands_dependency_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/dependency_command" diff --git a/test/rubygems/test_gem_commands_environment_command.rb b/test/rubygems/test_gem_commands_environment_command.rb index 91ed774cb6..48252d84d4 100644 --- a/test/rubygems/test_gem_commands_environment_command.rb +++ b/test/rubygems/test_gem_commands_environment_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/environment_command" @@ -11,7 +12,8 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase def test_execute orig_sources = Gem.sources.dup - orig_path, ENV["PATH"] = ENV["PATH"], %w[/usr/local/bin /usr/bin /bin].join(File::PATH_SEPARATOR) + orig_path = ENV["PATH"] + ENV["PATH"] = %w[/usr/local/bin /usr/bin /bin].join(File::PATH_SEPARATOR) Gem.sources.replace %w[http://gems.example.com] Gem.configuration["gemcutter_key"] = "blah" @@ -21,34 +23,33 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase @cmd.execute end - assert_match %r{RUBYGEMS VERSION: (\d\.)+\d}, @ui.output - assert_match %r{RUBY VERSION: \d+\.\d+\.\d+ \(.*\) \[.*\]}, @ui.output - assert_match %r{INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}}, - @ui.output - assert_match %r{USER INSTALLATION DIRECTORY: #{Regexp.escape Gem.user_dir}}, - @ui.output - assert_match %r{RUBYGEMS PREFIX: }, @ui.output - assert_match %r{RUBY EXECUTABLE:.*#{RbConfig::CONFIG['ruby_install_name']}}, - @ui.output - assert_match %r{GIT EXECUTABLE: #{@cmd.send(:git_path)}}, @ui.output - assert_match %r{SYSTEM CONFIGURATION DIRECTORY:}, @ui.output - assert_match %r{EXECUTABLE DIRECTORY:}, @ui.output - assert_match %r{RUBYGEMS PLATFORMS:}, @ui.output - assert_match %r{- #{Gem::Platform.local}}, @ui.output - assert_match %r{GEM PATHS:}, @ui.output - assert_match %r{- #{Regexp.escape @gemhome}}, @ui.output - assert_match %r{GEM CONFIGURATION:}, @ui.output - assert_match %r{"gemcutter_key" => "\*\*\*\*"}, @ui.output - assert_match %r{:verbose => }, @ui.output - assert_match %r{REMOTE SOURCES:}, @ui.output - - assert_match %r{- SHELL PATH:}, @ui.output + assert_match(/RUBYGEMS VERSION: (\d\.)+\d/, @ui.output) + assert_match(/RUBY VERSION: \d+\.\d+\.\d+ \(.*\) \[.*\]/, @ui.output) + assert_match(/INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}/, + @ui.output) + assert_match(/USER INSTALLATION DIRECTORY: #{Regexp.escape Gem.user_dir}/, + @ui.output) + assert_match(/RUBYGEMS PREFIX: /, @ui.output) + assert_match(/RUBY EXECUTABLE:.*#{RbConfig::CONFIG["ruby_install_name"]}/, + @ui.output) + assert_match(/GIT EXECUTABLE: #{@cmd.send(:git_path)}/, @ui.output) + assert_match(/SYSTEM CONFIGURATION DIRECTORY:/, @ui.output) + assert_match(/EXECUTABLE DIRECTORY:/, @ui.output) + assert_match(/RUBYGEMS PLATFORMS:/, @ui.output) + assert_match(/- #{Gem::Platform.local}/, @ui.output) + assert_match(/GEM PATHS:/, @ui.output) + assert_match(/- #{Regexp.escape @gemhome}/, @ui.output) + assert_match(/GEM CONFIGURATION:/, @ui.output) + assert_match(/"gemcutter_key" => "\*\*\*\*"/, @ui.output) + assert_match(/:verbose => /, @ui.output) + assert_match(/REMOTE SOURCES:/, @ui.output) + + assert_match(/- SHELL PATH:/, @ui.output) assert_match %r{- /usr/local/bin$}, @ui.output assert_match %r{- /usr/bin$}, @ui.output assert_match %r{- /bin$}, @ui.output assert_empty @ui.error - ensure Gem.sources.replace orig_sources ENV["PATH"] = orig_path @@ -125,7 +126,6 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase assert_equal "http://gems.example.com\n", @ui.output assert_equal "", @ui.error - ensure Gem.sources.replace orig_sources end diff --git a/test/rubygems/test_gem_commands_exec_command.rb b/test/rubygems/test_gem_commands_exec_command.rb new file mode 100644 index 0000000000..e52fe247a2 --- /dev/null +++ b/test/rubygems/test_gem_commands_exec_command.rb @@ -0,0 +1,859 @@ +# frozen_string_literal: true + +require_relative "helper" +require "rubygems/commands/exec_command" + +class TestGemCommandsExecCommand < Gem::TestCase + def setup + @orig_args = Gem::Command.build_args + @orig_specific_extra_args = Gem::Command.specific_extra_args_hash.dup + @orig_extra_args = Gem::Command.extra_args.dup + + super + common_installer_setup + + @cmd = Gem::Commands::ExecCommand.new + + @gem_home = Gem.dir + @gem_path = Gem.path + @test_arch = RbConfig::CONFIG["arch"] + + @installed_specs = [] + Gem.post_install {|installer| @installed_specs << installer.spec } + end + + def teardown + super + + common_installer_teardown + + Gem::Command.build_args = @orig_args + Gem::Command.specific_extra_args_hash = @orig_specific_extra_args + Gem::Command.extra_args = @orig_extra_args + Gem.configuration = nil + end + + def invoke(*args) + @ui.outs.truncate(0) + @ui.outs.rewind + @ui.errs.truncate(0) + @ui.errs.rewind + @installed_specs.clear + + @cmd.invoke(*args) + ensure + Gem::Specification.unresolved_deps.clear + Gem.loaded_specs.clear + Gem.instance_variable_set(:@activated_gem_paths, 0) + Gem.clear_default_specs + Gem.use_paths(@gem_home, @gem_path) + Gem.refresh + 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_platforms + spec_fetcher do |fetcher| + fetcher.download "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 + + fetcher.download "a", 2 do |s| + s.executables = %w[a] + s.files = %w[bin/a lib/a.rb] + s.platform = "x86_64-darwin" + + write_file File.join(*%W[gems #{s.original_name} bin a]) do |f| + f << "Gem.ui.say #{s.original_name.dump}" + end + end + end + + use_ui @ui do + invoke "a:2" + assert_equal "a-2\n", @ui.output + end + + use_ui @ui do + util_set_arch "x86_64-darwin-18" + invoke "a:2" + assert_equal "a-2-x86_64-darwin\n", @ui.output + end + end + + def test_gem_with_platform_dependencies + spec_fetcher do |fetcher| + fetcher.download "a", 2 do |s| + s.executables = %w[a] + s.files = %w[bin/a lib/a.rb] + s.add_runtime_dependency "with_platform" + + write_file File.join(*%W[gems #{s.original_name} bin a]) do |f| + f << 'require "with_platform"' << "\n" + f << 'Gem.ui.say Gem.loaded_specs.each_value.map(&:original_name).sort.join("\n")' + end + end + + fetcher.download "with_platform", 2 do |s| + s.files = %w[lib/with_platform.rb] + s.platform = Gem::Platform.local + end + + fetcher.download "with_platform", 2 do |s| + s.files = %w[lib/with_platform.rb] + end + end + + use_ui @ui do + util_set_arch "unknown-unknown" + invoke "a" + assert_equal "a-2\nwith_platform-2\n", @ui.output + end + + use_ui @ui do + util_set_arch @test_arch + invoke "a" + assert_empty @ui.error + assert_equal "a-2\nwith_platform-2-#{Gem::Platform.local}\n", @ui.output + end + end + + def test_gem_with_platform_and_platform_dependencies + pend "extensions don't quite work on jruby" if Gem.java_platform? + pend "terminates on mswin" if vc_windows? && ruby_repo? + + spec_fetcher do |fetcher| + fetcher.download "a", 2 do |s| + s.executables = %w[a] + s.files = %w[bin/a lib/a.rb] + s.add_runtime_dependency "with_platform" + s.platform = Gem::Platform.local.to_s + + write_file File.join(*%W[gems #{s.original_name} bin a]) do |f| + f << 'require "with_platform"' << "\n" + f << 'Gem.ui.say Gem.loaded_specs.each_value.map(&:original_name).sort.join("\n")' + end + end + + fetcher.download "a", 2 do |s| + s.executables = %w[a] + s.files = %w[bin/a lib/a.rb extconf.rb] + s.add_runtime_dependency "with_platform" + + write_file File.join(*%W[gems #{s.original_name} bin a]) do |f| + f << 'require "with_platform"' << "\n" + f << 'Gem.ui.say Gem.loaded_specs.each_value.map(&:original_name).sort.join("\n")' + end + + s.extensions = %w[extconf.rb] + write_file File.join(*%W[gems #{s.original_name} extconf.rb]) do |f| + f.write <<-RUBY + gem('with_platform', '~> 2.0') + require 'with_platform' + gem 'sometimes_used' + require 'sometimes_used' + require "mkmf" + create_makefile("#{s.name}") + RUBY + end + end + + fetcher.download "with_platform", 2 do |s| + s.files = %w[lib/with_platform.rb] + s.platform = Gem::Platform.local.to_s + end + + fetcher.download "with_platform", 2 do |s| + s.files = %w[lib/with_platform.rb] + s.add_runtime_dependency "sometimes_used" + end + + fetcher.download "sometimes_used", 2 do |s| + s.files = %w[lib/sometimes_used.rb] + end + end + + use_ui @ui do + util_set_arch "unknown-unknown" + invoke "a" + assert_empty @ui.error + assert_equal "Building native extensions. This could take a while...\na-2\nsometimes_used-2\nwith_platform-2\n", @ui.output + end + + use_ui @ui do + util_set_arch @test_arch + invoke "a" + assert_empty @ui.error + assert_equal "a-2-#{Gem::Platform.local}\nwith_platform-2-#{Gem::Platform.local}\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.download "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.download "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 + + 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.download "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 + + use_ui @ui do + invoke "--verbose", "--conservative", "a" + assert_include @ui.output, "a (>= 0) not available locally" + assert_include @ui.output, "a-1 foo" + assert_equal %w[a-1], @installed_specs.map(&:original_name) + end + + 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.download "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 + invoke "--verbose", "--conservative", "a" + assert_not_include @ui.output, "a (>= 0) not available locally" + assert_include @ui.output, "a-1 foo" + assert_empty @installed_specs.map(&:original_name) + end + end + + def test_uses_newest_version + spec_fetcher do |fetcher| + fetcher.download "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 + + use_ui @ui do + invoke "a" + assert_include @ui.output, "a-1 foo" + end + + spec_fetcher do |fetcher| + fetcher.download "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.download "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 + invoke "--verbose", "a:2" + refute_predicate @ui, :terminated? + assert_empty @ui.error + assert_include @ui.output, "a-2 foo" + assert_equal %w[a-2], @installed_specs.map(&:original_name) + end + end + + def test_uses_newest_version_of_dependency + spec_fetcher do |fetcher| + fetcher.gem "a", 1 do |s| + s.executables = %w[] + s.files = %w[lib/a.rb] + s.add_runtime_dependency "b" + end + + fetcher.gem "b", 1 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} + ' ' + File.basename(__FILE__)" + end + end + + fetcher.download "b", 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} + ' ' + File.basename(__FILE__)" + end + end + end + + use_ui @ui do + invoke "a" + assert_include @ui.output, "b-2 a" + assert_equal %w[b-2], @installed_specs.map(&:original_name) + end + end + + def test_gem_exec_gem_uninstall + spec_fetcher do |fetcher| + fetcher.download "a", 2 do |s| + s.executables = %w[a] + s.files = %w[bin/a lib/a.rb] + s.add_runtime_dependency "b" + + write_file File.join(*%W[gems #{s.original_name} bin a]) do |f| + f << "Gem.ui.say #{s.original_name.dump}" + end + end + + fetcher.download "b", 2 do |s| + s.files = %w[lib/b.rb] + end + end + + use_ui @ui do + invoke "a:2" + assert_equal "a-2\n", @ui.output + + invoke "gem", "list", "--local" + assert_includes @ui.output, "a (2)\n" + assert_includes @ui.output, "b (2)\n" + + begin + invoke "gem", "uninstall", "--verbose", "-x", "a" + rescue StandardError + nil + end + + assert_empty @ui.error + refute_includes @ui.output, "running gem exec with" + assert_includes @ui.output, "Successfully uninstalled a-2\n" + + invoke "--verbose", "gem", "uninstall", "b" + assert_includes @ui.output, "Successfully uninstalled b-2\n" + + invoke "gem", "list", "--local" + assert_empty @ui.error + assert_match(/\A\s*\** LOCAL GEMS \**\s*\z/m, @ui.output) + + invoke "gem", "env", "GEM_HOME" + assert_equal "#{@gem_home}/gem_exec\n", @ui.output + end + end + + def test_only_prerelease_available + spec_fetcher do |fetcher| + fetcher.download "a", "1.a" do |s| + s.executables = %w[a] + s.files = %w[lib/a.rb bin/a] + + 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 + + use_ui @ui do + assert_raise Gem::MockGemUi::TermError do + invoke "a" + end + assert_equal "ERROR: Could not find a valid gem 'a' (>= 0) in any repository\n" \ + "ERROR: Possible alternatives: a\n", @ui.error + assert_empty @ui.output + assert_empty @installed_specs + end + + use_ui @ui do + invoke "a:1.a" + assert_empty @ui.error + assert_equal "a-1.a a\n", @ui.output + assert_equal %w[a-1.a], @installed_specs.map(&:full_name) + end + + FileUtils.rm_rf Gem.dir + + use_ui @ui do + invoke "--version", ">= 1.a", "a" + assert_empty @ui.error + assert_equal "a-1.a a\n", @ui.output + assert_equal %w[a-1.a], @installed_specs.map(&:full_name) + end + + FileUtils.rm_rf Gem.dir + + use_ui @ui do + invoke "--pre", "a" + assert_empty @ui.error + assert_equal "a-1.a a\n", @ui.output + assert_equal %w[a-1.a], @installed_specs.map(&:full_name) + end + end + + def test_newer_prerelease_available + spec_fetcher do |fetcher| + fetcher.download "a", "1" do |s| + s.executables = %w[a] + s.files = %w[lib/a.rb bin/a] + + 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 + + fetcher.download "a", "1.1.a" do |s| + s.executables = %w[a] + s.files = %w[lib/a.rb bin/a] + + 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 + + use_ui @ui do + invoke "a" + assert_empty @ui.error + assert_equal "a-1 a\n", @ui.output + assert_equal %w[a-1], @installed_specs.map(&:full_name) + end + + FileUtils.rm_rf Gem.dir + + use_ui @ui do + invoke "a:1.1.a" + assert_empty @ui.error + assert_equal "a-1.1.a a\n", @ui.output + assert_equal %w[a-1.1.a], @installed_specs.map(&:full_name) + end + + FileUtils.rm_rf Gem.dir + + use_ui @ui do + invoke "--version", ">= 1.a", "a" + assert_empty @ui.error + assert_equal "a-1.1.a a\n", @ui.output + assert_equal %w[a-1.1.a], @installed_specs.map(&:full_name) + end + + FileUtils.rm_rf Gem.dir + + use_ui @ui do + invoke "--pre", "a" + assert_empty @ui.error + assert_equal "a-1.1.a a\n", @ui.output + assert_equal %w[a-1.1.a], @installed_specs.map(&:full_name) + end + end +end diff --git a/test/rubygems/test_gem_commands_fetch_command.rb b/test/rubygems/test_gem_commands_fetch_command.rb index f2a4464c7d..e8710d3cd1 100644 --- a/test/rubygems/test_gem_commands_fetch_command.rb +++ b/test/rubygems/test_gem_commands_fetch_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/package" require "rubygems/security" diff --git a/test/rubygems/test_gem_commands_generate_index_command.rb b/test/rubygems/test_gem_commands_generate_index_command.rb deleted file mode 100644 index c0e18119ed..0000000000 --- a/test/rubygems/test_gem_commands_generate_index_command.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: true -require_relative "helper" -require "rubygems/indexer" -require "rubygems/commands/generate_index_command" - -class TestGemCommandsGenerateIndexCommand < Gem::TestCase - def setup - super - - @cmd = Gem::Commands::GenerateIndexCommand.new - @cmd.options[:directory] = @gemhome - end - - def test_execute - use_ui @ui do - @cmd.execute - end - - specs = File.join @gemhome, "specs.4.8.gz" - - assert File.exist?(specs), specs - end - - def test_execute_no_modern - @cmd.options[:modern] = false - - use_ui @ui do - @cmd.execute - end - - specs = File.join @gemhome, "specs.4.8.gz" - - assert File.exist?(specs), specs - end - - def test_handle_options_directory - return if win_platform? - refute_equal "/nonexistent", @cmd.options[:directory] - - @cmd.handle_options %w[--directory /nonexistent] - - assert_equal "/nonexistent", @cmd.options[:directory] - end - - def test_handle_options_directory_windows - return unless win_platform? - - refute_equal "/nonexistent", @cmd.options[:directory] - - @cmd.handle_options %w[--directory C:/nonexistent] - - assert_equal "C:/nonexistent", @cmd.options[:directory] - end - - def test_handle_options_update - @cmd.handle_options %w[--update] - - assert @cmd.options[:update] - end - - def test_handle_options_modern - use_ui @ui do - @cmd.handle_options %w[--modern] - end - - assert_equal \ - "WARNING: The \"--modern\" option has been deprecated and will be removed in Rubygems 4.0. Modern indexes (specs, latest_specs, and prerelease_specs) are always generated, so this option is not needed.\n", - @ui.error - end - - def test_handle_options_no_modern - use_ui @ui do - @cmd.handle_options %w[--no-modern] - end - - assert_equal \ - "WARNING: The \"--no-modern\" option has been deprecated and will be removed in Rubygems 4.0. The `--no-modern` option is currently ignored. Modern indexes (specs, latest_specs, and prerelease_specs) are always generated.\n", - @ui.error - end -end diff --git a/test/rubygems/test_gem_commands_help_command.rb b/test/rubygems/test_gem_commands_help_command.rb index b84bc4f7ef..359da0a6d0 100644 --- a/test/rubygems/test_gem_commands_help_command.rb +++ b/test/rubygems/test_gem_commands_help_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require "rubygems" require_relative "helper" require "rubygems/commands/help_command" @@ -55,7 +56,7 @@ class TestGemCommandsHelpCommand < Gem::TestCase if Gem::HAVE_OPENSSL assert_empty err - refute_match %r{No command found for }, out + refute_match(/No command found for /, out) end end end @@ -63,7 +64,7 @@ class TestGemCommandsHelpCommand < Gem::TestCase def test_gem_help_commands_omits_deprecated_commands mgr = Gem::CommandManager.new - util_gem "commands" do |out, err| + util_gem "commands" do |out, _err| deprecated_commands = mgr.command_names.select {|cmd| mgr[cmd].deprecated? } deprecated_commands.each do |cmd| refute_match(/\A\s+#{cmd}\s+\S+\z/, out) diff --git a/test/rubygems/test_gem_commands_info_command.rb b/test/rubygems/test_gem_commands_info_command.rb index b18b405da6..83e4c8a896 100644 --- a/test/rubygems/test_gem_commands_info_command.rb +++ b/test/rubygems/test_gem_commands_info_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/info_command" @@ -32,12 +33,38 @@ class TestGemCommandsInfoCommand < Gem::TestCase @cmd.execute end - assert_match %r{#{@gem.name} \(#{@gem.version}\)\n}, @ui.output - assert_match %r{Authors: #{@gem.authors.join(', ')}\n}, @ui.output - assert_match %r{Homepage: #{@gem.homepage}\n}, @ui.output - assert_match %r{License: #{@gem.license}\n}, @ui.output - assert_match %r{Installed at: #{@gem.base_dir}\n}, @ui.output - assert_match %r{#{@gem.summary}\n}, @ui.output + assert_include(@ui.output, "#{@gem.name} (#{@gem.version})\n") + assert_include(@ui.output, "Authors: #{@gem.authors.join(", ")}\n") + assert_include(@ui.output, "Homepage: #{@gem.homepage}\n") + assert_include(@ui.output, "License: #{@gem.license}\n") + assert_include(@ui.output, "Installed at: #{@gem.base_dir}\n") + assert_include(@ui.output, "#{@gem.summary}\n") assert_match "", @ui.error end + + def test_execute_with_version_flag + spec_fetcher do |fetcher| + fetcher.spec "coolgem", "1.0" + fetcher.spec "coolgem", "2.0" + end + + @cmd.handle_options %w[coolgem --remote --version 1.0] + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF + +*** REMOTE GEMS *** + +coolgem (1.0) + Author: A User + Homepage: http://example.com + + this is a summary + EOF + + assert_equal expected, @ui.output + end end diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb index 7a58bcd7cb..5b09512ac4 100644 --- a/test/rubygems/test_gem_commands_install_command.rb +++ b/test/rubygems/test_gem_commands_install_command.rb @@ -1,11 +1,14 @@ # frozen_string_literal: true + require_relative "helper" +require_relative "test_gem_update_suggestion" require "rubygems/commands/install_command" require "rubygems/request_set" require "rubygems/rdoc" class TestGemCommandsInstallCommand < Gem::TestCase def setup + @orig_args = Gem::Command.build_args super common_installer_setup @@ -13,7 +16,6 @@ class TestGemCommandsInstallCommand < Gem::TestCase @cmd.options[:document] = [] @gemdeps = "tmp_install_gemdeps" - @orig_args = Gem::Command.build_args common_installer_setup end @@ -42,7 +44,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase end end - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) end def test_execute_explicit_version_includes_prerelease @@ -64,7 +66,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase end end - assert_equal %w[a-2.a], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2.a], @cmd.installed_specs.map(&:full_name) end def test_execute_local @@ -90,7 +92,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase end end - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) assert_match "1 gem installed", @ui.output end @@ -181,40 +183,35 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a end end - assert_equal %w[a-2 b-2.a c-3], @cmd.installed_specs.map {|spec| spec.full_name }.sort + assert_equal %w[a-2 b-2.a c-3], @cmd.installed_specs.map(&:full_name).sort assert_match "3 gems installed", @ui.output end def test_execute_no_user_install - pend "skipped on MS Windows (chmod has no effect)" if win_platform? + pend "skipped on MS Windows (chmod has no effect)" if Gem.win_platform? pend "skipped in root privilege" if Process.uid.zero? - specs = spec_fetcher do |fetcher| - fetcher.gem "a", 2 + spec_fetcher do |fetcher| + fetcher.download "a", 2 end @cmd.options[:user_install] = false - FileUtils.mv specs["a-2"].cache_file, @tempdir - @cmd.options[:args] = %w[a] use_ui @ui do - orig_dir = Dir.pwd - begin - FileUtils.chmod 0755, @userhome - FileUtils.chmod 0555, @gemhome + FileUtils.chmod 0o755, @userhome + FileUtils.chmod 0o555, @gemhome - Dir.chdir @tempdir - assert_raise Gem::FilePermissionError do - @cmd.execute - end - ensure - Dir.chdir orig_dir - FileUtils.chmod 0755, @gemhome + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute end + ensure + FileUtils.chmod 0o755, @gemhome end + + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name).sort end def test_execute_local_missing @@ -231,7 +228,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a assert_equal 2, e.exit_code end - # HACK no repository was checked + # HACK: no repository was checked assert_match(/ould not find a valid gem 'no_such_gem'/, @ui.error) end @@ -250,7 +247,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a assert_equal 2, e.exit_code end - # HACK no repository was checked + # HACK: no repository was checked assert_match(/ould not find a valid gem 'no_such_gem'/, @ui.error) end @@ -434,21 +431,6 @@ ERROR: Possible alternatives: non_existent_with_hint assert_equal expected, output end - def test_execute_conflicting_install_options - @cmd.options[:user_install] = true - @cmd.options[:install_dir] = "whatever" - - use_ui @ui do - assert_raise Gem::MockGemUi::TermError do - @cmd.execute - end - end - - expected = "ERROR: Use --install-dir or --user-install but not both\n" - - assert_equal expected, @ui.error - end - def test_execute_prerelease_skipped_when_no_flag_set spec_fetcher do |fetcher| fetcher.gem "a", 1 @@ -464,7 +446,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-1], @cmd.installed_specs.map(&:full_name) end def test_execute_prerelease_wins_over_previous_ver @@ -482,7 +464,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2.a], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2.a], @cmd.installed_specs.map(&:full_name) end def test_execute_with_version_specified_by_colon @@ -499,7 +481,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-1], @cmd.installed_specs.map(&:full_name) end def test_execute_prerelease_skipped_when_non_pre_available @@ -517,7 +499,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) end def test_execute_required_ruby_version @@ -547,7 +529,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) end def test_execute_required_ruby_version_upper_bound @@ -568,7 +550,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2.0], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2.0], @cmd.installed_specs.map(&:full_name) end def test_execute_required_ruby_version_specific_not_met @@ -606,7 +588,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-1.0], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-1.0], @cmd.installed_specs.map(&:full_name) end def test_execute_required_ruby_version_specific_prerelease_not_met @@ -773,7 +755,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) assert_match "1 gem installed", @ui.output end @@ -793,7 +775,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) assert_match "1 gem installed", @ui.output end @@ -813,7 +795,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-1], @cmd.installed_specs.map(&:full_name) assert_match "1 gem installed", @ui.output a1_gemspec = File.join(@gemhome, "specifications", "a-1.gemspec") @@ -867,7 +849,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-1], @cmd.installed_specs.map(&:full_name) assert_match "1 gem installed", @ui.output @@ -901,7 +883,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2 b-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2 b-2], @cmd.installed_specs.map(&:full_name) assert_match "2 gems installed", @ui.output end @@ -943,7 +925,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-1 b-1], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-1 b-1], @cmd.installed_specs.map(&:full_name) end def test_execute_conservative @@ -969,7 +951,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[b-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[b-2], @cmd.installed_specs.map(&:full_name) assert_equal "", @ui.error assert_match "1 gem installed", @ui.output @@ -991,7 +973,7 @@ ERROR: Possible alternatives: non_existent_with_hint @cmd.install_gem "a", ">= 0" - assert_equal %w[a-2], @cmd.installed_specs.map {|s| s.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) assert done_installing, "documentation was not generated" end @@ -1005,7 +987,7 @@ ERROR: Possible alternatives: non_existent_with_hint @cmd.install_gem "a", ">= 0" - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) end def test_install_gem_ignore_dependencies_remote_platform_local @@ -1022,7 +1004,7 @@ ERROR: Possible alternatives: non_existent_with_hint @cmd.install_gem "a", ">= 0" - assert_equal %W[a-3-#{local}], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %W[a-3-#{local}], @cmd.installed_specs.map(&:full_name) end def test_install_gem_ignore_dependencies_specific_file @@ -1036,7 +1018,7 @@ ERROR: Possible alternatives: non_existent_with_hint @cmd.install_gem File.join(@tempdir, spec.file_name), nil - assert_equal %w[a-2], @cmd.installed_specs.map {|s| s.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) end def test_parses_requirement_from_gemname @@ -1065,7 +1047,7 @@ ERROR: Possible alternatives: non_existent_with_hint end assert_equal 2, e.exit_code - assert_match %r{Could not find a valid gem 'a' \(= 10.0\)}, @ui.error + assert_match(/Could not find a valid gem 'a' \(= 10.0\)/, @ui.error) end def test_show_errors_on_failure @@ -1106,7 +1088,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) assert_match "1 gem installed", @ui.output @@ -1131,7 +1113,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) assert_match "1 gem installed", @ui.output @@ -1158,7 +1140,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[], @cmd.installed_specs.map(&:full_name) assert_match "Using a (2)", @ui.output assert File.exist?("#{@gemdeps}.lock") @@ -1182,7 +1164,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[], @cmd.installed_specs.map(&:full_name) assert_match "Using a (2)", @ui.output assert !File.exist?("#{@gemdeps}.lock") @@ -1207,7 +1189,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[], @cmd.installed_specs.map(&:full_name) assert_match "Using a (1)", @ui.output end @@ -1229,7 +1211,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name } + assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name) assert_match "Installing a (2)", @ui.output end @@ -1252,7 +1234,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - names = @cmd.installed_specs.map {|spec| spec.full_name } + names = @cmd.installed_specs.map(&:full_name) assert_equal %w[q-1.0 r-2.0], names @@ -1279,7 +1261,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - names = @cmd.installed_specs.map {|spec| spec.full_name } + names = @cmd.installed_specs.map(&:full_name) assert_equal %w[r-2.0], names @@ -1306,7 +1288,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - names = @cmd.installed_specs.map {|spec| spec.full_name } + names = @cmd.installed_specs.map(&:full_name) assert_equal %w[q-1.0 r-2.0], names @@ -1338,7 +1320,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - names = @cmd.installed_specs.map {|spec| spec.full_name } + names = @cmd.installed_specs.map(&:full_name) assert_equal %w[q-1.0 r-2.0], names @@ -1355,7 +1337,7 @@ ERROR: Possible alternatives: non_existent_with_hint fetcher.gem "r", "2.0", "q" => nil end - i = Gem::Installer.at specs["q-1.0"].cache_file, :install_dir => "gf-path" + i = Gem::Installer.at specs["q-1.0"].cache_file, install_dir: "gf-path" i.install assert File.file?("gf-path/specifications/q-1.0.gemspec"), "not installed" @@ -1373,7 +1355,7 @@ ERROR: Possible alternatives: non_existent_with_hint end end - names = @cmd.installed_specs.map {|spec| spec.full_name } + names = @cmd.installed_specs.map(&:full_name) assert_equal %w[r-2.0], names @@ -1550,4 +1532,22 @@ ERROR: Possible alternatives: non_existent_with_hint assert_equal " a-3", out.shift assert_empty out end + + def test_suggest_update_if_enabled + TestUpdateSuggestion.with_eligible_environment(cmd: @cmd) do + spec_fetcher do |fetcher| + fetcher.gem "a", 2 + end + + @cmd.options[:args] = %w[a] + + use_ui @ui do + assert_raise Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute + end + end + + assert_includes @ui.output, "A new release of RubyGems is available: 1.2.3 → 2.0.0!" + end + end end diff --git a/test/rubygems/test_gem_commands_list_command.rb b/test/rubygems/test_gem_commands_list_command.rb index ec3f2517bf..c83dd51b67 100644 --- a/test/rubygems/test_gem_commands_list_command.rb +++ b/test/rubygems/test_gem_commands_list_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/list_command" diff --git a/test/rubygems/test_gem_commands_lock_command.rb b/test/rubygems/test_gem_commands_lock_command.rb index b785cbcfdd..6afe4f35c5 100644 --- a/test/rubygems/test_gem_commands_lock_command.rb +++ b/test/rubygems/test_gem_commands_lock_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/lock_command" diff --git a/test/rubygems/test_gem_commands_mirror.rb b/test/rubygems/test_gem_commands_mirror.rb index 423aba2656..2256a3ab33 100644 --- a/test/rubygems/test_gem_commands_mirror.rb +++ b/test/rubygems/test_gem_commands_mirror.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/mirror_command" @@ -14,6 +15,6 @@ class TestGemCommandsMirrorCommand < Gem::TestCase @cmd.execute end - assert_match %r{Install the rubygems-mirror}i, @ui.error + assert_match(/Install the rubygems-mirror/i, @ui.error) end end diff --git a/test/rubygems/test_gem_commands_open_command.rb b/test/rubygems/test_gem_commands_open_command.rb index f970ca12d6..d9e518048c 100644 --- a/test/rubygems/test_gem_commands_open_command.rb +++ b/test/rubygems/test_gem_commands_open_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/open_command" @@ -21,20 +22,23 @@ class TestGemCommandsOpenCommand < Gem::TestCase def test_execute @cmd.options[:args] = %w[foo] - @cmd.options[:editor] = "#{ruby_with_rubygems_in_load_path} -eexit --" + @cmd.options[:editor] = (ruby_with_rubygems_in_load_path + ["-e", "puts(ARGV,Dir.pwd)", "--"]).join(" ") gem "foo", "1.0.0" spec = gem "foo", "1.0.1" assert_nothing_raised Gem::MockGemUi::TermError do - Dir.stub(:chdir, spec.full_gem_path) do + stdout, stderr = capture_subprocess_io do use_ui @ui do @cmd.execute end end + assert_equal [spec.full_gem_path, spec.full_gem_path], stdout.split("\n") + assert_equal "", stderr end assert_equal "", @ui.error + assert_equal "", @ui.output end def test_wrong_version @@ -49,7 +53,7 @@ class TestGemCommandsOpenCommand < Gem::TestCase end end - assert_match %r{Unable to find gem 'foo'}, @ui.output + assert_match(/Unable to find gem 'foo'/, @ui.output) assert_equal "", @ui.error end @@ -62,7 +66,7 @@ class TestGemCommandsOpenCommand < Gem::TestCase end end - assert_match %r{Unable to find gem 'foo'}, @ui.output + assert_match(/Unable to find gem 'foo'/, @ui.output) assert_equal "", @ui.error end @@ -91,7 +95,7 @@ class TestGemCommandsOpenCommand < Gem::TestCase end end - assert_match %r{'foo' is a default gem and can't be opened\.} , @ui.output + assert_match(/'foo' is a default gem and can't be opened\./, @ui.output) assert_equal "", @ui.error end end diff --git a/test/rubygems/test_gem_commands_outdated_command.rb b/test/rubygems/test_gem_commands_outdated_command.rb index 4ed111a0e7..3e61033af3 100644 --- a/test/rubygems/test_gem_commands_outdated_command.rb +++ b/test/rubygems/test_gem_commands_outdated_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/outdated_command" diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb index ca77041000..eddd8afaf5 100644 --- a/test/rubygems/test_gem_commands_owner_command.rb +++ b/test/rubygems/test_gem_commands_owner_command.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true + require_relative "helper" +require_relative "multifactor_auth_utilities" require "rubygems/commands/owner_command" class TestGemCommandsOwnerCommand < Gem::TestCase @@ -10,7 +12,7 @@ class TestGemCommandsOwnerCommand < Gem::TestCase ENV["RUBYGEMS_HOST"] = nil @stub_ui = Gem::MockGemUi.new - @stub_fetcher = Gem::FakeFetcher.new + @stub_fetcher = Gem::MultifactorAuthFetcher.new Gem::RemoteFetcher.fetcher = @stub_fetcher Gem.configuration = nil Gem.configuration.rubygems_api_key = "ed244fbf2b1a52e012da8616c512fa47f9aa5250" @@ -36,20 +38,20 @@ class TestGemCommandsOwnerCommand < Gem::TestCase - id: 4 EOF - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.show_owners("freewill") end - assert_equal Net::HTTP::Get, @stub_fetcher.last_request.class + assert_equal Gem::Net::HTTP::Get, @stub_fetcher.last_request.class assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"] - assert_match %r{Owners for gem: freewill}, @stub_ui.output - assert_match %r{- user1@example.com}, @stub_ui.output - assert_match %r{- user2@example.com}, @stub_ui.output - assert_match %r{- user3}, @stub_ui.output - assert_match %r{- 4}, @stub_ui.output + assert_match(/Owners for gem: freewill/, @stub_ui.output) + assert_match(/- user1@example.com/, @stub_ui.output) + assert_match(/- user2@example.com/, @stub_ui.output) + assert_match(/- user3/, @stub_ui.output) + assert_match(/- 4/, @stub_ui.output) end def test_show_owners_dont_load_objects @@ -66,7 +68,7 @@ EOF - id: 4 EOF - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") assert_raise Psych::DisallowedClass do use_ui @ui do @@ -80,14 +82,14 @@ EOF host = "http://rubygems.example" ENV["RUBYGEMS_HOST"] = host - @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.show_owners("freewill") end - assert_match %r{Owners for gem: freewill}, @stub_ui.output - assert_match %r{- user1@example.com}, @stub_ui.output + assert_match(/Owners for gem: freewill/, @stub_ui.output) + assert_match(/- user1@example.com/, @stub_ui.output) end def test_show_owners_setting_up_host @@ -95,19 +97,19 @@ EOF host = "http://rubygems.example" @cmd.host = host - @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.show_owners("freewill") end - assert_match %r{Owners for gem: freewill}, @stub_ui.output - assert_match %r{- user1@example.com}, @stub_ui.output + assert_match(/Owners for gem: freewill/, @stub_ui.output) + assert_match(/- user1@example.com/, @stub_ui.output) end def test_show_owners_denied response = "You don't have permission to push to this gem" - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 403, "Forbidden"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden") assert_raise Gem::MockGemUi::TermError do use_ui @stub_ui do @@ -118,9 +120,32 @@ EOF assert_match response, @stub_ui.output end + def test_show_owners_permanent_redirect + host = "http://rubygems.example" + ENV["RUBYGEMS_HOST"] = host + path = "/api/v1/gems/freewill/owners.yaml" + redirected_uri = "https://rubygems.example#{path}" + + @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "301", + msg: "Moved Permanently", + headers: { "location" => redirected_uri } + ) + + assert_raise Gem::MockGemUi::TermError do + use_ui @stub_ui do + @cmd.show_owners("freewill") + end + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, @stub_ui.output + end + def test_show_owners_key response = "- email: user1@example.com\n" - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") File.open Gem.configuration.credentials_path, "a" do |f| f.write ":other: 701229f217cdf23b1344c7b4b54ca97" end @@ -134,13 +159,13 @@ EOF def test_add_owners response = "Owner added successfully." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.add_owners("freewill", ["user-new1@example.com"]) end - assert_equal Net::HTTP::Post, @stub_fetcher.last_request.class + assert_equal Gem::Net::HTTP::Post, @stub_fetcher.last_request.class assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"] assert_equal "email=user-new1%40example.com", @stub_fetcher.last_request.body @@ -149,7 +174,7 @@ EOF def test_add_owners_denied response = "You don't have permission to push to this gem" - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, "Forbidden"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden") use_ui @stub_ui do @cmd.add_owners("freewill", ["user-new1@example.com"]) @@ -158,12 +183,33 @@ EOF assert_match response, @stub_ui.output end + def test_add_owners_permanent_redirect + host = "http://rubygems.example" + ENV["RUBYGEMS_HOST"] = host + path = "/api/v1/gems/freewill/owners" + redirected_uri = "https://rubygems.example#{path}" + + @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "308", + msg: "Permanent Redirect", + headers: { "location" => redirected_uri } + ) + + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, @stub_ui.output + end + def test_add_owner_with_host_option_through_execute host = "http://rubygems.example" add_owner_response = "Owner added successfully." show_owners_response = "- email: user1@example.com\n" - @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners"] = [add_owner_response, 200, "OK"] - @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [show_owners_response, 200, "OK"] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: add_owner_response, code: 200, msg: "OK") + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: show_owners_response, code: 200, msg: "OK") @cmd.handle_options %W[--host #{host} --add user-new1@example.com freewill] @@ -172,13 +218,13 @@ EOF end assert_match add_owner_response, @stub_ui.output - assert_match %r{Owners for gem: freewill}, @stub_ui.output - assert_match %r{- user1@example.com}, @stub_ui.output + assert_match(/Owners for gem: freewill/, @stub_ui.output) + assert_match(/- user1@example.com/, @stub_ui.output) end def test_add_owners_key response = "Owner added successfully." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") File.open Gem.configuration.credentials_path, "a" do |f| f.write ":other: 701229f217cdf23b1344c7b4b54ca97" end @@ -192,13 +238,13 @@ EOF def test_remove_owners response = "Owner removed successfully." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.remove_owners("freewill", ["user-remove1@example.com"]) end - assert_equal Net::HTTP::Delete, @stub_fetcher.last_request.class + assert_equal Gem::Net::HTTP::Delete, @stub_fetcher.last_request.class assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"] assert_equal "email=user-remove1%40example.com", @stub_fetcher.last_request.body @@ -207,18 +253,55 @@ EOF def test_remove_owners_denied response = "You don't have permission to push to this gem" - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, "Forbidden"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden") + + use_ui @stub_ui do + @cmd.remove_owners("freewill", ["user-remove1@example.com"]) + end + + assert_match response, @stub_ui.output + end + + def test_remove_owners_permanent_redirect + host = "http://rubygems.example" + ENV["RUBYGEMS_HOST"] = host + path = "/api/v1/gems/freewill/owners" + redirected_uri = "https://rubygems.example#{path}" + @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "308", + msg: "Permanent Redirect", + headers: { "location" => redirected_uri } + ) use_ui @stub_ui do @cmd.remove_owners("freewill", ["user-remove1@example.com"]) end + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, @stub_ui.output + + path = "/api/v1/gems/freewill/owners" + redirected_uri = "https://rubygems.example#{path}" + + @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "308", + msg: "Permanent Redirect", + headers: { "location" => redirected_uri } + ) + + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." assert_match response, @stub_ui.output end def test_remove_owners_key response = "Owner removed successfully." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") File.open Gem.configuration.credentials_path, "a" do |f| f.write ":other: 701229f217cdf23b1344c7b4b54ca97" end @@ -232,7 +315,7 @@ EOF def test_remove_owners_missing response = "Owner could not be found." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 404, "Not Found"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 404, msg: "Not Found") use_ui @stub_ui do @cmd.remove_owners("freewill", ["missing@example"]) @@ -242,13 +325,8 @@ EOF end def test_otp_verified_success - response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." response_success = "Owner added successfully." - - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [ - [response_fail, 401, "Unauthorized"], - [response_success, 200, "OK"], - ] + @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success) @otp_ui = Gem::MockGemUi.new "111111\n" use_ui @otp_ui do @@ -263,7 +341,9 @@ EOF def test_otp_verified_failure response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 401, "Unauthorized"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized") + @stub_fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] = + HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity") @otp_ui = Gem::MockGemUi.new "111111\n" use_ui @otp_ui do @@ -276,15 +356,112 @@ EOF assert_equal "111111", @stub_fetcher.last_request["OTP"] end + def test_with_webauthn_enabled_success + response_success = "Owner added successfully." + server = Gem::MockTCPServer.new + + @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success) + @stub_fetcher.respond_with_webauthn_url + + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + end + + assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output + assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"] + assert_match response_success, @stub_ui.output + end + + def test_with_webauthn_enabled_failure + response_success = "Owner added successfully." + server = Gem::MockTCPServer.new + error = Gem::WebauthnVerificationError.new("Something went wrong") + + @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success) + @stub_fetcher.respond_with_webauthn_url + + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + end + + assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key + assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output + assert_match "ERROR: Security device verification failed: Something went wrong", @stub_ui.error + refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + refute_match response_success, @stub_ui.output + end + + def test_with_webauthn_enabled_success_with_polling + response_success = "Owner added successfully." + server = Gem::MockTCPServer.new + + @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success) + @stub_fetcher.respond_with_webauthn_url + @stub_fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo") + + TCPServer.stub(:new, server) do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + + assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \ + "command with the `--otp [your_code]` option.", @stub_ui.output + assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"] + assert_match response_success, @stub_ui.output + end + + def test_with_webauthn_enabled_failure_with_polling + response_success = "Owner added successfully." + server = Gem::MockTCPServer.new + + @stub_fetcher.respond_with_require_otp( + "#{Gem.host}/api/v1/gems/freewill/owners", + response_success + ) + @stub_fetcher.respond_with_webauthn_url + @stub_fetcher.respond_with_webauthn_polling_failure + + TCPServer.stub(:new, server) do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + + assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key + assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \ + "command with the `--otp [your_code]` option.", @stub_ui.output + assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \ + "or been used already.", @stub_ui.error + refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + refute_match response_success, @stub_ui.output + end + def test_remove_owners_unathorized_api_key response_forbidden = "The API key doesn't have access" response_success = "Owner removed successfully." @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [ - [response_forbidden, 403, "Forbidden"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] - @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK") @cmd.instance_variable_set :@scope, :remove_owner @stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n" @@ -294,7 +471,7 @@ EOF access_notice = "The existing key doesn't have access of remove_owner on RubyGems.org. Please sign in to update access." assert_match access_notice, @stub_ui.output - assert_match "Email:", @stub_ui.output + assert_match "Username/email:", @stub_ui.output assert_match "Password:", @stub_ui.output assert_match "Added remove_owner scope to the existing API key", @stub_ui.output assert_match response_success, @stub_ui.output @@ -305,10 +482,10 @@ EOF response_success = "Owner added successfully." @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [ - [response_forbidden, 403, "Forbidden"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] - @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK") @cmd.instance_variable_set :@scope, :add_owner @stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n" @@ -318,7 +495,7 @@ EOF access_notice = "The existing key doesn't have access of add_owner on RubyGems.org. Please sign in to update access." assert_match access_notice, @stub_ui.output - assert_match "Email:", @stub_ui.output + assert_match "Username/email:", @stub_ui.output assert_match "Password:", @stub_ui.output assert_match "Added add_owner scope to the existing API key", @stub_ui.output assert_match response_success, @stub_ui.output diff --git a/test/rubygems/test_gem_commands_pristine_command.rb b/test/rubygems/test_gem_commands_pristine_command.rb index 5bf1d27eb9..a17d7837c9 100644 --- a/test/rubygems/test_gem_commands_pristine_command.rb +++ b/test/rubygems/test_gem_commands_pristine_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/pristine_command" @@ -53,7 +54,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase end def test_execute_user_install - FileUtils.chmod 0555, @gemhome + FileUtils.chmod 0o555, @gemhome a = util_spec "a" do |s| s.executables = %w[foo] @@ -98,7 +99,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase assert_equal "Restored #{a.full_name}", out.shift assert_empty out, out.inspect ensure - FileUtils.chmod(0755, @gemhome) + FileUtils.chmod(0o755, @gemhome) end def test_execute_all @@ -157,11 +158,11 @@ class TestGemCommandsPristineCommand < Gem::TestCase assert_path_exist gem_exec - ruby_exec = sprintf Gem.default_exec_format, "ruby" + ruby_exec = format Gem.default_exec_format, "ruby" - bin_env = win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " " + bin_env = Gem.win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " " - assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(gem_exec) + assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(gem_exec)) end def test_execute_extensions_explicit @@ -202,6 +203,54 @@ class TestGemCommandsPristineCommand < Gem::TestCase assert_empty out, out.inspect end + def test_execute_extensions_only_missing_extensions + a = util_spec "a" do |s| + s.extensions << "ext/a/extconf.rb" + end + + ext_path = File.join @tempdir, "ext", "a", "extconf.rb" + write_file ext_path do |io| + io.write <<-'RUBY' + File.open "Makefile", "w" do |f| + f.puts "clean:\n\techo cleaned\n" + f.puts "all:\n\techo built\n" + f.puts "install:\n\techo installed\n" + end + RUBY + end + + b = util_spec "b" do |s| + s.extensions << "ext/b/extconf.rb" + end + + ext_path = File.join @tempdir, "ext", "b", "extconf.rb" + write_file ext_path do |io| + io.write <<-'RUBY' + File.open "Makefile", "w" do |f| + f.puts "clean:\n\techo cleaned\n" + f.puts "all:\n\techo built\n" + f.puts "install:\n\techo installed\n" + end + RUBY + end + + install_gem a + install_gem b + + # Remove the extension files for b + FileUtils.rm_rf b.gem_build_complete_path + + @cmd.options[:only_missing_extensions] = true + @cmd.options[:args] = [] + + use_ui @ui do + @cmd.execute + end + + refute_includes @ui.output, "Restored #{a.full_name}" + assert_includes @ui.output, "Restored #{b.full_name}" + end + def test_execute_no_extension a = util_spec "a" do |s| s.extensions << "ext/a/extconf.rb" @@ -247,7 +296,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase build_args = %w[--with-awesome=true --sweet] - install_gem a, :build_args => build_args + install_gem a, build_args: build_args @cmd.options[:args] = %w[a] @@ -343,6 +392,9 @@ class TestGemCommandsPristineCommand < Gem::TestCase b = util_spec "b" install_gem b + assert_path_exist File.join(gemhome2, "gems", "b-2") + assert_path_not_exist File.join(@gemhome, "gems", "b-2") + @cmd.options[:args] = %w[a b] use_ui @ui do @@ -455,7 +507,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase end end - assert_match %r{at least one gem name}, e.message + assert_match(/at least one gem name/, e.message) end def test_execute_only_executables @@ -497,7 +549,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase fp.puts "puts __FILE__" end write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |fp| - fp.puts "puts __FILE__" + fp.puts "# do nothing" end write_file File.join(@tempdir, "bin", "foo") do |fp| fp.puts "#!/usr/bin/ruby" @@ -547,7 +599,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase FileUtils.rm gem_exec FileUtils.rm gem_bindir - @cmd.handle_options ["--all", "--only-executables", "--bindir", "#{gem_bindir}"] + @cmd.handle_options ["--all", "--only-executables", "--bindir", gem_bindir.to_s] use_ui @ui do @cmd.execute diff --git a/test/rubygems/test_gem_commands_push_command.rb b/test/rubygems/test_gem_commands_push_command.rb index f38a2ae7a1..a7a18ff4ab 100644 --- a/test/rubygems/test_gem_commands_push_command.rb +++ b/test/rubygems/test_gem_commands_push_command.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true + require_relative "helper" +require_relative "multifactor_auth_utilities" require "rubygems/commands/push_command" +require "rubygems/config_file" class TestGemCommandsPushCommand < Gem::TestCase def setup @@ -24,7 +27,7 @@ class TestGemCommandsPushCommand < Gem::TestCase @host = "https://rubygems.example" @api_key = Gem.configuration.rubygems_api_key - @fetcher = Gem::FakeFetcher.new + @fetcher = Gem::MultifactorAuthFetcher.new Gem::RemoteFetcher.fetcher = @fetcher @cmd = Gem::Commands::PushCommand.new @@ -55,9 +58,9 @@ class TestGemCommandsPushCommand < Gem::TestCase @cmd.send_gem(@path) end - assert_match %r{Pushing gem to #{@host}...}, @ui.output + assert_match(/Pushing gem to #{@host}.../, @ui.output) - assert_equal Net::HTTP::Post, @fetcher.last_request.class + assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class assert_equal Gem.read_binary(@path), @fetcher.last_request.body assert_equal File.size(@path), @fetcher.last_request["Content-Length"].to_i assert_equal "application/octet-stream", @fetcher.last_request["Content-Type"] @@ -68,13 +71,13 @@ class TestGemCommandsPushCommand < Gem::TestCase def test_execute @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{Gem.host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{Gem.host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") @cmd.options[:args] = [@path] @cmd.execute - assert_equal Net::HTTP::Post, @fetcher.last_request.class + assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class assert_equal Gem.read_binary(@path), @fetcher.last_request.body assert_equal "application/octet-stream", @fetcher.last_request["Content-Type"] @@ -84,7 +87,7 @@ class TestGemCommandsPushCommand < Gem::TestCase host = "https://other.example" @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") @fetcher.data["#{Gem.host}/api/v1/gems"] = ["fail", 500, "Internal Server Error"] @@ -93,7 +96,7 @@ class TestGemCommandsPushCommand < Gem::TestCase @cmd.execute - assert_equal Net::HTTP::Post, @fetcher.last_request.class + assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class assert_equal Gem.read_binary(@path), @fetcher.last_request.body assert_equal "application/octet-stream", @fetcher.last_request["Content-Type"] @@ -105,7 +108,7 @@ class TestGemCommandsPushCommand < Gem::TestCase end @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{@spec.metadata['allowed_push_host']}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@spec.metadata["allowed_push_host"]}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") @fetcher.data["#{Gem.host}/api/v1/gems"] = ["fail", 500, "Internal Server Error"] @@ -113,7 +116,7 @@ class TestGemCommandsPushCommand < Gem::TestCase @cmd.execute - assert_equal Net::HTTP::Post, @fetcher.last_request.class + assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class assert_equal Gem.read_binary(@path), @fetcher.last_request.body assert_equal "application/octet-stream", @fetcher.last_request["Content-Type"] @@ -136,7 +139,7 @@ class TestGemCommandsPushCommand < Gem::TestCase ENV["RUBYGEMS_HOST"] = @host Gem.configuration.disable_default_gem_server = true @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -156,21 +159,21 @@ class TestGemCommandsPushCommand < Gem::TestCase } File.open Gem.configuration.credentials_path, "w" do |f| - f.write keys.to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys) end Gem.configuration.load_api_keys FileUtils.rm Gem.configuration.credentials_path @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end def test_sending_gem @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -190,14 +193,14 @@ class TestGemCommandsPushCommand < Gem::TestCase } File.open Gem.configuration.credentials_path, "w" do |f| - f.write keys.to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys) end Gem.configuration.load_api_keys FileUtils.rm Gem.configuration.credentials_path @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -212,7 +215,7 @@ class TestGemCommandsPushCommand < Gem::TestCase ENV["GEM_HOST_API_KEY"] = "PRIVKEY" @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -227,18 +230,18 @@ class TestGemCommandsPushCommand < Gem::TestCase @api_key = "DOESNTMATTER" keys = { - :rubygems_api_key => @api_key, + rubygems_api_key: @api_key, } File.open Gem.configuration.credentials_path, "w" do |f| - f.write keys.to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys) end Gem.configuration.load_api_keys FileUtils.rm Gem.configuration.credentials_path @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -272,7 +275,7 @@ class TestGemCommandsPushCommand < Gem::TestCase } File.open Gem.configuration.credentials_path, "w" do |f| - f.write keys.to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys) end Gem.configuration.load_api_keys @@ -302,21 +305,21 @@ class TestGemCommandsPushCommand < Gem::TestCase } File.open Gem.configuration.credentials_path, "w" do |f| - f.write keys.to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys) end Gem.configuration.load_api_keys FileUtils.rm Gem.configuration.credentials_path @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") # do not set @host use_ui(@ui) { @cmd.send_gem(@path) } - assert_match %r{Pushing gem to #{host}...}, @ui.output + assert_match(/Pushing gem to #{host}.../, @ui.output) - assert_equal Net::HTTP::Post, @fetcher.last_request.class + assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class assert_equal Gem.read_binary(@path), @fetcher.last_request.body assert_equal File.size(@path), @fetcher.last_request["Content-Length"].to_i assert_equal "application/octet-stream", @fetcher.last_request["Content-Type"] @@ -325,6 +328,27 @@ class TestGemCommandsPushCommand < Gem::TestCase assert_match @response, @ui.output end + def test_sending_gem_to_host_permanent_redirect + @host = "http://rubygems.example" + redirected_uri = "https://rubygems.example/api/v1/gems" + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create( + body: "", + code: 308, + msg: "Permanent Redirect", + headers: { "Location" => redirected_uri } + ) + + assert_raise Gem::MockGemUi::TermError do + use_ui @ui do + @cmd.instance_variable_set :@host, @host + @cmd.send_gem(@path) + end + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, @ui.output + end + def test_raises_error_with_no_arguments def @cmd.sign_in(*); end assert_raise Gem::CommandLineError do @@ -334,7 +358,7 @@ class TestGemCommandsPushCommand < Gem::TestCase def test_sending_gem_denied response = "You don't have permission to push to this gem" - @fetcher.data["#{@host}/api/v1/gems"] = [response, 403, "Forbidden"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden") @cmd.instance_variable_set :@host, @host assert_raise Gem::MockGemUi::TermError do @@ -348,7 +372,7 @@ class TestGemCommandsPushCommand < Gem::TestCase def test_sending_gem_key @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") File.open Gem.configuration.credentials_path, "a" do |f| f.write ":other: 701229f217cdf23b1344c7b4b54ca97" end @@ -363,13 +387,9 @@ class TestGemCommandsPushCommand < Gem::TestCase end def test_otp_verified_success - response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." response_success = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{Gem.host}/api/v1/gems"] = [ - [response_fail, 401, "Unauthorized"], - [response_success, 200, "OK"], - ] + @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success) @otp_ui = Gem::MockGemUi.new "111111\n" use_ui @otp_ui do @@ -384,7 +404,9 @@ class TestGemCommandsPushCommand < Gem::TestCase def test_otp_verified_failure response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." - @fetcher.data["#{Gem.host}/api/v1/gems"] = [response, 401, "Unauthorized"] + @fetcher.data["#{Gem.host}/api/v1/gems"] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized") + @fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] = + HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity") @otp_ui = Gem::MockGemUi.new "111111\n" assert_raise Gem::MockGemUi::TermError do @@ -399,18 +421,120 @@ class TestGemCommandsPushCommand < Gem::TestCase assert_equal "111111", @fetcher.last_request["OTP"] end + def test_with_webauthn_enabled_success + response_success = "Successfully registered gem: freewill (1.0.0)" + server = Gem::MockTCPServer.new + + @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success) + @fetcher.respond_with_webauthn_url + + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do + use_ui @ui do + @cmd.send_gem(@path) + end + end + end + + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match "You are verified with a security device. You may close the browser window.", @ui.output + assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] + assert_match response_success, @ui.output + end + + def test_with_webauthn_enabled_failure + response_success = "Successfully registered gem: freewill (1.0.0)" + server = Gem::MockTCPServer.new + error = Gem::WebauthnVerificationError.new("Something went wrong") + + @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success) + @fetcher.respond_with_webauthn_url + + error = assert_raise Gem::MockGemUi::TermError do + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do + use_ui @ui do + @cmd.send_gem(@path) + end + end + end + end + assert_equal 1, error.exit_code + + assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match "ERROR: Security device verification failed: Something went wrong", @ui.error + refute_match "You are verified with a security device. You may close the browser window.", @ui.output + refute_match response_success, @ui.output + end + + def test_with_webauthn_enabled_success_with_polling + response_success = "Successfully registered gem: freewill (1.0.0)" + server = Gem::MockTCPServer.new + + @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success) + @fetcher.respond_with_webauthn_url + @fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo") + + TCPServer.stub(:new, server) do + use_ui @ui do + @cmd.send_gem(@path) + end + end + + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match "You are verified with a security device. You may close the browser window.", @ui.output + assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] + assert_match response_success, @ui.output + end + + def test_with_webauthn_enabled_failure_with_polling + response_success = "Successfully registered gem: freewill (1.0.0)" + server = Gem::MockTCPServer.new + + @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success) + @fetcher.respond_with_webauthn_url + @fetcher.respond_with_webauthn_polling_failure + + error = assert_raise Gem::MockGemUi::TermError do + TCPServer.stub(:new, server) do + use_ui @ui do + @cmd.send_gem(@path) + end + end + end + assert_equal 1, error.exit_code + + assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \ + "command with the `--otp [your_code]` option.", @ui.output + assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \ + "or been used already.", @ui.error + refute_match "You are verified with a security device. You may close the browser window.", @ui.output + refute_match response_success, @ui.output + end + def test_sending_gem_unathorized_api_key_with_mfa_enabled response_mfa_enabled = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." response_forbidden = "The API key doesn't have access" response_success = "Successfully registered gem: freewill (1.0.0)" @fetcher.data["#{@host}/api/v1/gems"] = [ - [response_mfa_enabled, 401, "Unauthorized"], - [response_forbidden, 403, "Forbidden"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_mfa_enabled, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] + @fetcher.data["#{@host}/api/v1/webauthn_verification"] = + HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity") - @fetcher.data["#{@host}/api/v1/api_key"] = ["", 200, "OK"] + @fetcher.data["#{@host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK") @cmd.instance_variable_set :@host, @host @cmd.instance_variable_set :@scope, :push_rubygem @@ -423,7 +547,7 @@ class TestGemCommandsPushCommand < Gem::TestCase access_notice = "The existing key doesn't have access of push_rubygem on https://rubygems.example. Please sign in to update access." assert_match mfa_notice, @ui.output assert_match access_notice, @ui.output - assert_match "Email:", @ui.output + assert_match "Username/email:", @ui.output assert_match "Password:", @ui.output assert_match "Added push_rubygem scope to the existing API key", @ui.output assert_match response_success, @ui.output @@ -438,17 +562,19 @@ class TestGemCommandsPushCommand < Gem::TestCase response_profile = "mfa: disabled\n" @fetcher.data["#{@host}/api/v1/gems"] = [ - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] @fetcher.data["#{@host}/api/v1/api_key"] = [ - [response_mfa_enabled, 401, "Unauthorized"], - ["", 200, "OK"], + HTTPResponseFactory.create(body: response_mfa_enabled, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: "", code: 200, msg: "OK"), ] @fetcher.data["#{@host}/api/v1/profile/me.yaml"] = [ - [response_profile, 200, "OK"], + HTTPResponseFactory.create(body: response_profile, code: 200, msg: "OK"), ] + @fetcher.data["#{@host}/api/v1/webauthn_verification"] = + HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity") @cmd.instance_variable_set :@scope, :push_rubygem @cmd.options[:args] = [@path] @@ -462,7 +588,7 @@ class TestGemCommandsPushCommand < Gem::TestCase mfa_notice = "You have enabled multi-factor authentication. Please enter OTP code." assert_match mfa_notice, @ui.output assert_match "Enter your https://rubygems.example credentials.", @ui.output - assert_match "Email:", @ui.output + assert_match "Username/email:", @ui.output assert_match "Password:", @ui.output assert_match "Signed in with API key:", @ui.output assert_match response_success, @ui.output diff --git a/test/rubygems/test_gem_commands_query_command.rb b/test/rubygems/test_gem_commands_query_command.rb index 6882098c53..8e590df124 100644 --- a/test/rubygems/test_gem_commands_query_command.rb +++ b/test/rubygems/test_gem_commands_query_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/query_command" @@ -22,9 +23,7 @@ class TestGemCommandsQueryCommandWithInstalledGems < Gem::TestCase include TestGemCommandsQueryCommandSetup def test_execute - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[-r] @@ -45,9 +44,7 @@ pl (1 i386-linux) end def test_execute_all - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[-r --all] @@ -68,9 +65,7 @@ pl (1 i386-linux) end def test_execute_all_prerelease - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[-r --all --prerelease] @@ -310,9 +305,7 @@ pl (1) end def test_execute_local - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.options[:domain] = :local @@ -333,9 +326,7 @@ pl (1 i386-linux) end def test_execute_local_notty - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[] @@ -355,9 +346,7 @@ pl (1 i386-linux) end def test_execute_local_quiet - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.options[:domain] = :local Gem.configuration.verbose = false @@ -376,9 +365,7 @@ pl (1 i386-linux) end def test_execute_no_versions - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[-r --no-versions] @@ -399,9 +386,7 @@ pl end def test_execute_notty - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[-r] @@ -439,9 +424,7 @@ a (3.a) end def test_execute_prerelease_local - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[-l --prerelease] @@ -461,9 +444,7 @@ pl (1 i386-linux) end def test_execute_no_prerelease_local - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[-l --no-prerelease] @@ -483,9 +464,7 @@ pl (1 i386-linux) end def test_execute_remote - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.options[:domain] = :remote @@ -506,9 +485,7 @@ pl (1 i386-linux) end def test_execute_remote_notty - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[] @@ -528,9 +505,7 @@ pl (1 i386-linux) end def test_execute_remote_quiet - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.options[:domain] = :remote Gem.configuration.verbose = false @@ -569,9 +544,7 @@ pl (1 i386-linux) # Test for multiple args handling! def test_execute_multiple_args - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) @cmd.handle_options %w[a pl] @@ -579,8 +552,8 @@ pl (1 i386-linux) @cmd.execute end - assert_match %r{^a }, @stub_ui.output - assert_match %r{^pl }, @stub_ui.output + assert_match(/^a /, @stub_ui.output) + assert_match(/^pl /, @stub_ui.output) assert_equal "", @stub_ui.error end @@ -592,8 +565,8 @@ pl (1 i386-linux) @cmd.send :show_gems, /a/i end - assert_match %r{^a }, @stub_ui.output - refute_match %r{^pl }, @stub_ui.output + assert_match(/^a /, @stub_ui.output) + refute_match(/^pl /, @stub_ui.output) assert_empty @stub_ui.error end diff --git a/test/rubygems/test_gem_commands_rebuild_command.rb b/test/rubygems/test_gem_commands_rebuild_command.rb new file mode 100644 index 0000000000..3b7927c44e --- /dev/null +++ b/test/rubygems/test_gem_commands_rebuild_command.rb @@ -0,0 +1,154 @@ +# frozen_string_literal: true + +require_relative "helper" +require "rubygems/commands/build_command" +require "rubygems/commands/rebuild_command" +require "rubygems/package" + +class TestGemCommandsRebuildCommand < Gem::TestCase + def setup + super + + readme_file = File.join(@tempdir, "README.md") + + begin + umask_orig = File.umask(2) + File.open readme_file, "w" do |f| + f.write "My awesome gem" + end + ensure + File.umask(umask_orig) + end + + @gem_name = "rebuild_test_gem" + @gem_version = "1.0.0" + @gem = util_spec @gem_name do |s| + s.version = @gem_version + s.license = "AGPL-3.0" + s.files = ["README.md"] + end + end + + def util_test_build_gem(gem, args) + @ui = Gem::MockGemUi.new + + cmd = Gem::Commands::BuildCommand.new + + cmd.options[:args] = args + cmd.options[:build_path] = @tempdir + use_ui @ui do + cmd.execute + end + gem_file = "#{@gem_name}-#{@gem_version}.gem" + output = @ui.output.split "\n" + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: #{@gem_name}", output.shift + assert_equal " Version: #{@gem_version}", output.shift + assert_equal " File: #{gem_file}", output.shift + assert_equal [], output + + gem_file = File.join(@tempdir, gem_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal @gem_name, spec.name + assert_equal "this is a summary", spec.summary + gem_file + end + + def util_test_rebuild_gem(gem, args, original_gem_file, gemspec_file, timestamp) + @ui = Gem::MockGemUi.new + + cmd = Gem::Commands::RebuildCommand.new + + cmd.options[:args] = args + cmd.options[:original_gem_file] = original_gem_file + cmd.options[:build_path] = @tempdir + cmd.options[:gemspec_file] = gemspec_file + use_ui @ui do + cmd.execute + end + gem_file = "#{@gem_name}-#{@gem_version}.gem" + output = @ui.output.split "\n" + + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: #{@gem_name}", output.shift + assert_equal " Version: #{@gem_version}", output.shift + assert_equal " File: #{gem_file}", output.shift + assert_empty output.shift + assert_match(/^Built at: .+ \(#{timestamp}\)/, output.shift) + original_line = output.shift + original = original_line.split(" ")[-1] + assert_match(/^Original build saved to: /, original_line) + reproduced_line = output.shift + reproduced = reproduced_line.split(" ")[-1] + assert_match(/^Reproduced build saved to: /, reproduced_line) + assert_equal "Working directory: #{@tempdir}", output.shift + assert_equal "", output.shift + assert_equal "Hash comparison:", output.shift + output.shift # " #{old_hash}\t#{old_file}" + output.shift # " #{new_hash}\t#{new_file}" + assert_empty output.shift + assert_equal "SUCCESS - original and rebuild hashes matched", output.shift + assert_equal [], output + + assert File.exist?(original) + assert File.exist?(reproduced) + + old_spec = Gem::Package.new(original).spec + new_spec = Gem::Package.new(reproduced).spec + + assert_equal @gem_name, old_spec.name + assert_equal "this is a summary", old_spec.summary + + assert_equal old_spec.name, new_spec.name + assert_equal old_spec.summary, new_spec.summary + + [reproduced, original] + end + + def test_build_is_reproducible + # Back up SOURCE_DATE_EPOCH to restore later. + epoch = ENV["SOURCE_DATE_EPOCH"] + + gemspec_file = File.join(@tempdir, @gem.spec_name) + + # Initial Build + + # Set SOURCE_DATE_EPOCH to 2001-02-03 04:05:06 -0500. + ENV["SOURCE_DATE_EPOCH"] = timestamp = Time.new(2001, 2, 3, 4, 5, 6).to_i.to_s + File.write(gemspec_file, @gem.to_ruby) + gem_file = util_test_build_gem @gem, [gemspec_file] + + build_contents = File.read(gem_file) + + gem_file_dir = File.dirname(gem_file) + gem_file_name = File.basename(gem_file) + original_gem_file = File.join(gem_file_dir, "original-" + gem_file_name) + File.rename(gem_file, original_gem_file) + + # Rebuild + + # Set SOURCE_DATE_EPOCH to a different value, meaning we are + # also testing that `gem rebuild` overrides the value. + ENV["SOURCE_DATE_EPOCH"] = Time.new(2007, 8, 9, 10, 11, 12).to_s + + rebuild_gem_file, saved_gem_file = + util_test_rebuild_gem(@gem, [@gem_name, @gem_version], original_gem_file, gemspec_file, timestamp) + + rebuild_contents = File.read(rebuild_gem_file) + + assert_equal build_contents, rebuild_contents + ensure + ENV["SOURCE_DATE_EPOCH"] = epoch + if rebuild_gem_file + File.unlink(rebuild_gem_file) + dir = File.dirname(rebuild_gem_file) + Dir.rmdir(dir) + File.unlink(saved_gem_file) + Dir.rmdir(File.dirname(saved_gem_file)) + Dir.rmdir(File.dirname(dir)) + end + end +end diff --git a/test/rubygems/test_gem_commands_search_command.rb b/test/rubygems/test_gem_commands_search_command.rb index afa6ff8d13..47aefa0cf7 100644 --- a/test/rubygems/test_gem_commands_search_command.rb +++ b/test/rubygems/test_gem_commands_search_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/search_command" diff --git a/test/rubygems/test_gem_commands_server_command.rb b/test/rubygems/test_gem_commands_server_command.rb index 1becde3ae2..cabb7cf49d 100644 --- a/test/rubygems/test_gem_commands_server_command.rb +++ b/test/rubygems/test_gem_commands_server_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/server_command" @@ -14,6 +15,6 @@ class TestGemCommandsServerCommand < Gem::TestCase @cmd.execute end - assert_match %r{Install the rubygems-server}i, @ui.error + assert_match(/Install the rubygems-server/i, @ui.error) end end diff --git a/test/rubygems/test_gem_commands_setup_command.rb b/test/rubygems/test_gem_commands_setup_command.rb index 1c0963ee96..8eedb6c03a 100644 --- a/test/rubygems/test_gem_commands_setup_command.rb +++ b/test/rubygems/test_gem_commands_setup_command.rb @@ -8,16 +8,17 @@ class TestGemCommandsSetupCommand < Gem::TestCase if File.exist?(bundler_gemspec) BUNDLER_VERS = File.read(bundler_gemspec).match(/VERSION = "(#{Gem::Version::VERSION_PATTERN})"/)[1] else - BUNDLER_VERS = "2.0.1".freeze + BUNDLER_VERS = "2.0.1" end def setup super @cmd = Gem::Commands::SetupCommand.new + @cmd.options[:document] = [] filelist = %w[ - bin/gem + exe/gem lib/rubygems.rb lib/rubygems/requirement.rb lib/rubygems/ssl_certs/rubygems.org/foo.pem @@ -30,17 +31,14 @@ class TestGemCommandsSetupCommand < Gem::TestCase bundler/lib/bundler/man/gemfile.5 bundler/lib/bundler/man/gemfile.5.ronn bundler/lib/bundler/templates/.circleci/config.yml - bundler/lib/bundler/templates/.travis.yml ] create_dummy_files(filelist) - gemspec = Gem::Specification.new - gemspec.author = "Us" - gemspec.name = "bundler" - gemspec.version = BUNDLER_VERS - gemspec.bindir = "exe" - gemspec.executables = ["bundle", "bundler"] + gemspec = util_spec "bundler", BUNDLER_VERS do |s| + s.bindir = "exe" + s.executables = ["bundle", "bundler"] + end File.open "bundler/bundler.gemspec", "w" do |io| io.puts gemspec.to_ruby @@ -66,10 +64,9 @@ class TestGemCommandsSetupCommand < Gem::TestCase io.puts "I changed it!" end - @cmd.options[:document] = [] @cmd.execute - assert_match %r{\A#!}, File.read(gem_bin_path) + assert_match(/\A#!/, File.read(gem_bin_path)) end def test_execute_no_regenerate_binstubs @@ -78,7 +75,6 @@ class TestGemCommandsSetupCommand < Gem::TestCase io.puts "I changed it!" end - @cmd.options[:document] = [] @cmd.options[:regenerate_binstubs] = false @cmd.execute @@ -91,10 +87,9 @@ class TestGemCommandsSetupCommand < Gem::TestCase io.puts "I changed it!" end - @cmd.options[:document] = [] @cmd.execute - assert_match %r{\Arequire}, File.read(gem_plugin_path) + assert_match(/\Arequire/, File.read(gem_plugin_path)) end def test_execute_no_regenerate_plugins @@ -103,7 +98,6 @@ class TestGemCommandsSetupCommand < Gem::TestCase io.puts "I changed it!" end - @cmd.options[:document] = [] @cmd.options[:regenerate_plugins] = false @cmd.execute @@ -116,15 +110,12 @@ class TestGemCommandsSetupCommand < Gem::TestCase # Simulate gem installed with an older rubygems without a plugins layout FileUtils.rm_rf Gem.plugindir - @cmd.options[:document] = [] @cmd.execute - assert_match %r{\Arequire}, File.read(gem_plugin_path) + assert_match(/\Arequire/, File.read(gem_plugin_path)) end def test_execute_informs_about_installed_executables - @cmd.options[:document] = [] - use_ui @ui do @cmd.execute end @@ -143,17 +134,16 @@ class TestGemCommandsSetupCommand < Gem::TestCase io.puts "I changed it!" end - @cmd.options[:document] = [] @cmd.options[:env_shebang] = true @cmd.execute - ruby_exec = sprintf Gem.default_exec_format, "ruby" + ruby_exec = format Gem.default_exec_format, "ruby" - bin_env = win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " " - assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_gem_bin_path) - assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_bundle_bin_path) - assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_bundler_bin_path) - assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(gem_bin_path) + bin_env = Gem.win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " " + assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(default_gem_bin_path)) + assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(default_bundle_bin_path)) + assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(default_bundler_bin_path)) + assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(gem_bin_path)) end def test_destdir_flag_does_not_try_to_write_to_the_default_gem_home @@ -169,6 +159,23 @@ class TestGemCommandsSetupCommand < Gem::TestCase end end + def test_destdir_flag_regenerates_binstubs + # install to destdir + destdir = File.join(@tempdir, "foo") + gem_bin_path = gem_install "destdir-only-gem", install_dir: destdir + + # change binstub manually + write_file gem_bin_path do |io| + io.puts "I changed it!" + end + + @cmd.options[:destdir] = destdir + @cmd.options[:prefix] = "/" + @cmd.execute + + assert_match(/\A#!/, File.read(gem_bin_path)) + end + def test_files_in assert_equal %w[rubygems.rb rubygems/requirement.rb rubygems/ssl_certs/rubygems.org/foo.pem], @cmd.files_in("lib").sort @@ -187,7 +194,6 @@ class TestGemCommandsSetupCommand < Gem::TestCase assert_path_exist File.join(dir, "bundler/b.rb") assert_path_exist File.join(dir, "bundler/templates/.circleci/config.yml") - assert_path_exist File.join(dir, "bundler/templates/.travis.yml") end end @@ -423,7 +429,7 @@ class TestGemCommandsSetupCommand < Gem::TestCase end end - def gem_install(name) + def gem_install(name, **options) gem = util_spec name do |s| s.executables = [name] s.files = %W[bin/#{name}] @@ -431,8 +437,8 @@ class TestGemCommandsSetupCommand < Gem::TestCase write_file File.join @tempdir, "bin", name do |f| f.puts "#!/usr/bin/ruby" end - install_gem gem - File.join @gemhome, "bin", name + install_gem gem, **options + File.join options[:install_dir] || @gemhome, "bin", name end def gem_install_with_plugin(name) @@ -440,7 +446,7 @@ class TestGemCommandsSetupCommand < Gem::TestCase s.files = %W[lib/rubygems_plugin.rb] end write_file File.join @tempdir, "lib", "rubygems_plugin.rb" do |f| - f.puts "require '#{gem.plugins.first}'" + f.puts "# do nothing" end install_gem gem diff --git a/test/rubygems/test_gem_commands_signin_command.rb b/test/rubygems/test_gem_commands_signin_command.rb index ce745bff20..29e5edceb7 100644 --- a/test/rubygems/test_gem_commands_signin_command.rb +++ b/test/rubygems/test_gem_commands_signin_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/signin_command" require "rubygems/installer" @@ -23,14 +24,14 @@ class TestGemCommandsSigninCommand < Gem::TestCase def test_execute_when_not_already_signed_in sign_in_ui = util_capture { @cmd.execute } - assert_match %r{Signed in.}, sign_in_ui.output + assert_match(/Signed in./, sign_in_ui.output) end def test_execute_when_not_already_signed_in_and_not_preexisting_credentials_folder FileUtils.rm Gem.configuration.credentials_path sign_in_ui = util_capture { @cmd.execute } - assert_match %r{Signed in.}, sign_in_ui.output + assert_match(/Signed in./, sign_in_ui.output) end def test_execute_when_already_signed_in_with_same_host @@ -63,14 +64,39 @@ class TestGemCommandsSigninCommand < Gem::TestCase host = "http://some-gemcutter-compatible-host.org" sign_in_ui = util_capture(nil, host) { @cmd.execute } - assert_match %r{Enter your #{host} credentials.}, sign_in_ui.output - assert_match %r{Signed in.}, sign_in_ui.output + assert_match(/Enter your #{host} credentials./, sign_in_ui.output) + assert_match(/Signed in./, sign_in_ui.output) api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials[host] end + def test_execute_with_host_permanent_redirect + host = "http://rubygems.example/" + ENV["RUBYGEMS_HOST"] = host + path = "/api/v1/api_key" + redirected_uri = "http://rubygems.example#{path}" + fetcher = Gem::FakeFetcher.new + fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "308", + msg: "Permanent Redirect", + headers: { "location" => redirected_uri } + ) + Gem::RemoteFetcher.fetcher = fetcher + ui = Gem::MockGemUi.new("you@example.com\nsecret\n\n\n") + + assert_raise Gem::MockGemUi::TermError do + use_ui ui do + @cmd.execute + end + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, ui.output + end + def test_execute_with_valid_creds_set_for_default_host util_capture { @cmd.execute } @@ -80,51 +106,98 @@ class TestGemCommandsSigninCommand < Gem::TestCase assert_equal api_key, credentials[:rubygems_api_key] end - def test_execute_with_key_name_and_scope + def test_execute_with_key_name_default_scope + email = "you@example.com" + password = "secret" + api_key = "1234abcd" + fetcher = Gem::RemoteFetcher.fetcher + + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\n" + util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute } + + user = ENV["USER"] || ENV["USERNAME"] + + assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "index_rubygems: y", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_equal "name=test-key&index_rubygems=true", fetcher.last_request.body + + credentials = load_yaml_file Gem.configuration.credentials_path + assert_equal api_key, credentials[:rubygems_api_key] + end + + def test_execute_with_key_name_and_custom_scope email = "you@example.com" password = "secret" - api_key = "1234" + api_key = "1234abcd" fetcher = Gem::RemoteFetcher.fetcher - key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\n" + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\n" util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute } user = ENV["USER"] || ENV["USERNAME"] assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output assert_match "index_rubygems [yN]", key_name_ui.output assert_match "push_rubygem [yN]", key_name_ui.output assert_match "yank_rubygem [yN]", key_name_ui.output assert_match "add_owner [yN]", key_name_ui.output assert_match "remove_owner [yN]", key_name_ui.output assert_match "access_webhooks [yN]", key_name_ui.output - assert_match "show_dashboard [yN]", key_name_ui.output assert_equal "name=test-key&push_rubygem=true", fetcher.last_request.body credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials[:rubygems_api_key] end - def test_execute_with_key_name_scope_and_mfa_level_of_ui_only + def test_execute_with_key_name_and_exclusive_scope email = "you@example.com" password = "secret" - api_key = "1234" + api_key = "1234abcd" + fetcher = Gem::RemoteFetcher.fetcher + + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\ny\n" + util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute } + + user = ENV["USER"] || ENV["USERNAME"] + + assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "index_rubygems: y", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output + assert_equal "name=test-key&show_dashboard=true", fetcher.last_request.body + + credentials = load_yaml_file Gem.configuration.credentials_path + assert_equal api_key, credentials[:rubygems_api_key] + end + + def test_execute_with_key_name_custom_scope_and_mfa_level_of_ui_only + email = "you@example.com" + password = "secret" + api_key = "1234abcd" fetcher = Gem::RemoteFetcher.fetcher mfa_level = "ui_only" - key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\ny" + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\ny" util_capture(key_name_ui, nil, api_key, fetcher, mfa_level) { @cmd.execute } user = ENV["USER"] || ENV["USERNAME"] assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output assert_match "index_rubygems [yN]", key_name_ui.output assert_match "push_rubygem [yN]", key_name_ui.output assert_match "yank_rubygem [yN]", key_name_ui.output assert_match "add_owner [yN]", key_name_ui.output assert_match "remove_owner [yN]", key_name_ui.output assert_match "access_webhooks [yN]", key_name_ui.output - assert_match "show_dashboard [yN]", key_name_ui.output assert_match "Would you like to enable MFA for this key? (strongly recommended) [yn]", key_name_ui.output assert_equal "name=test-key&push_rubygem=true&mfa=true", fetcher.last_request.body @@ -132,26 +205,28 @@ class TestGemCommandsSigninCommand < Gem::TestCase assert_equal api_key, credentials[:rubygems_api_key] end - def test_execute_with_key_name_scope_and_mfa_level_of_gem_signin + def test_execute_with_key_name_custom_scope_and_mfa_level_of_gem_signin email = "you@example.com" password = "secret" - api_key = "1234" + api_key = "1234abcd" fetcher = Gem::RemoteFetcher.fetcher mfa_level = "ui_and_gem_signin" - key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\ny" + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\ny" util_capture(key_name_ui, nil, api_key, fetcher, mfa_level) { @cmd.execute } user = ENV["USER"] || ENV["USERNAME"] assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output assert_match "index_rubygems [yN]", key_name_ui.output assert_match "push_rubygem [yN]", key_name_ui.output assert_match "yank_rubygem [yN]", key_name_ui.output assert_match "add_owner [yN]", key_name_ui.output assert_match "remove_owner [yN]", key_name_ui.output assert_match "access_webhooks [yN]", key_name_ui.output - assert_match "show_dashboard [yN]", key_name_ui.output assert_match "Would you like to enable MFA for this key? (strongly recommended) [yn]", key_name_ui.output assert_equal "name=test-key&push_rubygem=true&mfa=true", fetcher.last_request.body @@ -162,7 +237,7 @@ class TestGemCommandsSigninCommand < Gem::TestCase def test_execute_with_warnings email = "you@example.com" password = "secret" - api_key = "1234" + api_key = "1234abcd" fetcher = Gem::RemoteFetcher.fetcher mfa_level = "disabled" warning = "/[WARNING/] For protection of your account and gems" @@ -178,15 +253,15 @@ class TestGemCommandsSigninCommand < Gem::TestCase email = "you@example.com" password = "secret" - api_key = "1234" + api_key = "1234abcd" fetcher = Gem::RemoteFetcher.fetcher - key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\ny" + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\ny" # Set the expected response for the Web-API supplied ENV["RUBYGEMS_HOST"] = host - data_key = "#{ENV['RUBYGEMS_HOST']}/api/v1/api_key" - fetcher.data[data_key] = [api_key, 200, "OK"] + data_key = "#{ENV["RUBYGEMS_HOST"]}/api/v1/api_key" + fetcher.data[data_key] = HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") use_ui key_name_ui do @cmd.execute @@ -195,13 +270,13 @@ class TestGemCommandsSigninCommand < Gem::TestCase user = ENV["USER"] || ENV["USERNAME"] assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output assert_match "index_rubygems [yN]", key_name_ui.output assert_match "push_rubygem [yN]", key_name_ui.output assert_match "yank_rubygem [yN]", key_name_ui.output assert_match "add_owner [yN]", key_name_ui.output assert_match "remove_owner [yN]", key_name_ui.output assert_match "access_webhooks [yN]", key_name_ui.output - assert_match "show_dashboard [yN]", key_name_ui.output assert_equal "name=test-key&push_rubygem=true", fetcher.last_request.body end @@ -209,20 +284,20 @@ class TestGemCommandsSigninCommand < Gem::TestCase def util_capture(ui_stub = nil, host = nil, api_key = nil, fetcher = Gem::FakeFetcher.new, mfa_level = "disabled", warning = nil) api_key ||= "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - response = [api_key, 200, "OK"] - profile_response = [ "mfa: #{mfa_level}\nwarning: #{warning}" , 200, "OK"] + response = HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") + profile_response = HTTPResponseFactory.create(body: "mfa: #{mfa_level}\nwarning: #{warning}", code: 200, msg: "OK") email = "you@example.com" password = "secret" # Set the expected response for the Web-API supplied ENV["RUBYGEMS_HOST"] = host || Gem::DEFAULT_HOST - data_key = "#{ENV['RUBYGEMS_HOST']}/api/v1/api_key" + data_key = "#{ENV["RUBYGEMS_HOST"]}/api/v1/api_key" fetcher.data[data_key] = response - profile = "#{ENV['RUBYGEMS_HOST']}/api/v1/profile/me.yaml" + profile = "#{ENV["RUBYGEMS_HOST"]}/api/v1/profile/me.yaml" fetcher.data[profile] = profile_response Gem::RemoteFetcher.fetcher = fetcher - sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n") + sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n\n\n") use_ui sign_in_ui do yield diff --git a/test/rubygems/test_gem_commands_signout_command.rb b/test/rubygems/test_gem_commands_signout_command.rb index 992b127a94..999a14080f 100644 --- a/test/rubygems/test_gem_commands_signout_command.rb +++ b/test/rubygems/test_gem_commands_signout_command.rb @@ -12,12 +12,12 @@ class TestGemCommandsSignoutCommand < Gem::TestCase def test_execute_when_user_is_signed_in FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path) - FileUtils::touch Gem.configuration.credentials_path + FileUtils.touch Gem.configuration.credentials_path @sign_out_ui = Gem::MockGemUi.new use_ui(@sign_out_ui) { @cmd.execute } - assert_match %r{You have successfully signed out}, @sign_out_ui.output + assert_match(/You have successfully signed out/, @sign_out_ui.output) assert_equal false, File.exist?(Gem.configuration.credentials_path) end @@ -25,6 +25,6 @@ class TestGemCommandsSignoutCommand < Gem::TestCase @sign_out_ui = Gem::MockGemUi.new use_ui(@sign_out_ui) { @cmd.execute } - assert_match %r{You are not currently signed in}, @sign_out_ui.error + assert_match(/You are not currently signed in/, @sign_out_ui.error) end end diff --git a/test/rubygems/test_gem_commands_sources_command.rb b/test/rubygems/test_gem_commands_sources_command.rb index b7c164c0e6..5e675e5c84 100644 --- a/test/rubygems/test_gem_commands_sources_command.rb +++ b/test/rubygems/test_gem_commands_sources_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/sources_command" diff --git a/test/rubygems/test_gem_commands_specification_command.rb b/test/rubygems/test_gem_commands_specification_command.rb index 7564baa2ca..454d6ea1c6 100644 --- a/test/rubygems/test_gem_commands_specification_command.rb +++ b/test/rubygems/test_gem_commands_specification_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/specification_command" @@ -20,8 +21,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase @cmd.execute end - assert_match %r{Gem::Specification}, @ui.output - assert_match %r{name: foo}, @ui.output + assert_match(/Gem::Specification/, @ui.output) + assert_match(/name: foo/, @ui.output) assert_equal "", @ui.error end @@ -36,10 +37,10 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase @cmd.execute end - assert_match %r{Gem::Specification}, @ui.output - assert_match %r{name: foo}, @ui.output - assert_match %r{version: 0.0.1}, @ui.output - assert_match %r{version: 0.0.2}, @ui.output + assert_match(/Gem::Specification/, @ui.output) + assert_match(/name: foo/, @ui.output) + assert_match(/version: 0.0.1/, @ui.output) + assert_match(/version: 0.0.2/, @ui.output) assert_equal "", @ui.error end @@ -98,8 +99,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase @cmd.execute end - assert_match %r{Gem::Specification}, @ui.output - assert_match %r{name: foo}, @ui.output + assert_match(/Gem::Specification/, @ui.output) + assert_match(/name: foo/, @ui.output) assert_equal "", @ui.error end @@ -130,8 +131,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase @cmd.execute end - assert_match %r{Gem::Specification}, @ui.output - assert_match %r{name: foo}, @ui.output + assert_match(/Gem::Specification/, @ui.output) + assert_match(/name: foo/, @ui.output) assert_equal "", @ui.error end @@ -164,7 +165,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output - assert_match %r{name: foo}, @ui.output + assert_match(/name: foo/, @ui.output) end def test_execute_remote_with_version @@ -228,7 +229,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output - assert_match %r{name: foo}, @ui.output + assert_match(/name: foo/, @ui.output) spec = load_yaml @ui.output @@ -250,7 +251,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output - assert_match %r{name: foo}, @ui.output + assert_match(/name: foo/, @ui.output) spec = load_yaml @ui.output @@ -269,8 +270,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase @cmd.execute end - assert_match %r{Gem::Specification.new}, @ui.output - assert_match %r{s.name = "foo"}, @ui.output + assert_match(/Gem::Specification.new/, @ui.output) + assert_match(/s.name = "foo"/, @ui.output) assert_equal "", @ui.error end end diff --git a/test/rubygems/test_gem_commands_stale_command.rb b/test/rubygems/test_gem_commands_stale_command.rb index 99eb23fb30..ea7493b418 100644 --- a/test/rubygems/test_gem_commands_stale_command.rb +++ b/test/rubygems/test_gem_commands_stale_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/stale_command" @@ -24,11 +25,11 @@ class TestGemCommandsStaleCommand < Gem::TestCase files.each do |file| filename = File.join(bar_baz.full_gem_path, file) FileUtils.mkdir_p File.dirname filename - FileUtils.touch(filename, :mtime => Time.now) + FileUtils.touch(filename, mtime: Time.now) filename = File.join(foo_bar.full_gem_path, file) FileUtils.mkdir_p File.dirname filename - FileUtils.touch(filename, :mtime => Time.now - 86400) + FileUtils.touch(filename, mtime: Time.now - 86_400) end use_ui @stub_ui do diff --git a/test/rubygems/test_gem_commands_uninstall_command.rb b/test/rubygems/test_gem_commands_uninstall_command.rb index 083b831c98..4daa61cb0c 100644 --- a/test/rubygems/test_gem_commands_uninstall_command.rb +++ b/test/rubygems/test_gem_commands_uninstall_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "installer_test_case" require "rubygems/commands/uninstall_command" @@ -20,14 +21,9 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase gemhome2 = "#{@gemhome}2" a_4, = util_gem "a", 4 - install_gem a_4, :install_dir => gemhome2 - - Gem::Specification.dirs = [@gemhome, gemhome2] + install_gem a_4, install_dir: gemhome2 - assert_includes Gem::Specification.all_names, "a-1" - assert_includes Gem::Specification.all_names, "a-4" - assert_includes Gem::Specification.all_names, "b-2" - assert_includes Gem::Specification.all_names, "default-1" + assert_gems_presence "a-1", "a-4", "b-2", "default-1", dirs: [@gemhome, gemhome2] @cmd.options[:all] = true @cmd.options[:args] = %w[a] @@ -118,7 +114,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase def test_execute_removes_executable initial_install - if win_platform? + if Gem.win_platform? assert File.exist?(@executable) else assert File.symlink?(@executable) @@ -162,7 +158,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase @cmd.execute assert_equal false, File.exist?(formatted_executable) - rescue + rescue StandardError Gem::Installer.exec_format = nil end @@ -233,6 +229,26 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase assert File.exist? File.join(@gemhome, "bin", "executable") end + def test_execute_with_multiple_version_specified_as_colon + initial_install + + ui = Gem::MockGemUi.new "y\n" + + util_make_gems + + assert_equal 3, Gem::Specification.find_all_by_name("a").length + + @cmd.options[:force] = true + @cmd.options[:args] = ["a:1", "a:2"] + + use_ui ui do + @cmd.execute + end + + assert_equal 1, Gem::Specification.find_all_by_name("a").length + assert_equal Gem::Version.new("3.a"), Gem::Specification.find_by_name("a").version + end + def test_uninstall_selection ui = Gem::MockGemUi.new "1\n" @@ -346,11 +362,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase a_4, = util_gem "a", 4 install_gem a_4 - Gem::Specification.dirs = [@gemhome, gemhome2] - - assert_includes Gem::Specification.all_names, "a-1" - assert_includes Gem::Specification.all_names, "a-4" - assert_includes Gem::Specification.all_names, "default-1" + assert_gems_presence "a-1", "a-4", "default-1", dirs: [@gemhome, gemhome2] @cmd.options[:all] = true @cmd.options[:args] = [] @@ -369,11 +381,9 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase gemhome2 = "#{@gemhome}2" a_4, = util_gem "a", 4 - install_gem a_4 , :install_dir => gemhome2 + install_gem a_4, install_dir: gemhome2 - Gem::Specification.dirs = [@gemhome, gemhome2] - - assert_includes Gem::Specification.all_names, "a-4" + assert_gems_presence "a-4", dirs: [@gemhome, gemhome2] @cmd.options[:args] = ["a:4"] @@ -386,6 +396,26 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase assert_includes e.message, "a is not installed in GEM_HOME" end + def test_execute_outside_gem_home_when_install_dir_given + gemhome2 = "#{@gemhome}2" + + a_4, = util_gem "a", 4 + install_gem a_4, install_dir: gemhome2 + + assert_gems_presence "a-4", dirs: [@gemhome, gemhome2] + + Gem::Specification.dirs = [@gemhome] + + @cmd.options[:install_dir] = gemhome2 + @cmd.options[:args] = ["a:4"] + + @cmd.execute + + Gem::Specification.dirs = [gemhome2] + + refute_includes Gem::Specification.all_names.sort, "a-4" + end + def test_handle_options @cmd.handle_options %w[] @@ -486,7 +516,7 @@ WARNING: Use your OS package manager to uninstall vendor gems end assert_empty @ui.output - assert_match %r{Error: unable to successfully uninstall '#{@spec.name}'}, @ui.error + assert_match(/Error: unable to successfully uninstall '#{@spec.name}'/, @ui.error) end private @@ -501,4 +531,12 @@ WARNING: Use your OS package manager to uninstall vendor gems end end end + + def assert_gems_presence(*gems, dirs:) + Gem::Specification.dirs = dirs + + gems.each do |full_name| + assert_includes Gem::Specification.all_names, full_name + end + end end diff --git a/test/rubygems/test_gem_commands_unpack_command.rb b/test/rubygems/test_gem_commands_unpack_command.rb index 1d9d0b6bd0..61cf8a611a 100644 --- a/test/rubygems/test_gem_commands_unpack_command.rb +++ b/test/rubygems/test_gem_commands_unpack_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/unpack_command" @@ -15,7 +16,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase util_make_gems assert_equal( - @cmd.find_in_cache(File.basename @a1.cache_file), + @cmd.find_in_cache(File.basename(@a1.cache_file)), @a1.cache_file, "found a-1.gem in the cache" ) @@ -151,11 +152,11 @@ class TestGemCommandsUnpackCommand < Gem::TestCase end def test_execute_sudo - pend "Cannot perform this test on windows (chmod)" if win_platform? + pend "Cannot perform this test on windows (chmod)" if Gem.win_platform? util_make_gems - FileUtils.chmod 0555, @gemhome + FileUtils.chmod 0o555, @gemhome @cmd.options[:args] = %w[b] @@ -167,7 +168,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase assert File.exist?(File.join(@tempdir, "b-2")), "b should be unpacked" ensure - FileUtils.chmod 0755, @gemhome + FileUtils.chmod 0o755, @gemhome end def test_execute_with_target_option diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb index 58bc7576da..2683840f2e 100644 --- a/test/rubygems/test_gem_commands_update_command.rb +++ b/test/rubygems/test_gem_commands_update_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/update_command" @@ -78,7 +79,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 9", out.shift assert_equal "RubyGems system software updated", out.shift @@ -122,7 +122,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_empty out err = @ui.error.split "\n" @@ -131,6 +130,34 @@ class TestGemCommandsUpdateCommand < Gem::TestCase assert_empty err end + def test_execute_system_when_latest_does_not_support_your_ruby_but_previous_one_does + spec_fetcher do |fetcher| + fetcher.download "rubygems-update", 9 do |s| + s.files = %w[setup.rb] + s.required_ruby_version = "> 9" + end + + fetcher.download "rubygems-update", 8 do |s| + s.files = %w[setup.rb] + end + end + + @cmd.options[:args] = [] + @cmd.options[:system] = true + + use_ui @ui do + @cmd.execute + end + + err = @ui.error.split "\n" + assert_empty err + + out = @ui.output.split "\n" + assert_equal "Installing RubyGems 8", out.shift + assert_equal "RubyGems system software updated", out.shift + assert_empty out + end + def test_execute_system_multiple spec_fetcher do |fetcher| fetcher.download "rubygems-update", 8 do |s| @@ -150,7 +177,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 9", out.shift assert_equal "RubyGems system software updated", out.shift @@ -184,7 +210,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 9", out.shift assert_equal "RubyGems system software updated", out.shift @@ -204,7 +229,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase gemhome2 = "#{@gemhome}2" - Gem::Installer.at(rubygems_update_package, :install_dir => gemhome2).install + Gem::Installer.at(rubygems_update_package, install_dir: gemhome2).install Gem.use_paths @gemhome, [gemhome2, @gemhome] @@ -241,7 +266,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 8", out.shift assert_equal "RubyGems system software updated", out.shift @@ -352,7 +376,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 9", out.shift assert_equal "RubyGems system software updated", out.shift @@ -669,10 +692,10 @@ class TestGemCommandsUpdateCommand < Gem::TestCase @cmd.handle_options %w[--system] expected = { - :args => [], - :document => %w[ri], - :force => false, - :system => true, + args: [], + document: %w[ri], + force: false, + system: true, } assert_equal expected, @cmd.options @@ -688,10 +711,10 @@ class TestGemCommandsUpdateCommand < Gem::TestCase @cmd.handle_options %w[--system 1.3.7] expected = { - :args => [], - :document => %w[ri], - :force => false, - :system => "1.3.7", + args: [], + document: %w[ri], + force: false, + system: "1.3.7", } assert_equal expected, @cmd.options diff --git a/test/rubygems/test_gem_commands_which_command.rb b/test/rubygems/test_gem_commands_which_command.rb index 46e95bf619..cbd5b5ef14 100644 --- a/test/rubygems/test_gem_commands_which_command.rb +++ b/test/rubygems/test_gem_commands_which_command.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/commands/which_command" @@ -32,8 +33,8 @@ class TestGemCommandsWhichCommand < Gem::TestCase end assert_equal "", @ui.output - assert_match %r{Can.t find Ruby library file or shared library directory\n}, - @ui.error + assert_match(/Can.t find Ruby library file or shared library directory\n/, + @ui.error) end def test_execute_one_missing @@ -50,8 +51,8 @@ class TestGemCommandsWhichCommand < Gem::TestCase end assert_equal "#{@foo_bar.full_gem_path}/lib/foo_bar.rb\n", @ui.output - assert_match %r{Can.t find Ruby library file or shared library missinglib\n}, - @ui.error + assert_match(/Can.t find Ruby library file or shared library missinglib\n/, + @ui.error) end def test_execute_missing @@ -64,8 +65,8 @@ class TestGemCommandsWhichCommand < Gem::TestCase end assert_equal "", @ui.output - assert_match %r{Can.t find Ruby library file or shared library missinglib\n}, - @ui.error + assert_match(/Can.t find Ruby library file or shared library missinglib\n/, + @ui.error) end def util_foo_bar diff --git a/test/rubygems/test_gem_commands_yank_command.rb b/test/rubygems/test_gem_commands_yank_command.rb index 878b52416e..eb78e3a542 100644 --- a/test/rubygems/test_gem_commands_yank_command.rb +++ b/test/rubygems/test_gem_commands_yank_command.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true + require_relative "helper" +require_relative "multifactor_auth_utilities" require "rubygems/commands/yank_command" class TestGemCommandsYankCommand < Gem::TestCase @@ -11,7 +13,8 @@ class TestGemCommandsYankCommand < Gem::TestCase @cmd = Gem::Commands::YankCommand.new @cmd.options[:host] = "http://example" - @fetcher = Gem::RemoteFetcher.fetcher + @fetcher = Gem::MultifactorAuthFetcher.new(host: "http://example") + Gem::RemoteFetcher.fetcher = @fetcher Gem.configuration.rubygems_api_key = "key" Gem.configuration.api_keys[:KEY] = "other" @@ -43,7 +46,7 @@ class TestGemCommandsYankCommand < Gem::TestCase def test_execute yank_uri = "http://example/api/v1/gems/yank" - @fetcher.data[yank_uri] = ["Successfully yanked", 200, "OK"] + @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK") @cmd.options[:args] = %w[a] @cmd.options[:added_platform] = true @@ -54,7 +57,7 @@ class TestGemCommandsYankCommand < Gem::TestCase end assert_match %r{Yanking gem from http://example}, @ui.output - assert_match %r{Successfully yanked}, @ui.output + assert_match(/Successfully yanked/, @ui.output) platform = Gem.platforms[1] body = @fetcher.last_request.body.split("&").sort @@ -69,8 +72,8 @@ class TestGemCommandsYankCommand < Gem::TestCase response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." yank_uri = "http://example/api/v1/gems/yank" @fetcher.data[yank_uri] = [ - [response_fail, 401, "Unauthorized"], - ["Successfully yanked", 200, "OK"], + HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK"), ] @cmd.options[:args] = %w[a] @@ -85,14 +88,14 @@ class TestGemCommandsYankCommand < Gem::TestCase assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @otp_ui.output assert_match "Code: ", @otp_ui.output assert_match %r{Yanking gem from http://example}, @otp_ui.output - assert_match %r{Successfully yanked}, @otp_ui.output + assert_match(/Successfully yanked/, @otp_ui.output) assert_equal "111111", @fetcher.last_request["OTP"] end def test_execute_with_otp_failure response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." yank_uri = "http://example/api/v1/gems/yank" - @fetcher.data[yank_uri] = [response, 401, "Unauthorized"] + @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized") @cmd.options[:args] = %w[a] @cmd.options[:added_platform] = true @@ -109,9 +112,125 @@ class TestGemCommandsYankCommand < Gem::TestCase assert_equal "111111", @fetcher.last_request["OTP"] end + def test_with_webauthn_enabled_success + server = Gem::MockTCPServer.new + + @fetcher.respond_with_require_otp("http://example/api/v1/gems/yank", "Successfully yanked") + @fetcher.respond_with_webauthn_url + + @cmd.options[:args] = %w[a] + @cmd.options[:added_platform] = true + @cmd.options[:version] = req("= 1.0") + + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do + use_ui @ui do + @cmd.execute + end + end + end + + assert_match %r{Yanking gem from http://example}, @ui.output + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match "You are verified with a security device. You may close the browser window.", @ui.output + assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] + assert_match "Successfully yanked", @ui.output + end + + def test_with_webauthn_enabled_failure + server = Gem::MockTCPServer.new + error = Gem::WebauthnVerificationError.new("Something went wrong") + + @fetcher.respond_with_require_otp("http://example/api/v1/gems/yank", "Successfully yanked") + @fetcher.respond_with_webauthn_url + + @cmd.options[:args] = %w[a] + @cmd.options[:added_platform] = true + @cmd.options[:version] = req("= 1.0") + + error = assert_raise Gem::MockGemUi::TermError do + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do + use_ui @ui do + @cmd.execute + end + end + end + end + assert_equal 1, error.exit_code + + assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key + assert_match %r{Yanking gem from http://example}, @ui.output + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match "ERROR: Security device verification failed: Something went wrong", @ui.error + refute_match "You are verified with a security device. You may close the browser window.", @ui.output + refute_match "Successfully yanked", @ui.output + end + + def test_with_webauthn_enabled_success_with_polling + server = Gem::MockTCPServer.new + + @fetcher.respond_with_require_otp("http://example/api/v1/gems/yank", "Successfully yanked") + @fetcher.respond_with_webauthn_url + @fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo") + + @cmd.options[:args] = %w[a] + @cmd.options[:added_platform] = true + @cmd.options[:version] = req("= 1.0") + + TCPServer.stub(:new, server) do + use_ui @ui do + @cmd.execute + end + end + + assert_match %r{Yanking gem from http://example}, @ui.output + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match "You are verified with a security device. You may close the browser window.", @ui.output + assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] + assert_match "Successfully yanked", @ui.output + end + + def test_with_webauthn_enabled_failure_with_polling + server = Gem::MockTCPServer.new + + @fetcher.respond_with_require_otp("http://example/api/v1/gems/yank", "Successfully yanked") + @fetcher.respond_with_webauthn_url + @fetcher.respond_with_webauthn_polling_failure + + @cmd.options[:args] = %w[a] + @cmd.options[:added_platform] = true + @cmd.options[:version] = req("= 1.0") + + error = assert_raise Gem::MockGemUi::TermError do + TCPServer.stub(:new, server) do + use_ui @ui do + @cmd.execute + end + end + end + assert_equal 1, error.exit_code + + assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key + assert_match %r{Yanking gem from http://example}, @ui.output + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \ + "or been used already.", @ui.error + refute_match "You are verified with a security device. You may close the browser window.", @ui.output + refute_match "Successfully yanked", @ui.output + end + def test_execute_key yank_uri = "http://example/api/v1/gems/yank" - @fetcher.data[yank_uri] = ["Successfully yanked", 200, "OK"] + @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK") @cmd.options[:args] = %w[a] @cmd.options[:version] = req("= 1.0") @@ -129,7 +248,7 @@ class TestGemCommandsYankCommand < Gem::TestCase def test_execute_host host = "https://other.example" yank_uri = "#{host}/api/v1/gems/yank" - @fetcher.data[yank_uri] = ["Successfully yanked", 200, "OK"] + @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK") @cmd.options[:args] = %w[a] @cmd.options[:version] = req("= 1.0") @@ -140,7 +259,7 @@ class TestGemCommandsYankCommand < Gem::TestCase end assert_match %r{Yanking gem from https://other.example}, @ui.output - assert_match %r{Successfully yanked}, @ui.output + assert_match(/Successfully yanked/, @ui.output) body = @fetcher.last_request.body.split("&").sort assert_equal %w[gem_name=a version=1.0], body @@ -154,11 +273,11 @@ class TestGemCommandsYankCommand < Gem::TestCase host = "http://example" @fetcher.data["#{host}/api/v1/gems/yank"] = [ - [response_forbidden, 403, "Forbidden"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] - @fetcher.data["#{host}/api/v1/api_key"] = ["", 200, "OK"] + @fetcher.data["#{host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK") @cmd.options[:args] = %w[a] @cmd.options[:added_platform] = true @cmd.options[:version] = req("= 1.0") @@ -172,7 +291,7 @@ class TestGemCommandsYankCommand < Gem::TestCase access_notice = "The existing key doesn't have access of yank_rubygem on http://example. Please sign in to update access." assert_match access_notice, @ui.output - assert_match "Email:", @ui.output + assert_match "Username/email:", @ui.output assert_match "Password:", @ui.output assert_match "Added yank_rubygem scope to the existing API key", @ui.output assert_match response_success, @ui.output diff --git a/test/rubygems/test_gem_config_file.rb b/test/rubygems/test_gem_config_file.rb index e23773a133..a055f248be 100644 --- a/test/rubygems/test_gem_config_file.rb +++ b/test/rubygems/test_gem_config_file.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/config_file" @@ -57,6 +58,7 @@ class TestGemConfigFile < Gem::TestCase fp.puts ":ssl_verify_mode: 0" fp.puts ":ssl_ca_cert: /etc/ssl/certs" fp.puts ":cert_expiration_length_days: 28" + fp.puts ":install_extension_in_lib: true" fp.puts ":ipv4_fallback_enabled: true" end @@ -72,6 +74,7 @@ class TestGemConfigFile < Gem::TestCase assert_equal 0, @cfg.ssl_verify_mode assert_equal "/etc/ssl/certs", @cfg.ssl_ca_cert assert_equal 28, @cfg.cert_expiration_length_days + assert_equal true, @cfg.install_extension_in_lib assert_equal true, @cfg.ipv4_fallback_enabled end @@ -184,22 +187,22 @@ class TestGemConfigFile < Gem::TestCase temp_cred = File.join Gem.user_home, ".gem", "credentials" FileUtils.mkdir_p File.dirname(temp_cred) - File.open temp_cred, "w", 0600 do |fp| + File.open temp_cred, "w", 0o600 do |fp| fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97" end util_config_file - assert_equal({ :rubygems => "701229f217cdf23b1344c7b4b54ca97" }, + assert_equal({ rubygems: "701229f217cdf23b1344c7b4b54ca97" }, @cfg.api_keys) end def test_check_credentials_permissions - pend "chmod not supported" if win_platform? + pend "chmod not supported" if Gem.win_platform? @cfg.rubygems_api_key = "x" - File.chmod 0644, @cfg.credentials_path + File.chmod 0o644, @cfg.credentials_path use_ui @ui do assert_raise Gem::MockGemUi::TermError do @@ -322,23 +325,28 @@ if you believe they were disclosed to a third party. def test_load_api_keys temp_cred = File.join Gem.user_home, ".gem", "credentials" FileUtils.mkdir_p File.dirname(temp_cred) - File.open temp_cred, "w", 0600 do |fp| - fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97" - fp.puts ":other: a5fdbb6ba150cbb83aad2bb2fede64c" + File.open temp_cred, "w", 0o600 do |fp| + fp.puts ":rubygems_api_key: rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c" + fp.puts ":other: rubygems_9636a120106ea8b81fbc792188251738665711d2ece160c5" + fp.puts "http://localhost:3000: rubygems_be293ad9dd71550a012b17d848893b41960b811ce9312b47" end util_config_file - assert_equal({ :rubygems => "701229f217cdf23b1344c7b4b54ca97", - :other => "a5fdbb6ba150cbb83aad2bb2fede64c" }, @cfg.api_keys) + assert_equal( + { :rubygems => "rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c", + :other => "rubygems_9636a120106ea8b81fbc792188251738665711d2ece160c5", + "http://localhost:3000" => "rubygems_be293ad9dd71550a012b17d848893b41960b811ce9312b47" }, + @cfg.api_keys + ) end def test_load_api_keys_bad_permission - pend "chmod not supported" if win_platform? + pend "chmod not supported" if Gem.win_platform? @cfg.rubygems_api_key = "x" - File.chmod 0644, @cfg.credentials_path + File.chmod 0o644, @cfg.credentials_path assert_raise Gem::MockGemUi::TermError do @cfg.load_api_keys @@ -363,38 +371,38 @@ if you believe they were disclosed to a third party. assert_equal "x", @cfg.rubygems_api_key expected = { - :rubygems_api_key => "x", + rubygems_api_key: "x", } assert_equal expected, load_yaml_file(@cfg.credentials_path) - unless win_platform? + unless Gem.win_platform? stat = File.stat @cfg.credentials_path - assert_equal 0600, stat.mode & 0600 + assert_equal 0o600, stat.mode & 0o600 end end def test_rubygems_api_key_equals_bad_permission - pend "chmod not supported" if win_platform? + pend "chmod not supported" if Gem.win_platform? @cfg.rubygems_api_key = "x" - File.chmod 0644, @cfg.credentials_path + File.chmod 0o644, @cfg.credentials_path assert_raise Gem::MockGemUi::TermError do @cfg.rubygems_api_key = "y" end expected = { - :rubygems_api_key => "x", + rubygems_api_key: "x", } assert_equal expected, load_yaml_file(@cfg.credentials_path) stat = File.stat @cfg.credentials_path - assert_equal 0644, stat.mode & 0644 + assert_equal 0o644, stat.mode & 0o644 end def test_write @@ -470,7 +478,8 @@ if you believe they were disclosed to a third party. end begin - verbose, $VERBOSE = $VERBOSE, nil + verbose = $VERBOSE + $VERBOSE = nil util_config_file ensure @@ -478,6 +487,16 @@ if you believe they were disclosed to a third party. end end + def test_accept_string_key + File.open @temp_conf, "w" do |fp| + fp.puts "verbose: false" + end + + util_config_file + + assert_equal false, @cfg.verbose + end + def test_load_ssl_verify_mode_from_config File.open @temp_conf, "w" do |fp| fp.puts ":ssl_verify_mode: 1" @@ -502,8 +521,12 @@ if you believe they were disclosed to a third party. assert_equal("/home/me/mine.pem", @cfg.ssl_client_cert) end - def util_config_file(args = @cfg_args) - @cfg = Gem::ConfigFile.new args + def test_load_install_extension_in_lib_from_config + File.open @temp_conf, "w" do |fp| + fp.puts ":install_extension_in_lib: false" + end + util_config_file + assert_equal(false, @cfg.install_extension_in_lib) end def test_disable_default_gem_server @@ -513,4 +536,46 @@ if you believe they were disclosed to a third party. util_config_file assert_equal(true, @cfg.disable_default_gem_server) end + + def test_load_with_rubygems_config_hash + yaml = <<~YAML + --- + :foo: bar + bar: 100 + buzz: true + alpha: :bravo + charlie: "" + delta: + YAML + actual = Gem::ConfigFile.load_with_rubygems_config_hash(yaml) + + assert_equal "bar", actual[:foo] + assert_equal 100, actual["bar"] + assert_equal true, actual["buzz"] + assert_equal :bravo, actual["alpha"] + assert_equal nil, actual["charlie"] + assert_equal nil, actual["delta"] + end + + def test_dump_with_rubygems_yaml + symbol_key_hash = { foo: "bar" } + + actual = Gem::ConfigFile.dump_with_rubygems_yaml(symbol_key_hash) + + assert_equal("---\n:foo: \"bar\"\n", actual) + end + + def test_handle_comment + yaml = <<~YAML + --- + :foo: bar # buzz + YAML + + actual = Gem::ConfigFile.load_with_rubygems_config_hash(yaml) + assert_equal("bar", actual[:foo]) + end + + def util_config_file(args = @cfg_args) + @cfg = Gem::ConfigFile.new args + end end diff --git a/test/rubygems/test_gem_console_ui.rb b/test/rubygems/test_gem_console_ui.rb new file mode 100644 index 0000000000..b8a619625f --- /dev/null +++ b/test/rubygems/test_gem_console_ui.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require_relative "helper" +require "rubygems/user_interaction" + +class TestGemConsoleUI < Gem::TestCase + def test_output_can_be_captured_by_test_unit + output = capture_output do + ui = Gem::ConsoleUI.new + + ui.alert_error "test error" + ui.alert_warning "test warning" + ui.alert "test alert" + end + + assert_equal "INFO: test alert\n", output.first + assert_equal "ERROR: test error\n" + "WARNING: test warning\n", output.last + end +end diff --git a/test/rubygems/test_gem_dependency.rb b/test/rubygems/test_gem_dependency.rb index c585e87087..2a989a5551 100644 --- a/test/rubygems/test_gem_dependency.rb +++ b/test/rubygems/test_gem_dependency.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/dependency" @@ -105,8 +106,13 @@ class TestGemDependency < Gem::TestCase def test_equals_tilde_object o = Object.new - def o.name ; "a" end - def o.version ; "0" end + def o.name + "a" + end + + def o.version + "0" + end assert_match dep("a"), o end @@ -358,6 +364,8 @@ class TestGemDependency < Gem::TestCase assert_equal [b, b_1], dep.to_specs + require "rubygems/bundler_version_finder" + Gem::BundlerVersionFinder.stub(:bundler_version, Gem::Version.new("1")) do assert_equal [b_1, b], dep.to_specs end @@ -386,6 +394,16 @@ class TestGemDependency < Gem::TestCase assert_match "Could not find 'b' (= 2.0) among 1 total gem(s)", e.message end + def test_to_spec_with_only_prereleases + a_2_a_1 = util_spec "a", "2.a1" + a_2_a_2 = util_spec "a", "2.a2" + install_specs a_2_a_1, a_2_a_2 + + a_dep = dep "a", ">= 1" + + assert_equal a_2_a_2, a_dep.to_spec + end + def test_identity assert_equal dep("a", "= 1").identity, :released assert_equal dep("a", "= 1.a").identity, :complete diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb index 2b0b874b2d..8999723ba1 100644 --- a/test/rubygems/test_gem_dependency_installer.rb +++ b/test/rubygems/test_gem_dependency_installer.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/dependency_installer" require "rubygems/security" @@ -74,7 +75,7 @@ class TestGemDependencyInstaller < Gem::TestCase @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 = Gem::DependencyInstaller.new prerelease: true inst.install dep assert_equal %w[a-10.a], Gem::Specification.map(&:full_name) @@ -96,7 +97,7 @@ class TestGemDependencyInstaller < Gem::TestCase dep = Gem::Dependency.new "a" - inst = Gem::DependencyInstaller.new :prerelease => true + 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) @@ -131,7 +132,7 @@ class TestGemDependencyInstaller < Gem::TestCase @fetcher.data["http://gems.example.com/gems/a-1.gem"] = p1a_data dep = Gem::Dependency.new "a" - inst = Gem::DependencyInstaller.new :prerelease => true + inst = Gem::DependencyInstaller.new prerelease: true inst.install dep assert_equal %w[a-1], Gem::Specification.map(&:full_name) @@ -152,11 +153,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :ignore_dependencies => true + inst = Gem::DependencyInstaller.new ignore_dependencies: true inst.install "b" end - assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }, + assert_equal %w[b-1], inst.installed_gems.map(&:full_name), "sanity check" Dir.chdir @tempdir do @@ -164,7 +165,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst.install "e" end - assert_equal %w[a-1 e-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1 e-1], inst.installed_gems.map(&:full_name) end def test_install_cache_dir @@ -177,11 +178,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir dir do - inst = Gem::DependencyInstaller.new :cache_dir => @tempdir + inst = Gem::DependencyInstaller.new cache_dir: @tempdir inst.install "b" end - assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } + 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) @@ -197,7 +198,7 @@ class TestGemDependencyInstaller < Gem::TestCase Gem::Specification.reset FileUtils.mv @a1_gem, @tempdir - FileUtils.mv a2_gem, @tempdir # not in index + FileUtils.mv a2_gem, @tempdir # not in index FileUtils.mv @b1_gem, @tempdir inst = nil @@ -206,7 +207,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst.install "a", req("= 2") end - assert_equal %w[a-2], inst.installed_gems.map {|s| s.full_name }, + assert_equal %w[a-2], inst.installed_gems.map(&:full_name), "sanity check" FileUtils.rm File.join(@tempdir, a2.file_name) @@ -217,7 +218,7 @@ class TestGemDependencyInstaller < Gem::TestCase end assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name) - assert_equal %w[b-1], inst.installed_gems.map {|s| s.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 @@ -236,7 +237,7 @@ class TestGemDependencyInstaller < Gem::TestCase Gem::Specification.reset FileUtils.mv @a1_gem, @tempdir - FileUtils.mv a2_gem, @tempdir # not in index + FileUtils.mv a2_gem, @tempdir # not in index FileUtils.mv @b1_gem, @tempdir FileUtils.mv a3_gem, @tempdir @@ -254,7 +255,7 @@ class TestGemDependencyInstaller < Gem::TestCase end assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name) - assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map(&:full_name) end def test_install_dependency @@ -273,11 +274,11 @@ class TestGemDependencyInstaller < Gem::TestCase FileUtils.mv @b1_gem, @tempdir Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new(:build_docs_in_background => false) + inst = Gem::DependencyInstaller.new(build_docs_in_background: false) inst.install "b" end - assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name) assert done_installing_ran, "post installs hook was not run" end @@ -293,11 +294,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new(:development => true) + inst = Gem::DependencyInstaller.new(development: true) inst.install "b" end - assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map(&:full_name) end def test_install_dependency_development_deep @@ -313,11 +314,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new(:development => true) + 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 {|s| s.full_name } + 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 @@ -333,11 +334,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new(:development => true, :dev_shallow => true) + inst = Gem::DependencyInstaller.new(development: true, dev_shallow: true) inst.install "d" end - assert_equal %w[c-1 d-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[c-1 d-1], inst.installed_gems.map(&:full_name) end def test_install_dependency_existing @@ -353,7 +354,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst.install "b" end - assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map(&:full_name) end def test_install_dependency_existing_extension @@ -390,7 +391,7 @@ class TestGemDependencyInstaller < Gem::TestCase Dir.chdir pwd end - assert_equal %w[f-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[f-1], inst.installed_gems.map(&:full_name) assert_path_exist e1.extension_dir end @@ -410,7 +411,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst.install "f" end - assert_equal %w[f-2], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[f-2], inst.installed_gems.map(&:full_name) end def test_install_local @@ -420,11 +421,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :domain => :local + inst = Gem::DependencyInstaller.new domain: :local inst.install "a-1.gem" end - assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map(&:full_name) end def test_install_local_prerelease @@ -434,11 +435,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :domain => :local + inst = Gem::DependencyInstaller.new domain: :local inst.install "a-1.a.gem" end - assert_equal %w[a-1.a], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1.a], inst.installed_gems.map(&:full_name) end def test_install_local_dependency @@ -450,11 +451,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :domain => :local + inst = Gem::DependencyInstaller.new domain: :local inst.install "b-1.gem" end - assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name) end def test_install_local_dependency_installed @@ -468,11 +469,45 @@ class TestGemDependencyInstaller < Gem::TestCase Dir.chdir @tempdir do Gem::Installer.at("a-1.gem").install - inst = Gem::DependencyInstaller.new :domain => :local + inst = Gem::DependencyInstaller.new domain: :local inst.install "b-1.gem" end - assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } + 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 @@ -481,11 +516,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :domain => :local + inst = Gem::DependencyInstaller.new domain: :local inst.install "gems/a-1.gem" end - assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map(&:full_name) end def test_install_minimal_deps @@ -507,19 +542,19 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :ignore_dependencies => true + inst = Gem::DependencyInstaller.new ignore_dependencies: true inst.install "b", req("= 1") end - assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }, + 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 = Gem::DependencyInstaller.new minimal_deps: true inst.install "e" end - assert_equal %w[a-1 e-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1 e-1], inst.installed_gems.map(&:full_name) end def test_install_no_minimal_deps @@ -541,19 +576,19 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :ignore_dependencies => true + inst = Gem::DependencyInstaller.new ignore_dependencies: true inst.install "b", req("= 1") end - assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }, + 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 = Gem::DependencyInstaller.new minimal_deps: false inst.install "e" end - assert_equal %w[a-1 b-2 e-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1 b-2 e-1], inst.installed_gems.map(&:full_name) end def test_install_no_document @@ -561,12 +596,12 @@ class TestGemDependencyInstaller < Gem::TestCase done_installing_called = false - Gem.done_installing do |dep_installer, specs| + 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 = Gem::DependencyInstaller.new domain: :local, document: [] inst.install @a1_gem @@ -580,14 +615,14 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :env_shebang => true, :wrappers => true, :format_executable => false + 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 %r{\A#!#{env} #{RbConfig::CONFIG['ruby_install_name']}\n}, - File.read(File.join(@gemhome, "bin", "a_bin")) + assert_match(/\A#!#{env} #{RbConfig::CONFIG["ruby_install_name"]}\n/, + File.read(File.join(@gemhome, "bin", "a_bin"))) end def test_install_force @@ -599,11 +634,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :force => true + inst = Gem::DependencyInstaller.new force: true inst.install "b" end - assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map(&:full_name) end def test_install_build_args @@ -614,8 +649,7 @@ class TestGemDependencyInstaller < Gem::TestCase build_args = %w[--a --b="c"] Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new( - :build_args => build_args) + inst = Gem::DependencyInstaller.new(build_args: build_args) inst.install "a" end @@ -629,11 +663,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :ignore_dependencies => true + inst = Gem::DependencyInstaller.new ignore_dependencies: true inst.install "b" end - assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map(&:full_name) end def test_install_install_dir @@ -650,11 +684,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :install_dir => gemhome2 + inst = Gem::DependencyInstaller.new install_dir: gemhome2 inst.install "b" end - assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } + 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)) @@ -674,11 +708,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :domain => :both + inst = Gem::DependencyInstaller.new domain: :both inst.install "b" end - assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } + 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 @@ -698,11 +732,11 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :domain => :both + inst = Gem::DependencyInstaller.new domain: :both inst.install "b" end - assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name) end def test_install_domain_local @@ -713,7 +747,7 @@ class TestGemDependencyInstaller < Gem::TestCase Dir.chdir @tempdir do e = assert_raise Gem::UnsatisfiableDependencyError do - inst = Gem::DependencyInstaller.new :domain => :local + inst = Gem::DependencyInstaller.new domain: :local inst.install "b" end @@ -721,7 +755,7 @@ class TestGemDependencyInstaller < Gem::TestCase assert_equal expected, e.message end - assert_equal [], inst.installed_gems.map {|s| s.full_name } + assert_equal [], inst.installed_gems.map(&:full_name) end def test_install_domain_remote @@ -734,10 +768,10 @@ class TestGemDependencyInstaller < Gem::TestCase @fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data - inst = Gem::DependencyInstaller.new :domain => :remote + inst = Gem::DependencyInstaller.new domain: :remote inst.install "a" - assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map(&:full_name) end def test_install_dual_repository @@ -750,11 +784,11 @@ class TestGemDependencyInstaller < Gem::TestCase gemhome2 = "#{@gemhome}2" Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :install_dir => gemhome2 + inst = Gem::DependencyInstaller.new install_dir: gemhome2 inst.install "a" end - assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }, + assert_equal %w[a-1], inst.installed_gems.map(&:full_name), "sanity check" ENV["GEM_HOME"] = @gemhome @@ -766,7 +800,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst.install "b" end - assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[b-1], inst.installed_gems.map(&:full_name) end def test_install_reinstall @@ -777,7 +811,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst = nil Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new :force => true + inst = Gem::DependencyInstaller.new force: true inst.install "a" end @@ -801,7 +835,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst.install "a" end - assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map(&:full_name) end def test_install_remote_dep @@ -821,7 +855,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst.install dep end - assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map(&:full_name) end def test_install_remote_platform_newer @@ -851,10 +885,10 @@ class TestGemDependencyInstaller < Gem::TestCase @fetcher.data["http://gems.example.com/gems/#{a2_o.file_name}"] = a2_o_data - inst = Gem::DependencyInstaller.new :domain => :remote + inst = Gem::DependencyInstaller.new domain: :remote inst.install "a" - assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1], inst.installed_gems.map(&:full_name) end def test_install_platform_is_ignored_when_a_file_is_specified @@ -862,10 +896,10 @@ class TestGemDependencyInstaller < Gem::TestCase s.platform = Gem::Platform.new %w[cpu other_platform 1] end - inst = Gem::DependencyInstaller.new :domain => :local + inst = Gem::DependencyInstaller.new domain: :local inst.install a_gem - assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map(&:full_name) end require "rubygems/openssl" @@ -874,14 +908,14 @@ class TestGemDependencyInstaller < Gem::TestCase def test_install_security_policy util_setup_gems - data = File.open(@a1_gem, "rb") {|f| f.read } + data = File.open(@a1_gem, "rb", &:read) @fetcher.data["http://gems.example.com/gems/a-1.gem"] = data - data = File.open(@b1_gem, "rb") {|f| f.read } + 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 + inst = Gem::DependencyInstaller.new security_policy: policy e = assert_raise Gem::Security::Exception do inst.install "b" @@ -890,21 +924,21 @@ class TestGemDependencyInstaller < Gem::TestCase assert_equal "unsigned gems are not allowed by the High Security policy", e.message - assert_equal %w[], inst.installed_gems.map {|s| s.full_name } + assert_equal %w[], inst.installed_gems.map(&:full_name) end end # Wrappers don't work on mswin - unless win_platform? + 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 = Gem::DependencyInstaller.new wrappers: false, format_executable: false inst.install "a" - refute_match(%r{This file was generated by RubyGems.}, + refute_match(/This file was generated by RubyGems./, File.read(File.join(@gemhome, "bin", "a_bin"))) end end @@ -912,32 +946,32 @@ class TestGemDependencyInstaller < Gem::TestCase def test_install_version util_setup_d - data = File.open(@d2_gem, "rb") {|f| f.read } + data = File.open(@d2_gem, "rb", &:read) @fetcher.data["http://gems.example.com/gems/d-2.gem"] = data - data = File.open(@d1_gem, "rb") {|f| f.read } + 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 {|s| s.full_name } + 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") {|f| f.read } + data = File.open(@d2_gem, "rb", &:read) @fetcher.data["http://gems.example.com/gems/d-2.gem"] = data - data = File.open(@d1_gem, "rb") {|f| f.read } + 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 {|s| s.full_name } + assert_equal %w[d-2], inst.installed_gems.map(&:full_name) end def test_install_legacy_spec_with_nil_required_ruby_version @@ -1110,7 +1144,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst = Gem::DependencyInstaller.new request_set = inst.resolve_dependencies "b", req(">= 0") - requests = request_set.sorted_requests.map {|req| req.full_name } + requests = request_set.sorted_requests.map(&:full_name) assert_equal %w[a-1 b-1], requests end @@ -1121,10 +1155,10 @@ class TestGemDependencyInstaller < Gem::TestCase FileUtils.mv @a1_gem, @tempdir FileUtils.mv @b1_gem, @tempdir - inst = Gem::DependencyInstaller.new :ignore_dependencies => true + inst = Gem::DependencyInstaller.new ignore_dependencies: true request_set = inst.resolve_dependencies "b", req(">= 0") - requests = request_set.sorted_requests.map {|req| req.full_name } + requests = request_set.sorted_requests.map(&:full_name) assert request_set.ignore_dependencies @@ -1141,7 +1175,7 @@ class TestGemDependencyInstaller < Gem::TestCase inst = Gem::DependencyInstaller.new request_set = inst.resolve_dependencies "a-1.gem", req(">= 0") - requests = request_set.sorted_requests.map {|req| req.full_name } + requests = request_set.sorted_requests.map(&:full_name) assert_equal %w[a-1], requests end diff --git a/test/rubygems/test_gem_dependency_list.rb b/test/rubygems/test_gem_dependency_list.rb index 0dca8f8c3a..590e042315 100644 --- a/test/rubygems/test_gem_dependency_list.rb +++ b/test/rubygems/test_gem_dependency_list.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/dependency_list" @@ -52,7 +53,7 @@ class TestGemDependencyList < Gem::TestCase order = @deplist.dependency_order - assert_equal %w[d-1 c-1 b-1 a-1], order.map {|s| s.full_name } + assert_equal %w[d-1 c-1 b-1 a-1], order.map(&:full_name) end def test_dependency_order_circle @@ -61,7 +62,7 @@ class TestGemDependencyList < Gem::TestCase order = @deplist.dependency_order - assert_equal %w[b-1 c-1 a-1], order.map {|s| s.full_name } + assert_equal %w[b-1 c-1 a-1], order.map(&:full_name) end def test_dependency_order_development @@ -79,7 +80,7 @@ class TestGemDependencyList < Gem::TestCase order = deplist.dependency_order - assert_equal %w[g-1 a-1 f-1 e-1], order.map {|s| s.full_name }, + assert_equal %w[g-1 a-1 f-1 e-1], order.map(&:full_name), "development on" deplist2 = Gem::DependencyList.new @@ -87,7 +88,7 @@ class TestGemDependencyList < Gem::TestCase order = deplist2.dependency_order - assert_equal %w[a-1 g-1 f-1 e-1], order.map {|s| s.full_name }, + assert_equal %w[a-1 g-1 f-1 e-1], order.map(&:full_name), "development off" end @@ -99,7 +100,7 @@ class TestGemDependencyList < Gem::TestCase order = @deplist.dependency_order - assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map {|s| s.full_name }, + assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map(&:full_name), "deps of trimmed specs not included" end @@ -108,7 +109,7 @@ class TestGemDependencyList < Gem::TestCase order = @deplist.dependency_order - assert_equal %w[c-2 a-1], order.map {|s| s.full_name } + assert_equal %w[c-2 a-1], order.map(&:full_name) end def test_find_name diff --git a/test/rubygems/test_gem_dependency_resolution_error.rb b/test/rubygems/test_gem_dependency_resolution_error.rb index 26b9e4ddc0..98a6b6b8fd 100644 --- a/test/rubygems/test_gem_dependency_resolution_error.rb +++ b/test/rubygems/test_gem_dependency_resolution_error.rb @@ -1,26 +1,25 @@ # frozen_string_literal: true + require_relative "helper" class TestGemDependencyResolutionError < Gem::TestCase def setup super - @DR = Gem::Resolver - @spec = util_spec "a", 2 - @a1_req = @DR::DependencyRequest.new dep("a", "= 1"), nil - @a2_req = @DR::DependencyRequest.new dep("a", "= 2"), nil + @a1_req = Gem::Resolver::DependencyRequest.new dep("a", "= 1"), nil + @a2_req = Gem::Resolver::DependencyRequest.new dep("a", "= 2"), nil - @activated = @DR::ActivationRequest.new @spec, @a2_req + @activated = Gem::Resolver::ActivationRequest.new @spec, @a2_req - @conflict = @DR::Conflict.new @a1_req, @activated + @conflict = Gem::Resolver::Conflict.new @a1_req, @activated @error = Gem::DependencyResolutionError.new @conflict end def test_message - assert_match %r{^conflicting dependencies a \(= 1\) and a \(= 2\)$}, - @error.message + assert_match(/^conflicting dependencies a \(= 1\) and a \(= 2\)$/, + @error.message) end end diff --git a/test/rubygems/test_gem_doctor.rb b/test/rubygems/test_gem_doctor.rb index d26a6ee310..1bcdc39022 100644 --- a/test/rubygems/test_gem_doctor.rb +++ b/test/rubygems/test_gem_doctor.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/doctor" diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb index 34d8903595..d5812da2aa 100644 --- a/test/rubygems/test_gem_ext_builder.rb +++ b/test/rubygems/test_gem_ext_builder.rb @@ -1,10 +1,13 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/ext" require "rubygems/installer" class TestGemExtBuilder < Gem::TestCase def setup + @orig_destdir = ENV["DESTDIR"] + @orig_make = ENV["make"] super @ext = File.join @tempdir, "ext" @@ -13,19 +16,15 @@ class TestGemExtBuilder < Gem::TestCase FileUtils.mkdir_p @ext FileUtils.mkdir_p @dest_path - @orig_DESTDIR = ENV["DESTDIR"] - @orig_make = ENV["make"] - @spec = util_spec "a" @builder = Gem::Ext::Builder.new @spec, "" end def teardown - ENV["DESTDIR"] = @orig_DESTDIR - ENV["make"] = @orig_make - super + ENV["DESTDIR"] = @orig_destdir + ENV["make"] = @orig_make end def test_class_make @@ -49,14 +48,14 @@ install: results = results.join("\n").b - assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} clean$}, results - assert_match %r{DESTDIR\\=#{ENV['DESTDIR']}$}, results - assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} install$}, results + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} clean$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]}$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} install$/, results) - if /nmake/ !~ results - assert_match %r{^clean: destination$}, results - assert_match %r{^all: destination$}, results - assert_match %r{^install: destination$}, results + unless results.include?("nmake") + assert_match(/^clean: destination$/, results) + assert_match(/^all: destination$/, results) + assert_match(/^install: destination$/, results) end end @@ -78,12 +77,14 @@ install: results = results.join("\n").b - assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} clean$}, results - assert_match %r{DESTDIR\\=#{ENV['DESTDIR']}$}, results - assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} install$}, results + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} clean$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]}$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} install$/, results) end def test_custom_make_with_options + pend "native windows platform only provides nmake" if vc_windows? + ENV["make"] = "make V=1" results = [] File.open File.join(@ext, "Makefile"), "w" do |io| @@ -100,49 +101,52 @@ install: end Gem::Ext::Builder.make @dest_path, results, @ext results = results.join("\n").b - assert_match %r{clean: OK}, results - assert_match %r{all: OK}, results - assert_match %r{install: OK}, results + assert_match(/clean: OK/, results) + assert_match(/all: OK/, results) + assert_match(/install: OK/, results) end def test_build_extensions - pend if RUBY_PLATFORM.include?("mswin") && ENV.key?("GITHUB_ACTIONS") # not working from the beginning - @spec.extensions << "ext/extconf.rb" + pend "terminates on mswin" if vc_windows? && ruby_repo? - ext_dir = File.join @spec.gem_dir, "ext" + extension_in_lib do + @spec.extensions << "ext/extconf.rb" - FileUtils.mkdir_p ext_dir + ext_dir = File.join @spec.gem_dir, "ext" - extconf_rb = File.join ext_dir, "extconf.rb" + FileUtils.mkdir_p ext_dir - File.open extconf_rb, "w" do |f| - f.write <<-'RUBY' - require 'mkmf' + extconf_rb = File.join ext_dir, "extconf.rb" - create_makefile 'a' - RUBY - end + File.open extconf_rb, "w" do |f| + f.write <<-'RUBY' + require 'mkmf' - ext_lib_dir = File.join ext_dir, "lib" - FileUtils.mkdir ext_lib_dir - FileUtils.touch File.join ext_lib_dir, "a.rb" - FileUtils.mkdir File.join ext_lib_dir, "a" - FileUtils.touch File.join ext_lib_dir, "a", "b.rb" + create_makefile 'a' + RUBY + end - use_ui @ui do - @builder.build_extensions - end + ext_lib_dir = File.join ext_dir, "lib" + FileUtils.mkdir ext_lib_dir + FileUtils.touch File.join ext_lib_dir, "a.rb" + FileUtils.mkdir File.join ext_lib_dir, "a" + FileUtils.touch File.join ext_lib_dir, "a", "b.rb" - assert_path_exist @spec.extension_dir - assert_path_exist @spec.gem_build_complete_path - assert_path_exist File.join @spec.extension_dir, "gem_make.out" - assert_path_exist File.join @spec.extension_dir, "a.rb" - assert_path_exist File.join @spec.gem_dir, "lib", "a.rb" - assert_path_exist File.join @spec.gem_dir, "lib", "a", "b.rb" + use_ui @ui do + @builder.build_extensions + end + + assert_path_exist @spec.extension_dir + assert_path_exist @spec.gem_build_complete_path + assert_path_exist File.join @spec.extension_dir, "gem_make.out" + assert_path_exist File.join @spec.extension_dir, "a.rb" + assert_path_exist File.join @spec.gem_dir, "lib", "a.rb" + assert_path_exist File.join @spec.gem_dir, "lib", "a", "b.rb" + end end def test_build_extensions_with_gemhome_with_space - pend if RUBY_PLATFORM.include?("mswin") && ENV.key?("GITHUB_ACTIONS") # not working from the beginning + pend "terminates on mswin" if vc_windows? && ruby_repo? new_gemhome = File.join @tempdir, "gem home" File.rename(@gemhome, new_gemhome) @gemhome = new_gemhome @@ -154,55 +158,47 @@ install: end def test_build_extensions_install_ext_only - class << Gem - alias orig_install_extension_in_lib install_extension_in_lib + pend "terminates on mswin" if vc_windows? && ruby_repo? - remove_method :install_extension_in_lib + extension_in_lib(false) do + @orig_install_extension_in_lib = Gem.configuration.install_extension_in_lib + Gem.configuration.install_extension_in_lib = false - def Gem.install_extension_in_lib - false - end - end - pend if RUBY_PLATFORM.include?("mswin") && ENV.key?("GITHUB_ACTIONS") # not working from the beginning + @spec.extensions << "ext/extconf.rb" - @spec.extensions << "ext/extconf.rb" + ext_dir = File.join @spec.gem_dir, "ext" - ext_dir = File.join @spec.gem_dir, "ext" + FileUtils.mkdir_p ext_dir - FileUtils.mkdir_p ext_dir + extconf_rb = File.join ext_dir, "extconf.rb" - extconf_rb = File.join ext_dir, "extconf.rb" + File.open extconf_rb, "w" do |f| + f.write <<-'RUBY' + require 'mkmf' - File.open extconf_rb, "w" do |f| - f.write <<-'RUBY' - require 'mkmf' + create_makefile 'a' + RUBY + end - create_makefile 'a' - RUBY - end + ext_lib_dir = File.join ext_dir, "lib" + FileUtils.mkdir ext_lib_dir + FileUtils.touch File.join ext_lib_dir, "a.rb" + FileUtils.mkdir File.join ext_lib_dir, "a" + FileUtils.touch File.join ext_lib_dir, "a", "b.rb" - ext_lib_dir = File.join ext_dir, "lib" - FileUtils.mkdir ext_lib_dir - FileUtils.touch File.join ext_lib_dir, "a.rb" - FileUtils.mkdir File.join ext_lib_dir, "a" - FileUtils.touch File.join ext_lib_dir, "a", "b.rb" + use_ui @ui do + @builder.build_extensions + end - use_ui @ui do - @builder.build_extensions + assert_path_exist @spec.extension_dir + assert_path_exist @spec.gem_build_complete_path + assert_path_exist File.join @spec.extension_dir, "gem_make.out" + assert_path_exist File.join @spec.extension_dir, "a.rb" + assert_path_not_exist File.join @spec.gem_dir, "lib", "a.rb" + assert_path_not_exist File.join @spec.gem_dir, "lib", "a", "b.rb" end - - assert_path_exist @spec.extension_dir - assert_path_exist @spec.gem_build_complete_path - assert_path_exist File.join @spec.extension_dir, "gem_make.out" - assert_path_exist File.join @spec.extension_dir, "a.rb" - assert_path_not_exist File.join @spec.gem_dir, "lib", "a.rb" - assert_path_not_exist File.join @spec.gem_dir, "lib", "a", "b.rb" ensure - class << Gem - remove_method :install_extension_in_lib - - alias install_extension_in_lib orig_install_extension_in_lib - end + Gem.configuration.install_extension_in_lib = @orig_install_extension_in_lib end def test_build_extensions_none @@ -252,7 +248,7 @@ install: cmd_make_out = File.read(gem_make_out) assert_match %r{#{Regexp.escape Gem.ruby} .* extconf\.rb}, cmd_make_out - assert_match %r{: No such file}, cmd_make_out + assert_match(/: No such file/, cmd_make_out) assert_path_not_exist @spec.gem_build_complete_path diff --git a/test/rubygems/test_gem_ext_cargo_builder.rb b/test/rubygems/test_gem_ext_cargo_builder.rb index c6bbab2cb3..5faf3e2480 100644 --- a/test/rubygems/test_gem_ext_cargo_builder.rb +++ b/test/rubygems/test_gem_ext_cargo_builder.rb @@ -2,6 +2,7 @@ require_relative "helper" require "rubygems/ext" +require "open3" class TestGemExtCargoBuilder < Gem::TestCase def setup @@ -22,25 +23,6 @@ class TestGemExtCargoBuilder < Gem::TestCase FileUtils.cp_r(@fixture_dir.to_s, @ext) end - def test_build_staticlib - skip_unsupported_platforms! - setup_rust_gem "rust_ruby_example" - - content = @fixture_dir.join("Cargo.toml").read.gsub("cdylib", "staticlib") - File.write(File.join(@ext, "Cargo.toml"), content) - - output = [] - - Dir.chdir @ext do - ENV.update(@rust_envs) - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) - assert_raise(Gem::Ext::CargoBuilder::DylibNotFoundError) do - builder.build nil, @dest_path, output - end - end - end - def test_build_cdylib skip_unsupported_platforms! setup_rust_gem "rust_ruby_example" @@ -49,42 +31,43 @@ class TestGemExtCargoBuilder < Gem::TestCase Dir.chdir @ext do ENV.update(@rust_envs) - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) - builder.build nil, @dest_path, output + builder = Gem::Ext::CargoBuilder.new + builder.build "Cargo.toml", @dest_path, output end output = output.join "\n" - bundle = File.join(@dest_path, "release/rust_ruby_example.#{RbConfig::CONFIG['DLEXT']}") + bundle = File.join(@dest_path, "rust_ruby_example.#{RbConfig::CONFIG["DLEXT"]}") - assert_match "Finished release [optimized] target(s)", output + assert_match(/Finished/, output) + assert_match(/release/, output) assert_ffi_handle bundle, "Init_rust_ruby_example" - rescue Exception => e + rescue StandardError => e pp output if output raise(e) end - def test_build_dev_profile + def test_rubygems_cfg_passed_to_rustc skip_unsupported_platforms! setup_rust_gem "rust_ruby_example" - + version_slug = Gem::VERSION.tr(".", "_") output = [] + replace_in_rust_file("src/lib.rs", "rubygems_x_x_x", "rubygems_#{version_slug}") + Dir.chdir @ext do ENV.update(@rust_envs) - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) - builder.profile = :dev - builder.build nil, @dest_path, output + builder = Gem::Ext::CargoBuilder.new + builder.build "Cargo.toml", @dest_path, output end output = output.join "\n" - bundle = File.join(@dest_path, "debug/rust_ruby_example.#{RbConfig::CONFIG['DLEXT']}") + bundle = File.join(@dest_path, "rust_ruby_example.#{RbConfig::CONFIG["DLEXT"]}") - assert_match "Finished dev [unoptimized + debuginfo] target(s)", output - assert_ffi_handle bundle, "Init_rust_ruby_example" - rescue Exception => e + assert_ffi_handle bundle, "hello_from_rubygems" + assert_ffi_handle bundle, "hello_from_rubygems_version" + refute_ffi_handle bundle, "should_never_exist" + rescue StandardError => e pp output if output raise(e) @@ -94,22 +77,17 @@ class TestGemExtCargoBuilder < Gem::TestCase skip_unsupported_platforms! setup_rust_gem "rust_ruby_example" - output = [] - FileUtils.rm(File.join(@ext, "src/lib.rs")) error = assert_raise(Gem::InstallError) do Dir.chdir @ext do ENV.update(@rust_envs) - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) - builder.build nil, @dest_path, output + builder = Gem::Ext::CargoBuilder.new + builder.build "Cargo.toml", @dest_path, [] end end - output = output.join "\n" - - assert_match "cargo failed", error.message + assert_match(/cargo\s.*\sfailed/, error.message) end def test_full_integration @@ -122,7 +100,7 @@ class TestGemExtCargoBuilder < Gem::TestCase require "tmpdir" env_for_subprocess = @rust_envs.merge("GEM_HOME" => Gem.paths.home) - gem = [env_for_subprocess, *ruby_with_rubygems_in_load_path, File.expand_path("../../bin/gem", __dir__)] + gem = [env_for_subprocess, *ruby_with_rubygems_in_load_path, File.expand_path("../../exe/gem", __dir__)] Dir.mktmpdir("rust_ruby_example") do |dir| built_gem = File.expand_path(File.join(dir, "rust_ruby_example.gem")) @@ -144,7 +122,7 @@ class TestGemExtCargoBuilder < Gem::TestCase require "tmpdir" env_for_subprocess = @rust_envs.merge("GEM_HOME" => Gem.paths.home) - gem = [env_for_subprocess, *ruby_with_rubygems_in_load_path, File.expand_path("../../bin/gem", __dir__)] + gem = [env_for_subprocess, *ruby_with_rubygems_in_load_path, File.expand_path("../../exe/gem", __dir__)] Dir.mktmpdir("custom_name") do |dir| built_gem = File.expand_path(File.join(dir, "custom_name.gem")) @@ -162,17 +140,32 @@ class TestGemExtCargoBuilder < Gem::TestCase private def skip_unsupported_platforms! - pend "jruby not supported" if java_platform? + pend "jruby not supported" if Gem.java_platform? pend "truffleruby not supported (yet)" if RUBY_ENGINE == "truffleruby" - pend "mswin not supported (yet)" if RUBY_PLATFORM.include?("mswin") && ENV.key?("GITHUB_ACTIONS") system(@rust_envs, "cargo", "-V", out: IO::NULL, err: [:child, :out]) pend "cargo not present" unless $?.success? pend "ruby.h is not provided by ruby repo" if ruby_repo? + pend "rust toolchain of mingw is broken" if mingw_windows? end def assert_ffi_handle(bundle, name) require "fiddle" dylib_handle = Fiddle.dlopen bundle assert_nothing_raised { dylib_handle[name] } + ensure + dylib_handle&.close + end + + def refute_ffi_handle(bundle, name) + require "fiddle" + dylib_handle = Fiddle.dlopen bundle + assert_raise { dylib_handle[name] } + ensure + dylib_handle&.close + end + + def replace_in_rust_file(name, from, to) + content = @fixture_dir.join(name).read.gsub(from, to) + File.write(File.join(@ext, name), content) end end diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/build.rb b/test/rubygems/test_gem_ext_cargo_builder/custom_name/build.rb deleted file mode 100644 index 0e04f0de5e..0000000000 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/build.rb +++ /dev/null @@ -1,21 +0,0 @@ -if ENV["RUBYOPT"] || defined? Gem - ENV.delete "RUBYOPT" - - require "rbconfig" - cmd = [RbConfig.ruby, "--disable-gems", "build.rb", *ARGV] - - exec(*cmd) -end - -require "tmpdir" - -lp = File.expand_path("../../../../lib", __dir__) -gem = ["ruby", "-I#{lp}", File.expand_path("../../../../bin/gem", __dir__)] -gemspec = File.expand_path("custom_name.gemspec", __dir__) - -Dir.mktmpdir("custom_name") do |dir| - built_gem = File.expand_path(File.join(dir, "custom_name.gem")) - system(*gem, "build", gemspec, "--output", built_gem) - system(*gem, "install", "--verbose", "--local", built_gem, *ARGV) - system %q(ruby -rcustom_name -e "puts 'Result: ' + CustomName.say_hello") -end diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec b/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec index 1f8e270e96..5f130527dd 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec @@ -1,10 +1,10 @@ +# frozen_string_literal: true + Gem::Specification.new do |s| s.name = "custom_name" s.version = "0.1.0" s.summary = "A Rust extension for Ruby" - s.extensions = ["Cargo.toml"] + s.extensions = ["ext/custom_name_lib/Cargo.toml"] s.authors = ["Ian Ker-Seymer"] - s.files = ["Cargo.toml", "Cargo.lock", "src/lib.rs"] - - s.metadata["cargo_crate_name"] = "custom-name-ext" + s.files = ["lib/custom_name.rb", "ext/custom_name_lib/Cargo.toml", "ext/custom_name_lib/Cargo.lock", "ext/custom_name_lib/src/lib.rs"] end diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock index da09e717f0..abd1e0ae33 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] name = "bindgen" -version = "0.60.1" +version = "0.69.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" +checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2" dependencies = [ "bitflags", "cexpr", @@ -28,13 +28,14 @@ dependencies = [ "regex", "rustc-hash", "shlex", + "syn", ] [[package]] name = "bitflags" -version = "1.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "cexpr" @@ -53,9 +54,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clang-sys" -version = "1.3.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", @@ -89,30 +90,21 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if", "winapi", ] [[package]] -name = "linkify" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96dd5884008358112bc66093362197c7248ece00d46624e2cf71e50029f8cff5" -dependencies = [ - "memchr", -] - -[[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -142,48 +134,51 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.20" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] [[package]] name = "rb-sys" -version = "0.9.29" +version = "0.9.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0317cb843cdeef14c5622917c55c0a170cee31348eb600c4a1683fb8c9e87e7a" +checksum = "47d30bcad206b51f2f66121190ca678dce1fdf3a2eae0ac5d838d1818b19bdf5" dependencies = [ - "bindgen", - "linkify", "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.29" +version = "0.9.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4b8274327aecb7edcff86e290d9cbe7b572b7889c1cfc7476358f4831f78ce5" +checksum = "3cbd92f281615f3c2dcb9dcb0f0576624752afbf9a7f99173b37c4b55b62dd8a" dependencies = [ + "bindgen", + "lazy_static", + "proc-macro2", + "quote", "regex", "shell-words", + "syn", ] [[package]] name = "regex" -version = "1.5.6" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -192,9 +187,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "rustc-hash" @@ -210,15 +205,26 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "winapi" diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml index 2a215a55dd..ad3e7f9b76 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = { version = "0.9.29", features = ["gem"] } +rb-sys = "0.9.97" diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/src/lib.rs b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/src/lib.rs index 543ad4a70e..28ba3be564 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/src/lib.rs +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/src/lib.rs @@ -12,7 +12,7 @@ unsafe extern "C" fn say_hello(_klass: VALUE) -> VALUE { #[allow(non_snake_case)] #[no_mangle] -pub extern "C" fn Init_custom_name() { +pub extern "C" fn Init_custom_name_ext() { let name = CString::new("CustomName").unwrap(); let function_name = CString::new("say_hello").unwrap(); // bindgen does not properly detect the arity of the ruby callback function, so we have to transmute diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb b/test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb new file mode 100644 index 0000000000..9f8d190baf --- /dev/null +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require "custom_name_lib/custom_name_ext" diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock index e351819848..1d174f569e 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] name = "bindgen" -version = "0.60.1" +version = "0.69.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" +checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2" dependencies = [ "bitflags", "cexpr", @@ -28,13 +28,14 @@ dependencies = [ "regex", "rustc-hash", "shlex", + "syn", ] [[package]] name = "bitflags" -version = "1.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "cexpr" @@ -53,9 +54,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clang-sys" -version = "1.3.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", @@ -82,30 +83,21 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if", "winapi", ] [[package]] -name = "linkify" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96dd5884008358112bc66093362197c7248ece00d46624e2cf71e50029f8cff5" -dependencies = [ - "memchr", -] - -[[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -135,48 +127,51 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.20" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] [[package]] name = "rb-sys" -version = "0.9.29" +version = "0.9.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0317cb843cdeef14c5622917c55c0a170cee31348eb600c4a1683fb8c9e87e7a" +checksum = "47d30bcad206b51f2f66121190ca678dce1fdf3a2eae0ac5d838d1818b19bdf5" dependencies = [ - "bindgen", - "linkify", "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.29" +version = "0.9.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4b8274327aecb7edcff86e290d9cbe7b572b7889c1cfc7476358f4831f78ce5" +checksum = "3cbd92f281615f3c2dcb9dcb0f0576624752afbf9a7f99173b37c4b55b62dd8a" dependencies = [ + "bindgen", + "lazy_static", + "proc-macro2", + "quote", "regex", "shell-words", + "syn", ] [[package]] name = "regex" -version = "1.5.6" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -185,9 +180,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "rust_ruby_example" @@ -210,15 +205,26 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "winapi" diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml index 1867db8e66..60cf49ce03 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = { version = "0.9.29", features = ["gem"] } +rb-sys = "0.9.97" diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/build.rb b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/build.rb deleted file mode 100644 index f404aa3468..0000000000 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/build.rb +++ /dev/null @@ -1,21 +0,0 @@ -if ENV["RUBYOPT"] || defined? Gem - ENV.delete "RUBYOPT" - - require "rbconfig" - cmd = [RbConfig.ruby, "--disable-gems", "build.rb", *ARGV] - - exec(*cmd) -end - -require "tmpdir" - -lp = File.expand_path("../../../../lib", __dir__) -gem = ["ruby", "-I#{lp}", File.expand_path("../../../../bin/gem", __dir__)] -gemspec = File.expand_path("rust_ruby_example.gemspec", __dir__) - -Dir.mktmpdir("rust_ruby_example") do |dir| - built_gem = File.expand_path(File.join(dir, "rust_ruby_example.gem")) - system(*gem, "build", gemspec, "--output", built_gem) - system(*gem, "install", "--verbose", "--local", built_gem, *ARGV) - system %q(ruby -rrust_ruby_example -e "puts 'Result: ' + RustRubyExample.reverse('hello world')") -end diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec index 82c84ba818..d3f8b11a8b 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Gem::Specification.new do |s| s.name = "rust_ruby_example" s.version = "0.1.0" diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs index b2a907c736..0626f04e0f 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs @@ -21,6 +21,18 @@ unsafe extern "C" fn pub_reverse(_klass: VALUE, mut input: VALUE) -> VALUE { rb_utf8_str_new(reversed_cstring.as_ptr(), size) } +#[cfg(rubygems)] +#[no_mangle] +pub extern "C" fn hello_from_rubygems() {} + +#[cfg(rubygems_0_0_0)] +#[no_mangle] +pub extern "C" fn should_never_exist() {} + +#[cfg(rubygems_x_x_x)] +#[no_mangle] +pub extern "C" fn hello_from_rubygems_version() {} + #[allow(non_snake_case)] #[no_mangle] pub extern "C" fn Init_rust_ruby_example() { diff --git a/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb b/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb index 88581ea4d8..a3fef50d54 100644 --- a/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb +++ b/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb @@ -1,26 +1,27 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/ext" require "rubygems/ext/cargo_builder/link_flag_converter" class TestGemExtCargoBuilderLinkFlagConverter < Gem::TestCase CASES = { - test_search_path_basic: ["-L/usr/local/lib", ["-L", "native=/usr/local/lib"]], - test_search_path_space: ["-L /usr/local/lib", ["-L", "native=/usr/local/lib"]], - test_search_path_space_in_path: ["-L/usr/local/my\ lib", ["-L", "native=/usr/local/my\ lib"]], - test_simple_lib: ["-lfoo", ["-l", "foo"]], - test_lib_with_nonascii: ["-lws2_32", ["-l", "ws2_32"]], - test_simple_lib_space: ["-l foo", ["-l", "foo"]], - test_verbose_lib_space: ["--library=foo", ["-l", "foo"]], - test_libstatic_with_colon: ["-l:libssp.a", ["-l", "static=ssp"]], - test_libstatic_with_colon_space: ["-l :libssp.a", ["-l", "static=ssp"]], - test_unconventional_lib_with_colon: ["-l:ssp.a", ["-C", "link_arg=-l:ssp.a"]], - test_dylib_with_colon_space: ["-l :libssp.dylib", ["-l", "dylib=ssp"]], - test_so_with_colon_space: ["-l :libssp.so", ["-l", "dylib=ssp"]], - test_dll_with_colon_space: ["-l :libssp.dll", ["-l", "dylib=ssp"]], - test_framework: ["-F/some/path", ["-l", "framework=/some/path"]], - test_framework_space: ["-F /some/path", ["-l", "framework=/some/path"]], - test_non_lib_dash_l: ["test_rubygems_20220413-976-lemgf9/prefix", ["-C", "link_arg=test_rubygems_20220413-976-lemgf9/prefix"]], + test_search_path_basic: ["-L/usr/local/lib", ["-L", "native=/usr/local/lib"]], + test_search_path_space: ["-L /usr/local/lib", ["-L", "native=/usr/local/lib"]], + test_search_path_space_in_path: ["-L/usr/local/my\ lib", ["-L", "native=/usr/local/my\ lib"]], + test_simple_lib: ["-lfoo", ["-l", "foo"]], + test_lib_with_nonascii: ["-lws2_32", ["-l", "ws2_32"]], + test_simple_lib_space: ["-l foo", ["-l", "foo"]], + test_verbose_lib_space: ["--library=foo", ["-l", "foo"]], + test_libstatic_with_colon: ["-l:libssp.a", ["-C", "link-args=-l:libssp.a"]], + test_libstatic_with_colon_space: ["-l :libssp.a", ["-C", "link-args=-l :libssp.a"]], + test_unconventional_lib_with_colon: ["-l:ssp.a", ["-C", "link-args=-l:ssp.a"]], + test_dylib_with_colon_space: ["-l :libssp.dylib", ["-C", "link-args=-l :libssp.dylib"]], + test_so_with_colon_space: ["-l :libssp.so", ["-C", "link-args=-l :libssp.so"]], + test_dll_with_colon_space: ["-l :libssp.dll", ["-C", "link-args=-l :libssp.dll"]], + test_framework: ["-F/some/path", ["-l", "framework=/some/path"]], + test_framework_space: ["-F /some/path", ["-l", "framework=/some/path"]], + test_non_lib_dash_l: ["test_rubygems_20220413-976-lemgf9/prefix", ["-C", "link-args=test_rubygems_20220413-976-lemgf9/prefix"]], }.freeze CASES.each do |test_name, (arg, expected)| diff --git a/test/rubygems/test_gem_ext_cargo_builder_unit.rb b/test/rubygems/test_gem_ext_cargo_builder_unit.rb index 4484f48ca9..89495b84ff 100644 --- a/test/rubygems/test_gem_ext_cargo_builder_unit.rb +++ b/test/rubygems/test_gem_ext_cargo_builder_unit.rb @@ -6,8 +6,7 @@ require "rubygems/ext" class TestGemExtCargoBuilderUnit < Gem::TestCase def test_cargo_command_passes_args skip_unsupported_platforms! - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) + builder = Gem::Ext::CargoBuilder.new command = builder.cargo_command(Dir.pwd, @tempdir, ["--all-features"]) assert_includes command, "--all-features" @@ -15,30 +14,18 @@ class TestGemExtCargoBuilderUnit < Gem::TestCase def test_cargo_command_locks_in_release_profile skip_unsupported_platforms! - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) + builder = Gem::Ext::CargoBuilder.new builder.profile = :release command = builder.cargo_command(Dir.pwd, @tempdir) assert_includes command, "--locked" end - def test_cargo_command_does_not_lock_in_dev_profile - skip_unsupported_platforms! - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) - builder.profile = :dev - command = builder.cargo_command(Dir.pwd, @tempdir) - - assert_not_includes command, "--locked" - end - def test_cargo_command_passes_respects_cargo_env_var skip_unsupported_platforms! old_cargo = ENV["CARGO"] ENV["CARGO"] = "mycargo" - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) + builder = Gem::Ext::CargoBuilder.new command = builder.cargo_command(Dir.pwd, @tempdir) assert_includes command, "mycargo" @@ -48,8 +35,7 @@ class TestGemExtCargoBuilderUnit < Gem::TestCase def test_build_env_includes_rbconfig skip_unsupported_platforms! - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) + builder = Gem::Ext::CargoBuilder.new env = builder.build_env assert_equal env.fetch("RBCONFIG_RUBY_SO_NAME"), RbConfig::CONFIG["RUBY_SO_NAME"] @@ -59,8 +45,7 @@ class TestGemExtCargoBuilderUnit < Gem::TestCase skip_unsupported_platforms! old_cargo = ENV["CARGO_BUILD_TARGET"] ENV["CARGO_BUILD_TARGET"] = "x86_64-unknown-linux-gnu" - spec = Gem::Specification.new "rust_ruby_example", "0.1.0" - builder = Gem::Ext::CargoBuilder.new(spec) + builder = Gem::Ext::CargoBuilder.new command = builder.cargo_command(Dir.pwd, @tempdir, ["--locked"]) assert_includes command, "--target" @@ -70,6 +55,6 @@ class TestGemExtCargoBuilderUnit < Gem::TestCase end def skip_unsupported_platforms! - pend "jruby not supported" if java_platform? + pend "jruby not supported" if Gem.java_platform? end end diff --git a/test/rubygems/test_gem_ext_cmake_builder.rb b/test/rubygems/test_gem_ext_cmake_builder.rb index ee84b8e728..5f886af05f 100644 --- a/test/rubygems/test_gem_ext_cmake_builder.rb +++ b/test/rubygems/test_gem_ext_cmake_builder.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/ext" @@ -42,11 +43,11 @@ install (FILES test.txt DESTINATION bin) output = output.join "\n" - assert_match %r{^cmake \. -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}}, output - assert_match %r{#{Regexp.escape @ext}}, output + assert_match(/^cmake \. -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}/, output) + assert_match(/#{Regexp.escape @ext}/, output) assert_contains_make_command "", output assert_contains_make_command "install", output - assert_match %r{test\.txt}, output + assert_match(/test\.txt/, output) end def test_self_build_fail @@ -58,12 +59,12 @@ install (FILES test.txt DESTINATION bin) output = output.join "\n" - shell_error_msg = %r{(CMake Error: .*)} + shell_error_msg = /(CMake Error: .*)/ assert_match "cmake failed", error.message - assert_match %r{^cmake . -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}}, output - assert_match %r{#{shell_error_msg}}, output + assert_match(/^cmake . -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}/, output) + assert_match(/#{shell_error_msg}/, output) end def test_self_build_has_makefile diff --git a/test/rubygems/test_gem_ext_configure_builder.rb b/test/rubygems/test_gem_ext_configure_builder.rb index 191b332dda..6a2f9883f0 100644 --- a/test/rubygems/test_gem_ext_configure_builder.rb +++ b/test/rubygems/test_gem_ext_configure_builder.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/ext" @@ -56,7 +57,7 @@ class TestGemExtConfigureBuilder < Gem::TestCase assert_match(/^current directory:/, output.shift) assert_equal "#{sh_prefix_configure}#{@dest_path}", output.shift - assert_match %r{#{shell_error_msg}}, output.shift + assert_match(/#{shell_error_msg}/, output.shift) assert_equal true, output.empty? end diff --git a/test/rubygems/test_gem_ext_ext_conf_builder.rb b/test/rubygems/test_gem_ext_ext_conf_builder.rb index e6b980a96b..218c6f3d5e 100644 --- a/test/rubygems/test_gem_ext_ext_conf_builder.rb +++ b/test/rubygems/test_gem_ext_ext_conf_builder.rb @@ -15,7 +15,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase end def test_class_build - if java_platform? + if Gem.java_platform? pend("failing on jruby") end @@ -34,7 +34,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase assert_same result, output assert_match(/^current directory:/, output[0]) - assert_match(/^#{Gem.ruby}.* extconf.rb/, output[1]) + assert_match(/^#{Regexp.quote(Gem.ruby)}.* extconf.rb/, output[1]) assert_equal "creating Makefile\n", output[2] assert_match(/^current directory:/, output[3]) assert_contains_make_command "clean", output[4] @@ -45,7 +45,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase end def test_class_build_rbconfig_make_prog - if java_platform? + if Gem.java_platform? pend("failing on jruby") end @@ -65,14 +65,14 @@ class TestGemExtExtConfBuilder < Gem::TestCase end end - def test_class_build_env_MAKE + def test_class_build_env_make env_make = ENV.delete "make" ENV["make"] = nil - env_MAKE = ENV.delete "MAKE" + env_large_make = ENV.delete "MAKE" ENV["MAKE"] = "anothermake" - if java_platform? + if Gem.java_platform? pend("failing on jruby") end @@ -91,7 +91,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase assert_contains_make_command "clean", output[4] end ensure - ENV["MAKE"] = env_MAKE + ENV["MAKE"] = env_large_make ENV["make"] = env_make end @@ -114,7 +114,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase assert_equal "extconf failed, exit code 1", error.message - assert_match(/^#{Gem.ruby}.* extconf.rb/, output[1]) + assert_match(/^#{Regexp.quote(Gem.ruby)}.* extconf.rb/, output[1]) assert_match(File.join(@dest_path, "mkmf.log"), output[4]) assert_includes(output, "To see why this extension failed to compile, please check the mkmf.log which can be found here:\n") @@ -218,7 +218,6 @@ end RbConfig::CONFIG["configure_args"] = args if args yield - ensure if configure_args RbConfig::CONFIG["configure_args"] = configure_args diff --git a/test/rubygems/test_gem_ext_rake_builder.rb b/test/rubygems/test_gem_ext_rake_builder.rb index 3ed818a7f8..bd72c1aa08 100644 --- a/test/rubygems/test_gem_ext_rake_builder.rb +++ b/test/rubygems/test_gem_ext_rake_builder.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/ext" @@ -22,9 +23,9 @@ class TestGemExtRakeBuilder < Gem::TestCase output = output.join "\n" - refute_match %r{^rake failed:}, output - assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output - assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}}, output + refute_match(/^rake failed:/, output) + assert_match(/^#{Regexp.escape Gem.ruby} mkrf_conf\.rb/, output) + assert_match(/^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}/, output) end end @@ -41,9 +42,9 @@ class TestGemExtRakeBuilder < Gem::TestCase output = output.join "\n" - refute_match %r{^rake failed:}, output - assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output - assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}}, output + refute_match(/^rake failed:/, output) + assert_match(/^#{Regexp.escape Gem.ruby} mkrf_conf\.rb/, output) + assert_match(/^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}/, output) end end @@ -71,7 +72,7 @@ class TestGemExtRakeBuilder < Gem::TestCase output = output.join "\n" assert_match "OpenSSL", output - assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output + assert_match(/^#{Regexp.escape Gem.ruby} mkrf_conf\.rb/, output) end def test_class_build_no_mkrf_passes_args @@ -82,8 +83,8 @@ class TestGemExtRakeBuilder < Gem::TestCase output = output.join "\n" - refute_match %r{^rake failed:}, output - assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path} test1 test2}, output + refute_match(/^rake failed:/, output) + assert_match(/^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path} test1 test2/, output) end end @@ -91,12 +92,12 @@ class TestGemExtRakeBuilder < Gem::TestCase create_temp_mkrf_file("task :default do abort 'fail' end") output = [] - build_rake_in(false) do |rake| + build_rake_in(false) do |_rake| error = assert_raise Gem::InstallError do Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output, [], nil, @ext end - assert_match %r{^rake failed}, error.message + assert_match(/^rake failed/, error.message) end end diff --git a/test/rubygems/test_gem_gem_runner.rb b/test/rubygems/test_gem_gem_runner.rb index f0128febc8..c05e74c991 100644 --- a/test/rubygems/test_gem_gem_runner.rb +++ b/test/rubygems/test_gem_gem_runner.rb @@ -1,20 +1,26 @@ # frozen_string_literal: true + require_relative "helper" class TestGemGemRunner < Gem::TestCase def setup - super - require "rubygems/command" @orig_args = Gem::Command.build_args @orig_specific_extra_args = Gem::Command.specific_extra_args_hash.dup @orig_extra_args = Gem::Command.extra_args.dup + super + + @orig_gem_home = ENV["GEM_HOME"] + ENV["GEM_HOME"] = @gemhome + require "rubygems/gem_runner" @runner = Gem::GemRunner.new end def teardown + ENV["GEM_HOME"] = @orig_gem_home + super Gem::Command.build_args = @orig_args diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb index 2ca5b402d9..a3236e6276 100644 --- a/test/rubygems/test_gem_gemcutter_utilities.rb +++ b/test/rubygems/test_gem_gemcutter_utilities.rb @@ -1,14 +1,18 @@ # frozen_string_literal: true + require_relative "helper" +require_relative "multifactor_auth_utilities" require "rubygems" require "rubygems/command" require "rubygems/gemcutter_utilities" +require "rubygems/config_file" class TestGemGemcutterUtilities < Gem::TestCase def setup super credential_setup + @fetcher = SignInFetcher.new # below needed for random testing, class property Gem.configuration.disable_default_gem_server = nil @@ -38,7 +42,7 @@ class TestGemGemcutterUtilities < Gem::TestCase } File.open Gem.configuration.credentials_path, "w" do |f| - f.write keys.to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys) end ENV["RUBYGEMS_HOST"] = "http://rubygems.engineyard.com" @@ -49,10 +53,10 @@ class TestGemGemcutterUtilities < Gem::TestCase end def test_api_key - keys = { :rubygems_api_key => "KEY" } + keys = { rubygems_api_key: "KEY" } File.open Gem.configuration.credentials_path, "w" do |f| - f.write keys.to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys) end Gem.configuration.load_api_keys @@ -61,10 +65,10 @@ class TestGemGemcutterUtilities < Gem::TestCase end def test_api_key_override - keys = { :rubygems_api_key => "KEY", :other => "OTHER" } + keys = { rubygems_api_key: "KEY", other: "OTHER" } File.open Gem.configuration.credentials_path, "w" do |f| - f.write keys.to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys) end Gem.configuration.load_api_keys @@ -92,120 +96,111 @@ class TestGemGemcutterUtilities < Gem::TestCase end def test_sign_in - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - util_sign_in [api_key, 200, "OK"] + util_sign_in - assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output + assert_match(/Enter your RubyGems.org credentials./, @sign_in_ui.output) assert @fetcher.last_request["authorization"] - assert_match %r{Signed in.}, @sign_in_ui.output + assert_match(/Signed in./, @sign_in_ui.output) credentials = load_yaml_file Gem.configuration.credentials_path - assert_equal api_key, credentials[:rubygems_api_key] + assert_equal @fetcher.api_key, credentials[:rubygems_api_key] end def test_sign_in_with_host - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - - util_sign_in [api_key, 200, "OK"], "http://example.com", ["http://example.com"] + @fetcher = SignInFetcher.new(host: "http://example.com") + util_sign_in assert_match "Enter your http://example.com credentials.", @sign_in_ui.output assert @fetcher.last_request["authorization"] - assert_match %r{Signed in.}, @sign_in_ui.output + assert_match(/Signed in./, @sign_in_ui.output) credentials = load_yaml_file Gem.configuration.credentials_path - assert_equal api_key, credentials["http://example.com"] + assert_equal @fetcher.api_key, credentials["http://example.com"] end def test_sign_in_with_host_nil - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - - util_sign_in [api_key, 200, "OK"], nil, [nil] + @fetcher = SignInFetcher.new(host: nil) + util_sign_in(args: [nil]) assert_match "Enter your RubyGems.org credentials.", @sign_in_ui.output assert @fetcher.last_request["authorization"] - assert_match %r{Signed in.}, @sign_in_ui.output + assert_match(/Signed in./, @sign_in_ui.output) credentials = load_yaml_file Gem.configuration.credentials_path - assert_equal api_key, credentials[:rubygems_api_key] + assert_equal @fetcher.api_key, credentials[:rubygems_api_key] end def test_sign_in_with_host_ENV - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - util_sign_in [api_key, 200, "OK"], "http://example.com" + @fetcher = SignInFetcher.new(host: "http://example.com") + util_sign_in assert_match "Enter your http://example.com credentials.", @sign_in_ui.output assert @fetcher.last_request["authorization"] - assert_match %r{Signed in.}, @sign_in_ui.output + assert_match(/Signed in./, @sign_in_ui.output) credentials = load_yaml_file Gem.configuration.credentials_path - assert_equal api_key, credentials["http://example.com"] + assert_equal @fetcher.api_key, credentials["http://example.com"] end def test_sign_in_skips_with_existing_credentials - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - Gem.configuration.rubygems_api_key = api_key + Gem.configuration.rubygems_api_key = @fetcher.api_key - util_sign_in [api_key, 200, "OK"] + util_sign_in assert_equal "", @sign_in_ui.output end def test_sign_in_skips_with_key_override - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" Gem.configuration.api_keys[:KEY] = "other" @cmd.options[:key] = :KEY - util_sign_in [api_key, 200, "OK"] + util_sign_in assert_equal "", @sign_in_ui.output end def test_sign_in_with_other_credentials_doesnt_overwrite_other_keys - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" other_api_key = "f46dbb18bb6a9c97cdc61b5b85c186a17403cdcbf" + config = Hash[:other_api_key, other_api_key] + File.open Gem.configuration.credentials_path, "w" do |f| - f.write Hash[:other_api_key, other_api_key].to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(config) end - util_sign_in [api_key, 200, "OK"] + util_sign_in - assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output - assert_match %r{Signed in.}, @sign_in_ui.output + assert_match(/Enter your RubyGems.org credentials./, @sign_in_ui.output) + assert_match(/Signed in./, @sign_in_ui.output) credentials = load_yaml_file Gem.configuration.credentials_path - assert_equal api_key, credentials[:rubygems_api_key] + assert_equal @fetcher.api_key, credentials[:rubygems_api_key] assert_equal other_api_key, credentials[:other_api_key] end def test_sign_in_with_bad_credentials + @fetcher.respond_with_forbidden_api_key_response assert_raise Gem::MockGemUi::TermError do - util_sign_in ["Access Denied.", 403, "Forbidden"] + util_sign_in end - assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output - assert_match %r{Access Denied.}, @sign_in_ui.output + assert_match(/Enter your RubyGems.org credentials./, @sign_in_ui.output) + assert_match(/Access Denied./, @sign_in_ui.output) end def test_signin_with_env_otp_code ENV["GEM_HOST_OTP_CODE"] = "111111" - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - util_sign_in [api_key, 200, "OK"] + util_sign_in assert_match "Signed in with API key:", @sign_in_ui.output assert_equal "111111", @fetcher.last_request["OTP"] end def test_sign_in_with_correct_otp_code - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." - - util_sign_in(proc do - @call_count ||= 0 - (@call_count += 1).odd? ? [response_fail, 401, "Unauthorized"] : [api_key, 200, "OK"] - end, nil, [], "111111\n") + @fetcher.respond_with_require_otp + util_sign_in(extra_input: "111111\n") assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @sign_in_ui.output assert_match "Code: ", @sign_in_ui.output @@ -216,8 +211,9 @@ class TestGemGemcutterUtilities < Gem::TestCase def test_sign_in_with_incorrect_otp_code response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." + @fetcher.respond_with_unauthorized_api_key_response assert_raise Gem::MockGemUi::TermError do - util_sign_in [response, 401, "Unauthorized"], nil, [], "111111\n" + util_sign_in(extra_input: "111111\n") end assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @sign_in_ui.output @@ -226,23 +222,91 @@ class TestGemGemcutterUtilities < Gem::TestCase assert_equal "111111", @fetcher.last_request["OTP"] end - def util_sign_in(response, host = nil, args = [], extra_input = "") - email = "you@example.com" - password = "secret" - profile_response = [ "mfa: disabled\n" , 200, "OK"] + def test_sign_in_with_webauthn_enabled + server = Gem::MockTCPServer.new + + @fetcher.respond_with_require_otp + @fetcher.respond_with_webauthn_url + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do + util_sign_in + end + end + + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output + assert_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output + assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] + end + + def test_sign_in_with_webauthn_enabled_with_error + server = Gem::MockTCPServer.new + error = Gem::WebauthnVerificationError.new("Something went wrong") + + @fetcher.respond_with_require_otp + @fetcher.respond_with_webauthn_url + error = assert_raise Gem::MockGemUi::TermError do + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do + util_sign_in + end + end + end + assert_equal 1, error.exit_code + + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output + assert_match "ERROR: Security device verification failed: Something went wrong", @sign_in_ui.error + refute_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output + refute_match "Signed in with API key:", @sign_in_ui.output + end + + def test_sign_in_with_webauthn_enabled_with_polling + server = Gem::MockTCPServer.new + @fetcher.respond_with_require_otp + @fetcher.respond_with_webauthn_url + @fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo") + + TCPServer.stub(:new, server) do + util_sign_in + end + + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output + assert_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output + assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] + end + + def test_sign_in_with_webauthn_enabled_with_polling_failure + server = Gem::MockTCPServer.new + @fetcher.respond_with_require_otp + @fetcher.respond_with_webauthn_url + @fetcher.respond_with_webauthn_polling_failure - if host - ENV["RUBYGEMS_HOST"] = host - else - host = Gem.host + assert_raise Gem::MockGemUi::TermError do + TCPServer.stub(:new, server) do + util_sign_in + end end - @fetcher = Gem::FakeFetcher.new - @fetcher.data["#{host}/api/v1/api_key"] = response - @fetcher.data["#{host}/api/v1/profile/me.yaml"] = profile_response + assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output + assert_match "ERROR: Security device verification failed: " \ + "The token in the link you used has either expired or been used already.", @sign_in_ui.error + end + + def util_sign_in(args: [], extra_input: "") + email = "you@example.com" + password = "secret" + + ENV["RUBYGEMS_HOST"] = @fetcher.host Gem::RemoteFetcher.fetcher = @fetcher - @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n" + extra_input) + @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n\n\n" + extra_input) use_ui @sign_in_ui do if args.length > 0 @@ -254,9 +318,9 @@ class TestGemGemcutterUtilities < Gem::TestCase end def test_verify_api_key - keys = { :other => "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" } + keys = { other: "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" } File.open Gem.configuration.credentials_path, "w" do |f| - f.write keys.to_yaml + f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys) end Gem.configuration.load_api_keys @@ -269,4 +333,29 @@ class TestGemGemcutterUtilities < Gem::TestCase @cmd.verify_api_key :missing end end + + class SignInFetcher < Gem::MultifactorAuthFetcher + attr_reader :api_key + + def initialize(host: nil) + super(host: host) + @api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" + @data["#{@host}/api/v1/api_key"] = Gem::HTTPResponseFactory.create(body: @api_key, code: 200, msg: "OK") + @data["#{@host}/api/v1/profile/me.yaml"] = Gem::HTTPResponseFactory.create(body: "mfa: disabled\n", code: 200, msg: "OK") + end + + def respond_with_require_otp + super("#{host}/api/v1/api_key", @api_key) + end + + def respond_with_forbidden_api_key_response + @data["#{host}/api/v1/api_key"] = Gem::HTTPResponseFactory.create(body: "Access Denied.", code: 403, msg: "Forbidden") + end + + def respond_with_unauthorized_api_key_response + response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." + + @data["#{host}/api/v1/api_key"] = Gem::HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized") + end + end end diff --git a/test/rubygems/test_gem_impossible_dependencies_error.rb b/test/rubygems/test_gem_impossible_dependencies_error.rb index 59395f0bbd..94c0290ea1 100644 --- a/test/rubygems/test_gem_impossible_dependencies_error.rb +++ b/test/rubygems/test_gem_impossible_dependencies_error.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemImpossibleDependenciesError < Gem::TestCase diff --git a/test/rubygems/test_gem_indexer.rb b/test/rubygems/test_gem_indexer.rb deleted file mode 100644 index cfdff6e4c5..0000000000 --- a/test/rubygems/test_gem_indexer.rb +++ /dev/null @@ -1,361 +0,0 @@ -# frozen_string_literal: true -require_relative "helper" -require "rubygems/indexer" - -class TestGemIndexer < Gem::TestCase - def setup - super - - util_make_gems - - @d2_0 = util_spec "d", "2.0" do |s| - s.date = Gem::Specification::TODAY - 86400 * 3 - end - util_build_gem @d2_0 - - @d2_0_a = util_spec "d", "2.0.a" - util_build_gem @d2_0_a - - @d2_0_b = util_spec "d", "2.0.b" - util_build_gem @d2_0_b - - @default = new_default_spec "default", 2 - install_default_gems @default - - @indexerdir = File.join(@tempdir, "indexer") - - gems = File.join(@indexerdir, "gems") - FileUtils.mkdir_p gems - FileUtils.mv Dir[File.join(@gemhome, "cache", "*.gem")], gems - - @indexer = Gem::Indexer.new(@indexerdir) - end - - def test_initialize - assert_equal @indexerdir, @indexer.dest_directory - assert_match %r{#{Dir.mktmpdir('gem_generate_index').match(/.*-/)}}, @indexer.directory - - indexer = Gem::Indexer.new @indexerdir - assert indexer.build_modern - - indexer = Gem::Indexer.new @indexerdir, :build_modern => true - assert indexer.build_modern - end - - def test_build_indices - @indexer.make_temp_directories - - use_ui @ui do - @indexer.build_indices - end - - specs_path = File.join @indexer.directory, "specs.#{@marshal_version}" - specs_dump = Gem.read_binary specs_path - specs = Marshal.load specs_dump - - expected = [["a", Gem::Version.new("1"), "ruby"], - ["a", Gem::Version.new("2"), "ruby"], - ["a_evil", Gem::Version.new("9"), "ruby"], - ["b", Gem::Version.new("2"), "ruby"], - ["c", Gem::Version.new("1.2"), "ruby"], - ["d", Gem::Version.new("2.0"), "ruby"], - ["dep_x", Gem::Version.new("1"), "ruby"], - ["pl", Gem::Version.new("1"), "i386-linux"], - ["x", Gem::Version.new("1"), "ruby"]] - - assert_equal expected, specs - - latest_specs_path = File.join(@indexer.directory, - "latest_specs.#{@marshal_version}") - latest_specs_dump = Gem.read_binary latest_specs_path - latest_specs = Marshal.load latest_specs_dump - - expected = [["a", Gem::Version.new("2"), "ruby"], - ["a_evil", Gem::Version.new("9"), "ruby"], - ["b", Gem::Version.new("2"), "ruby"], - ["c", Gem::Version.new("1.2"), "ruby"], - ["d", Gem::Version.new("2.0"), "ruby"], - ["dep_x", Gem::Version.new("1"), "ruby"], - ["pl", Gem::Version.new("1"), "i386-linux"], - ["x", Gem::Version.new("1"), "ruby"]] - - assert_equal expected, latest_specs, "latest_specs" - end - - def test_generate_index - use_ui @ui do - @indexer.generate_index - end - - quickdir = File.join @indexerdir, "quick" - marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}" - - assert_directory_exists quickdir - assert_directory_exists marshal_quickdir - - assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz" - assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz" - - refute_indexed marshal_quickdir, File.basename(@c1_2.spec_file) - - assert_indexed @indexerdir, "specs.#{@marshal_version}" - assert_indexed @indexerdir, "specs.#{@marshal_version}.gz" - - assert_indexed @indexerdir, "latest_specs.#{@marshal_version}" - assert_indexed @indexerdir, "latest_specs.#{@marshal_version}.gz" - - refute_directory_exists @indexer.directory - end - - def test_generate_index_modern - @indexer.build_modern = true - - use_ui @ui do - @indexer.generate_index - end - - refute_indexed @indexerdir, "yaml" - refute_indexed @indexerdir, "yaml.Z" - refute_indexed @indexerdir, "Marshal.#{@marshal_version}" - refute_indexed @indexerdir, "Marshal.#{@marshal_version}.Z" - - quickdir = File.join @indexerdir, "quick" - marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}" - - assert_directory_exists quickdir, "quickdir should be directory" - assert_directory_exists marshal_quickdir - - refute_indexed quickdir, "index" - refute_indexed quickdir, "index.rz" - - refute_indexed quickdir, "latest_index" - refute_indexed quickdir, "latest_index.rz" - - refute_indexed quickdir, "#{File.basename(@a1.spec_file)}.rz" - refute_indexed quickdir, "#{File.basename(@a2.spec_file)}.rz" - refute_indexed quickdir, "#{File.basename(@b2.spec_file)}.rz" - refute_indexed quickdir, "#{File.basename(@c1_2.spec_file)}.rz" - - refute_indexed quickdir, "#{@pl1.original_name}.gemspec.rz" - refute_indexed quickdir, "#{File.basename(@pl1.spec_file)}.rz" - - assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz" - assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz" - - refute_indexed quickdir, "#{File.basename(@c1_2.spec_file)}" - refute_indexed marshal_quickdir, "#{File.basename(@c1_2.spec_file)}" - - assert_indexed @indexerdir, "specs.#{@marshal_version}" - assert_indexed @indexerdir, "specs.#{@marshal_version}.gz" - - assert_indexed @indexerdir, "latest_specs.#{@marshal_version}" - assert_indexed @indexerdir, "latest_specs.#{@marshal_version}.gz" - end - - def test_generate_index_modern_back_to_back - @indexer.build_modern = true - - use_ui @ui do - @indexer.generate_index - end - - @indexer = Gem::Indexer.new @indexerdir - @indexer.build_modern = true - - use_ui @ui do - @indexer.generate_index - end - quickdir = File.join @indexerdir, "quick" - marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}" - - assert_directory_exists quickdir - assert_directory_exists marshal_quickdir - - assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz" - assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz" - - assert_indexed @indexerdir, "specs.#{@marshal_version}" - assert_indexed @indexerdir, "specs.#{@marshal_version}.gz" - - assert_indexed @indexerdir, "latest_specs.#{@marshal_version}" - assert_indexed @indexerdir, "latest_specs.#{@marshal_version}.gz" - end - - def test_generate_index_ui - use_ui @ui do - @indexer.generate_index - end - - assert_match %r{^\.\.\.\.\.\.\.\.\.\.\.\.$}, @ui.output - assert_match %r{^Generating Marshal quick index gemspecs for 12 gems$}, - @ui.output - assert_match %r{^Complete$}, @ui.output - assert_match %r{^Generating specs index$}, @ui.output - assert_match %r{^Generating latest specs index$}, @ui.output - assert_match %r{^Generating prerelease specs index$}, @ui.output - assert_match %r{^Complete$}, @ui.output - assert_match %r{^Compressing indices$}, @ui.output - - assert_equal "", @ui.error - end - - def test_generate_index_specs - use_ui @ui do - @indexer.generate_index - end - - specs_path = File.join @indexerdir, "specs.#{@marshal_version}" - - specs_dump = Gem.read_binary specs_path - specs = Marshal.load specs_dump - - expected = [ - ["a", Gem::Version.new(1), "ruby"], - ["a", Gem::Version.new(2), "ruby"], - ["a_evil", Gem::Version.new(9), "ruby"], - ["b", Gem::Version.new(2), "ruby"], - ["c", Gem::Version.new("1.2"), "ruby"], - ["d", Gem::Version.new("2.0"), "ruby"], - ["dep_x", Gem::Version.new(1), "ruby"], - ["pl", Gem::Version.new(1), "i386-linux"], - ["x", Gem::Version.new(1), "ruby"], - ] - - assert_equal expected, specs - - assert_same specs[0].first, specs[1].first, - "identical names not identical" - - assert_same specs[0][1], specs[-1][1], - "identical versions not identical" - - assert_same specs[0].last, specs[1].last, - "identical platforms not identical" - - refute_same specs[1][1], specs[5][1], - "different versions not different" - end - - def test_generate_index_latest_specs - use_ui @ui do - @indexer.generate_index - end - - latest_specs_path = File.join @indexerdir, "latest_specs.#{@marshal_version}" - - latest_specs_dump = Gem.read_binary latest_specs_path - latest_specs = Marshal.load latest_specs_dump - - expected = [ - ["a", Gem::Version.new(2), "ruby"], - ["a_evil", Gem::Version.new(9), "ruby"], - ["b", Gem::Version.new(2), "ruby"], - ["c", Gem::Version.new("1.2"), "ruby"], - ["d", Gem::Version.new("2.0"), "ruby"], - ["dep_x", Gem::Version.new(1), "ruby"], - ["pl", Gem::Version.new(1), "i386-linux"], - ["x", Gem::Version.new(1), "ruby"], - ] - - assert_equal expected, latest_specs - - assert_same latest_specs[0][1], latest_specs[2][1], - "identical versions not identical" - - assert_same latest_specs[0].last, latest_specs[1].last, - "identical platforms not identical" - end - - def test_generate_index_prerelease_specs - use_ui @ui do - @indexer.generate_index - end - - prerelease_specs_path = File.join @indexerdir, "prerelease_specs.#{@marshal_version}" - - prerelease_specs_dump = Gem.read_binary prerelease_specs_path - prerelease_specs = Marshal.load prerelease_specs_dump - - assert_equal [["a", Gem::Version.new("3.a"), "ruby"], - ["d", Gem::Version.new("2.0.a"), "ruby"], - ["d", Gem::Version.new("2.0.b"), "ruby"]], - prerelease_specs - end - - ## - # Emulate the starting state of Gem::Specification in a live environment, - # where it will carry the list of system gems - def with_system_gems - Gem::Specification.reset - - sys_gem = util_spec "systemgem", "1.0" - util_build_gem sys_gem - install_default_gems sys_gem - yield - util_remove_gem sys_gem - end - - def test_update_index - use_ui @ui do - @indexer.generate_index - end - - quickdir = File.join @indexerdir, "quick" - marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}" - - assert_directory_exists quickdir - assert_directory_exists marshal_quickdir - - @d2_1 = util_spec "d", "2.1" - util_build_gem @d2_1 - @d2_1_tuple = [@d2_1.name, @d2_1.version, @d2_1.original_platform] - - @d2_1_a = util_spec "d", "2.2.a" - util_build_gem @d2_1_a - @d2_1_a_tuple = [@d2_1_a.name, @d2_1_a.version, @d2_1_a.original_platform] - - gems = File.join @indexerdir, "gems" - - FileUtils.mv @d2_1.cache_file, gems - FileUtils.mv @d2_1_a.cache_file, gems - - with_system_gems do - use_ui @ui do - @indexer.update_index - end - - assert_indexed marshal_quickdir, "#{File.basename(@d2_1.spec_file)}.rz" - - specs_index = Marshal.load Gem.read_binary(@indexer.dest_specs_index) - - assert_includes specs_index, @d2_1_tuple - refute_includes specs_index, @d2_1_a_tuple - - latest_specs_index = Marshal.load \ - Gem.read_binary(@indexer.dest_latest_specs_index) - - assert_includes latest_specs_index, @d2_1_tuple - assert_includes latest_specs_index, - [@d2_0.name, @d2_0.version, @d2_0.original_platform] - refute_includes latest_specs_index, @d2_1_a_tuple - - pre_specs_index = Marshal.load \ - Gem.read_binary(@indexer.dest_prerelease_specs_index) - - assert_includes pre_specs_index, @d2_1_a_tuple - refute_includes pre_specs_index, @d2_1_tuple - - refute_directory_exists @indexer.directory - end - end - - def assert_indexed(dir, name) - file = File.join dir, name - assert File.exist?(file), "#{file} does not exist" - end - - def refute_indexed(dir, name) - file = File.join dir, name - refute File.exist?(file), "#{file} exists" - end -end diff --git a/test/rubygems/test_gem_install_update_options.rb b/test/rubygems/test_gem_install_update_options.rb index e2225a1eba..8fd5d9c543 100644 --- a/test/rubygems/test_gem_install_update_options.rb +++ b/test/rubygems/test_gem_install_update_options.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "installer_test_case" require "rubygems/install_update_options" require "rubygems/command" @@ -129,6 +130,9 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase end def test_user_install_disabled_read_only + pend "skipped on MS Windows (chmod has no effect)" if Gem.win_platform? + pend "skipped in root privilege" if Process.uid.zero? + @spec = quick_gem "a" do |spec| util_make_exec spec end @@ -136,26 +140,20 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase util_build_gem @spec @gem = @spec.cache_file - if win_platform? - pend("test_user_install_disabled_read_only test skipped on MS Windows") - elsif Process.uid.zero? - pend("test_user_install_disabled_read_only test skipped in root privilege") - else - @cmd.handle_options %w[--no-user-install] + @cmd.handle_options %w[--no-user-install] - refute @cmd.options[:user_install] + refute @cmd.options[:user_install] - FileUtils.chmod 0755, @userhome - FileUtils.chmod 0000, @gemhome + FileUtils.chmod 0o755, @userhome + FileUtils.chmod 0o000, @gemhome - Gem.use_paths @gemhome, @userhome + Gem.use_paths @gemhome, @userhome - assert_raise(Gem::FilePermissionError) do - Gem::Installer.at(@gem, @cmd.options).install - end + assert_raise(Gem::FilePermissionError) do + Gem::Installer.at(@gem, @cmd.options).install end ensure - FileUtils.chmod 0755, @gemhome + FileUtils.chmod 0o755, @gemhome end def test_vendor diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb index 0d0746ec84..61609a26c9 100644 --- a/test/rubygems/test_gem_installer.rb +++ b/test/rubygems/test_gem_installer.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "installer_test_case" class TestGemInstaller < Gem::InstallerTestCase @@ -83,7 +84,7 @@ end assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r{generated by RubyGems}, wrapper + assert_match(/generated by RubyGems/, wrapper) end def test_check_executable_overwrite_default_bin_dir @@ -99,8 +100,8 @@ end end conflicted = File.join @gemhome, "bin", "executable" - assert_match %r{\A"executable" from a conflicts with (?:#{Regexp.quote(conflicted)}|installed executable from conflict)\z}, - e.message + assert_match(/\A"executable" from a conflicts with (?:#{Regexp.quote(conflicted)}|installed executable from conflict)\z/, + e.message) end end end @@ -141,7 +142,7 @@ gem 'other', version assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r{generated by RubyGems}, wrapper + assert_match(/generated by RubyGems/, wrapper) ensure Gem::Installer.exec_format = nil end @@ -176,7 +177,7 @@ gem 'other', version assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r{generated by RubyGems}, wrapper + assert_match(/generated by RubyGems/, wrapper) end def test_check_executable_overwrite_other_non_gem @@ -191,7 +192,7 @@ gem 'other', version assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r{generated by RubyGems}, wrapper + assert_match(/generated by RubyGems/, wrapper) end unless Gem.win_platform? def test_check_that_user_bin_dir_is_in_path @@ -203,8 +204,8 @@ gem 'other', version bin_dir = bin_dir.downcase end - orig_PATH, ENV["PATH"] = - ENV["PATH"], [ENV["PATH"], bin_dir].join(File::PATH_SEPARATOR) + orig_path = ENV["PATH"] + ENV["PATH"] = [ENV["PATH"], bin_dir].join(File::PATH_SEPARATOR) use_ui @ui do installer.check_that_user_bin_dir_is_in_path @@ -212,9 +213,9 @@ gem 'other', version assert_empty @ui.error - return unless win_platform? + return unless Gem.win_platform? - ENV["PATH"] = [orig_PATH, bin_dir.tr(File::SEPARATOR, File::ALT_SEPARATOR)].join(File::PATH_SEPARATOR) + ENV["PATH"] = [orig_path, bin_dir.tr(File::SEPARATOR, File::ALT_SEPARATOR)].join(File::PATH_SEPARATOR) use_ui @ui do installer.check_that_user_bin_dir_is_in_path @@ -222,14 +223,14 @@ gem 'other', version assert_empty @ui.error ensure - ENV["PATH"] = orig_PATH + ENV["PATH"] = orig_path end def test_check_that_user_bin_dir_is_in_path_tilde - pend "Tilde is PATH is not supported under MS Windows" if win_platform? + pend "Tilde is PATH is not supported under MS Windows" if Gem.win_platform? - orig_PATH, ENV["PATH"] = - ENV["PATH"], [ENV["PATH"], "~/bin"].join(File::PATH_SEPARATOR) + orig_path = ENV["PATH"] + ENV["PATH"] = [ENV["PATH"], "~/bin"].join(File::PATH_SEPARATOR) installer = setup_base_installer installer.bin_dir.replace File.join @userhome, "bin" @@ -240,7 +241,7 @@ gem 'other', version assert_empty @ui.error ensure - ENV["PATH"] = orig_PATH unless win_platform? + ENV["PATH"] = orig_path unless Gem.win_platform? end def test_check_that_user_bin_dir_is_in_path_not_in_path @@ -286,7 +287,7 @@ gem 'other', version installer.ensure_loadable_spec end - assert_equal "The specification for #{a.full_name} is corrupt " + + assert_equal "The specification for #{a.full_name} is corrupt " \ "(SyntaxError)", e.message end @@ -298,7 +299,7 @@ gem 'other', version end policy = Gem::Security::HighSecurity - installer = Gem::Installer.at a_gem, :security_policy => policy + installer = Gem::Installer.at a_gem, security_policy: policy assert_raise Gem::Security::Exception do installer.ensure_loadable_spec @@ -334,22 +335,25 @@ gem 'other', version assert_directory_exists util_inst_bindir installed_exec = File.join(util_inst_bindir, "executable") assert_path_exist installed_exec - assert_equal mask, File.stat(installed_exec).mode unless win_platform? + assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? wrapper = File.read installed_exec - assert_match %r{generated by RubyGems}, wrapper + assert_match(/generated by RubyGems/, wrapper) end def test_generate_bin_bindir_with_user_install_warning - bin_dir = Gem.win_platform? ? File.expand_path(ENV["WINDIR"]).upcase : - "/usr/bin" + bin_dir = if Gem.win_platform? + File.expand_path(ENV["WINDIR"]).upcase + else + "/usr/bin" + end old_path = ENV["PATH"] ENV["PATH"] = [ENV["PATH"], bin_dir].compact.join(File::PATH_SEPARATOR) options = { - :bin_dir => bin_dir, - :install_dir => "/non/existent", + bin_dir: bin_dir, + install_dir: "/non/existent", } inst = Gem::Installer.at "", options @@ -361,7 +365,6 @@ gem 'other', version end assert_equal "", @ui.error - ensure ENV["PATH"] = old_path end @@ -377,10 +380,10 @@ gem 'other', version assert_directory_exists util_inst_bindir installed_exec = File.join util_inst_bindir, "executable" assert_path_exist installed_exec - assert_equal mask, File.stat(installed_exec).mode unless win_platform? + assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? wrapper = File.read installed_exec - assert_match %r{generated by RubyGems}, wrapper + assert_match(/generated by RubyGems/, wrapper) end def test_generate_bin_script_format @@ -436,10 +439,10 @@ gem 'other', version installed_exec = File.join("#{@gemhome}2", "bin", "executable") assert_path_exist installed_exec - assert_equal mask, File.stat(installed_exec).mode unless win_platform? + assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? wrapper = File.read installed_exec - assert_match %r{generated by RubyGems}, wrapper + assert_match(/generated by RubyGems/, wrapper) end def test_generate_bin_script_no_execs @@ -461,19 +464,19 @@ gem 'other', version Dir.mkdir util_inst_bindir - if win_platform? + if Gem.win_platform? pend("test_generate_bin_script_no_perms skipped on MS Windows") elsif Process.uid.zero? pend("test_generate_bin_script_no_perms skipped in root privilege") else - FileUtils.chmod 0000, util_inst_bindir + FileUtils.chmod 0o000, util_inst_bindir assert_raise Gem::FilePermissionError do installer.generate_bin end end ensure - FileUtils.chmod 0755, util_inst_bindir unless ($DEBUG || win_platform?) + FileUtils.chmod 0o755, util_inst_bindir unless $DEBUG || Gem.win_platform? end def test_generate_bin_script_no_shebang @@ -493,12 +496,12 @@ gem 'other', version installed_exec = File.join @gemhome, "bin", "executable" assert_path_exist installed_exec - assert_equal mask, File.stat(installed_exec).mode unless win_platform? + assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? wrapper = File.read installed_exec - assert_match %r{generated by RubyGems}, wrapper - # HACK some gems don't have #! in their executables, restore 2008/06 - #assert_no_match %r|generated by RubyGems|, wrapper + assert_match(/generated by RubyGems/, wrapper) + # HACK: some gems don't have #! in their executables, restore 2008/06 + # assert_no_match %r|generated by RubyGems|, wrapper end def test_generate_bin_script_wrappers @@ -520,12 +523,12 @@ gem 'other', version installer.generate_bin assert_directory_exists util_inst_bindir assert_path_exist installed_exec - assert_equal mask, File.stat(installed_exec).mode unless win_platform? + assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform? - assert_match %r{generated by RubyGems}, File.read(installed_exec) + assert_match(/generated by RubyGems/, File.read(installed_exec)) - refute_match %r{generated by RubyGems}, File.read(real_exec), - "real executable overwritten" + refute_match(/generated by RubyGems/, File.read(real_exec), + "real executable overwritten") end def test_generate_bin_symlink @@ -565,19 +568,19 @@ gem 'other', version Dir.mkdir util_inst_bindir - if win_platform? + if Gem.win_platform? pend("test_generate_bin_symlink_no_perms skipped on MS Windows") elsif Process.uid.zero? pend("test_user_install_disabled_read_only test skipped in root privilege") else - FileUtils.chmod 0000, util_inst_bindir + FileUtils.chmod 0o000, util_inst_bindir assert_raise Gem::FilePermissionError do installer.generate_bin end end ensure - FileUtils.chmod 0755, util_inst_bindir unless ($DEBUG || win_platform?) + FileUtils.chmod 0o755, util_inst_bindir unless $DEBUG || Gem.win_platform? end def test_generate_bin_symlink_update_newer @@ -735,9 +738,9 @@ gem 'other', version installer.generate_bin default_shebang = Gem.ruby - shebang_line = File.open("#{@gemhome}/bin/executable") {|f| f.readlines.first } + shebang_line = File.open("#{@gemhome}/bin/executable", &:gets) assert_match(/\A#!/, shebang_line) - assert_match(/#{default_shebang}/, shebang_line) + assert_include(shebang_line, default_shebang) end end @@ -746,8 +749,8 @@ gem 'other', version installer = Gem::Installer.at( gem_with_dangling_symlink, - :user_install => false, - :force => true + user_install: false, + force: true ) build_rake_in do @@ -766,7 +769,7 @@ gem 'other', version def test_generate_plugins installer = util_setup_installer do |spec| write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| - io.write "puts __FILE__" + io.write "# do nothing" end spec.files += %w[lib/rubygems_plugin.rb] @@ -815,10 +818,10 @@ gem 'other', version util_build_gem spec - File.chmod(0555, Gem.plugindir) + File.chmod(0o555, Gem.plugindir) system_path = File.join(Gem.plugindir, "a_plugin.rb") user_path = File.join(Gem.plugindir(Gem.user_dir), "a_plugin.rb") - installer = util_installer spec, Gem.dir, :user + installer = Gem::Installer.at spec.cache_file, user_install: true, force: true assert_equal spec, installer.install @@ -837,13 +840,13 @@ gem 'other', version util_build_gem spec - File.chmod(0555, Gem.plugindir) + File.chmod(0o555, Gem.plugindir) system_path = File.join(Gem.plugindir, "a_plugin.rb") build_root = File.join(@tempdir, "build_root") build_root_path = File.join(build_root, Gem.plugindir.gsub(/^[a-zA-Z]:/, ""), "a_plugin.rb") - installer = Gem::Installer.at spec.cache_file, :build_root => build_root + installer = Gem::Installer.at spec.cache_file, build_root: build_root assert_equal spec, installer.install @@ -853,11 +856,59 @@ gem 'other', version refute_includes File.read(build_root_path), build_root end + class << self + attr_accessor :plugin_loaded + attr_accessor :post_install_is_called + end + + def test_use_plugin_immediately + self.class.plugin_loaded = false + self.class.post_install_is_called = false + spec_version = nil + plugin_path = nil + installer = util_setup_installer do |spec| + spec_version = spec.version + plugin_path = File.join("lib", "rubygems_plugin.rb") + write_file File.join(@tempdir, plugin_path) do |io| + io.write <<-PLUGIN +#{self.class}.plugin_loaded = true +Gem.post_install do + #{self.class}.post_install_is_called = true +end + PLUGIN + end + spec.files += [plugin_path] + plugin_path = File.join(spec.gem_dir, plugin_path) + end + build_rake_in do + installer.install + end + assert self.class.plugin_loaded, "plugin is not loaded" + assert self.class.post_install_is_called, + "post install hook registered by plugin is not called" + + self.class.plugin_loaded = false + $LOADED_FEATURES.delete(plugin_path) + installer_new = util_setup_installer do |spec_new| + spec_new.version = spec_version.version.succ + plugin_path = File.join("lib", "rubygems_plugin.rb") + write_file File.join(@tempdir, plugin_path) do |io| + io.write "#{self.class}.plugin_loaded = true" + end + spec_new.files += [plugin_path] + end + build_rake_in do + installer_new.install + end + assert !self.class.plugin_loaded, + "plugin is loaded even when old version is already loaded" + end + def test_keeps_plugins_up_to_date # NOTE: version a-2 is already installed by setup hooks write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| - io.write "puts __FILE__" + io.write "# do nothing" end build_rake_in do @@ -902,7 +953,7 @@ gem 'other', version path = Gem::Package.build @spec - installer = Gem::Installer.at path, :install_dir => "#{@gemhome}3" + installer = Gem::Installer.at path, install_dir: "#{@gemhome}3" assert_equal @spec, installer.install end @@ -926,7 +977,7 @@ gem 'other', version def test_initialize_user_install @gem = setup_base_gem - installer = Gem::Installer.at @gem, :user_install => true + installer = Gem::Installer.at @gem, user_install: true assert_equal File.join(Gem.user_dir, "gems", @spec.full_name), installer.gem_dir @@ -937,13 +988,26 @@ gem 'other', version @gem = setup_base_gem installer = - Gem::Installer.at @gem, :user_install => true, :bin_dir => @tempdir + Gem::Installer.at @gem, user_install: true, bin_dir: @tempdir assert_equal File.join(Gem.user_dir, "gems", @spec.full_name), installer.gem_dir assert_equal @tempdir, installer.bin_dir end + def test_install_dir_takes_precedence_to_user_install + gemhome2 = "#{@gemhome}2" + + @gem = setup_base_gem + + installer = + Gem::Installer.at @gem, install_dir: gemhome2, user_install: true + installer.install + + assert_path_exist File.join(gemhome2, "gems", @spec.full_name) + assert_path_not_exist File.join(Gem.user_dir, "gems", @spec.full_name) + end + def test_install installer = util_setup_installer @@ -983,8 +1047,8 @@ gem 'other', version exe = File.join gemdir, "bin", "executable" assert_path_exist exe - exe_mode = File.stat(exe).mode & 0111 - assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform? + exe_mode = File.stat(exe).mode & 0o111 + assert_equal 0o111, exe_mode, format("0%o", exe_mode) unless Gem.win_platform? assert_path_exist File.join gemdir, "lib", "code.rb" @@ -1025,7 +1089,7 @@ gem 'other', version @gem = setup_base_gem # build old version that has a bin file - installer = util_setup_gem do |spec| + installer = util_setup_gem do |_spec| File.open File.join("bin", "executable"), "w" do |f| f.puts "require 'code'" end @@ -1186,7 +1250,7 @@ gem 'other', version Gem::Package.build @spec end end - installer = Gem::Installer.at @gem, :force => true + installer = Gem::Installer.at @gem, force: true build_rake_in do use_ui @ui do assert_equal @spec, installer.install @@ -1204,7 +1268,7 @@ gem 'other', version end use_ui @ui do - installer = Gem::Installer.at missing_dep_gem, :force => true + installer = Gem::Installer.at missing_dep_gem, force: true installer.install end @@ -1216,11 +1280,31 @@ gem 'other', version build_root = File.join(@tempdir, "build_root") @gem = setup_base_gem - installer = Gem::Installer.at @gem, :build_root => build_root + installer = Gem::Installer.at @gem, build_root: build_root assert_equal @spec, installer.install end + def test_install_build_root_when_gem_home_not_writable_does_not_fallback_to_user_install_inside_build_root + build_root = File.join(@tempdir, "build_root") + + orig_gem_home = ENV.delete("GEM_HOME") + + @gem = setup_base_gem + + FileUtils.chmod "-w", @gemhome + + installer = Gem::Installer.at @gem, build_root: build_root + + assert_equal @spec, installer.install + + build_root_path = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, "")) + assert File.exist?(build_root_path), "gem not written to build_root" + ensure + FileUtils.chmod "+w", @gemhome + ENV["GEM_HOME"] = orig_gem_home + end + def test_install_missing_dirs installer = setup_base_installer @@ -1335,7 +1419,7 @@ gem 'other', version installer.install end - assert_match %r{I am a shiny gem!}, @ui.output + assert_match(/I am a shiny gem!/, @ui.output) end def test_install_with_skipped_message @@ -1345,11 +1429,11 @@ gem 'other', version use_ui @ui do path = Gem::Package.build @spec - installer = Gem::Installer.at path, :post_install_message => false + installer = Gem::Installer.at path, post_install_message: false installer.install end - refute_match %r{I am a shiny gem!}, @ui.output + refute_match(/I am a shiny gem!/, @ui.output) end def test_install_extension_dir @@ -1369,7 +1453,7 @@ gem 'other', version use_ui @ui do path = Gem::Package.build @spec - installer = Gem::Installer.at path, :install_dir => gemhome2 + installer = Gem::Installer.at path, install_dir: gemhome2 installer.install end @@ -1408,7 +1492,7 @@ gem 'other', version # reinstall the gem, this is also the same as pristine use_ui @ui do - installer = Gem::Installer.at path, :force => true + installer = Gem::Installer.at path, force: true installer.install end @@ -1434,7 +1518,7 @@ gem 'other', version use_ui @ui do path = Gem::Package.build @spec - installer = Gem::Installer.at path, :user_install => true + installer = Gem::Installer.at path, user_install: true installer.install end @@ -1493,7 +1577,7 @@ gem 'other', version def test_install_extension_and_script pend "Makefile creation crashes on jruby" if Gem.java_platform? - pend if RUBY_PLATFORM.include?("mswin") && ENV.key?("GITHUB_ACTIONS") # not working from the beginning + pend "terminates on mswin" if vc_windows? && ruby_repo? @spec = setup_base_spec @spec.extensions << "extconf.rb" @@ -1559,7 +1643,7 @@ gem 'other', version write_file File.join(@tempdir, file) end - so = File.join(@spec.gem_dir, "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}") + so = File.join(@spec.extension_dir, "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}") assert_path_not_exist so use_ui @ui do path = Gem::Package.build @spec @@ -1568,20 +1652,42 @@ gem 'other', version installer.install end assert_path_exist so - rescue - puts "-" * 78 - puts File.read File.join(@gemhome, "gems", "a-2", "Makefile") - puts "-" * 78 + end + end - path = File.join(@gemhome, "gems", "a-2", "gem_make.out") + def test_install_extension_clean_intermediate_files + pend "extensions don't quite work on jruby" if Gem.java_platform? + @spec = setup_base_spec + @spec.require_paths = ["."] + @spec.extensions << "extconf.rb" - if File.exist?(path) - puts File.read(path) - puts "-" * 78 - end + File.write File.join(@tempdir, "extconf.rb"), <<-RUBY + require "mkmf" + CONFIG['CC'] = '$(TOUCH) $@ ||' + CONFIG['LDSHARED'] = '$(TOUCH) $@ ||' + $ruby = '#{Gem.ruby}' + create_makefile("#{@spec.name}") + RUBY + + # empty depend file for no auto dependencies + @spec.files += %W[depend #{@spec.name}.c].each do |file| + write_file File.join(@tempdir, file) + end + + shared_object = "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}" + extension_file = File.join @spec.extension_dir, shared_object + intermediate_file = File.join @spec.gem_dir, shared_object + + assert_path_not_exist extension_file, "no before installing" + use_ui @ui do + path = Gem::Package.build @spec - raise + installer = Gem::Installer.at path + installer.install end + + assert_path_exist extension_file, "installed" + assert_path_not_exist intermediate_file end def test_installation_satisfies_dependency_eh @@ -1651,7 +1757,7 @@ gem 'other', version # that it work everything out on it's own. Gem::Specification.reset - installer = Gem::Installer.at gem, :install_dir => gemhome2 + installer = Gem::Installer.at gem, install_dir: gemhome2 build_rake_in do use_ui @ui do @@ -1665,6 +1771,7 @@ gem 'other', version def spec.full_name # so the spec is buildable "malicious-1" end + def spec.validate(packaging, strict); end util_build_gem spec @@ -1685,6 +1792,7 @@ gem 'other', version def spec.full_name # so the spec is buildable "malicious-1" end + def spec.validate(*args); end util_build_gem spec @@ -1706,6 +1814,7 @@ gem 'other', version def spec.full_name # so the spec is buildable "malicious-1" end + def spec.validate(*args); end spec.require_paths = ["malicious\n``"] @@ -1729,6 +1838,7 @@ gem 'other', version def spec.full_name # so the spec is buildable "malicious-1" end + def spec.validate(*args); end spec.extensions = ["malicious\n``"] @@ -1750,6 +1860,7 @@ gem 'other', version def spec.full_name # so the spec is buildable "malicious-1" end + def spec.validate(*args); end spec.specification_version = "malicious\n``" @@ -1771,6 +1882,7 @@ gem 'other', version def spec.full_name # so the spec is buildable "malicious-1" end + def spec.validate(*args); end spec.add_dependency "b\nfoo", "> 5" @@ -1793,9 +1905,9 @@ gem 'other', version installer = Gem::Installer.at( gem_with_ill_formated_platform, - :install_dir => @gem_home, - :user_install => false, - :force => true + install_dir: @gemhome, + user_install: false, + force: true ) use_ui @ui do @@ -1835,7 +1947,7 @@ gem 'other', version plugins_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ""), "plugins") @gem = setup_base_gem - installer = use_ui(@ui) { Gem::Installer.at @gem, :build_root => build_root } + installer = use_ui(@ui) { Gem::Installer.at @gem, build_root: build_root } assert_equal build_root, installer.build_root assert_equal bin_dir, installer.bin_dir @@ -1850,6 +1962,48 @@ gem 'other', version assert_equal " Plugins dir: #{plugins_dir}", errors.shift end + def test_process_options_fallback_to_user_install_when_gem_home_not_writable + if Process.uid.zero? + pend("skipped in root privilege") + return + end + + orig_gem_home = ENV.delete("GEM_HOME") + + @gem = setup_base_gem + + FileUtils.chmod 0o000, @gemhome + + installer = use_ui(@ui) { Gem::Installer.at @gem } + + assert_equal Gem.user_dir, installer.gem_home + assert_equal "Defaulting to user installation because default installation directory (#{@gemhome}) is not writable.", @ui.output.strip + ensure + FileUtils.chmod 0o755, @gemhome + ENV["GEM_HOME"] = orig_gem_home + end + + def test_process_options_does_not_fallback_to_user_install_when_gem_home_not_writable_and_no_user_install + if Process.uid.zero? + pend("skipped in root privilege") + return + end + + orig_gem_home = ENV.delete("GEM_HOME") + + @gem = setup_base_gem + + FileUtils.chmod 0o000, @gemhome + + installer = use_ui(@ui) { Gem::Installer.at @gem, user_install: false } + + assert_equal @gemhome, installer.gem_home + assert_empty @ui.output.strip + ensure + FileUtils.chmod 0o755, @gemhome + ENV["GEM_HOME"] = orig_gem_home + end + def test_shebang_arguments load_relative "no" do installer = setup_base_installer @@ -1937,7 +2091,7 @@ gem 'other', version bin_env = get_bin_env - assert_equal("#!#{bin_env} #{RbConfig::CONFIG['ruby_install_name']}", + assert_equal("#!#{bin_env} #{RbConfig::CONFIG["ruby_install_name"]}", shebang) end @@ -2074,7 +2228,7 @@ gem 'other', version end def get_bin_env - if win_platform? + if Gem.win_platform? "" else %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } @@ -2156,7 +2310,7 @@ gem 'other', version def test_write_build_info_file_install_dir @gem = setup_base_gem - installer = Gem::Installer.at @gem, :install_dir => "#{@gemhome}2" + installer = Gem::Installer.at @gem, install_dir: "#{@gemhome}2" installer.build_args = %w[ --with-libyaml-dir /usr/local/Cellar/libyaml/0.1.4 @@ -2222,6 +2376,37 @@ gem 'other', version assert_equal @spec, eval(File.read(@spec.spec_file)) end + def test_leaves_no_empty_cached_spec_when_no_more_disk_space + @spec = setup_base_spec + FileUtils.rm @spec.spec_file + assert_path_not_exist @spec.spec_file + + @spec.files = %w[a.rb b.rb c.rb] + + installer = Gem::Installer.for_spec @spec + installer.gem_home = @gemhome + + File.class_eval do + alias_method :original_write, :write + + def write(data) + raise Errno::ENOSPC + end + end + + assert_raise Errno::ENOSPC do + installer.write_spec + end + + assert_path_not_exist @spec.spec_file + ensure + File.class_eval do + remove_method :write + alias_method :write, :original_write + remove_method :original_write + end + end + def test_dir installer = setup_base_installer @@ -2230,7 +2415,7 @@ gem 'other', version def test_default_gem_loaded_from spec = util_spec "a" - installer = Gem::Installer.for_spec spec, :install_as_default => true + installer = Gem::Installer.for_spec spec, install_as_default: true installer.install assert_predicate spec, :default_gem? end @@ -2267,10 +2452,10 @@ gem 'other', version wrapper = File.read installed_exec if symlink_supported? - refute_match %r{generated by RubyGems}, wrapper + refute_match(/generated by RubyGems/, wrapper) else # when symlink not supported, it warns and fallbacks back to installing wrapper - assert_match %r{Unable to use symlinks, installing wrapper}, @ui.error - assert_match %r{generated by RubyGems}, wrapper + assert_match(/Unable to use symlinks, installing wrapper/, @ui.error) + assert_match(/generated by RubyGems/, wrapper) end end @@ -2291,7 +2476,7 @@ gem 'other', version assert_path_exist installed_exec wrapper = File.read installed_exec - assert_match %r{generated by RubyGems}, wrapper + assert_match(/generated by RubyGems/, wrapper) end def test_default_gem_with_exe_as_bindir @@ -2383,15 +2568,15 @@ gem 'other', version end def mask - 0100755 + 0o100755 end def load_relative(value) - orig_LIBRUBY_RELATIVE = RbConfig::CONFIG["LIBRUBY_RELATIVE"] + orig_libruby_relative = RbConfig::CONFIG["LIBRUBY_RELATIVE"] RbConfig::CONFIG["LIBRUBY_RELATIVE"] = value yield ensure - RbConfig::CONFIG["LIBRUBY_RELATIVE"] = orig_LIBRUBY_RELATIVE + RbConfig::CONFIG["LIBRUBY_RELATIVE"] = orig_libruby_relative end end diff --git a/test/rubygems/test_gem_local_remote_options.rb b/test/rubygems/test_gem_local_remote_options.rb index 0c662a3f50..cea9cde82b 100644 --- a/test/rubygems/test_gem_local_remote_options.rb +++ b/test/rubygems/test_gem_local_remote_options.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/local_remote_options" require "rubygems/command" @@ -33,7 +34,7 @@ class TestGemLocalRemoteOptions < Gem::TestCase def test_clear_sources_option @cmd.add_local_remote_options - s = URI.parse "http://only-gems.example.com/" + s = Gem::URI.parse "http://only-gems.example.com/" @cmd.handle_options %W[--clear-sources --source #{s}] assert_equal [s.to_s], Gem.sources @@ -75,10 +76,10 @@ class TestGemLocalRemoteOptions < Gem::TestCase def test_source_option @cmd.add_source_option - s1 = URI.parse "http://more-gems.example.com/" - s2 = URI.parse "http://even-more-gems.example.com/" - s3 = URI.parse "http://other-gems.example.com/some_subdir" - s4 = URI.parse "http://more-gems.example.com/" # Intentional duplicate + s1 = Gem::URI.parse "http://more-gems.example.com/" + s2 = Gem::URI.parse "http://even-more-gems.example.com/" + s3 = Gem::URI.parse "http://other-gems.example.com/some_subdir" + s4 = Gem::URI.parse "http://more-gems.example.com/" # Intentional duplicate original_sources = Gem.sources.dup @@ -96,7 +97,7 @@ class TestGemLocalRemoteOptions < Gem::TestCase original_sources = Gem.sources.dup - source = URI.parse "http://more-gems.example.com/" + source = Gem::URI.parse "http://more-gems.example.com/" @cmd.handle_options %W[-s #{source}] original_sources << source diff --git a/test/rubygems/test_gem_name_tuple.rb b/test/rubygems/test_gem_name_tuple.rb index 6eca69084c..bdb8181ce8 100644 --- a/test/rubygems/test_gem_name_tuple.rb +++ b/test/rubygems/test_gem_name_tuple.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/name_tuple" @@ -18,14 +19,31 @@ class TestGemNameTuple < Gem::TestCase end def test_platform_normalization - n = Gem::NameTuple.new "a", Gem::Version.new(0), "ruby" - assert_equal "ruby", n.platform - - n = Gem::NameTuple.new "a", Gem::Version.new(0), nil - assert_equal "ruby", n.platform - - n = Gem::NameTuple.new "a", Gem::Version.new(0), "" - assert_equal "ruby", n.platform + a = Gem::NameTuple.new "a", Gem::Version.new(0), "ruby" + b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform::RUBY + assert_equal a, b + assert_equal a.hash, b.hash + + a = Gem::NameTuple.new "a", Gem::Version.new(0), nil + b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform.new("ruby") + assert_equal a, b + assert_equal a.hash, b.hash + + a = Gem::NameTuple.new "a", Gem::Version.new(0), "" + b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform.new("ruby") + assert_equal a, b + assert_equal a.hash, b.hash + + a = Gem::NameTuple.new "a", Gem::Version.new(0), "universal-darwin-23" + b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform.new("universal-darwin-23") + assert_equal a, b + assert_equal a.hash, b.hash + + # Gem::Platform does normalization so that these are equal (note the missing dash before 21) + a = Gem::NameTuple.new "a", Gem::Version.new(0), "universal-darwin-21" + b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform.new("universal-darwin21") + assert_equal a, b + assert_equal a.hash, b.hash end def test_spec_name diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index 9295f42dba..2065864107 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -189,7 +189,7 @@ class TestGemPackage < Gem::Package::TarTestCase File.symlink("code.rb", "lib/code_sym.rb") File.symlink("../lib/code.rb", "lib/code_sym2.rb") rescue Errno::EACCES => e - if win_platform? + if Gem.win_platform? pend "symlink - must be admin with no UAC on Windows" else raise e @@ -205,7 +205,8 @@ class TestGemPackage < Gem::Package::TarTestCase tar.rewind - files, symlinks = [], [] + files = [] + symlinks = [] Gem::Package::TarReader.new tar do |tar_io| tar_io.each_entry do |entry| @@ -286,8 +287,8 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal [PUBLIC_CERT.to_pem], reader.spec.cert_chain - assert_equal %w[metadata.gz metadata.gz.sig - data.tar.gz data.tar.gz.sig + assert_equal %w[metadata.gz metadata.gz.sig + data.tar.gz data.tar.gz.sig checksums.yaml.gz checksums.yaml.gz.sig], reader.files @@ -329,8 +330,8 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal [PUBLIC_CERT.to_pem], reader.spec.cert_chain - assert_equal %w[metadata.gz metadata.gz.sig - data.tar.gz data.tar.gz.sig + assert_equal %w[metadata.gz metadata.gz.sig + data.tar.gz data.tar.gz.sig checksums.yaml.gz checksums.yaml.gz.sig], reader.files @@ -392,8 +393,8 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal spec, reader.spec - assert_equal %w[metadata.gz metadata.gz.sig - data.tar.gz data.tar.gz.sig + assert_equal %w[metadata.gz metadata.gz.sig + data.tar.gz data.tar.gz.sig checksums.yaml.gz checksums.yaml.gz.sig], reader.files @@ -429,8 +430,8 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal spec, reader.spec - assert_equal %w[metadata.gz metadata.gz.sig - data.tar.gz data.tar.gz.sig + assert_equal %w[metadata.gz metadata.gz.sig + data.tar.gz data.tar.gz.sig checksums.yaml.gz checksums.yaml.gz.sig], reader.files @@ -441,11 +442,11 @@ class TestGemPackage < Gem::Package::TarTestCase data_tgz = util_tar_gz {} gem = util_tar do |tar| - tar.add_file "data.tar.gz", 0644 do |io| + tar.add_file "data.tar.gz", 0o644 do |io| io.write data_tgz.string end - tar.add_file "metadata.gz", 0644 do |io| + tar.add_file "metadata.gz", 0o644 do |io| Zlib::GzipWriter.wrap io do |gzio| gzio.write @spec.to_yaml end @@ -478,21 +479,21 @@ class TestGemPackage < Gem::Package::TarTestCase extracted = File.join @destination, "lib/code.rb" assert_path_exist extracted - mask = 0100666 & (~File.umask) + mask = 0o100666 & (~File.umask) assert_equal mask.to_s(8), File.stat(extracted).mode.to_s(8) unless - win_platform? + Gem.win_platform? end def test_extract_files_empty data_tgz = util_tar_gz {} gem = util_tar do |tar| - tar.add_file "data.tar.gz", 0644 do |io| + tar.add_file "data.tar.gz", 0o644 do |io| io.write data_tgz.string end - tar.add_file "metadata.gz", 0644 do |io| + tar.add_file "metadata.gz", 0o644 do |io| Zlib::GzipWriter.wrap io do |gzio| gzio.write @spec.to_yaml end @@ -510,11 +511,26 @@ class TestGemPackage < Gem::Package::TarTestCase assert_path_exist @destination end + def test_extract_file_permissions + pend "chmod not supported" if Gem.win_platform? + + gem_with_long_permissions = File.expand_path("packages/Bluebie-legs-0.6.2.gem", __dir__) + + package = Gem::Package.new gem_with_long_permissions + + package.extract_files @destination + + filepath = File.join @destination, "README.rdoc" + assert_path_exist filepath + + assert_equal 0o104444, File.stat(filepath).mode + end + def test_extract_tar_gz_absolute package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.add_file "/absolute.rb", 0644 do |io| + tar.add_file "/absolute.rb", 0o644 do |io| io.write "hi" end end @@ -523,7 +539,7 @@ class TestGemPackage < Gem::Package::TarTestCase package.extract_tar_gz tgz_io, @destination end - assert_equal("installing into parent path /absolute.rb of " + + assert_equal("installing into parent path /absolute.rb of " \ "#{@destination} is not allowed", e.message) end @@ -532,18 +548,18 @@ class TestGemPackage < Gem::Package::TarTestCase package.verify tgz_io = util_tar_gz do |tar| - tar.add_file "relative.rb", 0644 do |io| + tar.add_file "relative.rb", 0o644 do |io| io.write "hi" end - tar.mkdir "lib", 0755 - tar.add_symlink "lib/foo.rb", "../relative.rb", 0644 + tar.mkdir "lib", 0o755 + tar.add_symlink "lib/foo.rb", "../relative.rb", 0o644 end begin package.extract_tar_gz tgz_io, @destination rescue Errno::EACCES => e - if win_platform? + if Gem.win_platform? pend "symlink - must be admin with no UAC on Windows" else raise e @@ -558,13 +574,39 @@ class TestGemPackage < Gem::Package::TarTestCase File.read(extracted) end + def test_extract_symlink_into_symlink_dir + package = Gem::Package.new @gem + tgz_io = util_tar_gz do |tar| + tar.mkdir "lib", 0o755 + tar.add_symlink "lib/link", "./inside.rb", 0o644 + tar.add_file "lib/inside.rb", 0o644 do |io| + io.write "hi" + end + end + + destination_subdir = File.join @destination, "subdir" + FileUtils.mkdir_p destination_subdir + + destination_linkdir = File.join @destination, "linkdir" + File.symlink(destination_subdir, destination_linkdir) + + package.extract_tar_gz tgz_io, destination_linkdir + + extracted = File.join destination_subdir, "lib/link" + assert_path_exist extracted + assert_equal "./inside.rb", + File.readlink(extracted) + assert_equal "hi", + File.read(extracted) + end + def test_extract_tar_gz_symlink_broken_relative_path package = Gem::Package.new @gem package.verify tgz_io = util_tar_gz do |tar| - tar.mkdir "lib", 0755 - tar.add_symlink "lib/foo.rb", "../broken.rb", 0644 + tar.mkdir "lib", 0o755 + tar.add_symlink "lib/foo.rb", "../broken.rb", 0o644 end ui = Gem::MockGemUi.new @@ -583,9 +625,9 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.mkdir "lib", 0755 - tar.add_symlink "lib/link", "../..", 0644 - tar.add_file "lib/link/outside.txt", 0644 do |io| + tar.mkdir "lib", 0o755 + tar.add_symlink "lib/link", "../..", 0o644 + tar.add_file "lib/link/outside.txt", 0o644 do |io| io.write "hi" end end @@ -596,7 +638,7 @@ class TestGemPackage < Gem::Package::TarTestCase destination_subdir = File.join @destination, "subdir" FileUtils.mkdir_p destination_subdir - expected_exceptions = win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] + expected_exceptions = Gem.win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] e = assert_raise(*expected_exceptions) do package.extract_tar_gz tgz_io, destination_subdir @@ -604,7 +646,7 @@ class TestGemPackage < Gem::Package::TarTestCase pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e - assert_equal("installing symlink 'lib/link' pointing to parent path #{@destination} of " + + assert_equal("installing symlink 'lib/link' pointing to parent path #{@destination} of " \ "#{destination_subdir} is not allowed", e.message) assert_path_not_exist File.join(@destination, "outside.txt") @@ -627,11 +669,11 @@ class TestGemPackage < Gem::Package::TarTestCase pend "TMPDIR seems too long to add it as symlink into tar" if destination_user_dir.size > 90 tgz_io = util_tar_gz do |tar| - tar.add_symlink "link", destination_user_dir, 16877 - tar.add_symlink "link/dir", ".", 16877 + tar.add_symlink "link", destination_user_dir, 16_877 + tar.add_symlink "link/dir", ".", 16_877 end - expected_exceptions = win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] + expected_exceptions = Gem.win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] e = assert_raise(*expected_exceptions) do package.extract_tar_gz tgz_io, destination_subdir @@ -639,7 +681,7 @@ class TestGemPackage < Gem::Package::TarTestCase pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e - assert_equal("installing symlink 'link' pointing to parent path #{destination_user_dir} of " + + assert_equal("installing symlink 'link' pointing to parent path #{destination_user_dir} of " \ "#{destination_subdir} is not allowed", e.message) assert_path_exist destination_user_subdir @@ -651,11 +693,11 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.mkdir "lib", 0755 - tar.add_file "lib/foo.rb", 0644 do |io| + tar.mkdir "lib", 0o755 + tar.add_file "lib/foo.rb", 0o644 do |io| io.write "hi" end - tar.mkdir "lib/foo", 0755 + tar.mkdir "lib/foo", 0o755 end package.extract_tar_gz tgz_io, @destination @@ -671,7 +713,7 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.add_file "./dot_slash.rb", 0644 do |io| + tar.add_file "./dot_slash.rb", 0o644 do |io| io.write "hi" end end @@ -686,7 +728,7 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.add_file ".dot_file.rb", 0644 do |io| + tar.add_file ".dot_file.rb", 0o644 do |io| io.write "hi" end end @@ -702,7 +744,7 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.add_file "foo/file.rb", 0644 do |io| + tar.add_file "foo/file.rb", 0o644 do |io| io.write "hi" end end @@ -718,12 +760,10 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem file = "file.rb".dup - file.taint if RUBY_VERSION < "2.7" destination = package.install_location file, @destination assert_equal File.join(@destination, "file.rb"), destination - refute destination.tainted? if RUBY_VERSION < "2.7" end def test_install_location_absolute @@ -733,7 +773,7 @@ class TestGemPackage < Gem::Package::TarTestCase package.install_location "/absolute.rb", @destination end - assert_equal("installing into parent path /absolute.rb of " + + assert_equal("installing into parent path /absolute.rb of " \ "#{@destination} is not allowed", e.message) end @@ -757,12 +797,10 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem file = "foo//file.rb".dup - file.taint if RUBY_VERSION < "2.7" destination = package.install_location file, @destination assert_equal File.join(@destination, "foo", "file.rb"), destination - refute destination.tainted? if RUBY_VERSION < "2.7" end def test_install_location_relative @@ -774,7 +812,7 @@ class TestGemPackage < Gem::Package::TarTestCase parent = File.expand_path File.join @destination, "../relative.rb" - assert_equal("installing into parent path #{parent} of " + + assert_equal("installing into parent path #{parent} of " \ "#{@destination} is not allowed", e.message) end @@ -789,13 +827,15 @@ class TestGemPackage < Gem::Package::TarTestCase parent = File.expand_path File.join @destination, filename - assert_equal("installing into parent path #{parent} of " + + assert_equal("installing into parent path #{parent} of " \ "#{@destination} is not allowed", e.message) end def test_load_spec entry = StringIO.new Gem::Util.gzip @spec.to_yaml - def entry.full_name() "metadata.gz" end + def entry.full_name + "metadata.gz" + end package = Gem::Package.new "nonexistent.gem" @@ -816,7 +856,7 @@ class TestGemPackage < Gem::Package::TarTestCase def test_verify_checksum_bad data_tgz = util_tar_gz do |tar| - tar.add_file "lib/code.rb", 0444 do |io| + tar.add_file "lib/code.rb", 0o444 do |io| io.write "# lib/code.rb" end end @@ -826,11 +866,11 @@ class TestGemPackage < Gem::Package::TarTestCase gem = util_tar do |tar| metadata_gz = Gem::Util.gzip @spec.to_yaml - tar.add_file "metadata.gz", 0444 do |io| + tar.add_file "metadata.gz", 0o444 do |io| io.write metadata_gz end - tar.add_file "data.tar.gz", 0444 do |io| + tar.add_file "data.tar.gz", 0o444 do |io| io.write data_tgz end @@ -840,7 +880,7 @@ class TestGemPackage < Gem::Package::TarTestCase "metadata.gz" => "bogus", }, } - tar.add_file "checksums.yaml.gz", 0444 do |io| + tar.add_file "checksums.yaml.gz", 0o444 do |io| Zlib::GzipWriter.wrap io do |gz_io| gz_io.write Psych.dump bogus_checksums end @@ -863,7 +903,7 @@ class TestGemPackage < Gem::Package::TarTestCase def test_verify_checksum_missing data_tgz = util_tar_gz do |tar| - tar.add_file "lib/code.rb", 0444 do |io| + tar.add_file "lib/code.rb", 0o444 do |io| io.write "# lib/code.rb" end end @@ -873,7 +913,7 @@ class TestGemPackage < Gem::Package::TarTestCase gem = util_tar do |tar| metadata_gz = Gem::Util.gzip @spec.to_yaml - tar.add_file "metadata.gz", 0444 do |io| + tar.add_file "metadata.gz", 0o444 do |io| io.write metadata_gz end @@ -886,13 +926,13 @@ class TestGemPackage < Gem::Package::TarTestCase }, } - tar.add_file "checksums.yaml.gz", 0444 do |io| + tar.add_file "checksums.yaml.gz", 0o444 do |io| Zlib::GzipWriter.wrap io do |gz_io| gz_io.write Psych.dump checksums end end - tar.add_file "data.tar.gz", 0444 do |io| + tar.add_file "data.tar.gz", 0o444 do |io| io.write data_tgz end end @@ -911,7 +951,7 @@ class TestGemPackage < Gem::Package::TarTestCase tf = Tempfile.open "corrupt" do |io| data = Gem::Util.gzip "a" * 10 io.write \ - tar_file_header("metadata.gz", "\000x", 0644, data.length, Time.now) + tar_file_header("metadata.gz", "\000x", 0o644, data.length, Time.now) io.write data io.rewind @@ -928,6 +968,95 @@ class TestGemPackage < Gem::Package::TarTestCase tf.close! end + def test_verify_corrupt_tar_metadata_entry + gem = tar_file_header("metadata.gz", "", 0, 999, Time.now) + + File.open "corrupt.gem", "wb" do |io| + io.write gem + end + + package = Gem::Package.new "corrupt.gem" + + e = nil + out_err = capture_output do + e = assert_raise Gem::Package::FormatError do + package.verify + end + end + + assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message) + assert_equal(["", "Exception while verifying corrupt.gem\n"], out_err) + end + + def test_verify_corrupt_tar_checksums_entry + gem = tar_file_header("checksums.yaml.gz", "", 0, 100, Time.now) + + File.open "corrupt.gem", "wb" do |io| + io.write gem + end + + package = Gem::Package.new "corrupt.gem" + + e = assert_raise Gem::Package::FormatError do + package.verify + end + + assert_equal "not in gzip format in corrupt.gem", e.message + end + + def test_verify_corrupt_tar_data_entry + gem = tar_file_header("data.tar.gz", "", 0, 100, Time.now) + + File.open "corrupt.gem", "wb" do |io| + io.write gem + end + + package = Gem::Package.new "corrupt.gem" + + e = nil + out_err = capture_output do + e = assert_raise Gem::Package::FormatError do + package.verify + end + end + + assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message) + assert_equal(["", "Exception while verifying corrupt.gem\n"], out_err) + end + + def test_corrupt_data_tar_gz + data_tgz = util_gzip tar_file_header("lib/code.rb", "", 0, 100, Time.now) + metadata_gz = util_gzip @spec.to_yaml + + gem = util_tar do |tar| + tar.add_file "data.tar.gz", 0o444 do |io| + io.write data_tgz + end + + tar.add_file "metadata.gz", 0o644 do |io| + io.write metadata_gz + end + end + + File.open "corrupt.gem", "wb" do |io| + io.write gem.string + end + + package = Gem::Package.new "corrupt.gem" + + e = assert_raise Gem::Package::FormatError do + package.contents + end + + assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message) + + e = assert_raise Gem::Package::FormatError do + package.extract_files @destination + end + + assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message) + end + def test_verify_empty FileUtils.touch "empty.gem" @@ -947,8 +1076,8 @@ class TestGemPackage < Gem::Package::TarTestCase package.verify end - assert_match %r{^No such file or directory}, e.message - assert_match %r{nonexistent.gem$}, e.message + assert_match(/^No such file or directory/, e.message) + assert_match(/nonexistent.gem$/, e.message) end def test_verify_duplicate_file @@ -963,8 +1092,8 @@ class TestGemPackage < Gem::Package::TarTestCase build.add_metadata gem build.add_contents gem - gem.add_file_simple "a.sig", 0444, 0 - gem.add_file_simple "a.sig", 0444, 0 + gem.add_file_simple "a.sig", 0o444, 0 + gem.add_file_simple "a.sig", 0o444, 0 end end @@ -1035,12 +1164,23 @@ class TestGemPackage < Gem::Package::TarTestCase # write bogus data.tar.gz to foil signature bogus_data = Gem::Util.gzip "hello" fake_signer = Class.new do - def digest_name; "SHA512"; end - def digest_algorithm; OpenSSL::Digest(:SHA512).new; end - def key; "key"; end - def sign(*); "fake_sig"; end + def digest_name + "SHA512" + end + + def digest_algorithm + OpenSSL::Digest(:SHA512).new + end + + def key + "key" + end + + def sign(*) + "fake_sig" + end end - gem.add_file_signed "data2.tar.gz", 0444, fake_signer.new do |io| + gem.add_file_signed "data2.tar.gz", 0o444, fake_signer.new do |io| io.write bogus_data end @@ -1082,7 +1222,9 @@ class TestGemPackage < Gem::Package::TarTestCase def test_verify_entry entry = Object.new - def entry.full_name() raise ArgumentError, "whatever" end + def entry.full_name + raise ArgumentError, "whatever" + end package = Gem::Package.new @gem @@ -1109,11 +1251,15 @@ class TestGemPackage < Gem::Package::TarTestCase $good_name = vm entry = Object.new - def entry.full_name() $good_name end + def entry.full_name + $good_name + end package = Gem::Package.new(@gem) package.instance_variable_set(:@files, []) - def package.load_spec(entry) $spec_loaded = true end + def package.load_spec(entry) + $spec_loaded = true + end package.verify_entry(entry) @@ -1126,11 +1272,15 @@ class TestGemPackage < Gem::Package::TarTestCase $bad_name = vm entry = Object.new - def entry.full_name() $bad_name end + def entry.full_name + $bad_name + end package = Gem::Package.new(@gem) package.instance_variable_set(:@files, []) - def package.load_spec(entry) $spec_loaded = true end + def package.load_spec(entry) + $spec_loaded = true + end package.verify_entry(entry) @@ -1172,29 +1322,4 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal %w[lib/code.rb], package.contents end - - def util_tar - tar_io = StringIO.new - - Gem::Package::TarWriter.new tar_io do |tar| - yield tar - end - - tar_io.rewind - - tar_io - end - - def util_tar_gz(&block) - tar_io = util_tar(&block) - - tgz_io = StringIO.new - - # can't wrap TarWriter because it seeks - Zlib::GzipWriter.wrap tgz_io do |io| - io.write tar_io.string - end - - StringIO.new tgz_io.string - end end diff --git a/test/rubygems/test_gem_package_old.rb b/test/rubygems/test_gem_package_old.rb index d65d1edad6..7582dbedd4 100644 --- a/test/rubygems/test_gem_package_old.rb +++ b/test/rubygems/test_gem_package_old.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" unless Gem.java_platform? # jruby can't require the simple_gem file @@ -38,9 +39,9 @@ unless Gem.java_platform? # jruby can't require the simple_gem file extracted = File.join @destination, "lib/foo.rb" assert_path_exist extracted - mask = 0100644 & (~File.umask) + mask = 0o100644 & (~File.umask) - assert_equal mask, File.stat(extracted).mode unless win_platform? + assert_equal mask, File.stat(extracted).mode unless Gem.win_platform? end def test_extract_files_security_policy @@ -82,7 +83,7 @@ unless Gem.java_platform? # jruby can't require the simple_gem file @package.verify end - assert_equal "old format gems do not contain signatures " + + assert_equal "old format gems do not contain signatures " \ "and cannot be verified", e.message end diff --git a/test/rubygems/test_gem_package_tar_header.rb b/test/rubygems/test_gem_package_tar_header.rb index 3ff4f0b30b..a3f95bb770 100644 --- a/test/rubygems/test_gem_package_tar_header.rb +++ b/test/rubygems/test_gem_package_tar_header.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "package/tar_test_case" require "rubygems/package" @@ -7,19 +8,19 @@ class TestGemPackageTarHeader < Gem::Package::TarTestCase super header = { - :name => "x", - :mode => 0644, - :uid => 1000, - :gid => 10000, - :size => 100, - :mtime => 12345, - :typeflag => "0", - :linkname => "link", - :uname => "user", - :gname => "group", - :devmajor => 1, - :devminor => 2, - :prefix => "y", + name: "x", + mode: 0o644, + uid: 1000, + gid: 10_000, + size: 100, + mtime: 12_345, + typeflag: "0", + linkname: "link", + uname: "user", + gname: "group", + devmajor: 1, + devminor: 2, + prefix: "y", } @tar_header = Gem::Package::TarHeader.new header @@ -39,12 +40,12 @@ class TestGemPackageTarHeader < Gem::Package::TarTestCase assert_equal "", @tar_header.checksum, "checksum" assert_equal 1, @tar_header.devmajor, "devmajor" assert_equal 2, @tar_header.devminor, "devminor" - assert_equal 10000, @tar_header.gid, "gid" + assert_equal 10_000, @tar_header.gid, "gid" assert_equal "group", @tar_header.gname, "gname" assert_equal "link", @tar_header.linkname, "linkname" assert_equal "ustar", @tar_header.magic, "magic" - assert_equal 0644, @tar_header.mode, "mode" - assert_equal 12345, @tar_header.mtime, "mtime" + assert_equal 0o644, @tar_header.mode, "mode" + assert_equal 12_345, @tar_header.mtime, "mtime" assert_equal "x", @tar_header.name, "name" assert_equal "y", @tar_header.prefix, "prefix" assert_equal 100, @tar_header.size, "size" @@ -58,29 +59,29 @@ class TestGemPackageTarHeader < Gem::Package::TarTestCase def test_initialize_bad assert_raise ArgumentError do - Gem::Package::TarHeader.new :name => "", :size => "", :mode => "" + Gem::Package::TarHeader.new name: "", size: "", mode: "" end assert_raise ArgumentError do - Gem::Package::TarHeader.new :name => "", :size => "", :prefix => "" + Gem::Package::TarHeader.new name: "", size: "", prefix: "" end assert_raise ArgumentError do - Gem::Package::TarHeader.new :name => "", :prefix => "", :mode => "" + Gem::Package::TarHeader.new name: "", prefix: "", mode: "" end assert_raise ArgumentError do - Gem::Package::TarHeader.new :prefix => "", :size => "", :mode => "" + Gem::Package::TarHeader.new prefix: "", size: "", mode: "" end end def test_initialize_typeflag header = { - :mode => "", - :name => "", - :prefix => "", - :size => "", - :typeflag => "", + mode: "", + name: "", + prefix: "", + size: "", + typeflag: "", } tar_header = Gem::Package::TarHeader.new header @@ -91,11 +92,36 @@ class TestGemPackageTarHeader < Gem::Package::TarTestCase def test_empty_eh refute_empty @tar_header - @tar_header = Gem::Package::TarHeader.new :name => "x", :prefix => "", - :mode => 0, :size => 0, - :empty => true + @tar_header = Gem::Package::TarHeader.new name: "x", prefix: "", + mode: 0, size: 0, + empty: true + + assert_empty @tar_header + end + + def test_empty + @tar_header = Gem::Package::TarHeader.from(StringIO.new(Gem::Package::TarHeader::EMPTY_HEADER)) assert_empty @tar_header + assert_equal Gem::Package::TarHeader.new( + checksum: 0, + devmajor: 0, + devminor: 0, + empty: true, + gid: 0, + gname: "", + linkname: "", + magic: "", + mode: 0, + mtime: 0, + name: "", + prefix: "", + size: 0, + typeflag: "0", + uid: 0, + uname: "", + version: 0, + ), @tar_header end def test_equals2 @@ -159,6 +185,7 @@ group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 assert_raise ArgumentError do Gem::Package::TarHeader.from io end + ensure io.close! end end @@ -194,13 +221,13 @@ tjmather\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 tar_header = Gem::Package::TarHeader.from stream - assert_equal 1991400094, tar_header.uid - assert_equal 1991400094, tar_header.gid + assert_equal 1_991_400_094, tar_header.uid + assert_equal 1_991_400_094, tar_header.gid assert_equal "GeoIP2-City_20190528/", tar_header.name - assert_equal 0755, tar_header.mode + assert_equal 0o755, tar_header.mode assert_equal 0, tar_header.size - assert_equal 1559064640, tar_header.mtime + assert_equal 1_559_064_640, tar_header.mtime assert_equal 6932, tar_header.checksum end diff --git a/test/rubygems/test_gem_package_tar_reader.rb b/test/rubygems/test_gem_package_tar_reader.rb index 19860eb7e8..b2f7cc2d5c 100644 --- a/test/rubygems/test_gem_package_tar_reader.rb +++ b/test/rubygems/test_gem_package_tar_reader.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "package/tar_test_case" require "rubygems/package" @@ -24,11 +25,26 @@ class TestGemPackageTarReader < Gem::Package::TarTestCase io.close! end + def test_each_with_not_a_tar + text = "Hello, world!!?\n" * 256 # 4 KiB + io = TempIO.new text + + Gem::Package::TarReader.new io do |tar| + assert_raise Gem::Package::TarInvalidError do + tar.each do + flunk "TarInvalidError was expected to occur, but an entry was found" + end + end + end + ensure + io.close! + end + def test_rewind content = ("a".."z").to_a.join(" ") str = - tar_file_header("lib/foo", "", 010644, content.size, Time.now) + + tar_file_header("lib/foo", "", 0o10644, content.size, Time.now) + content + "\0" * (512 - content.size) str << "\0" * 1024 @@ -56,12 +72,14 @@ class TestGemPackageTarReader < Gem::Package::TarTestCase io = TempIO.new tar Gem::Package::TarReader.new io do |tar_reader| - tar_reader.seek "baz/bar" do |entry| + retval = tar_reader.seek "baz/bar" do |entry| assert_kind_of Gem::Package::TarReader::Entry, entry assert_equal "baz/bar", entry.full_name + entry.read end + assert_equal "", retval assert_equal 0, io.pos end ensure @@ -75,7 +93,7 @@ class TestGemPackageTarReader < Gem::Package::TarTestCase io = TempIO.new tar Gem::Package::TarReader.new io do |tar_reader| - tar_reader.seek "nonexistent" do |entry| + tar_reader.seek "nonexistent" do |_entry| flunk "entry missing but entry-found block was run" end @@ -84,4 +102,49 @@ class TestGemPackageTarReader < Gem::Package::TarTestCase ensure io.close! end + + def test_read_in_gem_data + gem_tar = util_gem_data_tar do |tar| + tar.add_file "lib/code.rb", 0o444 do |io| + io.write "# lib/code.rb" + end + end + + count = 0 + Gem::Package::TarReader.new(gem_tar).each do |entry| + next unless entry.full_name == "data.tar.gz" + + Zlib::GzipReader.wrap entry do |gzio| + Gem::Package::TarReader.new(gzio).each do |contents_entry| + assert_equal "# lib/code.rb", contents_entry.read + count += 1 + end + end + end + + assert_equal 1, count, "should have found one file" + end + + def test_seek_in_gem_data + gem_tar = util_gem_data_tar do |tar| + tar.add_file "lib/code.rb", 0o444 do |io| + io.write "# lib/code.rb" + end + tar.add_file "lib/foo.rb", 0o444 do |io| + io.write "# lib/foo.rb" + end + end + + count = 0 + Gem::Package::TarReader.new(gem_tar).seek("data.tar.gz") do |entry| + Zlib::GzipReader.wrap entry do |gzio| + Gem::Package::TarReader.new(gzio).seek("lib/foo.rb") do |contents_entry| + assert_equal "# lib/foo.rb", contents_entry.read + count += 1 + end + end + end + + assert_equal 1, count, "should have found one file" + end end diff --git a/test/rubygems/test_gem_package_tar_reader_entry.rb b/test/rubygems/test_gem_package_tar_reader_entry.rb index ffb4542178..67ab7922b5 100644 --- a/test/rubygems/test_gem_package_tar_reader_entry.rb +++ b/test/rubygems/test_gem_package_tar_reader_entry.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "package/tar_test_case" require "rubygems/package" @@ -10,8 +11,7 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase @tar = String.new @tar << tar_file_header("lib/foo", "", 0, @contents.size, Time.now) - @tar << @contents - @tar << "\0" * (512 - (@tar.size % 512)) + @tar << tar_file_contents(@contents) @entry = util_entry @tar end @@ -21,8 +21,39 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase super end - def close_util_entry(entry) - entry.instance_variable_get(:@io).close! + def test_open + io = TempIO.new @tar + header = Gem::Package::TarHeader.from io + retval = Gem::Package::TarReader::Entry.open header, io, &:getc + assert_equal "a", retval + assert_equal @tar.size, io.pos, "should have read to end of entry" + ensure + io&.close! + end + + def test_open_closes_entry + io = TempIO.new @tar + header = Gem::Package::TarHeader.from io + entry = nil + Gem::Package::TarReader::Entry.open header, io do |e| + entry = e + end + assert entry.closed? + assert_raise(IOError) { entry.getc } + ensure + io&.close! + end + + def test_open_returns_entry + io = TempIO.new @tar + header = Gem::Package::TarHeader.from io + entry = Gem::Package::TarReader::Entry.open header, io + refute entry.closed? + assert_equal "a", entry.getc + assert_nil entry.close + assert entry.closed? + ensure + io&.close! end def test_bytes_read @@ -86,7 +117,7 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase end def test_getc - assert_equal ?a, @entry.getc + assert_equal "a", @entry.getc end def test_directory_eh @@ -125,6 +156,18 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase assert_equal @contents, @entry.read end + def test_consecutive_read + expected = StringIO.new(@contents) + assert_equal expected.read, @entry.read + assert_equal expected.read, @entry.read + end + + def test_consecutive_read_bytes_past_eof + expected = StringIO.new(@contents) + assert_equal expected.read, @entry.read + assert_equal expected.read(1), @entry.read(1) + end + def test_read_big assert_equal @contents, @entry.read(@contents.size * 2) end @@ -133,13 +176,64 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase assert_equal @contents[0...100], @entry.read(100) end + def test_read_remaining + @entry.read(100) + assert_equal @contents[100..-1], @entry.read + end + def test_readpartial + assert_equal @contents[0...100], @entry.readpartial(100) + end + + def test_readpartial_to_eof + assert_equal @contents, @entry.readpartial(4096) + assert @entry.eof? + end + + def test_read_partial_buffer + buffer = "".b + @entry.readpartial(100, buffer) + assert_equal @contents[0...100], buffer + end + + def test_readpartial_past_eof + @entry.readpartial(@contents.size) + assert @entry.eof? assert_raise(EOFError) do - @entry.read(@contents.size) @entry.readpartial(1) end end + def test_read_corrupted_tar + corrupt_tar = String.new + corrupt_tar << tar_file_header("lib/foo", "", 0, 100, Time.now) + corrupt_tar << tar_file_contents("") + corrupt_entry = util_entry corrupt_tar + + assert_equal "", corrupt_entry.read(0) + assert_equal "", corrupt_entry.read, "IO.read without len should return empty string (even though it's at an unpexpected EOF)" + + corrupt_entry.rewind + + assert_nil corrupt_entry.read(100), "IO.read with len should return nil as per IO.read docs" + ensure + close_util_entry(corrupt_entry) if corrupt_entry + end + + def test_readpartial_corrupted_tar + corrupt_tar = String.new + corrupt_tar << tar_file_header("lib/foo", "", 0, 100, Time.now) + corrupt_tar << tar_file_contents("") + + corrupt_entry = util_entry corrupt_tar + + assert_raise EOFError do + corrupt_entry.readpartial(100) + end + ensure + close_util_entry(corrupt_entry) if corrupt_entry + end + def test_rewind char = @entry.getc @@ -149,4 +243,116 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase assert_equal char, @entry.getc end + + def test_seek + @entry.seek(50) + assert_equal 50, @entry.pos + assert_equal @contents[50..-1], @entry.read, "read remaining after seek" + @entry.seek(-50, IO::SEEK_CUR) + assert_equal @contents.size - 50, @entry.pos + assert_equal @contents[-50..-1], @entry.read, "read after stepping back 50 from the end" + @entry.seek(0, IO::SEEK_SET) + assert_equal 0, @entry.pos + assert_equal @contents, @entry.read, "read from beginning" + @entry.seek(-10, IO::SEEK_END) + assert_equal @contents.size - 10, @entry.pos + assert_equal @contents[-10..-1], @entry.read, "read from end" + end + + def test_read_zero + expected = StringIO.new("") + assert_equal expected.read(0), @entry.read(0) + end + + def test_readpartial_zero + expected = StringIO.new("") + assert_equal expected.readpartial(0), @entry.readpartial(0) + end + + def test_zero_byte_file_read + zero_entry = util_entry(tar_file_header("foo", "", 0, 0, Time.now)) + expected = StringIO.new("") + assert_equal expected.read, zero_entry.read + ensure + close_util_entry(zero_entry) if zero_entry + end + + def test_zero_byte_file_readpartial + zero_entry = util_entry(tar_file_header("foo", "", 0, 0, Time.now)) + expected = StringIO.new("") + assert_equal expected.readpartial(0), zero_entry.readpartial(0) + ensure + close_util_entry(zero_entry) if zero_entry + end + + def test_read_from_gzip_io + tgz = util_gzip(@tar) + + Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio| + entry = util_entry(gzio) + assert_equal @contents, entry.read + entry.rewind + assert_equal @contents, entry.read, "second read after rewind should read same contents" + end + end + + def test_read_from_gzip_io_with_non_zero_offset + contents2 = ("0".."9").to_a.join * 100 + @tar << tar_file_header("lib/bar", "", 0, contents2.size, Time.now) + @tar << tar_file_contents(contents2) + + tgz = util_gzip(@tar) + + Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio| + util_entry(gzio).close # skip the first entry so io.pos is not 0, preventing easy rewind + entry = util_entry(gzio) + + assert_equal contents2, entry.read + entry.rewind + assert_equal contents2, entry.read, "second read after rewind should read same contents" + end + end + + def test_seek_in_gzip_io_with_non_zero_offset + contents2 = ("0".."9").to_a.join * 100 + @tar << tar_file_header("lib/bar", "", 0, contents2.size, Time.now) + @tar << tar_file_contents(contents2) + + tgz = util_gzip(@tar) + + Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio| + util_entry(gzio).close # skip the first entry so io.pos is not 0 + entry = util_entry(gzio) + + entry.seek(50) + assert_equal 50, entry.pos + assert_equal contents2[50..-1], entry.read, "read remaining after seek" + entry.seek(-50, IO::SEEK_CUR) + assert_equal contents2.size - 50, entry.pos + assert_equal contents2[-50..-1], entry.read, "read after stepping back 50 from the end" + entry.seek(0, IO::SEEK_SET) + assert_equal 0, entry.pos + assert_equal contents2, entry.read, "read from beginning" + entry.seek(-10, IO::SEEK_END) + assert_equal contents2.size - 10, entry.pos + assert_equal contents2[-10..-1], entry.read, "read from end" + assert_equal contents2.size, entry.pos + end + end + + def test_seek_in_gzip_io_corrupted + @tar << tar_file_header("lib/bar", "", 0, 100, Time.now) + @tar << tar_file_contents("") + + tgz = util_gzip(@tar) + + Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio| + util_entry(gzio).close # skip the first entry so io.pos is not 0 + entry = util_entry(gzio) + + assert_raise EOFError do + entry.seek(50) + end + end + end end diff --git a/test/rubygems/test_gem_package_tar_writer.rb b/test/rubygems/test_gem_package_tar_writer.rb index 5dcb90c14e..751ceaca81 100644 --- a/test/rubygems/test_gem_package_tar_writer.rb +++ b/test/rubygems/test_gem_package_tar_writer.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "package/tar_test_case" require "rubygems/package/tar_writer" @@ -27,12 +28,12 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase end def test_add_file - Time.stub :now, Time.at(1458518157) do - @tar_writer.add_file "x", 0644 do |f| + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.add_file "x", 0o644 do |f| f.write "a" * 10 end - assert_headers_equal(tar_file_header("x", "", 0644, 10, Time.now), + assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now), @io.string[0, 512]) end assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512] @@ -41,19 +42,19 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase def test_add_file_source_date_epoch ENV["SOURCE_DATE_EPOCH"] = "123456789" - Time.stub :now, Time.at(1458518157) do - @tar_writer.mkdir "foo", 0644 + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.mkdir "foo", 0o644 - assert_headers_equal tar_dir_header("foo", "", 0644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), + assert_headers_equal tar_dir_header("foo", "", 0o644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), @io.string[0, 512] end end def test_add_symlink - Time.stub :now, Time.at(1458518157) do - @tar_writer.add_symlink "x", "y", 0644 + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.add_symlink "x", "y", 0o644 - assert_headers_equal(tar_symlink_header("x", "", 0644, Time.now, "y"), + assert_headers_equal(tar_symlink_header("x", "", 0o644, Time.now, "y"), @io.string[0, 512]) end assert_equal 512, @io.pos @@ -61,19 +62,19 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase def test_add_symlink_source_date_epoch ENV["SOURCE_DATE_EPOCH"] = "123456789" - Time.stub :now, Time.at(1458518157) do - @tar_writer.add_symlink "x", "y", 0644 + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.add_symlink "x", "y", 0o644 - assert_headers_equal(tar_symlink_header("x", "", 0644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc, "y"), + assert_headers_equal(tar_symlink_header("x", "", 0o644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc, "y"), @io.string[0, 512]) end end def test_add_file_digest - digest_algorithms = Digest::SHA1.new, Digest::SHA512.new + digest_algorithms = OpenSSL::Digest::SHA1.new, OpenSSL::Digest::SHA512.new - Time.stub :now, Time.at(1458518157) do - digests = @tar_writer.add_file_digest "x", 0644, digest_algorithms do |io| + Time.stub :now, Time.at(1_458_518_157) do + digests = @tar_writer.add_file_digest "x", 0o644, digest_algorithms do |io| io.write "a" * 10 end @@ -85,7 +86,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase "e1cf14b0", digests["SHA512"].hexdigest - assert_headers_equal(tar_file_header("x", "", 0644, 10, Time.now), + assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now), @io.string[0, 512]) end assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512] @@ -93,10 +94,10 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase end def test_add_file_digest_multiple - digest_algorithms = [Digest::SHA1.new, Digest::SHA512.new] + digest_algorithms = [OpenSSL::Digest::SHA1.new, OpenSSL::Digest::SHA512.new] - Time.stub :now, Time.at(1458518157) do - digests = @tar_writer.add_file_digest "x", 0644, digest_algorithms do |io| + Time.stub :now, Time.at(1_458_518_157) do + digests = @tar_writer.add_file_digest "x", 0o644, digest_algorithms do |io| io.write "a" * 10 end @@ -108,7 +109,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase "e1cf14b0", digests["SHA512"].hexdigest - assert_headers_equal(tar_file_header("x", "", 0644, 10, Time.now), + assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now), @io.string[0, 512]) end assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512] @@ -120,12 +121,12 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase signer = Gem::Security::Signer.new PRIVATE_KEY, [PUBLIC_CERT] - Time.stub :now, Time.at(1458518157) do - @tar_writer.add_file_signed "x", 0644, signer do |io| + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.add_file_signed "x", 0o644, signer do |io| io.write "a" * 10 end - assert_headers_equal(tar_file_header("x", "", 0644, 10, Time.now), + assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now), @io.string[0, 512]) assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512] @@ -135,7 +136,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase signature = signer.sign digest.digest - assert_headers_equal(tar_file_header("x.sig", "", 0444, signature.length, + assert_headers_equal(tar_file_header("x.sig", "", 0o444, signature.length, Time.now), @io.string[1024, 512]) assert_equal "#{signature}#{"\0" * (512 - signature.length)}", @@ -148,12 +149,12 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase def test_add_file_signer_empty signer = Gem::Security::Signer.new nil, nil - Time.stub :now, Time.at(1458518157) do - @tar_writer.add_file_signed "x", 0644, signer do |io| + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.add_file_signed "x", 0o644, signer do |io| io.write "a" * 10 end - assert_headers_equal(tar_file_header("x", "", 0644, 10, Time.now), + assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now), @io.string[0, 512]) end assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512] @@ -162,12 +163,12 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase end def test_add_file_simple - Time.stub :now, Time.at(1458518157) do - @tar_writer.add_file_simple "x", 0644, 10 do |io| + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.add_file_simple "x", 0o644, 10 do |io| io.write "a" * 10 end - assert_headers_equal(tar_file_header("x", "", 0644, 10, Time.now), + assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now), @io.string[0, 512]) assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512] @@ -177,18 +178,18 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase def test_add_file_simple_source_date_epoch ENV["SOURCE_DATE_EPOCH"] = "123456789" - Time.stub :now, Time.at(1458518157) do - @tar_writer.add_file_simple "x", 0644, 10 do |io| + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.add_file_simple "x", 0o644, 10 do |io| io.write "a" * 10 end - assert_headers_equal(tar_file_header("x", "", 0644, 10, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), + assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), @io.string[0, 512]) end end def test_add_file_simple_padding - Time.stub :now, Time.at(1458518157) do + Time.stub :now, Time.at(1_458_518_157) do @tar_writer.add_file_simple "x", 0, 100 assert_headers_equal tar_file_header("x", "", 0, 100, Time.now), @@ -246,10 +247,10 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase end def test_mkdir - Time.stub :now, Time.at(1458518157) do - @tar_writer.mkdir "foo", 0644 + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.mkdir "foo", 0o644 - assert_headers_equal tar_dir_header("foo", "", 0644, Time.now), + assert_headers_equal tar_dir_header("foo", "", 0o644, Time.now), @io.string[0, 512] assert_equal 512, @io.pos @@ -258,20 +259,20 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase def test_mkdir_source_date_epoch ENV["SOURCE_DATE_EPOCH"] = "123456789" - Time.stub :now, Time.at(1458518157) do - @tar_writer.mkdir "foo", 0644 + Time.stub :now, Time.at(1_458_518_157) do + @tar_writer.mkdir "foo", 0o644 - assert_headers_equal tar_dir_header("foo", "", 0644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), + assert_headers_equal tar_dir_header("foo", "", 0o644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), @io.string[0, 512] end end def test_split_name assert_equal ["b" * 100, "a" * 155], - @tar_writer.split_name("#{'a' * 155}/#{'b' * 100}") + @tar_writer.split_name("#{"a" * 155}/#{"b" * 100}") - assert_equal ["#{'qwer/' * 19}bla", "a" * 151], - @tar_writer.split_name("#{'a' * 151}/#{'qwer/' * 19}bla") + assert_equal ["#{"qwer/" * 19}bla", "a" * 151], + @tar_writer.split_name("#{"a" * 151}/#{"qwer/" * 19}bla") names = [ ([""] + ["123456789"] * 9 + ["1234567890"]).join("/"), # 101 bytes (several pieces) (["123456789"] * 9 + ["1234567890"] + [""]).join("/"), # 101 bytes (several pieces) @@ -282,7 +283,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase ] names.each do |name| newname, prefix = @tar_writer.split_name(name) - assert(!(newname.empty?), "split_name() returned empty name") + assert(!newname.empty?, "split_name() returned empty name") assert(newname.bytesize <= 100, "split_name() returned name longer than 100 bytes: '#{newname}' for '#{name}'") assert(prefix.bytesize <= 155, "split_name() returned prefix longer than 155 bytes: '#{prefix}' for '#{name}'") newname = [prefix, newname].join("/") unless prefix.empty? diff --git a/test/rubygems/test_gem_package_task.rb b/test/rubygems/test_gem_package_task.rb index 65fb818d7a..6f322ad61e 100644 --- a/test/rubygems/test_gem_package_task.rb +++ b/test/rubygems/test_gem_package_task.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems" @@ -8,10 +9,6 @@ rescue LoadError => e raise unless e.path == "rake/packagetask" end -unless defined?(Rake::PackageTask) - warn "Skipping Gem::PackageTask tests. rake not found." -end - class TestGemPackageTask < Gem::TestCase def test_gem_package original_rake_fileutils_verbosity = RakeFileUtils.verbose_flag diff --git a/test/rubygems/test_gem_path_support.rb b/test/rubygems/test_gem_path_support.rb index fa0e3990be..8720bcf858 100644 --- a/test/rubygems/test_gem_path_support.rb +++ b/test/rubygems/test_gem_path_support.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems" require "fileutils" diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb index 0fb5bf59a5..00e48498c6 100644 --- a/test/rubygems/test_gem_platform.rb +++ b/test/rubygems/test_gem_platform.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/platform" require "rbconfig" @@ -27,7 +28,7 @@ class TestGemPlatform < Gem::TestCase end def test_self_match_spec? - make_spec = -> platform do + make_spec = ->(platform) do util_spec "mygem-for-platform-match_spec", "1" do |s| s.platform = platform end @@ -40,7 +41,7 @@ class TestGemPlatform < Gem::TestCase end def test_self_match_spec_with_match_gem_override - make_spec = -> name, platform do + make_spec = ->(name, platform) do util_spec name, "1" do |s| s.platform = platform end @@ -70,7 +71,7 @@ class TestGemPlatform < Gem::TestCase Gem.platforms = platforms class << Gem::Platform remove_method :match_gem? - alias_method :match_gem?, :original_match_gem? # rubocop:disable Lint/DuplicateMethods + alias_method :match_gem?, :original_match_gem? remove_method :original_match_gem? end end @@ -85,65 +86,74 @@ class TestGemPlatform < Gem::TestCase def test_initialize test_cases = { - "amd64-freebsd6" => ["amd64", "freebsd", "6"], - "hppa2.0w-hpux11.31" => ["hppa2.0w", "hpux", "11"], - "java" => [nil, "java", nil], - "jruby" => [nil, "java", nil], - "universal-dotnet" => ["universal", "dotnet", nil], - "universal-dotnet2.0" => ["universal", "dotnet", "2.0"], - "universal-dotnet4.0" => ["universal", "dotnet", "4.0"], - "powerpc-aix5.3.0.0" => ["powerpc", "aix", "5"], - "powerpc-darwin7" => ["powerpc", "darwin", "7"], - "powerpc-darwin8" => ["powerpc", "darwin", "8"], - "powerpc-linux" => ["powerpc", "linux", nil], - "powerpc64-linux" => ["powerpc64", "linux", nil], - "sparc-solaris2.10" => ["sparc", "solaris", "2.10"], - "sparc-solaris2.8" => ["sparc", "solaris", "2.8"], - "sparc-solaris2.9" => ["sparc", "solaris", "2.9"], - "universal-darwin8" => ["universal", "darwin", "8"], - "universal-darwin9" => ["universal", "darwin", "9"], - "universal-macruby" => ["universal", "macruby", nil], - "i386-cygwin" => ["x86", "cygwin", nil], - "i686-darwin" => ["x86", "darwin", nil], - "i686-darwin8.4.1" => ["x86", "darwin", "8"], - "i386-freebsd4.11" => ["x86", "freebsd", "4"], - "i386-freebsd5" => ["x86", "freebsd", "5"], - "i386-freebsd6" => ["x86", "freebsd", "6"], - "i386-freebsd7" => ["x86", "freebsd", "7"], - "i386-freebsd" => ["x86", "freebsd", nil], - "universal-freebsd" => ["universal", "freebsd", nil], - "i386-java1.5" => ["x86", "java", "1.5"], - "x86-java1.6" => ["x86", "java", "1.6"], - "i386-java1.6" => ["x86", "java", "1.6"], - "i686-linux" => ["x86", "linux", nil], - "i586-linux" => ["x86", "linux", nil], - "i486-linux" => ["x86", "linux", nil], - "i386-linux" => ["x86", "linux", nil], - "i586-linux-gnu" => ["x86", "linux", nil], - "i386-linux-gnu" => ["x86", "linux", nil], - "i386-mingw32" => ["x86", "mingw32", nil], - "x64-mingw-ucrt" => ["x64", "mingw", "ucrt"], - "i386-mswin32" => ["x86", "mswin32", nil], - "i386-mswin32_80" => ["x86", "mswin32", "80"], - "i386-mswin32-80" => ["x86", "mswin32", "80"], - "x86-mswin32" => ["x86", "mswin32", nil], - "x86-mswin32_60" => ["x86", "mswin32", "60"], - "x86-mswin32-60" => ["x86", "mswin32", "60"], - "i386-netbsdelf" => ["x86", "netbsdelf", nil], - "i386-openbsd4.0" => ["x86", "openbsd", "4.0"], - "i386-solaris2.10" => ["x86", "solaris", "2.10"], - "i386-solaris2.8" => ["x86", "solaris", "2.8"], - "mswin32" => ["x86", "mswin32", nil], - "x86_64-linux" => ["x86_64", "linux", nil], - "x86_64-linux-musl" => ["x86_64", "linux", "musl"], - "x86_64-openbsd3.9" => ["x86_64", "openbsd", "3.9"], - "x86_64-openbsd4.0" => ["x86_64", "openbsd", "4.0"], - "x86_64-openbsd" => ["x86_64", "openbsd", nil], + "amd64-freebsd6" => ["amd64", "freebsd", "6"], + "java" => [nil, "java", nil], + "jruby" => [nil, "java", nil], + "universal-dotnet" => ["universal", "dotnet", nil], + "universal-dotnet2.0" => ["universal", "dotnet", "2.0"], + "universal-dotnet4.0" => ["universal", "dotnet", "4.0"], + "powerpc-aix5.3.0.0" => ["powerpc", "aix", "5"], + "powerpc-darwin7" => ["powerpc", "darwin", "7"], + "powerpc-darwin8" => ["powerpc", "darwin", "8"], + "powerpc-linux" => ["powerpc", "linux", nil], + "powerpc64-linux" => ["powerpc64", "linux", nil], + "sparc-solaris2.10" => ["sparc", "solaris", "2.10"], + "sparc-solaris2.8" => ["sparc", "solaris", "2.8"], + "sparc-solaris2.9" => ["sparc", "solaris", "2.9"], + "universal-darwin8" => ["universal", "darwin", "8"], + "universal-darwin9" => ["universal", "darwin", "9"], + "universal-macruby" => ["universal", "macruby", nil], + "i386-cygwin" => ["x86", "cygwin", nil], + "i686-darwin" => ["x86", "darwin", nil], + "i686-darwin8.4.1" => ["x86", "darwin", "8"], + "i386-freebsd4.11" => ["x86", "freebsd", "4"], + "i386-freebsd5" => ["x86", "freebsd", "5"], + "i386-freebsd6" => ["x86", "freebsd", "6"], + "i386-freebsd7" => ["x86", "freebsd", "7"], + "i386-freebsd" => ["x86", "freebsd", nil], + "universal-freebsd" => ["universal", "freebsd", nil], + "i386-java1.5" => ["x86", "java", "1.5"], + "x86-java1.6" => ["x86", "java", "1.6"], + "i386-java1.6" => ["x86", "java", "1.6"], + "i686-linux" => ["x86", "linux", nil], + "i586-linux" => ["x86", "linux", nil], + "i486-linux" => ["x86", "linux", nil], + "i386-linux" => ["x86", "linux", nil], + "i586-linux-gnu" => ["x86", "linux", "gnu"], + "i386-linux-gnu" => ["x86", "linux", "gnu"], + "i386-mingw32" => ["x86", "mingw32", nil], + "x64-mingw-ucrt" => ["x64", "mingw", "ucrt"], + "i386-mswin32" => ["x86", "mswin32", nil], + "i386-mswin32_80" => ["x86", "mswin32", "80"], + "i386-mswin32-80" => ["x86", "mswin32", "80"], + "x86-mswin32" => ["x86", "mswin32", nil], + "x86-mswin32_60" => ["x86", "mswin32", "60"], + "x86-mswin32-60" => ["x86", "mswin32", "60"], + "i386-netbsdelf" => ["x86", "netbsdelf", nil], + "i386-openbsd4.0" => ["x86", "openbsd", "4.0"], + "i386-solaris2.10" => ["x86", "solaris", "2.10"], + "i386-solaris2.8" => ["x86", "solaris", "2.8"], + "mswin32" => ["x86", "mswin32", nil], + "x86_64-linux" => ["x86_64", "linux", nil], + "x86_64-linux-gnu" => ["x86_64", "linux", "gnu"], + "x86_64-linux-musl" => ["x86_64", "linux", "musl"], + "x86_64-linux-uclibc" => ["x86_64", "linux", "uclibc"], + "arm-linux-eabi" => ["arm", "linux", "eabi"], + "arm-linux-gnueabi" => ["arm", "linux", "gnueabi"], + "arm-linux-musleabi" => ["arm", "linux", "musleabi"], + "arm-linux-uclibceabi" => ["arm", "linux", "uclibceabi"], + "x86_64-openbsd3.9" => ["x86_64", "openbsd", "3.9"], + "x86_64-openbsd4.0" => ["x86_64", "openbsd", "4.0"], + "x86_64-openbsd" => ["x86_64", "openbsd", nil], + "wasm32-wasi" => ["wasm32", "wasi", nil], + "wasm32-wasip1" => ["wasm32", "wasi", nil], + "wasm32-wasip2" => ["wasm32", "wasi", nil], } test_cases.each do |arch, expected| platform = Gem::Platform.new arch assert_equal expected, platform.to_a, arch.inspect + assert_equal expected, Gem::Platform.new(platform.to_s).to_a, arch.inspect end end @@ -168,7 +178,7 @@ class TestGemPlatform < Gem::TestCase end def test_initialize_mswin32_vc6 - orig_RUBY_SO_NAME = RbConfig::CONFIG["RUBY_SO_NAME"] + orig_ruby_so_name = RbConfig::CONFIG["RUBY_SO_NAME"] RbConfig::CONFIG["RUBY_SO_NAME"] = "msvcrt-ruby18" expected = ["x86", "mswin32", nil] @@ -177,8 +187,8 @@ class TestGemPlatform < Gem::TestCase assert_equal expected, platform.to_a, "i386-mswin32 VC6" ensure - if orig_RUBY_SO_NAME - RbConfig::CONFIG["RUBY_SO_NAME"] = orig_RUBY_SO_NAME + if orig_ruby_so_name + RbConfig::CONFIG["RUBY_SO_NAME"] = orig_ruby_so_name else RbConfig::CONFIG.delete "RUBY_SO_NAME" end @@ -205,7 +215,7 @@ class TestGemPlatform < Gem::TestCase end def test_to_s - if win_platform? + if Gem.win_platform? assert_equal "x86-mswin32-60", Gem::Platform.local.to_s else assert_equal "x86-darwin-8", Gem::Platform.local.to_s @@ -225,7 +235,7 @@ class TestGemPlatform < Gem::TestCase my = Gem::Platform.new %w[cpu my_platform 1] other = Gem::Platform.new %w[cpu other_platform 1] - assert(my === my) + assert(my === my) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands refute(other === my) refute(my === other) end @@ -262,6 +272,98 @@ class TestGemPlatform < Gem::TestCase assert((with_x86_arch === with_nil_arch), "x86 =~ nil") end + def test_nil_version_is_treated_as_any_version + x86_darwin_8 = Gem::Platform.new "i686-darwin8.0" + x86_darwin_nil = Gem::Platform.new "i686-darwin" + + assert((x86_darwin_8 === x86_darwin_nil), "8.0 =~ nil") + assert((x86_darwin_nil === x86_darwin_8), "nil =~ 8.0") + end + + def test_nil_version_is_stricter_for_linux_os + x86_linux = Gem::Platform.new "i686-linux" + x86_linux_gnu = Gem::Platform.new "i686-linux-gnu" + x86_linux_musl = Gem::Platform.new "i686-linux-musl" + x86_linux_uclibc = Gem::Platform.new "i686-linux-uclibc" + + # a naked linux runtime is implicit gnu, as it represents the common glibc-linked runtime + assert(x86_linux === x86_linux_gnu, "linux =~ linux-gnu") + assert(x86_linux_gnu === x86_linux, "linux-gnu =~ linux") + + # musl and explicit gnu should differ + refute(x86_linux_gnu === x86_linux_musl, "linux-gnu =~ linux-musl") + refute(x86_linux_musl === x86_linux_gnu, "linux-musl =~ linux-gnu") + + # explicit libc differ + refute(x86_linux_uclibc === x86_linux_musl, "linux-uclibc =~ linux-musl") + refute(x86_linux_musl === x86_linux_uclibc, "linux-musl =~ linux-uclibc") + + # musl host runtime accepts libc-generic or statically linked gems... + assert(x86_linux === x86_linux_musl, "linux =~ linux-musl") + # ...but implicit gnu runtime generally does not accept musl-specific gems + refute(x86_linux_musl === x86_linux, "linux-musl =~ linux") + + # other libc are not glibc compatible + refute(x86_linux === x86_linux_uclibc, "linux =~ linux-uclibc") + refute(x86_linux_uclibc === x86_linux, "linux-uclibc =~ linux") + end + + def test_eabi_version_is_stricter_for_linux_os + arm_linux_eabi = Gem::Platform.new "arm-linux-eabi" + arm_linux_gnueabi = Gem::Platform.new "arm-linux-gnueabi" + arm_linux_musleabi = Gem::Platform.new "arm-linux-musleabi" + arm_linux_uclibceabi = Gem::Platform.new "arm-linux-uclibceabi" + + # a naked linux runtime is implicit gnu, as it represents the common glibc-linked runtime + assert(arm_linux_eabi === arm_linux_gnueabi, "linux-eabi =~ linux-gnueabi") + assert(arm_linux_gnueabi === arm_linux_eabi, "linux-gnueabi =~ linux-eabi") + + # musl and explicit gnu should differ + refute(arm_linux_gnueabi === arm_linux_musleabi, "linux-gnueabi =~ linux-musleabi") + refute(arm_linux_musleabi === arm_linux_gnueabi, "linux-musleabi =~ linux-gnueabi") + + # explicit libc differ + refute(arm_linux_uclibceabi === arm_linux_musleabi, "linux-uclibceabi =~ linux-musleabi") + refute(arm_linux_musleabi === arm_linux_uclibceabi, "linux-musleabi =~ linux-uclibceabi") + + # musl host runtime accepts libc-generic or statically linked gems... + assert(arm_linux_eabi === arm_linux_musleabi, "linux-eabi =~ linux-musleabi") + # ...but implicit gnu runtime generally does not accept musl-specific gems + refute(arm_linux_musleabi === arm_linux_eabi, "linux-musleabi =~ linux-eabi") + + # other libc are not glibc compatible + refute(arm_linux_eabi === arm_linux_uclibceabi, "linux-eabi =~ linux-uclibceabi") + refute(arm_linux_uclibceabi === arm_linux_eabi, "linux-uclibceabi =~ linux-eabi") + end + + def test_eabi_and_nil_version_combination_strictness + arm_linux = Gem::Platform.new "arm-linux" + arm_linux_eabi = Gem::Platform.new "arm-linux-eabi" + arm_linux_eabihf = Gem::Platform.new "arm-linux-eabihf" + arm_linux_gnueabi = Gem::Platform.new "arm-linux-gnueabi" + arm_linux_gnueabihf = Gem::Platform.new "arm-linux-gnueabihf" + arm_linux_musleabi = Gem::Platform.new "arm-linux-musleabi" + arm_linux_musleabihf = Gem::Platform.new "arm-linux-musleabihf" + arm_linux_uclibceabi = Gem::Platform.new "arm-linux-uclibceabi" + arm_linux_uclibceabihf = Gem::Platform.new "arm-linux-uclibceabihf" + + # generic arm host runtime with eabi modifier accepts generic arm gems + assert(arm_linux === arm_linux_eabi, "arm-linux =~ arm-linux-eabi") + assert(arm_linux === arm_linux_eabihf, "arm-linux =~ arm-linux-eabihf") + + # explicit gnu arm host runtime with eabi modifier accepts generic arm gems + assert(arm_linux === arm_linux_gnueabi, "arm-linux =~ arm-linux-gnueabi") + assert(arm_linux === arm_linux_gnueabihf, "arm-linux =~ arm-linux-gnueabihf") + + # musl arm host runtime accepts libc-generic or statically linked gems... + assert(arm_linux === arm_linux_musleabi, "arm-linux =~ arm-linux-musleabi") + assert(arm_linux === arm_linux_musleabihf, "arm-linux =~ arm-linux-musleabihf") + + # other libc arm hosts are not glibc compatible + refute(arm_linux === arm_linux_uclibceabi, "arm-linux =~ arm-linux-uclibceabi") + refute(arm_linux === arm_linux_uclibceabihf, "arm-linux =~ arm-linux-uclibceabihf") + end + def test_equals3_cpu_arm arm = Gem::Platform.new "arm-linux" armv5 = Gem::Platform.new "armv5-linux" @@ -381,6 +483,15 @@ class TestGemPlatform < Gem::TestCase assert_equal 1, result.scan(/@version=/).size end + def test_gem_platform_match_with_string_argument + util_set_arch "x86_64-linux-musl" + + Gem::Deprecate.skip_during do + assert(Gem::Platform.match(Gem::Platform.new("x86_64-linux")), "should match Gem::Platform") + assert(Gem::Platform.match("x86_64-linux"), "should match String platform") + end + end + def assert_local_match(name) assert_match Gem::Platform.local, name end diff --git a/test/rubygems/test_gem_rdoc.rb b/test/rubygems/test_gem_rdoc.rb index 7a34542360..f9b1df6cd5 100644 --- a/test/rubygems/test_gem_rdoc.rb +++ b/test/rubygems/test_gem_rdoc.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require "rubygems" require_relative "helper" require "rubygems/rdoc" @@ -99,7 +100,7 @@ class TestGemRDoc < Gem::TestCase assert_equal @a.base_dir, e.directory ensure - FileUtils.chmod(0755, @a.base_dir) if File.directory?(@a.base_dir) + FileUtils.chmod(0o755, @a.base_dir) if File.directory?(@a.base_dir) end def test_ri_installed? @@ -129,7 +130,7 @@ class TestGemRDoc < Gem::TestCase assert_equal @a.doc_dir, e.directory ensure if File.exist? @a.doc_dir - FileUtils.chmod 0755, @a.doc_dir + FileUtils.chmod 0o755, @a.doc_dir FileUtils.rm_r @a.doc_dir end end diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb index d8b55a5f7a..e71b2f5ff6 100644 --- a/test/rubygems/test_gem_remote_fetcher.rb +++ b/test/rubygems/test_gem_remote_fetcher.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "webrick" @@ -28,7 +29,7 @@ require "rubygems/package" class TestGemRemoteFetcher < Gem::TestCase include Gem::DefaultUserInteraction - SERVER_DATA = <<-EOY.freeze + SERVER_DATA = <<-EOY --- !ruby/object:Gem::Cache gems: rake-0.4.11: !ruby/object:Gem::Specification @@ -161,7 +162,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_cache_update_path - uri = URI "http://example/file" + uri = Gem::URI "http://example/file" path = File.join @tempdir, "file" fetcher = util_fuck_with_fetcher "hello" @@ -175,7 +176,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_cache_update_path_with_utf8_internal_encoding with_internal_encoding("UTF-8") do - uri = URI "http://example/file" + uri = Gem::URI "http://example/file" path = File.join @tempdir, "file" data = String.new("\xC8").force_encoding(Encoding::BINARY) @@ -189,7 +190,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_cache_update_path_no_update - uri = URI "http://example/file" + uri = Gem::URI "http://example/file" path = File.join @tempdir, "file" fetcher = util_fuck_with_fetcher "hello" @@ -205,12 +206,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== fetcher = Gem::RemoteFetcher.fetcher fetcher.instance_variable_set :@test_data, data - unless blow - def fetcher.fetch_path(arg, *rest) - @test_arg = arg - @test_data - end - else + if blow def fetcher.fetch_path(arg, *rest) # OMG I'm such an ass class << self; remove_method :fetch_path; end @@ -221,6 +217,11 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== raise Gem::RemoteFetcher::FetchError.new("haha!", "") end + else + def fetcher.fetch_path(arg, *rest) + @test_arg = arg + @test_data + end end fetcher @@ -310,6 +311,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_download_local + omit "doesn't work if tempdir has +" if @tempdir.include?("+") FileUtils.mv @a1_gem, @tempdir local_path = File.join @tempdir, @a1.file_name inst = nil @@ -322,6 +324,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_download_local_space + omit "doesn't work if tempdir has +" if @tempdir.include?("+") space_path = File.join @tempdir, "space path" FileUtils.mkdir space_path FileUtils.mv @a1_gem, space_path @@ -336,9 +339,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_download_install_dir - a1_data = File.open @a1_gem, "rb" do |fp| - fp.read - end + a1_data = File.open @a1_gem, "rb", &:read fetcher = util_fuck_with_fetcher a1_data @@ -355,14 +356,19 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== assert File.exist?(a1_cache_gem) end - unless win_platform? || Process.uid.zero? # File.chmod doesn't work + unless Gem.win_platform? || Process.uid.zero? # File.chmod doesn't work def test_download_local_read_only + omit "doesn't work if tempdir has +" if @tempdir.include?("+") FileUtils.mv @a1_gem, @tempdir local_path = File.join @tempdir, @a1.file_name inst = nil - FileUtils.chmod 0555, @a1.cache_dir - FileUtils.mkdir_p File.join(Gem.user_dir, "cache") rescue nil - FileUtils.chmod 0555, File.join(Gem.user_dir, "cache") + FileUtils.chmod 0o555, @a1.cache_dir + begin + FileUtils.mkdir_p File.join(Gem.user_dir, "cache") + rescue StandardError + nil + end + FileUtils.chmod 0o555, File.join(Gem.user_dir, "cache") Dir.chdir @tempdir do inst = Gem::RemoteFetcher.fetcher @@ -371,21 +377,23 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== assert_equal(File.join(@tempdir, @a1.file_name), inst.download(@a1, local_path)) ensure - FileUtils.chmod 0755, File.join(Gem.user_dir, "cache") - FileUtils.chmod 0755, @a1.cache_dir + if local_path + FileUtils.chmod 0o755, File.join(Gem.user_dir, "cache") + FileUtils.chmod 0o755, @a1.cache_dir + end end def test_download_read_only - FileUtils.chmod 0555, @a1.cache_dir - FileUtils.chmod 0555, @gemhome + FileUtils.chmod 0o555, @a1.cache_dir + FileUtils.chmod 0o555, @gemhome fetcher = util_fuck_with_fetcher File.read(@a1_gem) fetcher.download(@a1, "http://gems.example.com") a1_cache_gem = File.join Gem.user_dir, "cache", @a1.file_name assert File.exist? a1_cache_gem ensure - FileUtils.chmod 0755, @gemhome - FileUtils.chmod 0755, @a1.cache_dir + FileUtils.chmod 0o755, @gemhome + FileUtils.chmod 0o755, @a1.cache_dir end end @@ -415,6 +423,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_download_same_file + omit "doesn't work if tempdir has +" if @tempdir.include?("+") FileUtils.mv @a1_gem, @tempdir local_path = File.join @tempdir, @a1.file_name inst = nil @@ -535,8 +544,8 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== fetcher.fetch_path url end - assert_match %r{ECONNREFUSED:.*connect\(2\) \(#{Regexp.escape url}\)\z}, - e.message + assert_match(/ECONNREFUSED:.*connect\(2\) \(#{Regexp.escape url}\)\z/, + e.message) assert_equal url, e.uri end @@ -545,7 +554,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== @fetcher = fetcher def fetcher.fetch_http(uri, mtime = nil, head = nil) - raise Timeout::Error, "timed out" + raise Gem::Timeout::Error, "timed out" end url = "http://example.com/uri" @@ -554,8 +563,8 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== fetcher.fetch_path url end - assert_match %r{Timeout::Error: timed out \(#{Regexp.escape url}\)\z}, - e.message + assert_match(/Gem::Timeout::Error: timed out \(#{Regexp.escape url}\)\z/, + e.message) assert_equal url, e.uri end @@ -573,8 +582,8 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== fetcher.fetch_path url end - assert_match %r{SocketError: getaddrinfo: nodename nor servname provided \(#{Regexp.escape url}\)\z}, - e.message + assert_match(/SocketError: getaddrinfo: nodename nor servname provided \(#{Regexp.escape url}\)\z/, + e.message) assert_equal url, e.uri end @@ -604,7 +613,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== nil end - assert_nil fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0)) + assert_nil fetcher.fetch_path(Gem::URI.parse(@gem_repo), Time.at(0)) end def test_implicit_no_proxy @@ -649,19 +658,20 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def fetcher.request(uri, request_class, last_modified = nil) url = "http://gems.example.com/redirect" - unless defined? @requested + if defined? @requested + res = Gem::Net::HTTPOK.new nil, 200, nil + def res.body + "real_path" + end + else @requested = true - res = Net::HTTPMovedPermanently.new nil, 301, nil + res = Gem::Net::HTTPMovedPermanently.new nil, 301, nil res.add_field "Location", url - res - else - res = Net::HTTPOK.new nil, 200, nil - def res.body() "real_path" end - res end + res end - data = fetcher.fetch_http URI.parse(url) + data = fetcher.fetch_http Gem::URI.parse(url) assert_equal "real_path", data end @@ -673,13 +683,13 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def fetcher.request(uri, request_class, last_modified = nil) url = "http://gems.example.com/redirect" - res = Net::HTTPMovedPermanently.new nil, 301, nil + res = Gem::Net::HTTPMovedPermanently.new nil, 301, nil res.add_field "Location", url res end e = assert_raise Gem::RemoteFetcher::FetchError do - fetcher.fetch_http URI.parse(url) + fetcher.fetch_http Gem::URI.parse(url) end assert_equal "too many redirects (#{url})", e.message @@ -691,12 +701,12 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== url = "http://gems.example.com/redirect" def fetcher.request(uri, request_class, last_modified = nil) - res = Net::HTTPMovedPermanently.new nil, 301, nil + res = Gem::Net::HTTPMovedPermanently.new nil, 301, nil res end e = assert_raise Gem::RemoteFetcher::FetchError do - fetcher.fetch_http URI.parse(url) + fetcher.fetch_http Gem::URI.parse(url) end assert_equal "redirecting but no redirect location was given (#{url})", e.message @@ -704,7 +714,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_fetch_http_with_additional_headers ENV["http_proxy"] = @proxy_uri - ENV["no_proxy"] = URI::parse(@server_uri).host + ENV["no_proxy"] = Gem::URI.parse(@server_uri).host fetcher = Gem::RemoteFetcher.new nil, nil, { "X-Captain" => "murphy" } @fetcher = fetcher assert_equal "murphy", fetcher.fetch_path(@server_uri) @@ -718,8 +728,10 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def fetcher.request(uri, request_class, last_modified = nil) $fetched_uri = uri - res = Net::HTTPOK.new nil, 200, nil - def res.body() "success" end + res = Gem::Net::HTTPOK.new nil, 200, nil + def res.body + "success" + end res end @@ -735,7 +747,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== s3_uri_signer end - data = fetcher.fetch_s3 URI.parse(url) + data = fetcher.fetch_s3 Gem::URI.parse(url) assert_equal "https://my-bucket.s3.#{region}.amazonaws.com/gems/specs.4.8.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=testuser%2F20190624%2F#{region}%2Fs3%2Faws4_request&X-Amz-Date=20190624T050641Z&X-Amz-Expires=86400#{token ? "&X-Amz-Security-Token=" + token : ""}&X-Amz-SignedHeaders=host&X-Amz-Signature=#{signature}", $fetched_uri.to_s assert_equal "success", data @@ -745,10 +757,10 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_fetch_s3_config_creds Gem.configuration[:s3_source] = { - "my-bucket" => { :id => "testuser", :secret => "testpass" }, + "my-bucket" => { id: "testuser", secret: "testpass" }, } url = "s3://my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b" end ensure @@ -757,10 +769,10 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_fetch_s3_config_creds_with_region Gem.configuration[:s3_source] = { - "my-bucket" => { :id => "testuser", :secret => "testpass", :region => "us-west-2" }, + "my-bucket" => { id: "testuser", secret: "testpass", region: "us-west-2" }, } url = "s3://my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9", nil, "us-west-2" end ensure @@ -769,10 +781,10 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_fetch_s3_config_creds_with_token Gem.configuration[:s3_source] = { - "my-bucket" => { :id => "testuser", :secret => "testpass", :security_token => "testtoken" }, + "my-bucket" => { id: "testuser", secret: "testpass", security_token: "testtoken" }, } url = "s3://my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c", "testtoken" end ensure @@ -784,10 +796,10 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== ENV["AWS_SECRET_ACCESS_KEY"] = "testpass" ENV["AWS_SESSION_TOKEN"] = nil Gem.configuration[:s3_source] = { - "my-bucket" => { :provider => "env" }, + "my-bucket" => { provider: "env" }, } url = "s3://my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b" end ensure @@ -800,10 +812,10 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== ENV["AWS_SECRET_ACCESS_KEY"] = "testpass" ENV["AWS_SESSION_TOKEN"] = nil Gem.configuration[:s3_source] = { - "my-bucket" => { :provider => "env", :region => "us-west-2" }, + "my-bucket" => { provider: "env", region: "us-west-2" }, } url = "s3://my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9", nil, "us-west-2" end ensure @@ -816,10 +828,10 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== ENV["AWS_SECRET_ACCESS_KEY"] = "testpass" ENV["AWS_SESSION_TOKEN"] = "testtoken" Gem.configuration[:s3_source] = { - "my-bucket" => { :provider => "env" }, + "my-bucket" => { provider: "env" }, } url = "s3://my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c", "testtoken" end ensure @@ -829,18 +841,18 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_fetch_s3_url_creds url = "s3://testuser:testpass@my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b" end end def test_fetch_s3_instance_profile_creds Gem.configuration[:s3_source] = { - "my-bucket" => { :provider => "instance_profile" }, + "my-bucket" => { provider: "instance_profile" }, } url = "s3://my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b", nil, "us-east-1", '{"AccessKeyId": "testuser", "SecretAccessKey": "testpass"}' end @@ -850,11 +862,11 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_fetch_s3_instance_profile_creds_with_region Gem.configuration[:s3_source] = { - "my-bucket" => { :provider => "instance_profile", :region => "us-west-2" }, + "my-bucket" => { provider: "instance_profile", region: "us-west-2" }, } url = "s3://my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9", nil, "us-west-2", '{"AccessKeyId": "testuser", "SecretAccessKey": "testpass"}' end @@ -864,11 +876,11 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_fetch_s3_instance_profile_creds_with_token Gem.configuration[:s3_source] = { - "my-bucket" => { :provider => "instance_profile" }, + "my-bucket" => { provider: "instance_profile" }, } url = "s3://my-bucket/gems/specs.4.8.gz" - Time.stub :now, Time.at(1561353581) do + Time.stub :now, Time.at(1_561_353_581) do assert_fetch_s3 url, "935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c", "testtoken", "us-east-1", '{"AccessKeyId": "testuser", "SecretAccessKey": "testpass", "Token": "testtoken"}' end @@ -881,7 +893,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== @fetcher = fetcher e = assert_raise Gem::RemoteFetcher::FetchError do - fetcher.fetch_s3 URI.parse(url) + fetcher.fetch_s3 Gem::URI.parse(url) end assert_match expected_message, e.message @@ -894,7 +906,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_fetch_s3_no_host Gem.configuration[:s3_source] = { - "my-bucket" => { :id => "testuser", :secret => "testpass" }, + "my-bucket" => { id: "testuser", secret: "testpass" }, } url = "s3://other-bucket/gems/specs.4.8.gz" @@ -904,7 +916,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_fetch_s3_no_id - Gem.configuration[:s3_source] = { "my-bucket" => { :secret => "testpass" } } + Gem.configuration[:s3_source] = { "my-bucket" => { secret: "testpass" } } url = "s3://my-bucket/gems/specs.4.8.gz" refute_fetch_s3 url, "s3_source for my-bucket missing id or secret" @@ -913,7 +925,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_fetch_s3_no_secret - Gem.configuration[:s3_source] = { "my-bucket" => { :id => "testuser" } } + Gem.configuration[:s3_source] = { "my-bucket" => { id: "testuser" } } url = "s3://my-bucket/gems/specs.4.8.gz" refute_fetch_s3 url, "s3_source for my-bucket missing id or secret" @@ -924,7 +936,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_observe_no_proxy_env_single_host use_ui @stub_ui do ENV["http_proxy"] = @proxy_uri - ENV["no_proxy"] = URI::parse(@server_uri).host + ENV["no_proxy"] = Gem::URI.parse(@server_uri).host fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher assert_data_from_server fetcher.fetch_path(@server_uri) @@ -934,7 +946,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def test_observe_no_proxy_env_list use_ui @stub_ui do ENV["http_proxy"] = @proxy_uri - ENV["no_proxy"] = "fakeurl.com, #{URI::parse(@server_uri).host}" + ENV["no_proxy"] = "fakeurl.com, #{Gem::URI.parse(@server_uri).host}" fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher assert_data_from_server fetcher.fetch_path(@server_uri) @@ -946,8 +958,8 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== @fetcher = fetcher assert_throws :block_called do - fetcher.request URI("http://example"), Net::HTTP::Get do |req| - assert_kind_of Net::HTTPGenericRequest, req + fetcher.request Gem::URI("http://example"), Gem::Net::HTTP::Get do |req| + assert_kind_of Gem::Net::HTTPGenericRequest, req throw :block_called end end @@ -971,31 +983,33 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_ssl_client_cert_auth_connection - ssl_server = start_ssl_server({ - :SSLVerifyClient => - OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT }) + ssl_server = start_ssl_server( + { SSLVerifyClient: OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT } + ) temp_ca_cert = File.join(__dir__, "ca_cert.pem") temp_client_cert = File.join(__dir__, "client.pem") with_configured_fetcher( - ":ssl_ca_cert: #{temp_ca_cert}\n" + - ":ssl_client_cert: #{temp_client_cert}\n") do |fetcher| + ":ssl_ca_cert: #{temp_ca_cert}\n" \ + ":ssl_client_cert: #{temp_client_cert}\n" + ) do |fetcher| fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml") end end def test_do_not_allow_invalid_client_cert_auth_connection - ssl_server = start_ssl_server({ - :SSLVerifyClient => - OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT }) + ssl_server = start_ssl_server( + { SSLVerifyClient: OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT } + ) temp_ca_cert = File.join(__dir__, "ca_cert.pem") temp_client_cert = File.join(__dir__, "invalid_client.pem") with_configured_fetcher( - ":ssl_ca_cert: #{temp_ca_cert}\n" + - ":ssl_client_cert: #{temp_client_cert}\n") do |fetcher| + ":ssl_ca_cert: #{temp_ca_cert}\n" \ + ":ssl_client_cert: #{temp_client_cert}\n" + ) do |fetcher| assert_raise Gem::RemoteFetcher::FetchError do fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml") end @@ -1080,7 +1094,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end class NilLog < WEBrick::Log - def log(level, data) #Do nothing + def log(level, data) # Do nothing end end @@ -1115,8 +1129,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== @ssl_server_thread.kill.join @ssl_server_thread = nil end - utils = WEBrick::Utils # TimeoutHandler is since 1.9 - utils::TimeoutHandler.terminate if defined?(utils::TimeoutHandler.terminate) + WEBrick::Utils::TimeoutHandler.terminate end def normal_server_port @@ -1132,17 +1145,17 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== null_logger = NilLog.new server = WEBrick::HTTPServer.new({ - :Port => 0, - :Logger => null_logger, - :AccessLog => [], - :SSLEnable => true, - :SSLCACertificateFile => File.join(__dir__, "ca_cert.pem"), - :SSLCertificate => cert("ssl_cert.pem"), - :SSLPrivateKey => key("ssl_key.pem"), - :SSLVerifyClient => nil, - :SSLCertName => nil, + Port: 0, + Logger: null_logger, + AccessLog: [], + SSLEnable: true, + SSLCACertificateFile: File.join(__dir__, "ca_cert.pem"), + SSLCertificate: cert("ssl_cert.pem"), + SSLPrivateKey: key("ssl_key.pem"), + SSLVerifyClient: nil, + SSLCertName: nil, }.merge(config)) - server.mount_proc("/yaml") do |req, res| + server.mount_proc("/yaml") do |_req, res| res.body = "--- true\n" end server.mount_proc("/insecure_redirect") do |req, res| @@ -1150,14 +1163,12 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end server.ssl_context.tmp_dh_callback = proc { TEST_KEY_DH2048 } t = Thread.new do - begin - server.start - rescue Exception => ex - puts "ERROR during server thread: #{ex.message}" - raise - ensure - server.shutdown - end + server.start + rescue StandardError => ex + puts "ERROR during server thread: #{ex.message}" + raise + ensure + server.shutdown end while server.status != :Running sleep 0.1 @@ -1174,12 +1185,12 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== def start_server(data) null_logger = NilLog.new s = WEBrick::HTTPServer.new( - :Port => 0, - :DocumentRoot => nil, - :Logger => null_logger, - :AccessLog => null_logger + Port: 0, + DocumentRoot: nil, + Logger: null_logger, + AccessLog: null_logger ) - s.mount_proc("/kill") {|req, res| s.shutdown } + s.mount_proc("/kill") {|_req, _res| s.shutdown } s.mount_proc("/yaml") do |req, res| if req["X-Captain"] res.body = req["X-Captain"] @@ -1193,7 +1204,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== res["Content-Type"] = "text/html" end end - s.mount_proc("/yaml.Z") do |req, res| + s.mount_proc("/yaml.Z") do |_req, res| if @enable_zip res.body = Zlib::Deflate.deflate(data) res["Content-Type"] = "text/plain" @@ -1204,13 +1215,11 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end end th = Thread.new do - begin - s.start - rescue Exception => ex - abort "ERROR during server thread: #{ex.message}" - ensure - s.shutdown - end + s.start + rescue StandardError => ex + abort "ERROR during server thread: #{ex.message}" + ensure + s.shutdown end th[:server] = s th diff --git a/test/rubygems/test_gem_request.rb b/test/rubygems/test_gem_request.rb index aba9dc5447..5e9b264dac 100644 --- a/test/rubygems/test_gem_request.rb +++ b/test/rubygems/test_gem_request.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/request" require "ostruct" -require "base64" unless Gem::HAVE_OPENSSL warn "Skipping Gem::Request tests. openssl not found." @@ -20,6 +20,12 @@ class TestGemRequest < Gem::TestCase Gem::Request.create_with_proxy uri, request_class, last_modified, proxy end + # This method is same code as Base64.encode64 + # We should not use Base64.encode64 because we need to avoid gem activation. + def base64_encode64(bin) + [bin].pack("m") + end + def setup @proxies = %w[http_proxy https_proxy HTTP_PROXY http_proxy_user HTTP_PROXY_USER http_proxy_pass HTTP_PROXY_PASS no_proxy NO_PROXY] @old_proxies = @proxies.map {|k| ENV[k] } @@ -28,7 +34,7 @@ class TestGemRequest < Gem::TestCase super @proxy_uri = "http://localhost:1234" - @uri = URI("http://example") + @uri = Gem::URI("http://example") @request = make_request @uri, nil, nil, nil end @@ -50,7 +56,7 @@ class TestGemRequest < Gem::TestCase def test_initialize_proxy_URI proxy_uri = "http://proxy.example.com" - request = make_request @uri, nil, nil, URI(proxy_uri) + request = make_request @uri, nil, nil, Gem::URI(proxy_uri) assert_equal proxy_uri, request.proxy_uri.to_s end @@ -71,18 +77,18 @@ class TestGemRequest < Gem::TestCase def test_initialize_proxy_ENV_https ENV["https_proxy"] = @proxy_uri - request = make_request URI("https://example"), nil, nil, nil + request = make_request Gem::URI("https://example"), nil, nil, nil proxy = request.proxy_uri - assert_equal URI(@proxy_uri), proxy + assert_equal Gem::URI(@proxy_uri), proxy end def test_proxy_ENV ENV["http_proxy"] = "http://proxy" ENV["https_proxy"] = "" - request = make_request URI("https://example"), nil, nil, nil + request = make_request Gem::URI("https://example"), nil, nil, nil proxy = request.proxy_uri @@ -90,13 +96,13 @@ class TestGemRequest < Gem::TestCase end def test_configure_connection_for_https - connection = Net::HTTP.new "localhost", 443 + connection = Gem::Net::HTTP.new "localhost", 443 request = Class.new(Gem::Request) do def self.get_cert_files [TestGemRequest::PUBLIC_CERT_FILE] end - end.create_with_proxy URI("https://example"), nil, nil, nil + end.create_with_proxy Gem::URI("https://example"), nil, nil, nil Gem::Request.configure_connection_for_https connection, request.cert_files @@ -106,16 +112,16 @@ class TestGemRequest < Gem::TestCase end def test_configure_connection_for_https_ssl_ca_cert - ssl_ca_cert, Gem.configuration.ssl_ca_cert = - Gem.configuration.ssl_ca_cert, CA_CERT_FILE + ssl_ca_cert = Gem.configuration.ssl_ca_cert + Gem.configuration.ssl_ca_cert = CA_CERT_FILE - connection = Net::HTTP.new "localhost", 443 + connection = Gem::Net::HTTP.new "localhost", 443 request = Class.new(Gem::Request) do def self.get_cert_files [TestGemRequest::PUBLIC_CERT_FILE] end - end.create_with_proxy URI("https://example"), nil, nil, nil + end.create_with_proxy Gem::URI("https://example"), nil, nil, nil Gem::Request.configure_connection_for_https connection, request.cert_files @@ -132,17 +138,17 @@ class TestGemRequest < Gem::TestCase request = make_request @uri, nil, nil, nil proxy = request.proxy_uri - assert_equal URI(@proxy_uri), proxy + assert_equal Gem::URI(@proxy_uri), proxy end def test_get_proxy_from_env_https ENV["https_proxy"] = @proxy_uri - uri = URI("https://example") + uri = Gem::URI("https://example") request = make_request uri, nil, nil, nil proxy = request.proxy_uri - assert_equal URI(@proxy_uri), proxy + assert_equal Gem::URI(@proxy_uri), proxy end def test_get_proxy_from_env_domain @@ -185,9 +191,9 @@ class TestGemRequest < Gem::TestCase end def test_fetch - uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}") - response = util_stub_net_http(:body => :junk, :code => 200) do - @request = make_request(uri, Net::HTTP::Get, nil, nil) + uri = Gem::Uri.new(Gem::URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}")) + response = util_stub_net_http(body: :junk, code: 200) do + @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil) @request.fetch end @@ -198,58 +204,58 @@ class TestGemRequest < Gem::TestCase def test_fetch_basic_auth Gem.configuration.verbose = :really - uri = Gem::Uri.new(URI.parse "https://user:pass@example.rubygems/specs.#{Gem.marshal_version}") - conn = util_stub_net_http(:body => :junk, :code => 200) do |c| + uri = Gem::Uri.new(Gem::URI.parse("https://user:pass@example.rubygems/specs.#{Gem.marshal_version}")) + conn = util_stub_net_http(body: :junk, code: 200) do |c| use_ui @ui do - @request = make_request(uri, Net::HTTP::Get, nil, nil) + @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil) @request.fetch end c end auth_header = conn.payload["Authorization"] - assert_equal "Basic #{Base64.encode64('user:pass')}".strip, auth_header + assert_equal "Basic #{base64_encode64("user:pass")}".strip, auth_header assert_includes @ui.output, "GET https://user:REDACTED@example.rubygems/specs.#{Gem.marshal_version}" end def test_fetch_basic_auth_encoded Gem.configuration.verbose = :really - uri = Gem::Uri.new(URI.parse "https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}") + uri = Gem::Uri.new(Gem::URI.parse("https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}")) - conn = util_stub_net_http(:body => :junk, :code => 200) do |c| + conn = util_stub_net_http(body: :junk, code: 200) do |c| use_ui @ui do - @request = make_request(uri, Net::HTTP::Get, nil, nil) + @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil) @request.fetch end c end auth_header = conn.payload["Authorization"] - assert_equal "Basic #{Base64.encode64('user:{DEScede}pass')}".strip, auth_header + assert_equal "Basic #{base64_encode64("user:{DEScede}pass")}".strip, auth_header assert_includes @ui.output, "GET https://user:REDACTED@example.rubygems/specs.#{Gem.marshal_version}" end def test_fetch_basic_oauth_encoded Gem.configuration.verbose = :really - uri = Gem::Uri.new(URI.parse "https://%7BDEScede%7Dpass:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}") + uri = Gem::Uri.new(Gem::URI.parse("https://%7BDEScede%7Dpass:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}")) - conn = util_stub_net_http(:body => :junk, :code => 200) do |c| + conn = util_stub_net_http(body: :junk, code: 200) do |c| use_ui @ui do - @request = make_request(uri, Net::HTTP::Get, nil, nil) + @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil) @request.fetch end c end auth_header = conn.payload["Authorization"] - assert_equal "Basic #{Base64.encode64('{DEScede}pass:x-oauth-basic')}".strip, auth_header + assert_equal "Basic #{base64_encode64("{DEScede}pass:x-oauth-basic")}".strip, auth_header assert_includes @ui.output, "GET https://REDACTED:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}" end def test_fetch_head - uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}") - response = util_stub_net_http(:body => "", :code => 200) do |conn| - @request = make_request(uri, Net::HTTP::Get, nil, nil) + uri = Gem::Uri.new(Gem::URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}")) + response = util_stub_net_http(body: "", code: 200) do |_conn| + @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil) @request.fetch end @@ -258,10 +264,10 @@ class TestGemRequest < Gem::TestCase end def test_fetch_unmodified - uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}") + uri = Gem::Uri.new(Gem::URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}")) t = Time.utc(2013, 1, 2, 3, 4, 5) - conn, response = util_stub_net_http(:body => "", :code => 304) do |c| - @request = make_request(uri, Net::HTTP::Get, t, nil) + conn, response = util_stub_net_http(body: "", code: 304) do |c| + @request = make_request(uri, Gem::Net::HTTP::Get, t, nil) [c, @request.fetch] end @@ -280,7 +286,7 @@ class TestGemRequest < Gem::TestCase assert_match %r{RubyGems/#{Regexp.escape Gem::VERSION}}, ua assert_match %r{ #{Regexp.escape Gem::Platform.local.to_s} }, ua assert_match %r{Ruby/#{Regexp.escape RUBY_VERSION}}, ua - assert_match %r{\(#{Regexp.escape RUBY_RELEASE_DATE} }, ua + assert_match(/\(#{Regexp.escape RUBY_RELEASE_DATE} /, ua) end def test_user_agent_engine @@ -291,7 +297,7 @@ class TestGemRequest < Gem::TestCase ua = make_request(@uri, nil, nil, nil).user_agent - assert_match %r{\) vroom}, ua + assert_match(/\) vroom/, ua) ensure util_restore_version end @@ -304,7 +310,7 @@ class TestGemRequest < Gem::TestCase ua = make_request(@uri, nil, nil, nil).user_agent - assert_match %r{\)}, ua + assert_match(/\)/, ua) ensure util_restore_version end @@ -327,7 +333,7 @@ class TestGemRequest < Gem::TestCase Object.send :remove_const, :RUBY_PATCHLEVEL Object.send :const_set, :RUBY_PATCHLEVEL, -1 - Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) + Object.send :remove_const, :RUBY_REVISION Object.send :const_set, :RUBY_REVISION, 6 ua = make_request(@uri, nil, nil, nil).user_agent @@ -338,20 +344,6 @@ class TestGemRequest < Gem::TestCase util_restore_version end - def test_user_agent_revision_missing - util_save_version - - Object.send :remove_const, :RUBY_PATCHLEVEL - Object.send :const_set, :RUBY_PATCHLEVEL, -1 - Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) - - ua = make_request(@uri, nil, nil, nil).user_agent - - assert_match %r{\(#{Regexp.escape RUBY_RELEASE_DATE}\)}, ua - ensure - util_restore_version - end - def test_verify_certificate pend if Gem.java_platform? @@ -492,21 +484,19 @@ ERROR: Certificate is an invalid CA certificate def util_restore_version Object.send :remove_const, :RUBY_ENGINE - Object.send :const_set, :RUBY_ENGINE, @orig_RUBY_ENGINE if - defined?(@orig_RUBY_ENGINE) + Object.send :const_set, :RUBY_ENGINE, @orig_ruby_engine Object.send :remove_const, :RUBY_PATCHLEVEL - Object.send :const_set, :RUBY_PATCHLEVEL, @orig_RUBY_PATCHLEVEL + Object.send :const_set, :RUBY_PATCHLEVEL, @orig_ruby_patchlevel - Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) - Object.send :const_set, :RUBY_REVISION, @orig_RUBY_REVISION if - defined?(@orig_RUBY_REVISION) + Object.send :remove_const, :RUBY_REVISION + Object.send :const_set, :RUBY_REVISION, @orig_ruby_revision end def util_save_version - @orig_RUBY_ENGINE = RUBY_ENGINE - @orig_RUBY_PATCHLEVEL = RUBY_PATCHLEVEL - @orig_RUBY_REVISION = RUBY_REVISION if defined? RUBY_REVISION + @orig_ruby_engine = RUBY_ENGINE + @orig_ruby_patchlevel = RUBY_PATCHLEVEL + @orig_ruby_revision = RUBY_REVISION end def util_stub_net_http(hash) @@ -521,7 +511,10 @@ ERROR: Certificate is an invalid CA certificate class Conn attr_accessor :payload - def new(*args); self; end + def new(*args) + self + end + def use_ssl=(bool); end def verify_callback=(setting); end def verify_mode=(setting); end diff --git a/test/rubygems/test_gem_request_connection_pools.rb b/test/rubygems/test_gem_request_connection_pools.rb index 964d5c961f..966447bff6 100644 --- a/test/rubygems/test_gem_request_connection_pools.rb +++ b/test/rubygems/test_gem_request_connection_pools.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/request" -require "timeout" +require "rubygems/vendored_timeout" class TestGemRequestConnectionPool < Gem::TestCase class FakeHttp @@ -17,7 +18,7 @@ class TestGemRequestConnectionPool < Gem::TestCase @old_client = Gem::Request::ConnectionPools.client Gem::Request::ConnectionPools.client = FakeHttp - @proxy = URI "http://proxy.example" + @proxy = Gem::URI "http://proxy.example" end def teardown @@ -48,7 +49,7 @@ class TestGemRequestConnectionPool < Gem::TestCase end def test_checkout_same_connection - uri = URI.parse("http://example/some_endpoint") + uri = Gem::URI.parse("http://example/some_endpoint") pools = Gem::Request::ConnectionPools.new nil, [] pool = pools.pool_for uri @@ -98,7 +99,7 @@ class TestGemRequestConnectionPool < Gem::TestCase def test_net_http_args pools = Gem::Request::ConnectionPools.new nil, [] - net_http_args = pools.send :net_http_args, URI("http://example"), nil + net_http_args = pools.send :net_http_args, Gem::URI("http://example"), nil assert_equal ["example", 80], net_http_args end @@ -106,7 +107,7 @@ class TestGemRequestConnectionPool < Gem::TestCase def test_net_http_args_ipv6 pools = Gem::Request::ConnectionPools.new nil, [] - net_http_args = pools.send :net_http_args, URI("http://[::1]"), nil + net_http_args = pools.send :net_http_args, Gem::URI("http://[::1]"), nil assert_equal ["::1", 80], net_http_args end @@ -114,34 +115,34 @@ class TestGemRequestConnectionPool < Gem::TestCase def test_net_http_args_proxy pools = Gem::Request::ConnectionPools.new nil, [] - net_http_args = pools.send :net_http_args, URI("http://example"), @proxy + net_http_args = pools.send :net_http_args, Gem::URI("http://example"), @proxy assert_equal ["example", 80, "proxy.example", 80, nil, nil], net_http_args end def test_net_http_args_no_proxy - orig_no_proxy, ENV["no_proxy"] = ENV["no_proxy"], "example" + orig_no_proxy = ENV["no_proxy"] + ENV["no_proxy"] = "example" pools = Gem::Request::ConnectionPools.new nil, [] - net_http_args = pools.send :net_http_args, URI("http://example"), @proxy + net_http_args = pools.send :net_http_args, Gem::URI("http://example"), @proxy assert_equal ["example", 80, nil, nil], net_http_args - ensure ENV["no_proxy"] = orig_no_proxy end def test_thread_waits_for_connection - uri = URI.parse("http://example/some_endpoint") + uri = Gem::URI.parse("http://example/some_endpoint") pools = Gem::Request::ConnectionPools.new nil, [] pool = pools.pool_for uri pool.checkout Thread.new do - assert_raise(Timeout::Error) do - Timeout.timeout(1) do + assert_raise(Gem::Timeout::Error) do + Gem::Timeout.timeout(1) do pool.checkout end end diff --git a/test/rubygems/test_gem_request_set.rb b/test/rubygems/test_gem_request_set.rb index 6d14321126..9aa244892c 100644 --- a/test/rubygems/test_gem_request_set.rb +++ b/test/rubygems/test_gem_request_set.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/request_set" @@ -7,8 +8,6 @@ class TestGemRequestSet < Gem::TestCase super Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new - - @DR = Gem::Resolver end def test_gem @@ -45,7 +44,7 @@ class TestGemRequestSet < Gem::TestCase done_installing_ran = false - Gem.done_installing do |installer, specs| + Gem.done_installing do |_installer, _specs| done_installing_ran = true end @@ -56,7 +55,7 @@ class TestGemRequestSet < Gem::TestCase io.puts 'gem "a"' io.flush - result = rs.install_from_gemdeps :gemdeps => io.path do |req, installer| + result = rs.install_from_gemdeps gemdeps: io.path do |req, _installer| installed << req.full_name end @@ -88,7 +87,7 @@ Gems to install: EXPECTED actual, _ = capture_output do - rs.install_from_gemdeps :gemdeps => io.path, :explain => true + rs.install_from_gemdeps gemdeps: io.path, explain: true end assert_equal(expected, actual) end @@ -110,11 +109,11 @@ Gems to install: end options = { - :gemdeps => "gem.deps.rb", - :install_dir => "#{@gemhome}2", + gemdeps: "gem.deps.rb", + install_dir: "#{@gemhome}2", } - rs.install_from_gemdeps options do |req, installer| + rs.install_from_gemdeps options do |req, _installer| installed << req.full_name end @@ -134,7 +133,7 @@ Gems to install: io.flush assert_raise Gem::UnsatisfiableDependencyError do - rs.install_from_gemdeps :gemdeps => io.path, :domain => :local + rs.install_from_gemdeps gemdeps: io.path, domain: :local end end @@ -172,7 +171,7 @@ DEPENDENCIES io.puts 'gem "b"' end - rs.install_from_gemdeps :gemdeps => "gem.deps.rb" do |req, installer| + rs.install_from_gemdeps gemdeps: "gem.deps.rb" do |req, _installer| installed << req.full_name end @@ -226,7 +225,7 @@ end io.puts("gemspec") end - rs.install_from_gemdeps :gemdeps => "Gemfile" do |req, installer| + rs.install_from_gemdeps gemdeps: "Gemfile" do |req, _installer| installed << req.full_name end @@ -251,7 +250,7 @@ ruby "0" io.flush - rs.install_from_gemdeps :gemdeps => io.path do |req, installer| + rs.install_from_gemdeps gemdeps: io.path do |req, _installer| installed << req.full_name end end @@ -324,7 +323,7 @@ ruby "0" res = rs.resolve StaticSet.new([a, b]) assert_equal 2, res.size - names = res.map {|s| s.full_name }.sort + names = res.map(&:full_name).sort assert_equal ["a-2", "b-2"], names @@ -343,7 +342,7 @@ ruby "0" res = rs.resolve StaticSet.new([a, b, c]) assert_equal 3, res.size - names = res.map {|s| s.full_name }.sort + names = res.map(&:full_name).sort assert_equal %w[a-1.b b-1.b c-1.1.b], names end @@ -410,12 +409,12 @@ ruby "0" res = rs.resolve assert_equal 1, res.size - names = res.map {|s| s.full_name }.sort + names = res.map(&:full_name).sort assert_equal %w[a-1], names - assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet, @DR::SourceSet], - rs.sets.map {|set| set.class } + assert_equal [Gem::Resolver::BestSet, Gem::Resolver::GitSet, Gem::Resolver::VendorSet, Gem::Resolver::SourceSet], + rs.sets.map(&:class) end def test_resolve_ignore_dependencies @@ -429,7 +428,7 @@ ruby "0" res = rs.resolve StaticSet.new([a, b]) assert_equal 1, res.size - names = res.map {|s| s.full_name }.sort + names = res.map(&:full_name).sort assert_equal %w[a-2], names end @@ -474,12 +473,12 @@ ruby "0" res = rs.resolve assert_equal 2, res.size - names = res.map {|s| s.full_name }.sort + names = res.map(&:full_name).sort assert_equal ["a-1", "b-2"], names - assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet, @DR::SourceSet], - rs.sets.map {|set| set.class } + assert_equal [Gem::Resolver::BestSet, Gem::Resolver::GitSet, Gem::Resolver::VendorSet, Gem::Resolver::SourceSet], + rs.sets.map(&:class) end def test_sorted_requests @@ -492,7 +491,7 @@ ruby "0" rs.resolve StaticSet.new([a, b, c]) - names = rs.sorted_requests.map {|s| s.full_name } + names = rs.sorted_requests.map(&:full_name) assert_equal %w[c-2 b-2 a-2], names end @@ -521,14 +520,14 @@ ruby "0" installers << installer end - assert_equal %w[b-1 a-1], reqs.map {|req| req.full_name } + assert_equal %w[b-1 a-1], reqs.map(&:full_name) assert_equal %w[b-1 a-1], installers.map {|installer| installer.spec.full_name } assert_path_exist File.join @gemhome, "specifications", "a-1.gemspec" assert_path_exist File.join @gemhome, "specifications", "b-1.gemspec" - assert_equal %w[b-1 a-1], installed.map {|s| s.full_name } + assert_equal %w[b-1 a-1], installed.map(&:full_name) assert done_installing_ran end @@ -551,7 +550,7 @@ ruby "0" assert_path_exist File.join @tempdir, "specifications", "a-1.gemspec" assert_path_exist File.join @tempdir, "specifications", "b-1.gemspec" - assert_equal %w[b-1 a-1], installed.map {|s| s.full_name } + assert_equal %w[b-1 a-1], installed.map(&:full_name) end def test_install_into_development_shallow @@ -575,15 +574,15 @@ ruby "0" rs.resolve options = { - :development => true, - :development_shallow => true, + development: true, + development_shallow: true, } installed = rs.install_into @tempdir, true, options do assert_equal @tempdir, ENV["GEM_HOME"] end - assert_equal %w[a-1 b-1], installed.map {|s| s.full_name }.sort + assert_equal %w[a-1 b-1], installed.map(&:full_name).sort end def test_sorted_requests_development_shallow @@ -608,7 +607,7 @@ ruby "0" rs.resolve StaticSet.new [a_spec, b_spec, c_spec] - assert_equal %w[b-1 a-1], rs.sorted_requests.map {|req| req.full_name } + assert_equal %w[b-1 a-1], rs.sorted_requests.map(&:full_name) end def test_tsort_each_child_development @@ -637,7 +636,7 @@ ruby "0" deps = rs.enum_for(:tsort_each_child, a_req).to_a - assert_equal %w[b], deps.map {|dep| dep.name } + assert_equal %w[b], deps.map(&:name) end def test_tsort_each_child_development_shallow diff --git a/test/rubygems/test_gem_request_set_gem_dependency_api.rb b/test/rubygems/test_gem_request_set_gem_dependency_api.rb index d1411ddc56..af32005a16 100644 --- a/test/rubygems/test_gem_request_set_gem_dependency_api.rb +++ b/test/rubygems/test_gem_request_set_gem_dependency_api.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/request_set" @@ -6,14 +7,12 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def setup super - @GDA = Gem::RequestSet::GemDependencyAPI - @set = Gem::RequestSet.new @git_set = Gem::Resolver::GitSet.new @vendor_set = Gem::Resolver::VendorSet.new - @gda = @GDA.new @set, "gem.deps.rb" + @gda = Gem::RequestSet::GemDependencyAPI.new @set, "gem.deps.rb" @gda.instance_variable_set :@git_set, @git_set @gda.instance_variable_set :@vendor_set, @vendor_set end @@ -48,7 +47,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase s.add_runtime_dependency "bar", ">= 1.6.0", "< 1.6.4" end @gda.gemspec - assert_equal %w[ foo bar ].sort, @set.dependencies.map(&:name).sort + assert_equal %w[foo bar].sort, @set.dependencies.map(&:name).sort bar = @set.dependencies.find {|d| d.name == "bar" } assert_equal [["<", Gem::Version.create("1.6.4")], [">=", Gem::Version.create("1.6.0")]], bar.requirement.requirements.sort @@ -91,11 +90,11 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_git - @gda.gem "a", :git => "git/a" + @gda.gem "a", git: "git/a" assert_equal [dep("a")], @set.dependencies - assert_equal %w[git/a master], @git_set.repositories["a"] + assert_equal ["git/a", nil], @git_set.repositories["a"] expected = { "a" => Gem::Requirement.create("!") } @@ -103,11 +102,11 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_bitbucket - @gda.gem "a", :bitbucket => "example/repository" + @gda.gem "a", bitbucket: "example/repository" assert_equal [dep("a")], @set.dependencies - assert_equal %w[https://example@bitbucket.org/example/repository.git master], + assert_equal ["https://example@bitbucket.org/example/repository.git", nil], @git_set.repositories["a"] expected = { "a" => Gem::Requirement.create("!") } @@ -116,11 +115,11 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_bitbucket_expand_path - @gda.gem "a", :bitbucket => "example" + @gda.gem "a", bitbucket: "example" assert_equal [dep("a")], @set.dependencies - assert_equal %w[https://example@bitbucket.org/example/example.git master], + assert_equal ["https://example@bitbucket.org/example/example.git", nil], @git_set.repositories["a"] expected = { "a" => Gem::Requirement.create("!") } @@ -130,7 +129,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_git_branch _, err = capture_output do - @gda.gem "a", :git => "git/a", :branch => "other", :tag => "v1" + @gda.gem "a", git: "git/a", branch: "other", tag: "v1" end expected = "Gem dependencies file gem.deps.rb includes git reference for both ref/branch and tag but only ref/branch is used." assert_match expected, err @@ -141,17 +140,17 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_git_gist - @gda.gem "a", :gist => "a" + @gda.gem "a", gist: "a" assert_equal [dep("a")], @set.dependencies - assert_equal %w[https://gist.github.com/a.git master], + assert_equal ["https://gist.github.com/a.git", nil], @git_set.repositories["a"] end def test_gem_git_ref _, err = capture_output do - @gda.gem "a", :git => "git/a", :ref => "abcd123", :branch => "other" + @gda.gem "a", git: "git/a", ref: "abcd123", branch: "other" end expected = "Gem dependencies file gem.deps.rb includes git reference for both ref and branch but only ref is used." assert_match expected, err @@ -162,16 +161,16 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_git_submodules - @gda.gem "a", :git => "git/a", :submodules => true + @gda.gem "a", git: "git/a", submodules: true assert_equal [dep("a")], @set.dependencies - assert_equal %w[git/a master], @git_set.repositories["a"] + assert_equal ["git/a", nil], @git_set.repositories["a"] assert_equal %w[git/a], @git_set.need_submodules.keys end def test_gem_git_tag - @gda.gem "a", :git => "git/a", :tag => "v1" + @gda.gem "a", git: "git/a", tag: "v1" assert_equal [dep("a")], @set.dependencies @@ -179,11 +178,11 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_github - @gda.gem "a", :github => "example/repository" + @gda.gem "a", github: "example/repository" assert_equal [dep("a")], @set.dependencies - assert_equal %w[git://github.com/example/repository.git master], + assert_equal ["https://github.com/example/repository.git", nil], @git_set.repositories["a"] expected = { "a" => Gem::Requirement.create("!") } @@ -192,11 +191,11 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_github_expand_path - @gda.gem "a", :github => "example" + @gda.gem "a", github: "example" assert_equal [dep("a")], @set.dependencies - assert_equal %w[git://github.com/example/example.git master], + assert_equal ["https://github.com/example/example.git", nil], @git_set.repositories["a"] expected = { "a" => Gem::Requirement.create("!") } @@ -205,7 +204,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_group - @gda.gem "a", :group => :test + @gda.gem "a", group: :test assert_equal [dep("a")], @set.dependencies end @@ -213,7 +212,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_group_without @gda.without_groups << :test - @gda.gem "a", :group => :test + @gda.gem "a", group: :test assert_empty @set.dependencies @@ -223,7 +222,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_groups - @gda.gem "a", :groups => [:test, :development] + @gda.gem "a", groups: [:test, :development] assert_equal [dep("a")], @set.dependencies end @@ -231,7 +230,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_path name, version, directory = vendor_gem - @gda.gem name, :path => directory + @gda.gem name, path: directory assert_equal [dep(name)], @set.dependencies @@ -245,10 +244,11 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_platforms - win_platform, Gem.win_platform = Gem.win_platform?, false + win_platform = Gem.win_platform? + Gem.win_platform = false with_engine_version "ruby", "2.0.0" do - @gda.gem "a", :platforms => :ruby + @gda.gem "a", platforms: :ruby refute_empty @set.dependencies end @@ -257,36 +257,37 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_platforms_bundler_ruby - win_platform, Gem.win_platform = Gem.win_platform?, false + win_platform = Gem.win_platform? + Gem.win_platform = false with_engine_version "ruby", "2.0.0" do set = Gem::RequestSet.new - gda = @GDA.new set, "gem.deps.rb" - gda.gem "a", :platforms => :ruby + gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb" + gda.gem "a", platforms: :ruby refute_empty set.dependencies end with_engine_version "rbx", "2.0.0" do set = Gem::RequestSet.new - gda = @GDA.new set, "gem.deps.rb" - gda.gem "a", :platforms => :ruby + gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb" + gda.gem "a", platforms: :ruby refute_empty set.dependencies end with_engine_version "truffleruby", "2.0.0" do set = Gem::RequestSet.new - gda = @GDA.new set, "gem.deps.rb" - gda.gem "a", :platforms => :ruby + gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb" + gda.gem "a", platforms: :ruby refute_empty set.dependencies end with_engine_version "jruby", "1.7.6" do set = Gem::RequestSet.new - gda = @GDA.new set, "gem.deps.rb" - gda.gem "a", :platforms => :ruby + gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb" + gda.gem "a", platforms: :ruby assert_empty set.dependencies end @@ -295,8 +296,8 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase with_engine_version "ruby", "2.0.0" do set = Gem::RequestSet.new - gda = @GDA.new set, "gem.deps.rb" - gda.gem "a", :platforms => :ruby + gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb" + gda.gem "a", platforms: :ruby assert_empty set.dependencies end @@ -306,31 +307,32 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_platforms_engine with_engine_version "jruby", "1.7.6" do - @gda.gem "a", :platforms => :mri + @gda.gem "a", platforms: :mri assert_empty @set.dependencies end with_engine_version "truffleruby", "1.2.3" do - @gda.gem "a", :platforms => :mri + @gda.gem "a", platforms: :mri assert_empty @set.dependencies end end def test_gem_platforms_maglev - win_platform, Gem.win_platform = Gem.win_platform?, false + win_platform = Gem.win_platform? + Gem.win_platform = false with_engine_version "maglev", "1.0.0" do set = Gem::RequestSet.new - gda = @GDA.new set, "gem.deps.rb" - gda.gem "a", :platforms => :ruby + gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb" + gda.gem "a", platforms: :ruby refute_empty set.dependencies set = Gem::RequestSet.new - gda = @GDA.new set, "gem.deps.rb" - gda.gem "a", :platforms => :maglev + gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb" + gda.gem "a", platforms: :maglev refute_empty set.dependencies end @@ -341,37 +343,38 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_platforms_truffleruby with_engine_version "truffleruby", "1.0.0" do set = Gem::RequestSet.new - gda = @GDA.new set, "gem.deps.rb" - gda.gem "a", :platforms => :truffleruby + gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb" + gda.gem "a", platforms: :truffleruby refute_empty set.dependencies set = Gem::RequestSet.new - gda = @GDA.new set, "gem.deps.rb" - gda.gem "a", :platforms => :maglev + gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb" + gda.gem "a", platforms: :maglev assert_empty set.dependencies end end def test_gem_platforms_multiple - win_platform, Gem.win_platform = Gem.win_platform?, false + win_platform = Gem.win_platform? + Gem.win_platform = false with_engine_version "ruby", "2.0.0" do - @gda.gem "a", :platforms => [:mswin, :jruby] + @gda.gem "a", platforms: [:mswin, :jruby] assert_empty @set.dependencies end - ensure Gem.win_platform = win_platform end def test_gem_platforms_platform - win_platform, Gem.win_platform = Gem.win_platform?, false + win_platform = Gem.win_platform? + Gem.win_platform = false with_engine_version "ruby", "2.0.0" do - @gda.gem "a", :platforms => :jruby, :platform => :ruby + @gda.gem "a", platforms: :jruby, platform: :ruby refute_empty @set.dependencies end @@ -381,7 +384,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_platforms_version with_engine_version "ruby", "2.0.0" do - @gda.gem "a", :platforms => :ruby_18 + @gda.gem "a", platforms: :ruby_18 assert_empty @set.dependencies end @@ -389,15 +392,15 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_platforms_unknown e = assert_raise ArgumentError do - @gda.gem "a", :platforms => :unknown + @gda.gem "a", platforms: :unknown end assert_equal "unknown platform :unknown", e.message end def test_gem_requires - @gda.gem "a", :require => %w[b c] - @gda.gem "d", :require => "e" + @gda.gem "a", require: %w[b c] + @gda.gem "d", require: "e" assert_equal [dep("a"), dep("d")], @set.dependencies @@ -406,7 +409,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_requires_false - @gda.gem "a", :require => false + @gda.gem "a", require: false assert_equal [dep("a")], @set.dependencies @@ -416,7 +419,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_requires_without_group @gda.without_groups << :test - @gda.gem "a", :group => :test + @gda.gem "a", group: :test assert_empty @set.dependencies @@ -444,7 +447,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase end def test_gem_requirements_options - @gda.gem "c", :git => "https://example/c.git" + @gda.gem "c", git: "https://example/c.git" assert_equal [dep("c")], @set.dependencies end @@ -452,19 +455,19 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_source_mismatch name, _, directory = vendor_gem - gda = @GDA.new @set, nil + gda = Gem::RequestSet::GemDependencyAPI.new @set, nil gda.gem name e = assert_raise ArgumentError do - gda.gem name, :path => directory + gda.gem name, path: directory end assert_equal "duplicate source path: #{directory} for gem #{name}", e.message - gda = @GDA.new @set, nil + gda = Gem::RequestSet::GemDependencyAPI.new @set, nil gda.instance_variable_set :@vendor_set, @vendor_set - gda.gem name, :path => directory + gda.gem name, path: directory e = assert_raise ArgumentError do gda.gem name @@ -477,7 +480,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase def test_gem_deps_file assert_equal "gem.deps.rb", @gda.gem_deps_file - gda = @GDA.new @set, "foo/Gemfile" + gda = Gem::RequestSet::GemDependencyAPI.new @set, "foo/Gemfile" assert_equal "Gemfile", gda.gem_deps_file end @@ -486,10 +489,10 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase groups = [] @gda.group :a do - groups = @gda.send :gem_group, "a", :group => :b, :groups => [:c, :d] + groups = @gda.send :gem_group, "a", group: :b, groups: [:c, :d] end - assert_equal [:a, :b, :c, :d], groups.sort_by {|group| group.to_s } + assert_equal [:a, :b, :c, :d], groups.sort_by(&:to_s) end def test_gemspec @@ -534,7 +537,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase @gda.without_groups << :other - @gda.gemspec :development_group => :other + @gda.gemspec development_group: :other assert_equal [dep("a", "= 1"), dep("b", "= 2")], @set.dependencies @@ -566,7 +569,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase s.add_dependency "c", 3 end - @gda.gemspec :name => "b" + @gda.gemspec name: "b" assert_equal [dep("b", "= 2"), dep("c", "= 3")], @set.dependencies end @@ -596,7 +599,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase s.add_dependency "b", 2 end - @gda.gemspec :path => "other" + @gda.gemspec path: "other" assert_equal [dep("a", "= 1"), dep("b", "= 2")], @set.dependencies end @@ -609,8 +612,8 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase assert_equal [dep("a"), dep("b")], @set.dependencies - assert_equal %w[git://example/repo.git master], @git_set.repositories["a"] - assert_equal %w[git://example/repo.git master], @git_set.repositories["b"] + assert_equal ["git://example/repo.git", nil], @git_set.repositories["a"] + assert_equal ["git://example/repo.git", nil], @git_set.repositories["b"] end def test_git_source @@ -618,9 +621,9 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase "git://example/#{repo_name}.git" end - @gda.gem "a", :example => "repo" + @gda.gem "a", example: "repo" - assert_equal %w[git://example/repo.git master], @git_set.repositories["a"] + assert_equal ["git://example/repo.git", nil], @git_set.repositories["a"] end def test_group @@ -642,7 +645,7 @@ end GEM_DEPS io.flush - gda = @GDA.new @set, io.path + gda = Gem::RequestSet::GemDependencyAPI.new @set, io.path assert_equal gda, gda.load @@ -653,7 +656,7 @@ end end def test_pin_gem_source - gda = @GDA.new @set, nil + gda = Gem::RequestSet::GemDependencyAPI.new @set, nil gda.send :pin_gem_source, "a" gda.send :pin_gem_source, "a" @@ -674,7 +677,7 @@ end end def test_platform_mswin - if win_platform? + if Gem.win_platform? util_set_arch "x86-mswin32-60" do @gda.platform :mswin do @gda.gem "a" @@ -695,9 +698,10 @@ end end def test_platform_multiple - win_platform, Gem.win_platform = Gem.win_platform?, false + win_platform = Gem.win_platform? + Gem.win_platform = false - gda = @GDA.new @set, nil + gda = Gem::RequestSet::GemDependencyAPI.new @set, nil with_engine_version "ruby", "1.8.7" do gda.platform :mri_19, :mri_20 do @@ -707,7 +711,7 @@ end assert_empty @set.dependencies - gda = @GDA.new @set, nil + gda = Gem::RequestSet::GemDependencyAPI.new @set, nil with_engine_version "ruby", "2.0.0" do gda.platform :mri_19, :mri_20 do @@ -721,7 +725,8 @@ end end def test_platform_ruby - win_platform, Gem.win_platform = Gem.win_platform?, false + win_platform = Gem.win_platform? + Gem.win_platform = false @gda.platform :ruby do @gda.gem "a" @@ -733,7 +738,7 @@ end end def test_platforms - unless win_platform? + unless Gem.win_platform? util_set_arch "i686-darwin8.10.1" do @gda.platforms :ruby do @gda.gem "a" @@ -757,19 +762,19 @@ end def test_ruby_engine with_engine_version "jruby", "1.7.6" do assert @gda.ruby RUBY_VERSION, - :engine => "jruby", :engine_version => "1.7.6" + engine: "jruby", engine_version: "1.7.6" end with_engine_version "truffleruby", "1.0.0-rc11" do assert @gda.ruby RUBY_VERSION, - :engine => "truffleruby", :engine_version => "1.0.0-rc11" + engine: "truffleruby", engine_version: "1.0.0-rc11" end end def test_ruby_engine_mismatch_engine with_engine_version "ruby", "2.0.0" do e = assert_raise Gem::RubyVersionMismatch do - @gda.ruby RUBY_VERSION, :engine => "jruby", :engine_version => "1.7.4" + @gda.ruby RUBY_VERSION, engine: "jruby", engine_version: "1.7.4" end assert_equal "Your Ruby engine is ruby, but your gem.deps.rb requires jruby", @@ -780,7 +785,7 @@ end def test_ruby_engine_mismatch_version with_engine_version "jruby", "1.7.6" do e = assert_raise Gem::RubyVersionMismatch do - @gda.ruby RUBY_VERSION, :engine => "jruby", :engine_version => "1.7.4" + @gda.ruby RUBY_VERSION, engine: "jruby", engine_version: "1.7.4" end assert_equal "Your Ruby engine version is jruby 1.7.6, but your gem.deps.rb requires jruby 1.7.4", @@ -790,7 +795,7 @@ end def test_ruby_engine_no_engine_version e = assert_raise ArgumentError do - @gda.ruby RUBY_VERSION, :engine => "jruby" + @gda.ruby RUBY_VERSION, engine: "jruby" end assert_equal "You must specify engine_version along with the Ruby engine", diff --git a/test/rubygems/test_gem_request_set_lockfile.rb b/test/rubygems/test_gem_request_set_lockfile.rb index 30dcbbbfdc..83f5002508 100644 --- a/test/rubygems/test_gem_request_set_lockfile.rb +++ b/test/rubygems/test_gem_request_set_lockfile.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/request_set" require "rubygems/request_set/lockfile" diff --git a/test/rubygems/test_gem_request_set_lockfile_parser.rb b/test/rubygems/test_gem_request_set_lockfile_parser.rb index 757c764dc1..253a59b243 100644 --- a/test/rubygems/test_gem_request_set_lockfile_parser.rb +++ b/test/rubygems/test_gem_request_set_lockfile_parser.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/request_set" require "rubygems/request_set/lockfile" @@ -93,7 +94,7 @@ DEPENDENCIES assert lockfile_set, "could not find a LockSet" - assert_equal %w[a-2], lockfile_set.specs.map {|tuple| tuple.full_name } + assert_equal %w[a-2], lockfile_set.specs.map(&:full_name) end def test_parse_dependencies @@ -123,7 +124,7 @@ DEPENDENCIES assert lockfile_set, "could not find a LockSet" - assert_equal %w[a-2], lockfile_set.specs.map {|tuple| tuple.full_name } + assert_equal %w[a-2], lockfile_set.specs.map(&:full_name) end def test_parse_DEPENDENCIES_git @@ -217,7 +218,7 @@ DEPENDENCIES assert lockfile_set, "found a LockSet" - assert_equal %w[a-2], lockfile_set.specs.map {|s| s.full_name } + assert_equal %w[a-2], lockfile_set.specs.map(&:full_name) end def test_parse_GEM_remote_multiple @@ -245,7 +246,7 @@ DEPENDENCIES assert lockfile_set, "found a LockSet" - assert_equal %w[a-2], lockfile_set.specs.map {|s| s.full_name } + assert_equal %w[a-2], lockfile_set.specs.map(&:full_name) assert_equal %w[https://gems.example/ https://other.example/], lockfile_set.specs.flat_map {|s| s.sources.map {|src| src.uri.to_s } } @@ -257,7 +258,7 @@ DEPENDENCIES write_lockfile <<-LOCKFILE GIT remote: git://example/a.git - revision: master + revision: abranch specs: a (2) b (>= 3) @@ -275,7 +276,7 @@ DEPENDENCIES Gem::Resolver::LockSet === set end - refute lockfile_set, "fount a LockSet" + refute lockfile_set, "found a LockSet" git_set = @set.sets.find do |set| Gem::Resolver::GitSet === set @@ -283,13 +284,13 @@ DEPENDENCIES assert git_set, "could not find a GitSet" - assert_equal %w[a-2], git_set.specs.values.map {|s| s.full_name } + assert_equal %w[a-2], git_set.specs.values.map(&:full_name) assert_equal [dep("b", ">= 3"), dep("c")], git_set.specs.values.first.dependencies expected = { - "a" => %w[git://example/a.git master], + "a" => %w[git://example/a.git abranch], } assert_equal expected, git_set.repositories @@ -318,7 +319,7 @@ DEPENDENCIES Gem::Resolver::LockSet === set end - refute lockfile_set, "fount a LockSet" + refute lockfile_set, "found a LockSet" git_set = @set.sets.find do |set| Gem::Resolver::GitSet === set @@ -355,7 +356,7 @@ DEPENDENCIES Gem::Resolver::LockSet === set end - refute lockfile_set, "fount a LockSet" + refute lockfile_set, "found a LockSet" git_set = @set.sets.find do |set| Gem::Resolver::GitSet === set @@ -392,7 +393,7 @@ DEPENDENCIES Gem::Resolver::LockSet === set end - refute lockfile_set, "fount a LockSet" + refute lockfile_set, "found a LockSet" git_set = @set.sets.find do |set| Gem::Resolver::GitSet === set @@ -437,7 +438,7 @@ DEPENDENCIES assert vendor_set, "could not find a VendorSet" - assert_equal %w[a-1], vendor_set.specs.values.map {|s| s.full_name } + assert_equal %w[a-1], vendor_set.specs.values.map(&:full_name) spec = vendor_set.load_spec "a", nil, nil, nil @@ -496,14 +497,14 @@ DEPENDENCIES assert lockfile_set, "could not find a LockSet" - assert_equal %w[a-2 b-3], lockfile_set.specs.map {|tuple| tuple.full_name } + assert_equal %w[a-2 b-3], lockfile_set.specs.map(&:full_name) expected = [ Gem::Platform::RUBY, Gem::Platform.new("x86_64-linux"), ] - assert_equal expected, lockfile_set.specs.map {|tuple| tuple.platform } + assert_equal expected, lockfile_set.specs.map(&:platform) spec = lockfile_set.specs.first diff --git a/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb b/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb index 8db180eb27..dce8c9ada5 100644 --- a/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +++ b/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/request_set" require "rubygems/request_set/lockfile" diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 29bb264454..de0d11ec00 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/requirement" @@ -11,6 +12,14 @@ class TestGemRequirement < Gem::TestCase assert_equal [[">=", v(1)], ["<", v(2)]], r.requirements end + def test_initialize_copy + r = req("= 1.2") + r2 = r.dup + + assert_equal r.requirements, r2.requirements + refute_same r.requirements, r2.requirements + end + def test_equals2 r = req "= 1.2" assert_equal r, r.dup @@ -83,7 +92,7 @@ class TestGemRequirement < Gem::TestCase Gem::Requirement.parse(Gem::Version.new("2")) end - if RUBY_VERSION >= "2.5" && !(Gem.java_platform? && ENV["JRUBY_OPTS"].to_s.include?("--debug")) + unless Gem.java_platform? && ENV["JRUBY_OPTS"].to_s.include?("--debug") def test_parse_deduplication assert_same "~>", Gem::Requirement.parse("~> 1").first end @@ -286,7 +295,7 @@ class TestGemRequirement < Gem::TestCase end def test_illformed_requirements - [ ">>> 1.3.5", "> blah" ].each do |rq| + [">>> 1.3.5", "> blah"].each do |rq| assert_raise Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do Gem::Requirement.new rq end @@ -436,19 +445,19 @@ class TestGemRequirement < Gem::TestCase end def test_marshal_load_attack - wa = Net::WriteAdapter.allocate + wa = Gem::Net::WriteAdapter.allocate wa.instance_variable_set(:@socket, self.class) wa.instance_variable_set(:@method_id, :exploit) request_set = Gem::RequestSet.allocate request_set.instance_variable_set(:@git_set, "id") request_set.instance_variable_set(:@sets, wa) - wa = Net::WriteAdapter.allocate + wa = Gem::Net::WriteAdapter.allocate wa.instance_variable_set(:@socket, request_set) wa.instance_variable_set(:@method_id, :resolve) ent = Gem::Package::TarReader::Entry.allocate ent.instance_variable_set(:@read, 0) ent.instance_variable_set(:@header, "aaa") - io = Net::BufferedIO.allocate + io = Gem::Net::BufferedIO.allocate io.instance_variable_set(:@io, ent) io.instance_variable_set(:@debug_output, wa) reader = Gem::Package::TarReader.allocate diff --git a/test/rubygems/test_gem_resolver.rb b/test/rubygems/test_gem_resolver.rb index 2271244729..b7dadda708 100644 --- a/test/rubygems/test_gem_resolver.rb +++ b/test/rubygems/test_gem_resolver.rb @@ -1,19 +1,14 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolver < Gem::TestCase - def setup - super - - @DR = Gem::Resolver - end - def make_dep(name, *req) Gem::Dependency.new(name, *req) end def set(*specs) - source = Gem::Source.new URI @gem_repo + source = Gem::Source.new Gem::URI @gem_repo specs = specs.map do |spec| Gem::Resolver::SpecSpecification.new nil, spec, source @@ -25,10 +20,10 @@ class TestGemResolver < Gem::TestCase def assert_resolves_to(expected, resolver) actual = resolver.resolve - exp = expected.sort_by {|s| s.full_name } - act = actual.map {|a| a.spec.spec }.sort_by {|s| s.full_name } + exp = expected.sort_by(&:full_name) + act = actual.map {|a| a.spec.spec }.sort_by(&:full_name) - msg = "Set of gems was not the same: #{exp.map {|x| x.full_name }.inspect} != #{act.map {|x| x.full_name }.inspect}" + msg = "Set of gems was not the same: #{exp.map(&:full_name).inspect} != #{act.map(&:full_name).inspect}" assert_equal exp, act, msg rescue Gem::DependencyResolutionError => e @@ -36,18 +31,18 @@ class TestGemResolver < Gem::TestCase end def test_self_compose_sets_best_set - best_set = @DR::BestSet.new + best_set = Gem::Resolver::BestSet.new - composed = @DR.compose_sets best_set + composed = Gem::Resolver.compose_sets best_set assert_equal best_set, composed end def test_self_compose_sets_multiple - index_set = @DR::IndexSet.new - vendor_set = @DR::VendorSet.new + index_set = Gem::Resolver::IndexSet.new + vendor_set = Gem::Resolver::VendorSet.new - composed = @DR.compose_sets index_set, vendor_set + composed = Gem::Resolver.compose_sets index_set, vendor_set assert_kind_of Gem::Resolver::ComposedSet, composed @@ -55,14 +50,14 @@ class TestGemResolver < Gem::TestCase end def test_self_compose_sets_nest - index_set = @DR::IndexSet.new - vendor_set = @DR::VendorSet.new + index_set = Gem::Resolver::IndexSet.new + vendor_set = Gem::Resolver::VendorSet.new - inner = @DR.compose_sets index_set, vendor_set + inner = Gem::Resolver.compose_sets index_set, vendor_set - current_set = @DR::CurrentSet.new + current_set = Gem::Resolver::CurrentSet.new - composed = @DR.compose_sets inner, current_set + composed = Gem::Resolver.compose_sets inner, current_set assert_kind_of Gem::Resolver::ComposedSet, composed @@ -70,23 +65,23 @@ class TestGemResolver < Gem::TestCase end def test_self_compose_sets_nil - index_set = @DR::IndexSet.new + index_set = Gem::Resolver::IndexSet.new - composed = @DR.compose_sets index_set, nil + composed = Gem::Resolver.compose_sets index_set, nil assert_same index_set, composed e = assert_raise ArgumentError do - @DR.compose_sets nil + Gem::Resolver.compose_sets nil end assert_equal "one set in the composition must be non-nil", e.message end def test_self_compose_sets_single - index_set = @DR::IndexSet.new + index_set = Gem::Resolver::IndexSet.new - composed = @DR.compose_sets index_set + composed = Gem::Resolver.compose_sets index_set assert_same index_set, composed end @@ -104,7 +99,7 @@ class TestGemResolver < Gem::TestCase res.requests a1, act, reqs - assert_equal ["b (= 2)"], reqs.map {|req| req.to_s } + assert_equal ["b (= 2)"], reqs.map(&:to_s) end def test_requests_development @@ -126,7 +121,7 @@ class TestGemResolver < Gem::TestCase res.requests spec, act, reqs - assert_equal ["b (= 2)"], reqs.map {|req| req.to_s } + assert_equal ["b (= 2)"], reqs.map(&:to_s) assert spec.instance_variable_defined? :@called end @@ -207,8 +202,8 @@ class TestGemResolver < Gem::TestCase s.add_development_dependency "b" end - b_spec = util_spec "b", 1 do - |s| s.add_development_dependency "c" + b_spec = util_spec "b", 1 do |s| + s.add_development_dependency "c" end c_spec = util_spec "c", 1 @@ -322,16 +317,15 @@ class TestGemResolver < Gem::TestCase def test_picks_best_platform is = Gem::Resolver::IndexSpecification unknown = Gem::Platform.new "unknown" - a2_p1 = a3_p2 = nil spec_fetcher do |fetcher| fetcher.spec "a", 2 - a2_p1 = fetcher.spec "a", 2 do |s| + fetcher.spec "a", 2 do |s| s.platform = Gem::Platform.local end - a3_p2 = fetcher.spec "a", 3 do |s| + fetcher.spec "a", 3 do |s| s.platform = unknown end end @@ -357,6 +351,74 @@ class TestGemResolver < Gem::TestCase assert_resolves_to [a2_p1.spec], res end + def test_does_not_pick_musl_variants_on_non_musl_linux + util_set_arch "aarch64-linux" do + is = Gem::Resolver::IndexSpecification + + linux_musl = Gem::Platform.new("aarch64-linux-musl") + + spec_fetcher do |fetcher| + fetcher.spec "libv8-node", "15.14.0.1" do |s| + s.platform = Gem::Platform.local + end + + fetcher.spec "libv8-node", "15.14.0.1" do |s| + s.platform = linux_musl + end + end + + v15 = v("15.14.0.1") + source = Gem::Source.new @gem_repo + + s = set + + v15_linux = is.new s, "libv8-node", v15, source, Gem::Platform.local.to_s + v15_linux_musl = is.new s, "libv8-node", v15, source, linux_musl.to_s + + s.add v15_linux + s.add v15_linux_musl + + ad = make_dep "libv8-node", "= 15.14.0.1" + + res = Gem::Resolver.new([ad], s) + + assert_resolves_to [v15_linux.spec], res + end + end + + def test_pick_generic_linux_variants_on_musl_linux + util_set_arch "aarch64-linux-musl" do + is = Gem::Resolver::IndexSpecification + + linux = Gem::Platform.new("aarch64-linux") + + spec_fetcher do |fetcher| + fetcher.spec "libv8-node", "15.14.0.1" do |s| + s.platform = linux + end + + fetcher.spec "libv8-node", "15.14.0.1" + end + + v15 = v("15.14.0.1") + source = Gem::Source.new @gem_repo + + s = set + + v15_ruby = is.new s, "libv8-node", v15, source, Gem::Platform::RUBY + v15_linux = is.new s, "libv8-node", v15, source, linux.to_s + + s.add v15_linux + s.add v15_ruby + + ad = make_dep "libv8-node", "= 15.14.0.1" + + res = Gem::Resolver.new([ad], s) + + assert_resolves_to [v15_linux.spec], res + end + end + def test_only_returns_spec_once a1 = util_spec "a", "1", "c" => "= 1" b1 = util_spec "b", "1", "c" => "= 1" @@ -711,29 +773,29 @@ class TestGemResolver < Gem::TestCase end def test_sorts_by_source_then_version - sourceA = Gem::Source.new "http://example.com/a" - sourceB = Gem::Source.new "http://example.com/b" - sourceC = Gem::Source.new "http://example.com/c" + source_a = Gem::Source.new "http://example.com/a" + source_b = Gem::Source.new "http://example.com/b" + source_c = Gem::Source.new "http://example.com/c" - spec_A_1 = util_spec "some-dep", "0.0.1" - spec_A_2 = util_spec "some-dep", "1.0.0" - spec_B_1 = util_spec "some-dep", "0.0.1" - spec_B_2 = util_spec "some-dep", "0.0.2" - spec_C_1 = util_spec "some-dep", "0.1.0" + spec_a_1 = util_spec "some-dep", "0.0.1" + spec_a_2 = util_spec "some-dep", "1.0.0" + spec_b_1 = util_spec "some-dep", "0.0.1" + spec_b_2 = util_spec "some-dep", "0.0.2" + spec_c_1 = util_spec "some-dep", "0.1.0" set = StaticSet.new [ - Gem::Resolver::SpecSpecification.new(nil, spec_B_1, sourceB), - Gem::Resolver::SpecSpecification.new(nil, spec_B_2, sourceB), - Gem::Resolver::SpecSpecification.new(nil, spec_C_1, sourceC), - Gem::Resolver::SpecSpecification.new(nil, spec_A_2, sourceA), - Gem::Resolver::SpecSpecification.new(nil, spec_A_1, sourceA), + Gem::Resolver::SpecSpecification.new(nil, spec_b_1, source_b), + Gem::Resolver::SpecSpecification.new(nil, spec_b_2, source_b), + Gem::Resolver::SpecSpecification.new(nil, spec_c_1, source_c), + Gem::Resolver::SpecSpecification.new(nil, spec_a_2, source_a), + Gem::Resolver::SpecSpecification.new(nil, spec_a_1, source_a), ] dependency = make_dep "some-dep", "> 0" resolver = Gem::Resolver.new [dependency], set - assert_resolves_to [spec_B_2], resolver + assert_resolves_to [spec_b_2], resolver end def test_select_local_platforms diff --git a/test/rubygems/test_gem_resolver_activation_request.rb b/test/rubygems/test_gem_resolver_activation_request.rb index 397eb1e10d..53875b72cb 100644 --- a/test/rubygems/test_gem_resolver_activation_request.rb +++ b/test/rubygems/test_gem_resolver_activation_request.rb @@ -1,28 +1,27 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverActivationRequest < Gem::TestCase def setup super - @DR = Gem::Resolver - - @dep = @DR::DependencyRequest.new dep("a", ">= 0"), nil + @dep = Gem::Resolver::DependencyRequest.new dep("a", ">= 0"), nil source = Gem::Source::Local.new platform = Gem::Platform::RUBY - @a3 = @DR::IndexSpecification.new nil, "a", v(3), source, platform + @a3 = Gem::Resolver::IndexSpecification.new nil, "a", v(3), source, platform - @req = @DR::ActivationRequest.new @a3, @dep + @req = Gem::Resolver::ActivationRequest.new @a3, @dep end def test_development_eh refute @req.development? - dep_req = @DR::DependencyRequest.new dep("a", ">= 0", :development), nil + dep_req = Gem::Resolver::DependencyRequest.new dep("a", ">= 0", :development), nil - act_req = @DR::ActivationRequest.new @a3, dep_req + act_req = Gem::Resolver::ActivationRequest.new @a3, dep_req assert act_req.development? end @@ -35,7 +34,7 @@ class TestGemResolverActivationRequest < Gem::TestCase def test_installed_eh v_spec = Gem::Resolver::VendorSpecification.new nil, @a3 - @req = @DR::ActivationRequest.new v_spec, @dep + @req = Gem::Resolver::ActivationRequest.new v_spec, @dep assert @req.installed? end diff --git a/test/rubygems/test_gem_resolver_api_set.rb b/test/rubygems/test_gem_resolver_api_set.rb index 5c13311b1b..5781cf37d2 100644 --- a/test/rubygems/test_gem_resolver_api_set.rb +++ b/test/rubygems/test_gem_resolver_api_set.rb @@ -1,55 +1,55 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverAPISet < Gem::TestCase def setup super - @DR = Gem::Resolver - @dep_uri = URI "#{@gem_repo}info/" + @dep_uri = Gem::URI "#{@gem_repo}info/" end def test_initialize - set = @DR::APISet.new + set = Gem::Resolver::APISet.new - assert_equal URI("https://index.rubygems.org/info/"), set.dep_uri - assert_equal URI("https://index.rubygems.org/"), set.uri - assert_equal Gem::Source.new(URI("https://index.rubygems.org")), set.source + assert_equal Gem::URI("https://index.rubygems.org/info/"), set.dep_uri + assert_equal Gem::URI("https://index.rubygems.org/"), set.uri + assert_equal Gem::Source.new(Gem::URI("https://index.rubygems.org")), set.source end def test_initialize_deeper_uri - set = @DR::APISet.new "https://rubygemsserver.com/mygems/info" + set = Gem::Resolver::APISet.new "https://rubygemsserver.com/mygems/info" - assert_equal URI("https://rubygemsserver.com/mygems/info"), set.dep_uri - assert_equal URI("https://rubygemsserver.com/"), set.uri - assert_equal Gem::Source.new(URI("https://rubygemsserver.com/")), set.source + assert_equal Gem::URI("https://rubygemsserver.com/mygems/info"), set.dep_uri + assert_equal Gem::URI("https://rubygemsserver.com/"), set.uri + assert_equal Gem::Source.new(Gem::URI("https://rubygemsserver.com/")), set.source end def test_initialize_uri - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri - assert_equal URI("#{@gem_repo}info/"), set.dep_uri - assert_equal URI("#{@gem_repo}"), set.uri + assert_equal Gem::URI("#{@gem_repo}info/"), set.dep_uri + assert_equal Gem::URI(@gem_repo.to_s), set.uri end def test_find_all spec_fetcher data = [ - { :name => "a", - :number => "1", - :platform => "ruby", - :dependencies => [] }, + { name: "a", + number: "1", + platform: "ruby", + dependencies: [] }, ] @fetcher.data["#{@dep_uri}a"] = "---\n1 " - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri - a_dep = @DR::DependencyRequest.new dep("a"), nil + a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil expected = [ - @DR::APISpecification.new(set, data.first), + Gem::Resolver::APISpecification.new(set, data.first), ] assert_equal expected, set.find_all(a_dep) @@ -59,26 +59,26 @@ class TestGemResolverAPISet < Gem::TestCase spec_fetcher data = [ - { :name => "a", - :number => "1", - :platform => "ruby", - :dependencies => [] }, - { :name => "a", - :number => "2.a", - :platform => "ruby", - :dependencies => [] }, + { name: "a", + number: "1", + platform: "ruby", + dependencies: [] }, + { name: "a", + number: "2.a", + platform: "ruby", + dependencies: [] }, ] @fetcher.data["#{@dep_uri}a"] = "---\n1\n2.a" - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri set.prerelease = true - a_dep = @DR::DependencyRequest.new dep("a"), nil + a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil expected = [ - @DR::APISpecification.new(set, data.first), - @DR::APISpecification.new(set, data.last), + Gem::Resolver::APISpecification.new(set, data.first), + Gem::Resolver::APISpecification.new(set, data.last), ] assert_equal expected, set.find_all(a_dep) @@ -88,22 +88,22 @@ class TestGemResolverAPISet < Gem::TestCase spec_fetcher data = [ - { :name => "a", - :number => "1", - :platform => "ruby", - :dependencies => [] }, + { name: "a", + number: "1", + platform: "ruby", + dependencies: [] }, ] @fetcher.data["#{@dep_uri}a"] = "---\n1 " - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri - a_dep = @DR::DependencyRequest.new dep("a"), nil + a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil set.prefetch [a_dep] expected = [ - @DR::APISpecification.new(set, data.first), + Gem::Resolver::APISpecification.new(set, data.first), ] assert_equal expected, set.find_all(a_dep) @@ -112,10 +112,10 @@ class TestGemResolverAPISet < Gem::TestCase end def test_find_all_local - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri set.remote = false - a_dep = @DR::DependencyRequest.new dep("a"), nil + a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil assert_empty set.find_all(a_dep) end @@ -125,9 +125,9 @@ class TestGemResolverAPISet < Gem::TestCase @fetcher.data["#{@dep_uri}a"] = "---" - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri - a_dep = @DR::DependencyRequest.new dep("a"), nil + a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil assert_empty set.find_all(a_dep) @@ -142,14 +142,14 @@ class TestGemResolverAPISet < Gem::TestCase @fetcher.data["#{@dep_uri}a"] = "---\n1 \n" @fetcher.data["#{@dep_uri}b"] = "---" - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri - a_dep = @DR::DependencyRequest.new dep("a"), nil - b_dep = @DR::DependencyRequest.new dep("b"), nil + a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil + b_dep = Gem::Resolver::DependencyRequest.new dep("b"), nil set.prefetch [a_dep, b_dep] - assert_equal %w[a-1], set.find_all(a_dep).map {|s| s.full_name } + assert_equal %w[a-1], set.find_all(a_dep).map(&:full_name) assert_empty set.find_all(b_dep) end @@ -158,10 +158,10 @@ class TestGemResolverAPISet < Gem::TestCase @fetcher.data["#{@dep_uri}a"] = "---\n1 \n" - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri - a_dep = @DR::DependencyRequest.new dep("a"), nil - b_dep = @DR::DependencyRequest.new dep("b"), nil + a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil + b_dep = Gem::Resolver::DependencyRequest.new dep("b"), nil set.prefetch [a_dep] @@ -177,10 +177,10 @@ class TestGemResolverAPISet < Gem::TestCase @fetcher.data["#{@dep_uri}a"] = "---\n1 \n" @fetcher.data["#{@dep_uri}b"] = "---" - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri - a_dep = @DR::DependencyRequest.new dep("a"), nil - b_dep = @DR::DependencyRequest.new dep("b"), nil + a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil + b_dep = Gem::Resolver::DependencyRequest.new dep("b"), nil set.prefetch [a_dep, b_dep] @@ -196,11 +196,11 @@ class TestGemResolverAPISet < Gem::TestCase @fetcher.data["#{@dep_uri}a"] = "---\n1 \n" @fetcher.data["#{@dep_uri}b"] = "---" - set = @DR::APISet.new @dep_uri + set = Gem::Resolver::APISet.new @dep_uri set.remote = false - a_dep = @DR::DependencyRequest.new dep("a"), nil - b_dep = @DR::DependencyRequest.new dep("b"), nil + a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil + b_dep = Gem::Resolver::DependencyRequest.new dep("b"), nil set.prefetch [a_dep, b_dep] diff --git a/test/rubygems/test_gem_resolver_api_specification.rb b/test/rubygems/test_gem_resolver_api_specification.rb index 98981e53e9..2119d73478 100644 --- a/test/rubygems/test_gem_resolver_api_specification.rb +++ b/test/rubygems/test_gem_resolver_api_specification.rb @@ -1,14 +1,15 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverAPISpecification < Gem::TestCase def test_initialize set = Gem::Resolver::APISet.new data = { - :name => "rails", - :number => "3.0.3", - :platform => Gem::Platform.local.to_s, - :dependencies => [ + name: "rails", + number: "3.0.3", + platform: Gem::Platform.local.to_s, + dependencies: [ ["bundler", "~> 1.0"], ["railties", "= 3.0.3"], ], @@ -44,10 +45,10 @@ class TestGemResolverAPISpecification < Gem::TestCase set = Gem::Resolver::APISet.new repo data = { - :name => "rails", - :number => "3.0.3", - :platform => "ruby", - :dependencies => [ + name: "rails", + number: "3.0.3", + platform: "ruby", + dependencies: [ ["bundler", "~> 1.0"], ["railties", "= 3.0.3"], ], @@ -71,10 +72,10 @@ class TestGemResolverAPISpecification < Gem::TestCase def test_installable_platform_eh set = Gem::Resolver::APISet.new data = { - :name => "a", - :number => "1", - :platform => "ruby", - :dependencies => [], + name: "a", + number: "1", + platform: "ruby", + dependencies: [], } a_spec = Gem::Resolver::APISpecification.new set, data @@ -82,10 +83,10 @@ class TestGemResolverAPISpecification < Gem::TestCase assert a_spec.installable_platform? data = { - :name => "b", - :number => "1", - :platform => "cpu-other_platform-1", - :dependencies => [], + name: "b", + number: "1", + platform: "cpu-other_platform-1", + dependencies: [], } b_spec = Gem::Resolver::APISpecification.new set, data @@ -93,10 +94,10 @@ class TestGemResolverAPISpecification < Gem::TestCase refute b_spec.installable_platform? data = { - :name => "c", - :number => "1", - :platform => Gem::Platform.local.to_s, - :dependencies => [], + name: "c", + number: "1", + platform: Gem::Platform.local.to_s, + dependencies: [], } c_spec = Gem::Resolver::APISpecification.new set, data @@ -107,10 +108,10 @@ class TestGemResolverAPISpecification < Gem::TestCase def test_source set = Gem::Resolver::APISet.new data = { - :name => "a", - :number => "1", - :platform => "ruby", - :dependencies => [], + name: "a", + number: "1", + platform: "ruby", + dependencies: [], } api_spec = Gem::Resolver::APISpecification.new set, data @@ -123,13 +124,13 @@ class TestGemResolverAPISpecification < Gem::TestCase fetcher.spec "a", 1 end - dep_uri = URI(@gem_repo) + "info" + dep_uri = Gem::URI(@gem_repo) + "info" set = Gem::Resolver::APISet.new dep_uri data = { - :name => "a", - :number => "1", - :platform => "ruby", - :dependencies => [], + name: "a", + number: "1", + platform: "ruby", + dependencies: [], } api_spec = Gem::Resolver::APISpecification.new set, data @@ -147,13 +148,13 @@ class TestGemResolverAPISpecification < Gem::TestCase end end - dep_uri = URI(@gem_repo) + "info" + dep_uri = Gem::URI(@gem_repo) + "info" set = Gem::Resolver::APISet.new dep_uri data = { - :name => "j", - :number => "1", - :platform => "jruby", - :dependencies => [], + name: "j", + number: "1", + platform: "jruby", + dependencies: [], } api_spec = Gem::Resolver::APISpecification.new set, data diff --git a/test/rubygems/test_gem_resolver_best_set.rb b/test/rubygems/test_gem_resolver_best_set.rb index c1c67ba832..8a750cdf8f 100644 --- a/test/rubygems/test_gem_resolver_best_set.rb +++ b/test/rubygems/test_gem_resolver_best_set.rb @@ -1,15 +1,10 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverBestSet < Gem::TestCase - def setup - super - - @DR = Gem::Resolver - end - def test_initialize - set = @DR::BestSet.new + set = Gem::Resolver::BestSet.new assert_empty set.sets end @@ -21,15 +16,15 @@ class TestGemResolverBestSet < Gem::TestCase fetcher.spec "b", 1 end - set = @DR::BestSet.new + set = Gem::Resolver::BestSet.new dependency = dep "a", "~> 1" - req = @DR::DependencyRequest.new dependency, nil + req = Gem::Resolver::DependencyRequest.new dependency, nil found = set.find_all req - assert_equal %w[a-1], found.map {|s| s.full_name } + assert_equal %w[a-1], found.map(&:full_name) end def test_find_all_fallback @@ -37,19 +32,19 @@ class TestGemResolverBestSet < Gem::TestCase fetcher.spec "a", 1 end - set = @DR::BestSet.new + set = Gem::Resolver::BestSet.new - api_uri = URI(@gem_repo) + api_uri = Gem::URI(@gem_repo) set.sets << Gem::Resolver::APISet.new(api_uri) dependency = dep "a", "~> 1" - req = @DR::DependencyRequest.new dependency, nil + req = Gem::Resolver::DependencyRequest.new dependency, nil found = set.find_all req - assert_equal %w[a-1], found.map {|s| s.full_name } + assert_equal %w[a-1], found.map(&:full_name) end def test_find_all_local @@ -59,12 +54,12 @@ class TestGemResolverBestSet < Gem::TestCase fetcher.spec "b", 1 end - set = @DR::BestSet.new + set = Gem::Resolver::BestSet.new set.remote = false dependency = dep "a", "~> 1" - req = @DR::DependencyRequest.new dependency, nil + req = Gem::Resolver::DependencyRequest.new dependency, nil found = set.find_all req @@ -76,7 +71,7 @@ class TestGemResolverBestSet < Gem::TestCase fetcher.spec "a", 1 end - set = @DR::BestSet.new + set = Gem::Resolver::BestSet.new set.prefetch [] @@ -88,7 +83,7 @@ class TestGemResolverBestSet < Gem::TestCase fetcher.spec "a", 1 end - set = @DR::BestSet.new + set = Gem::Resolver::BestSet.new set.remote = false set.prefetch [] @@ -97,9 +92,9 @@ class TestGemResolverBestSet < Gem::TestCase end def test_replace_failed_api_set - set = @DR::BestSet.new + set = Gem::Resolver::BestSet.new - api_uri = URI(@gem_repo) + "./info/" + api_uri = Gem::URI(@gem_repo) + "./info/" api_set = Gem::Resolver::APISet.new api_uri set.sets << api_set @@ -118,7 +113,7 @@ class TestGemResolverBestSet < Gem::TestCase end def test_replace_failed_api_set_no_api_set - set = @DR::BestSet.new + set = Gem::Resolver::BestSet.new index_set = Gem::Resolver::IndexSet.new Gem::Source.new @gem_repo @@ -134,9 +129,9 @@ class TestGemResolverBestSet < Gem::TestCase end def test_replace_failed_api_set_uri_with_credentials - set = @DR::BestSet.new + set = Gem::Resolver::BestSet.new - api_uri = URI(@gem_repo) + "./info/" + api_uri = Gem::URI(@gem_repo) + "./info/" api_uri.user = "user" api_uri.password = "pass" api_set = Gem::Resolver::APISet.new api_uri diff --git a/test/rubygems/test_gem_resolver_composed_set.rb b/test/rubygems/test_gem_resolver_composed_set.rb index 5feceebb34..5a53000ec7 100644 --- a/test/rubygems/test_gem_resolver_composed_set.rb +++ b/test/rubygems/test_gem_resolver_composed_set.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverComposedSet < Gem::TestCase diff --git a/test/rubygems/test_gem_resolver_conflict.rb b/test/rubygems/test_gem_resolver_conflict.rb index 8bee6699c8..5696ff266d 100644 --- a/test/rubygems/test_gem_resolver_conflict.rb +++ b/test/rubygems/test_gem_resolver_conflict.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverConflict < Gem::TestCase @@ -35,16 +36,14 @@ class TestGemResolverConflict < Gem::TestCase end def test_explanation_user_request - @DR = Gem::Resolver - spec = util_spec "a", 2 - a1_req = @DR::DependencyRequest.new dep("a", "= 1"), nil - a2_req = @DR::DependencyRequest.new dep("a", "= 2"), nil + a1_req = Gem::Resolver::DependencyRequest.new dep("a", "= 1"), nil + a2_req = Gem::Resolver::DependencyRequest.new dep("a", "= 2"), nil - activated = @DR::ActivationRequest.new spec, a2_req + activated = Gem::Resolver::ActivationRequest.new spec, a2_req - conflict = @DR::Conflict.new a1_req, activated + conflict = Gem::Resolver::Conflict.new a1_req, activated expected = <<-EXPECTED Activated a-2 diff --git a/test/rubygems/test_gem_resolver_dependency_request.rb b/test/rubygems/test_gem_resolver_dependency_request.rb index 6ad3a09028..3e14771da8 100644 --- a/test/rubygems/test_gem_resolver_dependency_request.rb +++ b/test/rubygems/test_gem_resolver_dependency_request.rb @@ -1,23 +1,18 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverDependencyRequest < Gem::TestCase - def setup - super - - @DR = Gem::Resolver::DependencyRequest - end - def test_development_eh a_dep = dep "a", ">= 1" - a_dep_req = @DR.new a_dep, nil + a_dep_req = Gem::Resolver::DependencyRequest.new a_dep, nil refute a_dep_req.development? b_dep = dep "b", ">= 1", :development - b_dep_req = @DR.new b_dep, nil + b_dep_req = Gem::Resolver::DependencyRequest.new b_dep, nil assert b_dep_req.development? end @@ -26,7 +21,7 @@ class TestGemResolverDependencyRequest < Gem::TestCase spec = util_spec "a", 1 dependency = dep "a", ">= 1" - dr = @DR.new dependency, nil + dr = Gem::Resolver::DependencyRequest.new dependency, nil assert dr.match? spec end @@ -35,12 +30,12 @@ class TestGemResolverDependencyRequest < Gem::TestCase spec = util_spec "a", "1.a" a_dep = dep "a", ">= 1" - a_dr = @DR.new a_dep, nil + a_dr = Gem::Resolver::DependencyRequest.new a_dep, nil refute a_dr.match? spec a_pre_dep = dep "a", ">= 1.a" - a_pre_dr = @DR.new a_pre_dep, nil + a_pre_dr = Gem::Resolver::DependencyRequest.new a_pre_dep, nil assert a_pre_dr.match? spec end @@ -49,7 +44,7 @@ class TestGemResolverDependencyRequest < Gem::TestCase spec = util_spec "a", "2.a" a_dep = dep "a", ">= 1" - a_dr = @DR.new a_dep, nil + a_dr = Gem::Resolver::DependencyRequest.new a_dep, nil assert a_dr.match? spec, true end @@ -58,7 +53,7 @@ class TestGemResolverDependencyRequest < Gem::TestCase spec = util_spec "a", 1 dependency = dep "a", ">= 1" - dr = @DR.new dependency, nil + dr = Gem::Resolver::DependencyRequest.new dependency, nil assert dr.matches_spec? spec end @@ -67,7 +62,7 @@ class TestGemResolverDependencyRequest < Gem::TestCase spec = util_spec "a", "1.a" dependency = dep "a", ">= 0" - dr = @DR.new dependency, nil + dr = Gem::Resolver::DependencyRequest.new dependency, nil assert dr.matches_spec? spec end @@ -75,7 +70,7 @@ class TestGemResolverDependencyRequest < Gem::TestCase def test_requirement dependency = dep "a", ">= 1" - dr = @DR.new dependency, nil + dr = Gem::Resolver::DependencyRequest.new dependency, nil assert_equal dependency, dr.dependency end diff --git a/test/rubygems/test_gem_resolver_git_set.rb b/test/rubygems/test_gem_resolver_git_set.rb index f7063b3d45..90749d712c 100644 --- a/test/rubygems/test_gem_resolver_git_set.rb +++ b/test/rubygems/test_gem_resolver_git_set.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverGitSet < Gem::TestCase @@ -13,7 +14,7 @@ class TestGemResolverGitSet < Gem::TestCase def test_add_git_gem name, version, repository, = git_gem - @set.add_git_gem name, repository, "master", false + @set.add_git_gem name, repository, nil, false dependency = dep "a" @@ -27,7 +28,7 @@ class TestGemResolverGitSet < Gem::TestCase def test_add_git_gem_submodules name, _, repository, = git_gem - @set.add_git_gem name, repository, "master", true + @set.add_git_gem name, repository, nil, true dependency = dep "a" @@ -57,7 +58,7 @@ class TestGemResolverGitSet < Gem::TestCase def test_find_all name, _, repository, = git_gem - @set.add_git_gem name, repository, "master", false + @set.add_git_gem name, repository, nil, false dependency = dep "a", "~> 1.0" req = Gem::Resolver::DependencyRequest.new dependency, nil @@ -73,7 +74,7 @@ class TestGemResolverGitSet < Gem::TestCase def test_find_all_local name, _, repository, = git_gem - @set.add_git_gem name, repository, "master", false + @set.add_git_gem name, repository, nil, false @set.remote = false dependency = dep "a", "~> 1.0" @@ -88,7 +89,7 @@ class TestGemResolverGitSet < Gem::TestCase def test_find_all_prerelease name, _, repository, = git_gem "a", "1.a" - @set.add_git_gem name, repository, "master", false + @set.add_git_gem name, repository, nil, false dependency = dep "a", ">= 0" req = Gem::Resolver::DependencyRequest.new dependency, nil @@ -122,7 +123,7 @@ class TestGemResolverGitSet < Gem::TestCase def test_prefetch name, _, repository, = git_gem - @set.add_git_gem name, repository, "master", false + @set.add_git_gem name, repository, nil, false dependency = dep name req = Gem::Resolver::DependencyRequest.new dependency, nil @@ -136,7 +137,7 @@ class TestGemResolverGitSet < Gem::TestCase def test_prefetch_cache name, _, repository, = git_gem - @set.add_git_gem name, repository, "master", false + @set.add_git_gem name, repository, nil, false dependency = dep name req = Gem::Resolver::DependencyRequest.new dependency, nil @@ -154,7 +155,7 @@ class TestGemResolverGitSet < Gem::TestCase def test_prefetch_filter name, _, repository, = git_gem - @set.add_git_gem name, repository, "master", false + @set.add_git_gem name, repository, nil, false dependency = dep "b" req = Gem::Resolver::DependencyRequest.new dependency, nil @@ -168,7 +169,7 @@ class TestGemResolverGitSet < Gem::TestCase def test_prefetch_root_dir name, _, repository, = git_gem - @set.add_git_gem name, repository, "master", false + @set.add_git_gem name, repository, nil, false dependency = dep name req = Gem::Resolver::DependencyRequest.new dependency, nil diff --git a/test/rubygems/test_gem_resolver_git_specification.rb b/test/rubygems/test_gem_resolver_git_specification.rb index 454fd9c6e4..621333d3bf 100644 --- a/test/rubygems/test_gem_resolver_git_specification.rb +++ b/test/rubygems/test_gem_resolver_git_specification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/installer" @@ -28,7 +29,8 @@ class TestGemResolverGitSpecification < Gem::TestCase i_set = Gem::Resolver::IndexSet.new source = Gem::Source.new @gem_repo i_spec = Gem::Resolver::IndexSpecification.new( - i_set, "a", v(1), source, Gem::Platform::RUBY) + i_set, "a", v(1), source, Gem::Platform::RUBY + ) refute_equal g_spec_a, i_spec end @@ -63,7 +65,7 @@ class TestGemResolverGitSpecification < Gem::TestCase def test_install_extension pend if Gem.java_platform? - pend if RUBY_PLATFORM.include?("mswin") && ENV.key?("GITHUB_ACTIONS") # not working from the beginning + pend "terminates on mswin" if vc_windows? && ruby_repo? name, _, repository, = git_gem "a", 1 do |s| s.extensions << "ext/extconf.rb" end @@ -84,7 +86,7 @@ class TestGemResolverGitSpecification < Gem::TestCase system @git, "commit", "--quiet", "-m", "Add extension files" end - source = Gem::Source::Git.new name, repository, "master", true + source = Gem::Source::Git.new name, repository, nil, true spec = source.specs.first diff --git a/test/rubygems/test_gem_resolver_index_set.rb b/test/rubygems/test_gem_resolver_index_set.rb index 3b8f047808..8ff1acbf1e 100644 --- a/test/rubygems/test_gem_resolver_index_set.rb +++ b/test/rubygems/test_gem_resolver_index_set.rb @@ -1,15 +1,10 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverIndexSet < Gem::TestCase - def setup - super - - @DR = Gem::Resolver - end - def test_initialize - set = @DR::IndexSet.new + set = Gem::Resolver::IndexSet.new fetcher = set.instance_variable_get :@f @@ -17,7 +12,7 @@ class TestGemResolverIndexSet < Gem::TestCase end def test_initialize_source - set = @DR::IndexSet.new "http://alternate.example" + set = Gem::Resolver::IndexSet.new "http://alternate.example" fetcher = set.instance_variable_get :@f @@ -33,15 +28,15 @@ class TestGemResolverIndexSet < Gem::TestCase fetcher.spec "b", 1 end - set = @DR::IndexSet.new + set = Gem::Resolver::IndexSet.new dependency = dep "a", "~> 1" - req = @DR::DependencyRequest.new dependency, nil + req = Gem::Resolver::DependencyRequest.new dependency, nil found = set.find_all req - assert_equal %w[a-1], found.map {|s| s.full_name } + assert_equal %w[a-1], found.map(&:full_name) end def test_find_all_local @@ -51,12 +46,12 @@ class TestGemResolverIndexSet < Gem::TestCase fetcher.spec "b", 1 end - set = @DR::IndexSet.new + set = Gem::Resolver::IndexSet.new set.remote = false dependency = dep "a", "~> 1" - req = @DR::DependencyRequest.new dependency, nil + req = Gem::Resolver::DependencyRequest.new dependency, nil assert_empty set.find_all req end @@ -66,11 +61,11 @@ class TestGemResolverIndexSet < Gem::TestCase fetcher.spec "a", "1.a" end - set = @DR::IndexSet.new + set = Gem::Resolver::IndexSet.new dependency = dep "a" - req = @DR::DependencyRequest.new dependency, nil + req = Gem::Resolver::DependencyRequest.new dependency, nil found = set.find_all req @@ -78,10 +73,10 @@ class TestGemResolverIndexSet < Gem::TestCase dependency.prerelease = true - req = @DR::DependencyRequest.new dependency, nil + req = Gem::Resolver::DependencyRequest.new dependency, nil found = set.find_all req - assert_equal %w[a-1.a], found.map {|s| s.full_name } + assert_equal %w[a-1.a], found.map(&:full_name) end end diff --git a/test/rubygems/test_gem_resolver_index_specification.rb b/test/rubygems/test_gem_resolver_index_specification.rb index b479757bd5..ed9475f0cf 100644 --- a/test/rubygems/test_gem_resolver_index_specification.rb +++ b/test/rubygems/test_gem_resolver_index_specification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/available_set" @@ -9,7 +10,8 @@ class TestGemResolverIndexSpecification < Gem::TestCase version = Gem::Version.new "3.0.3" spec = Gem::Resolver::IndexSpecification.new( - set, "rails", version, source, Gem::Platform::RUBY) + set, "rails", version, source, Gem::Platform::RUBY + ) assert_equal "rails", spec.name assert_equal version, spec.version @@ -24,7 +26,8 @@ class TestGemResolverIndexSpecification < Gem::TestCase version = Gem::Version.new "3.0.3" spec = Gem::Resolver::IndexSpecification.new( - set, "rails", version, source, Gem::Platform.local) + set, "rails", version, source, Gem::Platform.local + ) assert_equal Gem::Platform.local, spec.platform end @@ -38,7 +41,8 @@ class TestGemResolverIndexSpecification < Gem::TestCase source = Gem::Source.new @gem_repo spec = Gem::Resolver::IndexSpecification.new( - set, "a", v(2), source, Gem::Platform::RUBY) + set, "a", v(2), source, Gem::Platform::RUBY + ) called = false diff --git a/test/rubygems/test_gem_resolver_installed_specification.rb b/test/rubygems/test_gem_resolver_installed_specification.rb index 156a88144d..5b10273b13 100644 --- a/test/rubygems/test_gem_resolver_installed_specification.rb +++ b/test/rubygems/test_gem_resolver_installed_specification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverInstalledSpecification < Gem::TestCase diff --git a/test/rubygems/test_gem_resolver_installer_set.rb b/test/rubygems/test_gem_resolver_installer_set.rb index 7617919e2c..202fe9d653 100644 --- a/test/rubygems/test_gem_resolver_installer_set.rb +++ b/test/rubygems/test_gem_resolver_installer_set.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverInstallerSet < Gem::TestCase @@ -14,7 +15,7 @@ class TestGemResolverInstallerSet < Gem::TestCase set.add_always_install dep("a") - assert_equal %w[a-2], set.always_install.map {|s| s.full_name } + assert_equal %w[a-2], set.always_install.map(&:full_name) e = assert_raise Gem::UnsatisfiableDependencyError do set.add_always_install dep("b") @@ -48,7 +49,7 @@ class TestGemResolverInstallerSet < Gem::TestCase set.add_always_install dep("a") - assert_equal %w[a-1], set.always_install.map {|s| s.full_name } + assert_equal %w[a-1], set.always_install.map(&:full_name) end def test_add_always_install_platform_if_gem_platforms_modified_by_platform_flag @@ -67,7 +68,7 @@ class TestGemResolverInstallerSet < Gem::TestCase set.add_always_install dep("a") - assert_equal %w[a-1-x86-freebsd-9], set.always_install.map {|s| s.full_name } + assert_equal %w[a-1-x86-freebsd-9], set.always_install.map(&:full_name) end def test_add_always_install_index_spec_platform @@ -80,7 +81,7 @@ class TestGemResolverInstallerSet < Gem::TestCase set = Gem::Resolver::InstallerSet.new :both set.add_always_install dep("a") - assert_equal [Gem::Platform.local], set.always_install.map {|s| s.platform } + assert_equal [Gem::Platform.local], set.always_install.map(&:platform) end def test_add_always_install_prerelease @@ -93,7 +94,7 @@ class TestGemResolverInstallerSet < Gem::TestCase set.add_always_install dep("a") - assert_equal %w[a-1], set.always_install.map {|s| s.full_name } + assert_equal %w[a-1], set.always_install.map(&:full_name) end def test_add_always_install_prerelease_github_problem @@ -111,7 +112,7 @@ class TestGemResolverInstallerSet < Gem::TestCase set.add_always_install dep("a") - assert_equal %w[a-1], set.always_install.map {|s| s.full_name } + assert_equal %w[a-1], set.always_install.map(&:full_name) end def test_add_always_install_prerelease_only @@ -142,7 +143,7 @@ class TestGemResolverInstallerSet < Gem::TestCase req = Gem::Resolver::DependencyRequest.new dep("a"), nil - assert_equal %w[a-1], set.find_all(req).map {|spec| spec.full_name } + assert_equal %w[a-1], set.find_all(req).map(&:full_name) end def test_consider_local_eh @@ -198,7 +199,7 @@ class TestGemResolverInstallerSet < Gem::TestCase req = Gem::Resolver::DependencyRequest.new dep("a"), nil - assert_equal %w[a-2], set.find_all(req).map {|spec| spec.full_name } + assert_equal %w[a-2], set.find_all(req).map(&:full_name) end def test_find_all_prerelease @@ -211,12 +212,12 @@ class TestGemResolverInstallerSet < Gem::TestCase req = Gem::Resolver::DependencyRequest.new dep("a"), nil - assert_equal %w[a-1], set.find_all(req).map {|spec| spec.full_name } + assert_equal %w[a-1], set.find_all(req).map(&:full_name) req = Gem::Resolver::DependencyRequest.new dep("a", ">= 0.a"), nil assert_equal %w[a-1 a-1.a], - set.find_all(req).map {|spec| spec.full_name }.sort + set.find_all(req).map(&:full_name).sort end def test_find_all_prerelease_dependencies_with_add_local @@ -228,7 +229,7 @@ class TestGemResolverInstallerSet < Gem::TestCase req = Gem::Resolver::DependencyRequest.new dep("activesupport", ">= 4.2.0"), nil - assert_equal %w[activesupport-7.1.0.alpha], set.find_all(req).map {|spec| spec.full_name } + assert_equal %w[activesupport-7.1.0.alpha], set.find_all(req).map(&:full_name) end def test_load_spec diff --git a/test/rubygems/test_gem_resolver_local_specification.rb b/test/rubygems/test_gem_resolver_local_specification.rb index 4ada391cb9..cefd761520 100644 --- a/test/rubygems/test_gem_resolver_local_specification.rb +++ b/test/rubygems/test_gem_resolver_local_specification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/available_set" diff --git a/test/rubygems/test_gem_resolver_lock_set.rb b/test/rubygems/test_gem_resolver_lock_set.rb index e01d73093c..ebb64ef583 100644 --- a/test/rubygems/test_gem_resolver_lock_set.rb +++ b/test/rubygems/test_gem_resolver_lock_set.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverLockSet < Gem::TestCase @@ -15,7 +16,7 @@ class TestGemResolverLockSet < Gem::TestCase specs = @set.add "a", "2", Gem::Platform::RUBY spec = specs.first - assert_equal %w[a-2], @set.specs.map {|t| t.full_name } + assert_equal %w[a-2], @set.specs.map(&:full_name) assert_kind_of Gem::Resolver::LockSpecification, spec @@ -33,11 +34,11 @@ class TestGemResolverLockSet < Gem::TestCase found = @set.find_all dep "a" - assert_equal %w[a-2], found.map {|s| s.full_name } + assert_equal %w[a-2], found.map(&:full_name) found = @set.find_all dep "a", ">= 0.a" - assert_equal %w[a-1.a a-2], found.map {|s| s.full_name } + assert_equal %w[a-1.a a-2], found.map(&:full_name) end def test_load_spec diff --git a/test/rubygems/test_gem_resolver_lock_specification.rb b/test/rubygems/test_gem_resolver_lock_specification.rb index 32adc25f94..402f5d1509 100644 --- a/test/rubygems/test_gem_resolver_lock_specification.rb +++ b/test/rubygems/test_gem_resolver_lock_specification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/installer" require "rubygems/resolver" @@ -7,14 +8,12 @@ class TestGemResolverLockSpecification < Gem::TestCase def setup super - @LS = Gem::Resolver::LockSpecification - @source = Gem::Source.new @gem_repo @set = Gem::Resolver::LockSet.new [@source] end def test_initialize - spec = @LS.new @set, "a", v(2), [@source], Gem::Platform::RUBY + spec = Gem::Resolver::LockSpecification.new @set, "a", v(2), [@source], Gem::Platform::RUBY assert_equal "a", spec.name assert_equal v(2), spec.version @@ -24,7 +23,7 @@ class TestGemResolverLockSpecification < Gem::TestCase end def test_add_dependency - l_spec = @LS.new @set, "a", v(2), [@source], Gem::Platform::RUBY + l_spec = Gem::Resolver::LockSpecification.new @set, "a", v(2), [@source], Gem::Platform::RUBY b_dep = dep("b", ">= 0") @@ -38,7 +37,7 @@ class TestGemResolverLockSpecification < Gem::TestCase fetcher.download "a", 2 end - spec = @LS.new @set, "a", v(2), [@source], Gem::Platform::RUBY + spec = Gem::Resolver::LockSpecification.new @set, "a", v(2), [@source], Gem::Platform::RUBY called = false @@ -50,7 +49,7 @@ class TestGemResolverLockSpecification < Gem::TestCase end def test_install_installed - spec = @LS.new @set, "a", v(2), [@source], Gem::Platform::RUBY + spec = Gem::Resolver::LockSpecification.new @set, "a", v(2), [@source], Gem::Platform::RUBY FileUtils.touch File.join(@gemhome, "specifications", spec.spec.spec_name) @@ -66,7 +65,7 @@ class TestGemResolverLockSpecification < Gem::TestCase def test_spec version = v(2) - l_spec = @LS.new @set, "a", version, [@source], Gem::Platform::RUBY + l_spec = Gem::Resolver::LockSpecification.new @set, "a", version, [@source], Gem::Platform::RUBY b_dep = dep "b", ">= 0" c_dep = dep "c", "~> 1" @@ -90,7 +89,7 @@ class TestGemResolverLockSpecification < Gem::TestCase version = v(2) - l_spec = @LS.new @set, "a", version, [@source], Gem::Platform::RUBY + l_spec = Gem::Resolver::LockSpecification.new @set, "a", version, [@source], Gem::Platform::RUBY assert_same real_spec, l_spec.spec end diff --git a/test/rubygems/test_gem_resolver_requirement_list.rb b/test/rubygems/test_gem_resolver_requirement_list.rb index e9e0d87bf5..20251805fc 100644 --- a/test/rubygems/test_gem_resolver_requirement_list.rb +++ b/test/rubygems/test_gem_resolver_requirement_list.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverRequirementList < Gem::TestCase diff --git a/test/rubygems/test_gem_resolver_specification.rb b/test/rubygems/test_gem_resolver_specification.rb index a8cba3dfd6..e2bbce0c0c 100644 --- a/test/rubygems/test_gem_resolver_specification.rb +++ b/test/rubygems/test_gem_resolver_specification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverSpecification < Gem::TestCase @@ -24,7 +25,7 @@ class TestGemResolverSpecification < Gem::TestCase a_spec = TestSpec.new a a_spec.source = Gem::Source.new @gem_repo - a_spec.install :install_dir => gemhome + a_spec.install install_dir: gemhome assert_path_exist File.join gemhome, "gems", a.full_name diff --git a/test/rubygems/test_gem_resolver_vendor_set.rb b/test/rubygems/test_gem_resolver_vendor_set.rb index 9517a4b06e..25a3c5fc7b 100644 --- a/test/rubygems/test_gem_resolver_vendor_set.rb +++ b/test/rubygems/test_gem_resolver_vendor_set.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverVendorSet < Gem::TestCase diff --git a/test/rubygems/test_gem_resolver_vendor_specification.rb b/test/rubygems/test_gem_resolver_vendor_specification.rb index d92ef0b010..3525a6c14c 100644 --- a/test/rubygems/test_gem_resolver_vendor_specification.rb +++ b/test/rubygems/test_gem_resolver_vendor_specification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemResolverVendorSpecification < Gem::TestCase @@ -27,7 +28,8 @@ class TestGemResolverVendorSpecification < Gem::TestCase i_set = Gem::Resolver::IndexSet.new source = Gem::Source.new @gem_repo i_spec = Gem::Resolver::IndexSpecification.new( - i_set, "a", v(1), source, Gem::Platform::RUBY) + i_set, "a", v(1), source, Gem::Platform::RUBY + ) refute_equal v_spec_a, i_spec end diff --git a/test/rubygems/test_gem_safe_marshal.rb b/test/rubygems/test_gem_safe_marshal.rb new file mode 100644 index 0000000000..ebb000a9ef --- /dev/null +++ b/test/rubygems/test_gem_safe_marshal.rb @@ -0,0 +1,404 @@ +# frozen_string_literal: true + +require_relative "helper" + +require "date" +require "rubygems/safe_marshal" + +class TestGemSafeMarshal < Gem::TestCase + define_method("test_safe_load_marshal Date #<Date: 1994-12-09 ((2449696j,0s,0n),+0s,2299161j)>") { assert_safe_load_marshal "\x04\bU:\tDate[\vi\x00i\x03 a%i\x00i\x00i\x00f\f2299161" } + define_method("test_safe_load_marshal Float 0.0") { assert_safe_load_marshal "\x04\bf\x060" } + define_method("test_safe_load_marshal Float -0.0") { assert_safe_load_marshal "\x04\bf\a-0" } + define_method("test_safe_load_marshal Float Infinity") { assert_safe_load_marshal "\x04\bf\binf" } + define_method("test_safe_load_marshal Float -Infinity") { assert_safe_load_marshal "\x04\bf\t-inf" } + define_method("test_safe_load_marshal Float NaN") { assert_safe_load_marshal "\x04\bf\bnan", equality: false } + define_method("test_safe_load_marshal Float 1.1") { assert_safe_load_marshal "\x04\bf\b1.1" } + define_method("test_safe_load_marshal Float -1.1") { assert_safe_load_marshal "\x04\bf\t-1.1" } + define_method("test_safe_load_marshal Float 30000000.0") { assert_safe_load_marshal "\x04\bf\b3e7" } + define_method("test_safe_load_marshal Float -30000000.0") { assert_safe_load_marshal "\x04\bf\t-3e7" } + define_method("test_safe_load_marshal Gem::Version #<Gem::Version \"1.abc\">") { assert_safe_load_marshal "\x04\bU:\x11Gem::Version[\x06I\"\n1.abc\x06:\x06ET" } + define_method("test_safe_load_marshal Hash {} default value") { assert_safe_load_marshal "\x04\b}\x00[\x00", additional_methods: [:default] } + define_method("test_safe_load_marshal Hash {}") { assert_safe_load_marshal "\x04\b{\x00" } + define_method("test_safe_load_marshal Array {}") { assert_safe_load_marshal "\x04\b[\x00" } + define_method("test_safe_load_marshal Hash {:runtime=>:development}") { assert_safe_load_marshal "\x04\bI{\x06:\fruntime:\x10development\x06:\n@type[\x00", permitted_ivars: { "Hash" => %w[@type] } } + define_method("test_safe_load_marshal Integer -1") { assert_safe_load_marshal "\x04\bi\xFA" } + define_method("test_safe_load_marshal Integer -1048575") { assert_safe_load_marshal "\x04\bi\xFD\x01\x00\xF0" } + define_method("test_safe_load_marshal Integer -122") { assert_safe_load_marshal "\x04\bi\x81" } + define_method("test_safe_load_marshal Integer -123") { assert_safe_load_marshal "\x04\bi\x80" } + define_method("test_safe_load_marshal Integer -124") { assert_safe_load_marshal "\x04\bi\xFF\x84" } + define_method("test_safe_load_marshal Integer -127") { assert_safe_load_marshal "\x04\bi\xFF\x81" } + define_method("test_safe_load_marshal Integer -128") { assert_safe_load_marshal "\x04\bi\xFF\x80" } + define_method("test_safe_load_marshal Integer -2") { assert_safe_load_marshal "\x04\bi\xF9" } + define_method("test_safe_load_marshal Integer -255") { assert_safe_load_marshal "\x04\bi\xFF\x01" } + define_method("test_safe_load_marshal Integer -256") { assert_safe_load_marshal "\x04\bi\xFF\x00" } + define_method("test_safe_load_marshal Integer -257") { assert_safe_load_marshal "\x04\bi\xFE\xFF\xFE" } + define_method("test_safe_load_marshal Integer -268435455") { assert_safe_load_marshal "\x04\bi\xFC\x01\x00\x00\xF0" } + define_method("test_safe_load_marshal Integer -268435456") { assert_safe_load_marshal "\x04\bi\xFC\x00\x00\x00\xF0" } + define_method("test_safe_load_marshal Integer -3") { assert_safe_load_marshal "\x04\bi\xF8" } + define_method("test_safe_load_marshal Integer -4") { assert_safe_load_marshal "\x04\bi\xF7" } + define_method("test_safe_load_marshal Integer -4294967295") { assert_safe_load_marshal "\x04\bl-\a\xFF\xFF\xFF\xFF" } + define_method("test_safe_load_marshal Integer -4294967296") { assert_safe_load_marshal "\x04\bl-\b\x00\x00\x00\x00\x01\x00" } + define_method("test_safe_load_marshal Integer -5") { assert_safe_load_marshal "\x04\bi\xF6" } + define_method("test_safe_load_marshal Integer -6") { assert_safe_load_marshal "\x04\bi\xF5" } + define_method("test_safe_load_marshal Integer -65535") { assert_safe_load_marshal "\x04\bi\xFE\x01\x00" } + define_method("test_safe_load_marshal Integer -65536") { assert_safe_load_marshal "\x04\bi\xFE\x00\x00" } + define_method("test_safe_load_marshal Integer -9223372036854775807") { assert_safe_load_marshal "\x04\bl-\t\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F" } + define_method("test_safe_load_marshal Integer -9223372036854775808") { assert_safe_load_marshal "\x04\bl-\t\x00\x00\x00\x00\x00\x00\x00\x80" } + define_method("test_safe_load_marshal Integer 0") { assert_safe_load_marshal "\x04\bi\x00" } + define_method("test_safe_load_marshal Integer 1") { assert_safe_load_marshal "\x04\bi\x06" } + define_method("test_safe_load_marshal Integer 1048574") { assert_safe_load_marshal "\x04\bi\x03\xFE\xFF\x0F" } + define_method("test_safe_load_marshal Integer 1048575") { assert_safe_load_marshal "\x04\bi\x03\xFF\xFF\x0F" } + define_method("test_safe_load_marshal Integer 1048576") { assert_safe_load_marshal "\x04\bi\x03\x00\x00\x10" } + define_method("test_safe_load_marshal Integer 121") { assert_safe_load_marshal "\x04\bi~" } + define_method("test_safe_load_marshal Integer 122") { assert_safe_load_marshal "\x04\bi\x7F" } + define_method("test_safe_load_marshal Integer 123") { assert_safe_load_marshal "\x04\bi\x01{" } + define_method("test_safe_load_marshal Integer 124") { assert_safe_load_marshal "\x04\bi\x01|" } + define_method("test_safe_load_marshal Integer 125") { assert_safe_load_marshal "\x04\bi\x01}" } + define_method("test_safe_load_marshal Integer 126") { assert_safe_load_marshal "\x04\bi\x01~" } + define_method("test_safe_load_marshal Integer 127") { assert_safe_load_marshal "\x04\bi\x01\x7F" } + define_method("test_safe_load_marshal Integer 128") { assert_safe_load_marshal "\x04\bi\x01\x80" } + define_method("test_safe_load_marshal Integer 129") { assert_safe_load_marshal "\x04\bi\x01\x81" } + define_method("test_safe_load_marshal Integer 2") { assert_safe_load_marshal "\x04\bi\a" } + define_method("test_safe_load_marshal Integer 254") { assert_safe_load_marshal "\x04\bi\x01\xFE" } + define_method("test_safe_load_marshal Integer 255") { assert_safe_load_marshal "\x04\bi\x01\xFF" } + define_method("test_safe_load_marshal Integer 256") { assert_safe_load_marshal "\x04\bi\x02\x00\x01" } + define_method("test_safe_load_marshal Integer 257") { assert_safe_load_marshal "\x04\bi\x02\x01\x01" } + define_method("test_safe_load_marshal Integer 258") { assert_safe_load_marshal "\x04\bi\x02\x02\x01" } + define_method("test_safe_load_marshal Integer 268435454") { assert_safe_load_marshal "\x04\bi\x04\xFE\xFF\xFF\x0F" } + define_method("test_safe_load_marshal Integer 268435455") { assert_safe_load_marshal "\x04\bi\x04\xFF\xFF\xFF\x0F" } + define_method("test_safe_load_marshal Integer 268435456") { assert_safe_load_marshal "\x04\bi\x04\x00\x00\x00\x10" } + define_method("test_safe_load_marshal Integer 268435457") { assert_safe_load_marshal "\x04\bi\x04\x01\x00\x00\x10" } + define_method("test_safe_load_marshal Integer 3") { assert_safe_load_marshal "\x04\bi\b" } + define_method("test_safe_load_marshal Integer 4") { assert_safe_load_marshal "\x04\bi\t" } + define_method("test_safe_load_marshal Integer 4294967294") { assert_safe_load_marshal "\x04\bl+\a\xFE\xFF\xFF\xFF" } + define_method("test_safe_load_marshal Integer 4294967295") { assert_safe_load_marshal "\x04\bl+\a\xFF\xFF\xFF\xFF" } + define_method("test_safe_load_marshal Integer 4294967296") { assert_safe_load_marshal "\x04\bl+\b\x00\x00\x00\x00\x01\x00" } + define_method("test_safe_load_marshal Integer 4294967297") { assert_safe_load_marshal "\x04\bl+\b\x01\x00\x00\x00\x01\x00" } + define_method("test_safe_load_marshal Integer 5") { assert_safe_load_marshal "\x04\bi\n" } + define_method("test_safe_load_marshal Integer 6") { assert_safe_load_marshal "\x04\bi\v" } + define_method("test_safe_load_marshal Integer 65534") { assert_safe_load_marshal "\x04\bi\x02\xFE\xFF" } + define_method("test_safe_load_marshal Integer 65535") { assert_safe_load_marshal "\x04\bi\x02\xFF\xFF" } + define_method("test_safe_load_marshal Integer 65536") { assert_safe_load_marshal "\x04\bi\x03\x00\x00\x01" } + define_method("test_safe_load_marshal Integer 65537") { assert_safe_load_marshal "\x04\bi\x03\x01\x00\x01" } + define_method("test_safe_load_marshal Integer 7") { assert_safe_load_marshal "\x04\bi\f" } + define_method("test_safe_load_marshal Integer 9223372036854775806") { assert_safe_load_marshal "\x04\bl+\t\xFE\xFF\xFF\xFF\xFF\xFF\xFF\x7F" } + define_method("test_safe_load_marshal Integer 9223372036854775807") { assert_safe_load_marshal "\x04\bl+\t\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F" } + define_method("test_safe_load_marshal Integer 9223372036854775808") { assert_safe_load_marshal "\x04\bl+\t\x00\x00\x00\x00\x00\x00\x00\x80" } + define_method("test_safe_load_marshal Integer 9223372036854775809") { assert_safe_load_marshal "\x04\bl+\t\x01\x00\x00\x00\x00\x00\x00\x80" } + define_method("test_safe_load_marshal Rational (1/3)") { assert_safe_load_marshal "\x04\bU:\rRational[\ai\x06i\b" } + define_method("test_safe_load_marshal Array [[...]]") { assert_safe_load_marshal "\x04\b[\x06@\x00" } + define_method("test_safe_load_marshal String \"hello\" ivar") { assert_safe_load_marshal "\x04\bI\"\nhello\a:\x06ET:\n@type@\x00", additional_methods: [:instance_variables], permitted_ivars: { "String" => %w[@type E] } } + define_method("test_safe_load_marshal Array [\"hello\", [\"hello\"], \"hello\", [\"hello\"]]") { assert_safe_load_marshal "\x04\b[\tI\"\nhello\x06:\x06ET[\x06@\x06@\x06@\a" } + define_method("test_safe_load_marshal Array [\"hello\", \"hello\"]") { assert_safe_load_marshal "\x04\b[\aI\"\nhello\x06:\x06ET@\x06" } + define_method("test_safe_load_marshal Array [:development, :development]") { assert_safe_load_marshal "\x04\b[\a:\x10development;\x00" } + define_method("test_safe_load_marshal String \"abc\" ascii") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\x06EF", additional_methods: [:encoding] } + define_method("test_safe_load_marshal Array [\"abc\", \"abc\"] ascii") { assert_safe_load_marshal "\x04\b[\aI\"\babc\x06:\x06EF@\x06", additional_methods: [->(x) { x.map(&:encoding) }] } + define_method("test_safe_load_marshal String \"abc\" utf8") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\x06ET", additional_methods: [:encoding] } + define_method("test_safe_load_marshal Array [\"abc\", \"abc\"] utf8") { assert_safe_load_marshal "\x04\b[\aI\"\babc\x06:\x06ET@\x06", additional_methods: [->(x) { x.map(&:encoding) }] } + define_method("test_safe_load_marshal String \"abc\" Windows-1256") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\rencoding\"\x11Windows-1256", additional_methods: [:encoding] } + define_method("test_safe_load_marshal Array [\"abc\", \"abc\"] Windows-1256") { assert_safe_load_marshal "\x04\b[\aI\"\babc\x06:\rencoding\"\x11Windows-1256@\x06", additional_methods: [->(x) { x.map(&:encoding) }] } + define_method("test_safe_load_marshal String \"abc\" binary") { assert_safe_load_marshal "\x04\b\"\babc", additional_methods: [:encoding] } + define_method("test_safe_load_marshal Array [\"abc\", \"abc\"] binary") { assert_safe_load_marshal "\x04\b[\a\"\babc@\x06", additional_methods: [->(x) { x.map(&:encoding) }] } + define_method("test_safe_load_marshal String \"\\x61\\x62\\x63\" utf32") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\rencoding\"\vUTF-32", additional_methods: [:encoding] } + define_method("test_safe_load_marshal Array [\"\\x61\\x62\\x63\", \"\\x61\\x62\\x63\"] utf32") { assert_safe_load_marshal "\x04\b[\aI\"\babc\x06:\rencoding\"\vUTF-32@\x06", additional_methods: [->(x) { x.map(&:encoding) }] } + define_method("test_safe_load_marshal String \"abc\" ivar") { assert_safe_load_marshal "\x04\bI\"\babc\a:\x06ET:\n@typeI\"\ttype\x06;\x00T", permitted_ivars: { "String" => %w[@type E] } } + define_method("test_safe_load_marshal String \"\"") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\x06ET" } + define_method("test_safe_load_marshal Time 2000-12-31 20:07:59 -1152") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\a:\voffseti\xFE Y:\tzone0", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\a:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 2254051613498933/2251799813685248000000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numl+\t5^\xBAI\f\x02\b\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\b\x00:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 2476979795053773/2251799813685248000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80L\x04\xB0\xEF\t:\rnano_numi\x025\f:\rnano_denl+\b\x00\x00\x00\x00\x00 :\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 2476979795053773/2251799813685248000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x01\x00\xB0\xEF\n:\rnano_numl+\t\x19\x00\x00\x00\x00\x00d\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\x01\x00:\rsubmicro\"\x06\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 2476979795053773/2251799813685248000000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numl+\t\xCD\xCC\xCC\xCC\xCC\xCC\b\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\b\x00:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 450364466336677/450359962737049600000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numl+\t9b->\x05\x00\b\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\b\x00:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 4548635623644201/4503599627370496000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\xF2\x03\xB0\xEF\t:\rnano_numi\x02q\x02:\rnano_denl+\b\x00\x00\x00\x00\x00@:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 4548635623644201/4503599627370496000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x01\x00\xB0\xEF\n:\rnano_numl+\t\x05\x00\x00\x00\x00\x00\x14\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\x02\x00:\rsubmicro\"\x06\x01:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 4548635623644201/4503599627370496000000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numl+\t)\\\x8F\xC2\xF5(\x10\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\x10\x00:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59.000000001 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numi\x06:\rnano_deni\x06:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59.000001 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x01\x00\xB0\xEF\a:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2000-12-31 23:59:59.001 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\xE8\x03\xB0\xEF\a:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2001-01-01 07:59:59 +0000") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\a:\voffseti\x00:\tzone0", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2001-01-01 07:59:59 UTC") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\xC0\x00\x00\xB0\xEF\x06:\tzoneI\"\bUTC\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2001-01-01 11:59:59 +0400") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\a:\voffseti\x02@8:\tzone0", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } + define_method("test_safe_load_marshal Time 2023-08-24 10:10:39.09565 -0700") { assert_safe_load_marshal "\x04\bIu:\tTime\r\x11\xDF\x1E\x80\xA2uq*\a:\voffseti\xFE\x90\x9D:\tzoneI\"\bPDT\x06:\x06EF" } + define_method("test_safe_load_marshal Time 2023-08-24 10:10:39.098453 -0700") { assert_safe_load_marshal "\x04\bIu:\tTime\r\x11\xDF\x1E\x80\x95\x80q*\b:\n@typeI\"\fruntime\x06:\x06ET:\voffseti\xFE\x90\x9D:\tzoneI\"\bPDT\x06;\aF", permitted_ivars: { "Time" => %w[@type offset zone], "String" => %w[E @debug_created_info] }, marshal_dump_equality: true } + + def test_repeated_symbol + assert_safe_load_as [:development, :development] + end + + def test_length_one_symbols + with_const(Gem::SafeMarshal, :PERMITTED_SYMBOLS, %w[E A b 0] << "") do + assert_safe_load_as [:A, :E, :E, :A, "".to_sym, "".to_sym], additional_methods: [:instance_variables] + end + end + + def test_repeated_string + s = "hello" + a = [s] + assert_safe_load_as [s, a, s, a] + assert_safe_load_as [s, s] + end + + def test_recursive_string + s = String.new("hello") + s.instance_variable_set(:@type, s) + with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { "String" => %w[@type E] }) do + assert_safe_load_as s, additional_methods: [:instance_variables] + end + end + + def test_recursive_array + a = [] + a << a + assert_safe_load_as a + end + + def test_time_loads + assert_safe_load_as Time.new + end + + def test_string_with_encoding + [ + String.new("abc", encoding: "US-ASCII"), + String.new("abc", encoding: "UTF-8"), + String.new("abc", encoding: "Windows-1256"), + String.new("abc", encoding: Encoding::BINARY), + String.new("abc", encoding: "UTF-32"), + + String.new("", encoding: "US-ASCII"), + String.new("", encoding: "UTF-8"), + String.new("", encoding: "Windows-1256"), + String.new("", encoding: Encoding::BINARY), + String.new("", encoding: "UTF-32"), + ].each do |s| + assert_safe_load_as s, additional_methods: [:encoding] + assert_safe_load_as [s, s], additional_methods: [->(a) { a.map(&:encoding) }] + end + end + + def test_string_with_ivar + str = String.new("abc") + str.instance_variable_set :@type, "type" + with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { "String" => %w[@type E @debug_created_info] }) do + assert_safe_load_as str + end + end + + def test_time_with_ivar + pend "Marshal.load of Time with ivars is broken on jruby, see https://github.com/jruby/jruby/issues/7902" if RUBY_ENGINE == "jruby" + + with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { "Time" => %w[@type offset zone nano_num nano_den submicro], "String" => %w[E @debug_created_info] }) do + assert_safe_load_as Time.new.tap {|t| t.instance_variable_set :@type, "runtime" }, marshal_dump_equality: true + end + end + + secs = Time.new(2000, 12, 31, 23, 59, 59).to_i + [ + Time.at(secs), + Time.at(secs, in: "+04:00"), + Time.at(secs, in: "-11:52"), + Time.at(secs, in: "+00:00"), + Time.at(secs, in: "-00:00"), + Time.at(secs, 1, :millisecond), + Time.at(secs, 1.1, :millisecond), + Time.at(secs, 1.01, :millisecond), + Time.at(secs, 1, :microsecond), + Time.at(secs, 1.1, :microsecond), + Time.at(secs, 1.01, :microsecond), + Time.at(secs, 1, :nanosecond), + Time.at(secs, 1.1, :nanosecond), + Time.at(secs, 1.01, :nanosecond), + Time.at(secs, 1.001, :nanosecond), + Time.at(secs, 1.00001, :nanosecond), + Time.at(secs, 1.00001, :nanosecond), + Time.at(secs, in: "UTC"), + Time.at(secs, in: "Z"), + ].each_with_index do |t, i| + define_method("test_time_#{i} #{t.inspect}") do + additional_methods = [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] + assert_safe_load_as t, additional_methods: additional_methods + end + end + + def test_floats + [0.0, Float::INFINITY, Float::NAN, 1.1, 3e7].each do |f| + assert_safe_load_as f + assert_safe_load_as(-f) + end + end + + def test_hash_with_ivar + h = { runtime: :development } + h.instance_variable_set :@type, [] + with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { "Hash" => %w[@type] }) do + assert_safe_load_as(h) + end + end + + def test_hash_with_default_value + assert_safe_load_as Hash.new([]) + end + + def test_hash_with_compare_by_identity + with_const(Gem::SafeMarshal, :PERMITTED_CLASSES, %w[Hash]) do + assert_safe_load_as Hash.new.compare_by_identity.tap {|h| + h[+"a"] = 1 + h[+"a"] = 2 }, additional_methods: [:compare_by_identity?], equality: false + assert_safe_load_as Hash.new.compare_by_identity, additional_methods: [:compare_by_identity?] + assert_safe_load_as Hash.new(0).compare_by_identity.tap {|h| + h[+"a"] = 1 + h[+"a"] = 2 }, additional_methods: [:compare_by_identity?, :default], equality: false + end + end + + class StringSubclass < ::String + end + + def test_string_subclass + with_const(Gem::SafeMarshal, :PERMITTED_CLASSES, [StringSubclass.name]) do + with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { StringSubclass.name => %w[E] }) do + e = assert_raise(Gem::SafeMarshal::Visitors::ToRuby::UnsupportedError) do + Gem::SafeMarshal.safe_load Marshal.dump StringSubclass.new("abc") + end + assert_equal "Unsupported user class #{StringSubclass.name} in marshal stream @ root.object", e.message + end + end + end + + class ArraySubclass < ::Array + end + + def test_array_subclass + with_const(Gem::SafeMarshal, :PERMITTED_CLASSES, [ArraySubclass.name]) do + e = assert_raise(Gem::SafeMarshal::Visitors::ToRuby::UnsupportedError) do + Gem::SafeMarshal.safe_load(Marshal.dump(ArraySubclass.new << "abc")) + end + assert_equal "Unsupported user class #{ArraySubclass.name} in marshal stream @ root", e.message + end + end + + def test_frozen_object + assert_safe_load_as Gem::Version.new("1.abc").freeze + end + + def test_date + assert_safe_load_as Date.new(1994, 12, 9) + end + + def test_rational + assert_safe_load_as Rational(1, 3) + end + + [ + 0, 1, 2, 3, 4, 5, 6, 122, 123, 124, 127, 128, 255, 256, 257, + 2**16, 2**16 - 1, 2**20 - 1, + 2**28, 2**28 - 1, + 2**32, 2**32 - 1, + 2**63, 2**63 - 1 + ]. + each do |i| + define_method("test_int_ #{i}") do + assert_safe_load_as i + assert_safe_load_as(-i) + assert_safe_load_as(i + 1) + assert_safe_load_as(i - 1) + end + end + + def test_gem_spec_disallowed_symbol + e = assert_raise(Gem::SafeMarshal::Visitors::ToRuby::UnpermittedSymbolError) do + spec = Gem::Specification.new do |s| + s.name = "hi" + s.version = "1.2.3" + + s.dependencies << Gem::Dependency.new("rspec", Gem::Requirement.new([">= 1.2.3"]), :runtime).tap {|d| d.instance_variable_set(:@name, :rspec) } + end + Gem::SafeMarshal.safe_load(Marshal.dump(spec)) + end + + assert_equal e.message, "Attempting to load unpermitted symbol \"rspec\" @ root.[9].[0].@name" + end + + def test_gem_spec_disallowed_ivar + e = assert_raise(Gem::SafeMarshal::Visitors::ToRuby::UnpermittedIvarError) do + spec = Gem::Specification.new do |s| + s.name = "hi" + s.version = "1.2.3" + + s.metadata.instance_variable_set(:@foobar, "rspec") + end + Gem::SafeMarshal.safe_load(Marshal.dump(spec)) + end + + assert_equal e.message, "Attempting to set unpermitted ivar \"@foobar\" on object of class Hash @ root.[18].ivar_0" + end + + def test_unexpected_eof + e = assert_raise(Gem::SafeMarshal::Reader::EOFError) do + Gem::SafeMarshal.safe_load("\x04\x08") + end + assert_equal e.message, "Unexpected EOF" + + e = assert_raise(Gem::SafeMarshal::Reader::EOFError) do + Gem::SafeMarshal.safe_load("\x04\x08[") + end + assert_equal e.message, "Unexpected EOF" + + e = assert_raise(Gem::SafeMarshal::Reader::EOFError) do + Gem::SafeMarshal.safe_load("\x04\x08[\x06") + end + assert_equal e.message, "Unexpected EOF" + end + + def assert_safe_load_marshal(dumped, additional_methods: [], permitted_ivars: nil, equality: true, marshal_dump_equality: true) + loaded = Marshal.load(dumped) + safe_loaded = + if permitted_ivars + with_const(Gem::SafeMarshal, :PERMITTED_IVARS, permitted_ivars) do + Gem::SafeMarshal.safe_load(dumped) + end + else + Gem::SafeMarshal.safe_load(dumped) + end + + # NaN != NaN, for example + if equality + assert_equal loaded, safe_loaded, "should equal what Marshal.load returns" + end + + assert_equal loaded.to_s, safe_loaded.to_s, "should have equal to_s" + assert_equal loaded.inspect, safe_loaded.inspect, "should have equal inspect" + additional_methods.each do |m| + if m.is_a?(Proc) + call = m + else + call = ->(obj) { obj.__send__(m) } + end + + assert_equal call[loaded], call[safe_loaded], "should have equal #{m}" + end + if marshal_dump_equality + assert_equal Marshal.dump(loaded).dump, Marshal.dump(safe_loaded).dump, "should Marshal.dump the same" + end + end + + def assert_safe_load_as(x, **kwargs) + dumped = Marshal.dump(x) + equality = x == x # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands + assert_safe_load_marshal(dumped, equality: equality, **kwargs) + end + + def with_const(mod, name, new_value, &block) + orig = mod.const_get(name) + mod.send :remove_const, name + mod.const_set name, new_value + + begin + yield + ensure + mod.send :remove_const, name + mod.const_set name, orig + mod.send :private_constant, name + end + end +end diff --git a/test/rubygems/test_gem_safe_yaml.rb b/test/rubygems/test_gem_safe_yaml.rb new file mode 100644 index 0000000000..02df9f97da --- /dev/null +++ b/test/rubygems/test_gem_safe_yaml.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require_relative "helper" + +Gem.load_yaml + +class TestGemSafeYAML < Gem::TestCase + def test_aliases_enabled_by_default + assert_predicate Gem::SafeYAML, :aliases_enabled? + assert_equal({ "a" => "a", "b" => "a" }, Gem::SafeYAML.safe_load("a: &a a\nb: *a\n")) + end + + def test_aliases_disabled + aliases_enabled = Gem::SafeYAML.aliases_enabled? + Gem::SafeYAML.aliases_enabled = false + refute_predicate Gem::SafeYAML, :aliases_enabled? + expected_error = defined?(Psych::AliasesNotEnabled) ? Psych::AliasesNotEnabled : Psych::BadAlias + assert_raise expected_error do + Gem::SafeYAML.safe_load("a: &a\nb: *a\n") + end + ensure + Gem::SafeYAML.aliases_enabled = aliases_enabled + end +end diff --git a/test/rubygems/test_gem_security.rb b/test/rubygems/test_gem_security.rb index f0b9824aab..82449a8626 100644 --- a/test/rubygems/test_gem_security.rb +++ b/test/rubygems/test_gem_security.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/security" @@ -18,17 +19,11 @@ class TestGemSecurity < Gem::TestCase CHILD_CERT = load_cert "child" EXPIRED_CERT = load_cert "expired" - def setup - super - - @SEC = Gem::Security - end - def test_class_create_cert name = PUBLIC_CERT.subject key = PRIVATE_KEY - cert = @SEC.create_cert name, key, 60, Gem::Security::EXTENSIONS, 5 + cert = Gem::Security.create_cert name, key, 60, Gem::Security::EXTENSIONS, 5 assert_kind_of OpenSSL::X509::Certificate, cert @@ -51,7 +46,7 @@ class TestGemSecurity < Gem::TestCase key_ident = cert.extensions.find {|ext| ext.oid == "subjectKeyIdentifier" } assert_equal 59, key_ident.value.length - assert_equal "5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B", + assert_equal "B1:1A:54:09:67:45:60:02:02:D7:CE:F4:1D:60:4A:89:DF:E7:58:D9", key_ident.value assert_equal "", cert.issuer.to_s @@ -61,7 +56,7 @@ class TestGemSecurity < Gem::TestCase def test_class_create_cert_self_signed subject = PUBLIC_CERT.subject - cert = @SEC.create_cert_self_signed subject, PRIVATE_KEY, 60 + cert = Gem::Security.create_cert_self_signed subject, PRIVATE_KEY, 60 assert_equal "/CN=nobody/DC=example", cert.issuer.to_s assert_equal "sha256WithRSAEncryption", cert.signature_algorithm @@ -72,7 +67,7 @@ class TestGemSecurity < Gem::TestCase name = PUBLIC_CERT.subject key = PRIVATE_KEY - cert = @SEC.create_cert_email email, key, 60 + cert = Gem::Security.create_cert_email email, key, 60 assert_kind_of OpenSSL::X509::Certificate, cert @@ -99,25 +94,25 @@ class TestGemSecurity < Gem::TestCase key_ident = cert.extensions.find {|ext| ext.oid == "subjectKeyIdentifier" } assert_equal 59, key_ident.value.length - assert_equal "5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B", + assert_equal "B1:1A:54:09:67:45:60:02:02:D7:CE:F4:1D:60:4A:89:DF:E7:58:D9", key_ident.value end def test_class_create_key - key = @SEC.create_key "rsa" + key = Gem::Security.create_key "rsa" assert_kind_of OpenSSL::PKey::RSA, key end def test_class_create_key_downcases - key = @SEC.create_key "DSA" + key = Gem::Security.create_key "DSA" assert_kind_of OpenSSL::PKey::DSA, key end def test_class_create_key_raises_unknown_algorithm e = assert_raise Gem::Security::Exception do - @SEC.create_key "NOT_RSA" + Gem::Security.create_key "NOT_RSA" end assert_equal "NOT_RSA algorithm not found. RSA, DSA, and EC algorithms are supported.", @@ -127,31 +122,31 @@ class TestGemSecurity < Gem::TestCase def test_class_get_public_key_rsa pkey_pem = PRIVATE_KEY.public_key.to_pem - assert_equal pkey_pem, @SEC.get_public_key(PRIVATE_KEY).to_pem + assert_equal pkey_pem, Gem::Security.get_public_key(PRIVATE_KEY).to_pem end def test_class_get_public_key_ec - pkey = @SEC.get_public_key(EC_KEY) + pkey = Gem::Security.get_public_key(EC_KEY) assert_respond_to pkey, :to_pem end def test_class_email_to_name assert_equal "/CN=nobody/DC=example", - @SEC.email_to_name("nobody@example").to_s + Gem::Security.email_to_name("nobody@example").to_s assert_equal "/CN=nobody/DC=example/DC=com", - @SEC.email_to_name("nobody@example.com").to_s + Gem::Security.email_to_name("nobody@example.com").to_s assert_equal "/CN=no.body/DC=example", - @SEC.email_to_name("no.body@example").to_s + Gem::Security.email_to_name("no.body@example").to_s assert_equal "/CN=no_body/DC=example", - @SEC.email_to_name("no+body@example").to_s + Gem::Security.email_to_name("no+body@example").to_s end def test_class_re_sign - assert_equal "sha1WithRSAEncryption", EXPIRED_CERT.signature_algorithm + assert_equal "sha256WithRSAEncryption", EXPIRED_CERT.signature_algorithm re_signed = Gem::Security.re_sign EXPIRED_CERT, PRIVATE_KEY, 60 assert_in_delta Time.now, re_signed.not_before, 10 @@ -171,7 +166,7 @@ class TestGemSecurity < Gem::TestCase extension.oid == "subjectAltName" end - assert_equal "#{child_alt_name.value} is not self-signed, contact " + + assert_equal "#{child_alt_name.value} is not self-signed, contact " \ "#{ALTERNATE_CERT.issuer} to obtain a valid certificate", e.message end @@ -182,16 +177,16 @@ class TestGemSecurity < Gem::TestCase end assert_equal "incorrect signing key for re-signing " + - "#{ALTERNATE_CERT.subject}", + ALTERNATE_CERT.subject.to_s, e.message end def test_class_reset - trust_dir = @SEC.trust_dir + trust_dir = Gem::Security.trust_dir - @SEC.reset + Gem::Security.reset - refute_equal trust_dir, @SEC.trust_dir + refute_equal trust_dir, Gem::Security.trust_dir end def test_class_sign @@ -205,7 +200,7 @@ class TestGemSecurity < Gem::TestCase cert.subject = signee cert.public_key = key.public_key - signed = @SEC.sign cert, key, PUBLIC_CERT, 60 + signed = Gem::Security.sign cert, key, PUBLIC_CERT, 60 assert_equal key.public_key.to_pem, signed.public_key.to_pem assert_equal signee.to_s, signed.subject.to_s @@ -230,7 +225,7 @@ class TestGemSecurity < Gem::TestCase key_ident = signed.extensions.find {|ext| ext.oid == "subjectKeyIdentifier" } assert_equal 59, key_ident.value.length - assert_equal "5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B", + assert_equal "B1:1A:54:09:67:45:60:02:02:D7:CE:F4:1D:60:4A:89:DF:E7:58:D9", key_ident.value assert signed.verify key @@ -240,9 +235,9 @@ class TestGemSecurity < Gem::TestCase issuer = PUBLIC_CERT.subject signee = OpenSSL::X509::Name.parse "/CN=signee/DC=example" - cert = @SEC.create_cert_email "signee@example", PRIVATE_KEY + cert = Gem::Security.create_cert_email "signee@example", PRIVATE_KEY - signed = @SEC.sign cert, PRIVATE_KEY, PUBLIC_CERT, 60 + signed = Gem::Security.sign cert, PRIVATE_KEY, PUBLIC_CERT, 60 assert_equal PUBLIC_KEY.to_pem, signed.public_key.to_pem assert_equal signee.to_s, signed.subject.to_s @@ -272,14 +267,14 @@ class TestGemSecurity < Gem::TestCase key_ident = signed.extensions.find {|ext| ext.oid == "subjectKeyIdentifier" } assert_equal 59, key_ident.value.length - assert_equal "5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B", + assert_equal "B1:1A:54:09:67:45:60:02:02:D7:CE:F4:1D:60:4A:89:DF:E7:58:D9", key_ident.value assert signed.verify PUBLIC_KEY end def test_class_trust_dir - trust_dir = @SEC.trust_dir + trust_dir = Gem::Security.trust_dir expected = File.join Gem.user_home, ".gem/trust" @@ -287,11 +282,11 @@ class TestGemSecurity < Gem::TestCase end def test_class_write - key = @SEC.create_key "rsa" + key = Gem::Security.create_key "rsa" path = File.join @tempdir, "test-private_key.pem" - @SEC.write key, path + Gem::Security.write key, path assert_path_exist path @@ -301,13 +296,13 @@ class TestGemSecurity < Gem::TestCase end def test_class_write_encrypted - key = @SEC.create_key "rsa" + key = Gem::Security.create_key "rsa" path = File.join @tempdir, "test-private_encrypted_key.pem" passphrase = "It should be long." - @SEC.write key, path, 0600, passphrase + Gem::Security.write key, path, 0o600, passphrase assert_path_exist path @@ -317,7 +312,7 @@ class TestGemSecurity < Gem::TestCase end def test_class_write_encrypted_cipher - key = @SEC.create_key "rsa" + key = Gem::Security.create_key "rsa" path = File.join @tempdir, "test-private_encrypted__with_non_default_cipher_key.pem" @@ -325,7 +320,7 @@ class TestGemSecurity < Gem::TestCase cipher = OpenSSL::Cipher.new "AES-192-CBC" - @SEC.write key, path, 0600, passphrase, cipher + Gem::Security.write key, path, 0o600, passphrase, cipher assert_path_exist path diff --git a/test/rubygems/test_gem_security_policy.rb b/test/rubygems/test_gem_security_policy.rb index 6680238245..2f4fb1ce28 100644 --- a/test/rubygems/test_gem_security_policy.rb +++ b/test/rubygems/test_gem_security_policy.rb @@ -33,7 +33,7 @@ class TestGemSecurityPolicy < Gem::TestCase end @digest = OpenSSL::Digest.new Gem::Security::DIGEST_NAME - @trust_dir = Gem::Security.trust_dir.dir # HACK use the object + @trust_dir = Gem::Security.trust_dir.dir # HACK: use the object @no = Gem::Security::NoSecurity @almost_no = Gem::Security::AlmostNoSecurity @@ -43,22 +43,22 @@ class TestGemSecurityPolicy < Gem::TestCase @chain = Gem::Security::Policy.new( "Chain", - :verify_data => true, - :verify_signer => true, - :verify_chain => true, - :verify_root => false, - :only_trusted => false, - :only_signed => false + verify_data: true, + verify_signer: true, + verify_chain: true, + verify_root: false, + only_trusted: false, + only_signed: false ) @root = Gem::Security::Policy.new( "Root", - :verify_data => true, - :verify_signer => true, - :verify_chain => true, - :verify_root => true, - :only_trusted => false, - :only_signed => false + verify_data: true, + verify_signer: true, + verify_chain: true, + verify_root: true, + only_trusted: false, + only_signed: false ) end @@ -105,8 +105,8 @@ class TestGemSecurityPolicy < Gem::TestCase @chain.check_chain chain, Time.now end - assert_equal "invalid signing chain: " + - "certificate #{INVALIDCHILD_CERT.subject} " + + assert_equal "invalid signing chain: " \ + "certificate #{INVALIDCHILD_CERT.subject} " \ "was not issued by #{CHILD_CERT.subject}", e.message end @@ -127,7 +127,7 @@ class TestGemSecurityPolicy < Gem::TestCase @low.check_cert EXPIRED_CERT, nil, Time.now end - assert_equal "certificate #{EXPIRED_CERT.subject} " + + assert_equal "certificate #{EXPIRED_CERT.subject} " \ "not valid after #{EXPIRED_CERT.not_after}", e.message end @@ -137,7 +137,7 @@ class TestGemSecurityPolicy < Gem::TestCase @low.check_cert FUTURE_CERT, nil, Time.now end - assert_equal "certificate #{FUTURE_CERT.subject} " + + assert_equal "certificate #{FUTURE_CERT.subject} " \ "not valid before #{FUTURE_CERT.not_before}", e.message end @@ -147,7 +147,7 @@ class TestGemSecurityPolicy < Gem::TestCase @low.check_cert INVALID_ISSUER_CERT, PUBLIC_CERT, Time.now end - assert_equal "certificate #{INVALID_ISSUER_CERT.subject} " + + assert_equal "certificate #{INVALID_ISSUER_CERT.subject} " \ "was not issued by #{PUBLIC_CERT.subject}", e.message end @@ -183,7 +183,7 @@ class TestGemSecurityPolicy < Gem::TestCase @almost_no.check_key(PUBLIC_CERT, ALTERNATE_KEY) end - assert_equal "certificate #{PUBLIC_CERT.subject} " + + assert_equal "certificate #{PUBLIC_CERT.subject} " \ "does not match the signing key", e.message end @@ -208,7 +208,7 @@ class TestGemSecurityPolicy < Gem::TestCase @chain.check_root chain, Time.now end - assert_equal "certificate #{INVALID_SIGNER_CERT.subject} " + + assert_equal "certificate #{INVALID_SIGNER_CERT.subject} " \ "was not issued by #{INVALID_SIGNER_CERT.issuer}", e.message end @@ -220,7 +220,7 @@ class TestGemSecurityPolicy < Gem::TestCase @chain.check_root chain, Time.now end - assert_equal "root certificate #{INVALID_ISSUER_CERT.subject} " + + assert_equal "root certificate #{INVALID_ISSUER_CERT.subject} " \ "is not self-signed (issuer #{INVALID_ISSUER_CERT.issuer})", e.message end @@ -260,7 +260,7 @@ class TestGemSecurityPolicy < Gem::TestCase @high.check_trust [WRONG_KEY_CERT], @digest, @trust_dir end - assert_equal "trusted root certificate #{PUBLIC_CERT.subject} checksum " + + assert_equal "trusted root certificate #{PUBLIC_CERT.subject} checksum " \ "does not match signing root certificate checksum", e.message end @@ -285,7 +285,7 @@ class TestGemSecurityPolicy < Gem::TestCase @high.check_trust [PUBLIC_CERT, CHILD_CERT], @digest, @trust_dir end - assert_equal "root cert #{PUBLIC_CERT.subject} is not trusted " + + assert_equal "root cert #{PUBLIC_CERT.subject} is not trusted " \ "(root of signing cert #{CHILD_CERT.subject})", e.message end @@ -452,7 +452,9 @@ class TestGemSecurityPolicy < Gem::TestCase package.checksums[Gem::Security::DIGEST_NAME] = {} s = StringIO.new metadata_gz - def s.full_name() "metadata.gz" end + def s.full_name + "metadata.gz" + end digests = package.digest s metadata_gz_digest = digests[Gem::Security::DIGEST_NAME]["metadata.gz"] @@ -475,7 +477,9 @@ class TestGemSecurityPolicy < Gem::TestCase package.checksums[Gem::Security::DIGEST_NAME] = {} s = StringIO.new metadata_gz - def s.full_name() "metadata.gz" end + def s.full_name + "metadata.gz" + end digests = package.digest s digests[Gem::Security::DIGEST_NAME]["data.tar.gz"] = @digest.hexdigest "hello" @@ -504,7 +508,9 @@ class TestGemSecurityPolicy < Gem::TestCase package.checksums[Gem::Security::DIGEST_NAME] = {} s = StringIO.new metadata_gz - def s.full_name() "metadata.gz" end + def s.full_name + "metadata.gz" + end digests = package.digest s digests[Gem::Security::DIGEST_NAME]["data.tar.gz"] = @digest.hexdigest "hello" @@ -530,6 +536,6 @@ class TestGemSecurityPolicy < Gem::TestCase digests = { Gem::Security::DIGEST_NAME => { 0 => data } } signatures = { 0 => sign(data, key) } - return digests, signatures + [digests, signatures] end end if Gem::HAVE_OPENSSL diff --git a/test/rubygems/test_gem_security_signer.rb b/test/rubygems/test_gem_security_signer.rb index d9f320eeb0..f4799cbd46 100644 --- a/test/rubygems/test_gem_security_signer.rb +++ b/test/rubygems/test_gem_security_signer.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" unless Gem::HAVE_OPENSSL @@ -36,8 +37,8 @@ class TestGemSecuritySigner < Gem::TestCase def test_initialize_cert_chain_mixed signer = Gem::Security::Signer.new nil, [@cert_file, CHILD_CERT] - assert_equal [PUBLIC_CERT, CHILD_CERT].map {|c| c.to_pem }, - signer.cert_chain.map {|c| c.to_pem } + assert_equal [PUBLIC_CERT, CHILD_CERT].map(&:to_pem), + signer.cert_chain.map(&:to_pem) end def test_initialize_cert_chain_invalid @@ -49,8 +50,8 @@ class TestGemSecuritySigner < Gem::TestCase def test_initialize_cert_chain_path signer = Gem::Security::Signer.new nil, [@cert_file] - assert_equal [PUBLIC_CERT].map {|c| c.to_pem }, - signer.cert_chain.map {|c| c.to_pem } + assert_equal [PUBLIC_CERT].map(&:to_pem), + signer.cert_chain.map(&:to_pem) end def test_initialize_default @@ -65,7 +66,7 @@ class TestGemSecuritySigner < Gem::TestCase signer = Gem::Security::Signer.new nil, nil assert_equal PRIVATE_KEY.to_pem, signer.key.to_pem - assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map {|c| c.to_pem } + assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map(&:to_pem) end def test_initialize_key_path @@ -99,7 +100,7 @@ class TestGemSecuritySigner < Gem::TestCase signer.load_cert_chain assert_equal [PUBLIC_CERT.to_pem, CHILD_CERT.to_pem], - signer.cert_chain.map {|c| c.to_pem } + signer.cert_chain.map(&:to_pem) end def test_load_cert_chain_broken @@ -111,7 +112,7 @@ class TestGemSecuritySigner < Gem::TestCase signer.load_cert_chain assert_equal [CHILD_CERT.to_pem, GRANDCHILD_CERT.to_pem], - signer.cert_chain.map {|c| c.to_pem } + signer.cert_chain.map(&:to_pem) end def test_sign @@ -120,12 +121,12 @@ class TestGemSecuritySigner < Gem::TestCase signature = signer.sign "hello" expected = <<-EXPECTED -cHze2sEfRysoUMCfGVAx/7o8jxj5liJJ2ptNxe2jf3l+EZvyjdqpXo9Ndzxx -6xLp2rxLG4K2//ip4aCH5Sh7hnia+F5u6iuLBETPlklPrmw5dnuKZxolz+vM -0O1aOZsQHcVzQoESTGjkms3KZk+gn3lg0sSBbAV5/LyDYoHCEjxlcA5D+Olb -rDmRyBMOnMS+q489OZ5Hr6B2YJJ3QbUwIZNhUeNmOxIBEYTrrKkZ92qkxbRN -qhlqFP4jR6zXFeyBCOr0KpTiWBNuxBFXDsxmhGyt2BOIjD6qmKn7RSIfYg/U -toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA== +FmrCYxEXW3dgYYNMxPdS16VrdXT+d5nyXTVlRm64ZHSgMxMAaPtQJsVYv73m +DWHTzNnLhhINSpgBMLh5a4atM52yxVdkPUTgqIH+LeIPBXn8xaP5JLmfDcmI +tBpc/9DhS3v9iKCX40igAArFu7Gg3swbgQ61SP+U22LvG5nDQZQz3sudtsw3 +qKPykFVaYjrRwzvBdSdJ1PwlAsanSwcwS/GKPtmE/ykZ6X5XOx7wvCDL/zGy +B8khkB8hDKC6moCzebmUxCBmTmXD0Wjzon+bf4MOriVE3a0ySGRvpr1mKR2+ +9EaVo7pDJLEM487+xg1CAZHRhwshd6II00XEzG/jBQ== EXPECTED assert_equal expected, [signature].pack("m") @@ -143,7 +144,7 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA== def test_sign_expired_auto_update pend if Gem.java_platform? - FileUtils.mkdir_p File.join(Gem.user_home, ".gem"), :mode => 0700 + FileUtils.mkdir_p File.join(Gem.user_home, ".gem"), mode: 0o700 private_key_path = File.join(Gem.user_home, ".gem", "gem-private_key.pem") Gem::Security.write PRIVATE_KEY, private_key_path @@ -170,7 +171,7 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA== end def test_sign_expired_auto_update_exists - FileUtils.mkdir_p File.join(Gem.user_home, ".gem"), :mode => 0700 + FileUtils.mkdir_p File.join(Gem.user_home, ".gem"), mode: 0o700 expiry = EXPIRED_CERT.not_after.strftime "%Y%m%d%H%M%S" expired_path = diff --git a/test/rubygems/test_gem_security_trust_dir.rb b/test/rubygems/test_gem_security_trust_dir.rb index b74e21fb5c..cfde8e9d48 100644 --- a/test/rubygems/test_gem_security_trust_dir.rb +++ b/test/rubygems/test_gem_security_trust_dir.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" unless Gem::HAVE_OPENSSL @@ -55,9 +56,9 @@ class TestGemSecurityTrustDir < Gem::TestCase assert_path_exist trusted - mask = 0100600 & (~File.umask) + mask = 0o100600 & (~File.umask) - assert_equal mask, File.stat(trusted).mode unless win_platform? + assert_equal mask, File.stat(trusted).mode unless Gem.win_platform? assert_equal PUBLIC_CERT.to_pem, File.read(trusted) end @@ -69,10 +70,10 @@ class TestGemSecurityTrustDir < Gem::TestCase assert_path_exist @dest_dir - mask = 040700 & (~File.umask) - mask |= 0200000 if RUBY_PLATFORM.include?("aix") + mask = 0o040700 & (~File.umask) + mask |= 0o200000 if RUBY_PLATFORM.include?("aix") - assert_equal mask, File.stat(@dest_dir).mode unless win_platform? + assert_equal mask, File.stat(@dest_dir).mode unless Gem.win_platform? end def test_verify_file @@ -86,13 +87,13 @@ class TestGemSecurityTrustDir < Gem::TestCase end def test_verify_wrong_permissions - FileUtils.mkdir_p @dest_dir, :mode => 0777 + FileUtils.mkdir_p @dest_dir, mode: 0o777 @trust_dir.verify - mask = 040700 & (~File.umask) - mask |= 0200000 if RUBY_PLATFORM.include?("aix") + mask = 0o40700 & (~File.umask) + mask |= 0o200000 if RUBY_PLATFORM.include?("aix") - assert_equal mask, File.stat(@dest_dir).mode unless win_platform? + assert_equal mask, File.stat(@dest_dir).mode unless Gem.win_platform? end end if Gem::HAVE_OPENSSL diff --git a/test/rubygems/test_gem_silent_ui.rb b/test/rubygems/test_gem_silent_ui.rb index c5d2a35c34..001a73eb51 100644 --- a/test/rubygems/test_gem_silent_ui.rb +++ b/test/rubygems/test_gem_silent_ui.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/user_interaction" -require "timeout" class TestGemSilentUI < Gem::TestCase def setup @@ -115,7 +115,7 @@ class TestGemSilentUI < Gem::TestCase end def test_new_without_dev_null - File.stub(:open, ->(path, mode) { raise Errno::ENOTCAPABLE if path == IO::NULL }) do + File.stub(:open, ->(path, _mode) { raise Errno::ENOTCAPABLE if path == IO::NULL }) do Gem::SilentUI.new end end diff --git a/test/rubygems/test_gem_source.rb b/test/rubygems/test_gem_source.rb index e164215b57..6baa203dcb 100644 --- a/test/rubygems/test_gem_source.rb +++ b/test/rubygems/test_gem_source.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/source" -require "rubygems/indexer" class TestGemSource < Gem::TestCase def tuple(*args) @@ -22,7 +22,7 @@ class TestGemSource < Gem::TestCase end def test_initialize_invalid_uri - assert_raise URI::InvalidURIError do + assert_raise Gem::URI::InvalidURIError do Gem::Source.new "git@example:a.git" end end @@ -30,21 +30,21 @@ class TestGemSource < Gem::TestCase def test_initialize_git repository = "git@example:a.git" - source = Gem::Source::Git.new "a", repository, "master", false + source = Gem::Source::Git.new "a", repository, nil, false assert_equal repository, source.uri end def test_cache_dir_escapes_windows_paths - uri = URI.parse("file:///C:/WINDOWS/Temp/gem_repo") + uri = Gem::URI.parse("file:///C:/WINDOWS/Temp/gem_repo") root = Gem.spec_cache_dir cache_dir = @source.cache_dir(uri).gsub(root, "") - assert cache_dir !~ /:/, "#{cache_dir} should not contain a :" + assert !cache_dir.include?(":"), "#{cache_dir} should not contain a :" end def test_dependency_resolver_set_bundler_api - response = Net::HTTPResponse.new "1.1", 200, "OK" - response.uri = URI("http://example") + response = Gem::Net::HTTPResponse.new "1.1", 200, "OK" + response.uri = Gem::URI("http://example") @fetcher.data[@gem_repo] = response @@ -54,7 +54,9 @@ class TestGemSource < Gem::TestCase end def test_dependency_resolver_set_file_uri - Gem::Indexer.new(@tempdir).generate_index + empty_dump = Gem::Util.gzip("\x04\x08[\x05".b) + File.binwrite(File.join(@tempdir, "prerelease_specs.4.8.gz"), empty_dump) + File.binwrite(File.join(@tempdir, "specs.4.8.gz"), empty_dump) source = Gem::Source.new "file://#{@tempdir}/" @@ -77,7 +79,7 @@ class TestGemSource < Gem::TestCase spec = @source.fetch_spec tuple("a", Gem::Version.new(1), "ruby") assert_equal a1.full_name, spec.full_name - cache_dir = @source.cache_dir URI.parse(spec_uri) + cache_dir = @source.cache_dir Gem::URI.parse(spec_uri) cache_file = File.join cache_dir, a1.spec_name @@ -90,7 +92,7 @@ class TestGemSource < Gem::TestCase spec_uri = "#{@gem_repo}/#{Gem::MARSHAL_SPEC_DIR}#{a1.spec_name}" @fetcher.data["#{spec_uri}.rz"] = nil - cache_dir = @source.cache_dir URI.parse(spec_uri) + cache_dir = @source.cache_dir Gem::URI.parse(spec_uri) FileUtils.mkdir_p cache_dir cache_file = File.join cache_dir, a1.spec_name @@ -104,9 +106,7 @@ class TestGemSource < Gem::TestCase end def test_fetch_spec_platform - specs = spec_fetcher do |fetcher| - fetcher.legacy_platform - end + specs = spec_fetcher(&:legacy_platform) spec = @source.fetch_spec tuple("pl", Gem::Version.new(1), "i386-linux") @@ -122,7 +122,7 @@ class TestGemSource < Gem::TestCase end def test_load_specs - released = @source.load_specs(:released).map {|spec| spec.full_name } + released = @source.load_specs(:released).map(&:full_name) assert_equal %W[a-2 a-1 b-2], released cache_dir = File.join Gem.spec_cache_dir, "gems.example.com%80" @@ -164,7 +164,7 @@ class TestGemSource < Gem::TestCase latest_specs << Gem::NameTuple.new("fixed", Gem::Version.new("1.0.0"), "ruby") # Setup valid data on the 'remote' @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = - util_gzip(Marshal.dump(latest_specs)) + util_gzip(Marshal.dump(latest_specs)) cache_dir = File.join Gem.spec_cache_dir, "gems.example.com%80" @@ -196,7 +196,7 @@ class TestGemSource < Gem::TestCase installed = Gem::Source::Installed.new local = Gem::Source::Local.new - assert_equal(0, remote.<=>(remote), "remote <=> remote") + assert_equal(0, remote.<=>(remote), "remote <=> remote") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(-1, remote.<=>(specific), "remote <=> specific") assert_equal(1, specific.<=>(remote), "specific <=> remote") @@ -214,12 +214,12 @@ class TestGemSource < Gem::TestCase end def test_spaceship_order_is_preserved_when_uri_differs - sourceA = Gem::Source.new "http://example.com/a" - sourceB = Gem::Source.new "http://example.com/b" + source_a = Gem::Source.new "http://example.com/a" + source_b = Gem::Source.new "http://example.com/b" - assert_equal(0, sourceA.<=>(sourceA), "sourceA <=> sourceA") - assert_equal(1, sourceA.<=>(sourceB), "sourceA <=> sourceB") - assert_equal(1, sourceB.<=>(sourceA), "sourceB <=> sourceA") + assert_equal(0, source_a.<=>(source_a), "source_a <=> source_a") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands + assert_equal(1, source_a.<=>(source_b), "source_a <=> source_b") + assert_equal(1, source_b.<=>(source_a), "source_b <=> source_a") end def test_update_cache_eh diff --git a/test/rubygems/test_gem_source_fetch_problem.rb b/test/rubygems/test_gem_source_fetch_problem.rb index 143c29050e..6d8ef360ae 100644 --- a/test/rubygems/test_gem_source_fetch_problem.rb +++ b/test/rubygems/test_gem_source_fetch_problem.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemSourceFetchProblem < Gem::TestCase diff --git a/test/rubygems/test_gem_source_git.rb b/test/rubygems/test_gem_source_git.rb index 5702da0597..20e750a0d4 100644 --- a/test/rubygems/test_gem_source_git.rb +++ b/test/rubygems/test_gem_source_git.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/source" @@ -8,9 +9,9 @@ class TestGemSourceGit < Gem::TestCase @name, @version, @repository, @head = git_gem - @hash = Digest::SHA1.hexdigest @repository + @hash = OpenSSL::Digest::SHA1.hexdigest @repository - @source = Gem::Source::Git.new @name, @repository, "master", false + @source = Gem::Source::Git.new @name, @repository, nil, false end def test_base_dir @@ -27,12 +28,13 @@ class TestGemSourceGit < Gem::TestCase assert_path_exist File.join @source.install_dir, "a.gemspec" end - def test_checkout_master + def test_checkout_default Dir.chdir @repository do + default_branch = Gem::Util.popen(@git, "branch", "--show-current").strip system @git, "checkout", "-q", "-b", "other" system @git, "mv", "a.gemspec", "b.gemspec" system @git, "commit", "-q", "-a", "-m", "rename gemspec" - system @git, "checkout", "-q", "master" + system @git, "checkout", "-q", default_branch end @source = Gem::Source::Git.new @name, @repository, "other", false @@ -63,7 +65,12 @@ class TestGemSourceGit < Gem::TestCase end def test_checkout_submodules - source = Gem::Source::Git.new @name, @repository, "master", true + # We need to allow to checkout submodules with file:// protocol + # CVE-2022-39253 + # https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/ + system(@git, *%W[config --global protocol.file.allow always]) + + source = Gem::Source::Git.new @name, @repository, nil, true git_gem "b" @@ -87,7 +94,7 @@ class TestGemSourceGit < Gem::TestCase assert_path_exist @source.repo_cache_dir Dir.chdir @source.repo_cache_dir do - assert_equal @head, Gem::Util.popen(@git, "rev-parse", "master").strip + assert_equal @head, Gem::Util.popen(@git, "rev-parse", "HEAD").strip end end @@ -173,7 +180,7 @@ class TestGemSourceGit < Gem::TestCase system @git, "checkout", "--quiet", "-b", "other" end - master_head = @head + default_head = @head git_gem "a", 2 @@ -181,7 +188,7 @@ class TestGemSourceGit < Gem::TestCase source.cache - refute_equal master_head, source.rev_parse + refute_equal default_head, source.rev_parse source = Gem::Source::Git.new @name, @repository, "nonexistent", false @@ -204,12 +211,12 @@ class TestGemSourceGit < Gem::TestCase end def test_spaceship - git = Gem::Source::Git.new "a", "git/a", "master", false + git = Gem::Source::Git.new "a", "git/a", nil, false remote = Gem::Source.new @gem_repo installed = Gem::Source::Installed.new vendor = Gem::Source::Vendor.new "vendor/foo" - assert_equal(0, git.<=>(git), "git <=> git") + assert_equal(0, git.<=>(git), "git <=> git") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(1, git.<=>(remote), "git <=> remote") assert_equal(-1, remote.<=>(git), "remote <=> git") @@ -222,7 +229,7 @@ class TestGemSourceGit < Gem::TestCase end def test_specs - source = Gem::Source::Git.new @name, @repository, "master", true + source = Gem::Source::Git.new @name, @repository, nil, true Dir.chdir "git/a" do FileUtils.mkdir "b" @@ -245,7 +252,7 @@ class TestGemSourceGit < Gem::TestCase specs = source.specs end - assert_equal %w[a-1 b-1], specs.map {|spec| spec.full_name } + assert_equal %w[a-1 b-1], specs.map(&:full_name) a_spec = specs.shift @@ -273,7 +280,7 @@ class TestGemSourceGit < Gem::TestCase end def test_specs_local - source = Gem::Source::Git.new @name, @repository, "master", true + source = Gem::Source::Git.new @name, @repository, nil, true source.remote = false capture_output do @@ -282,20 +289,20 @@ class TestGemSourceGit < Gem::TestCase end def test_uri - assert_equal URI(@repository), @source.uri + assert_equal Gem::URI(@repository), @source.uri end def test_uri_hash assert_equal @hash, @source.uri_hash source = - Gem::Source::Git.new "a", "http://git@example/repo.git", "master", false + Gem::Source::Git.new "a", "http://git@example/repo.git", nil, false assert_equal "291c4caac7feba8bb64c297987028acb3dde6cfe", source.uri_hash source = - Gem::Source::Git.new "a", "HTTP://git@EXAMPLE/repo.git", "master", false + Gem::Source::Git.new "a", "HTTP://git@EXAMPLE/repo.git", nil, false assert_equal "291c4caac7feba8bb64c297987028acb3dde6cfe", source.uri_hash diff --git a/test/rubygems/test_gem_source_installed.rb b/test/rubygems/test_gem_source_installed.rb index 7fb5017c59..0d6171b0e5 100644 --- a/test/rubygems/test_gem_source_installed.rb +++ b/test/rubygems/test_gem_source_installed.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/source" @@ -11,10 +12,10 @@ class TestGemSourceInstalled < Gem::TestCase specific = Gem::Source::SpecificFile.new a1.cache_file installed = Gem::Source::Installed.new local = Gem::Source::Local.new - git = Gem::Source::Git.new "a", "a", "master" + git = Gem::Source::Git.new "a", "a", nil vendor = Gem::Source::Vendor.new "a" - assert_equal(0, installed.<=>(installed), "installed <=> installed") + assert_equal(0, installed.<=>(installed), "installed <=> installed") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(-1, remote.<=>(installed), "remote <=> installed") assert_equal(1, installed.<=>(remote), "installed <=> remote") diff --git a/test/rubygems/test_gem_source_list.rb b/test/rubygems/test_gem_source_list.rb index 9fd1b3bdf9..64353f8f90 100644 --- a/test/rubygems/test_gem_source_list.rb +++ b/test/rubygems/test_gem_source_list.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require "rubygems" require "rubygems/source_list" require_relative "helper" @@ -36,7 +37,7 @@ class TestGemSourceList < Gem::TestCase assert_kind_of Gem::Source, source - assert_kind_of URI, source.uri + assert_kind_of Gem::URI, source.uri assert_equal source.uri.to_s, @uri assert_equal [source], sl.sources @@ -98,7 +99,7 @@ class TestGemSourceList < Gem::TestCase def test_include_eh assert @sl.include?(@uri), "string comparison not working" - assert @sl.include?(URI.parse(@uri)), "uri comparison not working" + assert @sl.include?(Gem::URI.parse(@uri)), "uri comparison not working" end def test_include_matches_a_source diff --git a/test/rubygems/test_gem_source_local.rb b/test/rubygems/test_gem_source_local.rb index ace3923009..c15e0e07c0 100644 --- a/test/rubygems/test_gem_source_local.rb +++ b/test/rubygems/test_gem_source_local.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/source" @@ -72,7 +73,7 @@ class TestGemSourceLocal < Gem::TestCase @sl.load_specs :released - inner = [@a, @ap, @b].map {|t| t.name_tuple }.inspect + inner = [@a, @ap, @b].map(&:name_tuple).inspect assert_equal "#<Gem::Source::Local specs: #{inner}>", @sl.inspect end @@ -92,7 +93,7 @@ class TestGemSourceLocal < Gem::TestCase installed = Gem::Source::Installed.new local = Gem::Source::Local.new - assert_equal(0, local.<=>(local), "local <=> local") + assert_equal(0, local.<=>(local), "local <=> local") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(-1, remote.<=>(local), "remote <=> local") assert_equal(1, local.<=>(remote), "local <=> remote") diff --git a/test/rubygems/test_gem_source_lock.rb b/test/rubygems/test_gem_source_lock.rb index ff9465d0ad..91ffee68f2 100644 --- a/test/rubygems/test_gem_source_lock.rb +++ b/test/rubygems/test_gem_source_lock.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemSourceLock < Gem::TestCase @@ -18,7 +19,7 @@ class TestGemSourceLock < Gem::TestCase end def test_equals2 - git = Gem::Source::Git.new "a", "git/a", "master", false + git = Gem::Source::Git.new "a", "git/a", nil, false g_lock = Gem::Source::Lock.new git installed = Gem::Source::Installed.new @@ -30,7 +31,7 @@ class TestGemSourceLock < Gem::TestCase end def test_spaceship - git = Gem::Source::Git.new "a", "git/a", "master", false + git = Gem::Source::Git.new "a", "git/a", nil, false g_lock = Gem::Source::Lock.new git installed = Gem::Source::Installed.new @@ -39,9 +40,11 @@ class TestGemSourceLock < Gem::TestCase vendor = Gem::Source::Vendor.new "vendor/a" v_lock = Gem::Source::Lock.new vendor + # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(0, g_lock.<=>(g_lock), "g_lock <=> g_lock") assert_equal(0, i_lock.<=>(i_lock), "i_lock <=> i_lock") assert_equal(0, v_lock.<=>(v_lock), "v_lock <=> v_lock") + # rubocop:enable Lint/BinaryOperatorWithIdenticalOperands assert_equal(1, g_lock.<=>(i_lock), "g_lock <=> i_lock") assert_equal(-1, i_lock.<=>(g_lock), "i_lock <=> g_lock") @@ -54,7 +57,7 @@ class TestGemSourceLock < Gem::TestCase end def test_spaceship_git - git = Gem::Source::Git.new "a", "git/a", "master", false + git = Gem::Source::Git.new "a", "git/a", nil, false lock = Gem::Source::Lock.new git assert_equal(1, lock.<=>(git), "lock <=> git") @@ -107,6 +110,6 @@ class TestGemSourceLock < Gem::TestCase remote = Gem::Source.new @gem_repo lock = Gem::Source::Lock.new remote - assert_equal URI(@gem_repo), lock.uri + assert_equal Gem::URI(@gem_repo), lock.uri end end diff --git a/test/rubygems/test_gem_source_specific_file.rb b/test/rubygems/test_gem_source_specific_file.rb index f9a572b76d..3bc1901ee1 100644 --- a/test/rubygems/test_gem_source_specific_file.rb +++ b/test/rubygems/test_gem_source_specific_file.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/source" @@ -45,7 +46,7 @@ class TestGemSourceSpecificFile < Gem::TestCase installed = Gem::Source::Installed.new local = Gem::Source::Local.new - assert_equal(0, specific.<=>(specific), "specific <=> specific") + assert_equal(0, specific.<=>(specific), "specific <=> specific") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(-1, remote.<=>(specific), "remote <=> specific") assert_equal(1, specific.<=>(remote), "specific <=> remote") @@ -69,7 +70,7 @@ class TestGemSourceSpecificFile < Gem::TestCase assert_nil a1_source.<=>(b1_source), "a1_source <=> b1_source" assert_equal(-1, a1_source.<=>(a2_source), "a1_source <=> a2_source") - assert_equal(0, a1_source.<=>(a1_source), "a1_source <=> a1_source") + assert_equal(0, a1_source.<=>(a1_source), "a1_source <=> a1_source") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(1, a2_source.<=>(a1_source), "a2_source <=> a1_source") end end diff --git a/test/rubygems/test_gem_source_subpath_problem.rb b/test/rubygems/test_gem_source_subpath_problem.rb index 219c344290..a451a81a25 100644 --- a/test/rubygems/test_gem_source_subpath_problem.rb +++ b/test/rubygems/test_gem_source_subpath_problem.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/source" @@ -20,8 +21,8 @@ class TestGemSourceSubpathProblem < Gem::TestCase end def test_dependency_resolver_set - response = Net::HTTPResponse.new "1.1", 200, "OK" - response.uri = URI("http://example") + response = Gem::Net::HTTPResponse.new "1.1", 200, "OK" + response.uri = Gem::URI("http://example") @fetcher.data["#{@gem_repo}/"] = response @@ -43,7 +44,7 @@ class TestGemSourceSubpathProblem < Gem::TestCase Gem::NameTuple.new(@b2.name, @b2.version, "ruby"), ])) - released = @source.load_specs(:latest).map {|spec| spec.full_name } + released = @source.load_specs(:latest).map(&:full_name) assert_equal %W[a-1 b-2], released end end diff --git a/test/rubygems/test_gem_source_vendor.rb b/test/rubygems/test_gem_source_vendor.rb index 29846e5c13..2543871439 100644 --- a/test/rubygems/test_gem_source_vendor.rb +++ b/test/rubygems/test_gem_source_vendor.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/source" @@ -12,10 +13,10 @@ class TestGemSourceVendor < Gem::TestCase def test_spaceship vendor = Gem::Source::Vendor.new "vendor/foo" remote = Gem::Source.new @gem_repo - git = Gem::Source::Git.new "a", "a", "master" + git = Gem::Source::Git.new "a", "a", nil installed = Gem::Source::Installed.new - assert_equal(0, vendor.<=>(vendor), "vendor <=> vendor") + assert_equal(0, vendor.<=>(vendor), "vendor <=> vendor") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(1, vendor.<=>(remote), "vendor <=> remote") assert_equal(-1, remote.<=>(vendor), "remote <=> vendor") diff --git a/test/rubygems/test_gem_spec_fetcher.rb b/test/rubygems/test_gem_spec_fetcher.rb index f23a93350b..cb4a4f7204 100644 --- a/test/rubygems/test_gem_spec_fetcher.rb +++ b/test/rubygems/test_gem_spec_fetcher.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/spec_fetcher" @@ -10,7 +11,7 @@ class TestGemSpecFetcher < Gem::TestCase def setup super - @uri = URI.parse @gem_repo + @uri = Gem::URI.parse @gem_repo @source = Gem::Source.new(@uri) @sf = Gem::SpecFetcher.new @@ -40,12 +41,12 @@ class TestGemSpecFetcher < Gem::TestCase def test_initialize_unwritable_home_dir pend "chmod not supported" if Gem.win_platform? - FileUtils.chmod 0000, Gem.user_home + FileUtils.chmod 0o000, Gem.user_home begin assert Gem::SpecFetcher.new ensure - FileUtils.chmod 0755, Gem.user_home + FileUtils.chmod 0o755, Gem.user_home end end @@ -108,9 +109,7 @@ class TestGemSpecFetcher < Gem::TestCase def test_spec_for_dependency_platform util_set_arch "i386-linux" - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) dep = Gem::Dependency.new "pl", 1 specs_and_sources, _ = @sf.spec_for_dependency dep @@ -126,9 +125,7 @@ class TestGemSpecFetcher < Gem::TestCase def test_spec_for_dependency_mismatched_platform util_set_arch "hrpa-989" - spec_fetcher do |fetcher| - fetcher.legacy_platform - end + spec_fetcher(&:legacy_platform) dep = Gem::Dependency.new "pl", 1 specs_and_sources, errors = @sf.spec_for_dependency dep diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index 8ce8293f33..9395e34f75 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require "benchmark" require_relative "helper" require "date" @@ -10,7 +11,7 @@ require "rubygems/installer" require "rubygems/platform" class TestGemSpecification < Gem::TestCase - LEGACY_YAML_SPEC = <<-EOF.freeze + LEGACY_YAML_SPEC = <<-EOF --- !ruby/object:Gem::Specification rubygems_version: "1.0" name: keyedlist @@ -29,7 +30,7 @@ email: flgr@ccan.de has_rdoc: true EOF - LEGACY_RUBY_SPEC = <<-EOF.freeze + LEGACY_RUBY_SPEC = <<-EOF Gem::Specification.new do |s| s.name = %q{keyedlist} s.version = %q{0.4.0} @@ -55,7 +56,6 @@ end s.add_dependency "jabber4r", "> 0.0.0" s.add_dependency "pqa", ["> 0.4", "<= 0.6"] - s.mark_version s.files = %w[lib/code.rb] end end @@ -68,7 +68,6 @@ end s.license = "MIT" s.platform = platform - s.mark_version s.files = %w[lib/code.rb] s.installed_by_version = v("2.2") end @@ -89,12 +88,12 @@ end Gem.instance_variable_set(:'@default_source_date_epoch', nil) @a1 = util_spec "a", "1" do |s| + s.required_ruby_version = ">= 2.3.0" s.executable = "exec" s.test_file = "test/suite.rb" s.requirements << "A working computer" s.license = "MIT" - s.mark_version s.files = %w[lib/code.rb] end @@ -691,7 +690,7 @@ end version ] - actual_value = Gem::Specification.attribute_names.map {|a| a.to_s }.sort + actual_value = Gem::Specification.attribute_names.map(&:to_s).sort assert_equal expected_value, actual_value end @@ -796,26 +795,6 @@ dependencies: [] assert_equal File.join(@tempdir, "a-2.gemspec"), spec.loaded_from end - if RUBY_ENGINE == "ruby" && RUBY_VERSION < "2.7" - def test_self_load_tainted - full_path = @a2.spec_file - write_file full_path do |io| - io.write @a2.to_ruby_for_cache - end - - full_path.taint - loader = Thread.new { $SAFE = 1; Gem::Specification.load full_path } - spec = loader.value - - @a2.files.clear - - assert_equal @a2, spec - - ensure - $SAFE = 0 - end - end - def test_self_load_escape_curly @a2.name = 'a};raise "improper escaping";%q{' @@ -962,13 +941,13 @@ dependencies: [] install_specs @a1 assert_includes Gem::Specification.all_names, "a-1" - assert_includes Gem::Specification.stubs.map {|s| s.full_name }, "a-1" + assert_includes Gem::Specification.stubs.map(&:full_name), "a-1" uninstall_gem @a1 Gem::Specification.reset refute_includes Gem::Specification.all_names, "a-1" - refute_includes Gem::Specification.stubs.map {|s| s.full_name }, "a-1" + refute_includes Gem::Specification.stubs.map(&:full_name), "a-1" end def test_self_remove_spec_removed @@ -983,31 +962,34 @@ dependencies: [] Gem::Specification.reset refute_includes Gem::Specification.all_names, "a-1" - refute_includes Gem::Specification.stubs.map {|s| s.full_name }, "a-1" + refute_includes Gem::Specification.stubs.map(&:full_name), "a-1" end def test_self_stubs_for_lazy_loading Gem.loaded_specs.clear - Gem::Specification.class_variable_set(:@@stubs, nil) + + specification_record = Gem::Specification.specification_record + + specification_record.instance_variable_set(:@stubs, nil) dir_standard_specs = File.join Gem.dir, "specifications" save_gemspec("a-1", "1", dir_standard_specs) {|s| s.name = "a" } save_gemspec("b-1", "1", dir_standard_specs) {|s| s.name = "b" } - assert_equal ["a-1"], Gem::Specification.stubs_for("a").map {|s| s.full_name } - assert_equal 1, Gem::Specification.class_variable_get(:@@stubs_by_name).length - assert_equal ["b-1"], Gem::Specification.stubs_for("b").map {|s| s.full_name } - assert_equal 2, Gem::Specification.class_variable_get(:@@stubs_by_name).length + assert_equal ["a-1"], Gem::Specification.stubs_for("a").map(&:full_name) + assert_equal 1, specification_record.instance_variable_get(:@stubs_by_name).length + assert_equal ["b-1"], Gem::Specification.stubs_for("b").map(&:full_name) + assert_equal 2, specification_record.instance_variable_get(:@stubs_by_name).length assert_equal( - Gem::Specification.stubs_for("a").map {|s| s.object_id }, - Gem::Specification.stubs_for("a").map {|s| s.object_id } + Gem::Specification.stubs_for("a").map(&:object_id), + Gem::Specification.stubs_for("a").map(&:object_id) ) Gem.loaded_specs.delete "a" Gem.loaded_specs.delete "b" - Gem::Specification.class_variable_set(:@@stubs, nil) + specification_record.instance_variable_set(:@stubs, nil) end def test_self_stubs_for_no_lazy_loading_after_all_specs_setup @@ -1015,7 +997,7 @@ dependencies: [] save_gemspec("b-1", "1", File.join(Gem.dir, "specifications")) {|s| s.name = "b" } - assert_equal [], Gem::Specification.stubs_for("b").map {|s| s.full_name } + assert_equal [], Gem::Specification.stubs_for("b").map(&:full_name) end def test_self_stubs_for_mult_platforms @@ -1034,7 +1016,7 @@ dependencies: [] v = "1.1.1" platforms = ["x86-mingw32", "x64-mingw32"] - #create specs + # create specs platforms.each do |plat| spec = Gem::Specification.new(gem, v) {|s| s.platform = plat } File.open File.join(user_spec_dir, "#{gem}-#{v}-#{plat}.gemspec"), "w" do |io| @@ -1068,19 +1050,46 @@ dependencies: [] end def test_handles_private_null_type + yaml_defined = Object.const_defined?("YAML") + path = File.expand_path "data/pry-0.4.7.gemspec.rz", __dir__ data = Marshal.load Gem::Util.inflate(Gem.read_binary(path)) assert_instance_of Gem::Specification, data + + assert_equal(yaml_defined, Object.const_defined?("YAML")) end def test_handles_dependencies_with_syck_requirements_bug + yaml_defined = Object.const_defined?("YAML") + path = File.expand_path "data/excon-0.7.7.gemspec.rz", __dir__ data = Marshal.load Gem::Util.inflate(Gem.read_binary(path)) assert_instance_of Gem::Specification, data + + assert_equal(yaml_defined, Object.const_defined?("YAML")) + end + + def test_handles_dependencies_with_other_syck_requirements_argument_error + yaml_defined = Object.const_defined?("YAML") + + data = Marshal.dump(Gem::Specification.new do |s| + v = Gem::Version.allocate + v.instance_variable_set :@version, "YAML::Syck::DefaultKey" + s.instance_variable_set :@version, v + end) + + assert_raise(ArgumentError) { Marshal.load(data) } + out, err = capture_output do + assert_raise(ArgumentError) { Marshal.load(data) } + end + assert_empty out + assert_empty err + + assert_equal(yaml_defined, Object.const_defined?("YAML")) end def test_initialize @@ -1186,10 +1195,13 @@ dependencies: [] assert_same spec.bindir, dup_spec.bindir assert_equal ">= 0", spec.required_ruby_version.to_s - assert_same spec.required_ruby_version, dup_spec.required_ruby_version + assert_equal spec.required_ruby_version, dup_spec.required_ruby_version + refute_same spec.required_ruby_version, dup_spec.required_ruby_version assert_equal ">= 0", spec.required_rubygems_version.to_s - assert_same spec.required_rubygems_version, + assert_equal spec.required_rubygems_version, + dup_spec.required_rubygems_version + refute_same spec.required_rubygems_version, dup_spec.required_rubygems_version end @@ -1199,7 +1211,7 @@ dependencies: [] s.version = "1" end - spec.instance_variable_set :@licenses, (class << (Object.new);self;end) + spec.instance_variable_set :@licenses, (class << Object.new;self;end) spec.loaded_from = "/path/to/file" e = assert_raise Gem::FormatException do @@ -1252,7 +1264,7 @@ dependencies: [] awesome.add_dependency :gem_name end - assert_equal %w[true gem_name], gem.dependencies.map {|dep| dep.name } + assert_equal %w[true gem_name], gem.dependencies.map(&:name) end def test_add_dependency_from_existing_dependency @@ -1322,9 +1334,7 @@ dependencies: [] assert_empty @ext.build_args - File.open @ext.build_info_file, "w" do |io| - io.puts - end + File.open @ext.build_info_file, "w", &:puts assert_empty @ext.build_args @@ -1444,15 +1454,15 @@ dependencies: [] end FileUtils.mkdir_p File.join @ext.base_dir, "extensions" - FileUtils.chmod 0555, @ext.base_dir - FileUtils.chmod 0555, File.join(@ext.base_dir, "extensions") + FileUtils.chmod 0o555, @ext.base_dir + FileUtils.chmod 0o555, File.join(@ext.base_dir, "extensions") @ext.build_extensions assert_path_not_exist @ext.extension_dir ensure - unless ($DEBUG || win_platform? || Process.uid.zero? || Gem.java_platform?) - FileUtils.chmod 0755, File.join(@ext.base_dir, "extensions") - FileUtils.chmod 0755, @ext.base_dir + unless $DEBUG || Gem.win_platform? || Process.uid.zero? || Gem.java_platform? + FileUtils.chmod 0o755, File.join(@ext.base_dir, "extensions") + FileUtils.chmod 0o755, @ext.base_dir end end @@ -1477,14 +1487,14 @@ dependencies: [] end FileUtils.rm_r File.join @gemhome, "extensions" - FileUtils.chmod 0555, @gemhome + FileUtils.chmod 0o555, @gemhome @ext.build_extensions gem_make_out = File.join @ext.extension_dir, "gem_make.out" assert_path_not_exist gem_make_out ensure - FileUtils.chmod 0755, @gemhome + FileUtils.chmod 0o755, @gemhome end def test_build_extensions_none @@ -1539,7 +1549,7 @@ dependencies: [] refute @ext.contains_requirable_file? "nonexistent" end - expected = "Ignoring ext-1 because its extensions are not built. " + + expected = "Ignoring ext-1 because its extensions are not built. " \ "Try: gem pristine ext --version 1\n" assert_equal expected, err @@ -1555,6 +1565,17 @@ dependencies: [] assert_empty err end + def test_contains_requirable_file_extension_soext + ext_spec + dlext = RbConfig::CONFIG["DLEXT"] + @ext.files += ["lib/ext.#{dlext}"] + + FileUtils.mkdir_p @ext.extension_dir + FileUtils.touch File.join(@ext.extension_dir, "ext.#{dlext}") + FileUtils.touch File.join(@ext.extension_dir, "gem.build_complete") + assert @ext.contains_requirable_file? "ext.so" + end + def test_date assert_date @a1.date end @@ -1592,12 +1613,12 @@ dependencies: [] def test_date_tolerates_hour_sec_zulu @a1.date = "2012-01-12 11:22:33.4444444 Z" - assert_equal Time.utc(2012,01,12,0,0,0), @a1.date + assert_equal Time.utc(2012,1,12,0,0,0), @a1.date end def test_date_tolerates_hour_sec_and_timezone @a1.date = "2012-01-12 11:22:33.4444444 +02:33" - assert_equal Time.utc(2012,01,12,0,0,0), @a1.date + assert_equal Time.utc(2012,1,12,0,0,0), @a1.date end def test_date_use_env_source_date_epoch @@ -1684,8 +1705,8 @@ dependencies: [] end def test_extension_dir - enable_shared, RbConfig::CONFIG["ENABLE_SHARED"] = - RbConfig::CONFIG["ENABLE_SHARED"], "no" + enable_shared = RbConfig::CONFIG["ENABLE_SHARED"] + RbConfig::CONFIG["ENABLE_SHARED"] = "no" ext_spec @@ -1701,11 +1722,11 @@ dependencies: [] end def test_extension_dir_override - enable_shared, RbConfig::CONFIG["ENABLE_SHARED"] = - RbConfig::CONFIG["ENABLE_SHARED"], "no" + enable_shared = RbConfig::CONFIG["ENABLE_SHARED"] + RbConfig::CONFIG["ENABLE_SHARED"] = "no" class << Gem - alias orig_default_ext_dir_for default_ext_dir_for + alias_method :orig_default_ext_dir_for, :default_ext_dir_for remove_method :default_ext_dir_for @@ -1727,7 +1748,7 @@ dependencies: [] class << Gem remove_method :default_ext_dir_for - alias default_ext_dir_for orig_default_ext_dir_for + alias_method :default_ext_dir_for, :orig_default_ext_dir_for end end @@ -1839,7 +1860,7 @@ dependencies: [] end def test_full_gem_path_double_slash - gemhome = @gemhome.to_s.sub(/\w\//, '\&/') + gemhome = @gemhome.to_s.sub(%r{\w/}, '\&/') @a1.loaded_from = File.join gemhome, "specifications", @a1.spec_name expected = File.join @gemhome, "gems", @a1.full_name @@ -1857,7 +1878,7 @@ dependencies: [] @a1.instance_variable_set :@new_platform, "mswin32" assert_equal "a-1-mswin32", @a1.full_name, "legacy" - return if win_platform? + return if Gem.win_platform? @a1 = Gem::Specification.new "a", 1 @a1.platform = "current" @@ -1866,9 +1887,9 @@ dependencies: [] def test_full_name_windows test_cases = { - "i386-mswin32" => "a-1-x86-mswin32-60", - "i386-mswin32_80" => "a-1-x86-mswin32-80", - "i386-mingw32" => "a-1-x86-mingw32", + "i386-mswin32" => "a-1-x86-mswin32-60", + "i386-mswin32_80" => "a-1-x86-mswin32-80", + "i386-mingw32" => "a-1-x86-mingw32", } test_cases.each do |arch, expected| @@ -1969,10 +1990,10 @@ dependencies: [] assert_equal Gem::Platform::RUBY, @a1.platform test_cases = { - "i386-mswin32" => ["x86", "mswin32", "60"], + "i386-mswin32" => ["x86", "mswin32", "60"], "i386-mswin32_80" => ["x86", "mswin32", "80"], - "i386-mingw32" => ["x86", "mingw32", nil ], - "x86-darwin8" => ["x86", "darwin", "8" ], + "i386-mingw32" => ["x86", "mingw32", nil], + "x86-darwin8" => ["x86", "darwin", "8"], } test_cases.each do |arch, expected| @@ -1999,12 +2020,6 @@ dependencies: [] assert_equal Gem::Platform.new("ppc-darwin"), @a1.platform end - def test_prerelease_spec_adds_required_rubygems_version - @prerelease = util_spec("tardis", "2.2.0.a") - refute @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new("1.3.1")) - assert @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new("1.4.0")) - end - def test_require_paths enable_shared "no" do ext_spec @@ -2186,7 +2201,7 @@ dependencies: [] expected = %w[rake jabber4r pqa] - assert_equal expected, @c1.runtime_dependencies.map {|d| d.name } + assert_equal expected, @c1.runtime_dependencies.map(&:name) end def test_spaceship_name @@ -2194,7 +2209,7 @@ dependencies: [] s2 = util_spec "b", "1" assert_equal(-1, (s1 <=> s2)) - assert_equal(0, (s1 <=> s1)) + assert_equal(0, (s1 <=> s1)) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(1, (s2 <=> s1)) end @@ -2205,7 +2220,7 @@ dependencies: [] end assert_equal(-1, (s1 <=> s2)) - assert_equal(0, (s1 <=> s1)) + assert_equal(0, (s1 <=> s1)) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(1, (s2 <=> s1)) end @@ -2214,7 +2229,7 @@ dependencies: [] s2 = util_spec "a", "2" assert_equal(-1, (s1 <=> s2)) - assert_equal(0, (s1 <=> s1)) + assert_equal(0, (s1 <=> s1)) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands assert_equal(1, (s2 <=> s1)) end @@ -2263,7 +2278,7 @@ dependencies: [] Gem::Specification.new do |s| s.name = "a".freeze - s.version = "2" + s.version = "2".freeze s.required_rubygems_version = Gem::Requirement.new(\"> 0\".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze, "other".freeze] @@ -2278,7 +2293,7 @@ Gem::Specification.new do |s| s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION} - s.add_runtime_dependency(%q<b>.freeze, [\"= 1\"]) + s.add_runtime_dependency(%q<b>.freeze, [\"= 1\".freeze]) end SPEC @@ -2303,7 +2318,7 @@ end Gem::Specification.new do |s| s.name = "a".freeze - s.version = "2" + s.version = "2".freeze s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] @@ -2336,7 +2351,7 @@ end Gem::Specification.new do |s| s.name = "a".freeze - s.version = "2" + s.version = "2".freeze s.required_rubygems_version = Gem::Requirement.new(\"> 0\".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] @@ -2348,11 +2363,11 @@ Gem::Specification.new do |s| s.rubygems_version = "#{Gem::VERSION}".freeze s.summary = "this is a summary".freeze - s.installed_by_version = "#{Gem::VERSION}" if s.respond_to? :installed_by_version + s.installed_by_version = "#{Gem::VERSION}".freeze if s.respond_to? :installed_by_version s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION} - s.add_runtime_dependency(%q<b>.freeze, [\"= 1\"]) + s.add_runtime_dependency(%q<b>.freeze, ["= 1".freeze]) end SPEC @@ -2372,19 +2387,19 @@ end ruby_code = @c1.to_ruby local = Gem::Platform.local - expected_platform = "[#{local.cpu.inspect}, #{local.os.inspect}, #{local.version.inspect}]" + expected_platform = "[#{local.cpu.inspect}.freeze, #{local.os.inspect}.freeze, #{local.version.inspect}.freeze]" stub_require_paths = @c1.instance_variable_get(:@require_paths).join "\u0000" extensions = @c1.extensions.join "\u0000" expected = <<-SPEC # -*- encoding: utf-8 -*- -# stub: a 1 #{win_platform? ? "x86-mswin32-60" : "x86-darwin-8"} #{stub_require_paths} +# stub: a 1 #{Gem.win_platform? ? "x86-mswin32-60" : "x86-darwin-8"} #{stub_require_paths} # stub: #{extensions} Gem::Specification.new do |s| s.name = "a".freeze - s.version = "1" + s.version = "1".freeze s.platform = Gem::Platform.new(#{expected_platform}) s.required_rubygems_version = Gem::Requirement.new(\">= 0\".freeze) if s.respond_to? :required_rubygems_version= @@ -2405,9 +2420,9 @@ Gem::Specification.new do |s| s.specification_version = 4 - s.add_runtime_dependency(%q<rake>.freeze, [\"> 0.4\"]) - s.add_runtime_dependency(%q<jabber4r>.freeze, [\"> 0.0.0\"]) - s.add_runtime_dependency(%q<pqa>.freeze, [\"> 0.4\", \"<= 0.6\"]) + s.add_runtime_dependency(%q<rake>.freeze, [\"> 0.4\".freeze]) + s.add_runtime_dependency(%q<jabber4r>.freeze, [\"> 0.0.0\".freeze]) + s.add_runtime_dependency(%q<pqa>.freeze, [\"> 0.4\".freeze, \"<= 0.6\".freeze]) end SPEC @@ -2423,7 +2438,7 @@ end s.add_dependency "b", ["~> 1.0", ">= 1.0.0"] end - assert_includes spec.to_ruby, '"~> 1.0", ">= 1.0.0"' + assert_includes spec.to_ruby, '"~> 1.0".freeze, ">= 1.0.0".freeze' end def test_to_ruby_legacy @@ -2438,13 +2453,13 @@ end def test_to_ruby_nested_hash metadata = {} - metadata[metadata] = metadata + metadata[:metadata] = {} @a2.metadata = metadata ruby = @a2.to_ruby - assert_match %r%^ s\.metadata = \{ "%, ruby + assert_match(/^ s\.metadata = \{ "/, ruby) end def test_to_ruby_platform @@ -2461,7 +2476,7 @@ end def test_to_yaml yaml_str = @a1.to_yaml - refute_match %r{!!null}, yaml_str + refute_match(/!!null/, yaml_str) same_spec = Gem::Specification.from_yaml(yaml_str) @@ -2482,7 +2497,7 @@ end def test_to_yaml_platform_empty_string @a1.instance_variable_set :@original_platform, "" - assert_match %r{^platform: ruby$}, @a1.to_yaml + assert_match(/^platform: ruby$/, @a1.to_yaml) end def test_to_yaml_platform_legacy @@ -2500,7 +2515,27 @@ end def test_to_yaml_platform_nil @a1.instance_variable_set :@original_platform, nil - assert_match %r{^platform: ruby$}, @a1.to_yaml + assert_match(/^platform: ruby$/, @a1.to_yaml) + end + + def test_to_yaml_no_autorequire + yaml_str = @a1.to_yaml + + refute_match(/^autorequire:/, yaml_str) + end + + def test_to_yaml_no_signing_key + @a1.signing_key = nil + yaml_str = @a1.to_yaml + + refute_match(/^signing_key:/, yaml_str) + end + + def test_to_yaml_no_post_install_message + @a1.post_install_message = nil + yaml_str = @a1.to_yaml + + refute_match(/^post_install_message:/, yaml_str) end def test_validate @@ -2511,10 +2546,21 @@ end end end - def x(s); s.gsub(/xxx/, ""); end - def w; x "WARxxxNING"; end - def t; x "TOxxxDO"; end - def f; x "FxxxIXME"; end + def x(s) + s.gsub(/xxx/, "") + end + + def w + x "WARxxxNING" + end + + def t + x "TOxxxDO" + end + + def f + x "FxxxIXME" + end def test_validate_authors util_setup_validate @@ -2598,18 +2644,18 @@ end #{w}: prerelease dependency on c (>= 2.0.rc2, development) is not recommended #{w}: open-ended dependency on i (>= 1.2) is not recommended if i is semantically versioned, use: - add_runtime_dependency 'i', '~> 1.2' + add_runtime_dependency "i", "~> 1.2" #{w}: open-ended dependency on j (>= 1.2.3) is not recommended if j is semantically versioned, use: - add_runtime_dependency 'j', '~> 1.2', '>= 1.2.3' + add_runtime_dependency "j", "~> 1.2", ">= 1.2.3" #{w}: open-ended dependency on k (> 1.2) is not recommended if k is semantically versioned, use: - add_runtime_dependency 'k', '~> 1.2', '> 1.2' + add_runtime_dependency "k", "~> 1.2", "> 1.2" #{w}: open-ended dependency on l (> 1.2.3) is not recommended if l is semantically versioned, use: - add_runtime_dependency 'l', '~> 1.2', '> 1.2.3' + add_runtime_dependency "l", "~> 1.2", "> 1.2.3" #{w}: open-ended dependency on o (>= 0) is not recommended - use a bounded requirement, such as '~> x.y' + use a bounded requirement, such as "~> x.y" #{w}: See https://guides.rubygems.org/specification-reference/ for help EXPECTED @@ -2633,9 +2679,9 @@ end expected = <<-EXPECTED duplicate dependency on b (>= 1.2.3), (~> 1.2) use: - add_runtime_dependency 'b', '>= 1.2.3', '~> 1.2' + add_runtime_dependency "b", ">= 1.2.3", "~> 1.2" duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: - add_development_dependency 'c', '>= 1.2.3', '~> 1.2' + add_development_dependency "c", ">= 1.2.3", "~> 1.2" EXPECTED assert_equal expected, e.message @@ -2662,6 +2708,53 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: end end + def test_validate_no_required_ruby_versions + util_setup_validate + + Dir.chdir @tempdir do + use_ui @ui do + @a1.required_ruby_version = nil # reset + @a1.validate + end + + assert_equal <<-EXPECTED, @ui.error +#{w}: make sure you specify the oldest ruby version constraint (like \">= 3.0\") that you want your gem to support by setting the `required_ruby_version` gemspec attribute +#{w}: See https://guides.rubygems.org/specification-reference/ for help + EXPECTED + end + end + + def test_validate_open_required_ruby_versions + util_setup_validate + + Dir.chdir @tempdir do + @a1.required_ruby_version = ">= 0" + + use_ui @ui do + @a1.validate + end + + assert_equal <<-EXPECTED, @ui.error +#{w}: make sure you specify the oldest ruby version constraint (like \">= 3.0\") that you want your gem to support by setting the `required_ruby_version` gemspec attribute +#{w}: See https://guides.rubygems.org/specification-reference/ for help + EXPECTED + end + end + + def test_validate_valid_required_ruby_versions + util_setup_validate + + Dir.chdir @tempdir do + @a1.required_ruby_version = ">= 2.3.0" + + use_ui @ui do + @a1.validate + end + + assert_equal "", @ui.error, "warning" + end + end + def test_validate_prerelease_dependencies_with_prerelease_version util_setup_validate @@ -2677,6 +2770,23 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: end end + def test_validate_self_referencing_dependencies + util_setup_validate + + Dir.chdir @tempdir do + @a1.add_runtime_dependency @a1.name, "1" + + use_ui @ui do + @a1.validate + end + + assert_equal <<-EXPECTED, @ui.error +#{w}: Self referencing dependency is unnecessary and strongly discouraged. +#{w}: See https://guides.rubygems.org/specification-reference/ for help + EXPECTED + end + end + def test_validate_rake_extension_have_rake_dependency_warning util_setup_validate @@ -2688,7 +2798,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: @a1.validate end - assert_match(/add rake as a dependency/, @ui.error) + assert_match(/add rake as a runtime dependency/, @ui.error) end end @@ -2704,7 +2814,40 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: @a1.validate end - refute_match(/add rake as a dependency/, @ui.error) + refute_match(/add rake as a runtime dependency/, @ui.error) + end + end + + def test_validate_rust_extension_have_missing_cargo_toml_error + util_setup_validate + + Dir.chdir @tempdir do + @a1.extensions = ["Cargo.toml"] + File.write File.join(@tempdir, "Cargo.toml"), "" + + e = assert_raise Gem::InvalidSpecificationException do + use_ui @ui do + @a1.validate + end + end + + assert_match(/but Cargo.lock is not part of the gem files/, e.message) + end + end + + def test_validate_rust_extension_have_no_missing_cargo_toml_error + util_setup_validate + + Dir.chdir @tempdir do + @a1.extensions = ["Cargo.toml"] + @a1.files << "Cargo.toml" + @a1.files << "Cargo.lock" + File.write File.join(@tempdir, "Cargo.toml"), "" + File.write File.join(@tempdir, "Cargo.lock"), "" + + use_ui @ui do + @a1.validate + end end end @@ -2835,7 +2978,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: end def test_validate_empty_require_paths - if win_platform? + if Gem.win_platform? pend "test_validate_empty_require_paths skipped on MS Windows (symlink)" else util_setup_validate @@ -2851,7 +2994,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: end def test_validate_files - pend "test_validate_files skipped on MS Windows (symlink)" if win_platform? + pend "test_validate_files skipped on MS Windows (symlink)" if Gem.win_platform? util_setup_validate @a1.files += ["lib", "lib2"] @@ -2880,7 +3023,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: { b: Gem::Dependency.new("x","1") } end - specification.define_singleton_method(:find_all_by_name) do |dep_name| + specification.define_singleton_method(:find_all_by_name) do |_dep_name| [] end @@ -2907,7 +3050,7 @@ Please report a bug if this causes problems. { b: Gem::Dependency.new("x","1") } end - specification.define_singleton_method(:find_all_by_name) do |dep_name| + specification.define_singleton_method(:find_all_by_name) do |_dep_name| [ specification.new {|s| s.name = "z", s.version = Gem::Version.new("1") }, specification.new {|s| s.name = "z", s.version = Gem::Version.new("2") }, @@ -2942,7 +3085,7 @@ Please report a bug if this causes problems. def set_orig(cls) s_cls = cls.singleton_class - s_cls.send :alias_method, :orig_unresolved_deps , :unresolved_deps + s_cls.send :alias_method, :orig_unresolved_deps, :unresolved_deps s_cls.send :alias_method, :orig_find_all_by_name, :find_all_by_name end @@ -3015,11 +3158,23 @@ Please report a bug if this causes problems. end assert_match <<-WARNING, @ui.error -WARNING: licenses is empty, but is recommended. Use a license identifier from -http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. +WARNING: licenses is empty, but is recommended. Use an license identifier from +https://spdx.org/licenses or 'Nonstandard' for a nonstandard license, +or set it to nil if you don't want to specify a license. WARNING end + def test_validate_nil_license + util_setup_validate + + use_ui @ui do + @a1.license = nil + @a1.validate + end + + assert_empty @ui.error + end + def test_validate_license_in_a_non_packaging_context util_setup_validate @@ -3032,7 +3187,7 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. end def test_removed_methods - assert_equal Gem::Specification::REMOVED_METHODS, [:rubyforge_project=] + assert_equal Gem::Specification::REMOVED_METHODS, [:rubyforge_project=, :mark_version] end def test_validate_removed_rubyforge_project @@ -3055,8 +3210,9 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. end assert_match <<-WARNING, @ui.error -WARNING: license value 'BSD' is invalid. Use a license identifier from -http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. +WARNING: License identifier 'BSD' is invalid. Use an identifier from +https://spdx.org/licenses or 'Nonstandard' for a nonstandard license, +or set it to nil if you don't want to specify a license. WARNING end @@ -3071,7 +3227,7 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. assert_empty @ui.error end - def test_validate_license_values_plus + def test_validate_deprecated_license_values_plus util_setup_validate use_ui @ui do @@ -3079,7 +3235,11 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. @a1.validate end - assert_empty @ui.error + assert_match <<-WARNING, @ui.error +WARNING: License identifier 'GPL-2.0+' is deprecated. Use an identifier from +https://spdx.org/licenses or 'Nonstandard' for a nonstandard license, +or set it to nil if you don't want to specify a license. + WARNING end def test_validate_license_values_or_later @@ -3097,7 +3257,7 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. util_setup_validate use_ui @ui do - @a1.licenses = ["GPL-2.0+ WITH Autoconf-exception-2.0"] + @a1.licenses = ["GPL-2.0-or-later WITH Autoconf-exception-2.0"] @a1.validate end @@ -3113,12 +3273,14 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. end assert_match <<-WARNING, @ui.error -WARNING: license value 'GPL-2.0+ FOO' is invalid. Use a license identifier from -http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. +WARNING: License identifier 'GPL-2.0+ FOO' is invalid. Use an identifier from +https://spdx.org/licenses or 'Nonstandard' for a nonstandard license, +or set it to nil if you don't want to specify a license. WARNING assert_match <<-WARNING, @ui.error -WARNING: license value 'GPL-2.0 FOO' is invalid. Use a license identifier from -http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. +WARNING: License identifier 'GPL-2.0+ FOO' is invalid. Use an identifier from +https://spdx.org/licenses or 'Nonstandard' for a nonstandard license, +or set it to nil if you don't want to specify a license. WARNING end @@ -3126,13 +3288,29 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. util_setup_validate use_ui @ui do - @a1.licenses = ["GPL-2.0+ WITH Autocofn-exception-2.0"] + @a1.licenses = ["GPL-2.0-only WITH Autocofn-exception-2.0"] @a1.validate end assert_match <<-WARNING, @ui.error -WARNING: license value 'GPL-2.0+ WITH Autocofn-exception-2.0' is invalid. Use a license identifier from -http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. +WARNING: License identifier 'GPL-2.0-only WITH Autocofn-exception-2.0' is invalid. Use an identifier from +https://spdx.org/licenses or 'Nonstandard' for a nonstandard license, +or set it to nil if you don't want to specify a license. + WARNING + end + + def test_validate_license_with_deprecated_exception + util_setup_validate + + use_ui @ui do + @a1.licenses = ["GPL-2.0-only WITH Nokia-Qt-exception-1.1"] + @a1.validate + end + + assert_match <<-WARNING, @ui.error +WARNING: Exception identifier at 'GPL-2.0-only WITH Nokia-Qt-exception-1.1' is deprecated. Use an identifier from +https://spdx.org/licenses or 'Nonstandard' for a nonstandard license, +or set it to nil if you don't want to specify a license. WARNING end @@ -3145,8 +3323,9 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. end assert_match <<-WARNING, @ui.error -WARNING: license value 'ruby' is invalid. Use a license identifier from -http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. +WARNING: License identifier 'ruby' is invalid. Use an identifier from +https://spdx.org/licenses or 'Nonstandard' for a nonstandard license, +or set it to nil if you don't want to specify a license. Did you mean 'Ruby'? WARNING end @@ -3244,7 +3423,7 @@ Did you mean 'Ruby'? spec.validate end - assert_match %r{^#{name}}, e.message + assert_match(/^#{name}/, e.message) end end end @@ -3255,8 +3434,8 @@ Did you mean 'Ruby'? util_setup_validate Dir.chdir @tempdir do - File.chmod 0640, File.join("lib", "code.rb") - File.chmod 0640, File.join("bin", "exec") + File.chmod 0o640, File.join("lib", "code.rb") + File.chmod 0o640, File.join("bin", "exec") use_ui @ui do @a1.validate @@ -3301,12 +3480,17 @@ Did you mean 'Ruby'? util_setup_validate @a1.rubygems_version = "3" - e = assert_raise Gem::InvalidSpecificationException do + + use_ui @ui do @a1.validate end - assert_equal "expected RubyGems version #{Gem::VERSION}, was 3", - e.message + expected = <<~EXPECTED + #{w}: expected RubyGems version #{Gem::VERSION}, was 3 + #{w}: See https://guides.rubygems.org/specification-reference/ for help + EXPECTED + + assert_equal expected, @ui.error end def test_validate_specification_version @@ -3404,7 +3588,7 @@ Did you mean 'Ruby'? capture_output do Gem::Specification.load(specfile.path) end - rescue => e + rescue StandardError => e name_rexp = Regexp.new(Regexp.escape(specfile.path)) assert e.backtrace.grep(name_rexp).any? end @@ -3449,10 +3633,10 @@ Did you mean 'Ruby'? @m1 = quick_gem "m", "1" do |s| s.files = %w[lib/code.rb] s.metadata = { - "one" => "two", - "home" => "three", + "one" => "two", + "home" => "three", "homepage_uri" => "https://example.com/user/repo", - "funding_uri" => "https://example.com/donate", + "funding_uri" => "https://example.com/donate", } end @@ -3547,6 +3731,39 @@ Did you mean 'Ruby'? end end + def test_metadata_link_validation_warns_for_duplicates + util_setup_validate + + Dir.chdir @tempdir do + @m2 = quick_gem "m", "2" do |s| + s.required_ruby_version = ">= 2.3.0" + s.files = %w[lib/code.rb] + s.licenses = "BSD-2-Clause" + s.metadata = { + "source_code_uri" => "http://example.com", + "homepage_uri" => "http://example.com", + "changelog_uri" => "http://example.com/changelog", + } + end + + use_ui @ui do + @m2.validate + end + + expected = <<~EXPECTED + #{w}: You have specified the uri: + http://example.com + for all of the following keys: + homepage_uri + source_code_uri + Only the first one will be shown on rubygems.org + #{w}: See https://guides.rubygems.org/specification-reference/ for help + EXPECTED + + assert_equal expected, @ui.error, "warning" + end + end + def test_metadata_specs @m1 = quick_gem "m", "1" do |s| s.files = %w[lib/code.rb] @@ -3559,7 +3776,7 @@ Did you mean 'Ruby'? Gem::Specification.new do |s| s.name = "m".freeze - s.version = "1" + s.version = "1".freeze s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "one" => "two", "two" => "three" } if s.respond_to? :metadata= @@ -3658,6 +3875,13 @@ end assert Gem::Specification.find_by_name "q" end + def test_find_by_name_with_only_prereleases_with_requirements + q = util_spec "q", "2.a" + install_specs q + + assert Gem::Specification.find_by_name "q", ">= 1" + end + def test_find_by_name_prerelease b = util_spec "b", "2.a" @@ -3676,6 +3900,23 @@ end assert Gem::Specification.find_by_name "b", ">1" end + def test_find_by_full_name + pl = Gem::Platform.new "x86_64-linux" + + a = util_spec "a", "1" + install_specs a + + a_pl = util_spec("a", "1") {|s| s.platform = pl } + install_specs a_pl + + assert_equal a, Gem::Specification.find_by_full_name("a-1") + assert_equal a_pl, Gem::Specification.find_by_full_name("a-1-x86_64-linux") + + assert_nil Gem::Specification.find_by_full_name("a-2") + assert_nil Gem::Specification.find_by_full_name("b-1") + assert_nil Gem::Specification.find_by_full_name("a-1-arm64-linux") + end + def test_find_by_path a = util_spec "foo", "1", nil, "lib/foo.rb" @@ -3733,7 +3974,7 @@ end FileUtils.touch File.join("lib", "code.rb") FileUtils.touch File.join("test", "suite.rb") - File.open "bin/exec", "w", 0755 do |fp| + File.open "bin/exec", "w", 0o755 do |fp| fp.puts "#!#{Gem.ruby}" end ensure diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb index 3dbc346271..b1fcb3bc26 100644 --- a/test/rubygems/test_gem_stream_ui.rb +++ b/test/rubygems/test_gem_stream_ui.rb @@ -1,19 +1,20 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/user_interaction" -require "timeout" +require "rubygems/vendored_timeout" class TestGemStreamUI < Gem::TestCase - # increase timeout with MJIT for --jit-wait testing - mjit_enabled = defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? - SHORT_TIMEOUT = (RUBY_ENGINE == "ruby" && !mjit_enabled) ? 0.1 : 1.0 + # increase timeout with RJIT for --jit-wait testing + rjit_enabled = defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? + SHORT_TIMEOUT = RUBY_ENGINE == "ruby" && !rjit_enabled ? 0.1 : 1.0 module IsTty attr_accessor :tty def tty? @tty = true unless defined? @tty - return @tty + @tty end alias_method :isatty, :tty? @@ -39,7 +40,7 @@ class TestGemStreamUI < Gem::TestCase end def test_ask - Timeout.timeout(5) do + Gem::Timeout.timeout(5) do expected_answer = "Arthur, King of the Britons" @in.string = "#{expected_answer}\n" actual_answer = @sui.ask("What is your name?") @@ -50,14 +51,14 @@ class TestGemStreamUI < Gem::TestCase def test_ask_no_tty @in.tty = false - Timeout.timeout(SHORT_TIMEOUT) do + Gem::Timeout.timeout(SHORT_TIMEOUT) do answer = @sui.ask("what is your favorite color?") assert_nil answer end end def test_ask_for_password - Timeout.timeout(5) do + Gem::Timeout.timeout(5) do expected_answer = "Arthur, King of the Britons" @in.string = "#{expected_answer}\n" actual_answer = @sui.ask_for_password("What is your name?") @@ -68,7 +69,7 @@ class TestGemStreamUI < Gem::TestCase def test_ask_for_password_no_tty @in.tty = false - Timeout.timeout(SHORT_TIMEOUT) do + Gem::Timeout.timeout(SHORT_TIMEOUT) do answer = @sui.ask_for_password("what is the airspeed velocity of an unladen swallow?") assert_nil answer end @@ -77,7 +78,7 @@ class TestGemStreamUI < Gem::TestCase def test_ask_yes_no_no_tty_with_default @in.tty = false - Timeout.timeout(SHORT_TIMEOUT) do + Gem::Timeout.timeout(SHORT_TIMEOUT) do answer = @sui.ask_yes_no("do coconuts migrate?", false) assert_equal false, answer @@ -89,7 +90,7 @@ class TestGemStreamUI < Gem::TestCase def test_ask_yes_no_no_tty_without_default @in.tty = false - Timeout.timeout(SHORT_TIMEOUT) do + Gem::Timeout.timeout(SHORT_TIMEOUT) do assert_raise(Gem::OperationNotSupportedError) do @sui.ask_yes_no("do coconuts migrate?") end @@ -113,6 +114,36 @@ class TestGemStreamUI < Gem::TestCase assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string end + def test_choose_from_list_0 + @in.puts "0" + @in.rewind + + result = @sui.choose_from_list "which one?", %w[foo bar] + + assert_equal [nil, nil], result + assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string + end + + def test_choose_from_list_over + @in.puts "3" + @in.rewind + + result = @sui.choose_from_list "which one?", %w[foo bar] + + assert_equal [nil, nil], result + assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string + end + + def test_choose_from_list_negative + @in.puts "-1" + @in.rewind + + result = @sui.choose_from_list "which one?", %w[foo bar] + + assert_equal [nil, nil], result + assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string + end + def test_progress_reporter_silent_nil @cfg.verbose = nil reporter = @sui.progress_reporter 10, "hi" diff --git a/test/rubygems/test_gem_stub_specification.rb b/test/rubygems/test_gem_stub_specification.rb index 22a0b6bb6f..fe30a78c0b 100644 --- a/test/rubygems/test_gem_stub_specification.rb +++ b/test/rubygems/test_gem_stub_specification.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/stub_specification" @@ -71,7 +72,7 @@ class TestStubSpecification < Gem::TestCase refute stub.contains_requirable_file? "nonexistent" end - expected = "Ignoring stub_e-2 because its extensions are not built. " + + expected = "Ignoring stub_e-2 because its extensions are not built. " \ "Try: gem pristine stub_e --version 2\n" assert_equal expected, err diff --git a/test/rubygems/test_gem_text.rb b/test/rubygems/test_gem_text.rb index 95cae1287c..8e99610946 100644 --- a/test/rubygems/test_gem_text.rb +++ b/test/rubygems/test_gem_text.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/text" diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index e81a9be0ff..aa5ab0ed67 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "installer_test_case" require "rubygems/uninstaller" @@ -24,7 +25,7 @@ class TestGemUninstaller < Gem::InstallerTestCase def test_initialize_expand_path FileUtils.mkdir_p "foo/bar" - uninstaller = Gem::Uninstaller.new nil, :install_dir => "foo//bar" + uninstaller = Gem::Uninstaller.new nil, install_dir: "foo//bar" assert_match %r{foo/bar$}, uninstaller.instance_variable_get(:@gem_home) end @@ -58,7 +59,7 @@ class TestGemUninstaller < Gem::InstallerTestCase end def test_remove_executables_force_keep - uninstaller = Gem::Uninstaller.new nil, :executables => false + uninstaller = Gem::Uninstaller.new nil, executables: false executable = File.join Gem.bindir(@user_spec.base_dir), "executable" assert File.exist?(executable), "executable not written" @@ -73,7 +74,7 @@ class TestGemUninstaller < Gem::InstallerTestCase end def test_remove_executables_force_remove - uninstaller = Gem::Uninstaller.new nil, :executables => true + uninstaller = Gem::Uninstaller.new nil, executables: true executable = File.join Gem.bindir(@user_spec.base_dir), "executable" assert File.exist?(executable), "executable not written" @@ -88,7 +89,7 @@ class TestGemUninstaller < Gem::InstallerTestCase end def test_remove_executables_user - uninstaller = Gem::Uninstaller.new nil, :executables => true + uninstaller = Gem::Uninstaller.new nil, executables: true use_ui @ui do uninstaller.remove_executables @user_spec @@ -103,7 +104,7 @@ class TestGemUninstaller < Gem::InstallerTestCase def test_remove_executables_user_format Gem::Installer.exec_format = "foo-%s-bar" - uninstaller = Gem::Uninstaller.new nil, :executables => true, :format_executable => true + uninstaller = Gem::Uninstaller.new nil, executables: true, format_executable: true use_ui @ui do uninstaller.remove_executables @user_spec @@ -120,7 +121,7 @@ class TestGemUninstaller < Gem::InstallerTestCase def test_remove_executables_user_format_disabled Gem::Installer.exec_format = "foo-%s-bar" - uninstaller = Gem::Uninstaller.new nil, :executables => true + uninstaller = Gem::Uninstaller.new nil, executables: true use_ui @ui do uninstaller.remove_executables @user_spec @@ -136,7 +137,7 @@ class TestGemUninstaller < Gem::InstallerTestCase def test_remove_not_in_home Dir.mkdir "#{@gemhome}2" - uninstaller = Gem::Uninstaller.new nil, :install_dir => "#{@gemhome}2" + uninstaller = Gem::Uninstaller.new nil, install_dir: "#{@gemhome}2" e = assert_raise Gem::GemNotInHomeException do use_ui ui do @@ -160,7 +161,7 @@ class TestGemUninstaller < Gem::InstallerTestCase FileUtils.ln_s(@gemhome, dir) - uninstaller = Gem::Uninstaller.new nil, :install_dir => symlinked_gem_home + uninstaller = Gem::Uninstaller.new nil, install_dir: symlinked_gem_home use_ui ui do uninstaller.remove @spec @@ -172,12 +173,12 @@ class TestGemUninstaller < Gem::InstallerTestCase def test_remove_plugins write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| - io.write "puts __FILE__" + io.write "# do nothing" end @spec.files += %w[lib/rubygems_plugin.rb] - Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + Gem::Installer.at(Gem::Package.build(@spec), force: true).install plugin_path = File.join Gem.plugindir, "a_plugin.rb" assert File.exist?(plugin_path), "plugin not written" @@ -187,32 +188,91 @@ class TestGemUninstaller < Gem::InstallerTestCase refute File.exist?(plugin_path), "plugin not removed" end - def test_remove_plugins_with_install_dir + def test_uninstall_with_install_dir_removes_plugins write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| - io.write "puts __FILE__" + io.write "# do nothing" end @spec.files += %w[lib/rubygems_plugin.rb] - Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + package = Gem::Package.build(@spec) + + Gem::Installer.at(package, force: true).install plugin_path = File.join Gem.plugindir, "a_plugin.rb" assert File.exist?(plugin_path), "plugin not written" - Dir.mkdir "#{@gemhome}2" - Gem::Uninstaller.new(nil, :install_dir => "#{@gemhome}2").remove_plugins @spec + install_dir = "#{@gemhome}2" + + Gem::Installer.at(package, force: true, install_dir: install_dir).install + + install_dir_plugin_path = File.join install_dir, "plugins/a_plugin.rb" + assert File.exist?(install_dir_plugin_path), "plugin not written" + + Gem::Specification.dirs = [install_dir] + Gem::Uninstaller.new(@spec.name, executables: true, install_dir: install_dir).uninstall assert File.exist?(plugin_path), "plugin unintentionally removed" + refute File.exist?(install_dir_plugin_path), "plugin not removed" + end + + def test_uninstall_with_install_dir_regenerates_plugins + write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| + io.write "# do nothing" + end + + @spec.files += %w[lib/rubygems_plugin.rb] + + install_dir = "#{@gemhome}2" + + package = Gem::Package.build(@spec) + + spec_v9 = @spec.dup + spec_v9.version = "9" + package_v9 = Gem::Package.build(spec_v9) + + Gem::Installer.at(package, force: true, install_dir: install_dir).install + Gem::Installer.at(package_v9, force: true, install_dir: install_dir).install + + install_dir_plugin_path = File.join install_dir, "plugins/a_plugin.rb" + assert File.exist?(install_dir_plugin_path), "plugin not written" + + Gem::Specification.dirs = [install_dir] + Gem::Uninstaller.new(@spec.name, version: "9", executables: true, install_dir: install_dir).uninstall + assert File.exist?(install_dir_plugin_path), "plugin unintentionally removed" + + Gem::Specification.dirs = [install_dir] + Gem::Uninstaller.new(@spec.name, executables: true, install_dir: install_dir).uninstall + refute File.exist?(install_dir_plugin_path), "plugin not removed" + end + + def test_remove_plugins_user_installed + write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| + io.write "# do nothing" + end + + @spec.files += %w[lib/rubygems_plugin.rb] + + Gem::Installer.at(Gem::Package.build(@spec), force: true, user_install: true).install + + plugin_path = File.join Gem.user_dir, "plugins/a_plugin.rb" + assert File.exist?(plugin_path), "plugin not written" + + Gem::Specification.dirs = [Gem.dir, Gem.user_dir] + + Gem::Uninstaller.new(@spec.name, executables: true, force: true, user_install: true).uninstall + + refute File.exist?(plugin_path), "plugin not removed" end def test_regenerate_plugins_for write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| - io.write "puts __FILE__" + io.write "# do nothing" end @spec.files += %w[lib/rubygems_plugin.rb] - Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + Gem::Installer.at(Gem::Package.build(@spec), force: true).install plugin_path = File.join Gem.plugindir, "a_plugin.rb" assert File.exist?(plugin_path), "plugin not written" @@ -246,17 +306,17 @@ class TestGemUninstaller < Gem::InstallerTestCase end def test_uninstall - uninstaller = Gem::Uninstaller.new @spec.name, :executables => true + uninstaller = Gem::Uninstaller.new @spec.name, executables: true gem_dir = File.join @gemhome, "gems", @spec.full_name Gem.pre_uninstall do - sleep(0.1) if win_platform? + sleep(0.1) if Gem.win_platform? assert File.exist?(gem_dir), "gem_dir should exist" end Gem.post_uninstall do - sleep(0.1) if win_platform? + sleep(0.1) if Gem.win_platform? refute File.exist?(gem_dir), "gem_dir should not exist" end @@ -273,7 +333,7 @@ class TestGemUninstaller < Gem::InstallerTestCase install_default_gems spec - uninstaller = Gem::Uninstaller.new spec.name, :executables => true + uninstaller = Gem::Uninstaller.new spec.name, executables: true use_ui @ui do uninstaller.uninstall @@ -293,7 +353,7 @@ class TestGemUninstaller < Gem::InstallerTestCase Gem::Specification.reset - uninstaller = Gem::Uninstaller.new spec.name, :executables => true + uninstaller = Gem::Uninstaller.new spec.name, executables: true ui = Gem::MockGemUi.new "1\ny\n" use_ui ui do @@ -321,20 +381,20 @@ create_makefile '#{@spec.name}' use_ui @ui do path = Gem::Package.build @spec - installer = Gem::Installer.at path, :force => true + installer = Gem::Installer.at path, force: true installer.install end assert_path_exist @spec.extension_dir, "sanity check" - uninstaller = Gem::Uninstaller.new @spec.name, :executables => true + uninstaller = Gem::Uninstaller.new @spec.name, executables: true uninstaller.uninstall assert_path_not_exist @spec.extension_dir end def test_uninstall_nonexistent - uninstaller = Gem::Uninstaller.new "bogus", :executables => true + uninstaller = Gem::Uninstaller.new "bogus", executables: true e = assert_raise Gem::InstallError do uninstaller.uninstall @@ -369,11 +429,11 @@ create_makefile '#{@spec.name}' end def test_uninstall_user_install - @user_spec = Gem::Specification.find_by_name "b" + Gem::Specification.dirs = [Gem.user_dir] uninstaller = Gem::Uninstaller.new(@user_spec.name, - :executables => true, - :user_install => true) + executables: true, + user_install: true) gem_dir = File.join @user_spec.gem_dir @@ -393,11 +453,37 @@ create_makefile '#{@spec.name}' assert_same uninstaller, @post_uninstall_hook_arg end + def test_uninstall_user_install_with_symlinked_home + pend "Symlinks not supported or not enabled" unless symlink_supported? + + Gem::Specification.dirs = [Gem.user_dir] + + symlinked_home = File.join(@tempdir, "new-home") + FileUtils.ln_s(Gem.user_home, symlinked_home) + + ENV["HOME"] = symlinked_home + Gem.instance_variable_set(:@user_home, nil) + Gem.instance_variable_set(:@data_home, nil) + + uninstaller = Gem::Uninstaller.new(@user_spec.name, + executables: true, + user_install: true, + force: true) + + gem_dir = File.join @user_spec.gem_dir + + assert_path_exist gem_dir + + uninstaller.uninstall + + assert_path_not_exist gem_dir + end + def test_uninstall_wrong_repo Dir.mkdir "#{@gemhome}2" Gem.use_paths "#{@gemhome}2", [@gemhome] - uninstaller = Gem::Uninstaller.new @spec.name, :executables => true + uninstaller = Gem::Uninstaller.new @spec.name, executables: true e = assert_raise Gem::InstallError do uninstaller.uninstall @@ -466,12 +552,12 @@ create_makefile '#{@spec.name}' lines = ui.output.split("\n") lines.shift - assert_match %r{You have requested to uninstall the gem:}, lines.shift + assert_match(/You have requested to uninstall the gem:/, lines.shift) lines.shift lines.shift - assert_match %r{r-1 depends on q \(= 1\)}, lines.shift - assert_match %r{Successfully uninstalled q-1}, lines.last + assert_match(/r-1 depends on q \(= 1\)/, lines.shift) + assert_match(/Successfully uninstalled q-1/, lines.last) end def test_uninstall_only_lists_unsatisfied_deps @@ -486,7 +572,7 @@ create_makefile '#{@spec.name}' quick_gem "q", "1.0" quick_gem "q", "1.1" - un = Gem::Uninstaller.new("q", :version => "1.0") + un = Gem::Uninstaller.new("q", version: "1.0") ui = Gem::MockGemUi.new("y\n") use_ui ui do @@ -496,12 +582,12 @@ create_makefile '#{@spec.name}' lines = ui.output.split("\n") lines.shift - assert_match %r{You have requested to uninstall the gem:}, lines.shift + assert_match(/You have requested to uninstall the gem:/, lines.shift) lines.shift lines.shift - assert_match %r{x-1 depends on q \(= 1.0\)}, lines.shift - assert_match %r{Successfully uninstalled q-1.0}, lines.last + assert_match(/x-1 depends on q \(= 1.0\)/, lines.shift) + assert_match(/Successfully uninstalled q-1.0/, lines.last) end def test_uninstall_doesnt_prompt_when_other_gem_satisfies_requirement @@ -512,7 +598,7 @@ create_makefile '#{@spec.name}' quick_gem "q", "1.0" quick_gem "q", "1.1" - un = Gem::Uninstaller.new("q", :version => "1.0") + un = Gem::Uninstaller.new("q", version: "1.0") ui = Gem::MockGemUi.new("y\n") use_ui ui do @@ -531,7 +617,7 @@ create_makefile '#{@spec.name}' quick_gem "q", "1.0" - un = Gem::Uninstaller.new("q", :version => "1.0") + un = Gem::Uninstaller.new("q", version: "1.0") ui = Gem::MockGemUi.new("y\n") use_ui ui do @@ -550,7 +636,7 @@ create_makefile '#{@spec.name}' quick_gem "q", "1" - un = Gem::Uninstaller.new("q", :abort_on_dependent => true) + un = Gem::Uninstaller.new("q", abort_on_dependent: true) ui = Gem::MockGemUi.new("y\n") assert_raise Gem::DependencyRemovalException do @@ -567,7 +653,7 @@ create_makefile '#{@spec.name}' quick_gem "q", "1" - un = Gem::Uninstaller.new("q", :check_dev => true) + un = Gem::Uninstaller.new("q", check_dev: true) ui = Gem::MockGemUi.new("y\n") use_ui ui do @@ -577,12 +663,12 @@ create_makefile '#{@spec.name}' lines = ui.output.split("\n") lines.shift - assert_match %r{You have requested to uninstall the gem:}, lines.shift + assert_match(/You have requested to uninstall the gem:/, lines.shift) lines.shift lines.shift - assert_match %r{r-1 depends on q \(= 1, development\)}, lines.shift - assert_match %r{Successfully uninstalled q-1}, lines.last + assert_match(/r-1 depends on q \(= 1, development\)/, lines.shift) + assert_match(/Successfully uninstalled q-1/, lines.last) end def test_uninstall_prompt_only_lists_the_dependents_that_prevented_uninstallation @@ -596,7 +682,7 @@ create_makefile '#{@spec.name}' quick_gem "q", "1" - un = Gem::Uninstaller.new("q", :check_dev => false) + un = Gem::Uninstaller.new("q", check_dev: false) ui = Gem::MockGemUi.new("y\n") use_ui ui do @@ -606,16 +692,16 @@ create_makefile '#{@spec.name}' lines = ui.output.split("\n") lines.shift - assert_match %r{You have requested to uninstall the gem:}, lines.shift + assert_match(/You have requested to uninstall the gem:/, lines.shift) lines.shift lines.shift - assert_match %r{s-1 depends on q \(= 1\)}, lines.shift - assert_match %r{Successfully uninstalled q-1}, lines.last + assert_match(/s-1 depends on q \(= 1\)/, lines.shift) + assert_match(/Successfully uninstalled q-1/, lines.last) end def test_uninstall_no_permission - uninstaller = Gem::Uninstaller.new @spec.name, :executables => true + uninstaller = Gem::Uninstaller.new @spec.name, executables: true stub_rm_r = lambda do |*args| _path = args.shift @@ -634,40 +720,40 @@ create_makefile '#{@spec.name}' def test_uninstall_keeps_plugins_up_to_date write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| - io.write "puts __FILE__" + io.write "# do nothing" end plugin_path = File.join Gem.plugindir, "a_plugin.rb" @spec.version = "1" - Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + Gem::Installer.at(Gem::Package.build(@spec), force: true).install refute File.exist?(plugin_path), "version without plugin installed, but plugin written" @spec.files += %w[lib/rubygems_plugin.rb] @spec.version = "2" - Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + Gem::Installer.at(Gem::Package.build(@spec), force: true).install assert File.exist?(plugin_path), "version with plugin installed, but plugin not written" assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), "written plugin has incorrect content" @spec.version = "3" - Gem::Installer.at(Gem::Package.build(@spec), :force => true).install + Gem::Installer.at(Gem::Package.build(@spec), force: true).install assert File.exist?(plugin_path), "version with plugin installed, but plugin removed" assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), "old version installed, but plugin updated" - Gem::Uninstaller.new("a", :version => "1", :executables => true).uninstall + Gem::Uninstaller.new("a", version: "1", executables: true).uninstall assert File.exist?(plugin_path), "plugin removed when old version uninstalled" assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), "old version uninstalled, but plugin updated" - Gem::Uninstaller.new("a", version: "3", :executables => true).uninstall + Gem::Uninstaller.new("a", version: "3", executables: true).uninstall assert File.exist?(plugin_path), "plugin removed when old version uninstalled and another version with plugin still present" assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), "latest version uninstalled, but plugin not updated to previous version" - Gem::Uninstaller.new("a", version: "2", :executables => true).uninstall + Gem::Uninstaller.new("a", version: "2", executables: true).uninstall refute File.exist?(plugin_path), "last version uninstalled, but plugin still present" end diff --git a/test/rubygems/test_gem_unsatisfiable_dependency_error.rb b/test/rubygems/test_gem_unsatisfiable_dependency_error.rb index 3ce98b3cdf..5202010dac 100644 --- a/test/rubygems/test_gem_unsatisfiable_dependency_error.rb +++ b/test/rubygems/test_gem_unsatisfiable_dependency_error.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" class TestGemUnsatisfiableDependencyError < Gem::TestCase diff --git a/test/rubygems/test_gem_update_suggestion.rb b/test/rubygems/test_gem_update_suggestion.rb new file mode 100644 index 0000000000..8cb8ee57ff --- /dev/null +++ b/test/rubygems/test_gem_update_suggestion.rb @@ -0,0 +1,209 @@ +# frozen_string_literal: true + +require_relative "helper" +require "rubygems/command" +require "rubygems/update_suggestion" + +class TestUpdateSuggestion < Gem::TestCase + def setup + super + + @cmd = Gem::Command.new "dummy", "dummy" + @cmd.extend Gem::UpdateSuggestion + @start_time = 1_000_000 + @minute = 60 * 60 + @week = 7 * 24 * @minute + end + + def with_eligible_environment(**params) + self.class.with_eligible_environment(**params) do + yield + end + end + + def self.with_eligible_environment( + tty: true, + rubygems_version: Gem::Version.new("1.2.3"), + latest_rubygems_version: Gem::Version.new("2.0.0"), + ci: false, + reset_last_update_check: true, + cmd: + ) + original_config = Gem.configuration[:prevent_update_suggestion] + Gem.configuration[:prevent_update_suggestion] = nil + original_env = ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] + ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = nil + original_disable = Gem.disable_system_update_message + Gem.disable_system_update_message = nil + Gem.configuration.last_update_check = 0 if reset_last_update_check + + Gem.ui.stub :tty?, tty do + Gem.stub :rubygems_version, rubygems_version do + Gem.stub :latest_rubygems_version, latest_rubygems_version do + Gem::CIDetector.stub :ci?, ci do + yield + end + end + end + end + ensure + Gem.configuration[:prevent_update_suggestion] = original_config + ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = original_env + Gem.disable_system_update_message = original_disable + end + + def test_update_suggestion + Gem.stub :rubygems_version, Gem::Version.new("1.2.3") do + Gem.stub :latest_rubygems_version, Gem::Version.new("2.0.0") do + assert_equal @cmd.update_suggestion, <<~SUGGESTION + + A new release of RubyGems is available: 1.2.3 → 2.0.0! + Run `gem update --system 2.0.0` to update your installation. + + SUGGESTION + end + end + end + + def test_eligible_for_update + with_eligible_environment(cmd: @cmd) do + Time.stub :now, 123_456_789 do + assert_predicate @cmd, :eligible_for_update? + assert_equal 123_456_789, Gem.configuration.last_update_check + + # test last check is written to config file + assert_include File.read(Gem.configuration.state_file_name), "123456789" + end + end + end + + def test_eligible_for_update_is_not_annoying_when_new_version_is_released + current_version = Gem::Version.new("1.2.0") + latest_version = current_version + + # checking for first time, it is not eligible since new version + # is not released yet and stored + with_eligible_environment(cmd: @cmd, rubygems_version: current_version, latest_rubygems_version: latest_version) do + Time.stub :now, @start_time do + refute_predicate @cmd, :eligible_for_update? + assert_equal @start_time, Gem.configuration.last_update_check + end + end + + # checking next week, it is not eligible since new version + # is not released yet and timestamp is stored + with_eligible_environment( + cmd: @cmd, + rubygems_version: current_version, + latest_rubygems_version: latest_version, + reset_last_update_check: false + ) do + Time.stub :now, @start_time + @week do + refute_predicate @cmd, :eligible_for_update? + assert_equal @start_time + @week, Gem.configuration.last_update_check + end + end + + # pretend new version is released + latest_version = Gem::Version.new("1.3.0") + + # checking later same next week, it is not eligible even new version + # is released and timestamp is not stored + with_eligible_environment( + cmd: @cmd, + rubygems_version: current_version, + latest_rubygems_version: latest_version, + reset_last_update_check: false + ) do + Time.stub :now, @start_time + @week + @minute do + refute_predicate @cmd, :eligible_for_update? + assert_equal @start_time + @week, Gem.configuration.last_update_check + end + end + end + + def test_eligible_for_update_is_not_annoying_when_not_upgraded + with_eligible_environment(cmd: @cmd) do + # checking for first time, it is eligible and stored + Time.stub :now, @start_time do + assert_predicate @cmd, :eligible_for_update? + assert_equal @start_time, Gem.configuration.last_update_check + end + + # checking minute later is not eligible and not stored + Time.stub :now, @start_time + @minute do + refute_predicate @cmd, :eligible_for_update? + assert_equal @start_time, Gem.configuration.last_update_check + end + + # checking week later is eligible again and stored + Time.stub :now, @start_time + @week do + assert_predicate @cmd, :eligible_for_update? + assert_equal @start_time + @week, Gem.configuration.last_update_check + end + end + end + + def test_eligible_for_update_prevent_config + with_eligible_environment(cmd: @cmd) do + original_config = Gem.configuration[:prevent_update_suggestion] + Gem.configuration[:prevent_update_suggestion] = true + refute_predicate @cmd, :eligible_for_update? + ensure + Gem.configuration[:prevent_update_suggestion] = original_config + end + end + + def test_eligible_for_update_prevent_env + with_eligible_environment(cmd: @cmd) do + original_env = ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] + ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = "yes" + refute_predicate @cmd, :eligible_for_update? + ensure + ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = original_env + end + end + + def test_eligible_for_update_non_tty + with_eligible_environment(tty: false, cmd: @cmd) do + refute_predicate @cmd, :eligible_for_update? + end + end + + def test_eligible_for_update_for_prerelease + with_eligible_environment(rubygems_version: Gem::Version.new("1.0.0-rc1"), cmd: @cmd) do + refute_predicate @cmd, :eligible_for_update? + end + end + + def test_eligible_for_update_disabled_update + with_eligible_environment(cmd: @cmd) do + original_disable = Gem.disable_system_update_message + Gem.disable_system_update_message = "disabled" + refute_predicate @cmd, :eligible_for_update? + ensure + Gem.disable_system_update_message = original_disable + end + end + + def test_eligible_for_update_on_ci + with_eligible_environment(ci: true, cmd: @cmd) do + refute_predicate @cmd, :eligible_for_update? + end + end + + def test_eligible_for_update_unwrittable_config + with_eligible_environment(cmd: @cmd) do + Gem.configuration.stub :state_file_writable?, false do + refute_predicate @cmd, :eligible_for_update? + end + end + end + + def test_eligible_for_update_notification_delay + with_eligible_environment(cmd: @cmd) do + Gem.configuration.last_update_check = Time.now.to_i + refute_predicate @cmd, :eligible_for_update? + end + end +end diff --git a/test/rubygems/test_gem_uri.rb b/test/rubygems/test_gem_uri.rb index bcd7b3b2f0..1253ebc6de 100644 --- a/test/rubygems/test_gem_uri.rb +++ b/test/rubygems/test_gem_uri.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "helper" require "rubygems/uri" diff --git a/test/rubygems/test_gem_uri_formatter.rb b/test/rubygems/test_gem_uri_formatter.rb index bdc3f76a25..5ab4730d62 100644 --- a/test/rubygems/test_gem_uri_formatter.rb +++ b/test/rubygems/test_gem_uri_formatter.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/uri_formatter" diff --git a/test/rubygems/test_gem_util.rb b/test/rubygems/test_gem_util.rb index 04cb000f8d..608210a903 100644 --- a/test/rubygems/test_gem_util.rb +++ b/test/rubygems/test_gem_util.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/util" @@ -35,12 +36,12 @@ class TestGemUtil < Gem::TestCase end def test_traverse_parents_does_not_crash_on_permissions_error - pend "skipped on MS Windows (chmod has no effect)" if win_platform? || java_platform? + pend "skipped on MS Windows (chmod has no effect)" if Gem.win_platform? || Gem.java_platform? FileUtils.mkdir_p "d/e/f" # remove 'execute' permission from "e" directory and make it # impossible to cd into it and its children - FileUtils.chmod(0666, "d/e") + FileUtils.chmod(0o666, "d/e") pend "skipped in root privilege" if Process.uid.zero? @@ -52,15 +53,7 @@ class TestGemUtil < Gem::TestCase assert_equal File.realpath("../..", @tempdir), paths[3] ensure # restore default permissions, allow the directory to be removed - FileUtils.chmod(0775, "d/e") unless win_platform? || java_platform? - end - - def test_linked_list_find - list = [1,2,3,4,5].inject(Gem::List.new(0)) do |m,o| - Gem::List.new o, m - end - assert_equal 5, list.find {|x| x == 5 } - assert_equal 4, list.find {|x| x == 4 } + FileUtils.chmod(0o775, "d/e") unless Gem.win_platform? || Gem.java_platform? end def test_glob_files_in_dir diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 9237608d4a..cf771bc5a1 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/version" @@ -43,7 +44,7 @@ class TestGemVersion < Gem::TestCase assert_equal v("5.1"), Gem::Version.create("5.1") - ver = "1.1".freeze + ver = "1.1" assert_equal v("1.1"), Gem::Version.create(ver) end @@ -88,7 +89,7 @@ class TestGemVersion < Gem::TestCase end def test_initialize - ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0".freeze].each do |good| + ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0"].each do |good| assert_version_equal "1.0", good end @@ -268,7 +269,8 @@ class TestGemVersion < Gem::TestCase # Assert that two versions are eql?. Checks both directions. def assert_version_eql(first, second) - first, second = v(first), v(second) + first = v(first) + second = v(second) assert first.eql?(second), "#{first} is eql? #{second}" assert second.eql?(first), "#{second} is eql? #{first}" end @@ -289,7 +291,8 @@ class TestGemVersion < Gem::TestCase # directions. def refute_version_eql(first, second) - first, second = v(first), v(second) + first = v(first) + second = v(second) refute first.eql?(second), "#{first} is NOT eql? #{second}" refute second.eql?(first), "#{second} is NOT eql? #{first}" end diff --git a/test/rubygems/test_gem_version_option.rb b/test/rubygems/test_gem_version_option.rb index 92945e1b08..8b6e14fc42 100644 --- a/test/rubygems/test_gem_version_option.rb +++ b/test/rubygems/test_gem_version_option.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems/command" require "rubygems/version_option" @@ -81,10 +82,10 @@ class TestGemVersionOption < Gem::TestCase @cmd.handle_options %w[--version >1] expected = { - :args => [], - :explicit_prerelease => false, - :prerelease => false, - :version => Gem::Requirement.new("> 1"), + args: [], + explicit_prerelease: false, + prerelease: false, + version: Gem::Requirement.new("> 1"), } assert_equal expected, @cmd.options @@ -96,10 +97,10 @@ class TestGemVersionOption < Gem::TestCase @cmd.handle_options ["--version", "< 1, > 0.9"] expected = { - :args => [], - :explicit_prerelease => false, - :prerelease => false, - :version => Gem::Requirement.new("< 1", "> 0.9"), + args: [], + explicit_prerelease: false, + prerelease: false, + version: Gem::Requirement.new("< 1", "> 0.9"), } assert_equal expected, @cmd.options @@ -111,10 +112,10 @@ class TestGemVersionOption < Gem::TestCase @cmd.handle_options ["--version", "< 1", "--version", "> 0.9"] expected = { - :args => [], - :explicit_prerelease => false, - :prerelease => false, - :version => Gem::Requirement.new("< 1", "> 0.9"), + args: [], + explicit_prerelease: false, + prerelease: false, + version: Gem::Requirement.new("< 1", "> 0.9"), } assert_equal expected, @cmd.options @@ -127,10 +128,10 @@ class TestGemVersionOption < Gem::TestCase @cmd.handle_options %w[--pre --version >1] expected = { - :args => [], - :explicit_prerelease => true, - :prerelease => true, - :version => Gem::Requirement.new("> 1"), + args: [], + explicit_prerelease: true, + prerelease: true, + version: Gem::Requirement.new("> 1"), } assert_equal expected, @cmd.options @@ -142,10 +143,10 @@ class TestGemVersionOption < Gem::TestCase @cmd.handle_options %w[--version >1.a] expected = { - :args => [], - :explicit_prerelease => false, - :prerelease => true, - :version => Gem::Requirement.new("> 1.a"), + args: [], + explicit_prerelease: false, + prerelease: true, + version: Gem::Requirement.new("> 1.a"), } assert_equal expected, @cmd.options @@ -153,10 +154,10 @@ class TestGemVersionOption < Gem::TestCase @cmd.handle_options %w[--version >1] expected = { - :args => [], - :explicit_prerelease => false, - :prerelease => false, - :version => Gem::Requirement.new("> 1"), + args: [], + explicit_prerelease: false, + prerelease: false, + version: Gem::Requirement.new("> 1"), } assert_equal expected, @cmd.options diff --git a/test/rubygems/test_kernel.rb b/test/rubygems/test_kernel.rb index 091a5419fb..d862b26fe9 100644 --- a/test/rubygems/test_kernel.rb +++ b/test/rubygems/test_kernel.rb @@ -1,23 +1,16 @@ # frozen_string_literal: true + require_relative "helper" -class TestKernel < Gem::TestCase +class TestGemKernel < Gem::TestCase def setup super - @old_path = $:.dup - util_make_gems without_any_upwards_gemfiles end - def teardown - super - - $:.replace @old_path - end - def test_gem assert gem("a", "= 1"), "Should load" assert $:.any? {|p| p.include?("a-1/lib") } @@ -50,19 +43,29 @@ class TestKernel < Gem::TestCase def test_gem_redundant assert gem("a", "= 1"), "Should load" refute gem("a", "= 1"), "Should not load" - assert_equal 1, $:.select {|p| p.include?("a-1/lib") }.size + assert_equal 1, $:.count {|p| p.include?("a-1/lib") } end def test_gem_overlapping assert gem("a", "= 1"), "Should load" refute gem("a", ">= 1"), "Should not load" - assert_equal 1, $:.select {|p| p.include?("a-1/lib") }.size + assert_equal 1, $:.count {|p| p.include?("a-1/lib") } end - def test_gem_prerelease + def test_gem_prerelease_is_the_only_available quick_gem "d", "1.1.a" - refute gem("d", ">= 1"), "release requirement must not load prerelease" - assert gem("d", ">= 1.a"), "prerelease requirement may load prerelease" + + assert gem("d", ">= 1"), "release requirement may load prerelease when sole option" + assert $:.one? {|p| p.include?("/d-1.1.a/lib") } + end + + def test_release_favored_over_prerelease + quick_gem "d", "1.1.a" + quick_gem "d", "1.2" + gem("d", ">= 1") + + refute $:.any? {|p| p.include?("/d-1.1.a/lib") } + assert $:.one? {|p| p.include?("/d-1.2/lib") } end def test_gem_env_req @@ -118,6 +121,8 @@ class TestKernel < Gem::TestCase end def test_gem_bundler_inferred_bundler_version + require "rubygems/bundler_version_finder" + Gem::BundlerVersionFinder.stub(:bundler_version, Gem::Version.new("1")) do quick_gem "bundler", "1" quick_gem "bundler", "2.a" diff --git a/test/rubygems/test_project_sanity.rb b/test/rubygems/test_project_sanity.rb index aff7c66413..7a7b779b08 100644 --- a/test/rubygems/test_project_sanity.rb +++ b/test/rubygems/test_project_sanity.rb @@ -3,13 +3,36 @@ require_relative "helper" require "open3" -class TestProjectSanity < Gem::TestCase +class TestGemProjectSanity < Gem::TestCase + def setup + end + + def teardown + end + def test_manifest_is_up_to_date - pend unless File.exist?(File.expand_path("../../Rakefile", __dir__)) + pend unless File.exist?("#{root}/Rakefile") _, status = Open3.capture2e("rake check_manifest") - assert status.success?, "Expected Manifest.txt to be up to date, but it's not. Run `rake update_manifest` to sync it." + unless status.success? + original_contents = File.read("#{root}/Manifest.txt") + + # Update the manifest to see if it fixes the problem + Open3.capture2e("rake update_manifest") + + out, status = Open3.capture2e("rake check_manifest") + + # If `rake update_manifest` fixed the problem, that was the original + # issue, otherwise it was an unknown error, so print the error output + if status.success? + File.write("#{root}/Manifest.txt", original_contents) + + raise "Expected Manifest.txt to be up to date, but it's not. Run `rake update_manifest` to sync it." + else + raise "There was an error running `rake check_manifest`: #{out}" + end + end end def test_require_rubygems_package @@ -17,4 +40,10 @@ class TestProjectSanity < Gem::TestCase assert status.success?, err end + + private + + def root + File.expand_path("../..", __dir__) + end end diff --git a/test/rubygems/test_remote_fetch_error.rb b/test/rubygems/test_remote_fetch_error.rb index 55c505d879..5d9028ede7 100644 --- a/test/rubygems/test_remote_fetch_error.rb +++ b/test/rubygems/test_remote_fetch_error.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true + require_relative "helper" -class TestRemoteFetchError < Gem::TestCase +class TestGemRemoteFetchError < Gem::TestCase def test_password_redacted error = Gem::RemoteFetcher::FetchError.new("There was an error fetching", "https://user:secret@gemsource.org") - refute_match %r{secret}, error.to_s + refute_match(/secret/, error.to_s) end def test_invalid_url diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index 6135acea92..30a4a477f9 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative "helper" require "rubygems" @@ -91,12 +92,10 @@ class TestGemRequire < Gem::TestCase def create_sync_thread Thread.new do - begin - yield - ensure - FILE_ENTERED_LATCH.release - FILE_EXIT_LATCH.await - end + yield + ensure + FILE_ENTERED_LATCH.release + FILE_EXIT_LATCH.await end end @@ -226,7 +225,7 @@ class TestGemRequire < Gem::TestCase pend "Not sure what's going on. If another spec creates a 'a' gem before this test, somehow require will load the benchmark in b, and ignore that the stdlib one is already in $LOADED_FEATURES?. Reproducible by running the - spaceship_specific_file test before this one" if java_platform? + spaceship_specific_file test before this one" if Gem.java_platform? pend "not installed yet" unless RbConfig::TOPDIR @@ -252,9 +251,9 @@ class TestGemRequire < Gem::TestCase # Activates a-1, but not b-1 and b-2 assert_require "test_gem_require_a" assert_equal %w[a-1], loaded_spec_names - assert $LOAD_PATH.include? a1.load_paths[0] - refute $LOAD_PATH.include? b1.load_paths[0] - refute $LOAD_PATH.include? b2.load_paths[0] + assert $LOAD_PATH.include? a1.full_require_paths[0] + refute $LOAD_PATH.include? b1.full_require_paths[0] + refute $LOAD_PATH.include? b2.full_require_paths[0] assert_equal unresolved_names, ["b (>= 1)"] @@ -265,13 +264,13 @@ class TestGemRequire < Gem::TestCase # and as a result #gem_original_require returns false. refute require("benchmark"), "the benchmark stdlib should be recognized as already loaded" - assert_includes $LOAD_PATH, b2.load_paths[0] + assert_includes $LOAD_PATH, b2.full_require_paths[0] assert_includes $LOAD_PATH, rubylibdir message = proc { "this test relies on the b-2 gem lib/ to be before stdlib to make sense\n" + $LOAD_PATH.pretty_inspect } - assert_operator $LOAD_PATH.index(b2.load_paths[0]), :<, $LOAD_PATH.index(rubylibdir), message + assert_operator $LOAD_PATH.index(b2.full_require_paths[0]), :<, $LOAD_PATH.index(rubylibdir), message # We detected that we should activate b-2, so we did so, but # then #gem_original_require decided "I've already got some benchmark.rb" loaded. @@ -383,8 +382,8 @@ class TestGemRequire < Gem::TestCase # Remove an old default gem version directly from disk as if someone ran # gem cleanup. - FileUtils.rm_rf(File.join @gemhome, "#{b1.full_name}") - FileUtils.rm_rf(File.join @gemhome, "specifications", "default", "#{b1.full_name}.gemspec") + FileUtils.rm_rf(File.join(@gemhome, b1.full_name.to_s)) + FileUtils.rm_rf(File.join(@gemhome, "specifications", "default", "#{b1.full_name}.gemspec")) # Require gems that have not been removed. assert_require "a/b" @@ -425,7 +424,7 @@ class TestGemRequire < Gem::TestCase times_called = 0 - Kernel.stub(:gem, ->(name, requirement) { times_called += 1 }) do + Kernel.stub(:gem, ->(_name, _requirement) { times_called += 1 }) do refute_require "default/gem" end @@ -472,11 +471,11 @@ class TestGemRequire < Gem::TestCase File.write(path, code) output = Gem::Util.popen({ "GEM_HOME" => @gemhome }, *ruby_with_rubygems_in_load_path, path).strip - assert $?.success? refute_empty output assert_equal "999.99.9", output.lines[0].chomp # Make sure only files from the newer json gem are loaded, and no files from the default json gem assert_equal ["#{@gemhome}/gems/json-999.99.9/lib/json.rb"], output.lines.grep(%r{/gems/json-}).map(&:chomp) + assert $?.success? end def test_default_gem_and_normal_gem @@ -490,6 +489,17 @@ class TestGemRequire < Gem::TestCase assert_equal %w[default-3.0], loaded_spec_names end + def test_normal_gem_does_not_shadow_default_gem + default_gem_spec = new_default_spec("foo", "2.0", nil, "foo.rb") + install_default_gems(default_gem_spec) + + normal_gem_spec = util_spec("fake-foo", "3.0", nil, "lib/foo.rb") + install_specs(normal_gem_spec) + + assert_require "foo" + assert_equal %w[foo-2.0], loaded_spec_names + end + def test_normal_gems_with_overridden_load_error_message normal_gem_spec = util_spec("normal", "3.0", nil, "lib/normal/gem.rb") @@ -530,6 +540,65 @@ class TestGemRequire < Gem::TestCase assert_equal %w[default-3.0.0.rc2], loaded_spec_names end + def test_default_gem_with_unresolved_gems_depending_on_it + my_http_old = util_spec "my-http", "0.1.1", nil, "lib/my/http.rb" + install_gem my_http_old + + my_http_default = new_default_spec "my-http", "0.3.0", nil, "my/http.rb" + install_default_gems my_http_default + + faraday_1 = util_spec "faraday", "1", { "my-http" => ">= 0" } + install_gem faraday_1 + + faraday_2 = util_spec "faraday", "2", { "my-http" => ">= 0" } + install_gem faraday_2 + + chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" + install_gem chef + + assert_require "chef" + assert_require "my/http" + end + + def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it + my_http_old = util_spec "my-http", "0.1.1", nil, "lib/my/http.rb" + install_gem my_http_old + + my_http_default = new_default_spec "my-http", "0.3.0", nil, "my/http.rb" + my_http_default_path = File.join(@tempdir, "default_gems", "lib", "my/http.rb") + install_default_gems my_http_default + File.write(my_http_default_path, 'require "my/http"') + + faraday_1 = util_spec "faraday", "1", { "my-http" => ">= 0" } + install_gem faraday_1 + + faraday_2 = util_spec "faraday", "2", { "my-http" => ">= 0" } + install_gem faraday_2 + + chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" + install_gem chef + + assert_require "chef" + + out, err = capture_output do + assert_require "my/http" + end + + assert_empty out + + circular_require_warning = false + + err_lines = err.split("\n").reject do |line| + if line.include?("circular require") + circular_require_warning = true + elsif circular_require_warning # ignore backtrace lines for circular require warning + circular_require_warning = line.start_with?(/[\s]/) + end + end + + assert_empty err_lines + end + def loaded_spec_names Gem.loaded_specs.values.map(&:full_name).sort end @@ -541,8 +610,10 @@ class TestGemRequire < Gem::TestCase def test_try_activate_error_unlocks_require_monitor silence_warnings do class << ::Gem - alias old_try_activate try_activate - def try_activate(*); raise "raised from try_activate"; end + alias_method :old_try_activate, :try_activate + def try_activate(*) + raise "raised from try_activate" + end end end @@ -553,7 +624,7 @@ class TestGemRequire < Gem::TestCase ensure silence_warnings do class << ::Gem - alias try_activate old_try_activate + alias_method :try_activate, :old_try_activate end end Kernel::RUBYGEMS_ACTIVATION_MONITOR.exit @@ -596,79 +667,93 @@ class TestGemRequire < Gem::TestCase assert_empty unresolved_names end - # uplevel is 2.5+ only - if RUBY_VERSION >= "2.5" - ["", "Kernel."].each do |prefix| - define_method "test_no_kernel_require_in_#{prefix.tr(".", "_")}warn_with_uplevel" do - Dir.mktmpdir("warn_test") do |dir| - File.write(dir + "/sub.rb", "#{prefix}warn 'uplevel', 'test', uplevel: 1\n") - File.write(dir + "/main.rb", "require 'sub'\n") - _, err = capture_subprocess_io do - system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb") - end - assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err) - _, err = capture_subprocess_io do - system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb") - end - assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err) + ["", "Kernel."].each do |prefix| + define_method "test_no_kernel_require_in_#{prefix.tr(".", "_")}warn_with_uplevel" do + Dir.mktmpdir("warn_test") do |dir| + File.write(dir + "/sub.rb", "#{prefix}warn 'uplevel', 'test', uplevel: 1\n") + File.write(dir + "/main.rb", "require 'sub'\n") + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb") end - end - - define_method "test_no_other_behavioral_changes_with_#{prefix.tr(".", "_")}warn" do - Dir.mktmpdir("warn_test") do |dir| - File.write(dir + "/main.rb", "#{prefix}warn({x:1}, {y:2}, [])\n") - _, err = capture_subprocess_io do - system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb") - end - assert_match(/{:x=>1}\n{:y=>2}\n$/, err) - _, err = capture_subprocess_io do - system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb") - end - assert_match(/{:x=>1}\n{:y=>2}\n$/, err) + assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err) + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb") end + assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err) end end - def test_no_crash_when_overriding_warn_with_warning_module + define_method "test_no_other_behavioral_changes_with_#{prefix.tr(".", "_")}warn" do Dir.mktmpdir("warn_test") do |dir| - File.write(dir + "/main.rb", "module Warning; def warn(str); super; end; end; warn 'Foo Bar'") + File.write(dir + "/main.rb", "#{prefix}warn({x:1}, {y:2}, [])\n") _, err = capture_subprocess_io do system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb") end - assert_match(/Foo Bar\n$/, err) + assert_match(/{:x=>1}\n{:y=>2}\n$/, err) _, err = capture_subprocess_io do system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb") end - assert_match(/Foo Bar\n$/, err) + assert_match(/{:x=>1}\n{:y=>2}\n$/, err) end end + end - def test_expected_backtrace_location_when_inheriting_from_basic_object_and_including_kernel - Dir.mktmpdir("warn_test") do |dir| - File.write(dir + "/main.rb", "\nrequire 'sub'\n") - File.write(dir + "/sub.rb", <<-'RUBY') - require 'rubygems' - class C < BasicObject - include ::Kernel - def deprecated - warn "This is a deprecated method", uplevel: 2 - end - end - C.new.deprecated - RUBY + def test_no_crash_when_overriding_warn_with_warning_module + Dir.mktmpdir("warn_test") do |dir| + File.write(dir + "/main.rb", "module Warning; def warn(str); super; end; end; warn 'Foo Bar'") + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb") + end + assert_match(/Foo Bar\n$/, err) + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb") + end + assert_match(/Foo Bar\n$/, err) + end + end - _, err = capture_subprocess_io do - system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb") - end - assert_match(/main\.rb:2: warning: This is a deprecated method$/, err) - _, err = capture_subprocess_io do - system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb") + def test_expected_backtrace_location_when_inheriting_from_basic_object_and_including_kernel + Dir.mktmpdir("warn_test") do |dir| + File.write(dir + "/main.rb", "\nrequire 'sub'\n") + File.write(dir + "/sub.rb", <<-'RUBY') + require 'rubygems' + class C < BasicObject + include ::Kernel + def deprecated + warn "This is a deprecated method", uplevel: 2 + end end - assert_match(/main\.rb:2: warning: This is a deprecated method$/, err) + C.new.deprecated + RUBY + + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb") end + assert_match(/main\.rb:2: warning: This is a deprecated method$/, err) + _, err = capture_subprocess_io do + system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb") + end + assert_match(/main\.rb:2: warning: This is a deprecated method$/, err) end end + def test_require_does_not_crash_when_utilizing_bundler_version_finder + a1 = util_spec "a", "1.1", { "bundler" => ">= 0" } + a2 = util_spec "a", "1.2", { "bundler" => ">= 0" } + b1 = util_spec "bundler", "2.3.7" + b2 = util_spec "bundler", "2.3.24" + c = util_spec "c", "1", { "a" => [">= 1.1", "< 99.0"] }, "lib/test_gem_require_c.rb" + + install_specs a1, a2, b1, b2, c + + cmd = <<-RUBY + require "test_gem_require_c" + require "json" + RUBY + out = Gem::Util.popen({ "GEM_HOME" => @gemhome }, *ruby_with_rubygems_in_load_path, "-e", cmd) + assert_predicate $?, :success?, "Require failed due to #{out}" + end + private def util_install_extension_file(name) @@ -694,13 +779,13 @@ class TestGemRequire < Gem::TestCase spec.files += ["extconf.rb", "depend", "#{name}.c"] - so = File.join(spec.gem_dir, "#{name}.#{RbConfig::CONFIG["DLEXT"]}") - assert_path_not_exist so + extension_file = File.join(spec.extension_dir, "#{name}.#{RbConfig::CONFIG["DLEXT"]}") + assert_path_not_exist extension_file path = Gem::Package.build spec installer = Gem::Installer.at path installer.install - assert_path_exist so + assert_path_exist extension_file spec.gem_dir end diff --git a/test/rubygems/test_rubygems.rb b/test/rubygems/test_rubygems.rb index 8bd116646f..ec195b65cd 100644 --- a/test/rubygems/test_rubygems.rb +++ b/test/rubygems/test_rubygems.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + require_relative "helper" class GemTest < Gem::TestCase def test_rubygems_normal_behaviour - _ = Gem::Util.popen(*ruby_with_rubygems_in_load_path, "-e", "'require \"rubygems\"'", { :err => [:child, :out] }).strip + _ = Gem::Util.popen(*ruby_with_rubygems_in_load_path, "-e", "'require \"rubygems\"'", { err: [:child, :out] }).strip assert $?.success? end @@ -13,9 +15,9 @@ class GemTest < Gem::TestCase intentionally_not_implemented_method RUBY - output = Gem::Util.popen(*ruby_with_rubygems_and_fake_operating_system_in_load_path(path), "-e", "'require \"rubygems\"'", { :err => [:child, :out] }).strip + output = Gem::Util.popen(*ruby_with_rubygems_and_fake_operating_system_in_load_path(path), "-e", "'require \"rubygems\"'", { err: [:child, :out] }).strip assert !$?.success? - assert_includes output, "undefined local variable or method `intentionally_not_implemented_method'" + assert_match(/undefined local variable or method [`']intentionally_not_implemented_method'/, output) assert_includes output, "Loading the #{operating_system_rb_at(path)} file caused an error. " \ "This file is owned by your OS, not by rubygems upstream. " \ "Please find out which OS package this file belongs to and follow the guidelines from your OS to report " \ @@ -40,7 +42,7 @@ class GemTest < Gem::TestCase *ruby_with_rubygems_and_fake_operating_system_in_load_path(path), "-e", "require \"rubygems\"; puts Gem::Specification.stubs.map(&:full_name)", - { :err => [:child, :out] } + { err: [:child, :out] } ).strip begin assert_empty output @@ -69,6 +71,6 @@ class GemTest < Gem::TestCase end def ruby_with_rubygems_and_fake_operating_system_in_load_path(operating_system_path) - [Gem.ruby, "-I", operating_system_path, "-I" , $LOAD_PATH.find {|p| p == File.dirname($LOADED_FEATURES.find {|f| f.end_with?("/rubygems.rb") }) }] + [Gem.ruby, "-I", operating_system_path, "-I", $LOAD_PATH.find {|p| p == File.dirname($LOADED_FEATURES.find {|f| f.end_with?("/rubygems.rb") }) }] end end diff --git a/test/rubygems/test_webauthn_listener.rb b/test/rubygems/test_webauthn_listener.rb new file mode 100644 index 0000000000..08edabceb2 --- /dev/null +++ b/test/rubygems/test_webauthn_listener.rb @@ -0,0 +1,143 @@ +# frozen_string_literal: true + +require_relative "helper" +require "rubygems/gemcutter_utilities/webauthn_listener" +require "rubygems/gemcutter_utilities" + +class WebauthnListenerTest < Gem::TestCase + def setup + super + @server = TCPServer.new 0 + @port = @server.addr[1].to_s + end + + def teardown + @thread.kill.join if @thread + @server&.close + super + end + + def test_listener_thread_retreives_otp_code + thread = Gem::GemcutterUtilities::WebauthnListener.listener_thread(Gem.host, @server) + Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}?code=xyz") + + thread.join + assert_equal "xyz", thread[:otp] + end + + def test_listener_thread_sets_error + thread = Gem::GemcutterUtilities::WebauthnListener.listener_thread(Gem.host, @server) + Gem::MockBrowser.post Gem::URI("http://localhost:#{@port}?code=xyz") + + thread.join + assert_equal "Security device verification failed: Invalid HTTP method POST received.", thread[:error].message + end + + def test_wait_for_otp_code_get_follows_options + wait_for_otp_code + assert Gem::MockBrowser.options(Gem::URI("http://localhost:#{@port}?code=xyz")).is_a? Gem::Net::HTTPNoContent + assert Gem::MockBrowser.get(Gem::URI("http://localhost:#{@port}?code=xyz")).is_a? Gem::Net::HTTPOK + end + + def test_wait_for_otp_code_options_request + wait_for_otp_code + response = Gem::MockBrowser.options Gem::URI("http://localhost:#{@port}?code=xyz") + + assert response.is_a? Gem::Net::HTTPNoContent + assert_equal Gem.host, response["access-control-allow-origin"] + assert_equal "POST", response["access-control-allow-methods"] + assert_equal "Content-Type, Authorization, x-csrf-token", response["access-control-allow-headers"] + assert_equal "close", response["Connection"] + end + + def test_wait_for_otp_code_get_request + wait_for_otp_code + response = Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}?code=xyz") + + assert response.is_a? Gem::Net::HTTPOK + assert_equal "text/plain; charset=utf-8", response["Content-Type"] + assert_equal "7", response["Content-Length"] + assert_equal Gem.host, response["access-control-allow-origin"] + assert_equal "POST", response["access-control-allow-methods"] + assert_equal "Content-Type, Authorization, x-csrf-token", response["access-control-allow-headers"] + assert_equal "close", response["Connection"] + assert_equal "success", response.body + + @thread.join + assert_equal "xyz", @thread[:otp] + end + + def test_wait_for_otp_code_invalid_post_req_method + wait_for_otp_code_expect_error_with_message("Security device verification failed: Invalid HTTP method POST received.") + response = Gem::MockBrowser.post Gem::URI("http://localhost:#{@port}?code=xyz") + + assert response + assert response.is_a? Gem::Net::HTTPMethodNotAllowed + assert_equal "GET, OPTIONS", response["allow"] + assert_equal "close", response["Connection"] + + @thread.join + assert_nil @thread[:otp] + end + + def test_wait_for_otp_code_incorrect_path + wait_for_otp_code_expect_error_with_message("Security device verification failed: Page at /path not found.") + response = Gem::MockBrowser.post Gem::URI("http://localhost:#{@port}/path?code=xyz") + + assert response.is_a? Gem::Net::HTTPNotFound + assert_equal "close", response["Connection"] + + @thread.join + assert_nil @thread[:otp] + end + + def test_wait_for_otp_code_no_params_response + wait_for_otp_code_expect_error_with_message("Security device verification failed: Did not receive OTP from https://rubygems.org.") + response = Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}") + + assert response.is_a? Gem::Net::HTTPBadRequest + assert_equal "text/plain; charset=utf-8", response["Content-Type"] + assert_equal "22", response["Content-Length"] + assert_equal "close", response["Connection"] + assert_equal "missing code parameter", response.body + + @thread.join + assert_nil @thread[:otp] + end + + def test_wait_for_otp_code_incorrect_params + wait_for_otp_code_expect_error_with_message("Security device verification failed: Did not receive OTP from https://rubygems.org.") + response = Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}?param=xyz") + + assert response.is_a? Gem::Net::HTTPBadRequest + assert_equal "text/plain; charset=utf-8", response["Content-Type"] + assert_equal "22", response["Content-Length"] + assert_equal "close", response["Connection"] + assert_equal "missing code parameter", response.body + + @thread.join + assert_nil @thread[:otp] + end + + private + + def wait_for_otp_code + @thread = Thread.new do + Thread.current[:otp] = Gem::GemcutterUtilities::WebauthnListener.new(Gem.host).wait_for_otp_code(@server) + end + @thread.abort_on_exception = true + @thread.report_on_exception = false + end + + def wait_for_otp_code_expect_error_with_message(message) + @thread = Thread.new do + error = assert_raise Gem::WebauthnVerificationError do + Thread.current[:otp] = Gem::GemcutterUtilities::WebauthnListener.new(Gem.host).wait_for_otp_code(@server) + end + + assert_equal message, error.message + end + @thread.abort_on_exception = true + @thread.report_on_exception = false + end +end diff --git a/test/rubygems/test_webauthn_listener_response.rb b/test/rubygems/test_webauthn_listener_response.rb new file mode 100644 index 0000000000..377e5bfe5a --- /dev/null +++ b/test/rubygems/test_webauthn_listener_response.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require_relative "helper" +require "rubygems/gemcutter_utilities/webauthn_listener/response" + +class WebauthnListenerResponseTest < Gem::TestCase + def setup + super + @host = "rubygems.example" + end + + def test_ok_response_to_s + to_s = Gem::GemcutterUtilities::WebauthnListener::OkResponse.new(@host).to_s + + expected_to_s = <<~RESPONSE + HTTP/1.1 200 OK\r + connection: close\r + access-control-allow-origin: rubygems.example\r + access-control-allow-methods: POST\r + access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r + content-type: text/plain; charset=utf-8\r + content-length: 7\r + \r + success + RESPONSE + + assert_equal expected_to_s, to_s + end + + def test_no_to_s_response_to_s + to_s = Gem::GemcutterUtilities::WebauthnListener::NoContentResponse.new(@host).to_s + + expected_to_s = <<~RESPONSE + HTTP/1.1 204 No Content\r + connection: close\r + access-control-allow-origin: rubygems.example\r + access-control-allow-methods: POST\r + access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r + \r + RESPONSE + + assert_equal expected_to_s, to_s + end + + def test_method_not_allowed_response_to_s + to_s = Gem::GemcutterUtilities::WebauthnListener::MethodNotAllowedResponse.new(@host).to_s + + expected_to_s = <<~RESPONSE + HTTP/1.1 405 Method Not Allowed\r + connection: close\r + access-control-allow-origin: rubygems.example\r + access-control-allow-methods: POST\r + access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r + allow: GET, OPTIONS\r + \r + RESPONSE + + assert_equal expected_to_s, to_s + end + + def test_method_not_found_response_to_s + to_s = Gem::GemcutterUtilities::WebauthnListener::NotFoundResponse.new(@host).to_s + + expected_to_s = <<~RESPONSE + HTTP/1.1 404 Not Found\r + connection: close\r + access-control-allow-origin: rubygems.example\r + access-control-allow-methods: POST\r + access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r + \r + RESPONSE + + assert_equal expected_to_s, to_s + end + + def test_bad_request_response_to_s + to_s = Gem::GemcutterUtilities::WebauthnListener::BadRequestResponse.new(@host).to_s + + expected_to_s = <<~RESPONSE + HTTP/1.1 400 Bad Request\r + connection: close\r + access-control-allow-origin: rubygems.example\r + access-control-allow-methods: POST\r + access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r + content-type: text/plain; charset=utf-8\r + content-length: 22\r + \r + missing code parameter + RESPONSE + + assert_equal expected_to_s, to_s + end +end diff --git a/test/rubygems/test_webauthn_poller.rb b/test/rubygems/test_webauthn_poller.rb new file mode 100644 index 0000000000..fd24081758 --- /dev/null +++ b/test/rubygems/test_webauthn_poller.rb @@ -0,0 +1,134 @@ +# frozen_string_literal: true + +require_relative "helper" +require "rubygems/gemcutter_utilities/webauthn_poller" +require "rubygems/gemcutter_utilities" + +class WebauthnPollerTest < Gem::TestCase + def setup + super + + @host = Gem.host + @webauthn_url = "#{@host}/api/v1/webauthn_verification/odow34b93t6aPCdY" + @fetcher = Gem::FakeFetcher.new + Gem::RemoteFetcher.fetcher = @fetcher + @credentials = { + identifier: "email@example.com", + password: "password", + } + end + + def test_poll_thread_success + @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create( + body: "{\"status\":\"success\",\"code\":\"Uvh6T57tkWuUnWYo\"}", + code: 200, + msg: "OK" + ) + + thread = Gem::GemcutterUtilities::WebauthnPoller.poll_thread({}, @host, @webauthn_url, @credentials) + thread.join + + assert_equal thread[:otp], "Uvh6T57tkWuUnWYo" + end + + def test_poll_thread_webauthn_verification_error + @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create( + body: "HTTP Basic: Access denied.", + code: 401, + msg: "Unauthorized" + ) + + thread = Gem::GemcutterUtilities::WebauthnPoller.poll_thread({}, @host, @webauthn_url, @credentials) + thread.join + + assert_equal thread[:error].message, "Security device verification failed: Unauthorized" + end + + def test_poll_thread_timeout_error + raise_error = ->(*_args) { raise Gem::Timeout::Error, "execution expired" } + Gem::Timeout.stub(:timeout, raise_error) do + thread = Gem::GemcutterUtilities::WebauthnPoller.poll_thread({}, @host, @webauthn_url, @credentials) + thread.join + assert_equal thread[:error].message, "execution expired" + end + end + + def test_poll_for_otp_success + @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create( + body: "{\"status\":\"success\",\"code\":\"Uvh6T57tkWuUnWYo\"}", + code: 200, + msg: "OK" + ) + + otp = Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials) + + assert_equal otp, "Uvh6T57tkWuUnWYo" + end + + def test_poll_for_otp_pending_sleeps + @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create( + body: "{\"status\":\"pending\",\"message\":\"Security device authentication is still pending.\"}", + code: 200, + msg: "OK" + ) + + assert_raise Gem::Timeout::Error do + Gem::Timeout.timeout(0.1) do + Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials) + end + end + end + + def test_poll_for_otp_not_http_success + @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create( + body: "HTTP Basic: Access denied.", + code: 401, + msg: "Unauthorized" + ) + + error = assert_raise Gem::WebauthnVerificationError do + Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials) + end + + assert_equal error.message, "Security device verification failed: Unauthorized" + end + + def test_poll_for_otp_invalid_format + @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create( + body: "{}", + code: 200, + msg: "OK" + ) + + error = assert_raise Gem::WebauthnVerificationError do + Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials) + end + + assert_equal error.message, "Security device verification failed: Invalid response from server" + end + + def test_poll_for_otp_invalid_status + @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create( + body: "{\"status\":\"expired\",\"message\":\"The token in the link you used has either expired or been used already.\"}", + code: 200, + msg: "OK" + ) + + error = assert_raise Gem::WebauthnVerificationError do + Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials) + end + + assert_equal error.message, + "Security device verification failed: The token in the link you used has either expired or been used already." + end + + def test_poll_for_otp_missing_credentials + @credentials = { password: "password" } + + error = assert_raise Gem::WebauthnVerificationError do + Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials) + end + + assert_equal error.message, "Security device verification failed: Provided missing credentials" + end +end diff --git a/test/rubygems/utilities.rb b/test/rubygems/utilities.rb index c01f7acd48..357379f88d 100644 --- a/test/rubygems/utilities.rb +++ b/test/rubygems/utilities.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require "tempfile" require "rubygems" require "rubygems/remote_fetcher" @@ -39,28 +40,36 @@ class Gem::FakeFetcher end def find_data(path) - return Gem.read_binary path.path if URI === path && "file" == path.scheme + return Gem.read_binary path.path if Gem::URI === path && path.scheme == "file" - if URI === path && "URI::#{path.scheme.upcase}" != path.class.name + if Gem::URI === path && "Gem::URI::#{path.scheme.upcase}" != path.class.name 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.start_with?("https://", "http://") + raise ArgumentError, "need full Gem::URI" unless path.start_with?("https://", "http://") unless @data.key? path raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) end - if @data[path].kind_of?(Array) && @data[path].first.kind_of?(Array) + if @data[path].is_a?(Array) @data[path].shift else @data[path] end end + def create_response(uri) + data = find_data(uri) + response = data.respond_to?(:call) ? data.call : data + raise TypeError, "#{response.class} is not a type of Gem::Net::HTTPResponse" unless response.is_a?(Gem::Net::HTTPResponse) + + response + end + def fetch_path(path, mtime = nil, head = false) data = find_data(path) @@ -85,26 +94,16 @@ class Gem::FakeFetcher # Thanks, FakeWeb! def open_uri_or_path(path) - data = find_data(path) - body, code, msg = data + find_data(path) - 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 + create_response(uri) end def request(uri, request_class, last_modified = nil) - data = find_data(uri) - body, code, msg = (data.respond_to?(:call) ? data.call : 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 + create_response(uri) end def pretty_print(q) # :nodoc: @@ -121,7 +120,7 @@ class Gem::FakeFetcher path = path.to_s @paths << path - raise ArgumentError, "need full URI" unless path =~ %r{^http://} + raise ArgumentError, "need full URI" unless %r{^http://}.match?(path) unless @data.key? path raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) @@ -142,7 +141,7 @@ class Gem::FakeFetcher path = File.join path, name - if source_uri =~ /^http/ + if /^http/.match?(source_uri) File.open(path, "wb") do |f| f.write fetch_path(File.join(source_uri, "gems", name)) end @@ -164,6 +163,66 @@ class Gem::FakeFetcher end end +## +# The HTTPResponseFactory allows easy creation of Gem::Net::HTTPResponse instances in RubyGems tests: +# +# Example: +# +# Gem::HTTPResponseFactory.create( +# body: "", +# code: 301, +# msg: "Moved Permanently", +# headers: { "location" => "http://example.com" } +# ) +# + +class Gem::HTTPResponseFactory + def self.create(body:, code:, msg:, headers: {}) + response = Gem::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) + headers.each {|name, value| response[name] = value } + + response + end +end + +## +# A Gem::MockBrowser is used in tests to mock a browser in that it can +# send HTTP requests to the defined URI. +# +# Example: +# +# # Sends a get request to http://localhost:5678 +# Gem::MockBrowser.get Gem::URI("http://localhost:5678") +# +# See RubyGems' tests for more examples of MockBrowser. +# + +class Gem::MockBrowser + def self.options(uri) + options = Gem::Net::HTTP::Options.new(uri) + Gem::Net::HTTP.start(uri.hostname, uri.port) do |http| + http.request(options) + end + end + + def self.get(uri) + get = Gem::Net::HTTP::Get.new(uri) + Gem::Net::HTTP.start(uri.hostname, uri.port) do |http| + http.request(get) + end + end + + def self.post(uri, content_type: "application/x-www-form-urlencoded") + headers = { "content-type" => content_type } if content_type + post = Gem::Net::HTTP::Post.new(uri, headers) + Gem::Net::HTTP.start(uri.hostname, uri.port) do |http| + http.request(post) + end + end +end + # :stopdoc: class Gem::RemoteFetcher def self.fetcher=(fetcher) @@ -307,13 +366,14 @@ class Gem::TestCase::SpecFetcherSetup Gem::Specification.reset begin - gem_repo, @test.gem_repo = @test.gem_repo, @repository - @test.uri = URI @repository + gem_repo = @test.gem_repo + @test.gem_repo = @repository + @test.uri = Gem::URI @repository @test.util_setup_spec_fetcher(*@downloaded) ensure @test.gem_repo = gem_repo - @test.uri = URI gem_repo + @test.uri = Gem::URI gem_repo end @gems.each do |spec, gem| @@ -350,7 +410,7 @@ end # # This class was added to flush out problems in Rubinius' IO implementation. -class TempIO < Tempfile +class Gem::TempIO < Tempfile ## # Creates a new TempIO that will be initialized to contain +string+. @@ -369,3 +429,8 @@ class TempIO < Tempfile Gem.read_binary path end end + +class Gem::TestCase + TempIO = Gem::TempIO + HTTPResponseFactory = Gem::HTTPResponseFactory +end diff --git a/test/rubygems/wrong_key_cert.pem b/test/rubygems/wrong_key_cert.pem index 23396d7c81..2f2cffbc61 100644 --- a/test/rubygems/wrong_key_cert.pem +++ b/test/rubygems/wrong_key_cert.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDDTCCAfWgAwIBAgIBEjANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv +MIIDDTCCAfWgAwIBAgIBEjANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCAXDTEyMDEwMTAwMDAwMFoYDzk5 OTkxMjMxMjM1OTU5WjAqMQ8wDQYDVQQDDAZub2JvZHkxFzAVBgoJkiaJk/IsZAEZ -FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvZQipBa1 -xH3M9OonkrUYhGZeX9UHAcJhe6jJbUr/uHXkh1Tu2ERWNnblm85upqBfjyZEnKer -7uBcwwkkvmisVgC8uBECymsBxuEIw0rfiKYEnLu0B6SiWFYz3dYPS92bBK7Vks2/ -kNyXUmLLGoZ3id2K0eK5C/AJ0j+p84OqPnVhylsjrZmXfIZrh7lkHhgCIrzPefjE -3pOloi/tz6fh2ktb0FYKQMfweT3Ba2TMeflG13PEOW80AD5w0THxDutGG0zPNCDy -DEoT7UU1a3B3RMHYuUxEk1GUEYWq9L6a6SMpZISWTSpCp0Ww1QB55PONiCCn+o6v -cIy46jI71dATAQIDAQABozwwOjAZBgNVHREEEjAQgQ5ub2JvZHlAZXhhbXBsZTAd -BgNVHQ4EFgQUyvn/FwcZnA7AkzPjmoooB4/tKgcwDQYJKoZIhvcNAQEFBQADggEB -ABswixv3veo8S0Omyhbch3t19xAd/I4ZAx/lq6a/Ubl+X33hRbZQ7ulXja6Y5ZCs -iIkezGcpc182e7hZdHuEGGnJ1fJwxz3rbFWvs+MrtRSaCC73HbbxF1x0mQY6Kc7W -PahB2v+Dx5n3dIN6ah5p+STUHmzhKGr3bsQswtSHrFn74wt6mBu/hyCz+t6UaQ7b -rpRpzDFO1q3tZB8MeIHg57Lk2bu0LtfaHdkGDghNa3t7oZfV5A6pruiTy/EdQvFL -ZJpvDgHCyUsDmukMMjz6U4ts+nx7kZ9JoIH9K2lMJo3SGw4iZ8rB+HTfsbUdRfBj -UlyNcLqCW+FPlUHgHgNugFA= +FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApebGm7NO +nx+DtWG1xQsJBfTfwNlZvfzY61nlZccrhU6vx0AnYNiDZAG3J/gFQmYZ9gJ98rzE +wfLMCGq9R/TZM+lAEaLhzYZCu3X4QdhKxr1xZ/SFC+1f8KVuH4tLXORW30DwayPh +NxnrOvup4pWLiYuXUSZpV9CGMvPSUCW2odhMkBMKqaTTPjxoXJIcgacyprkNgIq4 +8cSvqWG/e/HrMRtkqvFbD5ta00uO1mlpajYYw1RRftEwktFo8vQgDBo9NT/EqoE7 +2tffaDnLq6rQrVtw4Kr9fy775DjNAWXyiCBjnJgOQSXCGPsM/AEdFrh/LKQQv2M/ +M7WNevnEUgsEIwIDAQABozwwOjAZBgNVHREEEjAQgQ5ub2JvZHlAZXhhbXBsZTAd +BgNVHQ4EFgQUYPwS8g98+4Tq/8gcEK1iilkGXH4wDQYJKoZIhvcNAQELBQADggEB +AJacpAT2GQQn5Rmb/LYaPhguWFHEdjHBO6rU0p7tE8QJW5pwMgim0mFtQlbuXE2L +mbHrYCyRgVyaPV9gNiFg1sLzQMmmG4Afg1N4cpdg8zLZFZho+eyYGRkH+EtrAN0Q +l8l603zovMXj8q8Q1eeurxkDHA6mDgwwMGiBQgAiPixQVOjvL+5M5PkwNw/kVzjA +0EXumGQkeZ1jUAkVjp7uWbyoVatamUcpYvo51NQQQeuqwzdo2oDYLa27axWxaqj2 +m4TKsz2WnnrSnrpq3NnflXfWcOrnXI3odNlhQoPmtZQVt6P8pNbGrx4XD/WTGkGw +i/6jlkwwjK7A7dSepfnTI4Y= -----END CERTIFICATE----- diff --git a/test/rubygems/wrong_key_cert_32.pem b/test/rubygems/wrong_key_cert_32.pem index 7a3bb9f714..aca829ab44 100644 --- a/test/rubygems/wrong_key_cert_32.pem +++ b/test/rubygems/wrong_key_cert_32.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDCzCCAfOgAwIBAgIBEzANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv +MIIDCzCCAfOgAwIBAgIBEzANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTEyMDEwMTAwMDAwMFoXDTM4 MDExOTAzMTQwN1owKjEPMA0GA1UEAwwGbm9ib2R5MRcwFQYKCZImiZPyLGQBGRYH -ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2UIqQWtcR9 -zPTqJ5K1GIRmXl/VBwHCYXuoyW1K/7h15IdU7thEVjZ25ZvObqagX48mRJynq+7g -XMMJJL5orFYAvLgRAsprAcbhCMNK34imBJy7tAekolhWM93WD0vdmwSu1ZLNv5Dc -l1JiyxqGd4nditHiuQvwCdI/qfODqj51YcpbI62Zl3yGa4e5ZB4YAiK8z3n4xN6T -paIv7c+n4dpLW9BWCkDH8Hk9wWtkzHn5RtdzxDlvNAA+cNEx8Q7rRhtMzzQg8gxK -E+1FNWtwd0TB2LlMRJNRlBGFqvS+mukjKWSElk0qQqdFsNUAeeTzjYggp/qOr3CM -uOoyO9XQEwECAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD -VR0OBBYEFMr5/xcHGZwOwJMz45qKKAeP7SoHMA0GCSqGSIb3DQEBBQUAA4IBAQCU -VkESWkNeiJ1L3MfkMl2ybP2QPWP5nlhz+NOqwOCJSmEXF86Dq2XTY/GgSu1iPp4s -pPm1RSpnjujtiV7gjCziNif/XqAxeSjU2deApvq4mknyk958N0IS8c86dUXms1DQ -Rncmb3pxxvzP1d6Is35Uwoc5KqheJWR3aDwE8ejaFfO8pq/ncUDB25bc7OyslHMJ -7Ah+2YlFjvHYuPvN8bP44UMYyAPZCCJnjIPn7m7giyQiIo6SA9aiLQ8F7+NN3SU4 -7I9ED0F7RTDxNYISr1sLZ7aNtnXkTAnZclwKohuGfZD3OGAOshLZZXIB2pIRr/Kj -6zxTef39tli6orheYQXp +ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKXmxpuzTp8f +g7VhtcULCQX038DZWb382OtZ5WXHK4VOr8dAJ2DYg2QBtyf4BUJmGfYCffK8xMHy +zAhqvUf02TPpQBGi4c2GQrt1+EHYSsa9cWf0hQvtX/Clbh+LS1zkVt9A8Gsj4TcZ +6zr7qeKVi4mLl1EmaVfQhjLz0lAltqHYTJATCqmk0z48aFySHIGnMqa5DYCKuPHE +r6lhv3vx6zEbZKrxWw+bWtNLjtZpaWo2GMNUUX7RMJLRaPL0IAwaPTU/xKqBO9rX +32g5y6uq0K1bcOCq/X8u++Q4zQFl8oggY5yYDkElwhj7DPwBHRa4fyykEL9jPzO1 +jXr5xFILBCMCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD +VR0OBBYEFGD8EvIPfPuE6v/IHBCtYopZBlx+MA0GCSqGSIb3DQEBCwUAA4IBAQBE +lq/rPaPT+5uui42u4BTFayrQU9EFik9xPG6WJw+IJ/5CprECj6h90FC+GaMNeu2Z +R0l+iEfgx4xBM4DERiRVLZIlHbZzuPp0YRYH9gyJot/+0piaAcnUEvjz2Z8axoFq +lE3/q4s6Yw8xdqwxvc5kiwymv2nEm4+v5w6Pb3K/fP/QQLvDUBWrBUMHPgdYXYk2 +zvc58BBwgGDSpFRO0tw+lnqMTM1y+fbpfuvP9TY1m4y13nuw/g7KxVxYolAWVQs3 +TptnJqqzEwdFa2S9BidUIlDRRY8cuhY6R3DM6THNLjR3c1oyf04nhT3sd/ilAJdD +YjnEtcLlkjxZyLLoWjn2 -----END CERTIFICATE----- |