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 753
753: def self.make_command
754: ENV["make"] || (vc_windows? ? 'nmake' : 'make')
755: 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 778
778: def self.process_based_port
779: @@process_based_port ||= 8000 + $$ % 1000
780: end
Finds the path to the ruby executable
# File lib/rubygems/test_case.rb, line 810
810: def self.rubybin
811: ruby = ENV["RUBY"]
812: return ruby if ruby
813: ruby = "ruby"
814: rubyexe = "#{ruby}.exe"
815:
816: 3.times do
817: if File.exist? ruby and File.executable? ruby and !File.directory? ruby
818: return File.expand_path(ruby)
819: end
820: if File.exist? rubyexe and File.executable? rubyexe
821: return File.expand_path(rubyexe)
822: end
823: ruby = File.join("..", ruby)
824: end
825:
826: begin
827: require "rbconfig"
828: File.join(RbConfig::CONFIG["bindir"],
829: RbConfig::CONFIG["ruby_install_name"] +
830: RbConfig::CONFIG["EXEEXT"])
831: rescue LoadError
832: "ruby"
833: end
834: 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 792
792: def build_rake_in
793: gem_ruby = Gem.ruby
794: Gem.ruby = @@ruby
795: env_rake = ENV["rake"]
796: ENV["rake"] = @@rake
797: yield @@rake
798: ensure
799: Gem.ruby = gem_ruby
800: if env_rake
801: ENV["rake"] = env_rake
802: else
803: ENV.delete("rake")
804: end
805: 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 850
850: def dep name, *requirements
851: Gem::Dependency.new name, *requirements
852: 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 762
762: def make_command
763: ENV["make"] || (vc_windows? ? 'nmake' : 'make')
764: 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 769
769: def nmake_found?
770: system('nmake /? 1>NUL 2>&1')
771: end
# File lib/rubygems/test_case.rb, line 785
785: def process_based_port
786: self.class.process_based_port
787: 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 # 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 857
857: def req *requirements
858: return requirements.first if Gem::Requirement === requirements.first
859: Gem::Requirement.create requirements
860: end
# 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 865
865: def spec name, version, &block
866: Gem::Specification.new name, v(version), &block
867: end
# 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 517
517: def util_gem(name, version, deps = nil, &block)
518: # TODO: deprecate
519: raise "deps or block, not both" if deps and block
520:
521: if deps then
522: block = proc do |s|
523: deps.each do |n, req|
524: s.add_dependency n, (req || '>= 0')
525: end
526: end
527: end
528:
529: spec = quick_gem(name, version, &block)
530:
531: util_build_gem spec
532:
533: cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
534: FileUtils.mkdir_p File.dirname cache_file
535: FileUtils.mv spec.cache_file, cache_file
536: FileUtils.rm spec.spec_file
537:
538: spec.loaded_from = nil
539:
540: [spec, cache_file]
541: end
Gzips data.
# File lib/rubygems/test_case.rb, line 546
546: def util_gzip(data)
547: out = StringIO.new
548:
549: Zlib::GzipWriter.wrap out do |io|
550: io.write data
551: end
552:
553: out.string
554: 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 574
574: def util_make_gems(prerelease = false)
575: @a1 = quick_gem 'a', '1' do |s|
576: s.files = ]lib/code.rb]
577: s.require_paths = ]lib]
578: s.date = Gem::Specification::TODAY - 86400
579: s.homepage = 'http://a.example.com'
580: s.email = ]example@example.com example2@example.com]
581: s.authors = ]Example Example2]
582: 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.Also, a list: * An entry that\'s actually kind of sort * 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.
583: end
584:
585: init = proc do |s|
586: s.files = ]lib/code.rb]
587: s.require_paths = ]lib]
588: end
589:
590: @a2 = quick_gem('a', '2', &init)
591: @a3a = quick_gem('a', '3.a', &init)
592: @a_evil9 = quick_gem('a_evil', '9', &init)
593: @b2 = quick_gem('b', '2', &init)
594: @c1_2 = quick_gem('c', '1.2', &init)
595:
596: @pl1 = quick_gem 'pl', '1' do |s| # l for legacy
597: s.files = ]lib/code.rb]
598: s.require_paths = ]lib]
599: s.platform = Gem::Platform.new 'i386-linux'
600: s.instance_variable_set :@original_platform, 'i386-linux'
601: end
602:
603: if prerelease
604: @a2_pre = quick_gem('a', '2.a', &init)
605: write_file File.join(*]gems #{@a2_pre.original_name} lib code.rb])
606: util_build_gem @a2_pre
607: end
608:
609: write_file File.join(*]gems #{@a1.original_name} lib code.rb])
610: write_file File.join(*]gems #{@a2.original_name} lib code.rb])
611: write_file File.join(*]gems #{@a3a.original_name} lib code.rb])
612: write_file File.join(*]gems #{@b2.original_name} lib code.rb])
613: write_file File.join(*]gems #{@c1_2.original_name} lib code.rb])
614: write_file File.join(*]gems #{@pl1.original_name} lib code.rb])
615:
616: [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1].each do |spec|
617: util_build_gem spec
618: end
619:
620: FileUtils.rm_r File.join(@gemhome, "gems", @pl1.original_name)
621: end
Set the platform to arch
# File lib/rubygems/test_case.rb, line 632
632: def util_set_arch(arch)
633: Gem::ConfigMap[:arch] = arch
634: platform = Gem::Platform.new arch
635:
636: Gem.instance_variable_set :@platforms, nil
637: Gem::Platform.instance_variable_set :@local, nil
638:
639: platform
640: end
Sets up a fake fetcher using the gems from #. 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 648
648: def util_setup_fake_fetcher(prerelease = false)
649: require 'zlib'
650: require 'socket'
651: require 'rubygems/remote_fetcher'
652:
653: @fetcher = Gem::FakeFetcher.new
654:
655: util_make_gems(prerelease)
656: Gem::Specification.reset
657:
658: @all_gems = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2].sort
659: @all_gem_names = @all_gems.map { |gem| gem.full_name }
660:
661: gem_names = [@a1.full_name, @a2.full_name, @a3a.full_name, @b2.full_name]
662: @gem_names = gem_names.sort.join("\n")
663:
664: Gem::RemoteFetcher.fetcher = @fetcher
665: end
Sets up Gem::SpecFetcher to return information from the gems in specs. Best used with +@all_gems+ from #.
# File lib/rubygems/test_case.rb, line 671
671: def util_setup_spec_fetcher(*specs)
672: specs -= Gem::Specification._all
673: Gem::Specification.add_specs(*specs)
674:
675: spec_fetcher = Gem::SpecFetcher.fetcher
676:
677: prerelease, _ = Gem::Specification.partition { |spec|
678: spec.version.prerelease?
679: }
680:
681: spec_fetcher.specs[@uri] = []
682: Gem::Specification.each do |spec|
683: spec_tuple = [spec.name, spec.version, spec.original_platform]
684: spec_fetcher.specs[@uri] << spec_tuple
685: end
686:
687: spec_fetcher.latest_specs[@uri] = []
688: Gem::Specification.latest_specs.each do |spec|
689: spec_tuple = [spec.name, spec.version, spec.original_platform]
690: spec_fetcher.latest_specs[@uri] << spec_tuple
691: end
692:
693: spec_fetcher.prerelease_specs[@uri] = []
694: prerelease.each do |spec|
695: spec_tuple = [spec.name, spec.version, spec.original_platform]
696: spec_fetcher.prerelease_specs[@uri] << spec_tuple
697: end
698:
699: v = Gem.marshal_version
700:
701: Gem::Specification.each do |spec|
702: path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz"
703: data = Marshal.dump spec
704: data_deflate = Zlib::Deflate.deflate data
705: @fetcher.data[path] = data_deflate
706: end unless Gem::RemoteFetcher === @fetcher # HACK for test_download_to_cache
707:
708: nil # force errors
709: 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: deps.each do |n, req|
503: s.add_dependency n, (req || '>= 0')
504: end
505: end
506: end
507:
508: quick_spec(name, version, &block)
509: end
Deflates data
# File lib/rubygems/test_case.rb, line 714
714: def util_zip(data)
715: Zlib::Deflate.deflate data
716: end
Construct a new Gem::Version.
# File lib/rubygems/test_case.rb, line 872
872: def v string
873: Gem::Version.create string
874: 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 744
744: def vc_windows?
745: RUBY_PLATFORM.match('mswin')
746: end
Is this test being run on a Windows platform?
# File lib/rubygems/test_case.rb, line 728
728: def win_platform?
729: Gem.win_platform?
730: 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
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.