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
19 @b1, @b1_gem = util_gem 'b', '1' do |s| s.add_dependency 'a' end
21 @d1, @d1_gem = util_gem 'd', '1'
22 @d2, @d2_gem = util_gem 'd', '2'
24 @x1_m, @x1_m_gem = util_gem 'x', '1' do |s|
25 s.platform = Gem::Platform.new %w[cpu my_platform 1]
28 @x1_o, @x1_o_gem = util_gem 'x', '1' do |s|
29 s.platform = Gem::Platform.new %w[cpu other_platform 1]
32 @w1, @w1_gem = util_gem 'w', '1' do |s| s.add_dependency 'x' end
34 @y1, @y1_gem = util_gem 'y', '1'
35 @y1_1_p, @y1_1_p_gem = util_gem 'y', '1.1' do |s|
36 s.platform = Gem::Platform.new %w[cpu my_platform 1]
39 @z1, @z1_gem = util_gem 'z', '1' do |s| s.add_dependency 'y' end
41 si = util_setup_source_info_cache @a1, @b1, @d1, @d2, @x1_m, @x1_o, @w1,
44 @fetcher = FakeFetcher.new
45 Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher
46 @fetcher.uri = URI.parse 'http://gems.example.com'
47 @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
49 FileUtils.rm_rf File.join(@gemhome, 'gems')
53 FileUtils.mv @a1_gem, @tempdir
57 inst = Gem::DependencyInstaller.new
61 assert_equal Gem::SourceIndex.new(@a1.full_name => @a1),
62 Gem::SourceIndex.from_installed_gems
64 assert_equal [@a1], inst.installed_gems
67 def test_install_dependency
68 FileUtils.mv @a1_gem, @tempdir
69 FileUtils.mv @b1_gem, @tempdir
73 inst = Gem::DependencyInstaller.new
77 assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
80 def test_install_dependency_existing
81 Gem::Installer.new(@a1_gem).install
82 FileUtils.mv @a1_gem, @tempdir
83 FileUtils.mv @b1_gem, @tempdir
87 inst = Gem::DependencyInstaller.new
91 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
94 def test_install_dependency_old
95 e1, e1_gem = util_gem 'e', '1'
96 f1, f1_gem = util_gem 'f', '1' do |s| s.add_dependency 'e' end
97 f2, f2_gem = util_gem 'f', '2'
99 FileUtils.mv e1_gem, @tempdir
100 FileUtils.mv f1_gem, @tempdir
101 FileUtils.mv f2_gem, @tempdir
104 Dir.chdir @tempdir do
105 inst = Gem::DependencyInstaller.new
109 assert_equal %w[f-2], inst.installed_gems.map { |s| s.full_name }
112 def test_install_local
113 FileUtils.mv @a1_gem, @tempdir
116 Dir.chdir @tempdir do
117 inst = Gem::DependencyInstaller.new :domain => :local
118 inst.install 'a-1.gem'
121 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
124 def test_install_local_dependency
125 FileUtils.mv @a1_gem, @tempdir
126 FileUtils.mv @b1_gem, @tempdir
130 Dir.chdir @tempdir do
131 inst = Gem::DependencyInstaller.new :domain => :local
132 inst.install 'b-1.gem'
135 assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
138 def test_install_local_dependency_installed
139 FileUtils.mv @a1_gem, @tempdir
140 FileUtils.mv @b1_gem, @tempdir
144 Dir.chdir @tempdir do
145 Gem::Installer.new('a-1.gem').install
147 inst = Gem::DependencyInstaller.new :domain => :local
148 inst.install 'b-1.gem'
151 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
154 def test_install_local_subdir
157 Dir.chdir @tempdir do
158 inst = Gem::DependencyInstaller.new :domain => :local
159 inst.install 'gems/a-1.gem'
162 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
165 def test_install_env_shebang
166 FileUtils.mv @a1_gem, @tempdir
169 Dir.chdir @tempdir do
170 inst = Gem::DependencyInstaller.new :env_shebang => true, :wrappers => true
174 assert_match %r|\A#!/usr/bin/env #{Gem::ConfigMap[:RUBY_INSTALL_NAME]}\n|,
175 File.read(File.join(@gemhome, 'bin', 'a_bin'))
178 def test_install_force
179 FileUtils.mv @b1_gem, @tempdir
180 si = util_setup_source_info_cache @b1
181 @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
184 Dir.chdir @tempdir do
185 inst = Gem::DependencyInstaller.new :force => true
189 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
192 def test_install_ignore_dependencies
193 FileUtils.mv @b1_gem, @tempdir
196 Dir.chdir @tempdir do
197 inst = Gem::DependencyInstaller.new :ignore_dependencies => true
201 assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
204 def test_install_install_dir
205 FileUtils.mv @a1_gem, @tempdir
206 gemhome2 = File.join @tempdir, 'gemhome2'
210 Dir.chdir @tempdir do
211 inst = Gem::DependencyInstaller.new :install_dir => gemhome2
215 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
217 assert File.exist?(File.join(gemhome2, 'specifications',
218 "#{@a1.full_name}.gemspec"))
219 assert File.exist?(File.join(gemhome2, 'cache',
220 "#{@a1.full_name}.gem"))
223 def test_install_domain_both
225 File.open @a1_gem, 'rb' do |fp|
229 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
231 FileUtils.mv @b1_gem, @tempdir
234 Dir.chdir @tempdir do
235 inst = Gem::DependencyInstaller.new :domain => :both
239 assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
240 a1, b1 = inst.installed_gems
242 a1_expected = File.join(@gemhome, 'specifications',
243 "#{a1.full_name}.gemspec")
244 b1_expected = File.join(@gemhome, 'specifications',
245 "#{b1.full_name}.gemspec")
247 assert_equal a1_expected, a1.loaded_from
248 assert_equal b1_expected, b1.loaded_from
251 def test_install_domain_both_no_network
252 Gem::SourceInfoCache.instance_variable_set :@cache, nil
254 @fetcher.data["http://gems.example.com/gems/Marshal.#{@marshal_version}"] =
256 raise Gem::RemoteFetcher::FetchError
259 FileUtils.mv @a1_gem, @tempdir
260 FileUtils.mv @b1_gem, @tempdir
263 Dir.chdir @tempdir do
264 inst = Gem::DependencyInstaller.new :domain => :both
268 assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
271 def test_install_domain_local
272 FileUtils.mv @b1_gem, @tempdir
275 Dir.chdir @tempdir do
276 e = assert_raise Gem::InstallError do
277 inst = Gem::DependencyInstaller.new :domain => :local
280 assert_equal 'b requires a (>= 0)', e.message
283 assert_equal [], inst.installed_gems.map { |s| s.full_name }
286 def test_install_domain_remote
288 File.open @a1_gem, 'rb' do |fp|
292 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
294 inst = Gem::DependencyInstaller.new :domain => :remote
297 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
300 def test_install_remote
302 File.open @a1_gem, 'rb' do |fp|
306 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
308 inst = Gem::DependencyInstaller.new
310 Dir.chdir @tempdir do
314 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
317 def test_install_remote_dep
319 File.open @a1_gem, 'rb' do |fp|
323 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
325 inst = Gem::DependencyInstaller.new
327 Dir.chdir @tempdir do
328 dep = Gem::Dependency.new @a1.name, @a1.version
332 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
335 def test_install_domain_remote_platform_newer
336 a2_o, a2_o_gem = util_gem 'a', '2' do |s|
337 s.platform = Gem::Platform.new %w[cpu other_platform 1]
340 si = util_setup_source_info_cache @a1, a2_o
342 @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
347 File.open @a1_gem, 'rb' do |fp| a1_data = fp.read end
348 File.open a2_o_gem, 'rb' do |fp| a2_o_data = fp.read end
350 @fetcher.data["http://gems.example.com/gems/#{@a1.full_name}.gem"] =
352 @fetcher.data["http://gems.example.com/gems/#{a2_o.full_name}.gem"] =
355 inst = Gem::DependencyInstaller.new :domain => :remote
358 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
361 def test_install_reinstall
362 Gem::Installer.new(@a1_gem).install
363 FileUtils.mv @a1_gem, @tempdir
366 Dir.chdir @tempdir do
367 inst = Gem::DependencyInstaller.new
371 assert_equal Gem::SourceIndex.new(@a1.full_name => @a1),
372 Gem::SourceIndex.from_installed_gems
374 assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
377 if defined? OpenSSL then
378 def test_install_security_policy
379 data = File.open(@a1_gem, 'rb') { |f| f.read }
380 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = data
382 data = File.open(@b1_gem, 'rb') { |f| f.read }
383 @fetcher.data['http://gems.example.com/gems/b-1.gem'] = data
385 policy = Gem::Security::HighSecurity
386 inst = Gem::DependencyInstaller.new :security_policy => policy
388 e = assert_raise Gem::Exception do
392 assert_equal 'Unsigned gem', e.message
394 assert_equal %w[], inst.installed_gems.map { |s| s.full_name }
398 # Wrappers don't work on mswin
399 unless win_platform? then
400 def test_install_no_wrappers
401 @fetcher.data['http://gems.example.com/gems/a-1.gem'] = read_binary(@a1_gem)
403 inst = Gem::DependencyInstaller.new :wrappers => false
406 assert_no_match(%r|This file was generated by RubyGems.|,
407 File.read(File.join(@gemhome, 'bin', 'a_bin')))
411 def test_install_version
412 data = File.open(@d2_gem, 'rb') { |f| f.read }
413 @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
415 data = File.open(@d1_gem, 'rb') { |f| f.read }
416 @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
418 inst = Gem::DependencyInstaller.new
420 inst.install 'd', '= 1'
422 assert_equal %w[d-1], inst.installed_gems.map { |s| s.full_name }
425 def test_install_version_default
426 data = File.open(@d2_gem, 'rb') { |f| f.read }
427 @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
429 data = File.open(@d1_gem, 'rb') { |f| f.read }
430 @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
432 inst = Gem::DependencyInstaller.new
435 assert_equal %w[d-2], inst.installed_gems.map { |s| s.full_name }
438 def test_find_gems_gems_with_sources
439 inst = Gem::DependencyInstaller.new
440 dep = Gem::Dependency.new 'b', '>= 0'
442 assert_equal [[@b1, 'http://gems.example.com']],
443 inst.find_gems_with_sources(dep)
446 def test_find_gems_with_sources_local
447 FileUtils.mv @a1_gem, @tempdir
448 inst = Gem::DependencyInstaller.new
449 dep = Gem::Dependency.new 'a', '>= 0'
452 Dir.chdir @tempdir do
453 gems = inst.find_gems_with_sources dep
456 assert_equal 2, gems.length
458 assert_equal 'a-1', remote.first.full_name, 'remote spec'
459 assert_equal 'http://gems.example.com', remote.last, 'remote path'
462 assert_equal 'a-1', local.first.full_name, 'local spec'
463 assert_equal File.join(@tempdir, "#{@a1.full_name}.gem"),
464 local.last, 'local path'
467 def test_gather_dependencies
468 inst = Gem::DependencyInstaller.new
469 inst.find_spec_by_name_and_version 'b'
470 inst.gather_dependencies
472 assert_equal %w[a-1 b-1], inst.gems_to_install.map { |s| s.full_name }
475 def test_gather_dependencies_dropped
476 b2, = util_gem 'b', '2'
477 c1, = util_gem 'c', '1' do |s| s.add_dependency 'b' end
479 si = util_setup_source_info_cache @a1, @b1, b2, c1
481 @fetcher = FakeFetcher.new
482 Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher
483 @fetcher.uri = URI.parse 'http://gems.example.com'
484 @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
486 inst = Gem::DependencyInstaller.new
487 inst.find_spec_by_name_and_version 'c'
488 inst.gather_dependencies
490 assert_equal %w[b-2 c-1], inst.gems_to_install.map { |s| s.full_name }
493 def test_gather_dependencies_platform_alternate
494 util_set_arch 'cpu-my_platform1'
496 inst = Gem::DependencyInstaller.new
497 inst.find_spec_by_name_and_version 'w'
498 inst.gather_dependencies
500 assert_equal %w[x-1-cpu-my_platform-1 w-1],
501 inst.gems_to_install.map { |s| s.full_name }
504 def test_gather_dependencies_platform_bump
505 inst = Gem::DependencyInstaller.new
506 inst.find_spec_by_name_and_version 'z'
507 inst.gather_dependencies
509 assert_equal %w[y-1 z-1], inst.gems_to_install.map { |s| s.full_name }
512 def test_gather_dependencies_old_required
513 e1, = util_gem 'e', '1' do |s| s.add_dependency 'd', '= 1' end
515 si = util_setup_source_info_cache @d1, @d2, e1
517 @fetcher = FakeFetcher.new
518 Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher
519 @fetcher.uri = URI.parse 'http://gems.example.com'
520 @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
522 inst = Gem::DependencyInstaller.new
523 inst.find_spec_by_name_and_version 'e'
524 inst.gather_dependencies
526 assert_equal %w[d-1 e-1], inst.gems_to_install.map { |s| s.full_name }