1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
|
# frozen_string_literal: true
require_relative "helper"
require "rubygems"
class TestGemRequire < Gem::TestCase
class Latch
def initialize(count = 1)
@count = count
@lock = Monitor.new
@cv = @lock.new_cond
end
def release
@lock.synchronize do
@count -= 1 if @count > 0
@cv.broadcast if @count.zero?
end
end
def await
@lock.synchronize do
@cv.wait_while { @count > 0 }
end
end
end
def assert_require(path)
assert require(path), "'#{path}' was already required"
end
def refute_require(path)
refute require(path), "'#{path}' was not yet required"
end
def test_respect_loaded_features_caching_like_standard_require
dir = Dir.mktmpdir("test_require", @tempdir)
lp1 = File.join dir, "foo1"
foo1 = File.join lp1, "foo.rb"
FileUtils.mkdir_p lp1
File.open(foo1, "w") {|f| f.write "class Object; HELLO = 'foo1' end" }
lp = $LOAD_PATH.dup
$LOAD_PATH.unshift lp1
assert_require "foo"
assert_equal "foo1", ::Object::HELLO
lp2 = File.join dir, "foo2"
foo2 = File.join lp2, "foo.rb"
FileUtils.mkdir_p lp2
File.open(foo2, "w") {|f| f.write "class Object; HELLO = 'foo2' end" }
$LOAD_PATH.unshift lp2
refute_require "foo"
assert_equal "foo1", ::Object::HELLO
ensure
$LOAD_PATH.replace lp
Object.send :remove_const, :HELLO if Object.const_defined? :HELLO
end
# Providing -I on the commandline should always beat gems
def test_dash_i_beats_gems
a1 = util_spec "a", "1", { "b" => "= 1" }, "lib/test_gem_require_a.rb"
b1 = util_spec "b", "1", { "c" => "> 0" }, "lib/b/c.rb"
c1 = util_spec "c", "1", nil, "lib/c/c.rb"
c2 = util_spec "c", "2", nil, "lib/c/c.rb"
install_specs c1, c2, b1, a1
dir = Dir.mktmpdir("test_require", @tempdir)
dash_i_arg = File.join dir, "lib"
c_rb = File.join dash_i_arg, "b", "c.rb"
FileUtils.mkdir_p File.dirname c_rb
File.open(c_rb, "w") {|f| f.write "class Object; HELLO = 'world' end" }
# Pretend to provide a commandline argument that overrides a file in gem b
$LOAD_PATH.unshift dash_i_arg
assert_require "test_gem_require_a"
assert_require "b/c" # this should be required from -I
assert_equal "world", ::Object::HELLO
assert_equal %w[a-1 b-1], loaded_spec_names
ensure
Object.send :remove_const, :HELLO if Object.const_defined? :HELLO
end
def create_sync_thread
Thread.new do
yield
ensure
FILE_ENTERED_LATCH.release
FILE_EXIT_LATCH.await
end
end
# Providing -I on the commandline should always beat gems
def test_dash_i_beats_default_gems
a1 = new_default_spec "a", "1", { "b" => "= 1" }, "test_gem_require_a.rb"
b1 = new_default_spec "b", "1", { "c" => "> 0" }, "b/c.rb"
c1 = new_default_spec "c", "1", nil, "c/c.rb"
c2 = new_default_spec "c", "2", nil, "c/c.rb"
install_default_gems c1, c2, b1, a1
dir = Dir.mktmpdir("test_require", @tempdir)
dash_i_arg = File.join dir, "lib"
c_rb = File.join dash_i_arg, "c", "c.rb"
FileUtils.mkdir_p File.dirname c_rb
File.open(c_rb, "w") {|f| f.write "class Object; HELLO = 'world' end" }
assert_require "test_gem_require_a"
# Pretend to provide a commandline argument that overrides a file in gem b
$LOAD_PATH.unshift dash_i_arg
assert_require "b/c"
assert_require "c/c" # this should be required from -I
assert_equal "world", ::Object::HELLO
assert_equal %w[a-1 b-1], loaded_spec_names
ensure
Object.send :remove_const, :HELLO if Object.const_defined? :HELLO
end
def test_dash_i_respects_default_library_extension_priority
pend "needs investigation" if Gem.java_platform?
pend "not installed yet" unless RbConfig::TOPDIR
dash_i_ext_arg = util_install_extension_file("a")
dash_i_lib_arg = util_install_ruby_file("a")
$LOAD_PATH.unshift dash_i_lib_arg
$LOAD_PATH.unshift dash_i_ext_arg
assert_require "a"
assert_match(/a\.rb$/, $LOADED_FEATURES.last)
end
def test_concurrent_require
Object.const_set :FILE_ENTERED_LATCH, Latch.new(2)
Object.const_set :FILE_EXIT_LATCH, Latch.new(1)
a1 = util_spec "a#{$$}", "1", nil, "lib/a#{$$}.rb"
b1 = util_spec "b#{$$}", "1", nil, "lib/b#{$$}.rb"
install_specs a1, b1
t1 = create_sync_thread { assert_require "a#{$$}" }
t2 = create_sync_thread { assert_require "b#{$$}" }
# wait until both files are waiting on the exit latch
FILE_ENTERED_LATCH.await
# now let them finish
FILE_EXIT_LATCH.release
assert t1.join, "thread 1 should exit"
assert t2.join, "thread 2 should exit"
ensure
Object.send :remove_const, :FILE_ENTERED_LATCH if Object.const_defined? :FILE_ENTERED_LATCH
Object.send :remove_const, :FILE_EXIT_LATCH if Object.const_defined? :FILE_EXIT_LATCH
end
def test_require_is_not_lazy_with_exact_req
a1 = util_spec "a", "1", { "b" => "= 1" }, "lib/test_gem_require_a.rb"
b1 = util_spec "b", "1", nil, "lib/b/c.rb"
b2 = util_spec "b", "2", nil, "lib/b/c.rb"
install_specs b1, b2, a1
assert_require "test_gem_require_a"
assert_equal %w[a-1 b-1], loaded_spec_names
assert_equal unresolved_names, []
assert_require "b/c"
assert_equal %w[a-1 b-1], loaded_spec_names
end
def test_require_is_not_lazy_with_shadowed_default_gem
b1_default = new_default_spec("b", "1", nil, "foo.rb")
install_default_gems b1_default
a1 = util_spec "a", "1", { "b" => ">= 1" }, "lib/test_gem_require_a.rb"
b1 = util_spec("b", "1", nil, "lib/foo.rb")
install_specs b1, a1
# Load default ruby gems fresh as if we've just started a ruby script.
Gem::Specification.reset
assert_require "test_gem_require_a"
assert_equal %w[a-1 b-1], loaded_spec_names
assert_equal unresolved_names, []
end
def test_require_is_lazy_with_inexact_req
a1 = util_spec "a", "1", { "b" => ">= 1" }, "lib/test_gem_require_a.rb"
b1 = util_spec "b", "1", nil, "lib/b/c.rb"
b2 = util_spec "b", "2", nil, "lib/b/c.rb"
install_specs b1, b2, a1
assert_require "test_gem_require_a"
assert_equal %w[a-1], loaded_spec_names
assert_equal unresolved_names, ["b (>= 1)"]
assert_require "b/c"
assert_equal %w[a-1 b-2], loaded_spec_names
end
def test_require_is_not_lazy_with_one_possible
a1 = util_spec "a", "1", { "b" => ">= 1" }, "lib/test_gem_require_a.rb"
b1 = util_spec "b", "1", nil, "lib/b/c.rb"
install_specs b1, a1
assert_require "test_gem_require_a"
assert_equal %w[a-1 b-1], loaded_spec_names
assert_equal unresolved_names, []
assert_require "b/c"
assert_equal %w[a-1 b-1], loaded_spec_names
end
def test_require_can_use_a_pathname_object
a1 = util_spec "a", "1", nil, "lib/test_gem_require_a.rb"
install_specs a1
assert_require Pathname.new "test_gem_require_a"
assert_equal %w[a-1], loaded_spec_names
assert_equal unresolved_names, []
end
def test_activate_via_require_respects_loaded_files
pend "Not sure what's going on. If another spec creates a 'a' gem before
this test, somehow require will load the erb 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 Gem.java_platform?
pend "not installed yet" unless RbConfig::TOPDIR
lib_dir = File.expand_path("../lib", __dir__)
rubylibdir = File.realdirpath(RbConfig::CONFIG["rubylibdir"])
if rubylibdir == lib_dir
# testing in the ruby repository where RubyGems' lib/ == stdlib lib/
# In that case we want to move the stdlib lib/ to still be after b-2 in $LOAD_PATH
lp = $LOAD_PATH.dup
$LOAD_PATH.delete lib_dir
$LOAD_PATH.push lib_dir
load_path_changed = true
end
require "erb" # the stdlib
a1 = util_spec "a", "1", { "b" => ">= 1" }, "lib/test_gem_require_a.rb"
b1 = util_spec "b", "1", nil, "lib/erb.rb"
b2 = util_spec "b", "2", nil, "lib/erb.rb"
install_specs b1, b2, a1
# 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.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)"]
# The require('erb') below will activate b-2. However, its
# lib/erb.rb won't ever be loaded. The reason is MRI sees that even
# though b-2 is earlier in $LOAD_PATH it already loaded a erb.rb file
# and that still exists in $LOAD_PATH (further down),
# and as a result #gem_original_require returns false.
refute require("erb"), "the erb stdlib should be recognized as already loaded"
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.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 erb.rb" loaded.
# This case is fine because our lazy loading provided exactly
# the same behavior as eager loading would have.
assert_equal %w[a-1 b-2], loaded_spec_names
ensure
$LOAD_PATH.replace lp if load_path_changed
end
def test_activate_via_require_respects_loaded_default_from_default_gems
a1 = new_default_spec "a", "1", nil, "a.rb"
# simulate requiring a default gem before rubygems is loaded
Kernel.send(:gem_original_require, "a")
# simulate registering default specs on loading rubygems
install_default_gems a1
a2 = util_spec "a", "2", nil, "lib/a.rb"
install_specs a2
refute_require "a"
assert_equal %w[a-1], loaded_spec_names
end
def test_already_activated_direct_conflict
a1 = util_spec "a", "1", { "b" => "> 0" }
b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/ib.rb"
b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/ib.rb"
c1 = util_spec "c", "1", nil, "lib/d.rb"
c2 = util_spec("c", "2", nil, "lib/d.rb")
install_specs c1, c2, b1, b2, a1
a1.activate
c1.activate
assert_equal %w[a-1 c-1], loaded_spec_names
assert_equal ["b (> 0)"], unresolved_names
assert require("ib")
assert_equal %w[a-1 b-1 c-1], loaded_spec_names
assert_equal [], unresolved_names
end
def test_multiple_gems_with_the_same_path
a1 = util_spec "a", "1", { "b" => "> 0", "x" => "> 0" }
b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/ib.rb"
b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/ib.rb"
x1 = util_spec "x", "1", nil, "lib/ib.rb"
x2 = util_spec "x", "2", nil, "lib/ib.rb"
c1 = util_spec "c", "1", nil, "lib/d.rb"
c2 = util_spec("c", "2", nil, "lib/d.rb")
install_specs c1, c2, x1, x2, b1, b2, a1
a1.activate
c1.activate
assert_equal %w[a-1 c-1], loaded_spec_names
assert_equal ["b (> 0)", "x (> 0)"], unresolved_names
e = assert_raise(Gem::LoadError) do
require("ib")
end
assert_equal "ib found in multiple gems: b, x", e.message
end
def test_unable_to_find_good_unresolved_version
a1 = util_spec "a", "1", { "b" => "> 0" }
b1 = util_spec "b", "1", { "c" => ">= 2" }, "lib/ib.rb"
b2 = util_spec "b", "2", { "c" => ">= 3" }, "lib/ib.rb"
c1 = util_spec "c", "1", nil, "lib/d.rb"
c2 = util_spec "c", "2", nil, "lib/d.rb"
c3 = util_spec "c", "3", nil, "lib/d.rb"
install_specs c1, c2, c3, b1, b2, a1
a1.activate
c1.activate
assert_equal %w[a-1 c-1], loaded_spec_names
assert_equal ["b (> 0)"], unresolved_names
e = assert_raise(Gem::LoadError) do
require("ib")
end
assert_equal "unable to find a version of 'b' to activate", e.message
end
def test_require_works_after_cleanup
a1 = new_default_spec "a", "1.0", nil, "a/b.rb"
b1 = new_default_spec "b", "1.0", nil, "b/c.rb"
b2 = new_default_spec "b", "2.0", nil, "b/d.rb"
install_default_gems a1
install_default_gems b1
install_default_gems b2
# Load default ruby gems fresh as if we've just started a ruby script.
Gem::Specification.reset
require "rubygems"
Gem::Specification.stubs
# Remove an old default gem version directly from disk as if someone ran
# gem cleanup.
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"
assert_equal %w[a-1.0], loaded_spec_names
assert_require "b/d"
assert_equal %w[a-1.0 b-2.0], loaded_spec_names
end
def test_require_doesnt_traverse_development_dependencies
a = util_spec("a#{$$}", "1", nil, "lib/a#{$$}.rb")
z = util_spec("z", "1", "w" => "> 0")
w1 = util_spec("w", "1") {|s| s.add_development_dependency "non-existent" }
w2 = util_spec("w", "2") {|s| s.add_development_dependency "non-existent" }
install_specs a, w1, w2, z
assert gem("z")
assert_equal %w[z-1], loaded_spec_names
assert_equal ["w (> 0)"], unresolved_names
assert require("a#{$$}")
end
def test_default_gem_only
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
install_default_gems(default_gem_spec)
assert_require "default/gem"
assert_equal %w[default-2.0.0.0], loaded_spec_names
end
def test_default_gem_require_activates_just_once
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
install_default_gems(default_gem_spec)
assert_require "default/gem"
times_called = 0
Kernel.stub(:gem, ->(_name, _requirement) { times_called += 1 }) do
refute_require "default/gem"
end
assert_equal 0, times_called
end
def test_second_gem_require_does_not_resolve_path_manually_before_going_through_standard_require
a1 = util_spec "a", "1", nil, "lib/test_gem_require_a.rb"
install_gem a1
assert_require "test_gem_require_a"
stub(:gem_original_require, ->(path) { assert_equal "test_gem_require_a", path }) do
require "test_gem_require_a"
end
end
def test_realworld_default_gem
omit "this test can't work under ruby-core setup" if ruby_repo?
cmd = <<-RUBY
$stderr = $stdout
require "json"
puts Gem.loaded_specs["json"]
RUBY
output = Gem::Util.popen(*ruby_with_rubygems_in_load_path, "-e", cmd).strip
assert $?.success?
refute_empty output
end
def test_realworld_upgraded_default_gem
omit "this test can't work under ruby-core setup" if ruby_repo?
newer_json = util_spec("json", "999.99.9", nil, ["lib/json.rb"])
install_gem newer_json
path = "#{@tempdir}/test_realworld_upgraded_default_gem.rb"
code = <<-RUBY
$stderr = $stdout
require "json"
puts Gem.loaded_specs["json"].version
puts $LOADED_FEATURES
RUBY
File.write(path, code)
output = Gem::Util.popen({ "GEM_HOME" => @gemhome }, *ruby_with_rubygems_in_load_path, path).strip
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
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
install_default_gems(default_gem_spec)
normal_gem_spec = util_spec("default", "3.0", nil,
"lib/default/gem.rb")
install_specs(normal_gem_spec)
assert_require "default/gem"
assert_equal %w[default-3.0], loaded_spec_names
end
def test_default_gem_and_normal_gem_same_version
default_gem_spec = new_default_spec("default", "3.0",
nil, "default/gem.rb")
install_default_gems(default_gem_spec)
normal_gem_spec = util_spec("default", "3.0", nil,
"lib/default/gem.rb")
install_specs(normal_gem_spec)
# Load default ruby gems fresh as if we've just started a ruby script.
Gem::Specification.reset
assert_require "default/gem"
assert_equal %w[default-3.0], loaded_spec_names
refute Gem.loaded_specs["default"].default_gem?
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")
install_specs(normal_gem_spec)
File.write("require_with_overridden_load_error_message.rb", <<-RUBY)
LoadError.class_eval do
def message
"Overridden message"
end
end
require 'normal/gem'
RUBY
require "open3"
output, exit_status = Open3.capture2e(
{ "GEM_HOME" => Gem.paths.home },
*ruby_with_rubygems_in_load_path,
"-r",
"./require_with_overridden_load_error_message.rb"
)
assert exit_status.success?, "Require failed due to #{output}"
end
def test_default_gem_prerelease
default_gem_spec = new_default_spec("default", "2.0.0",
nil, "default/gem.rb")
install_default_gems(default_gem_spec)
normal_gem_higher_prerelease_spec = util_spec("default", "3.0.0.rc2", nil,
"lib/default/gem.rb")
install_default_gems(normal_gem_higher_prerelease_spec)
assert_require "default/gem"
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
def unresolved_names
Gem::Specification.unresolved_deps.values.map(&:to_s).sort
end
def test_try_activate_error_unlocks_require_monitor
silence_warnings do
class << ::Gem
alias_method :old_try_activate, :try_activate
def try_activate(*)
raise "raised from try_activate"
end
end
end
require "does_not_exist_for_try_activate_test"
rescue RuntimeError => e
assert_match(/raised from try_activate/, e.message)
assert Kernel::RUBYGEMS_ACTIVATION_MONITOR.try_enter, "require monitor was not unlocked when try_activate raised"
ensure
silence_warnings do
class << ::Gem
alias_method :try_activate, :old_try_activate
end
end
Kernel::RUBYGEMS_ACTIVATION_MONITOR.exit
end
def test_require_when_gem_defined
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
install_default_gems(default_gem_spec)
c = Class.new do
def self.gem(*args)
raise "received #gem with #{args.inspect}"
end
end
assert c.send(:require, "default/gem")
assert_equal %w[default-2.0.0.0], loaded_spec_names
end
def test_require_default_when_gem_defined
a = util_spec("a#{$$}", "1", nil, "lib/a#{$$}.rb")
install_specs a
c = Class.new do
def self.gem(*args)
raise "received #gem with #{args.inspect}"
end
end
assert c.send(:require, "a#{$$}")
assert_equal %W[a#{$$}-1], loaded_spec_names
end
def test_require_bundler
b1 = util_spec("bundler", "1", nil, "lib/bundler/setup.rb")
b2a = util_spec("bundler", "2.a", nil, "lib/bundler/setup.rb")
install_specs b1, b2a
require "rubygems/bundler_version_finder"
$:.clear
assert_require "bundler/setup"
assert_equal %w[bundler-2.a], loaded_spec_names
assert_empty unresolved_names
end
["", "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)
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 }.inspect}\n#{{ y: 2 }.inspect}\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 }.inspect}\n#{{ y: 2 }.inspect}\n$/, err)
end
end
end
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
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
_, 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)
spec = quick_gem name
util_build_gem spec
spec.extensions << "extconf.rb"
write_file File.join(@tempdir, "extconf.rb") do |io|
io.write <<-RUBY
require "mkmf"
CONFIG['LDSHARED'] = '$(TOUCH) $@ ||'
create_makefile("#{name}")
RUBY
end
write_file File.join(@tempdir, "#{name}.c") do |io|
io.write <<-C
void Init_#{name}() { }
C
end
write_file File.join(@tempdir, "depend")
spec.files += ["extconf.rb", "depend", "#{name}.c"]
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 extension_file
spec.gem_dir
end
def util_install_ruby_file(name)
dir_lib = Dir.mktmpdir("test_require_lib", @tempdir)
dash_i_lib_arg = File.join dir_lib
a_rb = File.join dash_i_lib_arg, "#{name}.rb"
FileUtils.mkdir_p File.dirname a_rb
File.open(a_rb, "w") {|f| f.write "# #{name}.rb" }
dash_i_lib_arg
end
end
|