2 require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
3 require 'rubygems/dependency_installer'
5 class TestGemDependencyInstaller < RubyGemTestCase
10 @gems_dir = File.join @tempdir, 'gems'
11 @cache_dir = File.join @gemhome, 'cache'
12 FileUtils.mkdir @gems_dir
14 write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp|
15 fp.puts "#!/usr/bin/ruby"
17 @a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
18 @aa1, @aa1_gem = util_gem 'aa', '1'
20 @b1, @b1_gem = util_gem 'b', '1' do |s|
22 s.add_development_dependency 'aa'
25 @d1, @d1_gem = util_gem 'd', '1'
26 @d2, @d2_gem = util_gem 'd', '2'
28 @x1_m, @x1_m_gem = util_gem 'x', '1' do |s|
29 s.platform = Gem::Platform.new %w[cpu my_platform 1]
32 @x1_o, @x1_o_gem = util_gem 'x', '1' do |s|
33 s.platform = Gem::Platform.new %w[cpu other_platform 1]
36 @w1, @w1_gem = util_gem 'w', '1' do |s| s.add_dependency 'x' end
38 @y1, @y1_gem = util_gem 'y', '1'
39 @y1_1_p, @y1_1_p_gem = util_gem 'y', '1.1' do |s|
40 s.platform = Gem::Platform.new %w[cpu my_platform 1]
43 @z1, @z1_gem = util_gem 'z', '1' do |s| s.add_dependency 'y' end
45 @fetcher = Gem::FakeFetcher.new
46 Gem::RemoteFetcher.fetcher = @fetcher
48 si = util_setup_spec_fetcher @a1, @b1, @d1, @d2, @x1_m, @x1_o, @w1, @y1,
55 FileUtils.mv @a1_gem, @tempdir
59 inst = Gem::DependencyInstaller.new
63 assert_equal Gem::SourceIndex.new(@a1.full_name => @a1),
64 Gem::SourceIndex.from_installed_gems
66 assert_equal [@a1], inst.installed_gems
69 def test_install_cache_dir
70 FileUtils.mv @a1_gem, @tempdir
71 FileUtils.mv @b1_gem, @tempdir
75 inst = Gem::DependencyInstaller.new :cache_dir => @tempdir
79 assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
81 assert File.exist?(File.join(@tempdir, 'cache', "#{@a1.full_name}.gem"))
82 assert File.exist?(File.join(@tempdir, 'cache', "#{@b1.full_name}.gem"))
85 def test_install_dependencies_satisfied
86 a2, a2_gem = util_gem 'a', '2'
88 FileUtils.rm_rf File.join(@gemhome, 'gems')
89 Gem.source_index.refresh!
91 FileUtils.mv @a1_gem, @tempdir
92 FileUtils.mv a2_gem, @tempdir # not in index
93 FileUtils.mv @b1_gem, @tempdir
97 inst = Gem::DependencyInstaller.new
101 FileUtils.rm File.join(@tempdir, "#{a2.full_name}.gem")
103 Dir.chdir @tempdir do
104 inst = Gem::DependencyInstaller.new
108 installed = Gem::SourceIndex.from_installed_gems.map { |n,s| s.full_name }
110 assert_equal %w[a-2 b-1], installed.sort
112 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
115 def test_install_dependency
116 FileUtils.mv @a1_gem, @tempdir
117 FileUtils.mv @b1_gem, @tempdir
120 Dir.chdir @tempdir do
121 inst = Gem::DependencyInstaller.new
125 assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
128 def test_install_dependency_development
129 FileUtils.mv @a1_gem, @tempdir
130 FileUtils.mv @aa1_gem, @tempdir
131 FileUtils.mv @b1_gem, @tempdir
134 Dir.chdir @tempdir do
135 inst = Gem::DependencyInstaller.new(:development => true)
139 assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map { |s| s.full_name }
142 def test_install_dependency_existing
143 Gem::Installer.new(@a1_gem).install
144 FileUtils.mv @a1_gem, @tempdir
145 FileUtils.mv @b1_gem, @tempdir
148 Dir.chdir @tempdir do
149 inst = Gem::DependencyInstaller.new
153 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
156 def test_install_dependency_old
157 e1, e1_gem = util_gem 'e', '1'
158 f1, f1_gem = util_gem 'f', '1' do |s| s.add_dependency 'e' end
159 f2, f2_gem = util_gem 'f', '2'
161 FileUtils.mv e1_gem, @tempdir
162 FileUtils.mv f1_gem, @tempdir
163 FileUtils.mv f2_gem, @tempdir
166 Dir.chdir @tempdir do
167 inst = Gem::DependencyInstaller.new
171 assert_equal %w[f-2], inst.installed_gems.map { |s| s.full_name }
174 def test_install_local
175 FileUtils.mv @a1_gem, @tempdir
178 Dir.chdir @tempdir do
179 inst = Gem::DependencyInstaller.new :domain => :local
180 inst.install 'a-1.gem'
183 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
186 def test_install_local_dependency
187 FileUtils.mv @a1_gem, @tempdir
188 FileUtils.mv @b1_gem, @tempdir
192 Dir.chdir @tempdir do
193 inst = Gem::DependencyInstaller.new :domain => :local
194 inst.install 'b-1.gem'
197 assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
200 def test_install_local_dependency_installed
201 FileUtils.mv @a1_gem, @tempdir
202 FileUtils.mv @b1_gem, @tempdir
206 Dir.chdir @tempdir do
207 Gem::Installer.new('a-1.gem').install
209 inst = Gem::DependencyInstaller.new :domain => :local
210 inst.install 'b-1.gem'
213 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
216 def test_install_local_subdir
219 Dir.chdir @tempdir do
220 inst = Gem::DependencyInstaller.new :domain => :local
221 inst.install 'gems/a-1.gem'
224 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
227 def test_install_env_shebang
228 FileUtils.mv @a1_gem, @tempdir
231 Dir.chdir @tempdir do
232 inst = Gem::DependencyInstaller.new :env_shebang => true, :wrappers => true
236 assert_match %r|\A#!/usr/bin/env #{Gem::ConfigMap[:RUBY_INSTALL_NAME]}\n|,
237 File.read(File.join(@gemhome, 'bin', 'a_bin'))
240 def test_install_force
241 FileUtils.mv @b1_gem, @tempdir
242 si = util_setup_spec_fetcher @b1
243 @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
246 Dir.chdir @tempdir do
247 inst = Gem::DependencyInstaller.new :force => true
251 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
254 def test_install_ignore_dependencies
255 FileUtils.mv @b1_gem, @tempdir
258 Dir.chdir @tempdir do
259 inst = Gem::DependencyInstaller.new :ignore_dependencies => true
263 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
266 def test_install_install_dir
267 FileUtils.mv @a1_gem, @tempdir
268 gemhome2 = File.join @tempdir, 'gemhome2'
272 Dir.chdir @tempdir do
273 inst = Gem::DependencyInstaller.new :install_dir => gemhome2
277 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
279 assert File.exist?(File.join(gemhome2, 'specifications',
280 "#{@a1.full_name}.gemspec"))
281 assert File.exist?(File.join(gemhome2, 'cache',
282 "#{@a1.full_name}.gem"))
285 def test_install_domain_both
287 File.open @a1_gem, 'rb' do |fp|
291 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
293 FileUtils.mv @b1_gem, @tempdir
296 Dir.chdir @tempdir do
297 inst = Gem::DependencyInstaller.new :domain => :both
301 assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
302 a1, b1 = inst.installed_gems
304 a1_expected = File.join(@gemhome, 'specifications',
305 "#{a1.full_name}.gemspec")
306 b1_expected = File.join(@gemhome, 'specifications',
307 "#{b1.full_name}.gemspec")
309 assert_equal a1_expected, a1.loaded_from
310 assert_equal b1_expected, b1.loaded_from
313 def test_install_domain_both_no_network
314 @fetcher.data["http://gems.example.com/gems/Marshal.#{@marshal_version}"] =
316 raise Gem::RemoteFetcher::FetchError
319 FileUtils.mv @a1_gem, @tempdir
320 FileUtils.mv @b1_gem, @tempdir
323 Dir.chdir @tempdir do
324 inst = Gem::DependencyInstaller.new :domain => :both
328 assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
331 def test_install_domain_local
332 FileUtils.mv @b1_gem, @tempdir
335 Gem.source_index.gems.delete @a1.full_name
337 Dir.chdir @tempdir do
338 e = assert_raise Gem::InstallError do
339 inst = Gem::DependencyInstaller.new :domain => :local
342 assert_equal 'b requires a (>= 0, runtime)', e.message
345 assert_equal [], inst.installed_gems.map { |s| s.full_name }
348 def test_install_domain_remote
350 File.open @a1_gem, 'rb' do |fp|
354 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
356 inst = Gem::DependencyInstaller.new :domain => :remote
359 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
362 def test_install_dual_repository
363 FileUtils.mv @a1_gem, @tempdir
364 FileUtils.mv @b1_gem, @tempdir
367 gemhome2 = "#{@gemhome}2"
369 Dir.chdir @tempdir do
370 inst = Gem::DependencyInstaller.new :install_dir => gemhome2
374 ENV['GEM_HOME'] = @gemhome
375 ENV['GEM_PATH'] = [@gemhome, gemhome2].join ':'
378 Dir.chdir @tempdir do
379 inst = Gem::DependencyInstaller.new
383 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
386 def test_install_remote
388 File.open @a1_gem, 'rb' do |fp|
392 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
394 inst = Gem::DependencyInstaller.new
396 Dir.chdir @tempdir do
400 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
403 def test_install_remote_dep
405 File.open @a1_gem, 'rb' do |fp|
409 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
411 inst = Gem::DependencyInstaller.new
413 Dir.chdir @tempdir do
414 dep = Gem::Dependency.new @a1.name, @a1.version
418 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
421 def test_install_domain_remote_platform_newer
422 a2_o, a2_o_gem = util_gem 'a', '2' do |s|
423 s.platform = Gem::Platform.new %w[cpu other_platform 1]
428 si = util_setup_spec_fetcher @a1, a2_o
430 @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
435 File.open @a1_gem, 'rb' do |fp| a1_data = fp.read end
436 File.open a2_o_gem, 'rb' do |fp| a2_o_data = fp.read end
438 @fetcher.data["http://gems.example.com/gems/#{@a1.full_name}.gem"] =
440 @fetcher.data["http://gems.example.com/gems/#{a2_o.full_name}.gem"] =
443 inst = Gem::DependencyInstaller.new :domain => :remote
446 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
449 def test_install_reinstall
450 Gem::Installer.new(@a1_gem).install
451 FileUtils.mv @a1_gem, @tempdir
454 Dir.chdir @tempdir do
455 inst = Gem::DependencyInstaller.new
459 assert_equal Gem::SourceIndex.new(@a1.full_name => @a1),
460 Gem::SourceIndex.from_installed_gems
462 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
465 if defined? OpenSSL then
466 def test_install_security_policy
467 data = File.open(@a1_gem, 'rb') { |f| f.read }
468 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = data
470 data = File.open(@b1_gem, 'rb') { |f| f.read }
471 @fetcher.data['http://gems.example.com/gems/b-1.gem'] = data
473 policy = Gem::Security::HighSecurity
474 inst = Gem::DependencyInstaller.new :security_policy => policy
476 e = assert_raise Gem::Exception do
480 assert_equal 'Unsigned gem', e.message
482 assert_equal %w[], inst.installed_gems.map { |s| s.full_name }
486 # Wrappers don't work on mswin
487 unless win_platform? then
488 def test_install_no_wrappers
489 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = read_binary(@a1_gem)
491 inst = Gem::DependencyInstaller.new :wrappers => false
494 assert_no_match(%r|This file was generated by RubyGems.|,
495 File.read(File.join(@gemhome, 'bin', 'a_bin')))
499 def test_install_version
500 data = File.open(@d2_gem, 'rb') { |f| f.read }
501 @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
503 data = File.open(@d1_gem, 'rb') { |f| f.read }
504 @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
506 inst = Gem::DependencyInstaller.new
508 inst.install 'd', '= 1'
510 assert_equal %w[d-1], inst.installed_gems.map { |s| s.full_name }
513 def test_install_version_default
514 data = File.open(@d2_gem, 'rb') { |f| f.read }
515 @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
517 data = File.open(@d1_gem, 'rb') { |f| f.read }
518 @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
520 inst = Gem::DependencyInstaller.new
523 assert_equal %w[d-2], inst.installed_gems.map { |s| s.full_name }
526 def test_find_gems_gems_with_sources
527 inst = Gem::DependencyInstaller.new
528 dep = Gem::Dependency.new 'b', '>= 0'
530 assert_equal [[@b1, @gem_repo]],
531 inst.find_gems_with_sources(dep)
534 def test_find_gems_with_sources_local
535 FileUtils.mv @a1_gem, @tempdir
536 inst = Gem::DependencyInstaller.new
537 dep = Gem::Dependency.new 'a', '>= 0'
540 Dir.chdir @tempdir do
541 gems = inst.find_gems_with_sources dep
544 assert_equal 2, gems.length
546 assert_equal 'a-1', remote.first.full_name, 'remote spec'
547 assert_equal @gem_repo, remote.last, 'remote path'
550 assert_equal 'a-1', local.first.full_name, 'local spec'
551 assert_equal File.join(@tempdir, "#{@a1.full_name}.gem"),
552 local.last, 'local path'
555 def test_gather_dependencies
556 inst = Gem::DependencyInstaller.new
557 inst.find_spec_by_name_and_version 'b'
558 inst.gather_dependencies
560 assert_equal %w[a-1 b-1], inst.gems_to_install.map { |s| s.full_name }
563 def test_gather_dependencies_dropped
564 b2, = util_gem 'b', '2'
565 c1, = util_gem 'c', '1' do |s| s.add_dependency 'b' end
569 si = util_setup_spec_fetcher @a1, @b1, b2, c1
571 inst = Gem::DependencyInstaller.new
572 inst.find_spec_by_name_and_version 'c'
573 inst.gather_dependencies
575 assert_equal %w[b-2 c-1], inst.gems_to_install.map { |s| s.full_name }
578 def test_gather_dependencies_platform_alternate
579 util_set_arch 'cpu-my_platform1'
581 inst = Gem::DependencyInstaller.new
582 inst.find_spec_by_name_and_version 'w'
583 inst.gather_dependencies
585 assert_equal %w[x-1-cpu-my_platform-1 w-1],
586 inst.gems_to_install.map { |s| s.full_name }
589 def test_gather_dependencies_platform_bump
590 inst = Gem::DependencyInstaller.new
591 inst.find_spec_by_name_and_version 'z'
592 inst.gather_dependencies
594 assert_equal %w[y-1 z-1], inst.gems_to_install.map { |s| s.full_name }
597 def test_gather_dependencies_old_required
598 e1, = util_gem 'e', '1' do |s| s.add_dependency 'd', '= 1' end
602 si = util_setup_spec_fetcher @d1, @d2, e1
604 inst = Gem::DependencyInstaller.new
605 inst.find_spec_by_name_and_version 'e'
606 inst.gather_dependencies
608 assert_equal %w[d-1 e-1], inst.gems_to_install.map { |s| s.full_name }