3 # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
5 # See LICENSE.txt for permissions.
14 require 'rubygems/package'
15 require 'rubygems/test_utilities'
17 require File.join(File.expand_path(File.dirname(__FILE__)), 'mockgemui')
20 def self.source_index=(si)
24 def self.win_platform=(val)
29 class RubyGemTestCase < Test::Unit::TestCase
31 include Gem::DefaultUserInteraction
33 undef_method :default_test if instance_methods.include? 'default_test' or
34 instance_methods.include? :default_test
41 Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end # HACK OSX /private/tmp
42 @tempdir = File.join tmpdir, "test_rubygems_#{$$}"
44 @gemhome = File.join @tempdir, "gemhome"
45 @gemcache = File.join(@gemhome, "source_cache")
46 @usrcache = File.join(@gemhome, ".gem", "user_cache")
47 @latest_usrcache = File.join(@gemhome, ".gem", "latest_user_cache")
48 @userhome = File.join @tempdir, 'userhome'
50 ENV['HOME'] = @userhome
51 Gem.instance_variable_set :@user_home, nil
53 FileUtils.mkdir_p @gemhome
54 FileUtils.mkdir_p @userhome
56 ENV['GEMCACHE'] = @usrcache
57 Gem.use_paths(@gemhome)
58 Gem.loaded_specs.clear
60 Gem.configuration.verbose = true
61 Gem.configuration.update_sources = true
63 @gem_repo = "http://gems.example.com/"
64 @uri = URI.parse @gem_repo
65 Gem.sources.replace [@gem_repo]
67 Gem::SpecFetcher.fetcher = nil
69 @orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
70 Gem::ConfigMap[:BASERUBY] = Gem::ConfigMap[:RUBY_INSTALL_NAME]
72 @orig_arch = Gem::ConfigMap[:arch]
75 util_set_arch 'i386-mswin32'
77 util_set_arch 'i686-darwin8.10.1'
80 @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
82 @private_key = File.expand_path File.join(File.dirname(__FILE__),
84 @public_cert = File.expand_path File.join(File.dirname(__FILE__),
89 Gem::ConfigMap[:BASERUBY] = @orig_BASERUBY
90 Gem::ConfigMap[:arch] = @orig_arch
92 if defined? Gem::RemoteFetcher then
93 Gem::RemoteFetcher.fetcher = nil
96 FileUtils.rm_rf @tempdir
100 ENV.delete 'GEM_PATH'
106 require 'rubygems/installer'
108 use_ui MockGemUi.new do
109 Dir.chdir @tempdir do
110 Gem::Builder.new(gem).build
114 gem = File.join(@tempdir, "#{gem.full_name}.gem").untaint
115 Gem::Installer.new(gem, :wrappers => true).install
118 def prep_cache_files(lc)
119 @usr_si ||= Gem::SourceIndex.new
120 @usr_sice ||= Gem::SourceInfoCacheEntry.new @usr_si, 0
122 @sys_si ||= Gem::SourceIndex.new
123 @sys_sice ||= Gem::SourceInfoCacheEntry.new @sys_si, 0
125 latest_si = Gem::SourceIndex.new
126 latest_si.add_specs(*@sys_si.latest_specs)
127 latest_sys_sice = Gem::SourceInfoCacheEntry.new latest_si, 0
129 latest_si = Gem::SourceIndex.new
130 latest_si.add_specs(*@usr_si.latest_specs)
131 latest_usr_sice = Gem::SourceInfoCacheEntry.new latest_si, 0
133 [ [lc.system_cache_file, @sys_sice],
134 [lc.latest_system_cache_file, latest_sys_sice],
135 [lc.user_cache_file, @usr_sice],
136 [lc.latest_user_cache_file, latest_usr_sice],
137 ].each do |filename, data|
138 FileUtils.mkdir_p File.dirname(filename).untaint
140 open filename.dup.untaint, 'wb' do |f|
141 f.write Marshal.dump({ @gem_repo => data })
147 open path.dup.untaint, 'rb' do |io|
152 def read_binary(path)
157 path = File.join(@gemhome, path)
158 dir = File.dirname path
159 FileUtils.mkdir_p dir
161 open path, 'wb' do |io|
168 def quick_gem(gemname, version='2')
169 require 'rubygems/specification'
171 spec = Gem::Specification.new do |s|
172 s.platform = Gem::Platform::RUBY
176 s.email = 'example@example.com'
177 s.homepage = 'http://example.com'
179 s.summary = "this is a summary"
180 s.description = "This is a test description"
182 yield(s) if block_given?
185 path = File.join "specifications", "#{spec.full_name}.gemspec"
186 written_path = write_file path do |io|
187 io.write(spec.to_ruby)
190 spec.loaded_from = written_path
192 Gem.source_index.add_spec spec
197 def util_build_gem(spec)
198 dir = File.join(@gemhome, 'gems', spec.full_name)
199 FileUtils.mkdir_p dir
202 spec.files.each do |file|
203 next if File.exist? file
204 FileUtils.mkdir_p File.dirname(file)
205 File.open file, 'w' do |fp| fp.puts "# #{file}" end
208 use_ui MockGemUi.new do
209 Gem::Builder.new(spec).build
212 FileUtils.mv "#{spec.full_name}.gem",
213 File.join(@gemhome, 'cache', "#{spec.original_name}.gem")
218 FileUtils.rm_r File.join(@gemhome, 'gems')
219 FileUtils.rm_r File.join(@gemhome, 'specifications')
220 Gem.source_index.refresh!
223 def util_gem(name, version, &block)
224 spec = quick_gem(name, version, &block)
228 cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
229 FileUtils.mv File.join(@gemhome, 'cache', "#{spec.original_name}.gem"),
231 FileUtils.rm File.join(@gemhome, 'specifications',
232 "#{spec.full_name}.gemspec")
234 spec.loaded_from = nil
243 Zlib::GzipWriter.wrap out do |io|
252 s.files = %w[lib/code.rb]
253 s.require_paths = %w[lib]
256 @a1 = quick_gem('a', '1', &init)
257 @a2 = quick_gem('a', '2', &init)
258 @a_evil9 = quick_gem('a_evil', '9', &init)
259 @b2 = quick_gem('b', '2', &init)
260 @c1_2 = quick_gem('c', '1.2', &init)
261 @pl1 = quick_gem 'pl', '1' do |s| # l for legacy
262 s.files = %w[lib/code.rb]
263 s.require_paths = %w[lib]
264 s.platform = Gem::Platform.new 'i386-linux'
265 s.instance_variable_set :@original_platform, 'i386-linux'
268 write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) do end
269 write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) do end
270 write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) do end
271 write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) do end
272 write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) do end
274 [@a1, @a2, @a_evil9, @b2, @c1_2, @pl1].each { |spec| util_build_gem spec }
276 FileUtils.rm_r File.join(@gemhome, 'gems', @pl1.original_name)
278 Gem.source_index = nil
282 # Set the platform to +arch+
284 def util_set_arch(arch)
285 Gem::ConfigMap[:arch] = arch
286 platform = Gem::Platform.new arch
288 Gem.instance_variable_set :@platforms, nil
289 Gem::Platform.instance_variable_set :@local, nil
294 def util_setup_fake_fetcher
297 require 'rubygems/remote_fetcher'
299 @fetcher = Gem::FakeFetcher.new
303 @all_gems = [@a1, @a2, @a_evil9, @b2, @c1_2].sort
304 @all_gem_names = @all_gems.map { |gem| gem.full_name }
306 gem_names = [@a1.full_name, @a2.full_name, @b2.full_name]
307 @gem_names = gem_names.sort.join("\n")
309 @source_index = Gem::SourceIndex.new
310 @source_index.add_spec @a1
311 @source_index.add_spec @a2
312 @source_index.add_spec @a_evil9
313 @source_index.add_spec @c1_2
315 Gem::RemoteFetcher.fetcher = @fetcher
318 def util_setup_source_info_cache(*specs)
319 require 'rubygems/source_info_cache'
320 require 'rubygems/source_info_cache_entry'
322 specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten]
323 si = Gem::SourceIndex.new specs
325 sice = Gem::SourceInfoCacheEntry.new si, 0
326 sic = Gem::SourceInfoCache.new
328 sic.set_cache_data( { @gem_repo => sice } )
333 Gem::SourceInfoCache.instance_variable_set :@cache, sic
338 def util_setup_spec_fetcher(*specs)
339 specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten]
340 si = Gem::SourceIndex.new specs
342 spec_fetcher = Gem::SpecFetcher.fetcher
344 spec_fetcher.specs[@uri] = []
345 si.gems.sort_by { |_, spec| spec }.each do |_, spec|
346 spec_tuple = [spec.name, spec.version, spec.original_platform]
347 spec_fetcher.specs[@uri] << spec_tuple
350 spec_fetcher.latest_specs[@uri] = []
351 si.latest_specs.sort.each do |spec|
352 spec_tuple = [spec.name, spec.version, spec.original_platform]
353 spec_fetcher.latest_specs[@uri] << spec_tuple
356 si.gems.sort_by { |_,spec| spec }.each do |_, spec|
357 path = "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{spec.original_name}.gemspec.rz"
358 data = Marshal.dump spec
359 data_deflate = Zlib::Deflate.deflate data
360 @fetcher.data[path] = data_deflate
367 Zlib::Deflate.deflate data
370 def self.win_platform?
378 # NOTE Allow tests to use a random (but controlled) port number instead of
379 # a hardcoded one. This helps CI tools when running parallels builds on
380 # the same builder slave.
381 def self.process_based_port
382 @@process_based_port ||= 8000 + $$ % 1000
385 def process_based_port
386 self.class.process_based_port