1# TODO: $SAFE = 1 2 3begin 4 gem 'minitest', '~> 4.0' 5rescue NoMethodError 6 # for ruby tests 7end 8 9if defined? Gem::QuickLoader 10 Gem::QuickLoader.load_full_rubygems_library 11else 12 require 'rubygems' 13end 14 15begin 16 gem 'minitest' 17rescue Gem::LoadError 18end 19 20# We have to load these up front because otherwise we'll try to load 21# them while we're testing rubygems, and thus we can't actually load them. 22unless Gem::Dependency.new('rdoc', '>= 3.10').matching_specs.empty? 23 gem 'rdoc' 24 gem 'json' 25end 26 27require 'rubygems/deprecate' 28require 'minitest/autorun' 29require 'fileutils' 30require 'tmpdir' 31require 'uri' 32require 'rubygems/package' 33require 'rubygems/test_utilities' 34require 'pp' 35require 'zlib' 36require 'pathname' 37require 'shellwords' 38Gem.load_yaml 39 40require 'rubygems/mock_gem_ui' 41 42module Gem 43 44 ## 45 # Allows setting the gem path searcher. This method is available when 46 # requiring 'rubygems/test_case' 47 48 def self.searcher=(searcher) 49 @searcher = searcher 50 end 51 52 ## 53 # Allows toggling Windows behavior. This method is available when requiring 54 # 'rubygems/test_case' 55 56 def self.win_platform=(val) 57 @@win_platform = val 58 end 59 60 ## 61 # Allows setting path to ruby. This method is available when requiring 62 # 'rubygems/test_case' 63 64 def self.ruby= ruby 65 @ruby = ruby 66 end 67 68 ## 69 # When rubygems/test_case is required the default user interaction is a 70 # MockGemUi. 71 72 module DefaultUserInteraction 73 @ui = Gem::MockGemUi.new 74 end 75end 76 77## 78# RubyGemTestCase provides a variety of methods for testing rubygems and 79# gem-related behavior in a sandbox. Through RubyGemTestCase you can install 80# and uninstall gems, fetch remote gems through a stub fetcher and be assured 81# your normal set of gems is not affected. 82# 83# Tests are always run at a safe level of 1. 84 85class Gem::TestCase < MiniTest::Unit::TestCase 86 87 # TODO: move to minitest 88 def assert_path_exists path, msg = nil 89 msg = message(msg) { "Expected path '#{path}' to exist" } 90 assert File.exist?(path), msg 91 end 92 93 # TODO: move to minitest 94 def refute_path_exists path, msg = nil 95 msg = message(msg) { "Expected path '#{path}' to not exist" } 96 refute File.exist?(path), msg 97 end 98 99 def scan_make_command_lines(output) 100 output.scan(/^#{Regexp.escape make_command}(?:[[:blank:]].*)?$/) 101 end 102 103 def parse_make_command_line(line) 104 command, *args = line.shellsplit 105 106 targets = [] 107 macros = {} 108 109 args.each do |arg| 110 case arg 111 when /\A(\w+)=/ 112 macros[$1] = $' 113 else 114 targets << arg 115 end 116 end 117 118 targets << '' if targets.empty? 119 120 { 121 :command => command, 122 :targets => targets, 123 :macros => macros, 124 } 125 end 126 127 def assert_contains_make_command(target, output, msg = nil) 128 if output.match(/\n/) 129 msg = message(msg) { 130 'Expected output containing make command "%s": %s' % [ 131 ('%s %s' % [make_command, target]).rstrip, 132 output.inspect 133 ] 134 } 135 else 136 msg = message(msg) { 137 'Expected make command "%s": %s' % [ 138 ('%s %s' % [make_command, target]).rstrip, 139 output.inspect 140 ] 141 } 142 end 143 144 assert scan_make_command_lines(output).any? { |line| 145 make = parse_make_command_line(line) 146 147 if make[:targets].include?(target) 148 yield make, line if block_given? 149 true 150 else 151 false 152 end 153 }, msg 154 end 155 156 include Gem::DefaultUserInteraction 157 158 undef_method :default_test if instance_methods.include? 'default_test' or 159 instance_methods.include? :default_test 160 161 @@project_dir = Dir.pwd.untaint unless defined?(@@project_dir) 162 163 @@initial_reset = false 164 165 ## 166 # #setup prepares a sandboxed location to install gems. All installs are 167 # directed to a temporary directory. All install plugins are removed. 168 # 169 # If the +RUBY+ environment variable is set the given path is used for 170 # Gem::ruby. The local platform is set to <tt>i386-mswin32</tt> for Windows 171 # or <tt>i686-darwin8.10.1</tt> otherwise. 172 # 173 # If the +KEEP_FILES+ environment variable is set the files will not be 174 # removed from <tt>/tmp/test_rubygems_#{$$}.#{Time.now.to_i}</tt>. 175 176 def setup 177 super 178 179 @orig_gem_home = ENV['GEM_HOME'] 180 @orig_gem_path = ENV['GEM_PATH'] 181 182 @current_dir = Dir.pwd 183 @ui = Gem::MockGemUi.new 184 185 tmpdir = File.expand_path Dir.tmpdir 186 tmpdir.untaint 187 188 if ENV['KEEP_FILES'] then 189 @tempdir = File.join(tmpdir, "test_rubygems_#{$$}.#{Time.now.to_i}") 190 else 191 @tempdir = File.join(tmpdir, "test_rubygems_#{$$}") 192 end 193 @tempdir.untaint 194 195 FileUtils.mkdir_p @tempdir 196 197 # This makes the tempdir consistent on OS X. 198 # File.expand_path Dir.tmpdir #=> "/var/..." 199 # Dir.chdir Dir.tmpdir do File.expand_path '.' end #=> "/private/var/..." 200 # TODO use File#realpath above instead of #expand_path once 1.8 support is 201 # dropped. 202 Dir.chdir @tempdir do 203 @tempdir = File.expand_path '.' 204 @tempdir.untaint 205 end 206 207 @gemhome = File.join @tempdir, 'gemhome' 208 @userhome = File.join @tempdir, 'userhome' 209 210 @orig_ruby = if ENV['RUBY'] then 211 ruby = Gem.instance_variable_get :@ruby 212 Gem.instance_variable_set :@ruby, ENV['RUBY'] 213 ruby 214 end 215 216 Gem.ensure_gem_subdirectories @gemhome 217 218 @orig_LOAD_PATH = $LOAD_PATH.dup 219 $LOAD_PATH.map! { |s| File.expand_path(s).untaint } 220 221 Dir.chdir @tempdir 222 223 @orig_ENV_HOME = ENV['HOME'] 224 ENV['HOME'] = @userhome 225 Gem.instance_variable_set :@user_home, nil 226 227 FileUtils.mkdir_p @gemhome 228 FileUtils.mkdir_p @userhome 229 230 @default_dir = File.join @tempdir, 'default' 231 @default_spec_dir = File.join @default_dir, "specifications", "default" 232 Gem.instance_variable_set :@default_dir, @default_dir 233 FileUtils.mkdir_p @default_spec_dir 234 235 # We use Gem::Specification.reset the first time only so that if there 236 # are unresolved deps that leak into the whole test suite, they're at least 237 # reported once. 238 if @@initial_reset 239 Gem::Specification.unresolved_deps.clear # done to avoid cross-test warnings 240 else 241 @@initial_reset = true 242 Gem::Specification.reset 243 end 244 Gem.use_paths(@gemhome) 245 246 Gem::Security.reset 247 248 Gem.loaded_specs.clear 249 Gem.clear_default_specs 250 Gem::Specification.unresolved_deps.clear 251 252 Gem.configuration.verbose = true 253 Gem.configuration.update_sources = true 254 255 Gem::RemoteFetcher.fetcher = Gem::FakeFetcher.new 256 257 @gem_repo = "http://gems.example.com/" 258 @uri = URI.parse @gem_repo 259 Gem.sources.replace [@gem_repo] 260 261 Gem.searcher = nil 262 Gem::SpecFetcher.fetcher = nil 263 @orig_BASERUBY = Gem::ConfigMap[:BASERUBY] 264 Gem::ConfigMap[:BASERUBY] = Gem::ConfigMap[:ruby_install_name] 265 266 @orig_arch = Gem::ConfigMap[:arch] 267 268 if win_platform? 269 util_set_arch 'i386-mswin32' 270 else 271 util_set_arch 'i686-darwin8.10.1' 272 end 273 274 @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" 275 276 # TODO: move to installer test cases 277 Gem.post_build_hooks.clear 278 Gem.post_install_hooks.clear 279 Gem.done_installing_hooks.clear 280 Gem.post_reset_hooks.clear 281 Gem.post_uninstall_hooks.clear 282 Gem.pre_install_hooks.clear 283 Gem.pre_reset_hooks.clear 284 Gem.pre_uninstall_hooks.clear 285 286 # TODO: move to installer test cases 287 Gem.post_build do |installer| 288 @post_build_hook_arg = installer 289 true 290 end 291 292 Gem.post_install do |installer| 293 @post_install_hook_arg = installer 294 end 295 296 Gem.post_uninstall do |uninstaller| 297 @post_uninstall_hook_arg = uninstaller 298 end 299 300 Gem.pre_install do |installer| 301 @pre_install_hook_arg = installer 302 true 303 end 304 305 Gem.pre_uninstall do |uninstaller| 306 @pre_uninstall_hook_arg = uninstaller 307 end 308 end 309 310 ## 311 # #teardown restores the process to its original state and removes the 312 # tempdir unless the +KEEP_FILES+ environment variable was set. 313 314 def teardown 315 $LOAD_PATH.replace @orig_LOAD_PATH if @orig_LOAD_PATH 316 317 Gem::ConfigMap[:BASERUBY] = @orig_BASERUBY 318 Gem::ConfigMap[:arch] = @orig_arch 319 320 if defined? Gem::RemoteFetcher then 321 Gem::RemoteFetcher.fetcher = nil 322 end 323 324 Dir.chdir @current_dir 325 326 FileUtils.rm_rf @tempdir unless ENV['KEEP_FILES'] 327 328 ENV['GEM_HOME'] = @orig_gem_home 329 ENV['GEM_PATH'] = @orig_gem_path 330 331 _ = @orig_ruby 332 Gem.instance_variable_set :@ruby, @orig_ruby if @orig_ruby 333 334 if @orig_ENV_HOME then 335 ENV['HOME'] = @orig_ENV_HOME 336 else 337 ENV.delete 'HOME' 338 end 339 340 Gem.instance_variable_set :@default_dir, nil 341 end 342 343 ## 344 # Builds and installs the Gem::Specification +spec+ 345 346 def install_gem spec, options = {} 347 require 'rubygems/installer' 348 349 gem = File.join @tempdir, "gems", "#{spec.full_name}.gem" 350 351 unless File.exists? gem 352 use_ui Gem::MockGemUi.new do 353 Dir.chdir @tempdir do 354 Gem::Package.build spec 355 end 356 end 357 358 gem = File.join(@tempdir, File.basename(spec.cache_file)).untaint 359 end 360 361 Gem::Installer.new(gem, options.merge({:wrappers => true})).install 362 end 363 364 ## 365 # Builds and installs the Gem::Specification +spec+ into the user dir 366 367 def install_gem_user spec 368 install_gem spec, :user_install => true 369 end 370 371 ## 372 # Uninstalls the Gem::Specification +spec+ 373 def uninstall_gem spec 374 require 'rubygems/uninstaller' 375 376 Gem::Uninstaller.new(spec.name, 377 :executables => true, :user_install => true).uninstall 378 end 379 380 ## 381 # creates a temporary directory with hax 382 # TODO: deprecate and remove 383 384 def create_tmpdir 385 tmpdir = nil 386 Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end # HACK OSX /private/tmp 387 tmpdir = File.join tmpdir, "test_rubygems_#{$$}" 388 FileUtils.mkdir_p tmpdir 389 return tmpdir 390 end 391 392 ## 393 # Enables pretty-print for all tests 394 395 def mu_pp(obj) 396 s = '' 397 s = PP.pp obj, s 398 s = s.force_encoding(Encoding.default_external) if defined? Encoding 399 s.chomp 400 end 401 402 ## 403 # Reads a Marshal file at +path+ 404 405 def read_cache(path) 406 open path.dup.untaint, 'rb' do |io| 407 Marshal.load io.read 408 end 409 end 410 411 ## 412 # Reads a binary file at +path+ 413 414 def read_binary(path) 415 Gem.read_binary path 416 end 417 418 ## 419 # Writes a binary file to +path+ which is relative to +@gemhome+ 420 421 def write_file(path) 422 path = File.join @gemhome, path unless Pathname.new(path).absolute? 423 dir = File.dirname path 424 FileUtils.mkdir_p dir 425 426 open path, 'wb' do |io| 427 yield io if block_given? 428 end 429 430 path 431 end 432 433 def all_spec_names 434 Gem::Specification.map(&:full_name) 435 end 436 437 ## 438 # Creates a Gem::Specification with a minimum of extra work. +name+ and 439 # +version+ are the gem's name and version, platform, author, email, 440 # homepage, summary and description are defaulted. The specification is 441 # yielded for customization. 442 # 443 # The gem is added to the installed gems in +@gemhome+ and the runtime. 444 # 445 # Use this with #write_file to build an installed gem. 446 447 def quick_gem(name, version='2') 448 require 'rubygems/specification' 449 450 spec = Gem::Specification.new do |s| 451 s.platform = Gem::Platform::RUBY 452 s.name = name 453 s.version = version 454 s.author = 'A User' 455 s.email = 'example@example.com' 456 s.homepage = 'http://example.com' 457 s.summary = "this is a summary" 458 s.description = "This is a test description" 459 460 yield(s) if block_given? 461 end 462 463 Gem::Specification.map # HACK: force specs to (re-)load before we write 464 465 written_path = write_file spec.spec_file do |io| 466 io.write spec.to_ruby_for_cache 467 end 468 469 spec.loaded_from = spec.loaded_from = written_path 470 471 Gem::Specification.add_spec spec.for_cache 472 473 return spec 474 end 475 476 def quick_spec name, version = '2' 477 # TODO: deprecate 478 require 'rubygems/specification' 479 480 spec = Gem::Specification.new do |s| 481 s.platform = Gem::Platform::RUBY 482 s.name = name 483 s.version = version 484 s.author = 'A User' 485 s.email = 'example@example.com' 486 s.homepage = 'http://example.com' 487 s.summary = "this is a summary" 488 s.description = "This is a test description" 489 490 yield(s) if block_given? 491 end 492 493 spec.loaded_from = spec.spec_file 494 495 Gem::Specification.add_spec spec 496 497 return spec 498 end 499 500 ## 501 # Builds a gem from +spec+ and places it in <tt>File.join @gemhome, 502 # 'cache'</tt>. Automatically creates files based on +spec.files+ 503 504 def util_build_gem(spec) 505 dir = spec.gem_dir 506 FileUtils.mkdir_p dir 507 508 Dir.chdir dir do 509 spec.files.each do |file| 510 next if File.exist? file 511 FileUtils.mkdir_p File.dirname(file) 512 File.open file, 'w' do |fp| fp.puts "# #{file}" end 513 end 514 515 use_ui Gem::MockGemUi.new do 516 Gem::Package.build spec 517 end 518 519 cache = spec.cache_file 520 FileUtils.mv File.basename(cache), cache 521 end 522 end 523 524 def util_remove_gem(spec) 525 FileUtils.rm_rf spec.cache_file 526 FileUtils.rm_rf spec.spec_file 527 end 528 529 ## 530 # Removes all installed gems from +@gemhome+. 531 532 def util_clear_gems 533 FileUtils.rm_rf File.join(@gemhome, "gems") # TODO: use Gem::Dirs 534 FileUtils.rm_rf File.join(@gemhome, "specifications") 535 Gem::Specification.reset 536 end 537 538 ## 539 # Install the provided specs 540 541 def install_specs(*specs) 542 Gem::Specification.add_specs(*specs) 543 Gem.searcher = nil 544 end 545 546 ## 547 # Installs the provided default specs including writing the spec file 548 549 def install_default_gems(*specs) 550 install_default_specs(*specs) 551 552 specs.each do |spec| 553 open spec.loaded_from, 'w' do |io| 554 io.write spec.to_ruby_for_cache 555 end 556 end 557 end 558 559 ## 560 # Install the provided default specs 561 562 def install_default_specs(*specs) 563 install_specs(*specs) 564 specs.each do |spec| 565 Gem.register_default_spec(spec) 566 end 567 end 568 569 ## 570 # Create a new spec (or gem if passed an array of files) and set it 571 # up properly. Use this instead of util_spec and util_gem. 572 573 def new_spec name, version, deps = nil, *files 574 require 'rubygems/specification' 575 576 spec = Gem::Specification.new do |s| 577 s.platform = Gem::Platform::RUBY 578 s.name = name 579 s.version = version 580 s.author = 'A User' 581 s.email = 'example@example.com' 582 s.homepage = 'http://example.com' 583 s.summary = "this is a summary" 584 s.description = "This is a test description" 585 586 Array(deps).each do |n, req| 587 s.add_dependency n, (req || '>= 0') 588 end 589 590 s.files.push(*files) unless files.empty? 591 592 yield s if block_given? 593 end 594 595 spec.loaded_from = spec.spec_file 596 597 unless files.empty? then 598 write_file spec.spec_file do |io| 599 io.write spec.to_ruby_for_cache 600 end 601 602 util_build_gem spec 603 604 cache_file = File.join @tempdir, 'gems', "#{spec.full_name}.gem" 605 FileUtils.mkdir_p File.dirname cache_file 606 FileUtils.mv spec.cache_file, cache_file 607 FileUtils.rm spec.spec_file 608 end 609 610 spec 611 end 612 613 def new_default_spec(name, version, deps = nil, *files) 614 spec = new_spec(name, version, deps) 615 spec.loaded_from = File.join(@default_spec_dir, spec.spec_name) 616 spec.files = files 617 618 lib_dir = File.join(@tempdir, "default_gems", "lib") 619 $LOAD_PATH.unshift(lib_dir) 620 files.each do |file| 621 rb_path = File.join(lib_dir, file) 622 FileUtils.mkdir_p(File.dirname(rb_path)) 623 File.open(rb_path, "w") do |rb| 624 rb << "# #{file}" 625 end 626 end 627 628 spec 629 end 630 631 ## 632 # Creates a spec with +name+, +version+ and +deps+. 633 634 def util_spec(name, version, deps = nil, &block) 635 # TODO: deprecate 636 raise "deps or block, not both" if deps and block 637 638 if deps then 639 block = proc do |s| 640 # Since Hash#each is unordered in 1.8, sort 641 # the keys and iterate that way so the tests are 642 # deteriminstic on all implementations. 643 deps.keys.sort.each do |n| 644 s.add_dependency n, (deps[n] || '>= 0') 645 end 646 end 647 end 648 649 quick_spec(name, version, &block) 650 end 651 652 ## 653 # Creates a gem with +name+, +version+ and +deps+. The specification will 654 # be yielded before gem creation for customization. The gem will be placed 655 # in <tt>File.join @tempdir, 'gems'</tt>. The specification and .gem file 656 # location are returned. 657 658 def util_gem(name, version, deps = nil, &block) 659 # TODO: deprecate 660 raise "deps or block, not both" if deps and block 661 662 if deps then 663 block = proc do |s| 664 # Since Hash#each is unordered in 1.8, sort 665 # the keys and iterate that way so the tests are 666 # deterministic on all implementations. 667 deps.keys.sort.each do |n| 668 s.add_dependency n, (deps[n] || '>= 0') 669 end 670 end 671 end 672 673 spec = quick_gem(name, version, &block) 674 675 util_build_gem spec 676 677 cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem" 678 FileUtils.mkdir_p File.dirname cache_file 679 FileUtils.mv spec.cache_file, cache_file 680 FileUtils.rm spec.spec_file 681 682 spec.loaded_from = nil 683 684 [spec, cache_file] 685 end 686 687 ## 688 # Gzips +data+. 689 690 def util_gzip(data) 691 out = StringIO.new 692 693 Zlib::GzipWriter.wrap out do |io| 694 io.write data 695 end 696 697 out.string 698 end 699 700 ## 701 # Creates several default gems which all have a lib/code.rb file. The gems 702 # are not installed but are available in the cache dir. 703 # 704 # +@a1+:: gem a version 1, this is the best-described gem. 705 # +@a2+:: gem a version 2 706 # +@a3a:: gem a version 3.a 707 # +@a_evil9+:: gem a_evil version 9, use this to ensure similarly-named gems 708 # don't collide with a. 709 # +@b2+:: gem b version 2 710 # +@c1_2+:: gem c version 1.2 711 # +@pl1+:: gem pl version 1, this gem has a legacy platform of i386-linux. 712 # 713 # Additional +prerelease+ gems may also be created: 714 # 715 # +@a2_pre+:: gem a version 2.a 716 # TODO: nuke this and fix tests. this should speed up a lot 717 718 def util_make_gems(prerelease = false) 719 @a1 = quick_gem 'a', '1' do |s| 720 s.files = %w[lib/code.rb] 721 s.require_paths = %w[lib] 722 s.date = Gem::Specification::TODAY - 86400 723 s.homepage = 'http://a.example.com' 724 s.email = %w[example@example.com example2@example.com] 725 s.authors = %w[Example Example2] 726 s.description = <<-DESC 727This line is really, really long. So long, in fact, that it is more than eighty characters long! The purpose of this line is for testing wrapping behavior because sometimes people don't wrap their text to eighty characters. Without the wrapping, the text might not look good in the RSS feed. 728 729Also, a list: 730 * An entry that\'s actually kind of sort 731 * an entry that\'s really long, which will probably get wrapped funny. That's ok, somebody wasn't thinking straight when they made it more than eighty characters. 732 DESC 733 end 734 735 init = proc do |s| 736 s.files = %w[lib/code.rb] 737 s.require_paths = %w[lib] 738 end 739 740 @a2 = quick_gem('a', '2', &init) 741 @a3a = quick_gem('a', '3.a', &init) 742 @a_evil9 = quick_gem('a_evil', '9', &init) 743 @b2 = quick_gem('b', '2', &init) 744 @c1_2 = quick_gem('c', '1.2', &init) 745 @x = quick_gem('x', '1', &init) 746 @dep_x = quick_gem('dep_x', '1') do |s| 747 s.files = %w[lib/code.rb] 748 s.require_paths = %w[lib] 749 s.add_dependency 'x', '>= 1' 750 end 751 752 @pl1 = quick_gem 'pl', '1' do |s| # l for legacy 753 s.files = %w[lib/code.rb] 754 s.require_paths = %w[lib] 755 s.platform = Gem::Platform.new 'i386-linux' 756 s.instance_variable_set :@original_platform, 'i386-linux' 757 end 758 759 if prerelease 760 @a2_pre = quick_gem('a', '2.a', &init) 761 write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb]) 762 util_build_gem @a2_pre 763 end 764 765 write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) 766 write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) 767 write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) 768 write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) 769 write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) 770 write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) 771 write_file File.join(*%W[gems #{@x.original_name} lib code.rb]) 772 write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb]) 773 774 [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1, @x, @dep_x].each do |spec| 775 util_build_gem spec 776 end 777 778 FileUtils.rm_r File.join(@gemhome, "gems", @pl1.original_name) 779 end 780 781 ## 782 # Set the platform to +arch+ 783 784 def util_set_arch(arch) 785 Gem::ConfigMap[:arch] = arch 786 platform = Gem::Platform.new arch 787 788 Gem.instance_variable_set :@platforms, nil 789 Gem::Platform.instance_variable_set :@local, nil 790 791 platform 792 end 793 794 ## 795 # Sets up a fake fetcher using the gems from #util_make_gems. Optionally 796 # additional +prerelease+ gems may be included. 797 # 798 # Gems created by this method may be fetched using Gem::RemoteFetcher. 799 800 def util_setup_fake_fetcher(prerelease = false) 801 require 'zlib' 802 require 'socket' 803 require 'rubygems/remote_fetcher' 804 805 @fetcher = Gem::FakeFetcher.new 806 807 util_make_gems(prerelease) 808 Gem::Specification.reset 809 810 @all_gems = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2].sort 811 @all_gem_names = @all_gems.map { |gem| gem.full_name } 812 813 gem_names = [@a1.full_name, @a2.full_name, @a3a.full_name, @b2.full_name] 814 @gem_names = gem_names.sort.join("\n") 815 816 Gem::RemoteFetcher.fetcher = @fetcher 817 end 818 819 ## 820 # Add +spec+ to +@fetcher+ serving the data in the file +path+. 821 # +repo+ indicates which repo to make +spec+ appear to be in. 822 823 def add_to_fetcher(spec, path=nil, repo=@gem_repo) 824 path ||= spec.cache_file 825 @fetcher.data["#{@gem_repo}gems/#{spec.file_name}"] = read_binary(path) 826 end 827 828 ## 829 # Sets up Gem::SpecFetcher to return information from the gems in +specs+. 830 # Best used with +@all_gems+ from #util_setup_fake_fetcher. 831 832 def util_setup_spec_fetcher(*specs) 833 specs -= Gem::Specification._all 834 Gem::Specification.add_specs(*specs) 835 836 spec_fetcher = Gem::SpecFetcher.fetcher 837 838 prerelease, all = Gem::Specification.partition { |spec| 839 spec.version.prerelease? 840 } 841 842 spec_fetcher.specs[@uri] = [] 843 all.each do |spec| 844 spec_fetcher.specs[@uri] << spec.name_tuple 845 end 846 847 spec_fetcher.latest_specs[@uri] = [] 848 Gem::Specification.latest_specs.each do |spec| 849 spec_fetcher.latest_specs[@uri] << spec.name_tuple 850 end 851 852 spec_fetcher.prerelease_specs[@uri] = [] 853 prerelease.each do |spec| 854 spec_fetcher.prerelease_specs[@uri] << spec.name_tuple 855 end 856 857 v = Gem.marshal_version 858 859 Gem::Specification.each do |spec| 860 path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz" 861 data = Marshal.dump spec 862 data_deflate = Zlib::Deflate.deflate data 863 @fetcher.data[path] = data_deflate 864 end unless Gem::RemoteFetcher === @fetcher # HACK for test_download_to_cache 865 866 nil # force errors 867 end 868 869 ## 870 # Deflates +data+ 871 872 def util_zip(data) 873 Zlib::Deflate.deflate data 874 end 875 876 ## 877 # Is this test being run on a Windows platform? 878 879 def self.win_platform? 880 Gem.win_platform? 881 end 882 883 ## 884 # Is this test being run on a Windows platform? 885 886 def win_platform? 887 Gem.win_platform? 888 end 889 890 ## 891 # Returns whether or not we're on a version of Ruby built with VC++ (or 892 # Borland) versus Cygwin, Mingw, etc. 893 894 def self.vc_windows? 895 RUBY_PLATFORM.match('mswin') 896 end 897 898 ## 899 # Returns whether or not we're on a version of Ruby built with VC++ (or 900 # Borland) versus Cygwin, Mingw, etc. 901 902 def vc_windows? 903 RUBY_PLATFORM.match('mswin') 904 end 905 906 ## 907 # Returns the make command for the current platform. For versions of Ruby 908 # built on MS Windows with VC++ or Borland it will return 'nmake'. On all 909 # other platforms, including Cygwin, it will return 'make'. 910 911 def self.make_command 912 ENV["make"] || (vc_windows? ? 'nmake' : 'make') 913 end 914 915 ## 916 # Returns the make command for the current platform. For versions of Ruby 917 # built on MS Windows with VC++ or Borland it will return 'nmake'. On all 918 # other platforms, including Cygwin, it will return 'make'. 919 920 def make_command 921 ENV["make"] || (vc_windows? ? 'nmake' : 'make') 922 end 923 924 ## 925 # Returns whether or not the nmake command could be found. 926 927 def nmake_found? 928 system('nmake /? 1>NUL 2>&1') 929 end 930 931 # In case we're building docs in a background process, this method waits for 932 # that process to exit (or if it's already been reaped, or never happened, 933 # swallows the Errno::ECHILD error). 934 def wait_for_child_process_to_exit 935 Process.wait if Process.respond_to?(:fork) 936 rescue Errno::ECHILD 937 end 938 939 ## 940 # Allows tests to use a random (but controlled) port number instead of 941 # a hardcoded one. This helps CI tools when running parallels builds on 942 # the same builder slave. 943 944 def self.process_based_port 945 @@process_based_port ||= 8000 + $$ % 1000 946 end 947 948 ## 949 # See ::process_based_port 950 951 def process_based_port 952 self.class.process_based_port 953 end 954 955 ## 956 # Allows the proper version of +rake+ to be used for the test. 957 958 def build_rake_in(good=true) 959 gem_ruby = Gem.ruby 960 Gem.ruby = @@ruby 961 env_rake = ENV["rake"] 962 rake = (good ? @@good_rake : @@bad_rake) 963 ENV["rake"] = rake 964 yield rake 965 ensure 966 Gem.ruby = gem_ruby 967 if env_rake 968 ENV["rake"] = env_rake 969 else 970 ENV.delete("rake") 971 end 972 end 973 974 ## 975 # Finds the path to the ruby executable 976 977 def self.rubybin 978 ruby = ENV["RUBY"] 979 return ruby if ruby 980 ruby = "ruby" 981 rubyexe = "#{ruby}.exe" 982 983 3.times do 984 if File.exist? ruby and File.executable? ruby and !File.directory? ruby 985 return File.expand_path(ruby) 986 end 987 if File.exist? rubyexe and File.executable? rubyexe 988 return File.expand_path(rubyexe) 989 end 990 ruby = File.join("..", ruby) 991 end 992 993 begin 994 require "rbconfig" 995 File.join(RbConfig::CONFIG["bindir"], 996 RbConfig::CONFIG["ruby_install_name"] + 997 RbConfig::CONFIG["EXEEXT"]) 998 rescue LoadError 999 "ruby" 1000 end 1001 end 1002 1003 @@ruby = rubybin 1004 @@good_rake = "#{rubybin} #{File.expand_path('../../../test/rubygems/good_rake.rb', __FILE__)}" 1005 @@bad_rake = "#{rubybin} #{File.expand_path('../../../test/rubygems/bad_rake.rb', __FILE__)}" 1006 1007 ## 1008 # Construct a new Gem::Dependency. 1009 1010 def dep name, *requirements 1011 Gem::Dependency.new name, *requirements 1012 end 1013 1014 ## 1015 # Constructs a new Gem::Requirement. 1016 1017 def req *requirements 1018 return requirements.first if Gem::Requirement === requirements.first 1019 Gem::Requirement.create requirements 1020 end 1021 1022 ## 1023 # Constructs a new Gem::Specification. 1024 1025 def spec name, version, &block 1026 Gem::Specification.new name, v(version), &block 1027 end 1028 1029 ## 1030 # Construct a new Gem::Version. 1031 1032 def v string 1033 Gem::Version.create string 1034 end 1035 1036 class StaticSet 1037 def initialize(specs) 1038 @specs = specs.sort_by { |s| s.full_name } 1039 end 1040 1041 def find_spec(dep) 1042 @specs.reverse_each do |s| 1043 return s if dep.matches_spec? s 1044 end 1045 end 1046 1047 def find_all(dep) 1048 @specs.find_all { |s| dep.matches_spec? s } 1049 end 1050 1051 def prefetch(reqs) 1052 end 1053 end 1054 1055 ## 1056 # Loads certificate named +cert_name+ from <tt>test/rubygems/</tt>. 1057 1058 def self.load_cert cert_name 1059 cert_file = cert_path cert_name 1060 1061 cert = File.read cert_file 1062 1063 OpenSSL::X509::Certificate.new cert 1064 end 1065 1066 ## 1067 # Returns the path to the certificate named +cert_name+ from 1068 # <tt>test/rubygems/</tt>. 1069 1070 def self.cert_path cert_name 1071 if 32 == (Time.at(2**32) rescue 32) then 1072 cert_file = 1073 File.expand_path "../../../test/rubygems/#{cert_name}_cert_32.pem", 1074 __FILE__ 1075 1076 return cert_file if File.exist? cert_file 1077 end 1078 1079 File.expand_path "../../../test/rubygems/#{cert_name}_cert.pem", __FILE__ 1080 end 1081 1082 ## 1083 # Loads an RSA private key named +key_name+ in <tt>test/rubygems/</tt> 1084 1085 def self.load_key key_name 1086 key_file = key_path key_name 1087 1088 key = File.read key_file 1089 1090 OpenSSL::PKey::RSA.new key 1091 end 1092 1093 ## 1094 # Returns the path tot he key named +key_name+ from <tt>test/rubygems</tt> 1095 1096 def self.key_path key_name 1097 File.expand_path "../../../test/rubygems/#{key_name}_key.pem", __FILE__ 1098 end 1099 1100 # :stopdoc: 1101 # only available in RubyGems tests 1102 1103 begin 1104 PRIVATE_KEY = load_key 'private' 1105 PRIVATE_KEY_PATH = key_path 'private' 1106 PUBLIC_KEY = PRIVATE_KEY.public_key 1107 1108 PUBLIC_CERT = load_cert 'public' 1109 PUBLIC_CERT_PATH = cert_path 'public' 1110 rescue Errno::ENOENT 1111 PRIVATE_KEY = nil 1112 PUBLIC_KEY = nil 1113 PUBLIC_CERT = nil 1114 end 1115 1116end 1117