1# -*- coding: us-ascii -*-
2require 'rubygems/test_case'
3require 'stringio'
4require 'rubygems/specification'
5
6class TestGemSpecification < Gem::TestCase
7
8  LEGACY_YAML_SPEC = <<-EOF
9--- !ruby/object:Gem::Specification
10rubygems_version: "1.0"
11name: keyedlist
12version: !ruby/object:Gem::Version
13  version: 0.4.0
14date: 2004-03-28 15:37:49.828000 +02:00
15platform:
16summary: A Hash which automatically computes keys.
17require_paths:
18  - lib
19files:
20  - lib/keyedlist.rb
21autorequire: keyedlist
22author: Florian Gross
23email: flgr@ccan.de
24has_rdoc: true
25  EOF
26
27  LEGACY_RUBY_SPEC = <<-EOF
28Gem::Specification.new do |s|
29  s.name = %q{keyedlist}
30  s.version = %q{0.4.0}
31  s.has_rdoc = true
32  s.summary = %q{A Hash which automatically computes keys.}
33  s.files = [%q{lib/keyedlist.rb}]
34  s.require_paths = [%q{lib}]
35  s.autorequire = %q{keyedlist}
36  s.author = %q{Florian Gross}
37  s.email = %q{flgr@ccan.de}
38end
39  EOF
40
41  def setup
42    super
43
44    @a1 = quick_spec 'a', '1' do |s|
45      s.executable = 'exec'
46      s.extensions << 'ext/a/extconf.rb'
47      s.test_file = 'test/suite.rb'
48      s.requirements << 'A working computer'
49      s.rubyforge_project = 'example'
50      s.license = 'MIT'
51
52      s.add_dependency 'rake', '> 0.4'
53      s.add_dependency 'jabber4r', '> 0.0.0'
54      s.add_dependency 'pqa', ['> 0.4', '<= 0.6']
55
56      s.mark_version
57      s.files = %w[lib/code.rb]
58    end
59
60    @a2 = quick_spec 'a', '2' do |s|
61      s.files = %w[lib/code.rb]
62    end
63
64    @current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
65
66    load 'rubygems/syck_hack.rb'
67  end
68
69  def test_self_attribute_names
70    expected_value = %w[
71      authors
72      autorequire
73      bindir
74      cert_chain
75      date
76      dependencies
77      description
78      email
79      executables
80      extensions
81      extra_rdoc_files
82      files
83      homepage
84      licenses
85      metadata
86      name
87      platform
88      post_install_message
89      rdoc_options
90      require_paths
91      required_ruby_version
92      required_rubygems_version
93      requirements
94      rubyforge_project
95      rubygems_version
96      signing_key
97      specification_version
98      summary
99      test_files
100      version
101    ]
102
103    actual_value = Gem::Specification.attribute_names.map { |a| a.to_s }.sort
104
105    assert_equal expected_value, actual_value
106  end
107
108  def test_self__load_future
109    spec = Gem::Specification.new
110    spec.name = 'a'
111    spec.version = '1'
112    spec.specification_version = @current_version + 1
113
114    new_spec = Marshal.load Marshal.dump(spec)
115
116    assert_equal 'a', new_spec.name
117    assert_equal Gem::Version.new(1), new_spec.version
118    assert_equal @current_version, new_spec.specification_version
119  end
120
121  def test_self_from_yaml
122    @a1.instance_variable_set :@specification_version, nil
123
124    spec = Gem::Specification.from_yaml @a1.to_yaml
125
126    assert_equal Gem::Specification::NONEXISTENT_SPECIFICATION_VERSION,
127                 spec.specification_version
128  end
129
130  def test_self_from_yaml_syck_date_bug
131    # This is equivalent to (and totally valid) psych 1.0 output and
132    # causes parse errors on syck.
133    yaml = @a1.to_yaml
134    yaml.sub!(/^date:.*/, "date: 2011-04-26 00:00:00.000000000Z")
135
136    new_spec = with_syck do
137      Gem::Specification.from_yaml yaml
138    end
139
140    assert_kind_of Time, @a1.date
141    assert_kind_of Time, new_spec.date
142  end
143
144  def test_self_from_yaml_syck_default_key_bug
145    # This is equivalent to (and totally valid) psych 1.0 output and
146    # causes parse errors on syck.
147    yaml = <<-YAML
148--- !ruby/object:Gem::Specification
149name: posix-spawn
150version: !ruby/object:Gem::Version
151  version: 0.3.6
152  prerelease:
153dependencies:
154- !ruby/object:Gem::Dependency
155  name: rake-compiler
156  requirement: &70243867725240 !ruby/object:Gem::Requirement
157    none: false
158    requirements:
159    - - =
160      - !ruby/object:Gem::Version
161        version: 0.7.6
162  type: :development
163  prerelease: false
164  version_requirements: *70243867725240
165platform: ruby
166files: []
167test_files: []
168bindir:
169    YAML
170
171    new_spec = with_syck do
172      Gem::Specification.from_yaml yaml
173    end
174
175    op = new_spec.dependencies.first.requirement.requirements.first.first
176    refute_kind_of YAML::Syck::DefaultKey, op
177
178    refute_match %r%DefaultKey%, new_spec.to_ruby
179  end
180
181  def test_self_from_yaml_cleans_up_defaultkey
182    yaml = <<-YAML
183--- !ruby/object:Gem::Specification
184name: posix-spawn
185version: !ruby/object:Gem::Version
186  version: 0.3.6
187  prerelease:
188dependencies:
189- !ruby/object:Gem::Dependency
190  name: rake-compiler
191  requirement: &70243867725240 !ruby/object:Gem::Requirement
192    none: false
193    requirements:
194    - - !ruby/object:YAML::Syck::DefaultKey {}
195
196      - !ruby/object:Gem::Version
197        version: 0.7.6
198  type: :development
199  prerelease: false
200  version_requirements: *70243867725240
201platform: ruby
202files: []
203test_files: []
204bindir:
205    YAML
206
207    new_spec = Gem::Specification.from_yaml yaml
208
209    op = new_spec.dependencies.first.requirement.requirements.first.first
210    refute_kind_of YAML::Syck::DefaultKey, op
211
212    refute_match %r%DefaultKey%, new_spec.to_ruby
213  end
214
215  def test_self_from_yaml_cleans_up_defaultkey_from_newer_192
216    yaml = <<-YAML
217--- !ruby/object:Gem::Specification
218name: posix-spawn
219version: !ruby/object:Gem::Version
220  version: 0.3.6
221  prerelease:
222dependencies:
223- !ruby/object:Gem::Dependency
224  name: rake-compiler
225  requirement: &70243867725240 !ruby/object:Gem::Requirement
226    none: false
227    requirements:
228    - - !ruby/object:Syck::DefaultKey {}
229
230      - !ruby/object:Gem::Version
231        version: 0.7.6
232  type: :development
233  prerelease: false
234  version_requirements: *70243867725240
235platform: ruby
236files: []
237test_files: []
238bindir:
239    YAML
240
241    new_spec = Gem::Specification.from_yaml yaml
242
243    op = new_spec.dependencies.first.requirement.requirements.first.first
244    refute_kind_of YAML::Syck::DefaultKey, op
245
246    refute_match %r%DefaultKey%, new_spec.to_ruby
247  end
248
249  def test_self_from_yaml_cleans_up_Date_objects
250    yaml = <<-YAML
251--- !ruby/object:Gem::Specification
252rubygems_version: 0.8.1
253specification_version: 1
254name: diff-lcs
255version: !ruby/object:Gem::Version
256  version: 1.1.2
257date: 2004-10-20
258summary: Provides a list of changes that represent the difference between two sequenced collections.
259require_paths:
260  - lib
261author: Austin Ziegler
262email: diff-lcs@halostatue.ca
263homepage: http://rubyforge.org/projects/ruwiki/
264rubyforge_project: ruwiki
265description: "Test"
266bindir: bin
267has_rdoc: true
268required_ruby_version: !ruby/object:Gem::Version::Requirement
269  requirements:
270    -
271      - ">="
272      - !ruby/object:Gem::Version
273        version: 1.8.1
274  version:
275platform: ruby
276files:
277  - tests/00test.rb
278rdoc_options:
279  - "--title"
280  - "Diff::LCS -- A Diff Algorithm"
281  - "--main"
282  - README
283  - "--line-numbers"
284extra_rdoc_files:
285  - README
286  - ChangeLog
287  - Install
288executables:
289  - ldiff
290  - htmldiff
291extensions: []
292requirements: []
293dependencies: []
294    YAML
295
296    new_spec = Gem::Specification.from_yaml yaml
297
298    assert_kind_of Time, new_spec.date
299  end
300
301  def test_self_load
302    full_path = @a2.spec_file
303    write_file full_path do |io|
304      io.write @a2.to_ruby_for_cache
305    end
306
307    spec = Gem::Specification.load full_path
308
309    @a2.files.clear
310
311    assert_equal @a2, spec
312  end
313
314  def test_self_load_tainted
315    full_path = @a2.spec_file
316    write_file full_path do |io|
317      io.write @a2.to_ruby_for_cache
318    end
319
320    full_path.taint
321    loader = Thread.new { $SAFE = 1; Gem::Specification.load full_path }
322    spec = loader.value
323
324    @a2.files.clear
325
326    assert_equal @a2, spec
327  end
328
329  def test_self_load_escape_curly
330    @a2.name = 'a};raise "improper escaping";%q{'
331
332    full_path = @a2.spec_file
333    write_file full_path do |io|
334      io.write @a2.to_ruby_for_cache
335    end
336
337    spec = Gem::Specification.load full_path
338
339    @a2.files.clear
340
341    assert_equal @a2, spec
342  end
343
344  def test_self_load_escape_interpolation
345    @a2.name = 'a#{raise %<improper escaping>}'
346
347    full_path = @a2.spec_file
348    write_file full_path do |io|
349      io.write @a2.to_ruby_for_cache
350    end
351
352    spec = Gem::Specification.load full_path
353
354    @a2.files.clear
355
356    assert_equal @a2, spec
357  end
358
359  def test_self_load_escape_quote
360    @a2.name = 'a";raise "improper escaping";"'
361
362    full_path = @a2.spec_file
363    write_file full_path do |io|
364      io.write @a2.to_ruby_for_cache
365    end
366
367    spec = Gem::Specification.load full_path
368
369    @a2.files.clear
370
371    assert_equal @a2, spec
372  end
373
374  if defined?(Encoding)
375  def test_self_load_utf8_with_ascii_encoding
376    int_enc = Encoding.default_internal
377    silence_warnings { Encoding.default_internal = 'US-ASCII' }
378
379    spec2 = @a2.dup
380    bin = "\u5678"
381    spec2.authors = [bin]
382    full_path = spec2.spec_file
383    write_file full_path do |io|
384      io.write spec2.to_ruby_for_cache.force_encoding('BINARY').sub("\\u{5678}", bin.force_encoding('BINARY'))
385    end
386
387    spec = Gem::Specification.load full_path
388
389    spec2.files.clear
390
391    assert_equal spec2, spec
392  ensure
393    silence_warnings { Encoding.default_internal = int_enc }
394  end
395  end
396
397  def test_self_load_legacy_ruby
398    spec = Gem::Deprecate.skip_during do
399      eval LEGACY_RUBY_SPEC
400    end
401    assert_equal 'keyedlist', spec.name
402    assert_equal '0.4.0', spec.version.to_s
403    assert_equal Gem::Specification::TODAY, spec.date
404    assert spec.required_ruby_version.satisfied_by?(Gem::Version.new('1'))
405    assert_equal false, spec.has_unit_tests?
406  end
407
408  def test_self_normalize_yaml_input_with_183_yaml
409    input = "!ruby/object:Gem::Specification "
410    assert_equal "--- #{input}", Gem::Specification.normalize_yaml_input(input)
411  end
412
413  def test_self_normalize_yaml_input_with_non_183_yaml
414    input = "--- !ruby/object:Gem::Specification "
415    assert_equal input, Gem::Specification.normalize_yaml_input(input)
416  end
417
418  def test_self_normalize_yaml_input_with_183_io
419    input = "!ruby/object:Gem::Specification "
420    assert_equal "--- #{input}",
421      Gem::Specification.normalize_yaml_input(StringIO.new(input))
422  end
423
424  def test_self_normalize_yaml_input_with_non_183_io
425    input = "--- !ruby/object:Gem::Specification "
426    assert_equal input,
427      Gem::Specification.normalize_yaml_input(StringIO.new(input))
428  end
429
430  def test_self_normalize_yaml_input_with_192_yaml
431    input = "--- !ruby/object:Gem::Specification \nblah: !!null \n"
432    expected = "--- !ruby/object:Gem::Specification \nblah: \n"
433
434    assert_equal expected, Gem::Specification.normalize_yaml_input(input)
435  end
436
437  def test_self_outdated
438    util_clear_gems
439    util_setup_fake_fetcher true
440
441    a4 = quick_gem @a1.name, '4'
442    util_build_gem a4
443    util_setup_spec_fetcher @a1, @a2, @a3a, a4
444
445    Gem::Specification.remove_spec @a1
446    Gem::Specification.remove_spec @a2
447    Gem::Specification.remove_spec a4
448
449    assert_equal %w[a], Gem::Specification.outdated
450  end
451
452  def test_self_remove_spec
453    assert_includes Gem::Specification.all_names, 'a-1'
454
455    Gem::Specification.remove_spec @a1
456
457    refute_includes Gem::Specification.all_names, 'a-1'
458  end
459
460  def test_self_remove_spec_removed
461    open @a1.spec_file, 'w' do |io|
462      io.write @a1.to_ruby
463    end
464
465    Gem::Specification.reset
466
467    FileUtils.rm @a1.spec_file # bug #698
468
469    Gem::Specification.remove_spec @a1
470
471    refute_includes Gem::Specification.all_names, 'a-1'
472  end
473
474  DATA_PATH = File.expand_path "../data", __FILE__
475
476  def test_handles_private_null_type
477    path = File.join DATA_PATH, "null-type.gemspec.rz"
478
479    data = Marshal.load Gem.inflate(Gem.read_binary(path))
480
481    assert_equal nil, data.rubyforge_project
482  end
483
484  def test_emits_zulu_timestamps_properly
485    t = Time.utc(2012, 3, 12)
486    @a2.date = t
487
488    yaml = with_psych { @a2.to_yaml }
489
490    assert_match %r!date: 2012-03-12 00:00:00\.000000000 Z!, yaml
491  end if RUBY_VERSION =~ /1\.9\.2/
492
493  def test_initialize
494    spec = Gem::Specification.new do |s|
495      s.name = "blah"
496      s.version = "1.3.5"
497    end
498
499    assert_equal "blah", spec.name
500    assert_equal "1.3.5", spec.version.to_s
501    assert_equal Gem::Platform::RUBY, spec.platform
502    assert_equal nil, spec.summary
503    assert_equal [], spec.files
504
505    assert_equal [], spec.test_files
506    assert_equal [], spec.rdoc_options
507    assert_equal [], spec.extra_rdoc_files
508    assert_equal [], spec.executables
509    assert_equal [], spec.extensions
510    assert_equal [], spec.requirements
511    assert_equal [], spec.dependencies
512    assert_equal 'bin', spec.bindir
513    assert_equal '>= 0', spec.required_ruby_version.to_s
514    assert_equal '>= 0', spec.required_rubygems_version.to_s
515  end
516
517  def test_initialize_future
518    version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + 1
519    spec = Gem::Specification.new do |s|
520      s.name = "blah"
521      s.version = "1.3.5"
522
523      s.specification_version = version
524
525      s.new_unknown_attribute = "a value"
526    end
527
528    assert_equal "blah", spec.name
529    assert_equal "1.3.5", spec.version.to_s
530  end
531
532  def test_initialize_copy
533    spec = Gem::Specification.new do |s|
534      s.name = "blah"
535      s.version = "1.3.5"
536      s.summary = 'summary'
537      s.description = 'description'
538      s.authors = 'author a', 'author b'
539      s.licenses = 'BSD'
540      s.files = 'lib/file.rb'
541      s.test_files = 'test/file.rb'
542      s.rdoc_options = '--foo'
543      s.extra_rdoc_files = 'README.txt'
544      s.executables = 'exec'
545      s.extensions = 'ext/extconf.rb'
546      s.requirements = 'requirement'
547      s.add_dependency 'some_gem'
548    end
549
550    new_spec = spec.dup
551
552    assert_equal "blah", spec.name
553    assert_same  spec.name, new_spec.name
554
555    assert_equal "1.3.5", spec.version.to_s
556    assert_same spec.version, new_spec.version
557
558    assert_equal Gem::Platform::RUBY, spec.platform
559    assert_same spec.platform, new_spec.platform
560
561    assert_equal 'summary', spec.summary
562    assert_same spec.summary, new_spec.summary
563
564    assert_equal %w[lib/file.rb test/file.rb bin/exec README.txt
565                    ext/extconf.rb],
566                 spec.files
567    refute_same spec.files, new_spec.files, 'files'
568
569    assert_equal %w[test/file.rb], spec.test_files
570    refute_same spec.test_files, new_spec.test_files, 'test_files'
571
572    assert_equal %w[--foo], spec.rdoc_options
573    refute_same spec.rdoc_options, new_spec.rdoc_options, 'rdoc_options'
574
575    assert_equal %w[README.txt], spec.extra_rdoc_files
576    refute_same spec.extra_rdoc_files, new_spec.extra_rdoc_files,
577                'extra_rdoc_files'
578
579    assert_equal %w[exec], spec.executables
580    refute_same spec.executables, new_spec.executables, 'executables'
581
582    assert_equal %w[ext/extconf.rb], spec.extensions
583    refute_same spec.extensions, new_spec.extensions, 'extensions'
584
585    assert_equal %w[requirement], spec.requirements
586    refute_same spec.requirements, new_spec.requirements, 'requirements'
587
588    assert_equal [Gem::Dependency.new('some_gem', Gem::Requirement.default)],
589                 spec.dependencies
590    refute_same spec.dependencies, new_spec.dependencies, 'dependencies'
591
592    assert_equal 'bin', spec.bindir
593    assert_same spec.bindir, new_spec.bindir
594
595    assert_equal '>= 0', spec.required_ruby_version.to_s
596    assert_same spec.required_ruby_version, new_spec.required_ruby_version
597
598    assert_equal '>= 0', spec.required_rubygems_version.to_s
599    assert_same spec.required_rubygems_version,
600                new_spec.required_rubygems_version
601  end
602
603  def test_initialize_copy_broken
604    spec = Gem::Specification.new do |s|
605      s.name = 'a'
606      s.version = '1'
607    end
608
609    spec.instance_variable_set :@licenses, :blah
610    spec.loaded_from = '/path/to/file'
611
612    e = assert_raises Gem::FormatException do
613      spec.dup
614    end
615
616    assert_equal 'a-1 has an invalid value for @licenses', e.message
617    assert_equal '/path/to/file', e.file_path
618  end
619
620  def test__dump
621    @a2.platform = Gem::Platform.local
622    @a2.instance_variable_set :@original_platform, 'old_platform'
623
624    data = Marshal.dump @a2
625
626    same_spec = Marshal.load data
627
628    assert_equal 'old_platform', same_spec.original_platform
629  end
630
631  def test_activate
632    @a2.activate
633
634    assert @a2.activated?
635  end
636
637  def test_add_dependency_with_type
638    gem = quick_spec "awesome", "1.0" do |awesome|
639      awesome.add_dependency true
640      awesome.add_dependency :gem_name
641    end
642
643    assert_equal %w[true gem_name], gem.dependencies.map { |dep| dep.name }
644  end
645
646  def test_add_dependency_with_type_explicit
647    gem = quick_spec "awesome", "1.0" do |awesome|
648      awesome.add_development_dependency "monkey"
649    end
650
651    monkey = gem.dependencies.detect { |d| d.name == "monkey" }
652    assert_equal(:development, monkey.type)
653  end
654
655  def test_author
656    assert_equal 'A User', @a1.author
657  end
658
659  def test_authors
660    assert_equal ['A User'], @a1.authors
661  end
662
663  def test_bindir_equals
664    @a1.bindir = 'apps'
665
666    assert_equal 'apps', @a1.bindir
667  end
668
669  def test_bindir_equals_nil
670    @a2.bindir = nil
671    @a2.executable = 'app'
672
673    assert_equal nil, @a2.bindir
674    assert_equal %w[lib/code.rb app], @a2.files
675  end
676
677  def test_date
678    assert_equal Gem::Specification::TODAY, @a1.date
679  end
680
681  def test_date_equals_date
682    @a1.date = Date.new(2003, 9, 17)
683    assert_equal Time.utc(2003, 9, 17, 0,0,0), @a1.date
684  end
685
686  def test_date_equals_string
687    @a1.date = '2003-09-17'
688    assert_equal Time.utc(2003, 9, 17, 0,0,0), @a1.date
689  end
690
691  def test_date_equals_string_bad
692    assert_raises Gem::InvalidSpecificationException do
693      @a1.date = '9/11/2003'
694    end
695  end
696
697  def test_date_equals_time
698    @a1.date = Time.local(2003, 9, 17, 0,0,0)
699    assert_equal Time.utc(2003, 9, 17, 0,0,0), @a1.date
700  end
701
702  def test_date_equals_time_local
703    @a1.date = Time.local(2003, 9, 17, 19,50,0) # may not pass in utc >= +4
704    assert_equal Time.utc(2003, 9, 17, 0,0,0), @a1.date
705  end
706
707  def test_date_equals_time_utc
708    @a1.date = Time.utc(2003, 9, 17, 19,50,0)
709    assert_equal Time.utc(2003, 9, 17, 0,0,0), @a1.date
710  end
711
712  def test_date_tolerates_hour_sec_zulu
713    @a1.date = "2012-01-12 11:22:33.4444444 Z"
714    assert_equal Time.utc(2012,01,12,0,0,0), @a1.date
715  end
716
717  def test_date_tolerates_hour_sec_and_timezone
718    @a1.date = "2012-01-12 11:22:33.4444444 +02:33"
719    assert_equal Time.utc(2012,01,12,0,0,0), @a1.date
720  end
721
722  def test_dependencies
723    util_setup_deps
724    assert_equal [@bonobo, @monkey], @gem.dependencies
725  end
726
727  def test_doc_dir
728    assert_equal File.join(@gemhome, 'doc', 'a-1'), @a1.doc_dir
729  end
730
731  def test_doc_dir_type
732    assert_equal File.join(@gemhome, 'doc', 'a-1', 'ri'), @a1.doc_dir('ri')
733  end
734
735  def test_runtime_dependencies
736    util_setup_deps
737    assert_equal [@bonobo], @gem.runtime_dependencies
738  end
739
740  def test_development_dependencies
741    util_setup_deps
742    assert_equal [@monkey], @gem.development_dependencies
743  end
744
745  def test_description
746    assert_equal 'This is a test description', @a1.description
747  end
748
749  def test_eql_eh
750    g1 = new_spec 'gem', 1
751    g2 = new_spec 'gem', 1
752
753    assert_equal g1, g2
754    assert_equal g1.hash, g2.hash
755    assert_equal true, g1.eql?(g2)
756  end
757
758  def test_eql_eh_extensions
759    spec = @a1.dup
760    spec.extensions = 'xx'
761
762    refute_operator @a1, :eql?, spec
763    refute_operator spec, :eql?, @a1
764  end
765
766  def test_executables
767    @a1.executable = 'app'
768    assert_equal %w[app], @a1.executables
769  end
770
771  def test_executable_equals
772    @a2.executable = 'app'
773    assert_equal 'app', @a2.executable
774    assert_equal %w[lib/code.rb bin/app], @a2.files
775  end
776
777  def test_extensions
778    assert_equal ['ext/a/extconf.rb'], @a1.extensions
779  end
780
781  def test_files
782    @a1.files = %w(files bin/common)
783    @a1.test_files = %w(test_files bin/common)
784    @a1.executables = %w(executables common)
785    @a1.extra_rdoc_files = %w(extra_rdoc_files bin/common)
786    @a1.extensions = %w(extensions bin/common)
787
788    expected = %w[
789      bin/common
790      bin/executables
791      extensions
792      extra_rdoc_files
793      files
794      test_files
795    ]
796    assert_equal expected, @a1.files.sort
797  end
798
799  def test_files_append
800    @a1.files            = %w(files bin/common)
801    @a1.test_files       = %w(test_files bin/common)
802    @a1.executables      = %w(executables common)
803    @a1.extra_rdoc_files = %w(extra_rdoc_files bin/common)
804    @a1.extensions       = %w(extensions bin/common)
805
806    expected = %w[
807      bin/common
808      bin/executables
809      extensions
810      extra_rdoc_files
811      files
812      test_files
813    ]
814    assert_equal expected, @a1.files.sort
815
816    @a1.files << "generated_file.c"
817
818    expected << "generated_file.c"
819    expected.sort!
820
821    assert_equal expected, @a1.files.sort
822  end
823
824  def test_files_duplicate
825    @a2.files = %w[a b c d b]
826    @a2.extra_rdoc_files = %w[x y z x]
827    @a2.normalize
828
829    assert_equal %w[a b c d x y z], @a2.files
830    assert_equal %w[x y z], @a2.extra_rdoc_files
831  end
832
833  def test_files_extra_rdoc_files
834    @a2.files = %w[a b c d]
835    @a2.extra_rdoc_files = %w[x y z]
836    @a2.normalize
837    assert_equal %w[a b c d x y z], @a2.files
838  end
839
840  def test_files_non_array
841    @a1.files = "F"
842    @a1.test_files = "TF"
843    @a1.executables = "X"
844    @a1.extra_rdoc_files = "ERF"
845    @a1.extensions = "E"
846
847    assert_equal %w[E ERF F TF bin/X], @a1.files.sort
848  end
849
850  def test_files_non_array_pathological
851    @a1.instance_variable_set :@files, "F"
852    @a1.instance_variable_set :@test_files, "TF"
853    @a1.instance_variable_set :@extra_rdoc_files, "ERF"
854    @a1.instance_variable_set :@extensions, "E"
855    @a1.instance_variable_set :@executables, "X"
856
857    assert_equal %w[E ERF F TF bin/X], @a1.files.sort
858    assert_kind_of Integer, @a1.hash
859  end
860
861  def test_for_cache
862    @a2.add_runtime_dependency 'b', '1'
863    @a2.dependencies.first.instance_variable_set :@type, nil
864    @a2.required_rubygems_version = Gem::Requirement.new '> 0'
865    @a2.test_files = %w[test/test_b.rb]
866
867    refute_empty @a2.files
868    refute_empty @a2.test_files
869
870    spec = @a2.for_cache
871
872    assert_empty spec.files
873    assert_empty spec.test_files
874
875    refute_empty @a2.files
876    refute_empty @a2.test_files
877  end
878
879  def test_full_gem_path
880    assert_equal File.join(@gemhome, 'gems', @a1.full_name), @a1.full_gem_path
881
882    @a1.original_platform = 'mswin32'
883
884    assert_equal File.join(@gemhome, 'gems', @a1.original_name),
885                 @a1.full_gem_path
886  end
887
888  def test_full_gem_path_double_slash
889    gemhome = @gemhome.to_s.sub(/\w\//, '\&/')
890    @a1.loaded_from = File.join gemhome, "specifications", @a1.spec_name
891
892    expected = File.join @gemhome, "gems", @a1.full_name
893    assert_equal expected, @a1.full_gem_path
894  end
895
896  def test_full_name
897    assert_equal 'a-1', @a1.full_name
898
899    @a1 = Gem::Specification.new "a", 1
900    @a1.platform = Gem::Platform.new ['universal', 'darwin', nil]
901    assert_equal 'a-1-universal-darwin', @a1.full_name
902
903    @a1 = Gem::Specification.new "a", 1
904    @a1.instance_variable_set :@new_platform, 'mswin32'
905    assert_equal 'a-1-mswin32', @a1.full_name, 'legacy'
906
907    return if win_platform?
908
909    @a1 = Gem::Specification.new "a", 1
910    @a1.platform = 'current'
911    assert_equal 'a-1-x86-darwin-8', @a1.full_name
912  end
913
914  def test_full_name_windows
915    test_cases = {
916      'i386-mswin32'      => 'a-1-x86-mswin32-60',
917      'i386-mswin32_80'   => 'a-1-x86-mswin32-80',
918      'i386-mingw32'      => 'a-1-x86-mingw32'
919    }
920
921    test_cases.each do |arch, expected|
922      @a1 = Gem::Specification.new "a", 1
923      util_set_arch arch
924      @a1.platform = 'current'
925      assert_equal expected, @a1.full_name
926    end
927  end
928
929  def test_hash
930    assert_equal @a1.hash, @a1.hash
931    assert_equal @a1.hash, @a1.dup.hash
932    refute_equal @a1.hash, @a2.hash
933  end
934
935  def test_base_dir
936    assert_equal @gemhome, @a1.base_dir
937  end
938
939  def test_base_dir_not_loaded
940    @a1.instance_variable_set :@loaded_from, nil
941
942    assert_equal Gem.dir, @a1.base_dir
943  end
944
945  def test_base_dir_default
946    default_dir =
947      File.join Gem::Specification.default_specifications_dir, @a1.spec_name
948
949    @a1.instance_variable_set :@loaded_from, default_dir
950
951    assert_equal Gem.default_dir, @a1.base_dir
952  end
953
954  def test_lib_files
955    @a1.files = %w[lib/foo.rb Rakefile]
956
957    assert_equal %w[lib/foo.rb], @a1.lib_files
958  end
959
960  def test_license
961    assert_equal 'MIT', @a1.license
962  end
963
964  def test_licenses
965    assert_equal ['MIT'], @a1.licenses
966  end
967
968  def test_name
969    assert_equal 'a', @a1.name
970  end
971
972  def test_original_name
973    assert_equal 'a-1', @a1.full_name
974
975    @a1.platform = 'i386-linux'
976    @a1.instance_variable_set :@original_platform, 'i386-linux'
977    assert_equal 'a-1-i386-linux', @a1.original_name
978  end
979
980  def test_platform
981    assert_equal Gem::Platform::RUBY, @a1.platform
982  end
983
984  def test_platform_change_reset_full_name
985    orig_full_name = @a1.full_name
986
987    @a1.platform = "universal-unknown"
988    refute_equal orig_full_name, @a1.full_name
989  end
990
991  def test_platform_change_reset_cache_file
992    orig_cache_file = @a1.cache_file
993
994    @a1.platform = "universal-unknown"
995    refute_equal orig_cache_file, @a1.cache_file
996  end
997
998  def test_platform_equals
999    @a1.platform = nil
1000    assert_equal Gem::Platform::RUBY, @a1.platform
1001
1002    @a1.platform = Gem::Platform::RUBY
1003    assert_equal Gem::Platform::RUBY, @a1.platform
1004
1005    test_cases = {
1006      'i386-mswin32'    => ['x86', 'mswin32', '60'],
1007      'i386-mswin32_80' => ['x86', 'mswin32', '80'],
1008      'i386-mingw32'    => ['x86', 'mingw32', nil ],
1009      'x86-darwin8'     => ['x86', 'darwin',  '8' ],
1010    }
1011
1012    test_cases.each do |arch, expected|
1013      util_set_arch arch
1014      @a1.platform = Gem::Platform::CURRENT
1015      assert_equal Gem::Platform.new(expected), @a1.platform
1016    end
1017  end
1018
1019  def test_platform_equals_current
1020    @a1.platform = Gem::Platform::CURRENT
1021    assert_equal Gem::Platform.local, @a1.platform
1022    assert_equal Gem::Platform.local.to_s, @a1.original_platform
1023  end
1024
1025  def test_platform_equals_legacy
1026    @a1.platform = 'mswin32'
1027    assert_equal Gem::Platform.new('x86-mswin32'), @a1.platform
1028
1029    @a1.platform = 'i586-linux'
1030    assert_equal Gem::Platform.new('x86-linux'), @a1.platform
1031
1032    @a1.platform = 'powerpc-darwin'
1033    assert_equal Gem::Platform.new('ppc-darwin'), @a1.platform
1034  end
1035
1036  def test_prerelease_spec_adds_required_rubygems_version
1037    @prerelease = quick_spec('tardis', '2.2.0.a')
1038    refute @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new('1.3.1'))
1039    assert @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new('1.4.0'))
1040  end
1041
1042  def test_require_paths
1043    @a1.require_path = 'lib'
1044    assert_equal %w[lib], @a1.require_paths
1045  end
1046
1047  def test_requirements
1048    assert_equal ['A working computer'], @a1.requirements
1049  end
1050
1051  def test_runtime_dependencies_legacy
1052    # legacy gems don't have a type
1053    @a1.runtime_dependencies.each do |dep|
1054      dep.instance_variable_set :@type, nil
1055    end
1056
1057    expected = %w[rake jabber4r pqa]
1058
1059    assert_equal expected, @a1.runtime_dependencies.map { |d| d.name }
1060  end
1061
1062  def test_spaceship_name
1063    s1 = new_spec 'a', '1'
1064    s2 = new_spec 'b', '1'
1065
1066    assert_equal(-1, (s1 <=> s2))
1067    assert_equal( 0, (s1 <=> s1))
1068    assert_equal( 1, (s2 <=> s1))
1069  end
1070
1071  def test_spaceship_platform
1072    s1 = new_spec 'a', '1'
1073    s2 = new_spec 'a', '1' do |s|
1074      s.platform = Gem::Platform.new 'x86-my_platform1'
1075    end
1076
1077    assert_equal( -1, (s1 <=> s2))
1078    assert_equal(  0, (s1 <=> s1))
1079    assert_equal(  1, (s2 <=> s1))
1080  end
1081
1082  def test_spaceship_version
1083    s1 = new_spec 'a', '1'
1084    s2 = new_spec 'a', '2'
1085
1086    assert_equal( -1, (s1 <=> s2))
1087    assert_equal(  0, (s1 <=> s1))
1088    assert_equal(  1, (s2 <=> s1))
1089  end
1090
1091  def test_spec_file
1092    assert_equal File.join(@gemhome, 'specifications', 'a-1.gemspec'),
1093                 @a1.spec_file
1094  end
1095
1096  def test_spec_name
1097    assert_equal 'a-1.gemspec', @a1.spec_name
1098  end
1099
1100  def test_summary
1101    assert_equal 'this is a summary', @a1.summary
1102  end
1103
1104  def test_test_files
1105    @a1.test_file = 'test/suite.rb'
1106    assert_equal ['test/suite.rb'], @a1.test_files
1107  end
1108
1109  def test_to_ruby
1110    @a2.add_runtime_dependency 'b', '1'
1111    @a2.dependencies.first.instance_variable_set :@type, nil
1112    @a2.required_rubygems_version = Gem::Requirement.new '> 0'
1113
1114    ruby_code = @a2.to_ruby
1115
1116    expected = <<-SPEC
1117# -*- encoding: utf-8 -*-
1118
1119Gem::Specification.new do |s|
1120  s.name = "a"
1121  s.version = "2"
1122
1123  s.required_rubygems_version = Gem::Requirement.new(\"> 0\") if s.respond_to? :required_rubygems_version=
1124  s.authors = ["A User"]
1125  s.date = "#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}"
1126  s.description = "This is a test description"
1127  s.email = "example@example.com"
1128  s.files = ["lib/code.rb"]
1129  s.homepage = "http://example.com"
1130  s.require_paths = ["lib"]
1131  s.rubygems_version = "#{Gem::VERSION}"
1132  s.summary = "this is a summary"
1133
1134  if s.respond_to? :specification_version then
1135    s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
1136
1137    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
1138      s.add_runtime_dependency(%q<b>, [\"= 1\"])
1139    else
1140      s.add_dependency(%q<b>, [\"= 1\"])
1141    end
1142  else
1143    s.add_dependency(%q<b>, [\"= 1\"])
1144  end
1145end
1146    SPEC
1147
1148    assert_equal expected, ruby_code
1149
1150    same_spec = eval ruby_code
1151
1152    assert_equal @a2, same_spec
1153  end
1154
1155  def test_to_ruby_for_cache
1156    @a2.add_runtime_dependency 'b', '1'
1157    @a2.dependencies.first.instance_variable_set :@type, nil
1158    @a2.required_rubygems_version = Gem::Requirement.new '> 0'
1159
1160    # cached specs do not have spec.files populated:
1161    ruby_code = @a2.to_ruby_for_cache
1162
1163    expected = <<-SPEC
1164# -*- encoding: utf-8 -*-
1165
1166Gem::Specification.new do |s|
1167  s.name = "a"
1168  s.version = "2"
1169
1170  s.required_rubygems_version = Gem::Requirement.new(\"> 0\") if s.respond_to? :required_rubygems_version=
1171  s.authors = ["A User"]
1172  s.date = "#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}"
1173  s.description = "This is a test description"
1174  s.email = "example@example.com"
1175  s.homepage = "http://example.com"
1176  s.require_paths = ["lib"]
1177  s.rubygems_version = "#{Gem::VERSION}"
1178  s.summary = "this is a summary"
1179
1180  if s.respond_to? :specification_version then
1181    s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
1182
1183    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
1184      s.add_runtime_dependency(%q<b>, [\"= 1\"])
1185    else
1186      s.add_dependency(%q<b>, [\"= 1\"])
1187    end
1188  else
1189    s.add_dependency(%q<b>, [\"= 1\"])
1190  end
1191end
1192    SPEC
1193
1194    assert_equal expected, ruby_code
1195
1196    same_spec = eval ruby_code
1197
1198    # cached specs do not have spec.files populated:
1199    @a2.files = []
1200    assert_equal @a2, same_spec
1201  end
1202
1203  def test_to_ruby_fancy
1204    @a1.platform = Gem::Platform.local
1205    ruby_code = @a1.to_ruby
1206
1207    local = Gem::Platform.local
1208    expected_platform = "[#{local.cpu.inspect}, #{local.os.inspect}, #{local.version.inspect}]"
1209
1210    expected = <<-SPEC
1211# -*- encoding: utf-8 -*-
1212
1213Gem::Specification.new do |s|
1214  s.name = "a"
1215  s.version = "1"
1216  s.platform = Gem::Platform.new(#{expected_platform})
1217
1218  s.required_rubygems_version = Gem::Requirement.new(\">= 0\") if s.respond_to? :required_rubygems_version=
1219  s.authors = ["A User"]
1220  s.date = "#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}"
1221  s.description = "This is a test description"
1222  s.email = "example@example.com"
1223  s.executables = ["exec"]
1224  s.extensions = ["ext/a/extconf.rb"]
1225  s.files = ["lib/code.rb", "test/suite.rb", "bin/exec", "ext/a/extconf.rb"]
1226  s.homepage = "http://example.com"
1227  s.licenses = ["MIT"]
1228  s.require_paths = ["lib"]
1229  s.requirements = ["A working computer"]
1230  s.rubyforge_project = "example"
1231  s.rubygems_version = "#{Gem::VERSION}"
1232  s.summary = "this is a summary"
1233  s.test_files = ["test/suite.rb"]
1234
1235  if s.respond_to? :specification_version then
1236    s.specification_version = 4
1237
1238    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
1239      s.add_runtime_dependency(%q<rake>, [\"> 0.4\"])
1240      s.add_runtime_dependency(%q<jabber4r>, [\"> 0.0.0\"])
1241      s.add_runtime_dependency(%q<pqa>, [\"<= 0.6\", \"> 0.4\"])
1242    else
1243      s.add_dependency(%q<rake>, [\"> 0.4\"])
1244      s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
1245      s.add_dependency(%q<pqa>, [\"<= 0.6\", \"> 0.4\"])
1246    end
1247  else
1248    s.add_dependency(%q<rake>, [\"> 0.4\"])
1249    s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
1250    s.add_dependency(%q<pqa>, [\"<= 0.6\", \"> 0.4\"])
1251  end
1252end
1253    SPEC
1254
1255    assert_equal expected, ruby_code
1256
1257    same_spec = eval ruby_code
1258
1259    assert_equal @a1, same_spec
1260  end
1261
1262  def test_to_ruby_legacy
1263    gemspec1 = Gem::Deprecate.skip_during do
1264      eval LEGACY_RUBY_SPEC
1265    end
1266    ruby_code = gemspec1.to_ruby
1267    gemspec2 = eval ruby_code
1268
1269    assert_equal gemspec1, gemspec2
1270  end
1271
1272  def test_to_ruby_nested_hash
1273    metadata = {}
1274    metadata[metadata] = metadata
1275
1276    @a2.metadata = metadata
1277
1278    ruby = @a2.to_ruby
1279
1280    assert_match %r%^  s\.metadata = \{ "%, ruby
1281  end
1282
1283  def test_to_ruby_platform
1284    @a2.platform = Gem::Platform.local
1285    @a2.instance_variable_set :@original_platform, 'old_platform'
1286
1287    ruby_code = @a2.to_ruby
1288
1289    same_spec = eval ruby_code
1290
1291    assert_equal 'old_platform', same_spec.original_platform
1292  end
1293
1294  def test_to_yaml
1295    yaml_str = @a1.to_yaml
1296
1297    refute_match '!!null', yaml_str
1298
1299    same_spec = Gem::Specification.from_yaml(yaml_str)
1300
1301    assert_equal @a1, same_spec
1302  end
1303
1304  def test_to_yaml_fancy
1305    @a1.platform = Gem::Platform.local
1306    yaml_str = @a1.to_yaml
1307
1308    same_spec = Gem::Specification.from_yaml(yaml_str)
1309
1310    assert_equal Gem::Platform.local, same_spec.platform
1311
1312    assert_equal @a1, same_spec
1313  end
1314
1315  def test_to_yaml_platform_empty_string
1316    @a1.instance_variable_set :@original_platform, ''
1317
1318    assert_match %r|^platform: ruby$|, @a1.to_yaml
1319  end
1320
1321  def test_to_yaml_platform_legacy
1322    @a1.platform = 'powerpc-darwin7.9.0'
1323    @a1.instance_variable_set :@original_platform, 'powerpc-darwin7.9.0'
1324
1325    yaml_str = @a1.to_yaml
1326
1327    same_spec = YAML.load yaml_str
1328
1329    assert_equal Gem::Platform.new('powerpc-darwin7'), same_spec.platform
1330    assert_equal 'powerpc-darwin7.9.0', same_spec.original_platform
1331  end
1332
1333  def test_to_yaml_platform_nil
1334    @a1.instance_variable_set :@original_platform, nil
1335
1336    assert_match %r|^platform: ruby$|, @a1.to_yaml
1337  end
1338
1339  def test_validate
1340    util_setup_validate
1341
1342    Dir.chdir @tempdir do
1343      assert @a1.validate
1344    end
1345  end
1346
1347  def x s; s.gsub(/xxx/, ''); end
1348  def w; x "WARxxxNING"; end
1349  def t; x "TOxxxDO"; end
1350  def f; x "FxxxIXME"; end
1351
1352  def test_validate_authors
1353    util_setup_validate
1354
1355    Dir.chdir @tempdir do
1356      @a1.authors = [""]
1357
1358      use_ui @ui do
1359        @a1.validate
1360      end
1361
1362      assert_equal "#{w}:  no author specified\n", @ui.error, 'error'
1363
1364      @a1.authors = [Object.new]
1365
1366      assert_equal [], @a1.authors
1367
1368      e = assert_raises Gem::InvalidSpecificationException do
1369        @a1.validate
1370      end
1371
1372      assert_equal "authors may not be empty", e.message
1373
1374      @a1.authors = ["#{f} (who is writing this software)"]
1375
1376      e = assert_raises Gem::InvalidSpecificationException do
1377        @a1.validate
1378      end
1379
1380      assert_equal %{"#{f}" or "#{t}" is not an author}, e.message
1381
1382      @a1.authors = ["#{t} (who is writing this software)"]
1383
1384      e = assert_raises Gem::InvalidSpecificationException do
1385        @a1.validate
1386      end
1387
1388      assert_equal %{"#{f}" or "#{t}" is not an author}, e.message
1389    end
1390  end
1391
1392  def test_validate_autorequire
1393    util_setup_validate
1394
1395    Dir.chdir @tempdir do
1396      @a1.autorequire = 'code'
1397
1398      use_ui @ui do
1399        @a1.validate
1400      end
1401
1402      assert_equal "#{w}:  deprecated autorequire specified\n",
1403                   @ui.error, 'error'
1404    end
1405  end
1406
1407  def test_validate_dependencies
1408    util_setup_validate
1409
1410    Dir.chdir @tempdir do
1411      @a1.add_runtime_dependency     'b', '>= 1.0.rc1'
1412      @a1.add_development_dependency 'c', '>= 2.0.rc2'
1413
1414      use_ui @ui do
1415        @a1.validate
1416      end
1417
1418      expected = <<-EXPECTED
1419#{w}:  prerelease dependency on b (>= 1.0.rc1) is not recommended
1420#{w}:  prerelease dependency on c (>= 2.0.rc2, development) is not recommended
1421      EXPECTED
1422
1423      assert_equal expected, @ui.error, 'warning'
1424    end
1425  end
1426
1427  def test_validate_description
1428    util_setup_validate
1429
1430    Dir.chdir @tempdir do
1431      @a1.description = ''
1432
1433      use_ui @ui do
1434        @a1.validate
1435      end
1436
1437      assert_equal "#{w}:  no description specified\n", @ui.error, "error"
1438
1439      @ui = Gem::MockGemUi.new
1440      @a1.summary = "this is my summary"
1441      @a1.description = @a1.summary
1442
1443      use_ui @ui do
1444        @a1.validate
1445      end
1446
1447      assert_equal "#{w}:  description and summary are identical\n",
1448                   @ui.error, "error"
1449
1450      @a1.description = "#{f} (describe your package)"
1451
1452      e = assert_raises Gem::InvalidSpecificationException do
1453        @a1.validate
1454      end
1455
1456      assert_equal %{"#{f}" or "#{t}" is not a description}, e.message
1457
1458      @a1.description = "#{t} (describe your package)"
1459
1460      e = assert_raises Gem::InvalidSpecificationException do
1461        @a1.validate
1462      end
1463
1464      assert_equal %{"#{f}" or "#{t}" is not a description}, e.message
1465    end
1466  end
1467
1468  def test_validate_email
1469    util_setup_validate
1470
1471    Dir.chdir @tempdir do
1472      @a1.email = ""
1473
1474      use_ui @ui do
1475        @a1.validate
1476      end
1477
1478      assert_equal "#{w}:  no email specified\n", @ui.error, "error"
1479
1480      @a1.email = "FIxxxXME (your e-mail)".sub(/xxx/, "")
1481
1482      e = assert_raises Gem::InvalidSpecificationException do
1483        @a1.validate
1484      end
1485
1486      assert_equal %{"#{f}" or "#{t}" is not an email}, e.message
1487
1488      @a1.email = "#{t} (your e-mail)"
1489
1490      e = assert_raises Gem::InvalidSpecificationException do
1491        @a1.validate
1492      end
1493
1494      assert_equal %{"#{f}" or "#{t}" is not an email}, e.message
1495    end
1496  end
1497
1498  def test_validate_empty
1499    e = assert_raises Gem::InvalidSpecificationException do
1500      Gem::Specification.new.validate
1501    end
1502
1503    assert_equal 'missing value for attribute name', e.message
1504  end
1505
1506  def test_validate_executables
1507    util_setup_validate
1508
1509    FileUtils.mkdir_p File.join(@tempdir, 'bin')
1510    File.open File.join(@tempdir, 'bin', 'exec'), 'w' do end
1511    FileUtils.mkdir_p File.join(@tempdir, 'exec')
1512
1513    use_ui @ui do
1514      Dir.chdir @tempdir do
1515        assert @a1.validate
1516      end
1517    end
1518
1519    assert_equal %w[exec], @a1.executables
1520
1521    assert_equal '', @ui.output, 'output'
1522    assert_equal "#{w}:  bin/exec is missing #! line\n", @ui.error, 'error'
1523  end
1524
1525  def test_validate_empty_require_paths
1526    if win_platform? then
1527      skip 'test_validate_empty_require_paths skipped on MS Windows (symlink)'
1528    else
1529      util_setup_validate
1530
1531      @a1.require_paths = []
1532      e = assert_raises Gem::InvalidSpecificationException do
1533        @a1.validate
1534      end
1535
1536      assert_equal 'specification must have at least one require_path',
1537                   e.message
1538    end
1539  end
1540
1541  def test_validate_files
1542    skip 'test_validate_files skipped on MS Windows (symlink)' if win_platform?
1543    util_setup_validate
1544
1545    @a1.files += ['lib', 'lib2']
1546
1547    Dir.chdir @tempdir do
1548      FileUtils.ln_s '/root/path', 'lib2' unless vc_windows?
1549
1550      e = assert_raises Gem::InvalidSpecificationException do
1551        @a1.validate
1552      end
1553
1554      assert_equal '["lib2"] are not files', e.message
1555    end
1556
1557    assert_equal %w[lib/code.rb test/suite.rb bin/exec ext/a/extconf.rb lib2],
1558                 @a1.files
1559  end
1560
1561  def test_validate_homepage
1562    util_setup_validate
1563
1564    Dir.chdir @tempdir do
1565      @a1.homepage = nil
1566
1567      use_ui @ui do
1568        @a1.validate
1569      end
1570
1571      assert_equal "#{w}:  no homepage specified\n", @ui.error, 'error'
1572
1573      @ui = Gem::MockGemUi.new
1574
1575      @a1.homepage = ''
1576
1577      use_ui @ui do
1578        @a1.validate
1579      end
1580
1581      assert_equal "#{w}:  no homepage specified\n", @ui.error, 'error'
1582
1583      @a1.homepage = 'over at my cool site'
1584
1585      e = assert_raises Gem::InvalidSpecificationException do
1586        @a1.validate
1587      end
1588
1589      assert_equal '"over at my cool site" is not a URI', e.message
1590    end
1591  end
1592
1593  def test_validate_name
1594    util_setup_validate
1595
1596    e = assert_raises Gem::InvalidSpecificationException do
1597      @a1.name = :json
1598      @a1.validate
1599    end
1600
1601    assert_equal 'invalid value for attribute name: ":json"', e.message
1602  end
1603
1604  def test_validate_non_nil
1605    util_setup_validate
1606
1607    Dir.chdir @tempdir do
1608      assert @a1.validate
1609
1610      Gem::Specification.non_nil_attributes.each do |name|
1611        next if name == :files # set by #normalize
1612        spec = @a1.dup
1613        spec.instance_variable_set "@#{name}", nil
1614
1615        e = assert_raises Gem::InvalidSpecificationException do
1616          spec.validate
1617        end
1618
1619        assert_match %r%^#{name}%, e.message
1620      end
1621    end
1622  end
1623
1624  def test_validate_permissions
1625    skip 'chmod not supported' if Gem.win_platform?
1626
1627    util_setup_validate
1628
1629    Dir.chdir @tempdir do
1630      File.chmod 0640, File.join('lib', 'code.rb')
1631      File.chmod 0640, File.join('bin', 'exec')
1632
1633      use_ui @ui do
1634        @a1.validate
1635      end
1636
1637      assert_match "#{w}:  lib/code.rb is not world-readable\n", @ui.error
1638      assert_match "#{w}:  bin/exec is not world-readable\n", @ui.error
1639      assert_match "#{w}:  bin/exec is not executable\n", @ui.error
1640    end
1641  end
1642
1643  def test_validate_platform_legacy
1644    util_setup_validate
1645
1646    Dir.chdir @tempdir do
1647      @a1.platform = 'mswin32'
1648      assert @a1.validate
1649
1650      @a1.platform = 'i586-linux'
1651      assert @a1.validate
1652
1653      @a1.platform = 'powerpc-darwin'
1654      assert @a1.validate
1655    end
1656  end
1657
1658  def test_validate_rubygems_version
1659    util_setup_validate
1660
1661    @a1.rubygems_version = "3"
1662    e = assert_raises Gem::InvalidSpecificationException do
1663      @a1.validate
1664    end
1665
1666    assert_equal "expected RubyGems version #{Gem::VERSION}, was 3",
1667                 e.message
1668  end
1669
1670  def test_validate_specification_version
1671    util_setup_validate
1672
1673    Dir.chdir @tempdir do
1674      @a1.specification_version = '1.0'
1675
1676      e = assert_raises Gem::InvalidSpecificationException do
1677        use_ui @ui do
1678          @a1.validate
1679        end
1680      end
1681
1682      err = 'specification_version must be a Fixnum (did you mean version?)'
1683      assert_equal err, e.message
1684    end
1685  end
1686
1687  def test_validate_summary
1688    util_setup_validate
1689
1690    Dir.chdir @tempdir do
1691      @a1.summary = ''
1692
1693      use_ui @ui do
1694        @a1.validate
1695      end
1696
1697      assert_equal "#{w}:  no summary specified\n", @ui.error, 'error'
1698
1699      @a1.summary = "#{f} (describe your package)"
1700
1701      e = assert_raises Gem::InvalidSpecificationException do
1702        @a1.validate
1703      end
1704
1705      assert_equal %{"#{f}" or "#{t}" is not a summary}, e.message
1706
1707      @a1.summary = "#{t} (describe your package)"
1708
1709      e = assert_raises Gem::InvalidSpecificationException do
1710        @a1.validate
1711      end
1712
1713      assert_equal %{"#{f}" or "#{t}" is not a summary}, e.message
1714    end
1715  end
1716
1717  def test_version
1718    assert_equal Gem::Version.new('1'), @a1.version
1719  end
1720
1721  def test_version_change_reset_full_name
1722    orig_full_name = @a1.full_name
1723
1724    @a1.version = "2"
1725
1726    refute_equal orig_full_name, @a1.full_name
1727  end
1728
1729  def test_version_change_reset_cache_file
1730    orig_cache_file = @a1.cache_file
1731
1732    @a1.version = "2"
1733
1734    refute_equal orig_cache_file, @a1.cache_file
1735  end
1736
1737  def test__load_fixes_Date_objects
1738    spec = new_spec "a", 1
1739    spec.instance_variable_set :@date, Date.today
1740
1741    spec = Marshal.load Marshal.dump(spec)
1742
1743    assert_kind_of Time, spec.date
1744  end
1745
1746  def test_load_errors_contain_filename
1747    specfile = Tempfile.new(self.class.name.downcase)
1748    specfile.write "raise 'boom'"
1749    specfile.close
1750    begin
1751      capture_io do
1752        Gem::Specification.load(specfile.path)
1753      end
1754    rescue => e
1755      name_rexp = Regexp.new(Regexp.escape(specfile.path))
1756      assert e.backtrace.grep(name_rexp).any?
1757    end
1758  ensure
1759    specfile.delete
1760  end
1761
1762  ##
1763  # KEEP p-1-x86-darwin-8
1764  # KEEP p-1
1765  # KEEP c-1.2
1766  # KEEP a_evil-9
1767  #      a-1
1768  #      a-1-x86-my_platform-1
1769  # KEEP a-2
1770  #      a-2-x86-other_platform-1
1771  # KEEP a-2-x86-my_platform-1
1772  #      a-3.a
1773  # KEEP a-3-x86-other_platform-1
1774
1775  def test_latest_specs
1776    util_clear_gems
1777    util_setup_fake_fetcher
1778
1779    quick_spec 'p', '1'
1780
1781    p1_curr = quick_spec 'p', '1' do |spec|
1782      spec.platform = Gem::Platform::CURRENT
1783    end
1784
1785    quick_spec @a1.name, @a1.version do |s|
1786      s.platform = Gem::Platform.new 'x86-my_platform1'
1787    end
1788
1789    quick_spec @a1.name, @a1.version do |s|
1790      s.platform = Gem::Platform.new 'x86-third_platform1'
1791    end
1792
1793    quick_spec @a2.name, @a2.version do |s|
1794      s.platform = Gem::Platform.new 'x86-my_platform1'
1795    end
1796
1797    quick_spec @a2.name, @a2.version do |s|
1798      s.platform = Gem::Platform.new 'x86-other_platform1'
1799    end
1800
1801    quick_spec @a2.name, @a2.version.bump do |s|
1802      s.platform = Gem::Platform.new 'x86-other_platform1'
1803    end
1804
1805    Gem::Specification.remove_spec @b2
1806    Gem::Specification.remove_spec @pl1
1807
1808    expected = %W[
1809                  a-2
1810                  a-2-x86-my_platform-1
1811                  a-3-x86-other_platform-1
1812                  a_evil-9
1813                  c-1.2
1814                  dep_x-1
1815                  p-1
1816                  #{p1_curr.full_name}
1817                  x-1
1818                 ]
1819
1820    latest_specs = Gem::Specification.latest_specs.map(&:full_name).sort
1821
1822    assert_equal expected, latest_specs
1823  end
1824
1825  def test_metadata_validates_ok
1826    util_setup_validate
1827
1828    Dir.chdir @tempdir do
1829      @m1 = quick_gem 'm', '1' do |s|
1830        s.files = %w[lib/code.rb]
1831        s.metadata = { 'one' => "two", 'two' => "three" }
1832      end
1833
1834      use_ui @ui do
1835        @m1.validate
1836      end
1837    end
1838  end
1839
1840  def test_metadata_key_type_validation_fails
1841    util_setup_validate
1842
1843    Dir.chdir @tempdir do
1844      @m2 = quick_gem 'm', '2' do |s|
1845        s.files = %w[lib/code.rb]
1846        s.metadata = { 1 => "fail" }
1847      end
1848
1849      e = assert_raises Gem::InvalidSpecificationException do
1850        @m2.validate
1851      end
1852
1853      assert_equal "metadata keys must be a String", e.message
1854    end
1855  end
1856
1857  def test_metadata_key_size_validation_fails
1858    util_setup_validate
1859
1860    Dir.chdir @tempdir do
1861      @m2 = quick_gem 'm', '2' do |s|
1862        s.files = %w[lib/code.rb]
1863        s.metadata = { ("x" * 129) => "fail" }
1864      end
1865
1866      e = assert_raises Gem::InvalidSpecificationException do
1867        @m2.validate
1868      end
1869
1870      assert_equal "metadata key too large (129 > 128)", e.message
1871    end
1872  end
1873
1874  def test_metadata_value_type_validation_fails
1875    util_setup_validate
1876
1877    Dir.chdir @tempdir do
1878      @m2 = quick_gem 'm', '2' do |s|
1879        s.files = %w[lib/code.rb]
1880        s.metadata = { 'fail' => [] }
1881      end
1882
1883      e = assert_raises Gem::InvalidSpecificationException do
1884        @m2.validate
1885      end
1886
1887      assert_equal "metadata values must be a String", e.message
1888    end
1889  end
1890
1891  def test_metadata_value_size_validation_fails
1892    util_setup_validate
1893
1894    Dir.chdir @tempdir do
1895      @m2 = quick_gem 'm', '2' do |s|
1896        s.files = %w[lib/code.rb]
1897        s.metadata = { 'fail' => ("x" * 1025) }
1898      end
1899
1900      e = assert_raises Gem::InvalidSpecificationException do
1901        @m2.validate
1902      end
1903
1904      assert_equal "metadata value too large (1025 > 1024)", e.message
1905    end
1906  end
1907
1908  def test_metadata_specs
1909    valid_ruby_spec = <<-EOF
1910# -*- encoding: utf-8 -*-
1911
1912Gem::Specification.new do |s|
1913  s.name = "m"
1914  s.version = "1"
1915
1916  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
1917  s.metadata = { "one" => "two", "two" => "three" } if s.respond_to? :metadata=
1918  s.authors = ["A User"]
1919  s.date = "#{Gem::Specification::TODAY.strftime("%Y-%m-%d")}"
1920  s.description = "This is a test description"
1921  s.email = "example@example.com"
1922  s.files = ["lib/code.rb"]
1923  s.homepage = "http://example.com"
1924  s.require_paths = ["lib"]
1925  s.rubygems_version = "#{Gem::VERSION}"
1926  s.summary = "this is a summary"
1927end
1928    EOF
1929
1930    @m1 = quick_gem 'm', '1' do |s|
1931      s.files = %w[lib/code.rb]
1932      s.metadata = { 'one' => "two", 'two' => "three" }
1933    end
1934
1935    assert_equal @m1.to_ruby, valid_ruby_spec
1936  end
1937
1938  def test_find_by_name
1939    util_make_gems
1940    assert(Gem::Specification.find_by_name("a"))
1941    assert(Gem::Specification.find_by_name("a", "1"))
1942    assert(Gem::Specification.find_by_name("a", ">1"))
1943    assert_raises(Gem::LoadError) do
1944      Gem::Specification.find_by_name("monkeys")
1945    end
1946  end
1947
1948  def test_find_by_path
1949    a = new_spec "foo", "1", nil, "lib/foo.rb"
1950
1951    install_specs a
1952
1953    assert_equal a, Gem::Specification.find_by_path('foo')
1954    a.activate
1955    assert_equal a, Gem::Specification.find_by_path('foo')
1956  end
1957
1958  def test_find_inactive_by_path
1959    a = new_spec "foo", "1", nil, "lib/foo.rb"
1960
1961    install_specs a
1962
1963    assert_equal a, Gem::Specification.find_inactive_by_path('foo')
1964    a.activate
1965    assert_equal nil, Gem::Specification.find_inactive_by_path('foo')
1966  end
1967
1968  def test_load_default_gem
1969    Gem::Specification.reset
1970    assert_equal [], Gem::Specification.map(&:full_name)
1971
1972    default_gem_spec = new_default_spec("default", "2.0.0.0",
1973                                        nil, "default/gem.rb")
1974    spec_path = File.join(@default_spec_dir, default_gem_spec.spec_name)
1975    write_file(spec_path) do |file|
1976      file.print(default_gem_spec.to_ruby)
1977    end
1978    Gem::Specification.reset
1979    assert_equal ["default-2.0.0.0"], Gem::Specification.map(&:full_name)
1980  end
1981
1982  def util_setup_deps
1983    @gem = quick_spec "awesome", "1.0" do |awesome|
1984      awesome.add_runtime_dependency "bonobo", []
1985      awesome.add_development_dependency "monkey", []
1986    end
1987
1988    @bonobo = Gem::Dependency.new("bonobo", [])
1989    @monkey = Gem::Dependency.new("monkey", [], :development)
1990  end
1991
1992  def util_setup_validate
1993    Dir.chdir @tempdir do
1994      FileUtils.mkdir_p File.join("ext", "a")
1995      FileUtils.mkdir_p "lib"
1996      FileUtils.mkdir_p "test"
1997      FileUtils.mkdir_p "bin"
1998
1999      FileUtils.touch File.join("ext", "a", "extconf.rb")
2000      FileUtils.touch File.join("lib", "code.rb")
2001      FileUtils.touch File.join("test", "suite.rb")
2002
2003      File.open "bin/exec", "w", 0755 do |fp|
2004        fp.puts "#!#{Gem.ruby}"
2005      end
2006    end
2007  end
2008
2009  def with_syck
2010    begin
2011      require "yaml"
2012      old_engine = YAML::ENGINE.yamler
2013      verbose, $VERBOSE = $VERBOSE, nil
2014      YAML::ENGINE.yamler = 'syck'
2015      load 'rubygems/syck_hack.rb'
2016    rescue NameError
2017      # probably on 1.8, ignore
2018    ensure
2019      $VERBOSE = verbose
2020    end
2021
2022    yield
2023  ensure
2024    begin
2025      YAML::ENGINE.yamler = old_engine
2026      load 'rubygems/syck_hack.rb'
2027    rescue NameError
2028      # ignore
2029    end
2030  end
2031
2032  def with_psych
2033    begin
2034      require "yaml"
2035      old_engine = YAML::ENGINE.yamler
2036      YAML::ENGINE.yamler = 'psych'
2037      load 'rubygems/syck_hack.rb'
2038    rescue NameError
2039      # probably on 1.8, ignore
2040    end
2041
2042    yield
2043  ensure
2044    begin
2045      YAML::ENGINE.yamler = old_engine
2046      load 'rubygems/syck_hack.rb'
2047    rescue NameError
2048      # ignore
2049    end
2050  end
2051
2052  def silence_warnings
2053    old_verbose, $VERBOSE = $VERBOSE, false
2054    yield
2055  ensure
2056    $VERBOSE = old_verbose
2057  end
2058end
2059