Change soft-fail to use the config, rather than env
[rbx.git] / test / rubygems / test_gem_dependency_installer.rb
blob80c446a2adc63f6c36740ffe52fc195d4816d08f
1 require 'test/unit'
2 require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
3 require 'rubygems/dependency_installer'
5 class TestGemDependencyInstaller < RubyGemTestCase
7   def setup
8     super
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"
16     end
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|
21       s.add_dependency 'a'
22       s.add_development_dependency 'aa'
23     end
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]
30     end
32     @x1_o, @x1_o_gem = util_gem 'x', '1' do |s|
33       s.platform = Gem::Platform.new %w[cpu other_platform 1]
34     end
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]
41     end
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,
49                                  @y1_1_p, @z1
51     util_clear_gems
52   end
54   def test_install
55     FileUtils.mv @a1_gem, @tempdir
56     inst = nil
58     Dir.chdir @tempdir do
59       inst = Gem::DependencyInstaller.new
60       inst.install 'a'
61     end
63     assert_equal Gem::SourceIndex.new(@a1.full_name => @a1),
64                  Gem::SourceIndex.from_installed_gems
66     assert_equal [@a1], inst.installed_gems
67   end
69   def test_install_cache_dir
70     FileUtils.mv @a1_gem, @tempdir
71     FileUtils.mv @b1_gem, @tempdir
72     inst = nil
74     Dir.chdir @tempdir do
75       inst = Gem::DependencyInstaller.new :cache_dir => @tempdir
76       inst.install 'b'
77     end
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"))
83   end
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
94     inst = nil
96     Dir.chdir @tempdir do
97       inst = Gem::DependencyInstaller.new
98       inst.install 'a-2'
99     end
101     FileUtils.rm File.join(@tempdir, "#{a2.full_name}.gem")
103     Dir.chdir @tempdir do
104       inst = Gem::DependencyInstaller.new
105       inst.install 'b'
106     end
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 }
113   end
115   def test_install_dependency
116     FileUtils.mv @a1_gem, @tempdir
117     FileUtils.mv @b1_gem, @tempdir
118     inst = nil
120     Dir.chdir @tempdir do
121       inst = Gem::DependencyInstaller.new
122       inst.install 'b'
123     end
125     assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
126   end
128   def test_install_dependency_development
129     FileUtils.mv @a1_gem, @tempdir
130     FileUtils.mv @aa1_gem, @tempdir
131     FileUtils.mv @b1_gem, @tempdir
132     inst = nil
134     Dir.chdir @tempdir do
135       inst = Gem::DependencyInstaller.new(:development => true)
136       inst.install 'b'
137     end
139     assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map { |s| s.full_name }
140   end
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
146     inst = nil
148     Dir.chdir @tempdir do
149       inst = Gem::DependencyInstaller.new
150       inst.install 'b'
151     end
153     assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
154   end
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
164     inst = nil
166     Dir.chdir @tempdir do
167       inst = Gem::DependencyInstaller.new
168       inst.install 'f'
169     end
171     assert_equal %w[f-2], inst.installed_gems.map { |s| s.full_name }
172   end
174   def test_install_local
175     FileUtils.mv @a1_gem, @tempdir
176     inst = nil
178     Dir.chdir @tempdir do
179       inst = Gem::DependencyInstaller.new :domain => :local
180       inst.install 'a-1.gem'
181     end
183     assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
184   end
186   def test_install_local_dependency
187     FileUtils.mv @a1_gem, @tempdir
188     FileUtils.mv @b1_gem, @tempdir
190     inst = nil
192     Dir.chdir @tempdir do
193       inst = Gem::DependencyInstaller.new :domain => :local
194       inst.install 'b-1.gem'
195     end
197     assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
198   end
200   def test_install_local_dependency_installed
201     FileUtils.mv @a1_gem, @tempdir
202     FileUtils.mv @b1_gem, @tempdir
204     inst = nil
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'
211     end
213     assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
214   end
216   def test_install_local_subdir
217     inst = nil
219     Dir.chdir @tempdir do
220       inst = Gem::DependencyInstaller.new :domain => :local
221       inst.install 'gems/a-1.gem'
222     end
224     assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
225   end
227   def test_install_env_shebang
228     FileUtils.mv @a1_gem, @tempdir
229     inst = nil
231     Dir.chdir @tempdir do
232       inst = Gem::DependencyInstaller.new :env_shebang => true, :wrappers => true
233       inst.install 'a'
234     end
236     assert_match %r|\A#!/usr/bin/env #{Gem::ConfigMap[:RUBY_INSTALL_NAME]}\n|,
237                  File.read(File.join(@gemhome, 'bin', 'a_bin'))
238   end
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
244     inst = nil
246     Dir.chdir @tempdir do
247       inst = Gem::DependencyInstaller.new :force => true
248       inst.install 'b'
249     end
251     assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
252   end
254   def test_install_ignore_dependencies
255     FileUtils.mv @b1_gem, @tempdir
256     inst = nil
258     Dir.chdir @tempdir do
259       inst = Gem::DependencyInstaller.new :ignore_dependencies => true
260       inst.install 'b'
261     end
263     assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
264   end
266   def test_install_install_dir
267     FileUtils.mv @a1_gem, @tempdir
268     gemhome2 = File.join @tempdir, 'gemhome2'
269     Dir.mkdir gemhome2
270     inst = nil
272     Dir.chdir @tempdir do
273       inst = Gem::DependencyInstaller.new :install_dir => gemhome2
274       inst.install 'a'
275     end
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"))
283   end
285   def test_install_domain_both
286     a1_data = nil
287     File.open @a1_gem, 'rb' do |fp|
288       a1_data = fp.read
289     end
291     @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
293     FileUtils.mv @b1_gem, @tempdir
294     inst = nil
296     Dir.chdir @tempdir do
297       inst = Gem::DependencyInstaller.new :domain => :both
298       inst.install 'b'
299     end
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
311   end
313   def test_install_domain_both_no_network
314     @fetcher.data["http://gems.example.com/gems/Marshal.#{@marshal_version}"] =
315       proc do
316         raise Gem::RemoteFetcher::FetchError
317       end
319     FileUtils.mv @a1_gem, @tempdir
320     FileUtils.mv @b1_gem, @tempdir
321     inst = nil
323     Dir.chdir @tempdir do
324       inst = Gem::DependencyInstaller.new :domain => :both
325       inst.install 'b'
326     end
328     assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
329   end
331   def test_install_domain_local
332     FileUtils.mv @b1_gem, @tempdir
333     inst = nil
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
340         inst.install 'b'
341       end
342       assert_equal 'b requires a (>= 0, runtime)', e.message
343     end
345     assert_equal [], inst.installed_gems.map { |s| s.full_name }
346   end
348   def test_install_domain_remote
349     a1_data = nil
350     File.open @a1_gem, 'rb' do |fp|
351       a1_data = fp.read
352     end
354     @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
356     inst = Gem::DependencyInstaller.new :domain => :remote
357     inst.install 'a'
359     assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
360   end
362   def test_install_dual_repository
363     FileUtils.mv @a1_gem, @tempdir
364     FileUtils.mv @b1_gem, @tempdir
365     inst = nil
367     gemhome2 = "#{@gemhome}2"
369     Dir.chdir @tempdir do
370       inst = Gem::DependencyInstaller.new :install_dir => gemhome2
371       inst.install 'a'
372     end
374     ENV['GEM_HOME'] = @gemhome
375     ENV['GEM_PATH'] = [@gemhome, gemhome2].join ':'
376     Gem.clear_paths
378     Dir.chdir @tempdir do
379       inst = Gem::DependencyInstaller.new
380       inst.install 'b'
381     end
383     assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
384   end
386   def test_install_remote
387     a1_data = nil
388     File.open @a1_gem, 'rb' do |fp|
389       a1_data = fp.read
390     end
392     @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
394     inst = Gem::DependencyInstaller.new
396     Dir.chdir @tempdir do
397       inst.install 'a'
398     end
400     assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
401   end
403   def test_install_remote_dep
404     a1_data = nil
405     File.open @a1_gem, 'rb' do |fp|
406       a1_data = fp.read
407     end
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
415       inst.install dep
416     end
418     assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
419   end
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]
424     end
426     util_clear_gems
428     si = util_setup_spec_fetcher @a1, a2_o
430     @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
432     a1_data = nil
433     a2_o_data = nil
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"] =
439       a1_data
440     @fetcher.data["http://gems.example.com/gems/#{a2_o.full_name}.gem"] =
441       a2_o_data
443     inst = Gem::DependencyInstaller.new :domain => :remote
444     inst.install 'a'
446     assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
447   end
449   def test_install_reinstall
450     Gem::Installer.new(@a1_gem).install
451     FileUtils.mv @a1_gem, @tempdir
452     inst = nil
454     Dir.chdir @tempdir do
455       inst = Gem::DependencyInstaller.new
456       inst.install 'a'
457     end
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 }
463   end
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
477         inst.install 'b'
478       end
480       assert_equal 'Unsigned gem', e.message
482       assert_equal %w[], inst.installed_gems.map { |s| s.full_name }
483     end
484   end
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
492       inst.install 'a'
494       assert_no_match(%r|This file was generated by RubyGems.|,
495                       File.read(File.join(@gemhome, 'bin', 'a_bin')))
496     end
497   end
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 }
511   end
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
521     inst.install 'd'
523     assert_equal %w[d-2], inst.installed_gems.map { |s| s.full_name }
524   end
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)
532   end
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'
538     gems = nil
540     Dir.chdir @tempdir do
541       gems = inst.find_gems_with_sources dep
542     end
544     assert_equal 2, gems.length
545     remote = gems.first
546     assert_equal 'a-1', remote.first.full_name, 'remote spec'
547     assert_equal @gem_repo, remote.last, 'remote path'
549     local = gems.last
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'
553   end
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 }
561   end
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
567     util_clear_gems
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 }
576   end
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 }
587   end
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 }
595   end
597   def test_gather_dependencies_old_required
598     e1, = util_gem 'e', '1' do |s| s.add_dependency 'd', '= 1' end
600     util_clear_gems
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 }
609   end