Class | Gem::TestCase |
In: |
lib/rubygems/test_case.rb
|
Parent: | MiniTest::Unit::TestCase |
RubyGemTestCase provides a variety of methods for testing rubygems and gem-related behavior in a sandbox. Through RubyGemTestCase you can install and uninstall gems, fetch remote gems through a stub fetcher and be assured your normal set of gems is not affected.
Tests are always run at a safe level of 1.
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’.
# File lib/rubygems/test_case.rb, line 760 760: def self.make_command 761: ENV["make"] || (vc_windows? ? 'nmake' : 'make') 762: 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.
# File lib/rubygems/test_case.rb, line 785 785: def self.process_based_port 786: @@process_based_port ||= 8000 + $$ % 1000 787: end
Finds the path to the ruby executable
# File lib/rubygems/test_case.rb, line 817 817: def self.rubybin 818: ruby = ENV["RUBY"] 819: return ruby if ruby 820: ruby = "ruby" 821: rubyexe = "#{ruby}.exe" 822: 823: 3.times do 824: if File.exist? ruby and File.executable? ruby and !File.directory? ruby 825: return File.expand_path(ruby) 826: end 827: if File.exist? rubyexe and File.executable? rubyexe 828: return File.expand_path(rubyexe) 829: end 830: ruby = File.join("..", ruby) 831: end 832: 833: begin 834: require "rbconfig" 835: File.join(RbConfig::CONFIG["bindir"], 836: RbConfig::CONFIG["ruby_install_name"] + 837: RbConfig::CONFIG["EXEEXT"]) 838: rescue LoadError 839: "ruby" 840: end 841: end
Returns whether or not we‘re on a version of Ruby built with VC++ (or Borland) versus Cygwin, Mingw, etc.
# File lib/rubygems/test_case.rb, line 743 743: def self.vc_windows? 744: RUBY_PLATFORM.match('mswin') 745: end
Is this test being run on a Windows platform?
# File lib/rubygems/test_case.rb, line 728 728: def self.win_platform? 729: Gem.win_platform? 730: end
# File lib/rubygems/test_case.rb, line 340 340: def all_spec_names 341: Gem::Specification.map(&:full_name) 342: end
TODO: move to minitest
# File lib/rubygems/test_case.rb, line 84 84: def assert_path_exists path, msg = nil 85: msg = message(msg) { "Expected path '#{path}' to exist" } 86: assert File.exist?(path), msg 87: end
Allows the proper version of rake to be used for the test.
# File lib/rubygems/test_case.rb, line 799 799: def build_rake_in 800: gem_ruby = Gem.ruby 801: Gem.ruby = @@ruby 802: env_rake = ENV["rake"] 803: ENV["rake"] = @@rake 804: yield @@rake 805: ensure 806: Gem.ruby = gem_ruby 807: if env_rake 808: ENV["rake"] = env_rake 809: else 810: ENV.delete("rake") 811: end 812: end
creates a temporary directory with hax
# File lib/rubygems/test_case.rb, line 291 291: def create_tmpdir 292: tmpdir = nil 293: Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end # HACK OSX /private/tmp 294: tmpdir = File.join tmpdir, "test_rubygems_#{$$}" 295: FileUtils.mkdir_p tmpdir 296: return tmpdir 297: end
Construct a new Gem::Dependency.
# File lib/rubygems/test_case.rb, line 857 857: def dep name, *requirements 858: Gem::Dependency.new name, *requirements 859: end
Builds and installs the Gem::Specification spec
# File lib/rubygems/test_case.rb, line 246 246: def install_gem spec 247: require 'rubygems/installer' 248: 249: use_ui Gem::MockGemUi.new do 250: Dir.chdir @tempdir do 251: Gem::Builder.new(spec).build 252: end 253: end 254: 255: gem = File.join(@tempdir, File.basename(spec.cache_file)).untaint 256: 257: Gem::Installer.new(gem, :wrappers => true).install 258: end
Builds and installs the Gem::Specification spec into the user dir
# File lib/rubygems/test_case.rb, line 263 263: def install_gem_user spec 264: require 'rubygems/installer' 265: 266: use_ui Gem::MockGemUi.new do 267: Dir.chdir @tempdir do 268: Gem::Builder.new(spec).build 269: end 270: end 271: 272: gem = File.join(@tempdir, File.basename(spec.cache_file)).untaint 273: 274: i = Gem::Installer.new(gem, :wrappers => true, :user_install => true) 275: i.install 276: i.spec 277: end
Install the provided specs
# File lib/rubygems/test_case.rb, line 444 444: def install_specs(*specs) 445: Gem::Specification.add_specs(*specs) 446: Gem.searcher = nil 447: 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’.
# File lib/rubygems/test_case.rb, line 769 769: def make_command 770: ENV["make"] || (vc_windows? ? 'nmake' : 'make') 771: end
Enables pretty-print for all tests
# File lib/rubygems/test_case.rb, line 302 302: def mu_pp(obj) 303: s = '' 304: s = PP.pp obj, s 305: s = s.force_encoding(Encoding.default_external) if defined? Encoding 306: s.chomp 307: end
Create a new spec (or gem if passed an array of files) and set it up properly. Use this instead of util_spec and util_gem.
# File lib/rubygems/test_case.rb, line 453 453: def new_spec name, version, deps = nil, *files 454: require 'rubygems/specification' 455: 456: spec = Gem::Specification.new do |s| 457: s.platform = Gem::Platform::RUBY 458: s.name = name 459: s.version = version 460: s.author = 'A User' 461: s.email = 'example@example.com' 462: s.homepage = 'http://example.com' 463: s.summary = "this is a summary" 464: s.description = "This is a test description" 465: 466: Array(deps).each do |n, req| 467: s.add_dependency n, (req || '>= 0') 468: end 469: 470: s.files.push(*files) unless files.empty? 471: 472: yield s if block_given? 473: end 474: 475: spec.loaded_from = spec.spec_file 476: 477: unless files.empty? then 478: write_file spec.spec_file do |io| 479: io.write spec.to_ruby_for_cache 480: end 481: 482: util_build_gem spec 483: 484: cache_file = File.join @tempdir, 'gems', "#{spec.full_name}.gem" 485: FileUtils.mkdir_p File.dirname cache_file 486: FileUtils.mv spec.cache_file, cache_file 487: FileUtils.rm spec.spec_file 488: end 489: 490: spec 491: end
Returns whether or not the nmake command could be found.
# File lib/rubygems/test_case.rb, line 776 776: def nmake_found? 777: system('nmake /? 1>NUL 2>&1') 778: end
See ::process_based_port
# File lib/rubygems/test_case.rb, line 792 792: def process_based_port 793: self.class.process_based_port 794: end
Creates a Gem::Specification with a minimum of extra work. name and version are the gem‘s name and version, platform, author, email, homepage, summary and description are defaulted. The specification is yielded for customization.
The gem is added to the installed gems in +@gemhome+ and to the current source_index.
Use this with write_file to build an installed gem.
# File lib/rubygems/test_case.rb, line 355 355: def quick_gem(name, version='2') 356: require 'rubygems/specification' 357: 358: spec = Gem::Specification.new do |s| 359: s.platform = Gem::Platform::RUBY 360: s.name = name 361: s.version = version 362: s.author = 'A User' 363: s.email = 'example@example.com' 364: s.homepage = 'http://example.com' 365: s.summary = "this is a summary" 366: s.description = "This is a test description" 367: 368: yield(s) if block_given? 369: end 370: 371: Gem::Specification.map # HACK: force specs to (re-)load before we write 372: 373: written_path = write_file spec.spec_file do |io| 374: io.write spec.to_ruby_for_cache 375: end 376: 377: spec.loaded_from = spec.loaded_from = written_path 378: 379: Gem::Specification.add_spec spec.for_cache 380: 381: return spec 382: end
# File lib/rubygems/test_case.rb, line 384 384: def quick_spec name, version = '2' 385: # TODO: deprecate 386: require 'rubygems/specification' 387: 388: spec = Gem::Specification.new do |s| 389: s.platform = Gem::Platform::RUBY 390: s.name = name 391: s.version = version 392: s.author = 'A User' 393: s.email = 'example@example.com' 394: s.homepage = 'http://example.com' 395: s.summary = "this is a summary" 396: s.description = "This is a test description" 397: 398: yield(s) if block_given? 399: end 400: 401: spec.loaded_from = spec.spec_file 402: 403: Gem::Specification.add_spec spec 404: 405: return spec 406: end
Reads a binary file at path
# File lib/rubygems/test_case.rb, line 321 321: def read_binary(path) 322: Gem.read_binary path 323: end
Reads a Marshal file at path
# File lib/rubygems/test_case.rb, line 312 312: def read_cache(path) 313: open path.dup.untaint, 'rb' do |io| 314: Marshal.load io.read 315: end 316: end
TODO: move to minitest
# File lib/rubygems/test_case.rb, line 90 90: def refute_path_exists path, msg = nil 91: msg = message(msg) { "Expected path '#{path}' to not exist" } 92: refute File.exist?(path), msg 93: end
Constructs a new Gem::Requirement.
# File lib/rubygems/test_case.rb, line 864 864: def req *requirements 865: return requirements.first if Gem::Requirement === requirements.first 866: Gem::Requirement.create requirements 867: end
setup prepares a sandboxed location to install gems. All installs are directed to a temporary directory. All install plugins are removed.
If the RUBY environment variable is set the given path is used for Gem::ruby. The local platform is set to i386-mswin32 for Windows or i686-darwin8.10.1 otherwise.
If the KEEP_FILES environment variable is set the files will not be removed from /tmp/test_rubygems_#{$$}.#{Time.now.to_i}.
# File lib/rubygems/test_case.rb, line 113 113: def setup 114: super 115: 116: @orig_gem_home = ENV['GEM_HOME'] 117: @orig_gem_path = ENV['GEM_PATH'] 118: 119: @current_dir = Dir.pwd 120: @ui = Gem::MockGemUi.new 121: 122: tmpdir = nil 123: Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end # HACK OSX /private/tmp 124: 125: if ENV['KEEP_FILES'] then 126: @tempdir = File.join(tmpdir, "test_rubygems_#{$$}.#{Time.now.to_i}") 127: else 128: @tempdir = File.join(tmpdir, "test_rubygems_#{$$}") 129: end 130: @tempdir.untaint 131: @gemhome = File.join @tempdir, 'gemhome' 132: @userhome = File.join @tempdir, 'userhome' 133: 134: @orig_ruby = if ruby = ENV['RUBY'] then 135: Gem.class_eval { ruby, @ruby = @ruby, ruby } 136: ruby 137: end 138: 139: Gem.ensure_gem_subdirectories @gemhome 140: 141: @orig_LOAD_PATH = $LOAD_PATH.dup 142: $LOAD_PATH.map! { |s| File.expand_path s } 143: 144: Dir.chdir @tempdir 145: 146: @orig_ENV_HOME = ENV['HOME'] 147: ENV['HOME'] = @userhome 148: Gem.instance_variable_set :@user_home, nil 149: 150: FileUtils.mkdir_p @gemhome 151: FileUtils.mkdir_p @userhome 152: 153: Gem.use_paths(@gemhome) 154: 155: Gem.loaded_specs.clear 156: Gem.unresolved_deps.clear 157: 158: Gem.configuration.verbose = true 159: Gem.configuration.update_sources = true 160: 161: @gem_repo = "http://gems.example.com/" 162: @uri = URI.parse @gem_repo 163: Gem.sources.replace [@gem_repo] 164: 165: Gem.searcher = nil 166: Gem::SpecFetcher.fetcher = nil 167: 168: @orig_BASERUBY = Gem::ConfigMap[:BASERUBY] 169: Gem::ConfigMap[:BASERUBY] = Gem::ConfigMap[:ruby_install_name] 170: 171: @orig_arch = Gem::ConfigMap[:arch] 172: 173: if win_platform? 174: util_set_arch 'i386-mswin32' 175: else 176: util_set_arch 'i686-darwin8.10.1' 177: end 178: 179: @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" 180: 181: # TODO: move to installer test cases 182: Gem.post_build_hooks.clear 183: Gem.post_install_hooks.clear 184: Gem.post_uninstall_hooks.clear 185: Gem.pre_install_hooks.clear 186: Gem.pre_uninstall_hooks.clear 187: 188: # TODO: move to installer test cases 189: Gem.post_build do |installer| 190: @post_build_hook_arg = installer 191: true 192: end 193: 194: Gem.post_install do |installer| 195: @post_install_hook_arg = installer 196: end 197: 198: Gem.post_uninstall do |uninstaller| 199: @post_uninstall_hook_arg = uninstaller 200: end 201: 202: Gem.pre_install do |installer| 203: @pre_install_hook_arg = installer 204: true 205: end 206: 207: Gem.pre_uninstall do |uninstaller| 208: @pre_uninstall_hook_arg = uninstaller 209: end 210: end
Constructs a new Gem::Specification.
# File lib/rubygems/test_case.rb, line 872 872: def spec name, version, &block 873: Gem::Specification.new name, v(version), &block 874: end
teardown restores the process to its original state and removes the tempdir unless the KEEP_FILES environment variable was set.
# File lib/rubygems/test_case.rb, line 216 216: def teardown 217: $LOAD_PATH.replace @orig_LOAD_PATH 218: 219: Gem::ConfigMap[:BASERUBY] = @orig_BASERUBY 220: Gem::ConfigMap[:arch] = @orig_arch 221: 222: if defined? Gem::RemoteFetcher then 223: Gem::RemoteFetcher.fetcher = nil 224: end 225: 226: Dir.chdir @current_dir 227: 228: FileUtils.rm_rf @tempdir unless ENV['KEEP_FILES'] 229: 230: ENV['GEM_HOME'] = @orig_gem_home 231: ENV['GEM_PATH'] = @orig_gem_path 232: 233: _ = @orig_ruby 234: Gem.class_eval { @ruby = _ } if _ 235: 236: if @orig_ENV_HOME then 237: ENV['HOME'] = @orig_ENV_HOME 238: else 239: ENV.delete 'HOME' 240: end 241: end
Uninstalls the Gem::Specification spec
# File lib/rubygems/test_case.rb, line 281 281: def uninstall_gem spec 282: require 'rubygems/uninstaller' 283: 284: Gem::Uninstaller.new(spec.name, 285: :executables => true, :user_install => true).uninstall 286: end
Builds a gem from spec and places it in File.join @gemhome, ‘cache‘. Automatically creates files based on +spec.files+
# File lib/rubygems/test_case.rb, line 412 412: def util_build_gem(spec) 413: dir = spec.gem_dir 414: FileUtils.mkdir_p dir 415: 416: Dir.chdir dir do 417: spec.files.each do |file| 418: next if File.exist? file 419: FileUtils.mkdir_p File.dirname(file) 420: File.open file, 'w' do |fp| fp.puts "# #{file}" end 421: end 422: 423: use_ui Gem::MockGemUi.new do 424: Gem::Builder.new(spec).build 425: end 426: 427: cache = spec.cache_file 428: FileUtils.mv File.basename(cache), cache 429: end 430: end
Removes all installed gems from +@gemhome+.
# File lib/rubygems/test_case.rb, line 435 435: def util_clear_gems 436: FileUtils.rm_rf File.join(@gemhome, "gems") # TODO: use Gem::Dirs 437: FileUtils.rm_rf File.join(@gemhome, "specifications") 438: Gem::Specification.reset 439: end
Creates a gem with name, version and deps. The specification will be yielded before gem creation for customization. The gem will be placed in File.join @tempdir, ‘gems‘. The specification and .gem file location are returned.
# File lib/rubygems/test_case.rb, line 520 520: def util_gem(name, version, deps = nil, &block) 521: # TODO: deprecate 522: raise "deps or block, not both" if deps and block 523: 524: if deps then 525: block = proc do |s| 526: # Since Hash#each is unordered in 1.8, sort 527: # the keys and iterate that way so the tests are 528: # deteriminstic on all implementations. 529: deps.keys.sort.each do |n| 530: s.add_dependency n, (deps[n] || '>= 0') 531: end 532: end 533: end 534: 535: spec = quick_gem(name, version, &block) 536: 537: util_build_gem spec 538: 539: cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem" 540: FileUtils.mkdir_p File.dirname cache_file 541: FileUtils.mv spec.cache_file, cache_file 542: FileUtils.rm spec.spec_file 543: 544: spec.loaded_from = nil 545: 546: [spec, cache_file] 547: end
Gzips data.
# File lib/rubygems/test_case.rb, line 552 552: def util_gzip(data) 553: out = StringIO.new 554: 555: Zlib::GzipWriter.wrap out do |io| 556: io.write data 557: end 558: 559: out.string 560: end
Creates several default gems which all have a lib/code.rb file. The gems are not installed but are available in the cache dir.
+@a1+: | gem a version 1, this is the best-described gem. |
+@a2+: | gem a version 2 |
+@a3a: | gem a version 3.a |
+@a_evil9+: | gem a_evil version 9, use this to ensure similarly-named gems don‘t collide with a. |
+@b2+: | gem b version 2 |
+@c1_2+: | gem c version 1.2 |
+@pl1+: | gem pl version 1, this gem has a legacy platform of i386-linux. |
Additional prerelease gems may also be created:
+@a2_pre+: | gem a version 2.a |
TODO: nuke this and fix tests. this should speed up a lot
# File lib/rubygems/test_case.rb, line 580 580: def util_make_gems(prerelease = false) 581: @a1 = quick_gem 'a', '1' do |s| 582: s.files = %w[lib/code.rb] 583: s.require_paths = %w[lib] 584: s.date = Gem::Specification::TODAY - 86400 585: s.homepage = 'http://a.example.com' 586: s.email = %w[example@example.com example2@example.com] 587: s.authors = %w[Example Example2] 588: s.description = "This 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.\n\nAlso, a list:\n* An entry that\\'s actually kind of sort\n* 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.\n" 589: end 590: 591: init = proc do |s| 592: s.files = %w[lib/code.rb] 593: s.require_paths = %w[lib] 594: end 595: 596: @a2 = quick_gem('a', '2', &init) 597: @a3a = quick_gem('a', '3.a', &init) 598: @a_evil9 = quick_gem('a_evil', '9', &init) 599: @b2 = quick_gem('b', '2', &init) 600: @c1_2 = quick_gem('c', '1.2', &init) 601: 602: @pl1 = quick_gem 'pl', '1' do |s| # l for legacy 603: s.files = %w[lib/code.rb] 604: s.require_paths = %w[lib] 605: s.platform = Gem::Platform.new 'i386-linux' 606: s.instance_variable_set :@original_platform, 'i386-linux' 607: end 608: 609: if prerelease 610: @a2_pre = quick_gem('a', '2.a', &init) 611: write_file File.join(*??[gems #{@a2_pre.original_name} lib code.rb]) 612: util_build_gem @a2_pre 613: end 614: 615: write_file File.join(*??[gems #{@a1.original_name} lib code.rb]) 616: write_file File.join(*??[gems #{@a2.original_name} lib code.rb]) 617: write_file File.join(*??[gems #{@a3a.original_name} lib code.rb]) 618: write_file File.join(*??[gems #{@b2.original_name} lib code.rb]) 619: write_file File.join(*??[gems #{@c1_2.original_name} lib code.rb]) 620: write_file File.join(*??[gems #{@pl1.original_name} lib code.rb]) 621: 622: [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1].each do |spec| 623: util_build_gem spec 624: end 625: 626: FileUtils.rm_r File.join(@gemhome, "gems", @pl1.original_name) 627: end
Set the platform to arch
# File lib/rubygems/test_case.rb, line 639 639: def util_set_arch(arch) 640: Gem::ConfigMap[:arch] = arch 641: platform = Gem::Platform.new arch 642: 643: Gem.instance_variable_set :@platforms, nil 644: Gem::Platform.instance_variable_set :@local, nil 645: 646: platform 647: end
Sets up a fake fetcher using the gems from util_make_gems. Optionally additional prerelease gems may be included.
Gems created by this method may be fetched using Gem::RemoteFetcher.
# File lib/rubygems/test_case.rb, line 655 655: def util_setup_fake_fetcher(prerelease = false) 656: require 'zlib' 657: require 'socket' 658: require 'rubygems/remote_fetcher' 659: 660: @fetcher = Gem::FakeFetcher.new 661: 662: util_make_gems(prerelease) 663: Gem::Specification.reset 664: 665: @all_gems = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2].sort 666: @all_gem_names = @all_gems.map { |gem| gem.full_name } 667: 668: gem_names = [@a1.full_name, @a2.full_name, @a3a.full_name, @b2.full_name] 669: @gem_names = gem_names.sort.join("\n") 670: 671: Gem::RemoteFetcher.fetcher = @fetcher 672: end
Sets up Gem::SpecFetcher to return information from the gems in specs. Best used with +@all_gems+ from util_setup_fake_fetcher.
# File lib/rubygems/test_case.rb, line 678 678: def util_setup_spec_fetcher(*specs) 679: specs -= Gem::Specification._all 680: Gem::Specification.add_specs(*specs) 681: 682: spec_fetcher = Gem::SpecFetcher.fetcher 683: 684: prerelease, _ = Gem::Specification.partition { |spec| 685: spec.version.prerelease? 686: } 687: 688: spec_fetcher.specs[@uri] = [] 689: Gem::Specification.each do |spec| 690: spec_tuple = [spec.name, spec.version, spec.original_platform] 691: spec_fetcher.specs[@uri] << spec_tuple 692: end 693: 694: spec_fetcher.latest_specs[@uri] = [] 695: Gem::Specification.latest_specs.each do |spec| 696: spec_tuple = [spec.name, spec.version, spec.original_platform] 697: spec_fetcher.latest_specs[@uri] << spec_tuple 698: end 699: 700: spec_fetcher.prerelease_specs[@uri] = [] 701: prerelease.each do |spec| 702: spec_tuple = [spec.name, spec.version, spec.original_platform] 703: spec_fetcher.prerelease_specs[@uri] << spec_tuple 704: end 705: 706: v = Gem.marshal_version 707: 708: Gem::Specification.each do |spec| 709: path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz" 710: data = Marshal.dump spec 711: data_deflate = Zlib::Deflate.deflate data 712: @fetcher.data[path] = data_deflate 713: end unless Gem::RemoteFetcher === @fetcher # HACK for test_download_to_cache 714: 715: nil # force errors 716: end
Creates a spec with name, version and deps.
# File lib/rubygems/test_case.rb, line 496 496: def util_spec(name, version, deps = nil, &block) 497: # TODO: deprecate 498: raise "deps or block, not both" if deps and block 499: 500: if deps then 501: block = proc do |s| 502: # Since Hash#each is unordered in 1.8, sort 503: # the keys and iterate that way so the tests are 504: # deteriminstic on all implementations. 505: deps.keys.sort.each do |n| 506: s.add_dependency n, (deps[n] || '>= 0') 507: end 508: end 509: end 510: 511: quick_spec(name, version, &block) 512: end
Deflates data
# File lib/rubygems/test_case.rb, line 721 721: def util_zip(data) 722: Zlib::Deflate.deflate data 723: end
Construct a new Gem::Version.
# File lib/rubygems/test_case.rb, line 879 879: def v string 880: Gem::Version.create string 881: end
Returns whether or not we‘re on a version of Ruby built with VC++ (or Borland) versus Cygwin, Mingw, etc.
# File lib/rubygems/test_case.rb, line 751 751: def vc_windows? 752: RUBY_PLATFORM.match('mswin') 753: end
Is this test being run on a Windows platform?
# File lib/rubygems/test_case.rb, line 735 735: def win_platform? 736: Gem.win_platform? 737: end
Writes a binary file to path which is relative to +@gemhome+
# File lib/rubygems/test_case.rb, line 328 328: def write_file(path) 329: path = File.join @gemhome, path unless Pathname.new(path).absolute? 330: dir = File.dirname path 331: FileUtils.mkdir_p dir 332: 333: open path, 'wb' do |io| 334: yield io if block_given? 335: end 336: 337: path 338: end