2 # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
4 # See LICENSE.txt for permissions.
9 require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
10 require 'rubygems/specification'
12 class TestGemSpecification < RubyGemTestCase
14 LEGACY_YAML_SPEC = <<-EOF
15 --- !ruby/object:Gem::Specification
16 rubygems_version: "1.0"
18 version: !ruby/object:Gem::Version
20 date: 2004-03-28 15:37:49.828000 +02:00
22 summary: A Hash which automatically computes keys.
27 autorequire: keyedlist
33 LEGACY_RUBY_SPEC = <<-EOF
34 Gem::Specification.new do |s|
35 s.name = %q{keyedlist}
38 s.summary = %q{A Hash which automatically computes keys.}
39 s.files = ["lib/keyedlist.rb"]
40 s.require_paths = ["lib"]
41 s.autorequire = %q{keyedlist}
42 s.author = %q{Florian Gross}
43 s.email = %q{flgr@ccan.de}
50 @a1 = quick_gem 'a', '1' do |s|
52 s.extensions << 'ext/a/extconf.rb'
54 s.test_file = 'test/suite.rb'
55 s.requirements << 'A working computer'
56 s.rubyforge_project = 'example'
58 s.add_dependency 'rake', '> 0.4'
59 s.add_dependency 'jabber4r', '> 0.0.0'
60 s.add_dependency 'pqa', ['> 0.4', '<= 0.6']
63 s.files = %w[lib/code.rb]
66 @a2 = quick_gem 'a', '2' do |s|
67 s.files = %w[lib/code.rb]
70 FileUtils.mkdir_p File.join(@tempdir, 'bin')
71 File.open File.join(@tempdir, 'bin', 'exec'), 'w' do |fp|
72 fp.puts "#!#{Gem.ruby}"
76 def test_self_attribute_names
99 required_rubygems_version
104 specification_version
110 actual_value = Gem::Specification.attribute_names.map { |a| a.to_s }.sort
112 assert_equal expected_value, actual_value
116 spec = File.join @gemhome, 'specifications', "#{@a2.full_name}.gemspec"
117 gs = Gem::Specification.load spec
122 def test_self_load_legacy_ruby
123 spec = eval LEGACY_RUBY_SPEC
124 assert_equal 'keyedlist', spec.name
125 assert_equal '0.4.0', spec.version.to_s
126 assert_equal true, spec.has_rdoc?
127 assert_equal Gem::Specification::TODAY, spec.date
128 assert spec.required_ruby_version.satisfied_by?(Gem::Version.new('1'))
129 assert_equal false, spec.has_unit_tests?
132 def test_self_load_legacy_yaml
133 s = YAML.load StringIO.new(LEGACY_YAML_SPEC)
134 assert_equal 'keyedlist', s.name
135 assert_equal '0.4.0', s.version.to_s
136 assert_equal true, s.has_rdoc?
137 #assert_equal Date.today, s.date
138 #assert s.required_ruby_version.satisfied_by?(Gem::Version.new('1'))
139 assert_equal false, s.has_unit_tests?
142 def test_self_normalize_yaml_input_with_183_yaml
143 input = "!ruby/object:Gem::Specification "
144 assert_equal "--- #{input}", Gem::Specification.normalize_yaml_input(input)
147 def test_self_normalize_yaml_input_with_non_183_yaml
148 input = "--- !ruby/object:Gem::Specification "
149 assert_equal input, Gem::Specification.normalize_yaml_input(input)
152 def test_self_normalize_yaml_input_with_183_io
153 input = "!ruby/object:Gem::Specification "
154 assert_equal "--- #{input}",
155 Gem::Specification.normalize_yaml_input(StringIO.new(input))
158 def test_self_normalize_yaml_input_with_non_183_io
159 input = "--- !ruby/object:Gem::Specification "
161 Gem::Specification.normalize_yaml_input(StringIO.new(input))
165 spec = Gem::Specification.new do |s|
170 assert_equal "blah", spec.name
171 assert_equal "1.3.5", spec.version.to_s
172 assert_equal Gem::Platform::RUBY, spec.platform
173 assert_equal nil, spec.summary
174 assert_equal [], spec.files
176 assert_equal [], spec.test_files
177 assert_equal [], spec.rdoc_options
178 assert_equal [], spec.extra_rdoc_files
179 assert_equal [], spec.executables
180 assert_equal [], spec.extensions
181 assert_equal [], spec.requirements
182 assert_equal [], spec.dependencies
183 assert_equal 'bin', spec.bindir
184 assert_equal false, spec.has_rdoc
185 assert_equal false, spec.has_rdoc?
186 assert_equal '>= 0', spec.required_ruby_version.to_s
187 assert_equal '>= 0', spec.required_rubygems_version.to_s
190 def test_initialize_future
191 version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + 1
192 spec = Gem::Specification.new do |s|
196 s.specification_version = version
198 s.new_unknown_attribute = "a value"
201 assert_equal "blah", spec.name
202 assert_equal "1.3.5", spec.version.to_s
206 @a2.platform = Gem::Platform.local
207 @a2.instance_variable_set :@original_platform, 'old_platform'
209 data = Marshal.dump @a2
211 same_spec = Marshal.load data
213 assert_equal 'old_platform', same_spec.original_platform
216 def test_add_dependency_with_explicit_type
217 gem = quick_gem "awesome", "1.0" do |awesome|
218 awesome.add_development_dependency "monkey"
221 monkey = gem.dependencies.detect { |d| d.name == "monkey" }
222 assert_equal(:development, monkey.type)
226 assert_equal 'A User', @a1.author
230 assert_equal ['A User'], @a1.authors
233 def test_bindir_equals
236 assert_equal 'apps', @a1.bindir
239 def test_bindir_equals_nil
241 @a2.executable = 'app'
243 assert_equal nil, @a2.bindir
244 assert_equal %w[lib/code.rb app], @a2.files
248 assert_equal Gem::Specification::TODAY, @a1.date
251 def test_date_equals_date
252 @a1.date = Date.new(2003, 9, 17)
253 assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
256 def test_date_equals_string
257 @a1.date = '2003-09-17'
258 assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
261 def test_date_equals_time
262 @a1.date = Time.local(2003, 9, 17, 0,0,0)
263 assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
266 def test_date_equals_time_local
268 @a1.date = Time.local(2003, 9, 17, 19,50,0)
269 assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
272 def test_date_equals_time_utc
274 @a1.date = Time.local(2003, 9, 17, 19,50,0)
275 assert_equal Time.local(2003, 9, 17, 0,0,0), @a1.date
278 def test_default_executable
279 assert_equal 'exec', @a1.default_executable
281 @a1.default_executable = nil
282 @a1.instance_variable_set :@executables, nil
283 assert_equal nil, @a1.default_executable
286 def test_dependencies
287 rake = Gem::Dependency.new 'rake', '> 0.4'
288 jabber = Gem::Dependency.new 'jabber4r', '> 0.0.0'
289 pqa = Gem::Dependency.new 'pqa', ['> 0.4', '<= 0.6']
291 assert_equal [rake, jabber, pqa], @a1.dependencies
294 def test_dependencies_scoped_by_type
295 gem = quick_gem "awesome", "1.0" do |awesome|
296 awesome.add_runtime_dependency "bonobo", []
297 awesome.add_development_dependency "monkey", []
300 bonobo = Gem::Dependency.new("bonobo", [])
301 monkey = Gem::Dependency.new("monkey", [], :development)
303 assert_equal([bonobo, monkey], gem.dependencies)
304 assert_equal([bonobo], gem.runtime_dependencies)
305 assert_equal([monkey], gem.development_dependencies)
309 assert_equal 'This is a test description', @a1.description
317 assert_equal g1.hash, g2.hash
318 assert_equal true, g1.eql?(g2)
322 assert_equal @a1, @a1
323 assert_equal @a1, @a1.dup
324 assert_not_equal @a1, @a2
325 assert_not_equal @a1, Object.new
328 # The cgikit specification was reported to be causing trouble in at least
329 # one version of RubyGems, so we test explicitly for it.
330 def test_equals2_cgikit
331 cgikit = Gem::Specification.new do |s|
334 s.date = %q{2004-03-13}
335 s.summary = %q{CGIKit is a componented-oriented web application } +
336 %q{framework like Apple Computers WebObjects. } +
337 %{This framework services Model-View-Controller architecture } +
338 %q{programming by components based on a HTML file, a definition } +
339 %q{file and a Ruby source. }
340 s.email = %q{info@spice-of-life.net}
341 s.homepage = %q{http://www.spice-of-life.net/download/cgikit/}
342 s.autorequire = %q{cgikit}
345 s.required_ruby_version = nil
347 s.files = ["lib/cgikit", "lib/cgikit.rb", "lib/cgikit/components", "..."]
350 assert_equal cgikit, cgikit
353 def test_equals2_default_executable
355 spec.default_executable = 'xx'
357 assert_not_equal @a1, spec
358 assert_not_equal spec, @a1
361 def test_equals2_extensions
363 spec.extensions = 'xx'
365 assert_not_equal @a1, spec
366 assert_not_equal spec, @a1
370 @a1.executable = 'app'
371 assert_equal %w[app], @a1.executables
374 def test_executable_equals
375 @a2.executable = 'app'
376 assert_equal 'app', @a2.executable
377 assert_equal %w[lib/code.rb bin/app], @a2.files
381 assert_equal ['ext/a/extconf.rb'], @a1.extensions
385 @a1.files = %w(files bin/common)
386 @a1.test_files = %w(test_files bin/common)
387 @a1.executables = %w(executables common)
388 @a1.extra_rdoc_files = %w(extra_rdoc_files bin/common)
389 @a1.extensions = %w(extensions bin/common)
399 assert_equal expected, @a1.files.sort
402 def test_files_duplicate
403 @a2.files = %w[a b c d b]
404 @a2.extra_rdoc_files = %w[x y z x]
407 assert_equal %w[a b c d x y z], @a2.files
408 assert_equal %w[x y z], @a2.extra_rdoc_files
411 def test_files_extra_rdoc_files
412 @a2.files = %w[a b c d]
413 @a2.extra_rdoc_files = %w[x y z]
415 assert_equal %w[a b c d x y z], @a2.files
418 def test_files_non_array
420 @a1.test_files = "TF"
421 @a1.executables = "X"
422 @a1.extra_rdoc_files = "ERF"
425 assert_equal %w[E ERF F TF bin/X], @a1.files.sort
428 def test_files_non_array_pathological
429 @a1.instance_variable_set :@files, "F"
430 @a1.instance_variable_set :@test_files, "TF"
431 @a1.instance_variable_set :@extra_rdoc_files, "ERF"
432 @a1.instance_variable_set :@extensions, "E"
433 @a1.instance_variable_set :@executables, "X"
435 assert_equal %w[E ERF F TF bin/X], @a1.files.sort
436 assert_kind_of Integer, @a1.hash
439 def test_full_gem_path
440 assert_equal File.join(@gemhome, 'gems', @a1.full_name),
443 @a1.original_platform = 'mswin32'
445 assert_equal File.join(@gemhome, 'gems', @a1.original_name),
449 def test_full_gem_path_double_slash
450 gemhome = @gemhome.sub(/\w\//, '\&/')
451 @a1.loaded_from = File.join gemhome, 'specifications',
452 "#{@a1.full_name}.gemspec"
454 assert_equal File.join(@gemhome, 'gems', @a1.full_name),
459 assert_equal 'a-1', @a1.full_name
461 @a1.platform = Gem::Platform.new ['universal', 'darwin', nil]
462 assert_equal 'a-1-universal-darwin', @a1.full_name
464 @a1.instance_variable_set :@new_platform, 'mswin32'
465 assert_equal 'a-1-mswin32', @a1.full_name, 'legacy'
467 return if win_platform?
469 @a1.platform = 'current'
470 assert_equal 'a-1-x86-darwin-8', @a1.full_name
473 def test_full_name_windows
475 'i386-mswin32' => 'a-1-x86-mswin32-60',
476 'i386-mswin32_80' => 'a-1-x86-mswin32-80',
477 'i386-mingw32' => 'a-1-x86-mingw32'
480 test_cases.each do |arch, expected|
482 @a1.platform = 'current'
483 assert_equal expected, @a1.full_name
488 assert_equal true, @a1.has_rdoc?
492 assert_equal @a1.hash, @a1.hash
493 assert_equal @a1.hash, @a1.dup.hash
494 assert_not_equal @a1.hash, @a2.hash
498 @a1.files = %w[lib/foo.rb Rakefile]
500 assert_equal %w[lib/foo.rb], @a1.lib_files
504 assert_equal 'a', @a1.name
507 def test_original_name
508 assert_equal 'a-1', @a1.full_name
510 @a1.platform = 'i386-linux'
511 @a1.instance_variable_set :@original_platform, 'i386-linux'
512 assert_equal 'a-1-i386-linux', @a1.original_name
516 assert_equal Gem::Platform::RUBY, @a1.platform
519 def test_platform_equals
521 assert_equal Gem::Platform::RUBY, @a1.platform
523 @a1.platform = Gem::Platform::RUBY
524 assert_equal Gem::Platform::RUBY, @a1.platform
527 'i386-mswin32' => ['x86', 'mswin32', '60'],
528 'i386-mswin32_80' => ['x86', 'mswin32', '80'],
529 'i386-mingw32' => ['x86', 'mingw32', nil ],
530 'x86-darwin8' => ['x86', 'darwin', '8' ],
533 test_cases.each do |arch, expected|
535 @a1.platform = Gem::Platform::CURRENT
536 assert_equal Gem::Platform.new(expected), @a1.platform
540 def test_platform_equals_current
541 @a1.platform = Gem::Platform::CURRENT
542 assert_equal Gem::Platform.local, @a1.platform
543 assert_equal Gem::Platform.local.to_s, @a1.original_platform
546 def test_platform_equals_legacy
547 @a1.platform = 'mswin32'
548 assert_equal Gem::Platform.new('x86-mswin32'), @a1.platform
550 @a1.platform = 'i586-linux'
551 assert_equal Gem::Platform.new('x86-linux'), @a1.platform
553 @a1.platform = 'powerpc-darwin'
554 assert_equal Gem::Platform.new('ppc-darwin'), @a1.platform
557 def test_require_paths
558 @a1.require_path = 'lib'
559 assert_equal %w[lib], @a1.require_paths
562 def test_requirements
563 assert_equal ['A working computer'], @a1.requirements
566 def test_runtime_dependencies_legacy
567 # legacy gems don't have a type
568 @a1.runtime_dependencies.each do |dep|
569 dep.instance_variable_set :@type, nil
572 expected = %w[rake jabber4r pqa]
574 assert_equal expected, @a1.runtime_dependencies.map { |d| d.name }
577 def test_spaceship_name
578 s1 = quick_gem 'a', '1'
579 s2 = quick_gem 'b', '1'
581 assert_equal(-1, (s1 <=> s2))
582 assert_equal( 0, (s1 <=> s1))
583 assert_equal( 1, (s2 <=> s1))
586 def test_spaceship_platform
587 s1 = quick_gem 'a', '1'
588 s2 = quick_gem 'a', '1' do |s|
589 s.platform = Gem::Platform.new 'x86-my_platform1'
592 assert_equal( -1, (s1 <=> s2))
593 assert_equal( 0, (s1 <=> s1))
594 assert_equal( 1, (s2 <=> s1))
597 def test_spaceship_version
598 s1 = quick_gem 'a', '1'
599 s2 = quick_gem 'a', '2'
601 assert_equal( -1, (s1 <=> s2))
602 assert_equal( 0, (s1 <=> s1))
603 assert_equal( 1, (s2 <=> s1))
607 assert_equal 'this is a summary', @a1.summary
611 @a1.test_file = 'test/suite.rb'
612 assert_equal ['test/suite.rb'], @a1.test_files
616 @a2.add_runtime_dependency 'b', '1'
617 @a2.dependencies.first.instance_variable_set :@type, nil
618 @a2.required_rubygems_version = Gem::Requirement.new '> 0'
620 ruby_code = @a2.to_ruby
622 expected = "Gem::Specification.new do |s|
626 s.required_rubygems_version = Gem::Requirement.new(\"> 0\") if s.respond_to? :required_rubygems_version=
627 s.authors = [\"A User\"]
628 s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}}
629 s.description = %q{This is a test description}
630 s.email = %q{example@example.com}
631 s.files = [\"lib/code.rb\"]
633 s.homepage = %q{http://example.com}
634 s.require_paths = [\"lib\"]
635 s.rubygems_version = %q{#{Gem::RubyGemsVersion}}
636 s.summary = %q{this is a summary}
638 if s.respond_to? :specification_version then
639 current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
640 s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
642 if current_version >= 3 then
643 s.add_runtime_dependency(%q<b>, [\"= 1\"])
645 s.add_dependency(%q<b>, [\"= 1\"])
648 s.add_dependency(%q<b>, [\"= 1\"])
653 assert_equal expected, ruby_code
655 same_spec = eval ruby_code
657 assert_equal @a2, same_spec
660 def test_to_ruby_fancy
661 @a1.platform = Gem::Platform.local
662 ruby_code = @a1.to_ruby
664 local = Gem::Platform.local
665 expected_platform = "[#{local.cpu.inspect}, #{local.os.inspect}, #{local.version.inspect}]"
667 expected = "Gem::Specification.new do |s|
670 s.platform = Gem::Platform.new(#{expected_platform})
672 s.required_rubygems_version = Gem::Requirement.new(\">= 0\") if s.respond_to? :required_rubygems_version=
673 s.authors = [\"A User\"]
674 s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}}
675 s.default_executable = %q{exec}
676 s.description = %q{This is a test description}
677 s.email = %q{example@example.com}
678 s.executables = [\"exec\"]
679 s.extensions = [\"ext/a/extconf.rb\"]
680 s.files = [\"lib/code.rb\", \"test/suite.rb\", \"bin/exec\", \"ext/a/extconf.rb\"]
681 s.has_rdoc = %q{true}
682 s.homepage = %q{http://example.com}
683 s.require_paths = [\"lib\"]
684 s.requirements = [\"A working computer\"]
685 s.rubyforge_project = %q{example}
686 s.rubygems_version = %q{#{Gem::RubyGemsVersion}}
687 s.summary = %q{this is a summary}
688 s.test_files = [\"test/suite.rb\"]
690 if s.respond_to? :specification_version then
691 current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
692 s.specification_version = 3
694 if current_version >= 3 then
695 s.add_runtime_dependency(%q<rake>, [\"> 0.4\"])
696 s.add_runtime_dependency(%q<jabber4r>, [\"> 0.0.0\"])
697 s.add_runtime_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
699 s.add_dependency(%q<rake>, [\"> 0.4\"])
700 s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
701 s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
704 s.add_dependency(%q<rake>, [\"> 0.4\"])
705 s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
706 s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
711 assert_equal expected, ruby_code
713 same_spec = eval ruby_code
715 assert_equal @a1, same_spec
718 def test_to_ruby_legacy
719 gemspec1 = eval LEGACY_RUBY_SPEC
720 ruby_code = gemspec1.to_ruby
721 gemspec2 = eval ruby_code
723 assert_equal gemspec1, gemspec2
726 def test_to_ruby_platform
727 @a2.platform = Gem::Platform.local
728 @a2.instance_variable_set :@original_platform, 'old_platform'
730 ruby_code = @a2.to_ruby
732 same_spec = eval ruby_code
734 assert_equal 'old_platform', same_spec.original_platform
738 yaml_str = @a1.to_yaml
739 same_spec = YAML.load(yaml_str)
741 assert_equal @a1, same_spec
744 def test_to_yaml_fancy
745 @a1.platform = Gem::Platform.local
746 yaml_str = @a1.to_yaml
748 same_spec = YAML.load(yaml_str)
750 assert_equal Gem::Platform.local, same_spec.platform
752 assert_equal @a1, same_spec
755 def test_to_yaml_platform_empty_string
756 @a1.instance_variable_set :@original_platform, ''
758 assert_match %r|^platform: ruby$|, @a1.to_yaml
761 def test_to_yaml_platform_legacy
762 @a1.platform = 'powerpc-darwin7.9.0'
763 @a1.instance_variable_set :@original_platform, 'powerpc-darwin7.9.0'
765 yaml_str = @a1.to_yaml
767 same_spec = YAML.load(yaml_str)
769 assert_equal Gem::Platform.new('powerpc-darwin7'), same_spec.platform
770 assert_equal 'powerpc-darwin7.9.0', same_spec.original_platform
773 def test_to_yaml_platform_nil
774 @a1.instance_variable_set :@original_platform, nil
776 assert_match %r|^platform: ruby$|, @a1.to_yaml
780 Dir.chdir @tempdir do
785 def test_validate_authors
786 Dir.chdir @tempdir do
793 assert_equal "WARNING: no author specified\n", @ui.error, 'error'
795 @a1.authors = [Object.new]
797 e = assert_raise Gem::InvalidSpecificationException do
801 assert_equal 'authors must be Array of Strings', e.message
805 def test_validate_autorequire
806 Dir.chdir @tempdir do
807 @a1.autorequire = 'code'
813 assert_equal "WARNING: deprecated autorequire specified\n",
818 def test_validate_email
819 Dir.chdir @tempdir do
826 assert_equal "WARNING: no email specified\n", @ui.error, 'error'
830 def test_validate_empty
831 e = assert_raise Gem::InvalidSpecificationException do
832 Gem::Specification.new.validate
835 assert_equal 'missing value for attribute name', e.message
838 def test_validate_executables
839 FileUtils.mkdir_p File.join(@tempdir, 'bin')
840 File.open File.join(@tempdir, 'bin', 'exec'), 'w' do end
843 Dir.chdir @tempdir do
848 assert_equal '', @ui.output, 'output'
849 assert_equal "WARNING: bin/exec is missing #! line\n", @ui.error, 'error'
852 def test_validate_empty_require_paths
853 @a1.require_paths = []
854 e = assert_raise Gem::InvalidSpecificationException do
858 assert_equal 'specification must have at least one require_path', e.message
861 def test_validate_homepage
862 Dir.chdir @tempdir do
869 assert_equal "WARNING: no homepage specified\n", @ui.error, 'error'
873 def test_validate_has_rdoc
874 Dir.chdir @tempdir do
881 assert_equal "WARNING: RDoc will not be generated (has_rdoc == false)\n",
886 def test_validate_platform_legacy
887 Dir.chdir @tempdir do
888 @a1.platform = 'mswin32'
891 @a1.platform = 'i586-linux'
894 @a1.platform = 'powerpc-darwin'
899 def test_validate_rubyforge_project
900 Dir.chdir @tempdir do
901 @a1.rubyforge_project = ''
907 assert_equal "WARNING: no rubyforge_project specified\n",
912 def test_validate_rubygems_version
913 @a1.rubygems_version = "3"
914 e = assert_raise Gem::InvalidSpecificationException do
918 assert_equal "expected RubyGems version #{Gem::RubyGemsVersion}, was 3",
922 def test_validate_summary
923 Dir.chdir @tempdir do
930 assert_equal "WARNING: no summary specified\n", @ui.error, 'error'
935 assert_equal Gem::Version.new('1'), @a1.version