1require 'rubygems/test_case'
2require 'rubygems/dependency_installer'
3require 'rubygems/security'
4
5class TestGemDependencyInstaller < Gem::TestCase
6
7  def setup
8    super
9
10    @gems_dir  = File.join @tempdir, 'gems'
11    @cache_dir = File.join @gemhome, 'cache'
12
13    FileUtils.mkdir @gems_dir
14
15    Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new
16  end
17
18  def util_setup_gems
19    @a1, @a1_gem         = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
20    @a1_pre, @a1_pre_gem = util_gem 'a', '1.a'
21    @b1, @b1_gem         = util_gem 'b', '1' do |s|
22      s.add_dependency 'a'
23      s.add_development_dependency 'aa'
24    end
25
26    @c1, @c1_gem         = util_gem 'c', '1' do |s|
27      s.add_development_dependency 'b'
28    end
29
30    @d1, @d1_gem         = util_gem 'd', '1' do |s|
31      s.add_development_dependency 'c'
32    end
33
34    util_clear_gems
35    util_reset_gems
36  end
37
38  def test_available_set_for_name
39    util_setup_gems
40    p1a, = util_gem 'a', '10.a'
41    util_setup_spec_fetcher p1a, @a1, @a1_pre
42
43    inst = Gem::DependencyInstaller.new
44
45    available = inst.available_set_for 'a', Gem::Requirement.default
46
47    assert_equal %w[a-1], available.set.map { |s| s.spec.full_name }
48  end
49
50  def test_available_set_for_name_prerelease
51    util_setup_gems
52    p1a, = util_gem 'a', '10.a'
53    util_setup_spec_fetcher p1a, @a1, @a1_pre
54
55    inst = Gem::DependencyInstaller.new :prerelease => true
56
57    available = inst.available_set_for 'a', Gem::Requirement.default
58
59    assert_equal %w[a-10.a],
60                 available.sorted.map { |s| s.spec.full_name }
61  end
62
63  def test_available_set_for_dep
64    util_setup_gems
65    p1a, = util_gem 'a', '10.a'
66    util_setup_spec_fetcher p1a, @a1, @a1_pre
67
68    inst = Gem::DependencyInstaller.new
69
70    dep = Gem::Dependency.new 'a', Gem::Requirement.default
71
72    available = inst.available_set_for dep, Gem::Requirement.default
73
74    assert_equal %w[a-1], available.set.map { |s| s.spec.full_name }
75  end
76
77  def test_available_set_for_dep_prerelease
78    util_setup_gems
79    p1a, = util_gem 'a', '10.a'
80    util_setup_spec_fetcher p1a, @a1, @a1_pre
81
82    inst = Gem::DependencyInstaller.new :prerelease => true
83
84    dep = Gem::Dependency.new 'a', Gem::Requirement.default
85    dep.prerelease = true
86
87    available = inst.available_set_for dep, Gem::Requirement.default
88
89    assert_equal %w[a-10.a],
90                 available.sorted.map { |s| s.spec.full_name }
91  end
92
93  def test_install
94    util_setup_gems
95
96    FileUtils.mv @a1_gem, @tempdir
97    inst = nil
98
99    Dir.chdir @tempdir do
100      inst = Gem::DependencyInstaller.new
101      inst.install 'a'
102    end
103
104    assert_equal %w[a-1], Gem::Specification.map(&:full_name)
105    assert_equal [@a1], inst.installed_gems
106  end
107
108  def test_install_prerelease
109    util_setup_gems
110
111    p1a, gem = util_gem 'a', '10.a'
112
113    util_setup_spec_fetcher(p1a, @a1, @a1_pre)
114    util_clear_gems
115
116    p1a_data = Gem.read_binary(gem)
117
118    @fetcher.data['http://gems.example.com/gems/a-10.a.gem'] = p1a_data
119
120    dep = Gem::Dependency.new "a"
121    inst = Gem::DependencyInstaller.new :prerelease => true
122    inst.install dep
123
124    assert_equal %w[a-10.a], Gem::Specification.map(&:full_name)
125    assert_equal [p1a], inst.installed_gems
126  end
127
128  def test_install_when_only_prerelease
129    p1a, gem = util_gem 'p', '1.a'
130
131    util_setup_spec_fetcher(p1a)
132    util_clear_gems
133
134    p1a_data = Gem.read_binary(gem)
135
136    @fetcher.data['http://gems.example.com/gems/p-1.a.gem'] = p1a_data
137
138    dep = Gem::Dependency.new "p"
139    inst = Gem::DependencyInstaller.new
140    inst.install dep
141
142    assert_equal %w[], Gem::Specification.map(&:full_name)
143    assert_equal [], inst.installed_gems
144  end
145
146  def test_install_prerelease_skipped_when_normal_ver
147    util_setup_gems
148
149    util_setup_spec_fetcher(@a1, @a1_pre)
150    util_clear_gems
151
152    p1a_data = Gem.read_binary(@a1_gem)
153
154    @fetcher.data['http://gems.example.com/gems/a-1.gem'] = p1a_data
155
156    dep = Gem::Dependency.new "a"
157    inst = Gem::DependencyInstaller.new :prerelease => true
158    inst.install dep
159
160    assert_equal %w[a-1], Gem::Specification.map(&:full_name)
161    assert_equal [@a1], inst.installed_gems
162  end
163
164  def test_install_all_dependencies
165    util_setup_gems
166
167    _, e1_gem = util_gem 'e', '1' do |s|
168      s.add_dependency 'b'
169    end
170
171    util_clear_gems
172
173    FileUtils.mv @a1_gem, @tempdir
174    FileUtils.mv @b1_gem, @tempdir
175    FileUtils.mv e1_gem, @tempdir
176    inst = nil
177
178    Dir.chdir @tempdir do
179      inst = Gem::DependencyInstaller.new :ignore_dependencies => true
180      inst.install 'b'
181    end
182
183    Dir.chdir @tempdir do
184      inst = Gem::DependencyInstaller.new
185      inst.install 'e'
186    end
187
188    assert_equal %w[e-1 a-1], inst.installed_gems.map { |s| s.full_name }
189  end
190
191  def test_install_ignore_satified_deps
192    util_setup_gems
193
194    _, e1_gem = util_gem 'e', '1' do |s|
195      s.add_dependency 'b'
196    end
197
198    util_clear_gems
199
200    FileUtils.mv @a1_gem, @tempdir
201    FileUtils.mv @b1_gem, @tempdir
202    FileUtils.mv e1_gem, @tempdir
203
204    Dir.chdir @tempdir do
205      i = Gem::DependencyInstaller.new :ignore_dependencies => true
206      i.install 'b'
207    end
208
209    inst = nil
210
211    Dir.chdir @tempdir do
212      inst = Gem::DependencyInstaller.new :minimal_deps => true
213      inst.install 'e'
214    end
215
216    assert_equal %w[e-1], inst.installed_gems.map { |s| s.full_name }
217  end
218
219  def test_install_cache_dir
220    util_setup_gems
221
222    dir = "dir"
223    Dir.mkdir dir
224    FileUtils.mv @a1_gem, dir
225    FileUtils.mv @b1_gem, dir
226    inst = nil
227
228    Dir.chdir dir do
229      inst = Gem::DependencyInstaller.new :cache_dir => @tempdir
230      inst.install 'b'
231    end
232
233    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
234
235    assert File.exist? File.join(@gemhome, "cache", @a1.file_name)
236    assert File.exist? File.join(@gemhome, "cache", @b1.file_name)
237  end
238
239  def test_install_dependencies_satisfied
240    util_setup_gems
241
242    a2, a2_gem = util_gem 'a', '2'
243
244    FileUtils.rm_rf File.join(@gemhome, 'gems')
245
246    Gem::Specification.reset
247
248    FileUtils.mv @a1_gem, @tempdir
249    FileUtils.mv a2_gem, @tempdir # not in index
250    FileUtils.mv @b1_gem, @tempdir
251    inst = nil
252
253    Dir.chdir @tempdir do
254      inst = Gem::DependencyInstaller.new
255      inst.install 'a', Gem::Requirement.create("= 2")
256    end
257
258    FileUtils.rm File.join(@tempdir, a2.file_name)
259
260    Dir.chdir @tempdir do
261      inst = Gem::DependencyInstaller.new
262      inst.install 'b'
263    end
264
265    assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name)
266    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
267  end
268
269  # This asserts that if a gem's dependency is satisfied by an
270  # already installed gem, RubyGems doesn't installed a newer
271  # version
272  def test_install_doesnt_upgrade_installed_depedencies
273    util_setup_gems
274
275    a2, a2_gem = util_gem 'a', '2'
276    a3, a3_gem = util_gem 'a', '3'
277
278    util_setup_spec_fetcher @a1, a3, @b1
279
280    FileUtils.rm_rf File.join(@gemhome, 'gems')
281
282    Gem::Specification.reset
283
284    FileUtils.mv @a1_gem, @tempdir
285    FileUtils.mv a2_gem, @tempdir # not in index
286    FileUtils.mv @b1_gem, @tempdir
287    FileUtils.mv a3_gem, @tempdir
288
289    inst = nil
290
291    Dir.chdir @tempdir do
292      inst = Gem::DependencyInstaller.new
293      inst.install 'a', Gem::Requirement.create("= 2")
294    end
295
296    FileUtils.rm File.join(@tempdir, a2.file_name)
297
298    Dir.chdir @tempdir do
299      inst = Gem::DependencyInstaller.new
300      inst.install 'b'
301    end
302
303    assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name)
304    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
305  end
306
307  def test_install_dependency
308    util_setup_gems
309
310    done_installing_ran = false
311    inst = nil
312
313    Gem.done_installing do |installer, specs|
314      done_installing_ran = true
315      assert_equal inst, installer
316      assert_equal [@a1, @b1], specs
317    end
318
319    FileUtils.mv @a1_gem, @tempdir
320    FileUtils.mv @b1_gem, @tempdir
321
322    Dir.chdir @tempdir do
323      inst = Gem::DependencyInstaller.new(:build_docs_in_background => false)
324      inst.install 'b'
325    end
326
327    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
328
329    assert done_installing_ran, 'post installs hook was not run'
330  end
331
332  def test_install_dependency_development
333    util_setup_gems
334
335    @aa1, @aa1_gem = util_gem 'aa', '1'
336
337    util_reset_gems
338
339    FileUtils.mv @a1_gem, @tempdir
340    FileUtils.mv @aa1_gem, @tempdir
341    FileUtils.mv @b1_gem, @tempdir
342    inst = nil
343
344    Dir.chdir @tempdir do
345      inst = Gem::DependencyInstaller.new(:development => true)
346      inst.install 'b'
347    end
348
349    assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map { |s| s.full_name }
350  end
351
352  def test_install_dependency_development_deep
353    util_setup_gems
354
355    @aa1, @aa1_gem = util_gem 'aa', '1'
356
357    util_reset_gems
358
359    FileUtils.mv @a1_gem, @tempdir
360    FileUtils.mv @aa1_gem, @tempdir
361    FileUtils.mv @b1_gem, @tempdir
362    FileUtils.mv @c1_gem, @tempdir
363    FileUtils.mv @d1_gem, @tempdir
364    inst = nil
365
366    Dir.chdir @tempdir do
367      inst = Gem::DependencyInstaller.new(:development => true)
368      inst.install 'd'
369    end
370
371    assert_equal %w[a-1 aa-1 b-1 c-1 d-1], inst.installed_gems.map { |s| s.full_name }
372  end
373
374  def test_install_dependency_development_shallow
375    util_setup_gems
376
377    @aa1, @aa1_gem = util_gem 'aa', '1'
378
379    util_reset_gems
380
381    FileUtils.mv @a1_gem, @tempdir
382    FileUtils.mv @aa1_gem, @tempdir
383    FileUtils.mv @b1_gem, @tempdir
384    FileUtils.mv @c1_gem, @tempdir
385    FileUtils.mv @d1_gem, @tempdir
386    inst = nil
387
388    Dir.chdir @tempdir do
389      inst = Gem::DependencyInstaller.new(:development => true, :dev_shallow => true)
390      inst.install 'd'
391    end
392
393    assert_equal %w[c-1 d-1], inst.installed_gems.map { |s| s.full_name }
394  end
395
396  def test_install_dependency_existing
397    util_setup_gems
398
399    Gem::Installer.new(@a1_gem).install
400    FileUtils.mv @a1_gem, @tempdir
401    FileUtils.mv @b1_gem, @tempdir
402    inst = nil
403
404    Dir.chdir @tempdir do
405      inst = Gem::DependencyInstaller.new
406      inst.install 'b'
407    end
408
409    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
410  end
411
412  def test_install_dependency_old
413    _, e1_gem = util_gem 'e', '1'
414    _, f1_gem = util_gem 'f', '1', 'e' => nil
415    _, f2_gem = util_gem 'f', '2'
416
417    FileUtils.mv e1_gem, @tempdir
418    FileUtils.mv f1_gem, @tempdir
419    FileUtils.mv f2_gem, @tempdir
420    inst = nil
421
422    Dir.chdir @tempdir do
423      inst = Gem::DependencyInstaller.new
424      inst.install 'f'
425    end
426
427    assert_equal %w[f-2], inst.installed_gems.map { |s| s.full_name }
428  end
429
430  def test_install_local
431    util_setup_gems
432
433    FileUtils.mv @a1_gem, @tempdir
434    inst = nil
435
436    Dir.chdir @tempdir do
437      inst = Gem::DependencyInstaller.new :domain => :local
438      inst.install 'a-1.gem'
439    end
440
441    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
442  end
443
444  def test_install_local_dependency
445    util_setup_gems
446
447    FileUtils.mv @a1_gem, @tempdir
448    FileUtils.mv @b1_gem, @tempdir
449
450    inst = nil
451
452    Dir.chdir @tempdir do
453      inst = Gem::DependencyInstaller.new :domain => :local
454      inst.install 'b-1.gem'
455    end
456
457    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
458  end
459
460  def test_install_local_dependency_installed
461    util_setup_gems
462
463    FileUtils.mv @a1_gem, @tempdir
464    FileUtils.mv @b1_gem, @tempdir
465
466    inst = nil
467
468    Dir.chdir @tempdir do
469      Gem::Installer.new('a-1.gem').install
470
471      inst = Gem::DependencyInstaller.new :domain => :local
472      inst.install 'b-1.gem'
473    end
474
475    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
476  end
477
478  def test_install_local_subdir
479    util_setup_gems
480
481    inst = nil
482
483    Dir.chdir @tempdir do
484      inst = Gem::DependencyInstaller.new :domain => :local
485      inst.install 'gems/a-1.gem'
486    end
487
488    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
489  end
490
491  def test_install_env_shebang
492    util_setup_gems
493
494    FileUtils.mv @a1_gem, @tempdir
495    inst = nil
496
497    Dir.chdir @tempdir do
498      inst = Gem::DependencyInstaller.new :env_shebang => true, :wrappers => true, :format_executable => false
499      inst.install 'a'
500    end
501
502    env = "/\\S+/env" unless Gem.win_platform?
503
504    assert_match %r|\A#!#{env} #{Gem::ConfigMap[:ruby_install_name]}\n|,
505                 File.read(File.join(@gemhome, 'bin', 'a_bin'))
506  end
507
508  def test_install_force
509    util_setup_gems
510
511    FileUtils.mv @b1_gem, @tempdir
512    si = util_setup_spec_fetcher @b1
513    @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
514    inst = nil
515
516    Dir.chdir @tempdir do
517      inst = Gem::DependencyInstaller.new :force => true
518      inst.install 'b'
519    end
520
521    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
522  end
523
524  def test_install_build_args
525    util_setup_gems
526
527    FileUtils.mv @a1_gem, @tempdir
528    inst = nil
529    build_args = %w[--a --b="c"]
530
531    Dir.chdir @tempdir do
532      inst = Gem::DependencyInstaller.new(
533        :build_args => build_args)
534      inst.install 'a'
535    end
536
537    assert_equal build_args.join("\n"), File.read(inst.installed_gems.first.build_info_file).strip
538  end
539
540  def test_install_ignore_dependencies
541    util_setup_gems
542
543    FileUtils.mv @b1_gem, @tempdir
544    inst = nil
545
546    Dir.chdir @tempdir do
547      inst = Gem::DependencyInstaller.new :ignore_dependencies => true
548      inst.install 'b'
549    end
550
551    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
552  end
553
554  def test_install_install_dir
555    util_setup_gems
556
557    FileUtils.mv @a1_gem, @tempdir
558    FileUtils.mv @b1_gem, @tempdir
559
560    inst = Gem::Installer.new @a1.file_name
561    inst.install
562
563    gemhome2 = File.join @tempdir, 'gemhome2'
564    Dir.mkdir gemhome2
565    inst = nil
566
567    Dir.chdir @tempdir do
568      inst = Gem::DependencyInstaller.new :install_dir => gemhome2
569      inst.install 'b'
570    end
571
572    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
573
574    assert File.exist?(File.join(gemhome2, 'specifications', @a1.spec_name))
575    assert File.exist?(File.join(gemhome2, 'cache', @a1.file_name))
576  end
577
578  def test_install_domain_both
579    util_setup_gems
580
581    a1_data = nil
582    File.open @a1_gem, 'rb' do |fp|
583      a1_data = fp.read
584    end
585
586    @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
587
588    FileUtils.mv @b1_gem, @tempdir
589    inst = nil
590
591    Dir.chdir @tempdir do
592      inst = Gem::DependencyInstaller.new :domain => :both
593      inst.install 'b'
594    end
595
596    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
597    a1, b1 = inst.installed_gems
598
599    assert_equal a1.spec_file, a1.loaded_from
600    assert_equal b1.spec_file, b1.loaded_from
601  end
602
603  def test_install_domain_both_no_network
604    util_setup_gems
605
606    @fetcher.data["http://gems.example.com/gems/Marshal.#{@marshal_version}"] =
607      proc do
608        raise Gem::RemoteFetcher::FetchError
609      end
610
611    FileUtils.mv @a1_gem, @tempdir
612    FileUtils.mv @b1_gem, @tempdir
613    inst = nil
614
615    Dir.chdir @tempdir do
616      inst = Gem::DependencyInstaller.new :domain => :both
617      inst.install 'b'
618    end
619
620    assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
621  end
622
623  def test_install_domain_local
624    util_setup_gems
625
626    FileUtils.mv @b1_gem, @tempdir
627    inst = nil
628
629    Dir.chdir @tempdir do
630      e = assert_raises Gem::DependencyError do
631        inst = Gem::DependencyInstaller.new :domain => :local
632        inst.install 'b'
633      end
634
635      expected = "Unable to resolve dependencies: b requires a (>= 0)"
636      assert_equal expected, e.message
637    end
638
639    assert_equal [], inst.installed_gems.map { |s| s.full_name }
640  end
641
642  def test_install_domain_remote
643    util_setup_gems
644
645    a1_data = nil
646    File.open @a1_gem, 'rb' do |fp|
647      a1_data = fp.read
648    end
649
650    @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
651
652    inst = Gem::DependencyInstaller.new :domain => :remote
653    inst.install 'a'
654
655    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
656  end
657
658  def test_install_dual_repository
659    util_setup_gems
660
661    FileUtils.mv @a1_gem, @tempdir
662    FileUtils.mv @b1_gem, @tempdir
663    inst = nil
664
665    gemhome2 = "#{@gemhome}2"
666
667    Dir.chdir @tempdir do
668      inst = Gem::DependencyInstaller.new :install_dir => gemhome2
669      inst.install 'a'
670    end
671
672    ENV['GEM_HOME'] = @gemhome
673    ENV['GEM_PATH'] = [@gemhome, gemhome2].join File::PATH_SEPARATOR
674    Gem.clear_paths
675
676    Dir.chdir @tempdir do
677      inst = Gem::DependencyInstaller.new
678      inst.install 'b'
679    end
680
681    assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
682  end
683
684  def test_install_reinstall
685    util_setup_gems
686
687    Gem::Installer.new(@a1_gem).install
688    FileUtils.mv @a1_gem, @tempdir
689    inst = nil
690
691    Dir.chdir @tempdir do
692      inst = Gem::DependencyInstaller.new
693      inst.install 'a'
694    end
695
696    assert_equal %w[a-1], Gem::Specification.map(&:full_name)
697    assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
698  end
699
700  def test_install_remote
701    util_setup_gems
702
703    a1_data = nil
704    File.open @a1_gem, 'rb' do |fp|
705      a1_data = fp.read
706    end
707
708    @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
709
710    inst = Gem::DependencyInstaller.new
711
712    Dir.chdir @tempdir do
713      inst.install 'a'
714    end
715
716    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
717  end
718
719  def test_install_remote_dep
720    util_setup_gems
721
722    a1_data = nil
723    File.open @a1_gem, 'rb' do |fp|
724      a1_data = fp.read
725    end
726
727    @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
728
729    inst = Gem::DependencyInstaller.new
730
731    Dir.chdir @tempdir do
732      dep = Gem::Dependency.new @a1.name, @a1.version
733      inst.install dep
734    end
735
736    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
737  end
738
739  def test_install_remote_platform_newer
740    util_setup_gems
741
742    a2_o, a2_o_gem = util_gem 'a', '2' do |s|
743      s.platform = Gem::Platform.new %w[cpu other_platform 1]
744    end
745
746    util_clear_gems
747
748    si = util_setup_spec_fetcher @a1, a2_o
749
750    @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
751
752    a1_data = nil
753    a2_o_data = nil
754
755    File.open @a1_gem, 'rb' do |fp| a1_data = fp.read end
756    File.open a2_o_gem, 'rb' do |fp| a2_o_data = fp.read end
757
758    @fetcher.data["http://gems.example.com/gems/#{@a1.file_name}"] =
759      a1_data
760    @fetcher.data["http://gems.example.com/gems/#{a2_o.file_name}"] =
761      a2_o_data
762
763    inst = Gem::DependencyInstaller.new :domain => :remote
764    inst.install 'a'
765
766    assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
767  end
768
769  if defined? OpenSSL then
770    def test_install_security_policy
771      util_setup_gems
772
773      data = File.open(@a1_gem, 'rb') { |f| f.read }
774      @fetcher.data['http://gems.example.com/gems/a-1.gem'] = data
775
776      data = File.open(@b1_gem, 'rb') { |f| f.read }
777      @fetcher.data['http://gems.example.com/gems/b-1.gem'] = data
778
779      policy = Gem::Security::HighSecurity
780      inst = Gem::DependencyInstaller.new :security_policy => policy
781
782      e = assert_raises Gem::Security::Exception do
783        inst.install 'b'
784      end
785
786      assert_equal 'unsigned gems are not allowed by the High Security policy',
787                   e.message
788
789      assert_equal %w[], inst.installed_gems.map { |s| s.full_name }
790    end
791  end
792
793  # Wrappers don't work on mswin
794  unless win_platform? then
795    def test_install_no_wrappers
796      util_setup_gems
797
798      @fetcher.data['http://gems.example.com/gems/a-1.gem'] = read_binary(@a1_gem)
799
800      inst = Gem::DependencyInstaller.new :wrappers => false, :format_executable => false
801      inst.install 'a'
802
803      refute_match(%r|This file was generated by RubyGems.|,
804                   File.read(File.join(@gemhome, 'bin', 'a_bin')))
805    end
806  end
807
808  def test_install_version
809    util_setup_d
810
811    data = File.open(@d2_gem, 'rb') { |f| f.read }
812    @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
813
814    data = File.open(@d1_gem, 'rb') { |f| f.read }
815    @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
816
817    inst = Gem::DependencyInstaller.new
818
819    inst.install 'd', '= 1'
820
821    assert_equal %w[d-1], inst.installed_gems.map { |s| s.full_name }
822  end
823
824  def test_install_version_default
825    util_setup_d
826
827    data = File.open(@d2_gem, 'rb') { |f| f.read }
828    @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
829
830    data = File.open(@d1_gem, 'rb') { |f| f.read }
831    @fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
832
833    inst = Gem::DependencyInstaller.new
834    inst.install 'd'
835
836    assert_equal %w[d-2], inst.installed_gems.map { |s| s.full_name }
837  end
838
839  def test_find_gems_gems_with_sources
840    util_setup_gems
841
842    inst = Gem::DependencyInstaller.new
843    dep = Gem::Dependency.new 'b', '>= 0'
844
845    Gem::Specification.reset
846
847    set = inst.find_gems_with_sources(dep)
848
849    assert_kind_of Gem::AvailableSet, set
850
851    s = set.set.first
852
853    assert_equal @b1, s.spec
854    assert_equal Gem::Source.new(@gem_repo), s.source
855  end
856
857  def test_find_spec_by_name_and_version_wildcard
858    util_gem 'a', 1
859    FileUtils.mv 'gems/a-1.gem', @tempdir
860
861    FileUtils.touch 'rdoc.gem'
862
863    inst = Gem::DependencyInstaller.new
864
865    available = inst.find_spec_by_name_and_version('*.gem')
866
867    assert_equal %w[a-1], available.all_specs.map { |spec| spec.full_name }
868  end
869
870  def test_find_spec_by_name_and_version_wildcard_bad_gem
871    FileUtils.touch 'rdoc.gem'
872
873    inst = Gem::DependencyInstaller.new
874
875    assert_raises Gem::Package::FormatError do
876      inst.find_spec_by_name_and_version '*.gem'
877    end
878  end
879
880  def test_find_spec_by_name_and_version_bad_gem
881    FileUtils.touch 'rdoc.gem'
882
883    inst = Gem::DependencyInstaller.new
884
885    e = assert_raises Gem::Package::FormatError do
886      inst.find_spec_by_name_and_version 'rdoc.gem'
887    end
888
889    full_path = File.join @tempdir, 'rdoc.gem'
890    assert_equal "package metadata is missing in #{full_path}", e.message
891  end
892
893  def test_find_spec_by_name_and_version_directory
894    Dir.mkdir 'rdoc'
895
896    inst = Gem::DependencyInstaller.new
897
898    e = assert_raises Gem::SpecificGemNotFoundException do
899      inst.find_spec_by_name_and_version 'rdoc'
900    end
901
902    assert_equal "Could not find a valid gem 'rdoc' (>= 0) " +
903                 "locally or in a repository",
904                 e.message
905  end
906
907  def test_find_spec_by_name_and_version_file
908    FileUtils.touch 'rdoc'
909
910    inst = Gem::DependencyInstaller.new
911
912    e = assert_raises Gem::SpecificGemNotFoundException do
913      inst.find_spec_by_name_and_version 'rdoc'
914    end
915
916    assert_equal "Could not find a valid gem 'rdoc' (>= 0) " +
917                 "locally or in a repository",
918                 e.message
919  end
920
921  def test_find_gems_with_sources_local
922    util_setup_gems
923
924    FileUtils.mv @a1_gem, @tempdir
925    inst = Gem::DependencyInstaller.new
926    dep = Gem::Dependency.new 'a', '>= 0'
927    set = nil
928
929    Dir.chdir @tempdir do
930      set = inst.find_gems_with_sources dep
931    end
932
933    gems = set.sorted
934
935    assert_equal 2, gems.length
936    local = gems.first
937    assert_equal 'a-1', local.spec.full_name, 'local spec'
938    assert_equal File.join(@tempdir, @a1.file_name),
939                 local.source.download(local.spec), 'local path'
940
941    remote = gems.last
942    assert_equal 'a-1', remote.spec.full_name, 'remote spec'
943    assert_equal Gem::Source.new(@gem_repo), remote.source, 'remote path'
944
945  end
946
947  def test_find_gems_with_sources_prerelease
948    util_setup_gems
949
950    installer = Gem::DependencyInstaller.new
951
952    dependency = Gem::Dependency.new('a', Gem::Requirement.default)
953
954    releases =
955      installer.find_gems_with_sources(dependency).all_specs
956
957    assert releases.any? { |s| s.name == 'a' and s.version.to_s == '1' }
958    refute releases.any? { |s| s.name == 'a' and s.version.to_s == '1.a' }
959
960    dependency.prerelease = true
961
962    prereleases =
963      installer.find_gems_with_sources(dependency).all_specs
964
965    assert_equal [@a1_pre, @a1], prereleases
966  end
967
968  def test_find_gems_with_sources_with_bad_source
969    Gem.sources.replace ["http://not-there.nothing"]
970
971    installer = Gem::DependencyInstaller.new
972
973    dep = Gem::Dependency.new('a')
974
975    out = installer.find_gems_with_sources(dep)
976
977    assert out.empty?
978    assert_kind_of Gem::SourceFetchProblem, installer.errors.first
979  end
980
981  def assert_resolve expected, *specs
982    util_clear_gems
983    util_setup_spec_fetcher(*specs)
984    Gem::Specification.reset
985
986    inst = Gem::DependencyInstaller.new
987    inst.find_spec_by_name_and_version specs.first.name
988    inst.gather_dependencies
989
990    actual = inst.gems_to_install.map { |s| s.full_name }
991    assert_equal expected, actual
992  end
993
994  def assert_resolve_pre expected, *specs
995    util_clear_gems
996
997    util_setup_spec_fetcher(*specs)
998    Gem::Specification.reset
999
1000    spec = specs.first
1001
1002    inst = Gem::DependencyInstaller.new :prerelease => true
1003    inst.find_spec_by_name_and_version spec.name, spec.version
1004    inst.gather_dependencies
1005
1006    actual = inst.gems_to_install.map { |s| s.full_name }
1007    assert_equal expected, actual
1008  end
1009
1010  def test_gather_dependencies
1011    util_setup_gems
1012    util_reset_gems
1013
1014    inst = Gem::DependencyInstaller.new
1015    inst.find_spec_by_name_and_version 'b'
1016    inst.gather_dependencies
1017
1018    assert_equal %w[a-1 b-1], inst.gems_to_install.map { |s| s.full_name }
1019  end
1020
1021  ##
1022  # [A1] depends on
1023  #    [B] > 0 (satisfied by 2.0)
1024  # [B1] depends on
1025  #    [C] > 0 (satisfied by 1.0)
1026  # [B2] depends on nothing!
1027  # [C1] depends on nothing
1028
1029  def test_gather_dependencies_dropped
1030    a1, = util_spec 'a', '1', 'b' => nil
1031    b1, = util_spec 'b', '1', 'c' => nil
1032    b2, = util_spec 'b', '2'
1033    c1, = util_spec 'c', '1'
1034
1035    assert_resolve %w[b-2 a-1], a1, b1, b2, c1
1036  end
1037
1038  ##
1039  # [A] depends on
1040  #     [B] >= 1.0 (satisfied by 1.1) depends on
1041  #         [Z]
1042  #     [C] >= 1.0 depends on
1043  #         [B] = 1.0
1044  #
1045  # and should backtrack to resolve using b-1.0, pruning Z from the
1046  # resolve.
1047
1048  def test_gather_dependencies_raggi_the_edgecase_generator
1049    a,  _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '>= 1.0'
1050    b1, _ = util_spec 'b', '1.0'
1051    b2, _ = util_spec 'b', '1.1', 'z' => '>= 1.0'
1052    c,  _ = util_spec 'c', '1.0', 'b' => '= 1.0'
1053
1054    assert_resolve %w[b-1.0 c-1.0 a-1.0], a, b1, b2, c
1055  end
1056
1057  ##
1058  # [A] depends on
1059  #     [B] >= 1.0 (satisfied by 2.0)
1060  #     [C]  = 1.0 depends on
1061  #         [B] ~> 1.0
1062  #
1063  # and should resolve using b-1.0
1064
1065  def test_gather_dependencies_over
1066    a, _  = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0'
1067    b1, _ = util_spec 'b', '1.0'
1068    b2, _ = util_spec 'b', '2.0'
1069    c,  _ = util_spec 'c', '1.0', 'b' => '~> 1.0'
1070
1071    assert_resolve %w[b-1.0 c-1.0 a-1.0], a, b1, b2, c
1072  end
1073
1074  ##
1075  # [A] depends on
1076  #     [B] ~> 1.0 (satisfied by 1.1)
1077  #     [C]  = 1.0 depends on
1078  #         [B] = 1.0
1079  #
1080  # and should resolve using b-1.0
1081  #
1082  # TODO: this is not under, but over... under would require depth
1083  # first resolve through a dependency that is later pruned.
1084
1085  def test_gather_dependencies_under
1086    a,   _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0'
1087    b10, _ = util_spec 'b', '1.0'
1088    b11, _ = util_spec 'b', '1.1'
1089    c,   _ = util_spec 'c', '1.0', 'b' => '= 1.0'
1090
1091    assert_resolve %w[b-1.0 c-1.0 a-1.0], a, b10, b11, c
1092  end
1093
1094  # under
1095  #
1096  # [A] depends on
1097  #     [B] ~> 1.0 (satisfied by 1.0)
1098  #     [C]  = 1.0 depends on
1099  #         [B] = 2.0
1100
1101  def test_gather_dependencies_divergent
1102    a, _  = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0'
1103    b1, _ = util_spec 'b', '1.0'
1104    b2, _ = util_spec 'b', '2.0'
1105    c,  _ = util_spec 'c', '1.0', 'b' => '= 2.0'
1106
1107    assert_raises Gem::DependencyError do
1108      assert_resolve :ignored, a, b1, b2, c
1109    end
1110  end
1111
1112  def test_gather_dependencies_platform_alternate
1113    util_setup_wxyz
1114    util_set_arch 'cpu-my_platform1'
1115
1116    assert_resolve %w[x-1-cpu-my_platform-1 w-1], @w1, @x1_m
1117  end
1118
1119  def test_gather_dependencies_platform_bump
1120    util_setup_wxyz
1121
1122    assert_resolve %w[y-1 z-1], @z1, @y1
1123  end
1124
1125  def test_gather_dependencies_prerelease
1126    util_setup_gems
1127    util_setup_c1_pre
1128
1129    assert_resolve_pre %w[a-1.a b-1 c-1.a], @c1_pre, @a1_pre, @b1
1130  end
1131
1132  def test_gather_dependencies_old_required
1133    util_setup_d
1134    e1, = util_spec 'e', '1', 'd' => '= 1'
1135    util_clear_gems
1136
1137    assert_resolve %w[d-1 e-1], e1, @d1, @d2
1138  end
1139
1140  def util_write_a1_bin
1141    write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp|
1142      fp.puts "#!/usr/bin/ruby"
1143    end
1144  end
1145
1146  def util_setup_c1_pre
1147    @c1_pre, @c1_pre_gem = util_spec 'c', '1.a' do |s|
1148      s.add_dependency 'a', '1.a'
1149      s.add_dependency 'b', '1'
1150    end
1151
1152    util_reset_gems
1153  end
1154
1155  def util_setup_d
1156    @d1, @d1_gem = util_gem 'd', '1'
1157    @d2, @d2_gem = util_gem 'd', '2'
1158
1159    util_reset_gems
1160  end
1161
1162  def util_setup_wxyz
1163    @x1_m, @x1_m_gem = util_spec 'x', '1' do |s|
1164      s.platform = Gem::Platform.new %w[cpu my_platform 1]
1165    end
1166
1167    @x1_o, @x1_o_gem = util_spec 'x', '1' do |s|
1168      s.platform = Gem::Platform.new %w[cpu other_platform 1]
1169    end
1170
1171    @w1, @w1_gem = util_spec 'w', '1', 'x' => nil
1172
1173    @y1, @y1_gem = util_spec 'y', '1'
1174    @y1_1_p, @y1_1_p_gem = util_spec 'y', '1.1' do |s|
1175      s.platform = Gem::Platform.new %w[cpu my_platform 1]
1176    end
1177
1178    @z1, @z1_gem = util_spec 'z', '1', 'y' => nil
1179
1180    util_reset_gems
1181  end
1182
1183  def util_reset_gems
1184    @a1     ||= nil
1185    @b1     ||= nil
1186    @a1_pre ||= nil
1187    @c1_pre ||= nil
1188    @d1     ||= nil
1189    @d2     ||= nil
1190    @w1     ||= nil
1191    @x1_m   ||= nil
1192    @x1_o   ||= nil
1193    @y1     ||= nil
1194    @y1_1_p ||= nil
1195    @z1     ||= nil
1196
1197    util_setup_spec_fetcher(*[@a1, @a1_pre, @b1, @c1_pre,
1198                              @d1, @d2, @x1_m, @x1_o, @w1, @y1,
1199                              @y1_1_p, @z1].compact)
1200
1201    util_clear_gems
1202  end
1203end
1204