diff options
Diffstat (limited to 'test')
62 files changed, 9079 insertions, 0 deletions
diff --git a/test/rubygems/bogussources.rb b/test/rubygems/bogussources.rb new file mode 100644 index 0000000000..008e3a1de5 --- /dev/null +++ b/test/rubygems/bogussources.rb @@ -0,0 +1,8 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'rubygems' +Gem.use_paths("test/mock/gems") diff --git a/test/rubygems/data/gem-private_key.pem b/test/rubygems/data/gem-private_key.pem new file mode 100644 index 0000000000..3e4be4cd9a --- /dev/null +++ b/test/rubygems/data/gem-private_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAz0tTOtsJuHDKAEXrQx0f6DUEzBEUTSLR1fk0iEHsY9rDCQxm +sw5Bf2UnVhdD03B4/XzIK+pat2CMQc37/vLIBuVgS7g/fzatGiM0m5rAHtycr0XU +8Ek6zjx4iSv70OLjybY+/utHCEc838awGDMCFR21jYxgATPVwqAIyasvwbKh/Vhw +uErFPqT9G8BKTHsaX+H+ADIRH001OmWkjB6EyjF05114kNMa0+2C7daV9hoBL3md +hCt6zOGcapl/9LkGxhcNEUB/So16V1ZQldg9macGyWktyNTSfctlF+f8okAmicG3 +XIwaW8UTmjFCmvDs/h1R/uKpe2IOHz87n29d2QIDAQABAoIBAQCR6n/nyg+JmTtX +/d+hGns/RTLfQpZ7xarXZ9gmoeD4WSE42VXhbIOGXXnXDAFecKl6Jb/xycGZm4if +OZPM3rEWyZeDNWrc7WvkHiwF7GSYVMqmRg2iJqoSSla+mAtl+pBFiNfHMW6K0Tp0 +erOyFRW+L2+A9/MMZaRun6AP9URkn0jz2kwmMFf+6szmzVn6fPFzZDRI+hEeaDmi +LBzSrfrddrIBX+xGEoBj6RmfnKBCSUVSSxOauYjd4mVjVYxvMH4SV1hXDUS5GPl5 +MbCiBb7bpNIg/8ljMoRrQiqk0XwwS7MaCqPtMhUtpSmC/zSjAfmoN7AOc/Xh69cQ +OCMNZH9BAoGBAPBlsuuU6fg0gVTKDdR12jHx03uRRt8/nPxHnpJkZCIh9XKh1LtY +bkumi9HZpp3mzDiaGg/rwfCwNckKx8NLhICLgkric6ClrKftxTu6C8tBAb5YDi6u +74KYnV8lMY/unzBtIloPgM3uluS292POmrWZpKwhvHLD71MewzMor5HFAoGBANy/ +mwsBs8i3Gzk8Twjq8effhPpE7kpxhC7bhwmjX3q41EjQWDT8M6xb1P9dRSsCIebi +kqP1yhl27dJpA8r5WqE/z89xhBvObAGRv41eXxOI0LaH2k5lJQrUeSC+51dy+BEB +T3GXD4C5ezZHQ8Wz/oL73uikrfhD+AqOZT2YbMEFAoGBAJvWEWpOGm3f+4bvhI+Z +5lxCG4oa3wqRvj58XvsfQRovUWGCLtlTtgwsZq8enLf3iaOXohV4Czzvva4Z4u1i +4v5BcbEBo1scixRBOn5BWKvl9C9j/a2dkX3jWQD4p2xaj69gz8f6DNFyPTb+tNhq +cjgO5YUASZ1MDrSfWIKteULRAoGAZkZv8x2KyofrmQ0UITGZerDYz4t4TA1kDMGx +QwnqhtVzpXjCJWpkFotFmDsCfPaz9mErR8PtKvcrIL1/AF+fWe5Sve3+I1P0PpXk +hf8fVdGhwbAXuRKrouTmagGI9b9Sp65PvHUcvasyJufFwqeuV8mScX87CzeSiHGI +/ozMdnECgYEAq4+losrhe0DEmiC9zVPvwRXjbSixDsSJxHfOcqIsZqhUgBiZ4TJD +SrkuukrMZib6BAD+PtCJS1TBbJyyvL3QecizhHSIh3ZnT0HnaRPatLEYmU65+3kE +kTqL4ik92bJnnWowy677sydl1lzBJDVa9ZlTs7BFSd8y/0DZaUxGg2I= +-----END RSA PRIVATE KEY----- diff --git a/test/rubygems/data/gem-public_cert.pem b/test/rubygems/data/gem-public_cert.pem new file mode 100644 index 0000000000..885bf7f369 --- /dev/null +++ b/test/rubygems/data/gem-public_cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMREwDwYDVQQDDAhydWJ5 +Z2VtczEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxEzARBgoJkiaJk/IsZAEZFgNj +b20wHhcNMDcwODAyMDMyNTQyWhcNMDgwODAxMDMyNTQyWjBBMREwDwYDVQQDDAhy +dWJ5Z2VtczEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxEzARBgoJkiaJk/IsZAEZ +FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPS1M62wm4cMoA +RetDHR/oNQTMERRNItHV+TSIQexj2sMJDGazDkF/ZSdWF0PTcHj9fMgr6lq3YIxB +zfv+8sgG5WBLuD9/Nq0aIzSbmsAe3JyvRdTwSTrOPHiJK/vQ4uPJtj7+60cIRzzf +xrAYMwIVHbWNjGABM9XCoAjJqy/BsqH9WHC4SsU+pP0bwEpMexpf4f4AMhEfTTU6 +ZaSMHoTKMXTnXXiQ0xrT7YLt1pX2GgEveZ2EK3rM4ZxqmX/0uQbGFw0RQH9KjXpX +VlCV2D2ZpwbJaS3I1NJ9y2UX5/yiQCaJwbdcjBpbxROaMUKa8Oz+HVH+4ql7Yg4f +Pzufb13ZAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW +BBRYTAoj4cn8CWZMHFnHGQgoO5jyFTANBgkqhkiG9w0BAQUFAAOCAQEATRrJC05l +dOmx67Sy3bU+AVXkOr7B9nn2Myqo9uSIAncPoElN6aHr/Q8wOOjtok4r0JcHPe1e +eotDCZUE1Jkl13Tpv26rOfOOUHtGlyAIAtpsUGOraaJkSut4WKLr1/KckyAAEtgP +c13A0s0mEiWFRuYxIdEi54561pTT2qQBE/DUPGoYD5rUg9XYAlSovMMwG99Oca7L +cI6vCymr1bzzddExoywBNOy0fbBT62I3ICBGbH5yOVVKVmlxeo2Zp10FCj0kDrnq +OuMJSDr5I2XPYqoC+W4YSbwn55o2jGIUX1lOq2Hvj4tFgSxlnJZn0tUhBfR3gSOn +IFnrqu8PlZsLFw== +-----END CERTIFICATE----- diff --git a/test/rubygems/fake_certlib/openssl.rb b/test/rubygems/fake_certlib/openssl.rb new file mode 100644 index 0000000000..948110f078 --- /dev/null +++ b/test/rubygems/fake_certlib/openssl.rb @@ -0,0 +1,7 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +fail LoadError, "no such file to load -- openssl" diff --git a/test/rubygems/functional.rb b/test/rubygems/functional.rb new file mode 100644 index 0000000000..4838167324 --- /dev/null +++ b/test/rubygems/functional.rb @@ -0,0 +1,95 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require 'rubygems' +require 'test/insure_session' +require 'rubygems/format' +require 'rubygems/command_manager' + +class FunctionalTest < Test::Unit::TestCase + def setup + @gem_path = File.expand_path("bin/gem") + lib_path = File.expand_path("lib") + @ruby_options = "-I#{lib_path} -I." + @verbose = false + end + + def test_gem_help_options + gem_nossl 'help options' + assert_match(/Usage:/, @out, @err) + assert_status + end + + def test_gem_help_commands + gem_nossl 'help commands' + assert_match(/gem install/, @out) + assert_status + end + + def test_gem_no_args_shows_help + gem_nossl + assert_match(/Usage:/, @out) + assert_status 1 + end + + # This test is disabled because of the insanely long time it takes + # to time out. + def xtest_bogus_source_hoses_up_remote_install_but_gem_command_gives_decent_error_message + @ruby_options << " -rtest/bogussources" + gem_nossl "install asdf --remote" + assert_match(/error/im, @err) + assert_status 1 + end + + def test_all_command_helps + mgr = Gem::CommandManager.new + mgr.command_names.each do |cmdname| + gem_nossl "help #{cmdname}" + assert_match(/Usage: gem #{cmdname}/, @out, + "should see help for #{cmdname}") + end + end + + # :section: Help Methods + + # Run a gem command without the SSL library. + def gem_nossl(options="") + old_options = @ruby_options.dup + @ruby_options << " -Itest/fake_certlib" + gem(options) + ensure + @ruby_options = old_options + end + + # Run a gem command with the SSL library. + def gem_withssl(options="") + gem(options) + end + + # Run a gem command for the functional test. + def gem(options="") + shell = Session::Shell.new + options = options + " --config-file missing_file" if options !~ /--config-file/ + command = "#{Gem.ruby} #{@ruby_options} #{@gem_path} #{options}" + puts "\n\nCOMMAND: [#{command}]" if @verbose + @out, @err = shell.execute command + @status = shell.exit_status + puts "STATUS: [#{@status}]" if @verbose + puts "OUTPUT: [#{@out}]" if @verbose + puts "ERROR: [#{@err}]" if @verbose + puts "PWD: [#{Dir.pwd}]" if @verbose + shell.close + end + + private + + def assert_status(expected_status=0) + assert_equal expected_status, @status + end + +end diff --git a/test/rubygems/gemutilities.rb b/test/rubygems/gemutilities.rb new file mode 100644 index 0000000000..96711be485 --- /dev/null +++ b/test/rubygems/gemutilities.rb @@ -0,0 +1,295 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +at_exit { $SAFE = 1 } + +require 'fileutils' +require 'test/unit/testcase' +require 'tmpdir' +require 'uri' +require 'rubygems/gem_open_uri' +require 'rubygems/source_info_cache' + +require File.join(File.expand_path(File.dirname(__FILE__)), 'mockgemui') + +module Gem + def self.source_index=(si) + @@source_index = si + end +end + +class FakeFetcher + + attr_reader :data + attr_accessor :uri + attr_accessor :paths + + def initialize + @data = {} + @paths = [] + @uri = nil + end + + def fetch_path(path) + path = path.to_s + @paths << path + raise ArgumentError, 'need full URI' unless path =~ %r'^http://' + data = @data[path] + raise OpenURI::HTTPError.new("no data for #{path}", nil) if data.nil? + data.respond_to?(:call) ? data.call : data + end + + def fetch_size(path) + path = path.to_s + @paths << path + raise ArgumentError, 'need full URI' unless path =~ %r'^http://' + data = @data[path] + raise OpenURI::HTTPError.new("no data for #{path}", nil) if data.nil? + data.respond_to?(:call) ? data.call : data.length + end + +end + +class RubyGemTestCase < Test::Unit::TestCase + + include Gem::DefaultUserInteraction + + undef_method :default_test + + def setup + super + + @ui = MockGemUi.new + tmpdir = nil + Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end # HACK OSX /private/tmp + @tempdir = File.join tmpdir, "test_rubygems_#{$$}" + @tempdir.untaint + @gemhome = File.join @tempdir, "gemhome" + @gemcache = File.join(@gemhome, "source_cache") + @usrcache = File.join(@gemhome, ".gem", "user_cache") + + FileUtils.mkdir_p @gemhome + + ENV['GEMCACHE'] = @usrcache + Gem.use_paths(@gemhome) + Gem.loaded_specs.clear + + Gem.configuration.verbose = true + Gem.configuration.update_sources = true + + @gem_repo = "http://gems.example.com" + Gem.sources.replace [@gem_repo] + + @orig_arch = Config::CONFIG['arch'] + + if win_platform? + util_set_arch 'i386-mswin32' + else + util_set_arch 'i686-darwin8.10.1' + end + + @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" + end + + def teardown + Config::CONFIG['arch'] = @orig_arch + + if defined? Gem::RemoteFetcher then + Gem::RemoteFetcher.instance_variable_set :@fetcher, nil + end + + FileUtils.rm_rf @tempdir + + ENV.delete 'GEMCACHE' + ENV.delete 'GEM_HOME' + ENV.delete 'GEM_PATH' + + Gem.clear_paths + Gem::SourceInfoCache.instance_variable_set :@cache, nil + end + + def install_gem gem + require 'rubygems/installer' + + use_ui MockGemUi.new do + Dir.chdir @tempdir do + Gem::Builder.new(gem).build + end + end + + gem = File.join(@tempdir, "#{gem.full_name}.gem").untaint + Gem::Installer.new(gem).install + end + + def prep_cache_files(lc) + [ [lc.system_cache_file, 'sys'], + [lc.user_cache_file, 'usr'], + ].each do |fn, data| + FileUtils.mkdir_p File.dirname(fn).untaint + open(fn.dup.untaint, "wb") { |f| f.write(Marshal.dump({'key' => data})) } + end + end + + def read_cache(fn) + open(fn.dup.untaint) { |f| Marshal.load f.read } + end + + def write_file(path) + path = File.join(@gemhome, path) + dir = File.dirname path + FileUtils.mkdir_p dir + File.open(path, "w") { |io| + yield(io) + } + path + end + + def quick_gem(gemname, version='0.0.2') + require 'rubygems/specification' + + spec = Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = gemname + s.version = version + s.author = 'A User' + s.email = 'example@example.com' + s.homepage = 'http://example.com' + s.has_rdoc = true + s.summary = "this is a summary" + s.description = "This is a test description" + yield(s) if block_given? + end + + path = File.join "specifications", "#{spec.full_name}.gemspec" + written_path = write_file path do |io| + io.write(spec.to_ruby) + end + + spec.loaded_from = written_path + + return spec + end + + def util_build_gem(spec) + dir = File.join(@gemhome, 'gems', spec.full_name) + FileUtils.mkdir_p dir + + Dir.chdir dir do + spec.files.each do |file| + next if File.exist? file + FileUtils.mkdir_p File.dirname(file) + File.open file, 'w' do |fp| fp.puts "# #{file}" end + end + + use_ui MockGemUi.new do + Gem::Builder.new(spec).build + end + + FileUtils.mv "#{spec.full_name}.gem", File.join(@gemhome, 'cache') + end + end + + def util_make_gems + spec = proc do |s| + s.files = %w[lib/code.rb] + s.require_paths = %w[lib] + end + + @a0_0_1 = quick_gem('a', '0.0.1', &spec) + @a0_0_2 = quick_gem('a', '0.0.2', &spec) + @b0_0_2 = quick_gem('b', '0.0.2', &spec) + @c1_2 = quick_gem('c', '1.2', &spec) + + write_file File.join(*%w[gems a-0.0.1 lib code.rb]) do end + write_file File.join(*%w[gems a-0.0.2 lib code.rb]) do end + write_file File.join(*%w[gems b-0.0.2 lib code.rb]) do end + write_file File.join(*%w[gems c-1.2 lib code.rb]) do end + + [@a0_0_1, @a0_0_2, @b0_0_2, @c1_2].each { |spec| util_build_gem spec } + + Gem.source_index = nil + end + + ## + # Set the platform to +cpu+ and +os+ + + def util_set_arch(arch) + Config::CONFIG['arch'] = arch + platform = Gem::Platform.new arch + + Gem.instance_variable_set :@platforms, nil + Gem::Platform.instance_variable_set :@local, nil + + platform + end + + def util_setup_fake_fetcher + require 'zlib' + require 'socket' + require 'rubygems/remote_fetcher' + + @uri = URI.parse @gem_repo + @fetcher = FakeFetcher.new + @fetcher.uri = @uri + + @gem1 = quick_gem 'gem_one' do |gem| + gem.files = %w[Rakefile lib/gem_one.rb] + end + + @gem2 = quick_gem 'gem_two' do |gem| + gem.files = %w[Rakefile lib/gem_two.rb] + end + + @gem3 = quick_gem 'gem_three' do |gem| # missing gem + gem.files = %w[Rakefile lib/gem_three.rb] + end + + # this gem has a higher version and longer name than the gem we want + @gem4 = quick_gem 'gem_one_evil', '666' do |gem| + gem.files = %w[Rakefile lib/gem_one.rb] + end + + @all_gems = [@gem1, @gem2, @gem3, @gem4].sort + @all_gem_names = @all_gems.map { |gem| gem.full_name } + + gem_names = [@gem1.full_name, @gem2.full_name, @gem4.full_name] + @gem_names = gem_names.sort.join("\n") + + @source_index = Gem::SourceIndex.new @gem1.full_name => @gem1, + @gem2.full_name => @gem2, + @gem4.full_name => @gem4 + + Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher + end + + def util_setup_source_info_cache(*specs) + require 'rubygems/source_info_cache_entry' + + specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten] + si = Gem::SourceIndex.new specs + + sice = Gem::SourceInfoCacheEntry.new si, 0 + sic = Gem::SourceInfoCache.new + sic.set_cache_data( { @gem_repo => sice } ) + Gem::SourceInfoCache.instance_variable_set :@cache, sic + si + end + + def util_zip(data) + Zlib::Deflate.deflate data + end + + def self.win_platform? + Gem.win_platform? + end + + def win_platform? + Gem.win_platform? + end + +end + diff --git a/test/rubygems/insure_session.rb b/test/rubygems/insure_session.rb new file mode 100644 index 0000000000..e56f9abcb8 --- /dev/null +++ b/test/rubygems/insure_session.rb @@ -0,0 +1,51 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + + +require 'rubygems' + +def install_session + path_to_gem = File.join("redist", "session.gem") + begin + Gem::Installer.new(path_to_gem).install + rescue Errno::EACCES => ex + puts + puts "*****************************************************************" + puts "Unable to install Gem 'Session'." + puts "Reason: #{ex.message}" + puts "Try running:" + puts + puts " gem -Li #{path_to_gem}" + puts + puts "with the appropriate admin privileges." + puts "*****************************************************************" + puts + exit + end + gem 'session' +end + +begin + require 'session' +rescue LoadError => e + puts + puts "Required Gem 'Session' missing." + puts "We can attempt to install from the RubyGems Distribution," + puts "but installation may require admin privileges on your system." + puts + print "Install now from RubyGems distribution? [Yn]" + answer = gets + if(answer =~ /^y/i || answer =~ /^[^a-zA-Z0-9]$/) then + install_session + puts + puts "Retry running the functional tests." + exit(0) + else + puts "Test cancelled...quitting" + exit(1) + end +end diff --git a/test/rubygems/mockgemui.rb b/test/rubygems/mockgemui.rb new file mode 100644 index 0000000000..d9bc2a8134 --- /dev/null +++ b/test/rubygems/mockgemui.rb @@ -0,0 +1,51 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + + +require 'stringio' +require 'rubygems/user_interaction' + +class MockGemUi < Gem::StreamUI + class TermError < RuntimeError; end + + def initialize(input="") + super(StringIO.new(input), StringIO.new, StringIO.new) + @terminated = false + @banged = false + end + + def input + @ins.string + end + + def output + @outs.string + end + + def error + @errs.string + end + + def banged? + @banged + end + + def terminated? + @terminated + end + + def terminate_interaction!(status=1) + @terminated = true + @banged = true + fail TermError + end + + def terminate_interaction(status=0) + @terminated = true + fail TermError + end +end diff --git a/test/rubygems/simple_gem.rb b/test/rubygems/simple_gem.rb new file mode 100644 index 0000000000..a6f14bc3c7 --- /dev/null +++ b/test/rubygems/simple_gem.rb @@ -0,0 +1,72 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + + SIMPLE_GEM = <<-GEMDATA + MD5SUM = "e3701f9db765a2358aef94c40ded71c8" + if $0 == __FILE__ + require 'optparse' + + options = {} + ARGV.options do |opts| + opts.on_tail("--help", "show this message") {puts opts; exit} + opts.on('--dir=DIRNAME', "Installation directory for the Gem") {|options[:directory]|} + opts.on('--force', "Force Gem to intall, bypassing dependency checks") {|options[:force]|} + opts.on('--gen-rdoc', "Generate RDoc documentation for the Gem") {|options[:gen_rdoc]|} + opts.parse! + end + + require 'rubygems' + @directory = options[:directory] || Gem.dir + @force = options[:force] + + gem = Gem::Installer.new(__FILE__).install(@force, @directory) + if options[:gen_rdoc] + Gem::DocManager.new(gem).generate_rdoc + end +end + +__END__ +--- !ruby/object:Gem::Specification +rubygems_version: "1.0" +name: testing +version: !ruby/object:Gem::Version + version: 1.2.3 +date: 2004-03-18 22:01:52.859121 -05:00 +platform: +summary: This exercise the gem testing stuff. +require_paths: + - lib +files: + - lib/foo.rb + - lib/test + - lib/test.rb + - lib/test/wow.rb +autorequire: test +test_suite_file: foo +requirements: + - a computer processor +--- +- + size: 109 + mode: 420 + path: lib/foo.rb +- + size: 0 + mode: 420 + path: lib/test.rb +- + size: 15 + mode: 420 + path: lib/test/wow.rb +--- +eJwVjDEKgDAUQ/eeIpsKguhY3ARPoHMp9quF0mL7e39/h5DwQpLpqz4TOqbC +U42eO6WuYEvBntIhECuaaX1KqXXLmy2kAEc32szExK+PjyBAlpTZyK0N/Twu +g1CKTjX9BGAj1w== +--- +eJwDAAAAAAE= +--- +eJwrKC0pVlAvzy9XyE3MU+cCACwiBP4= + GEMDATA diff --git a/test/rubygems/test_config.rb b/test/rubygems/test_config.rb new file mode 100644 index 0000000000..89ac0e4462 --- /dev/null +++ b/test/rubygems/test_config.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rbconfig' +require 'rubygems' + +class TestConfig < RubyGemTestCase + + def test_gem_original_datadir + datadir = Config::CONFIG['datadir'] + assert_equal "#{datadir}/xyz", Config.gem_original_datadir('xyz') + end + + def test_datadir + datadir = Config::CONFIG['datadir'] + assert_equal "#{datadir}/xyz", Config.datadir('xyz') + end + +end + diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb new file mode 100644 index 0000000000..723b2559bc --- /dev/null +++ b/test/rubygems/test_gem.rb @@ -0,0 +1,367 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems' +require 'rubygems/gem_openssl' +require 'pathname' + +class TestGem < RubyGemTestCase + + def setup + super + + @additional = %w[a b].map { |d| File.join @tempdir, d } + @default_dir_re = %r|/ruby/gems/[0-9.]+| + end + + def test_self_all_load_paths + util_make_gems + + expected = [ + File.join(@tempdir, *%w[gemhome gems a-0.0.1 lib]), + File.join(@tempdir, *%w[gemhome gems a-0.0.2 lib]), + File.join(@tempdir, *%w[gemhome gems b-0.0.2 lib]), + File.join(@tempdir, *%w[gemhome gems c-1.2 lib]), + ] + + assert_equal expected, Gem.all_load_paths.sort + end + + def test_self_bindir + assert_equal File.join(@gemhome, 'bin'), Gem.bindir + assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Gem.dir) + assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Pathname.new(Gem.dir)) + end + + def test_self_bindir_default_dir + default = Gem.default_dir + assert_equal Config::CONFIG['bindir'], Gem.bindir(default) + assert_equal Config::CONFIG['bindir'], Gem.bindir(Pathname.new(default)) + end + + def test_self_clear_paths + Gem.dir + Gem.path + searcher = Gem.searcher + source_index = Gem.source_index + + Gem.clear_paths + + assert_equal nil, Gem.instance_variable_get(:@gem_home) + assert_equal nil, Gem.instance_variable_get(:@gem_path) + assert_not_equal searcher, Gem.searcher + assert_not_equal source_index, Gem.source_index + end + + def test_self_configuration + expected = Gem::ConfigFile.new [] + Gem.configuration = nil + + assert_equal expected, Gem.configuration + end + + def test_self_datadir + foo = nil + + Dir.chdir @tempdir do + FileUtils.mkdir_p 'data' + File.open File.join('data', 'foo.txt'), 'w' do |fp| + fp.puts 'blah' + end + + foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end + install_gem foo + end + + gem 'foo' + + expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo' + + assert_equal expected, Gem.datadir('foo') + end + + def test_self_datadir_nonexistent_package + assert_nil Gem.datadir('xyzzy') + end + + def test_self_default_dir + assert_match @default_dir_re, Gem.default_dir + end + + def test_self_default_sources + assert_equal %w[http://gems.rubyforge.org], Gem.default_sources + end + + def test_self_dir + assert_equal @gemhome, Gem.dir + + Gem::DIRECTORIES.each do |filename| + assert File.directory?(File.join(Gem.dir, filename)), + "expected #{filename} to exist" + end + end + + def test_self_ensure_gem_directories + FileUtils.rm_r @gemhome + Gem.use_paths @gemhome + + Gem.ensure_gem_subdirectories @gemhome + + assert File.directory?(File.join(@gemhome, "cache")) + end + + def test_self_ensure_gem_directories_missing_parents + gemdir = File.join @tempdir, 'a/b/c/gemdir' + FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil + assert !File.exist?(File.join(@tempdir, 'a')), + "manually remove #{File.join @tempdir, 'a'}, tests are broken" + Gem.use_paths gemdir + + Gem.ensure_gem_subdirectories gemdir + + assert File.directory?("#{gemdir}/cache") + end + + unless win_platform? then # only for FS that support write protection + def test_self_ensure_gem_directories_write_protected + gemdir = File.join @tempdir, "egd" + FileUtils.rm_r gemdir rescue nil + assert !File.exist?(gemdir), "manually remove #{gemdir}, tests are broken" + FileUtils.mkdir_p gemdir + FileUtils.chmod 0400, gemdir + Gem.use_paths gemdir + + Gem.ensure_gem_subdirectories gemdir + + assert !File.exist?("#{gemdir}/cache") + ensure + FileUtils.chmod 0600, gemdir + end + + def test_self_ensure_gem_directories_write_protected_parents + parent = File.join(@tempdir, "egd") + gemdir = "#{parent}/a/b/c" + + FileUtils.rm_r parent rescue nil + assert !File.exist?(parent), "manually remove #{parent}, tests are broken" + FileUtils.mkdir_p parent + FileUtils.chmod 0400, parent + Gem.use_paths(gemdir) + + Gem.ensure_gem_subdirectories gemdir + + assert !File.exist?("#{gemdir}/cache") + ensure + FileUtils.chmod 0600, parent + end + end + + def test_ensure_ssl_available + orig_Gem_ssl_available = Gem.ssl_available? + + Gem.ssl_available = true + assert_nothing_raised do Gem.ensure_ssl_available end + + Gem.ssl_available = false + e = assert_raise Gem::Exception do Gem.ensure_ssl_available end + assert_equal 'SSL is not installed on this system', e.message + ensure + Gem.ssl_available = orig_Gem_ssl_available + end + + def test_self_latest_load_paths + util_make_gems + + expected = [ + File.join(@tempdir, *%w[gemhome gems a-0.0.2 lib]), + File.join(@tempdir, *%w[gemhome gems b-0.0.2 lib]), + File.join(@tempdir, *%w[gemhome gems c-1.2 lib]), + ] + + assert_equal expected, Gem.latest_load_paths.sort + end + + def test_self_loaded_specs + foo = quick_gem 'foo' + install_gem foo + Gem.source_index = nil + + Gem.activate 'foo', false + + assert_equal true, Gem.loaded_specs.keys.include?('foo') + end + + def test_self_path + assert_equal [Gem.dir], Gem.path + end + + def test_self_path_ENV_PATH + Gem.clear_paths + util_ensure_gem_dirs + + ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR) + + assert_equal @additional, Gem.path[0,2] + assert_equal 3, Gem.path.size + assert_match Gem.dir, Gem.path.last + end + + def test_self_path_duplicate + Gem.clear_paths + util_ensure_gem_dirs + dirs = @additional + [@gemhome] + [File.join(@tempdir, 'a')] + + ENV['GEM_HOME'] = @gemhome + ENV['GEM_PATH'] = dirs.join File::PATH_SEPARATOR + + assert_equal @gemhome, Gem.dir + assert_equal @additional + [Gem.dir], Gem.path + end + + def test_self_path_overlap + Gem.clear_paths + + util_ensure_gem_dirs + ENV['GEM_HOME'] = @gemhome + ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR) + + assert_equal @gemhome, Gem.dir + assert_equal @additional + [Gem.dir], Gem.path + end + + def test_self_platforms + assert_equal [Gem::Platform::RUBY, Gem::Platform.local], Gem.platforms + end + + def test_self_prefix + file_name = File.expand_path __FILE__ + assert_equal File.dirname(File.dirname(file_name)), Gem.prefix + end + + def test_self_required_location + util_make_gems + + assert_equal File.join(@tempdir, *%w[gemhome gems c-1.2 lib code.rb]), + Gem.required_location("c", "code.rb") + assert_equal File.join(@tempdir, *%w[gemhome gems a-0.0.1 lib code.rb]), + Gem.required_location("a", "code.rb", "<0.0.2") + assert_equal File.join(@tempdir, *%w[gemhome gems a-0.0.2 lib code.rb]), + Gem.required_location("a", "code.rb", "=0.0.2") + end + + def test_self_searcher + assert_kind_of Gem::GemPathSearcher, Gem.searcher + end + + def test_self_source_index + assert_kind_of Gem::SourceIndex, Gem.source_index + end + + def test_self_sources + assert_equal %w[http://gems.example.com], Gem.sources + end + + def test_ssl_available_eh + orig_Gem_ssl_available = Gem.ssl_available? + + Gem.ssl_available = true + assert_equal true, Gem.ssl_available? + + Gem.ssl_available = false + assert_equal false, Gem.ssl_available? + ensure + Gem.ssl_available = orig_Gem_ssl_available + end + + def test_self_use_paths + util_ensure_gem_dirs + + Gem.use_paths @gemhome, @additional + + assert_equal @gemhome, Gem.dir + assert_equal @additional + [Gem.dir], Gem.path + end + + def test_self_user_home + if ENV['HOME'] then + assert_equal ENV['HOME'], Gem.user_home + else + assert true, 'count this test' + end + end + + def test_require_gem_autorequire + name = "AutorequireArray" + files = %w(a.rb b.rb) + gem = quick_gem(name) do |s| + s.files = files.map { |f| File.join("lib", f) } + s.autorequire = files + end + + fullname = gem.full_name + + write_file "gems/#{fullname}/lib/a.rb" do |io| + io.puts "$LOADED_A = true" + end + + write_file "gems/#{fullname}/lib/b.rb" do |io| + io.puts "$LOADED_B = true" + end + + Gem.source_index = nil + + old_loaded = $".dup + old_verbose = $VERBOSE + $VERBOSE = nil + require_gem name + $VERBOSE = old_verbose + new_loaded = $".dup + + if RUBY_VERSION > "1.9" then + files = files.map do |file| + File.join @gemhome, 'gems', gem.full_name, 'lib', file + end + end + + assert_equal files, (new_loaded - old_loaded) + assert defined?($LOADED_A) + assert defined?($LOADED_B) + end + + def test_require_gem_autorequire_string + name = "AutorequireString" + file = "c.rb" + gem = quick_gem(name) do |s| + s.files = File.join("lib", file) + s.autorequire = file + end + + fullname = gem.full_name + + write_file("gems/#{fullname}/lib/c.rb") do |io| + io.puts "$LOADED_C = true" + end + + old_loaded = $".dup + old_verbose = $VERBOSE + $VERBOSE = nil + require_gem name + $VERBOSE = old_verbose + new_loaded = $".dup + + if RUBY_VERSION > "1.9" then + file = File.join @gemhome, 'gems', gem.full_name, 'lib', file + end + + assert_equal(Array(file), (new_loaded - old_loaded)) + assert(defined? $LOADED_C) + end + + def util_ensure_gem_dirs + Gem.ensure_gem_subdirectories @gemhome + @additional.each do |dir| + Gem.ensure_gem_subdirectories @gemhome + end + end + +end + diff --git a/test/rubygems/test_gem_builder.rb b/test/rubygems/test_gem_builder.rb new file mode 100644 index 0000000000..31a0d71880 --- /dev/null +++ b/test/rubygems/test_gem_builder.rb @@ -0,0 +1,34 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/builder' + +class TestGemBuilder < RubyGemTestCase + + def test_build + builder = Gem::Builder.new quick_gem('a') + + use_ui @ui do + Dir.chdir @tempdir do + builder.build + end + end + + assert_match %r|Successfully built RubyGem\n Name: a|, @ui.output + end + + def test_build_validates + builder = Gem::Builder.new Gem::Specification.new + + assert_raises Gem::InvalidSpecificationException do + builder.build + end + end + +end + diff --git a/test/rubygems/test_gem_command.rb b/test/rubygems/test_gem_command.rb new file mode 100644 index 0000000000..9ed57b3692 --- /dev/null +++ b/test/rubygems/test_gem_command.rb @@ -0,0 +1,196 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/command' + +class Gem::Command + public :parser +end + +class TestGemCommand < RubyGemTestCase + + def setup + super + + @xopt = nil + + Gem::Command.common_options.clear + Gem::Command.common_options << [ + ['-x', '--exe', 'Execute'], lambda do |*a| + @xopt = true + end + ] + + @cmd_name = 'doit' + @cmd = Gem::Command.new @cmd_name, 'summary' + end + + def test_self_add_specific_extra_args + added_args = %w[--all] + @cmd.add_option '--all' do |v,o| end + + Gem::Command.add_specific_extra_args @cmd_name, added_args + + assert_equal added_args, Gem::Command.specific_extra_args(@cmd_name) + + h = @cmd.add_extra_args [] + + assert_equal added_args, h + end + + def test_self_add_specific_extra_args_unknown + added_args = %w[--definitely_not_there] + + Gem::Command.add_specific_extra_args @cmd_name, added_args + + assert_equal added_args, Gem::Command.specific_extra_args(@cmd_name) + + h = @cmd.add_extra_args [] + + assert_equal [], h + end + + def test_add_option_overlapping_common_and_local_options + @cmd.add_option('-x', '--zip', 'BAD!') do end + @cmd.add_option('-z', '--exe', 'BAD!') do end + @cmd.add_option('-x', '--exe', 'BAD!') do end + + assert_match %r|-x, --zip|, @cmd.parser.to_s + assert_match %r|-z, --exe|, @cmd.parser.to_s + assert_no_match %r|-x, --exe|, @cmd.parser.to_s + end + + def test_basic_accessors + assert_equal "doit", @cmd.command + assert_equal "gem doit", @cmd.program_name + assert_equal "summary", @cmd.summary + end + + def test_common_option_in_class + assert Array === Gem::Command.common_options + end + + def test_defaults + @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options| + options[:help] = value + end + + @cmd.defaults = { :help => true } + + @cmd.when_invoked do |options| + assert options[:help], "Help options should default true" + end + + use_ui @ui do + @cmd.invoke + end + + assert_match %r|Usage: gem doit|, @ui.output + end + + def test_invoke + done = false + @cmd.when_invoked { done = true } + + use_ui @ui do + @cmd.invoke + end + + assert done + end + + def test_invode_with_bad_options + use_ui @ui do + @cmd.when_invoked do true end + + ex = assert_raise(OptionParser::InvalidOption) do + @cmd.invoke('-zzz') + end + + assert_match(/invalid option:/, ex.message) + end + end + + def test_invoke_with_common_options + @cmd.when_invoked do true end + + use_ui @ui do + @cmd.invoke "-x" + end + + assert @xopt, "Should have done xopt" + end + + # Returning false from the command handler invokes the usage output. + def test_invoke_with_help + done = false + + use_ui @ui do + @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options| + options[:help] = true + done = true + end + + @cmd.invoke('--help') + + assert done + end + + assert_match(/Usage/, @ui.output) + assert_match(/gem doit/, @ui.output) + assert_match(/\[options\]/, @ui.output) + assert_match(/-h/, @ui.output) + assert_match(/--help \[COMMAND\]/, @ui.output) + assert_match(/Get help on COMMAND/, @ui.output) + assert_match(/-x/, @ui.output) + assert_match(/--exe/, @ui.output) + assert_match(/Execute/, @ui.output) + assert_match(/Common Options:/, @ui.output) + end + + def test_invoke_with_options + @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options| + options[:help] = true + end + + @cmd.when_invoked do |opts| + assert opts[:help] + end + + use_ui @ui do + @cmd.invoke '-h' + end + + assert_match %r|Usage: gem doit|, @ui.output + end + + def test_option_recognition + @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options| + options[:help] = true + end + @cmd.add_option('-f', '--file FILE', 'File option') do |value, options| + options[:help] = true + end + assert @cmd.handles?(['-x']) + assert @cmd.handles?(['-h']) + assert @cmd.handles?(['-h', 'command']) + assert @cmd.handles?(['--help', 'command']) + assert @cmd.handles?(['-f', 'filename']) + assert @cmd.handles?(['--file=filename']) + assert ! @cmd.handles?(['-z']) + assert ! @cmd.handles?(['-f']) + assert ! @cmd.handles?(['--toothpaste']) + + args = ['-h', 'command'] + @cmd.handles?(args) + assert_equal ['-h', 'command'], args + end + +end + diff --git a/test/rubygems/test_gem_command_manager.rb b/test/rubygems/test_gem_command_manager.rb new file mode 100644 index 0000000000..4198bb9a2a --- /dev/null +++ b/test/rubygems/test_gem_command_manager.rb @@ -0,0 +1,211 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/command_manager' + +class InterruptCommand < Gem::Command + + def initialize + super('interrupt', 'Raises an Interrupt Exception', {}) + end + + def execute + raise Interrupt, "Interrupt exception" + end + +end + +class TestGemCommandManager < RubyGemTestCase + + def setup + super + + @command_manager = Gem::CommandManager.new + end + + def test_run_interrupt + use_ui @ui do + @command_manager.register_command :interrupt + assert_raises MockGemUi::TermError do + @command_manager.run 'interrupt' + end + assert_equal '', ui.output + assert_equal "ERROR: Interrupted\n", ui.error + end + end + + def test_process_args_bad_arg + use_ui @ui do + assert_raises(MockGemUi::TermError) { + @command_manager.process_args("--bad-arg") + } + end + + assert_match(/invalid option: --bad-arg/i, @ui.error) + end + + def test_process_args_install + #capture all install options + use_ui @ui do + check_options = nil + @command_manager['install'].when_invoked do |options| + check_options = options + true + end + + #check defaults + @command_manager.process_args("install") + assert_equal false, check_options[:test] + assert_equal true, check_options[:generate_rdoc] + assert_equal false, check_options[:force] + assert_equal :both, check_options[:domain] + assert_equal true, check_options[:wrappers] + assert_equal Gem::Requirement.default, check_options[:version] + assert_equal Gem.dir, check_options[:install_dir] + + #check settings + check_options = nil + @command_manager.process_args( + "install --force --test --local --rdoc --install-dir . --version 3.0 --no-wrapper") + assert_equal true, check_options[:test] + assert_equal true, check_options[:generate_rdoc] + assert_equal true, check_options[:force] + assert_equal :local, check_options[:domain] + assert_equal false, check_options[:wrappers] + assert_equal Gem::Requirement.new('3.0'), check_options[:version] + assert_equal Dir.pwd, check_options[:install_dir] + + #check remote domain + check_options = nil + @command_manager.process_args("install --remote") + assert_equal :remote, check_options[:domain] + + #check both domain + check_options = nil + @command_manager.process_args("install --both") + assert_equal :both, check_options[:domain] + + #check both domain + check_options = nil + @command_manager.process_args("install --both") + assert_equal :both, check_options[:domain] + end + end + + def test_process_args_uninstall + #capture all uninstall options + check_options = nil + @command_manager['uninstall'].when_invoked do |options| + check_options = options + true + end + + #check defaults + @command_manager.process_args("uninstall") + assert_equal Gem::Requirement.default, check_options[:version] + + #check settings + check_options = nil + @command_manager.process_args("uninstall foobar --version 3.0") + assert_equal "foobar", check_options[:args].first + assert_equal Gem::Requirement.new('3.0'), check_options[:version] + end + + def test_process_args_check + #capture all check options + check_options = nil + @command_manager['check'].when_invoked do |options| + check_options = options + true + end + + #check defaults + @command_manager.process_args("check") + assert_equal false, check_options[:verify] + assert_equal false, check_options[:alien] + + #check settings + check_options = nil + @command_manager.process_args("check --verify foobar --alien") + assert_equal "foobar", check_options[:verify] + assert_equal true, check_options[:alien] + end + + def test_process_args_build + #capture all build options + check_options = nil + @command_manager['build'].when_invoked do |options| + check_options = options + true + end + + #check defaults + @command_manager.process_args("build") + #NOTE: Currently no defaults + + #check settings + check_options = nil + @command_manager.process_args("build foobar.rb") + assert_equal 'foobar.rb', check_options[:args].first + end + + def test_process_args_query + #capture all query options + check_options = nil + @command_manager['query'].when_invoked do |options| + check_options = options + true + end + + #check defaults + @command_manager.process_args("query") + assert_equal(/.*/, check_options[:name]) + assert_equal :local, check_options[:domain] + assert_equal false, check_options[:details] + + #check settings + check_options = nil + @command_manager.process_args("query --name foobar --local --details") + assert_equal(/foobar/i, check_options[:name]) + assert_equal :local, check_options[:domain] + assert_equal true, check_options[:details] + + #remote domain + check_options = nil + @command_manager.process_args("query --remote") + assert_equal :remote, check_options[:domain] + + #both (local/remote) domains + check_options = nil + @command_manager.process_args("query --both") + assert_equal :both, check_options[:domain] + end + + def test_process_args_update + #capture all update options + check_options = nil + @command_manager['update'].when_invoked do |options| + check_options = options + true + end + + #check defaults + @command_manager.process_args("update") + assert_equal true, check_options[:generate_rdoc] + + #check settings + check_options = nil + @command_manager.process_args("update --force --test --rdoc --install-dir .") + assert_equal true, check_options[:test] + assert_equal true, check_options[:generate_rdoc] + assert_equal true, check_options[:force] + assert_equal Dir.pwd, check_options[:install_dir] + end + +end + diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb new file mode 100644 index 0000000000..f1fd1503ba --- /dev/null +++ b/test/rubygems/test_gem_commands_build_command.rb @@ -0,0 +1,75 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/build_command' +require 'rubygems/format' + +class TestGemCommandsBuildCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::BuildCommand.new + end + + def test_execute + gem = quick_gem 'some_gem' + + gemspec_file = File.join(@tempdir, "#{gem.full_name}.gemspec") + + File.open gemspec_file, 'w' do |gs| + gs.write gem.to_ruby + end + + util_test_build_gem gem, gemspec_file + end + + def test_execute_yaml + gem = quick_gem 'some_gem' + + gemspec_file = File.join(@tempdir, "#{gem.full_name}.gemspec") + + File.open gemspec_file, 'w' do |gs| + gs.write gem.to_yaml + end + + util_test_build_gem gem, gemspec_file + end + + def test_execute_bad_gem + @cmd.options[:args] = %w[some_gem] + use_ui @ui do + @cmd.execute + end + + assert_equal '', @ui.output + assert_equal "ERROR: Gemspec file not found: some_gem\n", @ui.error + end + + def util_test_build_gem(gem, gemspec_file) + @cmd.options[:args] = [gemspec_file] + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + + output = @ui.output.split "\n" + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 0.0.2", output.shift + assert_equal " File: some_gem-0.0.2.gem", output.shift + assert_equal [], output + assert_equal '', @ui.error + + gem_file = File.join @tempdir, "#{gem.full_name}.gem" + assert File.exist?(gem_file) + + spec = Gem::Format.from_file_by_path(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + +end + diff --git a/test/rubygems/test_gem_commands_cert_command.rb b/test/rubygems/test_gem_commands_cert_command.rb new file mode 100644 index 0000000000..09a401e4f7 --- /dev/null +++ b/test/rubygems/test_gem_commands_cert_command.rb @@ -0,0 +1,122 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') + +require 'rubygems/commands/cert_command' + +class TestGemCommandsCertCommand < RubyGemTestCase + + def setup + super + + @orig_security_trust_dir = Gem::Security::OPT[:trust_dir] + Gem::Security::OPT[:trust_dir] = @tempdir + + @cmd = Gem::Commands::CertCommand.new + + root = File.expand_path(File.dirname(__FILE__)) + + FileUtils.cp File.join(root, 'data', 'gem-private_key.pem'), @tempdir + FileUtils.cp File.join(root, 'data', 'gem-public_cert.pem'), @tempdir + + @cert_file_name = File.join @tempdir, 'gem-public_cert.pem' + @pkey_file_name = File.join @tempdir, 'gem-private_key.pem' + end + + def teardown + Gem::Security::OPT[:trust_dir] = @orig_security_trust_dir + + super + end + + def test_execute_add + use_ui @ui do + @cmd.send :handle_options, %W[--add #{@cert_file_name}] + end + + assert_equal "Added '/CN=rubygems/DC=example/DC=com'\n", @ui.output + assert_equal '', @ui.error + end + + def test_execute_build + FileUtils.rm @cert_file_name + FileUtils.rm @pkey_file_name + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.send :handle_options, %W[--build nobody@example.com] + end + end + + output = @ui.output.split "\n" + + assert_equal 'Public Cert: gem-public_cert.pem', output.shift + assert_equal 'Private Key: gem-private_key.pem', output.shift + assert_equal 'Don\'t forget to move the key file to somewhere private...', + output.shift + assert_equal [], output + + assert_equal '', @ui.error + + assert File.exist?(File.join(@tempdir, 'gem-private_key.pem')) + assert File.exist?(File.join(@tempdir, 'gem-public_cert.pem')) + end + + def test_execute_certificate + use_ui @ui do + @cmd.send :handle_options, %W[--certificate #{@cert_file_name}] + end + + assert_equal '', @ui.output + assert_equal '', @ui.error + + assert_equal File.read(@cert_file_name), + Gem::Security::OPT[:issuer_cert].to_s + end + + def test_execute_list + use_ui @ui do + @cmd.send :handle_options, %W[--list] + end + + assert_equal "/CN=rubygems/DC=example/DC=com\n", @ui.output + assert_equal '', @ui.error + end + + def test_execute_private_key + use_ui @ui do + @cmd.send :handle_options, %W[--private-key #{@pkey_file_name}] + end + + assert_equal '', @ui.output + assert_equal '', @ui.error + + assert_equal File.read(@pkey_file_name), + Gem::Security::OPT[:issuer_key].to_s + end + + def test_execute_remove + use_ui @ui do + @cmd.send :handle_options, %W[--remove rubygems] + end + + assert_equal "Removed '/CN=rubygems/DC=example/DC=com'\n", @ui.output + assert_equal '', @ui.error + + assert !File.exist?(@cert_file_name) + end + + def test_execute_sign + use_ui @ui do + @cmd.send :handle_options, %W[ + -K #{@pkey_file_name} -C #{@cert_file_name} --sign #{@cert_file_name} + ] + end + + assert_equal '', @ui.output + assert_equal '', @ui.error + + # HACK this test sucks + end + +end + diff --git a/test/rubygems/test_gem_commands_check_command.rb b/test/rubygems/test_gem_commands_check_command.rb new file mode 100644 index 0000000000..eea7cc5cfa --- /dev/null +++ b/test/rubygems/test_gem_commands_check_command.rb @@ -0,0 +1,25 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/check_command' + +class TestGemCommandsCheckCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::CheckCommand.new + end + + def test_initialize + assert_equal "check", @cmd.command + assert_equal "gem check", @cmd.program_name + assert_match(/Check/, @cmd.summary) + end + +end diff --git a/test/rubygems/test_gem_commands_contents_command.rb b/test/rubygems/test_gem_commands_contents_command.rb new file mode 100644 index 0000000000..cdb89673da --- /dev/null +++ b/test/rubygems/test_gem_commands_contents_command.rb @@ -0,0 +1,92 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/contents_command' + +class TestGemCommandsContentsCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::ContentsCommand.new + end + + def test_execute + @cmd.options[:args] = %w[foo] + quick_gem 'foo' do |gem| + gem.files = %w[lib/foo.rb Rakefile] + end + + use_ui @ui do + @cmd.execute + end + + assert_match %r|lib/foo\.rb|, @ui.output + assert_match %r|Rakefile|, @ui.output + assert_equal "", @ui.error + end + + def test_execute_bad_gem + @cmd.options[:args] = %w[foo] + + assert_raise MockGemUi::TermError do + use_ui @ui do + @cmd.execute + end + end + + assert_match %r|Unable to find gem 'foo' in default gem paths|, @ui.output + assert_match %r|Directories searched:|, @ui.output + assert_equal "", @ui.error + end + + def test_execute_exact_match + @cmd.options[:args] = %w[foo] + quick_gem 'foo' do |gem| + gem.files = %w[lib/foo.rb Rakefile] + end + + quick_gem 'foo_bar' do |gem| + gem.files = %w[lib/foo_bar.rb Rakefile] + end + + use_ui @ui do + @cmd.execute + end + + assert_match %r|lib/foo\.rb|, @ui.output + assert_match %r|Rakefile|, @ui.output + assert_equal "", @ui.error + end + + def test_execute_lib_only + @cmd.options[:args] = %w[foo] + @cmd.options[:lib_only] = true + + quick_gem 'foo' do |gem| + gem.files = %w[lib/foo.rb Rakefile] + end + + use_ui @ui do + @cmd.execute + end + + assert_match %r|lib/foo\.rb|, @ui.output + assert_no_match %r|Rakefile|, @ui.output + + assert_equal "", @ui.error + end + + def test_handle_options + assert_equal false, @cmd.options[:lib_only] + assert_equal [], @cmd.options[:specdirs] + assert_equal nil, @cmd.options[:version] + + @cmd.send :handle_options, %w[-l -s foo --version 0.0.2] + + assert_equal true, @cmd.options[:lib_only] + assert_equal %w[foo], @cmd.options[:specdirs] + assert_equal Gem::Requirement.new('0.0.2'), @cmd.options[:version] + end + +end + diff --git a/test/rubygems/test_gem_commands_dependency_command.rb b/test/rubygems/test_gem_commands_dependency_command.rb new file mode 100644 index 0000000000..9bf59537fd --- /dev/null +++ b/test/rubygems/test_gem_commands_dependency_command.rb @@ -0,0 +1,108 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/dependency_command' + +class TestGemCommandsDependencyCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::DependencyCommand.new + @cmd.options[:domain] = :local + end + + def test_execute + quick_gem 'foo' do |gem| + gem.add_dependency 'bar', '> 1.0.0' + end + + @cmd.options[:args] = %w[foo] + + use_ui @ui do + @cmd.execute + end + + assert_equal "Gem foo-0.0.2\n bar (> 1.0.0)\n\n", @ui.output + assert_equal '', @ui.error + end + + def test_execute_no_match + @cmd.options[:args] = %w[foo] + + assert_raise MockGemUi::TermError do + use_ui @ui do + @cmd.execute + end + end + + assert_equal "No match found for foo (>= 0)\n", @ui.output + assert_equal '', @ui.error + end + + def test_execute_pipe_format + quick_gem 'foo' do |gem| + gem.add_dependency 'bar', '> 1.0.0' + end + + @cmd.options[:args] = %w[foo] + @cmd.options[:pipe_format] = true + + use_ui @ui do + @cmd.execute + end + + assert_equal "bar --version '> 1.0.0'\n", @ui.output + assert_equal '', @ui.error + end + + def test_execute_reverse + quick_gem 'foo' do |gem| + gem.add_dependency 'bar', '> 1.0.0' + end + + quick_gem 'baz' do |gem| + gem.add_dependency 'foo' + end + + @cmd.options[:args] = %w[foo] + @cmd.options[:reverse_dependencies] = true + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF +Gem foo-0.0.2 + bar (> 1.0.0) + Used by + baz-0.0.2 (foo (>= 0)) + + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + end + + def test_execute_remote + foo = quick_gem 'foo' do |gem| + gem.add_dependency 'bar', '> 1.0.0' + end + + util_setup_source_info_cache foo + + FileUtils.rm File.join(@gemhome, 'specifications', + "#{foo.full_name}.gemspec") + + @cmd.options[:args] = %w[foo] + @cmd.options[:domain] = :remote + + use_ui @ui do + @cmd.execute + end + + assert_equal "Gem foo-0.0.2\n bar (> 1.0.0)\n\n", @ui.output + assert_equal '', @ui.error + end + +end + diff --git a/test/rubygems/test_gem_commands_environment_command.rb b/test/rubygems/test_gem_commands_environment_command.rb new file mode 100644 index 0000000000..0b97009efa --- /dev/null +++ b/test/rubygems/test_gem_commands_environment_command.rb @@ -0,0 +1,116 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/environment_command' + +class TestGemCommandsEnvironmentCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::EnvironmentCommand.new + end + + def test_execute + orig_sources = Gem.sources.dup + Gem.sources.replace %w[http://gems.example.com] + + @cmd.send :handle_options, %w[] + + use_ui @ui do + @cmd.execute + end + + assert_match %r|RUBYGEMS VERSION: (\d\.)+\d \((\d\.)+\d\)|, @ui.output + assert_match %r|RUBY VERSION: \d\.\d\.\d \(.*\) \[.*\]|, @ui.output + assert_match %r|INSTALLATION DIRECTORY: #{@gemhome}|, @ui.output + assert_match %r|RUBYGEMS PREFIX: |, @ui.output + assert_match %r|RUBY EXECUTABLE:.*ruby|, @ui.output + assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output + assert_match %r|- #{Gem::Platform.local}|, @ui.output + assert_match %r|GEM PATHS:|, @ui.output + assert_match %r|- #{@gemhome}|, @ui.output + assert_match %r|GEM CONFIGURATION:|, @ui.output + assert_match %r|:verbose => |, @ui.output + assert_match %r|REMOTE SOURCES:|, @ui.output + assert_equal '', @ui.error + + ensure + Gem.sources.replace orig_sources + end + + def test_execute_gemdir + @cmd.send :handle_options, %w[gemdir] + + use_ui @ui do + @cmd.execute + end + + assert_equal "#{@gemhome}\n", @ui.output + assert_equal '', @ui.error + end + + def test_execute_gempath + @cmd.send :handle_options, %w[gempath] + + use_ui @ui do + @cmd.execute + end + + assert_equal "#{@gemhome}\n", @ui.output + assert_equal '', @ui.error + end + + def test_execute_packageversion + @cmd.send :handle_options, %w[packageversion] + + use_ui @ui do + @cmd.execute + end + + assert_equal "#{Gem::RubyGemsPackageVersion}\n", @ui.output + assert_equal '', @ui.error + end + + def test_execute_remotesources + orig_sources = Gem.sources.dup + Gem.sources.replace %w[http://gems.example.com] + + @cmd.send :handle_options, %w[remotesources] + + use_ui @ui do + @cmd.execute + end + + assert_equal "http://gems.example.com\n", @ui.output + assert_equal '', @ui.error + + ensure + Gem.sources.replace orig_sources + end + + def test_execute_unknown + @cmd.send :handle_options, %w[unknown] + + assert_raise Gem::CommandLineError do + use_ui @ui do + @cmd.execute + end + end + + assert_equal '', @ui.output + assert_equal '', @ui.error + end + + def test_execute_version + @cmd.send :handle_options, %w[version] + + use_ui @ui do + @cmd.execute + end + + assert_equal "#{Gem::RubyGemsVersion}\n", @ui.output + assert_equal '', @ui.error + end + +end + diff --git a/test/rubygems/test_gem_commands_fetch_command.rb b/test/rubygems/test_gem_commands_fetch_command.rb new file mode 100644 index 0000000000..3aa9119378 --- /dev/null +++ b/test/rubygems/test_gem_commands_fetch_command.rb @@ -0,0 +1,34 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/fetch_command' + +class TestGemCommandsFetchCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::FetchCommand.new + end + + def test_execute + util_setup_fake_fetcher + + util_build_gem @gem1 + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = + @source_index.dump + @fetcher.data["#{@gem_repo}/gems/#{@gem1.full_name}.gem"] = + File.read(File.join(@gemhome, 'cache', "#{@gem1.full_name}.gem")) + + @cmd.options[:args] = [@gem1.name] + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + + assert File.exist?(File.join(@tempdir, "#{@gem1.full_name}.gem")) + end + +end + diff --git a/test/rubygems/test_gem_commands_generate_index_command.rb b/test/rubygems/test_gem_commands_generate_index_command.rb new file mode 100644 index 0000000000..548197841b --- /dev/null +++ b/test/rubygems/test_gem_commands_generate_index_command.rb @@ -0,0 +1,32 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/indexer' +require 'rubygems/commands/generate_index_command' + +class TestGemCommandsGenerateIndexCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::GenerateIndexCommand.new + @cmd.options[:directory] = @gemhome + end + + def test_execute + use_ui @ui do + @cmd.execute + end + + yaml = File.join @gemhome, 'yaml' + yaml_z = File.join @gemhome, 'yaml.Z' + quick_index = File.join @gemhome, 'quick', 'index' + quick_index_rz = File.join @gemhome, 'quick', 'index.rz' + + assert File.exist?(yaml), yaml + assert File.exist?(yaml_z), yaml_z + assert File.exist?(quick_index), quick_index + assert File.exist?(quick_index_rz), quick_index_rz + end + +end if ''.respond_to? :to_xs + diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb new file mode 100644 index 0000000000..78840be8c6 --- /dev/null +++ b/test/rubygems/test_gem_commands_install_command.rb @@ -0,0 +1,160 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/install_command' + +class TestGemCommandsInstallCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::InstallCommand.new + @cmd.options[:generate_rdoc] = false + @cmd.options[:generate_ri] = false + end + + def test_execute_include_dependencies + @cmd.options[:include_dependencies] = true + @cmd.options[:args] = [] + + assert_raise Gem::CommandLineError do + use_ui @ui do + @cmd.execute + end + end + + output = @ui.output.split "\n" + assert_equal "INFO: `gem install -y` is now default and will be removed", + output.shift + assert_equal "INFO: use --ignore-dependencies to install only the gems you list", + output.shift + assert output.empty?, output.inspect + end + + def test_execute_local + util_setup_fake_fetcher + @cmd.options[:domain] = :local + + gem1 = quick_gem 'gem_one' + util_build_gem gem1 + FileUtils.mv File.join(@gemhome, 'cache', "#{@gem1.full_name}.gem"), + File.join(@tempdir) + + @cmd.options[:args] = [gem1.name] + + use_ui @ui do + orig_dir = Dir.pwd + begin + Dir.chdir @tempdir + @cmd.execute + ensure + Dir.chdir orig_dir + end + end + + out = @ui.output.split "\n" + assert_equal "Successfully installed #{@gem1.full_name}", out.shift + assert_equal "1 gem installed", out.shift + assert out.empty?, out.inspect + end + + def test_execute_local_missing + util_setup_fake_fetcher + @cmd.options[:domain] = :local + + @cmd.options[:args] = %w[gem_one] + + use_ui @ui do + @cmd.execute + end + + # HACK no repository was checked + assert_equal "ERROR: could not find gem_one locally or in a repository\n", + @ui.error + end + + def test_execute_no_gem + @cmd.options[:args] = %w[] + + assert_raise Gem::CommandLineError do + @cmd.execute + end + end + + def test_execute_nonexistent + util_setup_fake_fetcher + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = + @source_index.dump + + @cmd.options[:args] = %w[nonexistent] + + use_ui @ui do + @cmd.execute + end + + assert_equal "ERROR: could not find nonexistent locally or in a repository\n", + @ui.error + end + + def test_execute_remote + @cmd.options[:generate_rdoc] = true + @cmd.options[:generate_ri] = true + util_setup_fake_fetcher + + util_build_gem @gem1 + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = + @source_index.dump + @fetcher.data["#{@gem_repo}/gems/gem_one-0.0.2.gem"] = + File.read(File.join(@gemhome, 'cache', "#{@gem1.full_name}.gem")) + + @cmd.options[:args] = [@gem1.name] + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + assert_match %r|Bulk updating|, out.shift + assert_equal "Successfully installed #{@gem1.full_name}", out.shift + assert_equal "1 gem installed", out.shift + assert_equal "Installing ri documentation for #{@gem1.full_name}...", + out.shift + assert_equal "Installing RDoc documentation for #{@gem1.full_name}...", + out.shift + assert out.empty?, out.inspect + end + + def test_execute_two + util_setup_fake_fetcher + @cmd.options[:domain] = :local + + gem1 = quick_gem 'gem_one' + util_build_gem gem1 + FileUtils.mv File.join(@gemhome, 'cache', "#{@gem1.full_name}.gem"), + File.join(@tempdir) + + gem2 = quick_gem 'gem_two' + util_build_gem gem2 + FileUtils.mv File.join(@gemhome, 'cache', "#{@gem2.full_name}.gem"), + File.join(@tempdir) + + @cmd.options[:args] = [gem1.name, gem2.name] + + use_ui @ui do + orig_dir = Dir.pwd + begin + Dir.chdir @tempdir + @cmd.execute + ensure + Dir.chdir orig_dir + end + end + + out = @ui.output.split "\n" + assert_equal "Successfully installed #{@gem1.full_name}", out.shift + assert_equal "Successfully installed #{@gem2.full_name}", out.shift + assert_equal "2 gems installed", out.shift + assert out.empty?, out.inspect + end + +end + diff --git a/test/rubygems/test_gem_commands_mirror_command.rb b/test/rubygems/test_gem_commands_mirror_command.rb new file mode 100644 index 0000000000..7ddc8b92f8 --- /dev/null +++ b/test/rubygems/test_gem_commands_mirror_command.rb @@ -0,0 +1,56 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/indexer' +require 'rubygems/commands/mirror_command' + +class TestGemCommandsMirrorCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::MirrorCommand.new + end + + def test_execute + util_make_gems + + gems_dir = File.join @tempdir, 'gems' + mirror = File.join @tempdir, 'mirror' + + FileUtils.mkdir_p gems_dir + FileUtils.mkdir_p mirror + + Dir[File.join(@gemhome, 'cache', '*.gem')].each do |gem| + FileUtils.mv gem, gems_dir + end + + use_ui @ui do + Gem::Indexer.new(@tempdir).generate_index + end + + orig_HOME = ENV['HOME'] + ENV['HOME'] = @tempdir + Gem.instance_variable_set :@user_home, nil + + File.open File.join(Gem.user_home, '.gemmirrorrc'), 'w' do |fp| + fp.puts "---" + fp.puts "- from: file://#{@tempdir}" + fp.puts " to: #{mirror}" + end + + use_ui @ui do + @cmd.execute + end + + assert File.exist?(File.join(mirror, 'gems', "#{@a0_0_1.full_name}.gem")) + assert File.exist?(File.join(mirror, 'gems', "#{@a0_0_2.full_name}.gem")) + assert File.exist?(File.join(mirror, 'gems', "#{@b0_0_2.full_name}.gem")) + assert File.exist?(File.join(mirror, 'gems', "#{@c1_2.full_name}.gem")) + assert File.exist?(File.join(mirror, "Marshal.#{@marshal_version}")) + ensure + orig_HOME.nil? ? ENV.delete('HOME') : ENV['HOME'] = orig_HOME + Gem.instance_variable_set :@user_home, nil + end + +end if ''.respond_to? :to_xs + diff --git a/test/rubygems/test_gem_commands_pristine_command.rb b/test/rubygems/test_gem_commands_pristine_command.rb new file mode 100644 index 0000000000..cd1d3500ae --- /dev/null +++ b/test/rubygems/test_gem_commands_pristine_command.rb @@ -0,0 +1,100 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/pristine_command' + +class TestGemCommandsPristineCommand < RubyGemTestCase + + def setup + super + @cmd = Gem::Commands::PristineCommand.new + end + + def test_execute + a = quick_gem 'a' do |s| s.executables = %w[foo] end + FileUtils.mkdir_p File.join(@tempdir, 'bin') + File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp| + fp.puts "#!/usr/bin/ruby" + end + + install_gem a + + @cmd.options[:args] = %w[a] + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + + assert_equal "Restoring gem(s) to pristine condition...", out.shift + assert_equal "#{a.full_name} is in pristine condition", out.shift + assert out.empty?, out.inspect + end + + def test_execute_all + a = quick_gem 'a' do |s| s.executables = %w[foo] end + FileUtils.mkdir_p File.join(@tempdir, 'bin') + File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp| + fp.puts "#!/usr/bin/ruby" + end + + install_gem a + + gem_bin = File.join @gemhome, 'gems', "#{a.full_name}", 'bin', 'foo' + + FileUtils.rm gem_bin + + @cmd.handle_options %w[--all] + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + + assert_equal "Restoring gem(s) to pristine condition...", out.shift + assert_equal "Restoring 1 file to #{a.full_name}...", out.shift + assert_equal " #{gem_bin}", out.shift + assert out.empty?, out.inspect + end + + def test_execute_missing_cache_gem + a = quick_gem 'a' do |s| s.executables = %w[foo] end + FileUtils.mkdir_p File.join(@tempdir, 'bin') + File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp| + fp.puts "#!/usr/bin/ruby" + end + + install_gem a + + FileUtils.rm File.join(@gemhome, 'cache', "#{a.full_name}.gem") + + @cmd.options[:args] = %w[a] + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + + assert_equal "Restoring gem\(s\) to pristine condition...", out.shift + assert out.empty?, out.inspect + + assert_equal "ERROR: Cached gem for #{a.full_name} not found, use `gem install` to restore\n", + @ui.error + end + + def test_execute_no_gem + @cmd.options[:args] = %w[] + + e = assert_raise Gem::CommandLineError do + use_ui @ui do + @cmd.execute + end + end + + assert_match %r|specify a gem name|, e.message + end + +end + diff --git a/test/rubygems/test_gem_commands_query_command.rb b/test/rubygems/test_gem_commands_query_command.rb new file mode 100644 index 0000000000..e2b6a45e92 --- /dev/null +++ b/test/rubygems/test_gem_commands_query_command.rb @@ -0,0 +1,82 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/query_command' + +class TestGemCommandsQueryCommand < RubyGemTestCase + + def setup + super + + @foo_gem = quick_gem 'foo' do |spec| + spec.summary = 'This is a lot of text. ' * 5 + end + @bar_gem = quick_gem 'bar' + + @cmd = Gem::Commands::QueryCommand.new + end + + def test_execute + util_setup_source_info_cache @foo_gem + + @cmd.handle_options %w[-r] + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF + +*** REMOTE GEMS *** + +foo (0.0.2) + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + end + + def test_execute_details + util_setup_source_info_cache @foo_gem + + @cmd.handle_options %w[-r -d] + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF + +*** REMOTE GEMS *** + +foo (0.0.2) + This is a lot of text. This is a lot of text. This is a lot of + text. This is a lot of text. This is a lot of text. + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + end + + def test_execute_no_versions + util_setup_source_info_cache @foo_gem, @bar_gem + + @cmd.handle_options %w[-r --no-versions] + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF + +*** REMOTE GEMS *** + +bar +foo + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + end + +end + diff --git a/test/rubygems/test_gem_commands_sources_command.rb b/test/rubygems/test_gem_commands_sources_command.rb new file mode 100644 index 0000000000..3d1ab801b1 --- /dev/null +++ b/test/rubygems/test_gem_commands_sources_command.rb @@ -0,0 +1,147 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/sources_command' + +class TestGemCommandsSourcesCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::SourcesCommand.new + end + + def test_execute + util_setup_source_info_cache + @cmd.handle_options [] + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF +*** CURRENT SOURCES *** + +#{@gem_repo} + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + end + + def test_execute_add + util_setup_fake_fetcher + + @si = Gem::SourceIndex.new @gem1.full_name => @gem1.name + + @fetcher.data["http://beta-gems.example.com/Marshal.#{@marshal_version}"] = + @si.dump + + @cmd.handle_options %w[--add http://beta-gems.example.com] + + util_setup_source_info_cache + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF +Bulk updating Gem source index for: http://beta-gems.example.com +http://beta-gems.example.com added to sources + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + + Gem::SourceInfoCache.cache.flush + assert_equal %W[http://beta-gems.example.com #{@gem_repo}], + Gem::SourceInfoCache.cache_data.keys.sort + end + + def test_execute_add_nonexistent_source + util_setup_fake_fetcher + + @si = Gem::SourceIndex.new @gem1.full_name => @gem1.name + + @fetcher.data["http://beta-gems.example.com/Marshal.#{@marshal_version}"] = + proc do + raise Gem::RemoteFetcher::FetchError, 'it died' + end + + + Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher + + @cmd.handle_options %w[--add http://beta-gems.example.com] + + util_setup_source_info_cache + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF +Error fetching http://beta-gems.example.com: +\tit died + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + end + + def test_execute_add_bad_uri + @cmd.handle_options %w[--add beta-gems.example.com] + + util_setup_source_info_cache + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF +beta-gems.example.com is not a URI + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + end + + def test_execute_remove + @cmd.handle_options %W[--remove #{@gem_repo}] + + util_setup_source_info_cache + + use_ui @ui do + @cmd.execute + end + + expected = "#{@gem_repo} removed from sources\n" + + assert_equal expected, @ui.output + assert_equal '', @ui.error + + Gem::SourceInfoCache.cache.flush + assert_equal [], Gem::SourceInfoCache.cache_data.keys + end + + def test_execute_update + @cmd.handle_options %w[--update] + + util_setup_source_info_cache + util_setup_fake_fetcher + @si = Gem::SourceIndex.new @gem1.full_name => @gem1.name + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = @si.dump + + use_ui @ui do + @cmd.execute + end + + expected = <<-EOF +Bulk updating Gem source index for: #{@gem_repo} +source cache successfully updated + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + end + +end + diff --git a/test/rubygems/test_gem_commands_specification_command.rb b/test/rubygems/test_gem_commands_specification_command.rb new file mode 100644 index 0000000000..3741446536 --- /dev/null +++ b/test/rubygems/test_gem_commands_specification_command.rb @@ -0,0 +1,93 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/specification_command' + +class TestGemCommandsSpecificationCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::SpecificationCommand.new + end + + def test_execute + foo = quick_gem 'foo' + + @cmd.options[:args] = %w[foo] + + use_ui @ui do + @cmd.execute + end + + assert_match %r|Gem::Specification|, @ui.output + assert_match %r|name: foo|, @ui.output + assert_equal '', @ui.error + end + + def test_execute_all + foo1 = quick_gem 'foo', '0.0.1' + foo2 = quick_gem 'foo', '0.0.2' + + @cmd.options[:args] = %w[foo] + @cmd.options[:all] = true + + use_ui @ui do + @cmd.execute + end + + assert_match %r|Gem::Specification|, @ui.output + assert_match %r|name: foo|, @ui.output + assert_match %r|version: 0.0.1|, @ui.output + assert_match %r|version: 0.0.2|, @ui.output + assert_equal '', @ui.error + end + + def test_execute_bad_name + @cmd.options[:args] = %w[foo] + + assert_raise MockGemUi::TermError do + use_ui @ui do + @cmd.execute + end + end + + assert_equal '', @ui.output + assert_equal "ERROR: Unknown gem 'foo'\n", @ui.error + end + + def test_execute_exact_match + foo = quick_gem 'foo' + foo_bar = quick_gem 'foo_bar' + + @cmd.options[:args] = %w[foo] + + use_ui @ui do + @cmd.execute + end + + assert_match %r|Gem::Specification|, @ui.output + assert_match %r|name: foo|, @ui.output + assert_equal '', @ui.error + end + + def test_execute_remote + foo = quick_gem 'foo' + + util_setup_source_info_cache foo + + FileUtils.rm File.join(@gemhome, 'specifications', + "#{foo.full_name}.gemspec") + + @cmd.options[:args] = %w[foo] + @cmd.options[:domain] = :remote + + use_ui @ui do + @cmd.execute + end + + assert_equal "#{foo.to_yaml}\n", @ui.output + assert_equal "WARNING: Remote information is not complete\n\n", @ui.error + end + +end + diff --git a/test/rubygems/test_gem_commands_unpack_command.rb b/test/rubygems/test_gem_commands_unpack_command.rb new file mode 100644 index 0000000000..ff3d4e0eae --- /dev/null +++ b/test/rubygems/test_gem_commands_unpack_command.rb @@ -0,0 +1,55 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/unpack_command' + +class TestGemCommandsUnpackCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::UnpackCommand.new + end + + def test_execute + util_make_gems + + @cmd.options[:args] = %w[a] + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + + assert File.exist?(File.join(@tempdir, 'a-0.0.2')) + end + + def test_execute_exact_match + foo_spec = quick_gem 'foo' + foo_bar_spec = quick_gem 'foo_bar' + + use_ui @ui do + Dir.chdir @tempdir do + Gem::Builder.new(foo_spec).build + Gem::Builder.new(foo_bar_spec).build + end + end + + foo_path = File.join(@tempdir, "#{foo_spec.full_name}.gem") + foo_bar_path = File.join(@tempdir, "#{foo_bar_spec.full_name}.gem") + Gem::Installer.new(foo_path).install + Gem::Installer.new(foo_bar_path).install + + @cmd.options[:args] = %w[foo] + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + + assert File.exist?(File.join(@tempdir, foo_spec.full_name)) + end + +end + diff --git a/test/rubygems/test_gem_config_file.rb b/test/rubygems/test_gem_config_file.rb new file mode 100644 index 0000000000..e0360b0d6b --- /dev/null +++ b/test/rubygems/test_gem_config_file.rb @@ -0,0 +1,210 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/config_file' + +class TestGemConfigFile < RubyGemTestCase + + def setup + super + + @temp_conf = File.join @tempdir, '.gemrc' + + @cfg_args = %W[--config-file #{@temp_conf}] + util_config_file + end + + def test_initialize + assert_equal @temp_conf, @cfg.config_file_name + + assert_equal false, @cfg.backtrace + assert_equal true, @cfg.update_sources + assert_equal false, @cfg.benchmark + assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold + assert_equal true, @cfg.verbose + assert_equal %w[http://gems.example.com], Gem.sources + + File.open @temp_conf, 'w' do |fp| + fp.puts ":backtrace: true" + fp.puts ":update_sources: false" + fp.puts ":benchmark: true" + fp.puts ":bulk_threshold: 10" + fp.puts ":verbose: false" + fp.puts ":sources:" + fp.puts " - http://more-gems.example.com" + fp.puts "install: --wrappers" + end + + util_config_file + + assert_equal true, @cfg.backtrace + assert_equal true, @cfg.benchmark + assert_equal 10, @cfg.bulk_threshold + assert_equal false, @cfg.verbose + assert_equal false, @cfg.update_sources + assert_equal %w[http://more-gems.example.com], Gem.sources + assert_equal '--wrappers', @cfg[:install] + end + + def test_initialize_handle_arguments_config_file + util_config_file %W[--config-file #{@temp_conf}] + + assert_equal @temp_conf, @cfg.config_file_name + end + + def test_initialize_handle_arguments_config_file_equals + util_config_file %W[--config-file=#{@temp_conf}] + + assert_equal @temp_conf, @cfg.config_file_name + end + + def test_handle_arguments + args = %w[--backtrace --bunch --of --args here] + + @cfg.handle_arguments args + + assert_equal %w[--bunch --of --args here], @cfg.args + end + + def test_handle_arguments_backtrace + assert_equal false, @cfg.backtrace + + args = %w[--backtrace] + + @cfg.handle_arguments args + + assert_equal true, @cfg.backtrace + end + + def test_handle_arguments_benchmark + assert_equal false, @cfg.benchmark + + args = %w[--benchmark] + + @cfg.handle_arguments args + + assert_equal true, @cfg.benchmark + end + + def test_handle_arguments_debug + old_dollar_DEBUG = $DEBUG + assert_equal false, $DEBUG + + args = %w[--debug] + + @cfg.handle_arguments args + + assert_equal true, $DEBUG + ensure + $DEBUG = old_dollar_DEBUG + end + + def test_handle_arguments_override + File.open @temp_conf, 'w' do |fp| + fp.puts ":benchmark: false" + end + + util_config_file %W[--benchmark --config-file=#{@temp_conf}] + + assert_equal true, @cfg.benchmark + end + + def test_handle_arguments_traceback + assert_equal false, @cfg.backtrace + + args = %w[--traceback] + + @cfg.handle_arguments args + + assert_equal true, @cfg.backtrace + end + + def test_really_verbose + assert_equal false, @cfg.really_verbose + + @cfg.verbose = true + + assert_equal false, @cfg.really_verbose + + @cfg.verbose = 1 + + assert_equal true, @cfg.really_verbose + end + + def test_write + @cfg.backtrace = true + @cfg.benchmark = true + @cfg.update_sources = false + @cfg.bulk_threshold = 10 + @cfg.verbose = false + Gem.sources.replace %w[http://more-gems.example.com] + @cfg[:install] = '--wrappers' + + @cfg.write + + util_config_file + + # These should not be written out to the config file. + assert_equal false, @cfg.backtrace, 'backtrace' + assert_equal false, @cfg.benchmark, 'benchmark' + assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold, + 'bulk_threshold' + assert_equal true, @cfg.update_sources, 'update_sources' + assert_equal true, @cfg.verbose, 'verbose' + + assert_equal '--wrappers', @cfg[:install], 'install' + + # this should be written out to the config file. + assert_equal %w[http://more-gems.example.com], Gem.sources + end + + def test_write_from_hash + File.open @temp_conf, 'w' do |fp| + fp.puts ":backtrace: true" + fp.puts ":benchmark: true" + fp.puts ":bulk_threshold: 10" + fp.puts ":update_sources: false" + fp.puts ":verbose: false" + fp.puts ":sources:" + fp.puts " - http://more-gems.example.com" + fp.puts "install: --wrappers" + end + + util_config_file + + @cfg.backtrace = :junk + @cfg.benchmark = :junk + @cfg.update_sources = :junk + @cfg.bulk_threshold = 20 + @cfg.verbose = :junk + Gem.sources.replace %w[http://even-more-gems.example.com] + @cfg[:install] = '--wrappers --no-rdoc' + + @cfg.write + + util_config_file + + # These should not be written out to the config file + assert_equal true, @cfg.backtrace, 'backtrace' + assert_equal true, @cfg.benchmark, 'benchmark' + assert_equal 10, @cfg.bulk_threshold, 'bulk_threshold' + assert_equal false, @cfg.update_sources, 'update_sources' + assert_equal false, @cfg.verbose, 'verbose' + + assert_equal '--wrappers --no-rdoc', @cfg[:install], 'install' + + assert_equal %w[http://even-more-gems.example.com], Gem.sources + end + + def util_config_file(args = @cfg_args) + @cfg = Gem::ConfigFile.new args + end + +end + diff --git a/test/rubygems/test_gem_dependency.rb b/test/rubygems/test_gem_dependency.rb new file mode 100644 index 0000000000..f280221a00 --- /dev/null +++ b/test/rubygems/test_gem_dependency.rb @@ -0,0 +1,89 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/version' + +class TestGemDependency < RubyGemTestCase + + def setup + super + + @pkg1_0 = Gem::Dependency.new 'pkg', ['> 1.0'] + @pkg1_1 = Gem::Dependency.new 'pkg', ['> 1.1'] + + @oth1_0 = Gem::Dependency.new 'other', ['> 1.0'] + + @r1_0 = Gem::Requirement.new ['> 1.0'] + end + + def test_initialize + assert_equal "pkg", @pkg1_0.name + assert_equal @r1_0, @pkg1_0.version_requirements + end + + def test_initialize_double + dep = Gem::Dependency.new("pkg", ["> 1.0", "< 2.0"]) + + assert_equal Gem::Requirement.new(["> 1.0", "< 2.0"]), + dep.version_requirements + end + + def test_initialize_empty + dep = Gem::Dependency.new("pkg", []) + req = @r1_0 + + req.instance_eval do + @version = ">= 1.0" + @op = ">=" + @nums = [1,0] + @requirements = nil + end + + dep.instance_eval do + @version_requirement = req + @version_requirements = nil + end + + assert_equal Gem::Requirement.new([">= 1.0"]), dep.version_requirements + end + + def test_initialize_version + dep = Gem::Dependency.new 'pkg', Gem::Version.new('2') + + assert_equal 'pkg', dep.name + + assert_equal Gem::Requirement.new('= 2'), dep.version_requirements + end + + def test_equals2 + assert_equal @pkg1_0, @pkg1_0.dup + assert_equal @pkg1_0.dup, @pkg1_0 + + assert_not_equal @pkg1_0, @pkg1_1, "requirements different" + assert_not_equal @pkg1_1, @pkg1_0, "requirements different" + + assert_not_equal @pkg1_0, @oth1_0, "names different" + assert_not_equal @oth1_0, @pkg1_0, "names different" + + assert_not_equal @pkg1_0, Object.new + assert_not_equal Object.new, @pkg1_0 + end + + def test_hash + assert_equal @pkg1_0.hash, @pkg1_0.dup.hash + assert_equal @pkg1_0.dup.hash, @pkg1_0.hash + + assert_not_equal @pkg1_0.hash, @pkg1_1.hash, "requirements different" + assert_not_equal @pkg1_1.hash, @pkg1_0.hash, "requirements different" + + assert_not_equal @pkg1_0.hash, @oth1_0.hash, "names different" + assert_not_equal @oth1_0.hash, @pkg1_0.hash, "names different" + end + +end + diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb new file mode 100644 index 0000000000..18793d3065 --- /dev/null +++ b/test/rubygems/test_gem_dependency_installer.rb @@ -0,0 +1,519 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/dependency_installer' + +class TestGemDependencyInstaller < RubyGemTestCase + + def setup + super + + @gems_dir = File.join @tempdir, 'gems' + @cache_dir = File.join @gemhome, 'cache' + FileUtils.mkdir @gems_dir + + write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp| + fp.puts "#!/usr/bin/ruby" + end + @a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end + + @b1, @b1_gem = util_gem 'b', '1' do |s| s.add_dependency 'a' end + + @d1, @d1_gem = util_gem 'd', '1' + @d2, @d2_gem = util_gem 'd', '2' + + @x1_m, @x1_m_gem = util_gem 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @x1_o, @x1_o_gem = util_gem 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu other_platform 1] + end + + @w1, @w1_gem = util_gem 'w', '1' do |s| s.add_dependency 'x' end + + @y1, @y1_gem = util_gem 'y', '1' + @y1_1_p, @y1_1_p_gem = util_gem 'y', '1.1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @z1, @z1_gem = util_gem 'z', '1' do |s| s.add_dependency 'y' end + + si = util_setup_source_info_cache @a1, @b1, @d1, @d2, @x1_m, @x1_o, @w1, + @y1, @y1_1_p, @z1 + + @fetcher = FakeFetcher.new + Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher + @fetcher.uri = URI.parse 'http://gems.example.com' + @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml + + FileUtils.rm_rf File.join(@gemhome, 'gems') + end + + def test_install + FileUtils.mv @a1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'a' + inst.install + end + + assert_equal Gem::SourceIndex.new(@a1.full_name => @a1), + Gem::SourceIndex.from_installed_gems + + assert_equal [@a1], inst.installed_gems + end + + def test_install_dependency + FileUtils.mv @a1_gem, @tempdir + FileUtils.mv @b1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'b' + inst.install + end + + assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_dependency_existing + Gem::Installer.new(@a1_gem).install + FileUtils.mv @a1_gem, @tempdir + FileUtils.mv @b1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'b' + inst.install + end + + assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_dependency_old + @e1, @e1_gem = util_gem 'e', '1' + @f1, @f1_gem = util_gem 'f', '1' do |s| s.add_dependency 'e' end + @f2, @f2_gem = util_gem 'f', '2' + + FileUtils.mv @e1_gem, @tempdir + FileUtils.mv @f1_gem, @tempdir + FileUtils.mv @f2_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'f' + inst.install + end + + assert_equal %w[f-2], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_local + FileUtils.mv @a1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'a-1.gem' + inst.install + end + + assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_local_subdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'gems/a-1.gem' + inst.install + end + + assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_env_shebang + FileUtils.mv @a1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'a', nil, :env_shebang => true, + :wrappers => true + inst.install + end + + assert_match %r|\A#!/usr/bin/env ruby\n|, + File.read(File.join(@gemhome, 'bin', 'a_bin')) + end + + def test_install_force + FileUtils.mv @b1_gem, @tempdir + si = util_setup_source_info_cache @b1 + @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'b', nil, :force => true + inst.install + end + + assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_ignore_dependencies + FileUtils.mv @b1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'b', nil, :ignore_dependencies => true + inst.install + end + + assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_install_dir + FileUtils.mv @a1_gem, @tempdir + gemhome2 = File.join @tempdir, 'gemhome2' + Dir.mkdir gemhome2 + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'a', nil, :install_dir => gemhome2 + inst.install + end + + assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + + assert File.exist?(File.join(gemhome2, 'specifications', + "#{@a1.full_name}.gemspec")) + end + + def test_install_domain_both + a1_data = nil + File.open @a1_gem, 'rb' do |fp| + a1_data = fp.read + end + + @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data + + FileUtils.mv @b1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'b', nil, :domain => :both + inst.install + end + + assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name } + a1, b1 = inst.installed_gems + + a1_expected = File.join(@gemhome, 'specifications', + "#{a1.full_name}.gemspec") + b1_expected = File.join(@gemhome, 'specifications', + "#{b1.full_name}.gemspec") + + assert_equal a1_expected, a1.loaded_from + assert_equal b1_expected, b1.loaded_from + end + + def test_install_domain_local + FileUtils.mv @b1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + e = assert_raise Gem::InstallError do + inst = Gem::DependencyInstaller.new 'b', nil, :domain => :local + inst.install + end + assert_equal 'b requires a (>= 0)', e.message + end + + assert_equal [], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_domain_remote + a1_data = nil + File.open @a1_gem, 'rb' do |fp| + a1_data = fp.read + end + + @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data + + inst = Gem::DependencyInstaller.new 'a', nil, :domain => :remote + inst.install + + assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_domain_remote_platform_newer + a2_o, a2_o_gem = util_gem 'a', '2' do |s| + s.platform = Gem::Platform.new %w[cpu other_platform 1] + end + + si = util_setup_source_info_cache @a1, a2_o + + @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml + + a1_data = nil + a2_o_data = nil + + File.open @a1_gem, 'rb' do |fp| a1_data = fp.read end + File.open a2_o_gem, 'rb' do |fp| a2_o_data = fp.read end + + @fetcher.data["http://gems.example.com/gems/#{@a1.full_name}.gem"] = + a1_data + @fetcher.data["http://gems.example.com/gems/#{a2_o.full_name}.gem"] = + a2_o_data + + inst = Gem::DependencyInstaller.new 'a', nil, :domain => :remote + inst.install + + assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_reinstall + Gem::Installer.new(@a1_gem).install + FileUtils.mv @a1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'a' + inst.install + end + + assert_equal Gem::SourceIndex.new(@a1.full_name => @a1), + Gem::SourceIndex.from_installed_gems + + assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_security_policy + FileUtils.mv @a1_gem, @cache_dir + FileUtils.mv @b1_gem, @cache_dir + policy = Gem::Security::HighSecurity + inst = Gem::DependencyInstaller.new 'b', nil, :security_policy => policy + + e = assert_raise Gem::Exception do + inst.install + end + + assert_equal 'Unsigned gem', e.message + + assert_equal %w[], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_wrappers + FileUtils.mv @a1_gem, @cache_dir + inst = Gem::DependencyInstaller.new 'a', :wrappers => true + + inst.install + + assert_match %r|This file was generated by RubyGems.|, + File.read(File.join(@gemhome, 'bin', 'a_bin')) + end + + def test_install_version + FileUtils.mv @d1_gem, @cache_dir + FileUtils.mv @d2_gem, @cache_dir + inst = Gem::DependencyInstaller.new 'd', '= 1' + + inst.install + + assert_equal %w[d-1], inst.installed_gems.map { |s| s.full_name } + end + + def test_install_version_default + FileUtils.mv @d1_gem, @cache_dir + FileUtils.mv @d2_gem, @cache_dir + inst = Gem::DependencyInstaller.new 'd' + + inst.install + + assert_equal %w[d-2], inst.installed_gems.map { |s| s.full_name } + end + + def test_download_gem + a1_data = nil + File.open @a1_gem, 'rb' do |fp| + a1_data = fp.read + end + + @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data + + inst = Gem::DependencyInstaller.new 'a' + + a1_cache_gem = File.join(@gemhome, 'cache', "#{@a1.full_name}.gem") + assert_equal a1_cache_gem, inst.download(@a1, 'http://gems.example.com') + + assert File.exist?(a1_cache_gem) + end + + def test_download_gem_cached + FileUtils.mv @a1_gem, @cache_dir + + inst = Gem::DependencyInstaller.new 'a' + + assert_equal File.join(@gemhome, 'cache', "#{@a1.full_name}.gem"), + inst.download(@a1, 'http://gems.example.com') + end + + def test_download_gem_local + FileUtils.mv @a1_gem, @tempdir + local_path = File.join @tempdir, "#{@a1.full_name}.gem" + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'a' + end + + assert_equal File.join(@gemhome, 'cache', "#{@a1.full_name}.gem"), + inst.download(@a1, local_path) + end + + def test_download_gem_install_dir + a1_data = nil + File.open @a1_gem, 'rb' do |fp| + a1_data = fp.read + end + + @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data + + install_dir = File.join @tempdir, 'more_gems' + + inst = Gem::DependencyInstaller.new 'a', nil, :install_dir => install_dir + + a1_cache_gem = File.join install_dir, 'cache', "#{@a1.full_name}.gem" + assert_equal a1_cache_gem, inst.download(@a1, 'http://gems.example.com') + + assert File.exist?(a1_cache_gem) + end + + unless win_platform? then # File.chmod doesn't work + def test_download_gem_local_read_only + FileUtils.mv @a1_gem, @tempdir + local_path = File.join @tempdir, "#{@a1.full_name}.gem" + inst = nil + File.chmod 0555, File.join(@gemhome, 'cache') + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new 'a' + end + + assert_equal File.join(@tempdir, "#{@a1.full_name}.gem"), + inst.download(@a1, local_path) + ensure + File.chmod 0755, File.join(@gemhome, 'cache') + end + end + + def test_download_gem_unsupported + inst = Gem::DependencyInstaller.new 'a' + + e = assert_raise Gem::InstallError do + inst.download @a1, 'ftp://gems.rubyforge.org' + end + + assert_equal 'unsupported URI scheme ftp', e.message + end + + def test_find_gems_gems_with_sources + inst = Gem::DependencyInstaller.new 'a' + dep = Gem::Dependency.new 'b', '>= 0' + + assert_equal [[@b1, 'http://gems.example.com']], + inst.find_gems_with_sources(dep) + end + + def test_find_gems_with_sources_local + FileUtils.mv @a1_gem, @tempdir + inst = Gem::DependencyInstaller.new 'b' + dep = Gem::Dependency.new 'a', '>= 0' + gems = nil + + Dir.chdir @tempdir do + gems = inst.find_gems_with_sources dep + end + + assert_equal 2, gems.length + remote = gems.first + assert_equal @a1, remote.first, 'remote spec' + assert_equal 'http://gems.example.com', remote.last, 'remote path' + + local = gems.last + assert_equal 'a-1', local.first.full_name, 'local spec' + assert_equal File.join(@tempdir, "#{@a1.full_name}.gem"), + local.last, 'local path' + end + + def test_gather_dependencies + inst = Gem::DependencyInstaller.new 'b' + + assert_equal %w[a-1 b-1], inst.gems_to_install.map { |s| s.full_name } + end + + def test_gather_dependencies_dropped + b2, = util_gem 'b', '2' + c1, = util_gem 'c', '1' do |s| s.add_dependency 'b' end + + si = util_setup_source_info_cache @a1, @b1, b2, c1 + + @fetcher = FakeFetcher.new + Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher + @fetcher.uri = URI.parse 'http://gems.example.com' + @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml + + inst = Gem::DependencyInstaller.new 'c' + + assert_equal %w[b-2 c-1], inst.gems_to_install.map { |s| s.full_name } + end + + def test_gather_dependencies_platform_alternate + util_set_arch 'cpu-my_platform1' + + inst = Gem::DependencyInstaller.new 'w' + + assert_equal %w[x-1-cpu-my_platform-1 w-1], + inst.gems_to_install.map { |s| s.full_name } + end + + def test_gather_dependencies_platform_bump + inst = Gem::DependencyInstaller.new 'z' + + assert_equal %w[y-1 z-1], inst.gems_to_install.map { |s| s.full_name } + end + + def test_gather_dependencies_old_required + e1, = util_gem 'e', '1' do |s| s.add_dependency 'd', '= 1' end + + si = util_setup_source_info_cache @d1, @d2, e1 + + @fetcher = FakeFetcher.new + Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher + @fetcher.uri = URI.parse 'http://gems.example.com' + @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml + + inst = Gem::DependencyInstaller.new 'e' + + assert_equal %w[d-1 e-1], inst.gems_to_install.map { |s| s.full_name } + end + + def util_gem(name, version, &block) + spec = quick_gem(name, version, &block) + + util_build_gem spec + + cache_file = File.join @tempdir, 'gems', "#{spec.full_name}.gem" + FileUtils.mv File.join(@gemhome, 'cache', "#{spec.full_name}.gem"), + cache_file + FileUtils.rm File.join(@gemhome, 'specifications', + "#{spec.full_name}.gemspec") + + spec.loaded_from = nil + spec.loaded = false + + [spec, cache_file] + end + +end + diff --git a/test/rubygems/test_gem_dependency_list.rb b/test/rubygems/test_gem_dependency_list.rb new file mode 100644 index 0000000000..5fdc227f05 --- /dev/null +++ b/test/rubygems/test_gem_dependency_list.rb @@ -0,0 +1,212 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/dependency_list' + +class TestGemDependencyList < RubyGemTestCase + + def setup + super + + @deplist = Gem::DependencyList.new + + @a1 = quick_gem 'a', '1' + @a2 = quick_gem 'a', '2' + @a3 = quick_gem 'a', '3' + + @b1 = quick_gem 'b', '1' do |s| s.add_dependency 'a', '>= 1' end + @b2 = quick_gem 'b', '2' do |s| s.add_dependency 'a', '>= 1' end + + @c1 = quick_gem 'c', '1' do |s| s.add_dependency 'b', '>= 1' end + @c2 = quick_gem 'c', '2' + + @d1 = quick_gem 'd', '1' do |s| s.add_dependency 'c', '>= 1' end + end + + def test_self_from_source_index + hash = { + 'a-1' => @a1, + 'b-2' => @b2, + } + + si = Gem::SourceIndex.new hash + deps = Gem::DependencyList.from_source_index si + + assert_equal %w[b-2 a-1], deps.dependency_order.map { |s| s.full_name } + end + + def test_active_count + assert_equal 0, @deplist.send(:active_count, [], {}) + assert_equal 1, @deplist.send(:active_count, [@a1], {}) + assert_equal 0, @deplist.send(:active_count, [@a1], + { @a1.full_name => true }) + end + + def test_add + assert_equal [], @deplist.dependency_order + + @deplist.add @a1, @b2 + + assert_equal [@b2, @a1], @deplist.dependency_order + end + + def test_dependency_order + @deplist.add @a1, @b1, @c1, @d1 + + order = @deplist.dependency_order + + assert_equal %w[d-1 c-1 b-1 a-1], order.map { |s| s.full_name } + end + + def test_dependency_order_circle + @a1.add_dependency 'c', '>= 1' + @deplist.add @a1, @b1, @c1 + + order = @deplist.dependency_order + + assert_equal %w[b-1 c-1 a-1], order.map { |s| s.full_name } + end + + def test_dependency_order_diamond + util_diamond + e1 = quick_gem 'e', '1' + @deplist.add e1 + @a1.add_dependency 'e', '>= 1' + + order = @deplist.dependency_order + + assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map { |s| s.full_name }, + 'deps of trimmed specs not included' + end + + def test_dependency_order_no_dependendencies + @deplist.add @a1, @c2 + + order = @deplist.dependency_order + + assert_equal %w[c-2 a-1], order.map { |s| s.full_name } + end + + def test_find_name + @deplist.add @a1, @b2 + + assert_equal "a-1", @deplist.find_name("a-1").full_name + assert_equal "b-2", @deplist.find_name("b-2").full_name + + assert_nil @deplist.find_name("c-2") + end + + def test_ok_eh + assert @deplist.ok?, 'no dependencies' + + @deplist.add @b2 + + assert ! @deplist.ok?, 'unsatisfied dependency' + + @deplist.add @a1 + + assert @deplist.ok?, 'satisfied dependency' + end + + def test_ok_eh_mismatch + a1 = quick_gem 'a', '1' + a2 = quick_gem 'a', '2' + + b = quick_gem 'b', '1' do |s| s.add_dependency 'a', '= 1' end + c = quick_gem 'c', '1' do |s| s.add_dependency 'a', '= 2' end + + d = quick_gem 'd', '1' do |s| + s.add_dependency 'b' + s.add_dependency 'c' + end + + @deplist.add a1, a2, b, c, d + + assert @deplist.ok?, 'this will break on require' + end + + def test_ok_eh_redundant + @deplist.add @a1, @a3, @b2 + + @deplist.remove_by_name("a-1") + + assert @deplist.ok? + end + + def test_ok_to_remove_eh + @deplist.add @a1 + + assert @deplist.ok_to_remove?("a-1") + + @deplist.add @b2 + + assert ! @deplist.ok_to_remove?("a-1") + + @deplist.add @a2 + + assert @deplist.ok_to_remove?("a-1") + assert @deplist.ok_to_remove?("a-2") + assert @deplist.ok_to_remove?("b-2") + end + + def test_ok_to_remove_eh_after_sibling_removed + @deplist.add @a1, @a2, @b2 + + assert @deplist.ok_to_remove?("a-1") + assert @deplist.ok_to_remove?("a-2") + + @deplist.remove_by_name("a-1") + + assert ! @deplist.ok_to_remove?("a-2") + end + + def test_remove_by_name + @deplist.add @a1, @b2 + + @deplist.remove_by_name "a-1" + + assert ! @deplist.ok? + end + + def test_tsort_each_node + util_diamond + + order = %w[a-1 a-2 b-1 c-2 d-1] + + @deplist.tsort_each_node do |node| + assert_equal order.shift, node.full_name + end + + assert order.empty? + end + + def test_tsort_each_child + util_diamond + + order = %w[a-2] + + @deplist.tsort_each_child(@b1) do |node| + assert_equal order.shift, node.full_name + end + + assert order.empty? + end + + # d1 -> b1 -> a1 + # d1 -> c2 -> a2 + def util_diamond + @c2.add_dependency 'a', '>= 2' + @d1.add_dependency 'b' + + @deplist.add @a1, @a2, @b1, @c2, @d1 + end + +end + diff --git a/test/rubygems/test_gem_digest.rb b/test/rubygems/test_gem_digest.rb new file mode 100755 index 0000000000..9d825b2796 --- /dev/null +++ b/test/rubygems/test_gem_digest.rb @@ -0,0 +1,44 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require "test/unit" +require "rubygems/digest/md5" +require "rubygems/digest/sha1" +require "rubygems/digest/sha2" + +class TestRubygemsGemDigest < Test::Unit::TestCase + def test_sha256_hex_digest_works + digester = Gem::SHA256.new + assert_equal "b5d4045c3f466fa91fe2cc6abe79232a1a57cdf104f7a26e716e0a1e2789df78", digester.hexdigest("ABC") + end + + def test_sha256_digest_works + digester = Gem::SHA256.new + assert_equal "\265\324\004\\?Fo\251\037\342\314j\276y#*\032W\315\361\004\367\242nqn\n\036'\211\337x", + digester.digest("ABC") + end + + def test_sha1_hex_digest_works + digester = Gem::SHA1.new + assert_equal "3c01bdbb26f358bab27f267924aa2c9a03fcfdb8", digester.hexdigest("ABC") + end + + def test_sha1_digest_works + digester = Gem::SHA1.new + assert_equal "<\001\275\273&\363X\272\262\177&y$\252,\232\003\374\375\270", digester.digest("ABC") + end + + def test_md5_hex_digest_works + digester = Gem::MD5.new + assert_equal "902fbdd2b1df0c4f70b4a5d23525e932", digester.hexdigest("ABC") + end + + def test_md5_digest_works + digester = Gem::MD5.new + assert_equal "\220/\275\322\261\337\fOp\264\245\3225%\3512", digester.digest("ABC") + end +end
\ No newline at end of file diff --git a/test/rubygems/test_gem_doc_manager.rb b/test/rubygems/test_gem_doc_manager.rb new file mode 100644 index 0000000000..e52fb9f0cd --- /dev/null +++ b/test/rubygems/test_gem_doc_manager.rb @@ -0,0 +1,32 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/doc_manager' + +class TestGemDocManager < RubyGemTestCase + + def setup + super + + @spec = quick_gem 'a' + @manager = Gem::DocManager.new(@spec) + end + + def test_uninstall_doc_unwritable + orig_mode = File.stat(@spec.installation_path).mode + File.chmod 0, @spec.installation_path + + assert_raise Gem::FilePermissionError do + @manager.uninstall_doc + end + ensure + File.chmod orig_mode, @spec.installation_path + end + +end + diff --git a/test/rubygems/test_gem_ext_configure_builder.rb b/test/rubygems/test_gem_ext_configure_builder.rb new file mode 100644 index 0000000000..c32aa2e23f --- /dev/null +++ b/test/rubygems/test_gem_ext_configure_builder.rb @@ -0,0 +1,84 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/ext' + +class TestGemExtConfigureBuilder < RubyGemTestCase + + def setup + super + + @makefile_body = "all:\n\t@echo ok\ninstall:\n\t@echo ok" + + @ext = File.join @tempdir, 'ext' + @dest_path = File.join @tempdir, 'prefix' + + FileUtils.mkdir_p @ext + FileUtils.mkdir_p @dest_path + end + + def test_self_build + return if RUBY_PLATFORM =~ /mswin/ # HACK + + File.open File.join(@ext, './configure'), 'w' do |configure| + configure.puts "#!/bin/sh\necho \"#{@makefile_body}\" > Makefile" + end + + output = [] + + Dir.chdir @ext do + Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output + end + + expected = [ + "sh ./configure --prefix=#{@dest_path}", + "", "make", "ok\n", "make install", "ok\n" + ] + + assert_equal expected, output + end + + def test_self_build_fail + return if RUBY_PLATFORM =~ /mswin/ # HACK + output = [] + + error = assert_raise Gem::InstallError do + Dir.chdir @ext do + Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output + end + end + + expected = %r|configure failed: + +sh \./configure --prefix=#{@dest_path} +.*?: \./configure: No such file or directory +| + + assert_match expected, error.message + + assert_equal "sh ./configure --prefix=#{@dest_path}", output.shift + assert_match %r|\./configure: No such file or directory\n|, output.shift + assert_equal true, output.empty? + end + + def test_self_build_has_makefile + File.open File.join(@ext, 'Makefile'), 'w' do |makefile| + makefile.puts @makefile_body + end + + output = [] + Dir.chdir @ext do + Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output + end + + case RUBY_PLATFORM + when /mswin/ then + assert_equal 'nmake', output[0] + assert_equal 'nmake install', output[2] + else + assert_equal 'make', output[0] + assert_equal 'make install', output[2] + end + end + +end + diff --git a/test/rubygems/test_gem_ext_ext_conf_builder.rb b/test/rubygems/test_gem_ext_ext_conf_builder.rb new file mode 100644 index 0000000000..fb21fa0755 --- /dev/null +++ b/test/rubygems/test_gem_ext_ext_conf_builder.rb @@ -0,0 +1,122 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/ext' + +class TestGemExtExtConfBuilder < RubyGemTestCase + + def setup + super + + @ext = File.join @tempdir, 'ext' + @dest_path = File.join @tempdir, 'prefix' + + FileUtils.mkdir_p @ext + FileUtils.mkdir_p @dest_path + end + + def test_class_build + File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf| + extconf.puts "require 'mkmf'\ncreate_makefile 'foo'" + end + + output = [] + + Dir.chdir @ext do + Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output + end + + expected = [ + "ruby extconf.rb", + "creating Makefile\n", + "make", + "make: Nothing to be done for `all'.\n", + "make install", + "make: Nothing to be done for `install'.\n" + ] + + assert_match(/^#{Gem.ruby} extconf.rb/, output[0]) + assert_equal "creating Makefile\n", output[1] + case RUBY_PLATFORM + when /mswin/ then + assert_equal "nmake", output[2] + assert_equal "nmake install", output[4] + else + assert_equal "make", output[2] + assert_equal "make install", output[4] + end + end + + def test_class_build_extconf_fail + File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf| + extconf.puts "require 'mkmf'" + extconf.puts "have_library 'nonexistent' or abort 'need libnonexistent'" + extconf.puts "create_makefile 'foo'" + end + + output = [] + + error = assert_raise Gem::InstallError do + Dir.chdir @ext do + Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output + end + end + + assert_match(/\Aextconf failed: + +#{Gem.ruby} extconf.rb.* +checking for main\(\) in .*?nonexistent/m, error.message) + + assert_match(/^#{Gem.ruby} extconf.rb/, output[0]) + end + + def test_class_make + output = [] + makefile_path = File.join(@ext, 'Makefile') + File.open makefile_path, 'w' do |makefile| + makefile.puts "RUBYARCHDIR = $(foo)$(target_prefix)" + makefile.puts "RUBYLIBDIR = $(bar)$(target_prefix)" + makefile.puts "all:" + makefile.puts "install:" + end + + Dir.chdir @ext do + Gem::Ext::ExtConfBuilder.make @ext, output + end + + case RUBY_PLATFORM + when /mswin/ then + assert_equal 'nmake', output[0] + assert_equal 'nmake install', output[2] + else + assert_equal 'make', output[0] + assert_equal 'make install', output[2] + end + + edited_makefile = <<-EOF +RUBYARCHDIR = #{@ext}$(target_prefix) +RUBYLIBDIR = #{@ext}$(target_prefix) +all: +install: + EOF + + assert_equal edited_makefile, File.read(makefile_path) + end + + def test_class_make_no_Makefile + error = assert_raise Gem::InstallError do + Dir.chdir @ext do + Gem::Ext::ExtConfBuilder.make @ext, ['output'] + end + end + + expected = <<-EOF.strip +Makefile not found: + +output + EOF + + assert_equal expected, error.message + end + +end + diff --git a/test/rubygems/test_gem_ext_rake_builder.rb b/test/rubygems/test_gem_ext_rake_builder.rb new file mode 100644 index 0000000000..cd63106077 --- /dev/null +++ b/test/rubygems/test_gem_ext_rake_builder.rb @@ -0,0 +1,73 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/ext' + +class TestGemExtRakeBuilder < RubyGemTestCase + + def setup + super + + @ext = File.join @tempdir, 'ext' + @dest_path = File.join @tempdir, 'prefix' + + FileUtils.mkdir_p @ext + FileUtils.mkdir_p @dest_path + end + + def test_class_build + File.open File.join(@ext, 'mkrf_conf.rb'), 'w' do |mkrf_conf| + mkrf_conf.puts <<-EO_MKRF + File.open("Rakefile","w") do |f| + f.puts "task :default" + end + EO_MKRF + end + + output = [] + realdir = nil # HACK /tmp vs. /private/tmp + + Dir.chdir @ext do + realdir = Dir.pwd + Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', nil, @dest_path, output + end + + expected = [ + "#{Gem.ruby} mkrf_conf.rb", + "", + "rake RUBYARCHDIR=#{@dest_path} RUBYLIBDIR=#{@dest_path}", + "(in #{realdir})\n" + ] + + assert_equal expected, output + end + + def test_class_build_fail + File.open File.join(@ext, 'mkrf_conf.rb'), 'w' do |mkrf_conf| + mkrf_conf.puts <<-EO_MKRF + File.open("Rakefile","w") do |f| + f.puts "task :default do abort 'fail' end" + end + EO_MKRF + end + + output = [] + + error = assert_raise Gem::InstallError do + Dir.chdir @ext do + Gem::Ext::RakeBuilder.build "mkrf_conf.rb", nil, @dest_path, output + end + end + + expected = <<-EOF.strip +rake failed: + +#{Gem.ruby} mkrf_conf.rb + +rake RUBYARCHDIR=#{@dest_path} RUBYLIBDIR=#{@dest_path} + EOF + + assert_equal expected, error.message.split("\n")[0..4].join("\n") + end + +end + diff --git a/test/rubygems/test_gem_format.rb b/test/rubygems/test_gem_format.rb new file mode 100644 index 0000000000..2b7d821952 --- /dev/null +++ b/test/rubygems/test_gem_format.rb @@ -0,0 +1,51 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require File.join(File.expand_path(File.dirname(__FILE__)), 'simple_gem') +require 'rubygems/format' + +class TestGemFormat < RubyGemTestCase + + def setup + super + + @simple_gem = SIMPLE_GEM + end + + def test_from_file_by_path_nonexistent + assert_raise Gem::Exception do + Gem::Format.from_file_by_path '/nonexistent' + end + end + + def test_from_io_garbled + e = assert_raise Gem::Package::FormatError do + # subtly bogus input + Gem::Format.from_io(StringIO.new(@simple_gem.upcase)) + end + + assert_equal 'No metadata found!', e.message + + e = assert_raise Gem::Package::FormatError do + # Totally bogus input + Gem::Format.from_io(StringIO.new(@simple_gem.reverse)) + end + + assert_equal 'No metadata found!', e.message + + e = assert_raise Gem::Package::FormatError do + # This was intentionally screws up YAML parsing. + Gem::Format.from_io(StringIO.new(@simple_gem.gsub(/:/, "boom"))) + end + + assert_equal 'No metadata found!', e.message + end + +end + + diff --git a/test/rubygems/test_gem_gem_path_searcher.rb b/test/rubygems/test_gem_gem_path_searcher.rb new file mode 100644 index 0000000000..d35416e867 --- /dev/null +++ b/test/rubygems/test_gem_gem_path_searcher.rb @@ -0,0 +1,57 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/gem_path_searcher' + +class Gem::GemPathSearcher + attr_accessor :gemspecs + attr_accessor :lib_dirs + + public :init_gemspecs + public :matching_file + public :lib_dirs_for +end + +class TestGemGemPathSearcher < RubyGemTestCase + + def setup + super + + @foo1 = quick_gem 'foo', '0.1' do |s| + s.require_paths << 'lib2' + s.files << 'lib/foo.rb' + end + + path = File.join 'gems', @foo1.full_name, 'lib', 'foo.rb' + write_file(path) { |fp| fp.puts "# #{path}" } + + @foo2 = quick_gem 'foo', '0.2' + @bar1 = quick_gem 'bar', '0.1' + @bar2 = quick_gem 'bar', '0.2' + + Gem.source_index = util_setup_source_info_cache @foo1, @foo2, @bar1, @bar2 + + @gps = Gem::GemPathSearcher.new + end + + def test_find + assert_equal @foo1, @gps.find('foo') + end + + def test_init_gemspecs + assert_equal [@bar2, @bar1, @foo2, @foo1], @gps.init_gemspecs + end + + def test_lib_dirs_for + lib_dirs = @gps.lib_dirs_for(@foo1) + expected = File.join @gemhome, 'gems', @foo1.full_name, '{lib,lib2}' + + assert_equal expected, lib_dirs + end + + def test_matching_file + assert !@gps.matching_file(@foo1, 'bar') + assert @gps.matching_file(@foo1, 'foo') + end + +end + diff --git a/test/rubygems/test_gem_gem_runner.rb b/test/rubygems/test_gem_gem_runner.rb new file mode 100644 index 0000000000..4e3239f015 --- /dev/null +++ b/test/rubygems/test_gem_gem_runner.rb @@ -0,0 +1,35 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/gem_runner' + +class TestGemGemRunner < RubyGemTestCase + + def test_do_configuration + Gem.clear_paths + + temp_conf = File.join @tempdir, '.gemrc' + + other_gem_path = File.join @tempdir, 'other_gem_path' + other_gem_home = File.join @tempdir, 'other_gem_home' + + Gem.ensure_gem_subdirectories other_gem_path + Gem.ensure_gem_subdirectories other_gem_home + + File.open temp_conf, 'w' do |fp| + fp.puts "gem: --commands" + fp.puts "gemhome: #{other_gem_home}" + fp.puts "gempath:" + fp.puts " - #{other_gem_path}" + fp.puts "rdoc: --all" + end + + gr = Gem::GemRunner.new + gr.send :do_configuration, %W[--config-file #{temp_conf}] + + assert_equal [other_gem_path, other_gem_home], Gem.path + assert_equal %w[--commands], Gem::Command.extra_args + assert_equal %w[--all], Gem::DocManager.configured_args + end + +end + diff --git a/test/rubygems/test_gem_indexer.rb b/test/rubygems/test_gem_indexer.rb new file mode 100644 index 0000000000..de509c6b97 --- /dev/null +++ b/test/rubygems/test_gem_indexer.rb @@ -0,0 +1,103 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') + +require 'rubygems/indexer' + +unless ''.respond_to? :to_xs then + warn "Gem::Indexer tests are being skipped. Install builder gem." +end + +class TestGemIndexer < RubyGemTestCase + + def setup + super + + util_make_gems + + gems = File.join(@tempdir, 'gems') + FileUtils.mkdir_p gems + cache_gems = File.join @gemhome, 'cache', '*.gem' + FileUtils.mv Dir[cache_gems], gems + + @indexer = Gem::Indexer.new @tempdir + end + + def test_initialize + assert_equal @tempdir, @indexer.dest_directory + assert_equal File.join(Dir.tmpdir, "gem_generate_index_#{$$}"), + @indexer.directory + end + + def test_generate_index + use_ui @ui do + @indexer.generate_index + end + + assert File.exist?(File.join(@tempdir, 'yaml')) + assert File.exist?(File.join(@tempdir, 'yaml.Z')) + assert File.exist?(File.join(@tempdir, "Marshal.#{@marshal_version}")) + assert File.exist?(File.join(@tempdir, "Marshal.#{@marshal_version}.Z")) + + quickdir = File.join @tempdir, 'quick' + marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}" + + assert File.directory?(quickdir) + assert File.directory?(marshal_quickdir) + assert File.exist?(File.join(quickdir, "index")) + assert File.exist?(File.join(quickdir, "index.rz")) + assert File.exist?(File.join(quickdir, "#{@a0_0_1.full_name}.gemspec.rz")) + assert File.exist?(File.join(marshal_quickdir, "#{@a0_0_1.full_name}.gemspec.rz")) + assert File.exist?(File.join(quickdir, "#{@a0_0_2.full_name}.gemspec.rz")) + assert File.exist?(File.join(marshal_quickdir, "#{@a0_0_2.full_name}.gemspec.rz")) + assert File.exist?(File.join(quickdir, "#{@b0_0_2.full_name}.gemspec.rz")) + assert File.exist?(File.join(quickdir, "#{@c1_2.full_name}.gemspec.rz")) + assert !File.exist?(File.join(quickdir, "#{@c1_2.full_name}.gemspec")) + assert !File.exist?(File.join(marshal_quickdir, "#{@c1_2.full_name}.gemspec")) + end + + def test_generate_index_ui + use_ui @ui do + @indexer.generate_index + end + + expected = <<-EOF +Generating index for 4 gems in #{@tempdir} +.... +Loaded all gems +Generating master indexes (this may take a while) + EOF + + assert_equal expected, @ui.output + assert_equal '', @ui.error + end + + def test_generate_index_contents + use_ui @ui do + @indexer.generate_index + end + + yaml_path = File.join(@tempdir, 'yaml') + dump_path = File.join(@tempdir, "Marshal.#{@marshal_version}") + + yaml_index = YAML.load_file(yaml_path) + dump_str = nil + File.open dump_path, 'rb' do |fp| dump_str = fp.read end + dump_index = Marshal.load dump_str + + dump_index.each do |_,gem| + gem.send :remove_instance_variable, :@loaded + gem.send :remove_instance_variable, :@original_platform + end + + assert_equal yaml_index, dump_index, + "expected YAML and Marshal to produce identical results" + end + +end if ''.respond_to? :to_xs + diff --git a/test/rubygems/test_gem_install_update_options.rb b/test/rubygems/test_gem_install_update_options.rb new file mode 100644 index 0000000000..dafdf65920 --- /dev/null +++ b/test/rubygems/test_gem_install_update_options.rb @@ -0,0 +1,40 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/install_update_options' +require 'rubygems/command' + +class TestGemInstallUpdateOptions < RubyGemTestCase + + def setup + super + + @cmd = Gem::Command.new 'dummy', 'dummy' + @cmd.extend Gem::InstallUpdateOptions + end + + def test_add_install_update_options + @cmd.add_install_update_options + + args = %w[-i /install_to --rdoc --ri -E -f -t -w -P HighSecurity + --ignore-dependencies --include-dependencies] + + assert @cmd.handles?(args) + end + + def test_security_policy + @cmd.add_install_update_options + + @cmd.handle_options %w[-P HighSecurity] + + assert_equal Gem::Security::HighSecurity, @cmd.options[:security_policy] + end + + def test_security_policy_unknown + @cmd.add_install_update_options + + assert_raise OptionParser::InvalidArgument do + @cmd.handle_options %w[-P UnknownSecurity] + end + end + +end diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb new file mode 100644 index 0000000000..05e38f67f8 --- /dev/null +++ b/test/rubygems/test_gem_installer.rb @@ -0,0 +1,796 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/installer' + +class Gem::Installer + attr_writer :format + attr_writer :gem_dir + attr_writer :gem_home + attr_writer :env_shebang + attr_writer :ignore_dependencies + attr_writer :security_policy + attr_writer :spec + attr_writer :wrappers +end + +class TestGemInstaller < RubyGemTestCase + + def setup + super + + @spec = quick_gem "a" + @gem = File.join @tempdir, "#{@spec.full_name}.gem" + + util_build_gem @spec + FileUtils.mv File.join(@gemhome, 'cache', "#{@spec.full_name}.gem"), + @tempdir + + @installer = Gem::Installer.new @gem + @installer.gem_dir = util_gem_dir + @installer.gem_home = @gemhome + @installer.spec = @spec + end + + def util_gem_dir(version = '0.0.2') + File.join @gemhome, "gems", "a-#{version}" # HACK + end + + def util_gem_bindir(version = '0.0.2') + File.join util_gem_dir(version), "bin" + end + + def util_inst_bindir + File.join @gemhome, "bin" + end + + def util_make_exec(version = '0.0.2', shebang = "#!/usr/bin/ruby") + @spec.executables = ["my_exec"] + + FileUtils.mkdir_p util_gem_bindir(version) + exec_file = File.join(util_gem_bindir(version), "my_exec") + File.open exec_file, 'w' do |f| + f.puts shebang + end + end + + def test_app_script_text + util_make_exec '0.0.2', '' + + expected = <<-EOF +#!#{Gem.ruby} +# +# This file was generated by RubyGems. +# +# The application 'a' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = \">= 0\" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'a', version +load 'my_exec' + EOF + + wrapper = @installer.app_script_text 'my_exec' + assert_equal expected, wrapper + end + + def test_build_extensions_none + use_ui @ui do + @installer.build_extensions + end + + assert_equal '', @ui.output + assert_equal '', @ui.error + + assert !File.exist?('gem_make.out') + end + + def test_build_extensions_extconf_bad + @spec.extensions << 'extconf.rb' + + e = assert_raise Gem::Installer::ExtensionBuildError do + use_ui @ui do + @installer.build_extensions + end + end + + assert_match(/\AERROR: Failed to build gem native extension.$/, e.message) + + assert_equal "Building native extensions. This could take a while...\n", + @ui.output + assert_equal '', @ui.error + + gem_make_out = File.join @gemhome, 'gems', @spec.full_name, 'gem_make.out' + expected = <<-EOF +#{Gem.ruby} extconf.rb +#{Gem.ruby}: No such file or directory -- extconf.rb (LoadError) + EOF + + assert_equal expected, File.read(gem_make_out) + end + + def test_build_extensions_unsupported + @spec.extensions << nil + + e = assert_raise Gem::Installer::ExtensionBuildError do + use_ui @ui do + @installer.build_extensions + end + end + + assert_match(/^No builder for extension ''$/, e.message) + + assert_equal "Building native extensions. This could take a while...\n", + @ui.output + assert_equal '', @ui.error + + assert_equal "No builder for extension ''\n", File.read('gem_make.out') + ensure + FileUtils.rm_f 'gem_make.out' + end + + def test_ensure_dependency + dep = Gem::Dependency.new 'a', '>= 0.0.2' + assert @installer.ensure_dependency(@spec, dep) + + dep = Gem::Dependency.new 'b', '> 0.0.2' + e = assert_raise Gem::InstallError do + @installer.ensure_dependency @spec, dep + end + + assert_equal 'a requires b (> 0.0.2)', e.message + end + + def test_expand_and_validate_gem_dir + @installer.gem_dir = '/nonexistent' + expanded_gem_dir = @installer.send(:expand_and_validate_gem_dir) + if win_platform? + expected = File.join(Config::CONFIG['bindir'][0..2], 'nonexistent').downcase + expanded_gem_dir = expanded_gem_dir.downcase + else + expected = '/nonexistent' + end + + assert_equal expected, expanded_gem_dir + end + + def test_extract_files + format = Object.new + def format.file_entries + [[{'size' => 7, 'mode' => 0400, 'path' => 'thefile'}, 'thefile']] + end + + @installer.format = format + + @installer.extract_files + + assert_equal 'thefile', File.read(File.join(util_gem_dir, 'thefile')) + end + + def test_extract_files_bad_dest + @installer.gem_dir = 'somedir' + @installer.format = nil + e = assert_raise ArgumentError do + @installer.extract_files + end + + assert_equal 'format required to extract from', e.message + end + + def test_extract_files_relative + format = Object.new + def format.file_entries + [[{'size' => 10, 'mode' => 0644, 'path' => '../thefile'}, '../thefile']] + end + + @installer.format = format + + e = assert_raise Gem::InstallError do + @installer.extract_files + end + + assert_equal "attempt to install file into \"../thefile\" under #{util_gem_dir.inspect}", + e.message + assert_equal false, File.file?(File.join(@tempdir, '../thefile')), + "You may need to remove this file if you broke the test once" + end + + def test_extract_files_absolute + format = Object.new + def format.file_entries + [[{'size' => 8, 'mode' => 0644, 'path' => '/thefile'}, '/thefile']] + end + + @installer.format = format + + e = assert_raise Gem::InstallError do + @installer.extract_files + end + + assert_equal 'attempt to install file into "/thefile"', e.message + assert_equal false, File.file?(File.join('/thefile')), + "You may need to remove this file if you broke the test once" + end + + def test_generate_bin_scripts + @installer.wrappers = true + util_make_exec + @installer.gem_dir = util_gem_dir + + @installer.generate_bin + assert_equal true, File.directory?(util_inst_bindir) + installed_exec = File.join(util_inst_bindir, "my_exec") + assert_equal true, File.exist?(installed_exec) + assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform? + + wrapper = File.read installed_exec + assert_match %r|generated by RubyGems|, wrapper + end + + def test_generate_bin_scripts_install_dir + @installer.wrappers = true + @spec.executables = ["my_exec"] + + gem_dir = File.join "#{@gemhome}2", 'gems', @spec.full_name + gem_bindir = File.join gem_dir, 'bin' + FileUtils.mkdir_p gem_bindir + File.open File.join(gem_bindir, "my_exec"), 'w' do |f| + f.puts "#!/bin/ruby" + end + + @installer.gem_home = "#{@gemhome}2" + @installer.gem_dir = gem_dir + + @installer.generate_bin + + installed_exec = File.join("#{@gemhome}2", 'bin', 'my_exec') + assert_equal true, File.exist?(installed_exec) + assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform? + + wrapper = File.read installed_exec + assert_match %r|generated by RubyGems|, wrapper + end + + def test_generate_bin_scripts_no_execs + @installer.wrappers = true + @installer.generate_bin + assert_equal false, File.exist?(util_inst_bindir) + end + + def test_generate_bin_scripts_no_perms + @installer.wrappers = true + util_make_exec + + Dir.mkdir util_inst_bindir + File.chmod 0000, util_inst_bindir + + assert_raises Gem::FilePermissionError do + @installer.generate_bin + end + + ensure + File.chmod 0700, util_inst_bindir unless $DEBUG + end + + def test_generate_bin_symlinks + return if win_platform? #Windows FS do not support symlinks + + @installer.wrappers = false + util_make_exec + @installer.gem_dir = util_gem_dir + + @installer.generate_bin + assert_equal true, File.directory?(util_inst_bindir) + installed_exec = File.join(util_inst_bindir, "my_exec") + assert_equal true, File.symlink?(installed_exec) + assert_equal(File.join(util_gem_dir, "bin", "my_exec"), + File.readlink(installed_exec)) + end + + def test_generate_bin_symlinks_no_execs + @installer.wrappers = false + @installer.generate_bin + assert_equal false, File.exist?(util_inst_bindir) + end + + def test_generate_bin_symlinks_no_perms + @installer.wrappers = false + util_make_exec + @installer.gem_dir = util_gem_dir + + Dir.mkdir util_inst_bindir + File.chmod 0000, util_inst_bindir + + assert_raises Gem::FilePermissionError do + @installer.generate_bin + end + + ensure + File.chmod 0700, util_inst_bindir unless $DEBUG + end + + def test_generate_bin_symlinks_update_newer + return if win_platform? #Windows FS do not support symlinks + + @installer.wrappers = false + util_make_exec + @installer.gem_dir = util_gem_dir + + @installer.generate_bin + installed_exec = File.join(util_inst_bindir, "my_exec") + assert_equal(File.join(util_gem_dir, "bin", "my_exec"), + File.readlink(installed_exec)) + + @spec = Gem::Specification.new do |s| + s.files = ['lib/code.rb'] + s.name = "a" + s.version = "0.0.3" + s.summary = "summary" + s.description = "desc" + s.require_path = 'lib' + end + + util_make_exec '0.0.3' + @installer.gem_dir = File.join util_gem_dir('0.0.3') + @installer.generate_bin + installed_exec = File.join(util_inst_bindir, "my_exec") + assert_equal(File.join(util_gem_bindir('0.0.3'), "my_exec"), + File.readlink(installed_exec), + "Ensure symlink moved to latest version") + end + + def test_generate_bin_symlinks_update_older + return if win_platform? #Windows FS do not support symlinks + + @installer.wrappers = false + util_make_exec + @installer.gem_dir = util_gem_dir + + @installer.generate_bin + installed_exec = File.join(util_inst_bindir, "my_exec") + assert_equal(File.join(util_gem_dir, "bin", "my_exec"), + File.readlink(installed_exec)) + + spec = Gem::Specification.new do |s| + s.files = ['lib/code.rb'] + s.name = "a" + s.version = "0.0.1" + s.summary = "summary" + s.description = "desc" + s.require_path = 'lib' + end + + util_make_exec '0.0.1' + @installer.gem_dir = util_gem_dir('0.0.1') + @installer.spec = spec + + @installer.generate_bin + + installed_exec = File.join(util_inst_bindir, "my_exec") + assert_equal(File.join(util_gem_dir('0.0.2'), "bin", "my_exec"), + File.readlink(installed_exec), + "Ensure symlink not moved") + end + + def test_generate_bin_symlinks_update_remove_wrapper + return if win_platform? #Windows FS do not support symlinks + + @installer.wrappers = true + util_make_exec + @installer.gem_dir = util_gem_dir + + @installer.generate_bin + installed_exec = File.join(util_inst_bindir, "my_exec") + assert_equal true, File.exist?(installed_exec) + + @spec = Gem::Specification.new do |s| + s.files = ['lib/code.rb'] + s.name = "a" + s.version = "0.0.3" + s.summary = "summary" + s.description = "desc" + s.require_path = 'lib' + end + + @installer.wrappers = false + util_make_exec '0.0.3' + @installer.gem_dir = util_gem_dir '0.0.3' + @installer.generate_bin + installed_exec = File.join(util_inst_bindir, "my_exec") + assert_equal(File.join(util_gem_dir('0.0.3'), "bin", "my_exec"), + File.readlink(installed_exec), + "Ensure symlink moved to latest version") + end + + def test_generate_bin_symlinks_win32 + old_arch = Config::CONFIG["arch"] + Config::CONFIG["arch"] = "win32" + @installer.wrappers = false + util_make_exec + @installer.gem_dir = util_gem_dir + + use_ui @ui do + @installer.generate_bin + end + + assert_equal true, File.directory?(util_inst_bindir) + installed_exec = File.join(util_inst_bindir, "my_exec") + assert_equal true, File.exist?(installed_exec) + + assert_match(/Unable to use symlinks on win32, installing wrapper/i, + @ui.error) + + expected_mode = win_platform? ? 0100644 : 0100755 + assert_equal expected_mode, File.stat(installed_exec).mode + + wrapper = File.read installed_exec + assert_match(/generated by RubyGems/, wrapper) + ensure + Config::CONFIG["arch"] = old_arch + end + + def test_generate_bin_uses_default_shebang + return if win_platform? #Windows FS do not support symlinks + + @installer.wrappers = true + util_make_exec + + @installer.generate_bin + + default_shebang = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']) + shebang_line = open("#{@gemhome}/bin/my_exec") { |f| f.readlines.first } + assert_match(/\A#!/, shebang_line) + assert_match(/#{default_shebang}/, shebang_line) + end + + def test_install + util_setup_gem + + use_ui @ui do + assert_equal @spec, @installer.install + end + + gemdir = File.join @gemhome, 'gems', @spec.full_name + assert File.exist?(gemdir) + + exe = File.join(gemdir, 'bin', 'executable') + assert File.exist?(exe) + exe_mode = File.stat(exe).mode & 0111 + assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform? + + assert File.exist?(File.join(gemdir, 'lib', 'code.rb')) + + assert File.exist?(File.join(gemdir, 'ext', 'a', 'Rakefile')) + + spec_file = File.join(@gemhome, 'specifications', + "#{@spec.full_name}.gemspec") + + assert_equal spec_file, @spec.loaded_from + assert File.exist?(spec_file) + end + + def test_install_bad_gem + gem = nil + + use_ui @ui do + Dir.chdir @tempdir do Gem::Builder.new(@spec).build end + gem = File.join @tempdir, "#{@spec.full_name}.gem" + end + + gem_data = File.open gem, 'rb' do |fp| fp.read 1024 end + File.open gem, 'wb' do |fp| fp.write gem_data end + + e = assert_raise Gem::InstallError do + use_ui @ui do + @installer = Gem::Installer.new gem + @installer.install + end + end + + assert_equal "invalid gem format for #{gem}", e.message + end + + def test_install_check_dependencies + @spec.add_dependency 'b', '> 5' + util_setup_gem + + use_ui @ui do + assert_raise Gem::InstallError do + @installer.install + end + end + end + + def test_install_force + use_ui @ui do + installer = Gem::Installer.new old_ruby_required, :force => true + installer.install + end + + gem_dir = File.join(@gemhome, 'gems', 'old_ruby_required-0.0.1') + assert File.exist?(gem_dir) + end + + def test_install_ignore_dependencies + @spec.add_dependency 'b', '> 5' + util_setup_gem + @installer.ignore_dependencies = true + + use_ui @ui do + assert_equal @spec, @installer.install + end + + gemdir = File.join @gemhome, 'gems', @spec.full_name + assert File.exist?(gemdir) + + exe = File.join(gemdir, 'bin', 'executable') + assert File.exist?(exe) + exe_mode = File.stat(exe).mode & 0111 + assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform? + assert File.exist?(File.join(gemdir, 'lib', 'code.rb')) + + assert File.exist?(File.join(@gemhome, 'specifications', + "#{@spec.full_name}.gemspec")) + end + + def test_install_missing_dirs + FileUtils.rm_f File.join(Gem.dir, 'cache') + FileUtils.rm_f File.join(Gem.dir, 'docs') + FileUtils.rm_f File.join(Gem.dir, 'specifications') + + use_ui @ui do + Dir.chdir @tempdir do Gem::Builder.new(@spec).build end + gem = File.join @tempdir, "#{@spec.full_name}.gem" + + @installer.install + end + + File.directory? File.join(Gem.dir, 'cache') + File.directory? File.join(Gem.dir, 'docs') + File.directory? File.join(Gem.dir, 'specifications') + + assert File.exist?(File.join(@gemhome, 'cache', "#{@spec.full_name}.gem")) + assert File.exist?(File.join(@gemhome, 'specifications', + "#{@spec.full_name}.gemspec")) + end + + def test_install_with_message + @spec.post_install_message = 'I am a shiny gem!' + + use_ui @ui do + Dir.chdir @tempdir do Gem::Builder.new(@spec).build end + + @installer.install + end + + assert_match %r|I am a shiny gem!|, @ui.output + end + + def test_install_writable + util_setup_gem + + orig_mode = File.stat(Gem.dir).mode + File.chmod 0000, Gem.dir + + e = assert_raise Gem::FilePermissionError do + @installer.install + end + + assert_equal "You don't have write permissions into the #{@gemhome} directory.", + e.message + ensure + File.chmod orig_mode, Gem.dir + end + + def test_install_wrong_ruby_version + use_ui @ui do + installer = Gem::Installer.new old_ruby_required + e = assert_raise Gem::InstallError do + installer.install + end + assert_equal 'old_ruby_required requires Ruby version = 1.4.6', + e.message + end + end + + def test_install_wrong_rubygems_version + spec = quick_gem 'old_rubygems_required', '0.0.1' do |s| + s.required_rubygems_version = '< 0.0.0' + end + + util_build_gem spec + + gem = File.join @gemhome, 'cache', "#{spec.full_name}.gem" + + use_ui @ui do + @installer = Gem::Installer.new gem + e = assert_raise Gem::InstallError do + @installer.install + end + assert_equal 'old_rubygems_required requires RubyGems version < 0.0.0', + e.message + end + end + + def test_installation_satisfies_dependency_eh + dep = Gem::Dependency.new 'a', '>= 0.0.2' + assert @installer.installation_satisfies_dependency?(dep) + + dep = Gem::Dependency.new 'a', '> 0.0.2' + assert ! @installer.installation_satisfies_dependency?(dep) + end + + def test_shebang + util_make_exec '0.0.2', "#!/usr/bin/ruby" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby}", shebang + end + + def test_shebang_arguments + util_make_exec '0.0.2', "#!/usr/bin/ruby -ws" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby} -ws", shebang + end + + def test_shebang_empty + util_make_exec '0.0.2', '' + + shebang = @installer.shebang 'my_exec' + assert_equal "#!#{Gem.ruby}", shebang + end + + def test_shebang_env + util_make_exec '0.0.2', "#!/usr/bin/env ruby" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby}", shebang + end + + def test_shebang_env_arguments + util_make_exec '0.0.2', "#!/usr/bin/env ruby -ws" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby} -ws", shebang + end + + def test_shebang_env_shebang + util_make_exec '0.0.2', '' + @installer.env_shebang = true + + shebang = @installer.shebang 'my_exec' + assert_equal "#!/usr/bin/env ruby", shebang + end + + def test_shebang_nested + util_make_exec '0.0.2', "#!/opt/local/ruby/bin/ruby" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby}", shebang + end + + def test_shebang_nested_arguments + util_make_exec '0.0.2', "#!/opt/local/ruby/bin/ruby -ws" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby} -ws", shebang + end + + def test_shebang_version + util_make_exec '0.0.2', "#!/usr/bin/ruby18" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby}", shebang + end + + def test_shebang_version_arguments + util_make_exec '0.0.2', "#!/usr/bin/ruby18 -ws" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby} -ws", shebang + end + + def test_shebang_version_env + util_make_exec '0.0.2', "#!/usr/bin/env ruby18" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby}", shebang + end + + def test_shebang_version_env_arguments + util_make_exec '0.0.2', "#!/usr/bin/env ruby18 -ws" + + shebang = @installer.shebang 'my_exec' + + assert_equal "#!#{Gem.ruby} -ws", shebang + end + + def test_unpack + util_setup_gem + + dest = File.join @gemhome, 'gems', @spec.full_name + + @installer.unpack dest + + assert File.exist?(File.join(dest, 'lib', 'code.rb')) + assert File.exist?(File.join(dest, 'bin', 'executable')) + end + + def test_write_spec + spec_dir = File.join @gemhome, 'specifications' + spec_file = File.join spec_dir, "#{@spec.full_name}.gemspec" + FileUtils.rm spec_file + assert !File.exist?(spec_file) + + @installer.spec = @spec + @installer.gem_home = @gemhome + + @installer.write_spec + + assert File.exist?(spec_file) + assert_equal @spec, eval(File.read(spec_file)) + end + + def old_ruby_required + spec = quick_gem 'old_ruby_required', '0.0.1' do |s| + s.required_ruby_version = '= 1.4.6' + end + + util_build_gem spec + + File.join @gemhome, 'cache', "#{spec.full_name}.gem" + end + + def util_setup_gem + @spec.files = File.join('lib', 'code.rb') + @spec.executables << 'executable' + @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb') + + Dir.chdir @tempdir do + FileUtils.mkdir_p 'bin' + FileUtils.mkdir_p 'lib' + FileUtils.mkdir_p File.join('ext', 'a') + File.open File.join('bin', 'executable'), 'w' do |f| f.puts '1' end + File.open File.join('lib', 'code.rb'), 'w' do |f| f.puts '1' end + File.open File.join('ext', 'a', 'mkrf_conf.rb'), 'w' do |f| + f << <<-EOF + File.open 'Rakefile', 'w' do |rf| rf.puts "task :default" end + EOF + end + + use_ui @ui do + FileUtils.rm @gem + Gem::Builder.new(@spec).build + end + end + + @installer = Gem::Installer.new @gem + end + +end + + diff --git a/test/rubygems/test_gem_local_remote_options.rb b/test/rubygems/test_gem_local_remote_options.rb new file mode 100644 index 0000000000..d5a6651ade --- /dev/null +++ b/test/rubygems/test_gem_local_remote_options.rb @@ -0,0 +1,84 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/local_remote_options' +require 'rubygems/command' + +class TestGemLocalRemoteOptions < RubyGemTestCase + + def setup + super + + @cmd = Gem::Command.new 'dummy', 'dummy' + @cmd.extend Gem::LocalRemoteOptions + end + + def test_add_local_remote_options + @cmd.add_local_remote_options + + args = %w[-l -r -b -B 10 --source http://gems.example.com -p --update-sources] + assert @cmd.handles?(args) + end + + def test_local_eh + assert_equal false, @cmd.local? + + @cmd.options[:domain] = :local + + assert_equal true, @cmd.local? + + @cmd.options[:domain] = :both + + assert_equal true, @cmd.local? + end + + def test_remote_eh + assert_equal false, @cmd.remote? + + @cmd.options[:domain] = :remote + + assert_equal true, @cmd.remote? + + @cmd.options[:domain] = :both + + assert_equal true, @cmd.remote? + end + + def test_source_option + @cmd.add_source_option + + s1 = URI.parse 'http://more-gems.example.com' + s2 = URI.parse 'http://even-more-gems.example.com' + + @cmd.handle_options %W[--source #{s1} --source #{s2}] + + assert_equal [s1, s2], Gem.sources + end + + def test_update_sources_option + @cmd.add_update_sources_option + + Gem.configuration.update_sources = false + + @cmd.handle_options %W[--update-sources] + + assert_equal true, Gem.configuration.update_sources + + @cmd.handle_options %W[--no-update-sources] + + assert_equal false, Gem.configuration.update_sources + end + + def test_source_option_bad + @cmd.add_source_option + + s1 = 'htp://more-gems.example.com' + + assert_raise OptionParser::InvalidArgument do + @cmd.handle_options %W[--source #{s1}] + end + + assert_equal %w[http://gems.example.com], Gem.sources + end + +end + diff --git a/test/rubygems/test_gem_outdated_command.rb b/test/rubygems/test_gem_outdated_command.rb new file mode 100644 index 0000000000..adcc4d1980 --- /dev/null +++ b/test/rubygems/test_gem_outdated_command.rb @@ -0,0 +1,40 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/commands/outdated_command' + +class TestGemOutdatedCommand < RubyGemTestCase + + def setup + super + + @cmd = Gem::Commands::OutdatedCommand.new + end + + def test_initialize + assert @cmd.handles?(%W[--platform #{Gem::Platform.local}]) + end + + def test_execute + local_01 = quick_gem 'foo', '0.1' + local_02 = quick_gem 'foo', '0.2' + remote_10 = quick_gem 'foo', '1.0' + remote_20 = quick_gem 'foo', '2.0' + + remote_spec_file = File.join @gemhome, 'specifications', + remote_10.full_name + ".gemspec" + FileUtils.rm remote_spec_file + + remote_spec_file = File.join @gemhome, 'specifications', + remote_20.full_name + ".gemspec" + FileUtils.rm remote_spec_file + + util_setup_source_info_cache remote_10, remote_20 + + use_ui @ui do @cmd.execute end + + assert_equal "foo (0.2 < 2.0)\n", @ui.output + assert_equal "", @ui.error + end + +end + diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb new file mode 100644 index 0000000000..4c583edf27 --- /dev/null +++ b/test/rubygems/test_gem_platform.rb @@ -0,0 +1,239 @@ +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'test/unit' +require 'rubygems/platform' +require 'rbconfig' + +class TestGemPlatform < RubyGemTestCase + + def test_self_local + util_set_arch 'i686-darwin8.10.1' + + assert_equal Gem::Platform.new(%w[x86 darwin 8]), Gem::Platform.local + end + + def test_self_match + assert Gem::Platform.match(nil), 'nil == ruby' + assert Gem::Platform.match(Gem::Platform.local), 'exact match' + assert Gem::Platform.match(Gem::Platform.local.to_s), '=~ match' + assert Gem::Platform.match(Gem::Platform::RUBY), 'ruby' + end + + def test_self_new + assert_equal Gem::Platform::RUBY, Gem::Platform.new(Gem::Platform::RUBY) + assert_equal Gem::Platform::RUBY, Gem::Platform.new(nil) + end + + def test_initialize + test_cases = { + 'amd64-freebsd6' => ['amd64', 'freebsd', '6'], + 'hppa2.0w-hpux11.31' => ['hppa2.0w', 'hpux', '11'], + 'java' => [nil, 'java', nil], + 'jruby' => [nil, 'java', nil], + 'powerpc-aix5.3.0.0' => ['powerpc', 'aix', '5'], + 'powerpc-darwin7' => ['powerpc', 'darwin', '7'], + 'powerpc-darwin8' => ['powerpc', 'darwin', '8'], + 'powerpc-linux' => ['powerpc', 'linux', nil], + 'powerpc64-linux' => ['powerpc64', 'linux', nil], + 'sparc-solaris2.10' => ['sparc', 'solaris', '2.10'], + 'sparc-solaris2.8' => ['sparc', 'solaris', '2.8'], + 'sparc-solaris2.9' => ['sparc', 'solaris', '2.9'], + 'universal-darwin8' => ['universal', 'darwin', '8'], + 'universal-darwin9' => ['universal', 'darwin', '9'], + 'i386-cygwin' => ['x86', 'cygwin', nil], + 'i686-darwin' => ['x86', 'darwin', nil], + 'i686-darwin8.4.1' => ['x86', 'darwin', '8'], + 'i386-freebsd4.11' => ['x86', 'freebsd', '4'], + 'i386-freebsd5' => ['x86', 'freebsd', '5'], + 'i386-freebsd6' => ['x86', 'freebsd', '6'], + 'i386-freebsd7' => ['x86', 'freebsd', '7'], + 'i386-java1.5' => ['x86', 'java', '1.5'], + 'x86-java1.6' => ['x86', 'java', '1.6'], + 'i386-java1.6' => ['x86', 'java', '1.6'], + 'i686-linux' => ['x86', 'linux', nil], + 'i586-linux' => ['x86', 'linux', nil], + 'i486-linux' => ['x86', 'linux', nil], + 'i386-linux' => ['x86', 'linux', nil], + 'i586-linux-gnu' => ['x86', 'linux', nil], + 'i386-linux-gnu' => ['x86', 'linux', nil], + 'i386-mingw32' => ['x86', 'mingw32', nil], + 'i386-mswin32' => ['x86', 'mswin32', nil], + 'i386-mswin32_80' => ['x86', 'mswin32', '80'], + 'i386-netbsdelf' => ['x86', 'netbsdelf', nil], + 'i386-openbsd4.0' => ['x86', 'openbsd', '4.0'], + 'i386-solaris2.10' => ['x86', 'solaris', '2.10'], + 'i386-solaris2.8' => ['x86', 'solaris', '2.8'], + 'x86_64-linux' => ['x86_64', 'linux', nil], + 'x86_64-openbsd3.9' => ['x86_64', 'openbsd', '3.9'], + 'x86_64-openbsd4.0' => ['x86_64', 'openbsd', '4.0'], + } + + test_cases.each do |arch, expected| + platform = Gem::Platform.new arch + assert_equal expected, platform.to_a, arch.inspect + end + end + + def test_initialize_command_line + expected = ['x86', 'mswin32', nil] + + platform = Gem::Platform.new 'i386-mswin32' + + assert_equal expected, platform.to_a, 'i386-mswin32' + + expected = ['x86', 'mswin32', '80'] + + platform = Gem::Platform.new 'i386-mswin32-80' + + assert_equal expected, platform.to_a, 'i386-mswin32-80' + end + + def test_initialize_mswin32_vc6 + orig_RUBY_SO_NAME = Config::CONFIG['RUBY_SO_NAME'] + Config::CONFIG['RUBY_SO_NAME'] = 'msvcrt-ruby18' + + expected = ['x86', 'mswin32', nil] + + platform = Gem::Platform.new 'i386-mswin32' + + assert_equal expected, platform.to_a, 'i386-mswin32 VC6' + ensure + Config::CONFIG['RUBY_SO_NAME'] = orig_RUBY_SO_NAME + end + + def test_initialize_platform + platform = Gem::Platform.new 'cpu-my_platform1' + expected = Gem::Platform.new platform + + assert_equal 'cpu', platform.cpu + assert_equal 'my_platform', platform.os + assert_equal '1', platform.version + end + + def test_initialize_test + platform = Gem::Platform.new 'cpu-my_platform1' + assert_equal 'cpu', platform.cpu + assert_equal 'my_platform', platform.os + assert_equal '1', platform.version + + platform = Gem::Platform.new 'cpu-other_platform1' + assert_equal 'cpu', platform.cpu + assert_equal 'other_platform', platform.os + assert_equal '1', platform.version + end + + def test_to_s + if win_platform? then + assert_equal 'x86-mswin32-60', Gem::Platform.local.to_s + else + assert_equal 'x86-darwin-8', Gem::Platform.local.to_s + end + end + + def test_equals2 + my = Gem::Platform.new %w[cpu my_platform 1] + other = Gem::Platform.new %w[cpu other_platform 1] + + assert_equal my, my + assert_not_equal my, other + assert_not_equal other, my + end + + def test_equals3 + my = Gem::Platform.new %w[cpu my_platform 1] + other = Gem::Platform.new %w[cpu other_platform 1] + + assert(my === my) + assert !(other === my) + assert !(my === other) + end + + def test_equals3_cpu + ppc_darwin8 = Gem::Platform.new 'powerpc-darwin8.0' + uni_darwin8 = Gem::Platform.new 'universal-darwin8.0' + x86_darwin8 = Gem::Platform.new 'i686-darwin8.0' + + util_set_arch 'powerpc-darwin8' + assert((ppc_darwin8 === Gem::Platform.local), 'powerpc =~ universal') + assert((uni_darwin8 === Gem::Platform.local), 'powerpc =~ universal') + assert !(x86_darwin8 === Gem::Platform.local), 'powerpc =~ universal' + + util_set_arch 'i686-darwin8' + assert !(ppc_darwin8 === Gem::Platform.local), 'powerpc =~ universal' + assert((uni_darwin8 === Gem::Platform.local), 'x86 =~ universal') + assert((x86_darwin8 === Gem::Platform.local), 'powerpc =~ universal') + + util_set_arch 'universal-darwin8' + assert((ppc_darwin8 === Gem::Platform.local), 'universal =~ ppc') + assert((uni_darwin8 === Gem::Platform.local), 'universal =~ universal') + assert((x86_darwin8 === Gem::Platform.local), 'universal =~ x86') + end + + def test_equals3_version + util_set_arch 'i686-darwin8' + + x86_darwin = Gem::Platform.new ['x86', 'darwin', nil] + x86_darwin7 = Gem::Platform.new ['x86', 'darwin', '7'] + x86_darwin8 = Gem::Platform.new ['x86', 'darwin', '8'] + x86_darwin9 = Gem::Platform.new ['x86', 'darwin', '9'] + + assert((x86_darwin === Gem::Platform.local), 'x86_darwin === x86_darwin8') + assert((x86_darwin8 === Gem::Platform.local), 'x86_darwin8 === x86_darwin8') + + assert !(x86_darwin7 === Gem::Platform.local), 'x86_darwin7 === x86_darwin8' + assert !(x86_darwin9 === Gem::Platform.local), 'x86_darwin9 === x86_darwin8' + end + + def test_equals_tilde + util_set_arch 'i386-mswin32' + + assert_match 'mswin32', Gem::Platform.local + assert_match 'i386-mswin32', Gem::Platform.local + + # oddballs + assert_match 'i386-mswin32-mq5.3', Gem::Platform.local + assert_match 'i386-mswin32-mq6', Gem::Platform.local + deny_match 'win32-1.8.2-VC7', Gem::Platform.local + deny_match 'win32-1.8.4-VC6', Gem::Platform.local + deny_match 'win32-source', Gem::Platform.local + deny_match 'windows', Gem::Platform.local + + util_set_arch 'i686-linux' + assert_match 'i486-linux', Gem::Platform.local + assert_match 'i586-linux', Gem::Platform.local + assert_match 'i686-linux', Gem::Platform.local + + util_set_arch 'i686-darwin8' + assert_match 'i686-darwin8.4.1', Gem::Platform.local + assert_match 'i686-darwin8.8.2', Gem::Platform.local + + util_set_arch 'java' + assert_match 'java', Gem::Platform.local + assert_match 'jruby', Gem::Platform.local + + util_set_arch 'powerpc-darwin' + assert_match 'powerpc-darwin', Gem::Platform.local + + util_set_arch 'powerpc-darwin7' + assert_match 'powerpc-darwin7.9.0', Gem::Platform.local + + util_set_arch 'powerpc-darwin8' + assert_match 'powerpc-darwin8.10.0', Gem::Platform.local + + util_set_arch 'sparc-solaris2.8' + assert_match 'sparc-solaris2.8-mq5.3', Gem::Platform.local + end + + def assert_match(pattern, platform, message = '') + full_message = build_message message, "<?> expected to be =~\n<?>.", + platform, pattern + assert_block(full_message) { platform =~ pattern } + end + + def deny_match(pattern, platform, message = '') + full_message = build_message message, "<?> expected to be !~\n<?>.", + platform, pattern + assert_block(full_message) { platform !~ pattern } + end + +end + diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb new file mode 100644 index 0000000000..83865e8033 --- /dev/null +++ b/test/rubygems/test_gem_remote_fetcher.rb @@ -0,0 +1,417 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'webrick' +require 'zlib' +require 'rubygems/remote_fetcher' + +# = Testing Proxy Settings +# +# These tests check the proper proxy server settings by running two +# web servers. The web server at http://localhost:#{SERVER_PORT} +# represents the normal gem server and returns a gemspec with a rake +# version of 0.4.11. The web server at http://localhost:#{PROXY_PORT} +# represents the proxy server and returns a different dataset where +# rake has version 0.4.2. This allows us to detect which server is +# returning the data. +# +# Note that the proxy server is not a *real* proxy server. But our +# software doesn't really care, as long as we hit the proxy URL when a +# proxy is configured. +# +class TestGemRemoteFetcher < RubyGemTestCase + + include Gem::DefaultUserInteraction + + SERVER_DATA = <<-EOY +--- !ruby/object:Gem::Cache +gems: + rake-0.4.11: !ruby/object:Gem::Specification + rubygems_version: "0.7" + specification_version: 1 + name: rake + version: !ruby/object:Gem::Version + version: 0.4.11 + date: 2004-11-12 + summary: Ruby based make-like utility. + require_paths: + - lib + author: Jim Weirich + email: jim@weirichhouse.org + homepage: http://rake.rubyforge.org + rubyforge_project: rake + description: Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax. + autorequire: + default_executable: rake + bindir: bin + has_rdoc: true + required_ruby_version: !ruby/object:Gem::Version::Requirement + requirements: + - + - ">" + - !ruby/object:Gem::Version + version: 0.0.0 + version: + platform: ruby + files: + - README + test_files: [] + library_stubs: + rdoc_options: + extra_rdoc_files: + executables: + - rake + extensions: [] + requirements: [] + dependencies: [] + EOY + + PROXY_DATA = SERVER_DATA.gsub(/0.4.11/, '0.4.2') + + # don't let 1.8 and 1.9 autotest collide + RUBY_VERSION =~ /(\d+)\.(\d+)\.(\d+)/ + PROXY_PORT = 12345 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i + SERVER_PORT = 23456 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i + + def setup + super + self.class.start_servers + self.class.enable_yaml = true + self.class.enable_zip = false + ENV.delete 'http_proxy' + ENV.delete 'HTTP_PROXY' + ENV.delete 'http_proxy_user' + ENV.delete 'HTTP_PROXY_USER' + ENV.delete 'http_proxy_pass' + ENV.delete 'HTTP_PROXY_PASS' + + base_server_uri = "http://localhost:#{SERVER_PORT}" + @proxy_uri = "http://localhost:#{PROXY_PORT}" + + @server_uri = base_server_uri + "/yaml" + @server_z_uri = base_server_uri + "/yaml.Z" + + Gem::RemoteFetcher.instance_variable_set :@fetcher, nil + end + + def test_self_fetcher + fetcher = Gem::RemoteFetcher.fetcher + assert_not_nil fetcher + assert_kind_of Gem::RemoteFetcher, fetcher + end + + def test_self_fetcher_with_proxy + proxy_uri = 'http://proxy.example.com' + Gem.configuration[:http_proxy] = proxy_uri + fetcher = Gem::RemoteFetcher.fetcher + assert_not_nil fetcher + assert_kind_of Gem::RemoteFetcher, fetcher + assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri).to_s + end + + def test_self_fetcher_with_proxy_URI + proxy_uri = URI.parse 'http://proxy.example.com' + Gem.configuration[:http_proxy] = proxy_uri + fetcher = Gem::RemoteFetcher.fetcher + assert_not_nil fetcher + assert_kind_of Gem::RemoteFetcher, fetcher + assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri) + end + + def test_fetch_size_bad_uri + fetcher = Gem::RemoteFetcher.new nil + + e = assert_raise ArgumentError do + fetcher.fetch_size 'gems.example.com/yaml' + end + + assert_equal 'uri is not an HTTP URI', e.message + end + + def test_fetch_size_socket_error + fetcher = Gem::RemoteFetcher.new nil + def fetcher.connect_to(host, port) + raise SocketError + end + + e = assert_raise Gem::RemoteFetcher::FetchError do + fetcher.fetch_size 'http://gems.example.com/yaml' + end + + assert_equal 'SocketError (SocketError)', e.message + end + + def test_no_proxy + use_ui @ui do + fetcher = Gem::RemoteFetcher.new nil + assert_data_from_server fetcher.fetch_path(@server_uri) + assert_equal SERVER_DATA.size, fetcher.fetch_size(@server_uri) + end + end + + def test_explicit_proxy + use_ui @ui do + fetcher = Gem::RemoteFetcher.new @proxy_uri + assert_equal PROXY_DATA.size, fetcher.fetch_size(@server_uri) + assert_data_from_proxy fetcher.fetch_path(@server_uri) + end + end + + def test_explicit_proxy_with_user_auth + use_ui @ui do + uri = URI.parse @proxy_uri + uri.user, uri.password = 'foo', 'bar' + fetcher = Gem::RemoteFetcher.new uri.to_s + proxy = fetcher.instance_variable_get("@proxy_uri") + assert_equal 'foo', proxy.user + assert_equal 'bar', proxy.password + assert_data_from_proxy fetcher.fetch_path(@server_uri) + end + + use_ui @ui do + uri = URI.parse @proxy_uri + uri.user, uri.password = 'domain%5Cuser', 'bar' + fetcher = Gem::RemoteFetcher.new uri.to_s + proxy = fetcher.instance_variable_get("@proxy_uri") + assert_equal 'domain\user', URI.unescape(proxy.user) + assert_equal 'bar', proxy.password + assert_data_from_proxy fetcher.fetch_path(@server_uri) + end + + use_ui @ui do + uri = URI.parse @proxy_uri + uri.user, uri.password = 'user', 'my%20pass' + fetcher = Gem::RemoteFetcher.new uri.to_s + proxy = fetcher.instance_variable_get("@proxy_uri") + assert_equal 'user', proxy.user + assert_equal 'my pass', URI.unescape(proxy.password) + assert_data_from_proxy fetcher.fetch_path(@server_uri) + end + end + + def test_explicit_proxy_with_user_auth_in_env + use_ui @ui do + ENV['http_proxy'] = @proxy_uri + ENV['http_proxy_user'] = 'foo' + ENV['http_proxy_pass'] = 'bar' + fetcher = Gem::RemoteFetcher.new nil + proxy = fetcher.instance_variable_get("@proxy_uri") + assert_equal 'foo', proxy.user + assert_equal 'bar', proxy.password + assert_data_from_proxy fetcher.fetch_path(@server_uri) + end + + use_ui @ui do + ENV['http_proxy'] = @proxy_uri + ENV['http_proxy_user'] = 'foo\user' + ENV['http_proxy_pass'] = 'my bar' + fetcher = Gem::RemoteFetcher.new nil + proxy = fetcher.instance_variable_get("@proxy_uri") + assert_equal 'foo\user', URI.unescape(proxy.user) + assert_equal 'my bar', URI.unescape(proxy.password) + assert_data_from_proxy fetcher.fetch_path(@server_uri) + end + end + + def test_fetch_path_io_error + fetcher = Gem::RemoteFetcher.new nil + + def fetcher.open_uri_or_path(uri) raise EOFError; end + + e = assert_raise Gem::RemoteFetcher::FetchError do + fetcher.fetch_path 'uri' + end + + assert_equal 'EOFError: EOFError reading uri', e.message + end + + def test_fetch_path_socket_error + fetcher = Gem::RemoteFetcher.new nil + + def fetcher.open_uri_or_path(uri) raise SocketError; end + + e = assert_raise Gem::RemoteFetcher::FetchError do + fetcher.fetch_path 'uri' + end + + assert_equal 'SocketError: SocketError reading uri', e.message + end + + def test_fetch_path_system_call_error + fetcher = Gem::RemoteFetcher.new nil + + def fetcher.open_uri_or_path(uri); + raise Errno::ECONNREFUSED, 'connect(2)' + end + + e = assert_raise Gem::RemoteFetcher::FetchError do + fetcher.fetch_path 'uri' + end + + assert_match %r|\AErrno::ECONNREFUSED: .* - connect\(2\) reading uri\z|, + e.message + end + + def test_get_proxy_from_env_empty + orig_env_HTTP_PROXY = ENV['HTTP_PROXY'] + orig_env_http_proxy = ENV['http_proxy'] + + ENV['HTTP_PROXY'] = '' + ENV.delete 'http_proxy' + + fetcher = Gem::RemoteFetcher.new nil + + assert_equal nil, fetcher.send(:get_proxy_from_env) + + ensure + orig_env_HTTP_PROXY.nil? ? ENV.delete('HTTP_PROXY') : + ENV['HTTP_PROXY'] = orig_env_HTTP_PROXY + orig_env_http_proxy.nil? ? ENV.delete('http_proxy') : + ENV['http_proxy'] = orig_env_http_proxy + end + + def test_implicit_no_proxy + use_ui @ui do + ENV['http_proxy'] = 'http://fakeurl:12345' + fetcher = Gem::RemoteFetcher.new :no_proxy + assert_data_from_server fetcher.fetch_path(@server_uri) + end + end + + def test_implicit_proxy + use_ui @ui do + ENV['http_proxy'] = @proxy_uri + fetcher = Gem::RemoteFetcher.new nil + assert_data_from_proxy fetcher.fetch_path(@server_uri) + end + end + + def test_implicit_upper_case_proxy + use_ui @ui do + ENV['HTTP_PROXY'] = @proxy_uri + fetcher = Gem::RemoteFetcher.new nil + assert_data_from_proxy fetcher.fetch_path(@server_uri) + end + end + + def test_implicit_proxy_no_env + use_ui @ui do + fetcher = Gem::RemoteFetcher.new nil + assert_data_from_server fetcher.fetch_path(@server_uri) + end + end + + def test_zip + use_ui @ui do + self.class.enable_zip = true + fetcher = Gem::RemoteFetcher.new nil + assert_equal SERVER_DATA.size, fetcher.fetch_size(@server_uri), "probably not from proxy" + zip_data = fetcher.fetch_path(@server_z_uri) + assert zip_data.size < SERVER_DATA.size, "Zipped data should be smaller" + end + end + + def test_no_zip + use_ui @ui do + self.class.enable_zip = false + fetcher = Gem::RemoteFetcher.new nil + assert_error { fetcher.fetch_path(@server_z_uri) } + end + end + + def test_yaml_error_on_size + use_ui @ui do + self.class.enable_yaml = false + fetcher = Gem::RemoteFetcher.new nil + assert_error { fetcher.size } + end + end + + private + + def assert_error(exception_class=Exception) + got_exception = false + begin + yield + rescue exception_class => ex + got_exception = true + end + assert got_exception, "Expected exception conforming to #{exception_class}" + end + + def assert_data_from_server(data) + assert_block("Data is not from server") { data =~ /0\.4\.11/ } + end + + def assert_data_from_proxy(data) + assert_block("Data is not from proxy") { data =~ /0\.4\.2/ } + end + + class NilLog < WEBrick::Log + def log(level, data) #Do nothing + end + end + + class << self + attr_reader :normal_server, :proxy_server + attr_accessor :enable_zip, :enable_yaml + + def start_servers + @normal_server ||= start_server(SERVER_PORT, SERVER_DATA) + @proxy_server ||= start_server(PROXY_PORT, PROXY_DATA) + @enable_yaml = true + @enable_zip = false + end + + private + + def start_server(port, data) + Thread.new do + begin + null_logger = NilLog.new + s = WEBrick::HTTPServer.new( + :Port => port, + :DocumentRoot => nil, + :Logger => null_logger, + :AccessLog => null_logger + ) + s.mount_proc("/kill") { |req, res| s.shutdown } + s.mount_proc("/yaml") { |req, res| + if @enable_yaml + res.body = data + res['Content-Type'] = 'text/plain' + res['content-length'] = data.size + else + res.status = "404" + res.body = "<h1>NOT FOUND</h1>" + res['Content-Type'] = 'text/html' + end + } + s.mount_proc("/yaml.Z") { |req, res| + if @enable_zip + res.body = Zlib::Deflate.deflate(data) + res['Content-Type'] = 'text/plain' + else + res.status = "404" + res.body = "<h1>NOT FOUND</h1>" + res['Content-Type'] = 'text/html' + end + } + s.start + rescue Exception => ex + abort ex.message + puts "ERROR during server thread: #{ex.message}" + end + end + sleep 0.2 # Give the servers time to startup + end + end + +end + diff --git a/test/rubygems/test_gem_remote_installer.rb b/test/rubygems/test_gem_remote_installer.rb new file mode 100644 index 0000000000..90d94843bd --- /dev/null +++ b/test/rubygems/test_gem_remote_installer.rb @@ -0,0 +1,161 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/remote_installer' + +class MockFetcher + def initialize(uri, proxy) + @uri = uri + @proxy = proxy + end + + def size + 1000 + end + + def source_index + if @uri =~ /non.existent.url/ + fail Gem::RemoteSourceException, + "Error fetching remote gem cache: Mock Socket Exception" + end + result = { + 'foo-1.2.3' => Gem::Specification.new do |s| + s.name = 'foo' + s.version = "1.2.3" + s.summary = "This is a cool package" + end, + 'foo-tools-2.0.0' => Gem::Specification.new do |s| + s.name = 'foo-tools' + s.version = "2.0.0" + s.summary = "This is an even cooler package" + end, + 'foo-2-2.0.0' => Gem::Specification.new do |s| + s.name = 'foo-2' + s.version = "2.0.0" + s.summary = "This is the coolest package evar!~!" + end, + } + result + end + + def fetch_path(path) + end + + def self.finish + end +end + +class TestGemRemoteInstaller < RubyGemTestCase + + def setup + super + + util_setup_fake_fetcher + + util_setup_source_info_cache @gem1, @gem4 + + @installer = Gem::RemoteInstaller.new + @installer.instance_variable_set("@fetcher_class", MockFetcher) + end + + def teardown + FileUtils.rm "dest_file" rescue nil + end + + def test_find_gem_to_install + future_gem = quick_gem @gem1.name, '9.9.9' do |spec| + spec.required_ruby_version = '> 999.999.999' # HACK + end + + util_setup_source_info_cache @gem1, future_gem + version = Gem::Version::Requirement.new "> 0.0.0" + gems = @installer.find_gem_to_install(@gem1.name, version) + + assert_equal @gem1.full_name, gems.first.full_name + end + + def test_source_index_hash + source_hash = @installer.source_index_hash + + assert_equal 1, source_hash.size + assert source_hash.has_key?('http://gems.example.com') + assert_equal [@gem1, @gem4], + source_hash['http://gems.example.com'].search(@gem1.name) + end + + def test_specs_n_sources_matching + version = Gem::Version::Requirement.new "> 0.0.0" + specs_n_sources = @installer.specs_n_sources_matching @gem1.name, version + + gems = specs_n_sources.map { |g,| g.full_name } + + assert_equal [@gem1.full_name], gems, + "Gems with longer names and higher versions must not match" + end + +end + +# This test suite has a number of TODOs in the test cases. The +# TestRemoteInstaller test suite is a reworking of this class from +# scratch. +class RemoteInstallerTest #< RubyGemTestCase # HACK disabled + class RInst < Gem::RemoteInstaller + include Test::Unit::Assertions + + attr_accessor :expected_destination_files + attr_accessor :expected_bodies + attr_accessor :caches + attr_accessor :responses + + def source_index_hash + @caches + end + + def fetch(uri) + @reponses ||= {} + @responses[uri] + end + + def write_gem_to_file(body, destination_file) + expected_destination_file = expected_destination_files.pop + expected_body = expected_bodies.pop + assert_equal expected_body, body, "Unexpected body" + assert_equal expected_destination_file, destination_file, "Unexpected destination file" + end + + def new_installer(gem) + return MockInstaller.new(gem) + end + end + + def setup + Gem.clear_paths + @remote_installer = Gem::RemoteInstaller.new + @remote_installer.instance_eval { @fetcher_class = MockFetcher } + end + + SAMPLE_SPEC = Gem::Specification.new do |s| + s.name = 'foo' + s.version = "1.2.3" + s.platform = Gem::Platform::RUBY + s.summary = "This is a cool package" + s.files = [] + end + SAMPLE_CACHE = { 'foo-1.2.3' => SAMPLE_SPEC } + SAMPLE_CACHE_YAML = SAMPLE_CACHE.to_yaml + + FOO_GEM = '' # TODO + CACHE_DIR = File.join(Gem.dir, 'cache') + + def test_install + result = @remote_installer.install('foo') + assert_equal [nil], result + end + +end + diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb new file mode 100644 index 0000000000..c441bd16df --- /dev/null +++ b/test/rubygems/test_gem_requirement.rb @@ -0,0 +1,223 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/version' + +class TestGemRequirement < RubyGemTestCase + + def setup + super + + @r1_2 = Gem::Requirement.new '= 1.2' + @r1_3 = Gem::Requirement.new '= 1.3' + end + + def test_initialize + r = Gem::Requirement.new '2' + assert_equal '= 2', r.to_s, 'String' + + r = Gem::Requirement.new %w[2] + assert_equal '= 2', r.to_s, 'Array of Strings' + + r = Gem::Requirement.new Gem::Version.new('2') + assert_equal '= 2', r.to_s, 'Gem::Version' + end + + def test_equals2 + assert_equal @r1_2, @r1_2.dup + assert_equal @r1_2.dup, @r1_2 + + assert_not_equal @r1_3, @r1_2 + assert_not_equal @r1_2, @r1_3 + + assert_not_equal Object.new, @r1_2 + assert_not_equal @r1_2, Object.new + end + + def test_hash + assert_equal @r1_2.hash, @r1_2.dup.hash + assert_equal @r1_2.dup.hash, @r1_2.hash + + assert_not_equal @r1_2.hash, @r1_3.hash + assert_not_equal @r1_3.hash, @r1_2.hash + end + + # We may get some old gems that have requirements in old formats. + # We need to be able to handle those old requirements by normalizing + # them to the latest format. + def test_normalization + require 'yaml' + yamldep = %{--- !ruby/object:Gem::Requirement + nums: + - 1 + - 0 + - 4 + op: ">=" + version: ">= 1.0.4"} + dep = YAML.load(yamldep) + dep.normalize + assert_equal ">= 1.0.4", dep.to_s + end + + def test_parse + assert_equal ['=', Gem::Version.new(1)], @r1_2.parse(' 1') + + assert_equal ['=', Gem::Version.new(1)], @r1_2.parse('= 1') + assert_equal ['>', Gem::Version.new(1)], @r1_2.parse('> 1') + + assert_equal ['=', Gem::Version.new(0)], @r1_2.parse('=') + assert_equal ['>', Gem::Version.new(0)], @r1_2.parse('>') + + assert_equal ['=', Gem::Version.new(1)], @r1_2.parse("=\n1") + assert_equal ['=', Gem::Version.new(0)], @r1_2.parse("=\njunk") + + assert_equal ['=', Gem::Version.new(2)], @r1_2.parse(Gem::Version.new('2')) + end + + def test_parse_illformed + e = assert_raise ArgumentError do + @r1_2.parse(nil) + end + + assert_equal 'Illformed requirement [nil]', e.message + + e = assert_raise ArgumentError do + @r1_2.parse('') + end + + assert_equal 'Illformed requirement [""]', e.message + end + + def test_satisfied_by_eh_bang_equal + r1_2 = Gem::Requirement.new '!= 1.2' + v1_1 = Gem::Version.new '1.1' + v1_2 = Gem::Version.new '1.2' + v1_3 = Gem::Version.new '1.3' + + assert_equal true, r1_2.satisfied_by?(nil) + assert_equal true, r1_2.satisfied_by?(v1_1) + assert_equal false, r1_2.satisfied_by?(v1_2) + assert_equal true, r1_2.satisfied_by?(v1_3) + end + + def test_satisfied_by_eh_blank + r1_2 = Gem::Requirement.new '1.2' + v1_1 = Gem::Version.new '1.1' + v1_2 = Gem::Version.new '1.2' + v1_3 = Gem::Version.new '1.3' + + assert_equal false, r1_2.satisfied_by?(nil) + assert_equal false, r1_2.satisfied_by?(v1_1) + assert_equal true, r1_2.satisfied_by?(v1_2) + assert_equal false, r1_2.satisfied_by?(v1_3) + end + + def test_satisfied_by_eh_equal + r1_2 = @r1_2 + v1_1 = Gem::Version.new '1.1' + v1_2 = Gem::Version.new '1.2' + v1_3 = Gem::Version.new '1.3' + + assert_equal false, r1_2.satisfied_by?(nil) + assert_equal false, r1_2.satisfied_by?(v1_1) + assert_equal true, r1_2.satisfied_by?(v1_2) + assert_equal false, r1_2.satisfied_by?(v1_3) + end + + def test_satisfied_by_eh_gt + r1_2 = Gem::Requirement.new '> 1.2' + v1_1 = Gem::Version.new '1.1' + v1_2 = Gem::Version.new '1.2' + v1_3 = Gem::Version.new '1.3' + + assert_equal false, r1_2.satisfied_by?(v1_1) + assert_equal false, r1_2.satisfied_by?(v1_2) + assert_equal true, r1_2.satisfied_by?(v1_3) + + assert_raise NoMethodError do + assert_equal true, r1_2.satisfied_by?(nil) + end + end + + def test_satisfied_by_eh_gte + r1_2 = Gem::Requirement.new '>= 1.2' + v1_1 = Gem::Version.new '1.1' + v1_2 = Gem::Version.new '1.2' + v1_3 = Gem::Version.new '1.3' + + assert_equal false, r1_2.satisfied_by?(v1_1) + assert_equal true, r1_2.satisfied_by?(v1_2) + assert_equal true, r1_2.satisfied_by?(v1_3) + + assert_raise NoMethodError do + assert_equal true, r1_2.satisfied_by?(nil) + end + end + + def test_satisfied_by_eh_list + r = Gem::Requirement.create(['> 1.1', '< 1.3']) + v1_1 = Gem::Version.new '1.1' + v1_2 = Gem::Version.new '1.2' + v1_3 = Gem::Version.new '1.3' + + assert_equal false, r.satisfied_by?(v1_1) + assert_equal true, r.satisfied_by?(v1_2) + assert_equal false, r.satisfied_by?(v1_3) + + assert_raise NoMethodError do + assert_equal true, r.satisfied_by?(nil) + end + end + + def test_satisfied_by_eh_lt + r1_2 = Gem::Requirement.new '< 1.2' + v1_1 = Gem::Version.new '1.1' + v1_2 = Gem::Version.new '1.2' + v1_3 = Gem::Version.new '1.3' + + assert_equal true, r1_2.satisfied_by?(v1_1) + assert_equal false, r1_2.satisfied_by?(v1_2) + assert_equal false, r1_2.satisfied_by?(v1_3) + + assert_raise NoMethodError do + assert_equal true, r1_2.satisfied_by?(nil) + end + end + + def test_satisfied_by_eh_lte + r1_2 = Gem::Requirement.new '<= 1.2' + v1_1 = Gem::Version.new '1.1' + v1_2 = Gem::Version.new '1.2' + v1_3 = Gem::Version.new '1.3' + + assert_equal true, r1_2.satisfied_by?(v1_1) + assert_equal true, r1_2.satisfied_by?(v1_2) + assert_equal false, r1_2.satisfied_by?(v1_3) + + assert_raise NoMethodError do + assert_equal true, r1_2.satisfied_by?(nil) + end + end + + def test_satisfied_by_eh_tilde_gt + r1_2 = Gem::Requirement.new '~> 1.2' + v1_1 = Gem::Version.new '1.1' + v1_2 = Gem::Version.new '1.2' + v1_3 = Gem::Version.new '1.3' + + assert_equal false, r1_2.satisfied_by?(v1_1) + assert_equal true, r1_2.satisfied_by?(v1_2) + assert_equal true, r1_2.satisfied_by?(v1_3) + + assert_raise NoMethodError do + assert_equal true, r1_2.satisfied_by?(nil) + end + end + +end + diff --git a/test/rubygems/test_gem_server.rb b/test/rubygems/test_gem_server.rb new file mode 100644 index 0000000000..98c8ba5543 --- /dev/null +++ b/test/rubygems/test_gem_server.rb @@ -0,0 +1,71 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/server' +require 'stringio' + +class Gem::Server + attr_reader :server +end + +class TestGemServer < RubyGemTestCase + + def setup + super + + @a1 = quick_gem 'a', '1' + + @server = Gem::Server.new Gem.dir, 8809, false + @req = WEBrick::HTTPRequest.new :Logger => nil + @res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0' + end + + def test_quick_index + data = StringIO.new "GET /quick/index HTTP/1.0\r\n\r\n" + @req.parse data + + @server.quick @req, @res + + assert_match %r| \d\d:\d\d:\d\d |, @res['date'] + assert_equal 'text/plain', @res['content-type'] + assert_equal "a-1", @res.body + end + + def test_quick_index_rz + data = StringIO.new "GET /quick/index.rz HTTP/1.0\r\n\r\n" + @req.parse data + + @server.quick @req, @res + + assert_match %r| \d\d:\d\d:\d\d |, @res['date'] + assert_equal 'text/plain', @res['content-type'] + assert_equal "a-1", Zlib::Inflate.inflate(@res.body) + end + + def test_quick_a_1_gemspec_rz + data = StringIO.new "GET /quick/a-1.gemspec.rz HTTP/1.0\r\n\r\n" + @req.parse data + + @server.quick @req, @res + + assert @res['date'] + assert_equal 'text/plain', @res['content-type'] + yaml = Zlib::Inflate.inflate(@res.body) + assert_match %r|Gem::Specification|, yaml + assert_match %r|name: a|, yaml + assert_match %r|version: "1"|, yaml + end + + def test_quick_z_9_gemspec_rz + data = StringIO.new "GET /quick/z-9.gemspec.rz HTTP/1.0\r\n\r\n" + @req.parse data + + @server.quick @req, @res + + assert_match %r| \d\d:\d\d:\d\d |, @res['date'] + assert_equal 'text/plain', @res['content-type'] + assert_equal '', @res.body + assert_equal 404, @res.status + end + +end + diff --git a/test/rubygems/test_gem_source_index.rb b/test/rubygems/test_gem_source_index.rb new file mode 100644 index 0000000000..befbbe6f67 --- /dev/null +++ b/test/rubygems/test_gem_source_index.rb @@ -0,0 +1,429 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/source_index' +require 'rubygems/config_file' + +class Gem::SourceIndex + public :fetcher, :fetch_bulk_index, :fetch_quick_index, + :find_missing, :gems, :remove_extra, + :update_with_missing, :unzip +end + +class TestGemSourceIndex < RubyGemTestCase + + def setup + super + + util_setup_fake_fetcher + end + + def test_create_from_directory + # TODO + end + + def test_fetcher + assert_equal @fetcher, @source_index.fetcher + end + + def test_fetch_bulk_index_compressed + util_setup_bulk_fetch true + + use_ui @ui do + fetched_index = @source_index.fetch_bulk_index @uri + assert_equal [@gem1.full_name, @gem4.full_name, @gem2.full_name].sort, + fetched_index.gems.map { |n,s| n }.sort + end + + paths = @fetcher.paths + + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift + + assert paths.empty?, paths.join(', ') + end + + def test_fetch_bulk_index_error + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}.Z"] = proc { raise SocketError } + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = proc { raise SocketError } + @fetcher.data["#{@gem_repo}/yaml.Z"] = proc { raise SocketError } + @fetcher.data["#{@gem_repo}/yaml"] = proc { raise SocketError } + + e = assert_raise Gem::RemoteSourceException do + use_ui @ui do + @source_index.fetch_bulk_index @uri + end + end + + paths = @fetcher.paths + + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}", paths.shift + assert_equal "#{@gem_repo}/yaml.Z", paths.shift + assert_equal "#{@gem_repo}/yaml", paths.shift + + assert paths.empty?, paths.join(', ') + + assert_equal 'Error fetching remote gem cache: SocketError', + e.message + end + + def test_fetch_bulk_index_fallback + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}.Z"] = + proc { raise SocketError } + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = + proc { raise SocketError } + @fetcher.data["#{@gem_repo}/yaml.Z"] = proc { raise SocketError } + @fetcher.data["#{@gem_repo}/yaml"] = @source_index.to_yaml + + use_ui @ui do + fetched_index = @source_index.fetch_bulk_index @uri + assert_equal [@gem1.full_name, @gem4.full_name, @gem2.full_name].sort, + fetched_index.gems.map { |n,s| n }.sort + end + + paths = @fetcher.paths + + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}", paths.shift + assert_equal "#{@gem_repo}/yaml.Z", paths.shift + assert_equal "#{@gem_repo}/yaml", paths.shift + + assert paths.empty?, paths.join(', ') + end + + def test_fetch_bulk_index_marshal_mismatch + marshal = @source_index.dump + marshal[0] = (Marshal::MAJOR_VERSION - 1).chr + + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = marshal + @fetcher.data["#{@gem_repo}/yaml"] = @source_index.to_yaml + + use_ui @ui do + fetched_index = @source_index.fetch_bulk_index @uri + assert_equal [@gem1.full_name, @gem4.full_name, @gem2.full_name].sort, + fetched_index.gems.map { |n,s| n }.sort + end + + paths = @fetcher.paths + + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}", paths.shift + assert_equal "#{@gem_repo}/yaml.Z", paths.shift + assert_equal "#{@gem_repo}/yaml", paths.shift + + assert paths.empty?, paths.join(', ') + end + + def test_fetch_bulk_index_uncompressed + util_setup_bulk_fetch false + use_ui @ui do + fetched_index = @source_index.fetch_bulk_index @uri + assert_equal [@gem1.full_name, @gem4.full_name, @gem2.full_name].sort, + fetched_index.gems.map { |n,s| n }.sort + end + + paths = @fetcher.paths + + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}", paths.shift + + assert paths.empty?, paths.join(', ') + end + + def test_fetch_quick_index + quick_index = util_zip @gem_names + @fetcher.data["#{@gem_repo}/quick/index.rz"] = quick_index + + quick_index = @source_index.fetch_quick_index @uri + assert_equal [@gem1.full_name, @gem4.full_name, @gem2.full_name].sort, + quick_index.sort + + paths = @fetcher.paths + + assert_equal "#{@gem_repo}/quick/index.rz", paths.shift + + assert paths.empty?, paths.join(', ') + end + + def test_fetch_quick_index_error + @fetcher.data["#{@gem_repo}/quick/index.rz"] = + proc { raise Exception } + + e = assert_raise Gem::OperationNotSupportedError do + @source_index.fetch_quick_index @uri + end + + assert_equal 'No quick index found: Exception', e.message + + paths = @fetcher.paths + + assert_equal "#{@gem_repo}/quick/index.rz", paths.shift + + assert paths.empty?, paths.join(', ') + end + + def test_find_missing + missing = @source_index.find_missing [@gem3.full_name] + assert_equal [@gem3.full_name], missing + end + + def test_find_missing_none_missing + missing = @source_index.find_missing @gem_names.split + assert_equal [], missing + end + + def test_latest_specs + spec = quick_gem @gem1.name, '0.0.1' + @source_index.add_spec spec + + expected = [ + @gem1.full_name, + @gem2.full_name, + @gem4.full_name, + ].sort + + assert_equal expected, @source_index.latest_specs.map { |s| s.full_name }.sort + end + + def test_outdated + sic = Gem::SourceInfoCache.new + Gem::SourceInfoCache.instance_variable_set :@cache, sic + + assert_equal [], @source_index.outdated + + updated = quick_gem @gem1.name, (@gem1.version.bump) + util_setup_source_info_cache updated + + assert_equal [updated.name], @source_index.outdated + + updated_platform = quick_gem @gem1.name, (updated.version.bump) do |s| + s.platform = Gem::Platform.new 'x86-other_platform1' + end + + util_setup_source_info_cache updated, updated_platform + + assert_equal [updated_platform.name], @source_index.outdated + end + + def test_remove_extra + @source_index.remove_extra [@gem1.full_name] + assert_equal [@gem1.full_name], @source_index.gems.map { |n,s| n } + end + + def test_remove_extra_no_changes + gems = @gem_names.split.sort + @source_index.remove_extra gems + assert_equal gems, @source_index.gems.map { |n,s| n }.sort + end + + def test_search + assert_equal [@gem1, @gem4], @source_index.search("gem_one") + assert_equal [@gem1], @source_index.search("gem_one", "= 0.0.2") + + assert_equal [], @source_index.search("bogusstring") + assert_equal [], @source_index.search("gem_one", "= 3.2.1") + + @a1 = quick_gem 'a', '1' + @a2 = quick_gem 'a', '2' + + source_index = Gem::SourceIndex.new @a1.full_name => @a1, + @a2.full_name => @a2 + + assert_equal [@a1], source_index.search(@a1.name, '= 1') + + r1 = Gem::Requirement.create '= 1' + assert_equal [@a1], source_index.search(@a1.name, r1) + + dep = Gem::Dependency.new @a1.name, r1 + assert_equal [@a1], source_index.search(dep) + end + + def test_search_empty_cache + empty_source_index = Gem::SourceIndex.new({}) + assert_equal [], empty_source_index.search("foo") + end + + def test_search_platform + util_set_arch 'x86-my_platform1' + + a1 = quick_gem 'a', '1' + a1_mine = quick_gem 'a', '1' do |s| + s.platform = Gem::Platform.new 'x86-my_platform1' + end + a1_other = quick_gem 'a', '1' do |s| + s.platform = Gem::Platform.new 'x86-other_platform1' + end + + si = Gem::SourceIndex.new(a1.full_name => a1, a1_mine.full_name => a1_mine, + a1_other.full_name => a1_other) + + dep = Gem::Dependency.new 'a', Gem::Requirement.new('1') + + gems = si.search dep, true + + assert_equal [a1, a1_mine], gems.sort + end + + def test_signature + sig = @source_index.gem_signature('foo-1.2.3') + assert_equal 64, sig.length + assert_match(/^[a-f0-9]{64}$/, sig) + end + + def test_specification + assert_equal @gem1, @source_index.specification(@gem1.full_name) + + assert_nil @source_index.specification("foo-1.2.4") + end + + def test_index_signature + sig = @source_index.index_signature + assert_match(/^[a-f0-9]{64}$/, sig) + end + + def test_unzip + input = "x\234+\316\317MU(I\255(\001\000\021\350\003\232" + assert_equal 'some text', @source_index.unzip(input) + end + + def test_update_bulk + util_setup_bulk_fetch true + + @source_index.gems.replace({}) + assert_equal [], @source_index.gems.keys.sort + + use_ui @ui do + @source_index.update @uri + + assert_equal @gem_names.split, @source_index.gems.keys.sort + end + + paths = @fetcher.paths + + assert_equal "#{@gem_repo}/quick/index.rz", paths.shift + assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift + + assert paths.empty?, paths.join(', ') + end + + def test_update_incremental + old_gem_conf = Gem.configuration + Gem.configuration = Gem::ConfigFile.new([]) + + quick_index = util_zip @all_gem_names.join("\n") + @fetcher.data["#{@gem_repo}/quick/index.rz"] = quick_index + + marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}", + "#{@gem3.full_name}.gemspec.rz" + @fetcher.data[marshal_uri] = util_zip Marshal.dump(@gem3) + + use_ui @ui do + @source_index.update @uri + + assert_equal @all_gem_names, @source_index.gems.keys.sort + end + + paths = @fetcher.paths + assert_equal "#{@gem_repo}/quick/index.rz", paths.shift + assert_equal marshal_uri, paths.shift + + assert paths.empty?, paths.join(', ') + ensure + Gem.configuration = old_gem_conf + end + + def test_update_incremental_fallback + old_gem_conf = Gem.configuration + Gem.configuration = Gem::ConfigFile.new([]) + + quick_index = util_zip @all_gem_names.join("\n") + @fetcher.data["#{@gem_repo}/quick/index.rz"] = quick_index + + marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}", + "#{@gem3.full_name}.gemspec.rz" + + yaml_uri = "#{@gem_repo}/quick/#{@gem3.full_name}.gemspec.rz" + @fetcher.data[yaml_uri] = util_zip @gem3.to_yaml + + use_ui @ui do + @source_index.update @uri + + assert_equal @all_gem_names, @source_index.gems.keys.sort + end + + paths = @fetcher.paths + assert_equal "#{@gem_repo}/quick/index.rz", paths.shift + assert_equal marshal_uri, paths.shift + assert_equal yaml_uri, paths.shift + + assert paths.empty?, paths.join(', ') + ensure + Gem.configuration = old_gem_conf + end + + def test_update_incremental_marshal_mismatch + old_gem_conf = Gem.configuration + Gem.configuration = Gem::ConfigFile.new([]) + + quick_index = util_zip @all_gem_names.join("\n") + @fetcher.data["#{@gem_repo}/quick/index.rz"] = quick_index + + marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}", + "#{@gem3.full_name}.gemspec.rz" + marshal_data = Marshal.dump(@gem3) + marshal_data[0] = (Marshal::MAJOR_VERSION - 1).chr + @fetcher.data[marshal_uri] = util_zip marshal_data + + yaml_uri = "#{@gem_repo}/quick/#{@gem3.full_name}.gemspec.rz" + @fetcher.data[yaml_uri] = util_zip @gem3.to_yaml + + use_ui @ui do + @source_index.update @uri + + assert_equal @all_gem_names, @source_index.gems.keys.sort + end + + paths = @fetcher.paths + assert_equal "#{@gem_repo}/quick/index.rz", paths.shift + assert_equal marshal_uri, paths.shift + assert_equal yaml_uri, paths.shift + + assert paths.empty?, paths.join(', ') + ensure + Gem.configuration = old_gem_conf + end + + def test_update_with_missing + marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}", + "#{@gem3.full_name}.gemspec.rz" + dumped = Marshal.dump(@gem3) + @fetcher.data[marshal_uri] = util_zip(dumped) + + use_ui @ui do + @source_index.update_with_missing @uri, [@gem3.full_name] + end + + spec = @source_index.specification(@gem3.full_name) + # We don't care about the equality of undumped attributes + @gem3.files = spec.files + @gem3.loaded_from = spec.loaded_from + + assert_equal @gem3, spec + end + + def util_setup_bulk_fetch(compressed) + source_index = @source_index.dump + + if compressed then + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}.Z"] = util_zip source_index + else + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = source_index + end + end + +end diff --git a/test/rubygems/test_gem_source_info_cache.rb b/test/rubygems/test_gem_source_info_cache.rb new file mode 100644 index 0000000000..570b643bc5 --- /dev/null +++ b/test/rubygems/test_gem_source_info_cache.rb @@ -0,0 +1,299 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/source_info_cache' + +class Gem::SourceIndex + public :gems +end + +class TestGemSourceInfoCache < RubyGemTestCase + + def setup + @original_sources = Gem.sources + + super + + util_setup_fake_fetcher + + @sic = Gem::SourceInfoCache.new + @sic.instance_variable_set :@fetcher, @fetcher + + prep_cache_files @sic + end + + def teardown + super + Gem.sources.replace @original_sources + end + + def test_self_cache_refreshes + Gem.configuration.update_sources = true #true by default + source_index = Gem::SourceIndex.new 'key' => 'sys' + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = source_index.dump + + Gem.sources.replace %W[#{@gem_repo}] + + use_ui @ui do + assert_not_nil Gem::SourceInfoCache.cache + assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache + assert_equal Gem::SourceInfoCache.cache.object_id, + Gem::SourceInfoCache.cache.object_id + assert_match %r|Bulk updating|, @ui.output + end + end + + def test_self_cache_skips_refresh_based_on_configuration + Gem.configuration.update_sources = false + source_index = Gem::SourceIndex.new 'key' => 'sys' + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = source_index.dump + + Gem.sources.replace %w[#{@gem_repo}] + + use_ui @ui do + assert_not_nil Gem::SourceInfoCache.cache + assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache + assert_equal Gem::SourceInfoCache.cache.object_id, + Gem::SourceInfoCache.cache.object_id + assert_no_match %r|Bulk updating|, @ui.output + end + end + + def test_self_cache_data + source_index = Gem::SourceIndex.new 'key' => 'sys' + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = source_index.dump + + Gem::SourceInfoCache.instance_variable_set :@cache, nil + sice = Gem::SourceInfoCacheEntry.new source_index, 0 + + use_ui @ui do + assert_equal source_index.gems, + Gem::SourceInfoCache.cache_data[@gem_repo].source_index.gems + end + end + + def test_cache_data + assert_equal [['key','sys']], @sic.cache_data.to_a.sort + end + + def test_cache_data_dirty + def @sic.dirty() @dirty; end + assert_equal false, @sic.dirty, 'clean on init' + @sic.cache_data + assert_equal false, @sic.dirty, 'clean on fetch' + @sic.update + @sic.cache_data + assert_equal true, @sic.dirty, 'still dirty' + end + + def test_cache_data_irreparable + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = @source_index.dump + + data = { @gem_repo => { 'totally' => 'borked' } } + + [@sic.system_cache_file, @sic.user_cache_file].each do |fn| + FileUtils.mkdir_p File.dirname(fn) + open(fn, "wb") { |f| f.write Marshal.dump(data) } + end + + @sic.instance_eval { @cache_data = nil } + + fetched = use_ui @ui do @sic.cache_data end + + fetched_si = fetched["#{@gem_repo}"].source_index + + assert_equal @source_index.index_signature, fetched_si.index_signature + end + + def test_cache_data_none_readable + FileUtils.chmod 0222, @sic.system_cache_file + FileUtils.chmod 0222, @sic.user_cache_file + return if (File.stat(@sic.system_cache_file).mode & 0222) != 0222 + return if (File.stat(@sic.user_cache_file).mode & 0222) != 0222 + # HACK for systems that don't support chmod + assert_equal({}, @sic.cache_data) + end + + def test_cache_data_none_writable + FileUtils.chmod 0444, @sic.system_cache_file + FileUtils.chmod 0444, @sic.user_cache_file + e = assert_raise RuntimeError do + @sic.cache_data + end + assert_equal 'unable to locate a writable cache file', e.message + end + + def test_cache_data_repair + data = { + @gem_repo => { + 'cache' => Gem::SourceIndex.new, + 'size' => 0, + } + } + [@sic.system_cache_file, @sic.user_cache_file].each do |fn| + FileUtils.mkdir_p File.dirname(fn) + open(fn, "wb") { |f| f.write Marshal.dump(data) } + end + + @sic.instance_eval { @cache_data = nil } + + expected = { + @gem_repo => + Gem::SourceInfoCacheEntry.new(Gem::SourceIndex.new, 0) + } + assert_equal expected, @sic.cache_data + end + + def test_cache_data_user_fallback + FileUtils.chmod 0444, @sic.system_cache_file + assert_equal [['key','usr']], @sic.cache_data.to_a.sort + end + + def test_cache_file + assert_equal @gemcache, @sic.cache_file + end + + def test_cache_file_user_fallback + FileUtils.chmod 0444, @sic.system_cache_file + assert_equal @usrcache, @sic.cache_file + end + + def test_cache_file_none_writable + FileUtils.chmod 0444, @sic.system_cache_file + FileUtils.chmod 0444, @sic.user_cache_file + e = assert_raise RuntimeError do + @sic.cache_file + end + assert_equal 'unable to locate a writable cache file', e.message + end + + def test_flush + @sic.cache_data['key'] = 'new' + @sic.update + @sic.flush + + assert_equal [['key','new']], read_cache(@sic.system_cache_file).to_a.sort + end + + def test_read_system_cache + assert_equal [['key','sys']], @sic.cache_data.to_a.sort + end + + def test_read_user_cache + FileUtils.chmod 0444, @sic.system_cache_file + + assert_equal [['key','usr']], @sic.cache_data.to_a.sort + end + + def test_search + si = Gem::SourceIndex.new @gem1.full_name => @gem1 + cache_data = { + @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) + } + @sic.instance_variable_set :@cache_data, cache_data + + assert_equal [@gem1], @sic.search(//) + end + + def test_search_dependency + si = Gem::SourceIndex.new @gem1.full_name => @gem1 + cache_data = { + @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) + } + @sic.instance_variable_set :@cache_data, cache_data + + dep = Gem::Dependency.new @gem1.name, @gem1.version + + assert_equal [@gem1], @sic.search(dep) + end + + def test_search_no_matches + si = Gem::SourceIndex.new @gem1.full_name => @gem1 + cache_data = { + @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) + } + @sic.instance_variable_set :@cache_data, cache_data + + assert_equal [], @sic.search(/nonexistent/) + end + + def test_search_no_matches_in_source + si = Gem::SourceIndex.new @gem1.full_name => @gem1 + cache_data = { + @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) + } + @sic.instance_variable_set :@cache_data, cache_data + Gem.sources.replace %w[more-gems.example.com] + + assert_equal [], @sic.search(/nonexistent/) + end + + def test_search_with_source + si = Gem::SourceIndex.new @gem1.full_name => @gem1 + cache_data = { + @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) + } + @sic.instance_variable_set :@cache_data, cache_data + + assert_equal [[@gem1, @gem_repo]], + @sic.search_with_source(//) + end + + def test_system_cache_file + assert_equal File.join(Gem.dir, "source_cache"), @sic.system_cache_file + end + + def test_user_cache_file + assert_equal @usrcache, @sic.user_cache_file + end + + def test_write_cache + @sic.cache_data['key'] = 'new' + @sic.write_cache + + assert_equal [['key', 'new']], + read_cache(@sic.system_cache_file).to_a.sort + assert_equal [['key', 'usr']], + read_cache(@sic.user_cache_file).to_a.sort + end + + def test_write_cache_user + FileUtils.chmod 0444, @sic.system_cache_file + @sic.set_cache_data({'key' => 'new'}) + @sic.update + @sic.write_cache + + assert_equal [['key', 'sys']], read_cache(@sic.system_cache_file).to_a.sort + assert_equal [['key', 'new']], read_cache(@sic.user_cache_file).to_a.sort + end + + def test_write_cache_user_from_scratch + FileUtils.rm_rf @sic.user_cache_file + FileUtils.chmod 0444, @sic.system_cache_file + @sic.set_cache_data({'key' => 'new'}) + @sic.update + @sic.write_cache + + assert_equal [['key', 'sys']], read_cache(@sic.system_cache_file).to_a.sort + assert_equal [['key', 'new']], read_cache(@sic.user_cache_file).to_a.sort + end + + def test_write_cache_user_no_directory + FileUtils.rm_rf File.dirname(@sic.user_cache_file) + FileUtils.chmod 0444, @sic.system_cache_file + @sic.set_cache_data({'key' => 'new'}) + @sic.update + @sic.write_cache + + assert_equal [['key','sys']], read_cache(@sic.system_cache_file).to_a.sort + assert_equal [['key','new']], read_cache(@sic.user_cache_file).to_a.sort + end + +end + diff --git a/test/rubygems/test_gem_source_info_cache_entry.rb b/test/rubygems/test_gem_source_info_cache_entry.rb new file mode 100644 index 0000000000..023baf948b --- /dev/null +++ b/test/rubygems/test_gem_source_info_cache_entry.rb @@ -0,0 +1,46 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/source_info_cache_entry' + +class TestGemSourceInfoCacheEntry < RubyGemTestCase + + def setup + super + + util_setup_fake_fetcher + + @si = Gem::SourceIndex.new @gem1.full_name => @gem1.name + @sic_e = Gem::SourceInfoCacheEntry.new @si, @si.dump.size + end + + def test_refresh + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}.Z"] = + proc { raise Exception } + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = @si.dump + + assert_nothing_raised do + @sic_e.refresh @gem_repo + end + end + + def test_refresh_bad_uri + assert_raise URI::BadURIError do + @sic_e.refresh 'gems.example.com' + end + end + + def test_refresh_update + si = Gem::SourceIndex.new @gem1.full_name => @gem1, + @gem2.full_name => @gem2 + @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = si.dump + + use_ui @ui do + @sic_e.refresh @gem_repo + end + + new_gem = @sic_e.source_index.specification(@gem2.full_name) + assert_equal @gem2.full_name, new_gem.full_name + end + +end + diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb new file mode 100644 index 0000000000..96db29c2c0 --- /dev/null +++ b/test/rubygems/test_gem_specification.rb @@ -0,0 +1,707 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'stringio' +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/specification' + +class TestGemSpecification < RubyGemTestCase + + LEGACY_YAML_SPEC = <<-EOF +--- !ruby/object:Gem::Specification +rubygems_version: "1.0" +name: keyedlist +version: !ruby/object:Gem::Version + version: 0.4.0 +date: 2004-03-28 15:37:49.828000 +02:00 +platform: +summary: A Hash which automatically computes keys. +require_paths: + - lib +files: + - lib/keyedlist.rb +autorequire: keyedlist +author: Florian Gross +email: flgr@ccan.de +has_rdoc: true + EOF + + LEGACY_RUBY_SPEC = <<-EOF +Gem::Specification.new do |s| + s.name = %q{keyedlist} + s.version = %q{0.4.0} + s.has_rdoc = true + s.summary = %q{A Hash which automatically computes keys.} + s.files = ["lib/keyedlist.rb"] + s.require_paths = ["lib"] + s.autorequire = %q{keyedlist} + s.author = %q{Florian Gross} + s.email = %q{flgr@ccan.de} +end + EOF + + def setup + super + + @a0_0_1 = quick_gem 'a', '0.0.1' do |s| + s.executable = 'exec' + s.extensions << 'ext/a/extconf.rb' + s.has_rdoc = 'true' + s.test_file = 'test/suite.rb' + s.requirements << 'A working computer' + + s.add_dependency 'rake', '> 0.4' + s.add_dependency 'jabber4r', '> 0.0.0' + s.add_dependency 'pqa', ['> 0.4', '<= 0.6'] + + s.mark_version + s.files = %w[lib/code.rb] + end + + @a0_0_2 = quick_gem 'a', '0.0.2' do |s| + s.files = %w[lib/code.rb] + end + end + + def test_self_attribute_names + expected_value = %w[ + authors + autorequire + bindir + cert_chain + date + default_executable + dependencies + description + email + executables + extensions + extra_rdoc_files + files + has_rdoc + homepage + name + platform + post_install_message + rdoc_options + require_paths + required_ruby_version + required_rubygems_version + requirements + rubyforge_project + rubygems_version + signing_key + specification_version + summary + test_files + version + ] + + actual_value = Gem::Specification.attribute_names.map { |a| a.to_s }.sort + + assert_equal expected_value, actual_value + end + + def test_self_load + spec = File.join @gemhome, 'specifications', "#{@a0_0_2.full_name}.gemspec" + gs = Gem::Specification.load spec + + assert_equal @a0_0_2, gs + end + + def test_self_load_legacy_ruby + s = eval LEGACY_RUBY_SPEC + assert_equal 'keyedlist', s.name + assert_equal '0.4.0', s.version.to_s + assert_equal true, s.has_rdoc? + assert_equal Gem::Specification::TODAY, s.date + assert s.required_ruby_version.satisfied_by?(Gem::Version.new('0.0.1')) + assert_equal false, s.has_unit_tests? + end + + def test_self_load_legacy_yaml + s = YAML.load StringIO.new(LEGACY_YAML_SPEC) + assert_equal 'keyedlist', s.name + assert_equal '0.4.0', s.version.to_s + assert_equal true, s.has_rdoc? + #assert_equal Date.today, s.date + #assert s.required_ruby_version.satisfied_by?(Gem::Version.new('0.0.1')) + assert_equal false, s.has_unit_tests? + end + + def test_self_normalize_yaml_input_with_183_yaml + input = "!ruby/object:Gem::Specification " + assert_equal "--- #{input}", Gem::Specification.normalize_yaml_input(input) + end + + def test_self_normalize_yaml_input_with_non_183_yaml + input = "--- !ruby/object:Gem::Specification " + assert_equal input, Gem::Specification.normalize_yaml_input(input) + end + + def test_self_normalize_yaml_input_with_183_io + input = "!ruby/object:Gem::Specification " + assert_equal "--- #{input}", + Gem::Specification.normalize_yaml_input(StringIO.new(input)) + end + + def test_self_normalize_yaml_input_with_non_183_io + input = "--- !ruby/object:Gem::Specification " + assert_equal input, + Gem::Specification.normalize_yaml_input(StringIO.new(input)) + end + + def test_initialize + spec = Gem::Specification.new do |s| + s.name = "blah" + s.version = "1.3.5" + end + + assert_equal "blah", spec.name + assert_equal "1.3.5", spec.version.to_s + assert_equal Gem::Platform::RUBY, spec.platform + assert_equal nil, spec.summary + assert_equal [], spec.files + + assert_equal [], spec.test_files + assert_equal [], spec.rdoc_options + assert_equal [], spec.extra_rdoc_files + assert_equal [], spec.executables + assert_equal [], spec.extensions + assert_equal [], spec.requirements + assert_equal [], spec.dependencies + assert_equal 'bin', spec.bindir + assert_equal false, spec.has_rdoc + assert_equal false, spec.has_rdoc? + assert_equal '>= 0', spec.required_ruby_version.to_s + assert_equal '>= 0', spec.required_rubygems_version.to_s + end + + def test_initialize_future + version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + 1 + spec = Gem::Specification.new do |s| + s.name = "blah" + s.version = "1.3.5" + + s.specification_version = version + + s.new_unknown_attribute = "a value" + end + + assert_equal "blah", spec.name + assert_equal "1.3.5", spec.version.to_s + end + + def test_author + assert_equal 'A User', @a0_0_1.author + end + + def test_authors + assert_equal ['A User'], @a0_0_1.authors + end + + def test_bindir_equals + @a0_0_1.bindir = 'apps' + + assert_equal 'apps', @a0_0_1.bindir + end + + def test_bindir_equals_nil + @a0_0_2.bindir = nil + @a0_0_2.executable = 'app' + + assert_equal nil, @a0_0_2.bindir + assert_equal %w[lib/code.rb app], @a0_0_2.files + end + + def test_date + assert_equal Gem::Specification::TODAY, @a0_0_1.date + end + + def test_date_equals_date + @a0_0_1.date = Date.new(2003, 9, 17) + assert_equal Time.local(2003, 9, 17, 0,0,0), @a0_0_1.date + end + + def test_date_equals_string + @a0_0_1.date = '2003-09-17' + assert_equal Time.local(2003, 9, 17, 0,0,0), @a0_0_1.date + end + + def test_date_equals_time + @a0_0_1.date = Time.local(2003, 9, 17, 0,0,0) + assert_equal Time.local(2003, 9, 17, 0,0,0), @a0_0_1.date + end + + def test_date_equals_time_local + # HACK PDT + @a0_0_1.date = Time.local(2003, 9, 17, 19,50,0) + assert_equal Time.local(2003, 9, 17, 0,0,0), @a0_0_1.date + end + + def test_date_equals_time_utc + # HACK PDT + @a0_0_1.date = Time.local(2003, 9, 17, 19,50,0) + assert_equal Time.local(2003, 9, 17, 0,0,0), @a0_0_1.date + end + + def test_default_executable + assert_equal 'exec', @a0_0_1.default_executable + + @a0_0_1.default_executable = nil + @a0_0_1.instance_variable_set :@executables, nil + assert_equal nil, @a0_0_1.default_executable + end + + def test_dependencies + rake = Gem::Dependency.new 'rake', '> 0.4' + jabber = Gem::Dependency.new 'jabber4r', '> 0.0.0' + pqa = Gem::Dependency.new 'pqa', ['> 0.4', '<= 0.6'] + + assert_equal [rake, jabber, pqa], @a0_0_1.dependencies + end + + def test_description + assert_equal 'This is a test description', @a0_0_1.description + end + + def test_eql_eh + g1 = quick_gem 'gem' + g2 = quick_gem 'gem' + + assert_equal g1, g2 + assert_equal g1.hash, g2.hash + assert_equal true, g1.eql?(g2) + end + + def test_equals2 + assert_equal @a0_0_1, @a0_0_1 + assert_equal @a0_0_1, @a0_0_1.dup + assert_not_equal @a0_0_1, @a0_0_2 + assert_not_equal @a0_0_1, Object.new + end + + # The cgikit specification was reported to be causing trouble in at least + # one version of RubyGems, so we test explicitly for it. + def test_equals2_cgikit + cgikit = Gem::Specification.new do |s| + s.name = %q{cgikit} + s.version = "1.1.0" + s.date = %q{2004-03-13} + s.summary = %q{CGIKit is a componented-oriented web application } + + %q{framework like Apple Computers WebObjects. } + + %{This framework services Model-View-Controller architecture } + + %q{programming by components based on a HTML file, a definition } + + %q{file and a Ruby source. } + s.email = %q{info@spice-of-life.net} + s.homepage = %q{http://www.spice-of-life.net/download/cgikit/} + s.autorequire = %q{cgikit} + s.bindir = nil + s.has_rdoc = nil + s.required_ruby_version = nil + s.platform = nil + s.files = ["lib/cgikit", "lib/cgikit.rb", "lib/cgikit/components", "..."] + end + + assert_equal cgikit, cgikit + end + + def test_equals2_default_executable + spec = @a0_0_1.dup + spec.default_executable = 'xx' + + assert_not_equal @a0_0_1, spec + assert_not_equal spec, @a0_0_1 + end + + def test_equals2_extensions + spec = @a0_0_1.dup + spec.extensions = 'xx' + + assert_not_equal @a0_0_1, spec + assert_not_equal spec, @a0_0_1 + end + + def test_executables + @a0_0_1.executable = 'app' + assert_equal %w[app], @a0_0_1.executables + end + + def test_executable_equals + @a0_0_2.executable = 'app' + assert_equal 'app', @a0_0_2.executable + assert_equal %w[lib/code.rb bin/app], @a0_0_2.files + end + + def test_extensions + assert_equal ['ext/a/extconf.rb'], @a0_0_1.extensions + end + + def test_files + @a0_0_1.files = %w(files bin/common) + @a0_0_1.test_files = %w(test_files bin/common) + @a0_0_1.executables = %w(executables common) + @a0_0_1.extra_rdoc_files = %w(extra_rdoc_files bin/common) + @a0_0_1.extensions = %w(extensions bin/common) + + expected = %w[ + bin/common + bin/executables + extensions + extra_rdoc_files + files + test_files + ] + assert_equal expected, @a0_0_1.files.sort + end + + def test_files_duplicate + @a0_0_2.files = %w[a b c d b] + @a0_0_2.extra_rdoc_files = %w[x y z x] + @a0_0_2.normalize + + assert_equal %w[a b c d x y z], @a0_0_2.files + assert_equal %w[x y z], @a0_0_2.extra_rdoc_files + end + + def test_files_extra_rdoc_files + @a0_0_2.files = %w[a b c d] + @a0_0_2.extra_rdoc_files = %w[x y z] + @a0_0_2.normalize + assert_equal %w[a b c d x y z], @a0_0_2.files + end + + def test_files_non_array + @a0_0_1.files = "F" + @a0_0_1.test_files = "TF" + @a0_0_1.executables = "X" + @a0_0_1.extra_rdoc_files = "ERF" + @a0_0_1.extensions = "E" + + assert_equal %w[E ERF F TF bin/X], @a0_0_1.files.sort + end + + def test_files_non_array_pathological + @a0_0_1.instance_variable_set :@files, "F" + @a0_0_1.instance_variable_set :@test_files, "TF" + @a0_0_1.instance_variable_set :@extra_rdoc_files, "ERF" + @a0_0_1.instance_variable_set :@extensions, "E" + @a0_0_1.instance_variable_set :@executables, "X" + + assert_equal %w[E ERF F TF bin/X], @a0_0_1.files.sort + assert_kind_of Integer, @a0_0_1.hash + end + + def test_full_name + assert_equal 'a-0.0.1', @a0_0_1.full_name + + @a0_0_1.platform = Gem::Platform.new ['universal', 'darwin', nil] + assert_equal 'a-0.0.1-universal-darwin', @a0_0_1.full_name + + @a0_0_1.instance_variable_set :@new_platform, 'mswin32' + assert_equal 'a-0.0.1-mswin32', @a0_0_1.full_name, 'legacy' + + return if win_platform? + + @a0_0_1.platform = 'current' + assert_equal 'a-0.0.1-x86-darwin-8', @a0_0_1.full_name + end + + def test_full_name_windows + test_cases = { + 'i386-mswin32' => 'a-0.0.1-x86-mswin32-60', + 'i386-mswin32_80' => 'a-0.0.1-x86-mswin32-80', + 'i386-mingw32' => 'a-0.0.1-x86-mingw32' + } + + test_cases.each do |arch, expected| + util_set_arch arch + @a0_0_1.platform = 'current' + assert_equal expected, @a0_0_1.full_name + end + end + + def test_has_rdoc_eh + assert_equal true, @a0_0_1.has_rdoc? + end + + def test_hash + assert_equal @a0_0_1.hash, @a0_0_1.hash + assert_equal @a0_0_1.hash, @a0_0_1.dup.hash + assert_not_equal @a0_0_1.hash, @a0_0_2.hash + end + + def test_lib_files + @a0_0_1.files = %w[lib/foo.rb Rakefile] + + assert_equal %w[lib/foo.rb], @a0_0_1.lib_files + end + + def test_name + assert_equal 'a', @a0_0_1.name + end + + def test_platform + assert_equal Gem::Platform::RUBY, @a0_0_1.platform + end + + def test_platform_equals + @a0_0_1.platform = nil + assert_equal Gem::Platform::RUBY, @a0_0_1.platform + + @a0_0_1.platform = Gem::Platform::RUBY + assert_equal Gem::Platform::RUBY, @a0_0_1.platform + + test_cases = { + 'i386-mswin32' => ['x86', 'mswin32', '60'], + 'i386-mswin32_80' => ['x86', 'mswin32', '80'], + 'i386-mingw32' => ['x86', 'mingw32', nil ], + 'x86-darwin8' => ['x86', 'darwin', '8' ], + } + + test_cases.each do |arch, expected| + util_set_arch arch + @a0_0_1.platform = Gem::Platform::CURRENT + assert_equal Gem::Platform.new(expected), @a0_0_1.platform + end + end + + def test_platform_equals_legacy + @a0_0_1.platform = Gem::Platform::WIN32 + assert_equal Gem::Platform::MSWIN32, @a0_0_1.platform + + @a0_0_1.platform = Gem::Platform::LINUX_586 + assert_equal Gem::Platform::X86_LINUX, @a0_0_1.platform + + @a0_0_1.platform = Gem::Platform::DARWIN + assert_equal Gem::Platform::PPC_DARWIN, @a0_0_1.platform + end + + def test_require_paths + @a0_0_1.require_path = 'lib' + assert_equal %w[lib], @a0_0_1.require_paths + end + + def test_requirements + assert_equal ['A working computer'], @a0_0_1.requirements + end + + def test_spaceship_name + s1 = quick_gem 'a', '1' + s2 = quick_gem 'b', '1' + + assert_equal(-1, (s1 <=> s2)) + assert_equal( 0, (s1 <=> s1)) + assert_equal( 1, (s2 <=> s1)) + end + + def test_spaceship_platform + s1 = quick_gem 'a', '1' + s2 = quick_gem 'a', '1' do |s| + s.platform = Gem::Platform.new 'x86-my_platform1' + end + + assert_equal( -1, (s1 <=> s2)) + assert_equal( 0, (s1 <=> s1)) + assert_equal( 1, (s2 <=> s1)) + end + + def test_spaceship_version + s1 = quick_gem 'a', '1' + s2 = quick_gem 'a', '2' + + assert_equal( -1, (s1 <=> s2)) + assert_equal( 0, (s1 <=> s1)) + assert_equal( 1, (s2 <=> s1)) + end + + def test_summary + assert_equal 'this is a summary', @a0_0_1.summary + end + + def test_test_files + @a0_0_1.test_file = 'test/suite.rb' + assert_equal ['test/suite.rb'], @a0_0_1.test_files + end + + def test_test_suite_file + @a0_0_2.test_suite_file = 'test/suite.rb' + assert_equal ['test/suite.rb'], @a0_0_2.test_files + # XXX: what about the warning? + end + + def test_to_ruby + @a0_0_2.required_rubygems_version = Gem::Requirement.new '> 0' + + ruby_code = @a0_0_2.to_ruby + + expected = "Gem::Specification.new do |s| + s.name = %q{a} + s.version = \"0.0.2\" + + s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION} if s.respond_to? :specification_version= + + s.required_rubygems_version = Gem::Requirement.new(\"> 0\") if s.respond_to? :required_rubygems_version= + s.authors = [\"A User\"] + s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}} + s.description = %q{This is a test description} + s.email = %q{example@example.com} + s.files = [\"lib/code.rb\"] + s.has_rdoc = true + s.homepage = %q{http://example.com} + s.require_paths = [\"lib\"] + s.rubygems_version = %q{#{Gem::RubyGemsVersion}} + s.summary = %q{this is a summary} +end +" + + assert_equal expected, ruby_code + + same_spec = eval ruby_code + + assert_equal @a0_0_2, same_spec + end + + def test_to_ruby_fancy + @a0_0_1.platform = Gem::Platform::PPC_DARWIN + ruby_code = @a0_0_1.to_ruby + + expected = "Gem::Specification.new do |s| + s.name = %q{a} + s.version = \"0.0.1\" + + s.specification_version = 2 if s.respond_to? :specification_version= + + s.required_rubygems_version = Gem::Requirement.new(\">= 0\") if s.respond_to? :required_rubygems_version= + s.authors = [\"A User\"] + s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}} + s.default_executable = %q{exec} + s.description = %q{This is a test description} + s.email = %q{example@example.com} + s.executables = [\"exec\"] + s.extensions = [\"ext/a/extconf.rb\"] + s.files = [\"lib/code.rb\", \"test/suite.rb\", \"bin/exec\", \"ext/a/extconf.rb\"] + s.has_rdoc = %q{true} + s.homepage = %q{http://example.com} + s.platform = Gem::Platform.new([\"ppc\", \"darwin\", nil]) + s.require_paths = [\"lib\"] + s.requirements = [\"A working computer\"] + s.rubygems_version = %q{0.9.4.6} + s.summary = %q{this is a summary} + s.test_files = [\"test/suite.rb\"] + + s.add_dependency(%q<rake>, [\"> 0.4\"]) + s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"]) + s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"]) +end +" + + assert_equal expected, ruby_code + + same_spec = eval ruby_code + + assert_equal @a0_0_1, same_spec + end + + def test_to_ruby_legacy + gemspec1 = eval LEGACY_RUBY_SPEC + ruby_code = gemspec1.to_ruby + gemspec2 = eval ruby_code + + assert_equal gemspec1, gemspec2 + end + + def test_to_yaml + yaml_str = @a0_0_1.to_yaml + same_spec = YAML.load(yaml_str) + + assert_equal @a0_0_1, same_spec + end + + def test_to_yaml_fancy + @a0_0_1.platform = Gem::Platform::PPC_DARWIN + yaml_str = @a0_0_1.to_yaml + + same_spec = YAML.load(yaml_str) + + assert_equal Gem::Platform::PPC_DARWIN, same_spec.platform + + assert_equal @a0_0_1, same_spec + end + + def test_to_yaml_legacy_platform + @a0_0_1.platform = 'powerpc-darwin7.9.0' + + yaml_str = @a0_0_1.to_yaml + + same_spec = YAML.load(yaml_str) + + assert_equal Gem::Platform.new('powerpc-darwin7'), same_spec.platform + assert_equal 'powerpc-darwin7.9.0', same_spec.original_platform + end + + def test_validate + assert @a0_0_1.validate + end + + def test_validate_empty + e = assert_raise Gem::InvalidSpecificationException do + Gem::Specification.new.validate + end + + assert_equal 'missing value for attribute name', e.message + end + + def test_validate_empty_require_paths + @a0_0_1.require_paths = [] + e = assert_raise Gem::InvalidSpecificationException do + @a0_0_1.validate + end + + assert_equal 'specification must have at least one require_path', e.message + end + + def test_validate_platform_bad + @a0_0_1.platform = Object.new + assert_raise Gem::InvalidSpecificationException do @a0_0_1.validate end + + @a0_0_1.platform = "my-custom-platform" + e = assert_raise Gem::InvalidSpecificationException do + @a0_0_1.validate + end + + assert_equal 'invalid platform "my-custom-platform", see Gem::Platform', + e.message + end + + def test_validate_platform_legacy + @a0_0_1.platform = Gem::Platform::WIN32 + assert @a0_0_1.validate + + @a0_0_1.platform = Gem::Platform::LINUX_586 + assert @a0_0_1.validate + + @a0_0_1.platform = Gem::Platform::DARWIN + assert @a0_0_1.validate + end + + def test_validate_rubygems_version + @a0_0_1.rubygems_version = "3" + e = assert_raise Gem::InvalidSpecificationException do + @a0_0_1.validate + end + + assert_equal "expected RubyGems version #{Gem::RubyGemsVersion}, was 3", + e.message + end + + def test_version + assert_equal Gem::Version.new('0.0.1'), @a0_0_1.version + end + +end + diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb new file mode 100644 index 0000000000..a8564ba94f --- /dev/null +++ b/test/rubygems/test_gem_stream_ui.rb @@ -0,0 +1,117 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/user_interaction' + +class TestGemStreamUI < RubyGemTestCase + + module IsTty + attr_accessor :tty + + def tty? + @tty = true unless defined? @tty + return @tty + end + + alias_method :isatty, :tty? + end + + def setup + super + + @cfg = Gem.configuration + + @in = StringIO.new + @out = StringIO.new + @err = StringIO.new + + @in.extend IsTty + + @sui = Gem::StreamUI.new @in, @out, @err + end + + def test_ask + timeout(1) do + expected_answer = "Arthur, King of the Britons" + @in.string = "#{expected_answer}\n" + actual_answer = @sui.ask("What is your name?") + assert_equal expected_answer, actual_answer + end + end + + def test_ask_no_tty + @in.tty = false + + timeout(0.1) do + answer = @sui.ask("what is your favorite color?") + assert_equal nil, answer + end + end + + def test_ask_yes_no_no_tty_with_default + @in.tty = false + + timeout(0.1) do + answer = @sui.ask_yes_no("do coconuts migrate?", false) + assert_equal false, answer + + answer = @sui.ask_yes_no("do coconuts migrate?", true) + assert_equal true, answer + end + end + + def test_ask_yes_no_no_tty_without_default + @in.tty = false + + timeout(0.1) do + assert_raises(Gem::OperationNotSupportedError) do + @sui.ask_yes_no("do coconuts migrate?") + end + end + end + + def test_choose_from_list + @in.puts "1" + @in.rewind + + result = @sui.choose_from_list 'which one?', %w[foo bar] + + assert_equal ['foo', 0], result + assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string + end + + def test_choose_from_list_EOF + result = @sui.choose_from_list 'which one?', %w[foo bar] + + assert_equal [nil, nil], result + assert_equal "which one?\n 1. foo\n 2. bar\n> ", @out.string + end + + def test_proress_reporter_silent_nil + @cfg.verbose = nil + reporter = @sui.progress_reporter 10, 'hi' + assert_kind_of Gem::StreamUI::SilentProgressReporter, reporter + end + + def test_proress_reporter_silent_false + @cfg.verbose = false + reporter = @sui.progress_reporter 10, 'hi' + assert_kind_of Gem::StreamUI::SilentProgressReporter, reporter + assert_equal "", @out.string + end + + def test_proress_reporter_simple + @cfg.verbose = true + reporter = @sui.progress_reporter 10, 'hi' + assert_kind_of Gem::StreamUI::SimpleProgressReporter, reporter + assert_equal "hi\n", @out.string + end + + def test_proress_reporter_verbose + @cfg.verbose = 0 + reporter = @sui.progress_reporter 10, 'hi' + assert_kind_of Gem::StreamUI::VerboseProgressReporter, reporter + assert_equal "hi\n", @out.string + end + +end + diff --git a/test/rubygems/test_gem_validator.rb b/test/rubygems/test_gem_validator.rb new file mode 100644 index 0000000000..c910cfdf11 --- /dev/null +++ b/test/rubygems/test_gem_validator.rb @@ -0,0 +1,70 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require File.join(File.expand_path(File.dirname(__FILE__)), 'simple_gem') +require 'rubygems/validator' + +class TestGemValidator < RubyGemTestCase + + def setup + super + + @simple_gem = SIMPLE_GEM + @validator = Gem::Validator.new + end + + def test_verify_gem_file + gem_file = File.join @tempdir, 'simple_gem.gem' + File.open gem_file, 'wb' do |fp| fp.write @simple_gem end + + assert_equal nil, @validator.verify_gem_file(gem_file) + end + + def test_verify_gem_file_empty + e = assert_raise Gem::VerificationError do + @validator.verify_gem_file '' + end + + assert_equal 'missing gem file ', e.message + end + + def test_verify_gem_file_nonexistent + file = '/nonexistent/nonexistent.gem' + e = assert_raise Gem::VerificationError do + @validator.verify_gem_file file + end + + assert_equal "missing gem file #{file}", e.message + end + + def test_verify_gem + assert_equal nil, @validator.verify_gem(@simple_gem) + end + + def test_verify_gem_empty + e = assert_raise Gem::VerificationError do + @validator.verify_gem '' + end + + assert_equal 'empty gem file', e.message + end + + def test_verify_gem_invalid_checksum + e = assert_raise Gem::VerificationError do + @validator.verify_gem @simple_gem.upcase + end + + assert_equal 'invalid checksum for gem file', e.message + end + + def test_verify_gem_no_sum + assert_equal nil, @validator.verify_gem('words') + end + +end + diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb new file mode 100644 index 0000000000..95f37ddd23 --- /dev/null +++ b/test/rubygems/test_gem_version.rb @@ -0,0 +1,191 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/version' + +class TestGemVersion < RubyGemTestCase + + def setup + super + + @v1_0 = Gem::Version.new '1.0' + @v1_2 = Gem::Version.new '1.2' + @v1_3 = Gem::Version.new '1.3' + end + + def test_class_create + assert_version Gem::Version.create('1.0') + assert_version Gem::Version.create("1.0 ") + assert_version Gem::Version.create(" 1.0 ") + assert_version Gem::Version.create("1.0\n") + assert_version Gem::Version.create("\n1.0\n") + + assert_equal Gem::Version.create('1'), Gem::Version.create(1) + end + + def test_class_create_malformed + e = assert_raise ArgumentError do Gem::Version.create("junk") end + assert_equal "Malformed version number string junk", e.message + + e = assert_raise ArgumentError do Gem::Version.create("1.0\n2.0") end + assert_equal "Malformed version number string 1.0\n2.0", e.message + end + + def test_bad + assert_inadequate( "", "> 0.1") + assert_inadequate( "1.2.3", "!= 1.2.3") + assert_inadequate( "1.2.003.0.0", "!= 1.02.3") + assert_inadequate( "4.5.6", "< 1.2.3") + assert_inadequate( "1.0", "> 1.1") + assert_inadequate( "0", ">") + assert_inadequate( "0", "<") + assert_inadequate( "", "= 0.1") + assert_inadequate( "1.1.1", "> 1.1.1") + assert_inadequate( "1.2", "= 1.1") + assert_inadequate( "1.40", "= 1.1") + assert_inadequate( "1.3", "= 1.40") + assert_inadequate( "9.3.3", "<= 9.3.2") + assert_inadequate( "9.3.1", ">= 9.3.2") + assert_inadequate( "9.3.03", "<= 9.3.2") + assert_inadequate( "1.0.0.1", "= 1.0") + end + + def test_bump + v = Gem::Version.new("5.2.4") + assert_equal "5.3", v.bump.to_s + end + + def test_bump_one_level + v = Gem::Version.new("5") + assert_equal "6", v.bump.to_s + end + + def test_equals2 + v = Gem::Version.new("1.2") + + assert_equal v, @v1_2 + assert_equal @v1_2, v + + assert_not_equal @v1_2, @v1_3 + assert_not_equal @v1_3, @v1_2 + end + + def test_hash + v = Gem::Version.new("1.2") + assert_equal v.hash, @v1_2.hash + assert_not_equal @v1_2.hash, @v1_3.hash + end + + def test_illformed_requirements + [ ">>> 1.3.5", "> blah" ].each do |rq| + assert_raises(ArgumentError, "req [#{rq}] should fail") { + Gem::Version::Requirement.new(rq) + } + end + end + + def test_normalize + assert_equal [1], Gem::Version.new("1").to_ints + assert_equal [1], Gem::Version.new("1.0").to_ints + assert_equal [1, 1], Gem::Version.new("1.1").to_ints + end + + def test_ok + assert_adequate( "0.2.33", "= 0.2.33") + assert_adequate( "0.2.34", "> 0.2.33") + assert_adequate( "1.0", "= 1.0") + assert_adequate( "1.0", "1.0") + assert_adequate( "1.8.2", "> 1.8.0") + assert_adequate( "1.112", "> 1.111") + assert_adequate( "0.2", "> 0.0.0") + assert_adequate( "0.0.0.0.0.2", "> 0.0.0") + assert_adequate( "0.0.1.0", "> 0.0.0.1") + assert_adequate( "10.3.2", "> 9.3.2") + assert_adequate( "1.0.0.0", "= 1.0") + assert_adequate( "10.3.2", "!= 9.3.4") + assert_adequate( "10.3.2", "> 9.3.2") + assert_adequate( "10.3.2", "> 9.3.2") + assert_adequate( " 9.3.2", ">= 9.3.2") + assert_adequate( "9.3.2 ", ">= 9.3.2") + assert_adequate( "", "= 0") + assert_adequate( "", "< 0.1") + assert_adequate( " ", "< 0.1 ") + assert_adequate( "", " < 0.1") + assert_adequate( "0", "=") + assert_adequate( "0", ">=") + assert_adequate( "0", "<=") + end + + def test_satisfied_by_eh_boxed + assert_inadequate("1.3", "~> 1.4") + assert_adequate( "1.4", "~> 1.4") + assert_adequate( "1.5", "~> 1.4") + assert_inadequate("2.0", "~> 1.4") + + assert_inadequate("1.3", "~> 1.4.4") + assert_inadequate("1.4", "~> 1.4.4") + assert_adequate( "1.4.4", "~> 1.4.4") + assert_adequate( "1.4.5", "~> 1.4.4") + assert_inadequate("1.5", "~> 1.4.4") + assert_inadequate("2.0", "~> 1.4.4") + end + + def test_satisfied_by_eh_multiple + req = [">= 1.4", "<= 1.6", "!= 1.5"] + assert_inadequate("1.3", req) + assert_adequate( "1.4", req) + assert_inadequate("1.5", req) + assert_adequate( "1.6", req) + assert_inadequate("1.7", req) + assert_inadequate("2.0", req) + end + + def test_spaceship + assert_equal 1, Gem::Version.new('1.8.2') <=> Gem::Version.new('0.0.0') + end + + def test_boxed + assert_inadequate("1.3", "~> 1.4") + assert_adequate( "1.4", "~> 1.4") + assert_adequate( "1.5", "~> 1.4") + assert_inadequate("2.0", "~> 1.4") + + assert_inadequate("1.3", "~> 1.4.4") + assert_inadequate("1.4", "~> 1.4.4") + assert_adequate( "1.4.4", "~> 1.4.4") + assert_adequate( "1.4.5", "~> 1.4.4") + assert_inadequate("1.5", "~> 1.4.4") + assert_inadequate("2.0", "~> 1.4.4") + end + + def test_to_s + v = Gem::Version.new("5.2.4") + assert_equal "5.2.4", v.to_s + end + + def assert_adequate(version, requirement) + ver = Gem::Version.new(version) + req = Gem::Version::Requirement.new(requirement) + assert req.satisfied_by?(ver), + "Version #{version} should be adequate for Requirement #{requirement}" + end + + def assert_inadequate(version, requirement) + ver = Gem::Version.new(version) + req = Gem::Version::Requirement.new(requirement) + assert ! req.satisfied_by?(ver), + "Version #{version} should not be adequate for Requirement #{requirement}" + end + + def assert_version(actual) + assert_equal @v1_0, actual + assert_equal @v1_0.version, actual.version + end + +end + diff --git a/test/rubygems/test_gem_version_option.rb b/test/rubygems/test_gem_version_option.rb new file mode 100644 index 0000000000..30c73390fe --- /dev/null +++ b/test/rubygems/test_gem_version_option.rb @@ -0,0 +1,77 @@ +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') +require 'rubygems/command' +require 'rubygems/version_option' + +class TestGemVersionOption < RubyGemTestCase + + def setup + super + + @cmd = Gem::Command.new 'dummy', 'dummy' + @cmd.extend Gem::VersionOption + end + + def test_add_platform_option + @cmd.add_platform_option + + assert @cmd.handles?(%w[--platform x86-darwin]) + end + + def test_add_version_option + @cmd.add_version_option + + assert @cmd.handles?(%w[--version >1]) + end + + def test_platform_option + @cmd.add_platform_option + + @cmd.handle_options %w[--platform x86-freebsd6 --platform x86-freebsd7] + + expected = [ + Gem::Platform::RUBY, + Gem::Platform.new('x86-freebsd6'), + Gem::Platform.new('x86-freebsd7'), + ] + + assert_equal expected, Gem.platforms + end + + def test_platform_option_ruby + @cmd.add_platform_option + + @cmd.handle_options %w[--platform ruby] + + expected = [ + Gem::Platform::RUBY + ] + + assert_equal expected, Gem.platforms + end + + def test_platform_option_twice + @cmd.add_platform_option + + @cmd.handle_options %w[--platform x86-freebsd6 --platform x86-freebsd-6] + + expected = [ + Gem::Platform::RUBY, + Gem::Platform.new('x86-freebsd6'), + ] + + assert_equal expected, Gem.platforms + end + + def test_version_option + @cmd.add_version_option + + @cmd.handle_options %w[--version >1] + + expected = { :version => Gem::Requirement.new('> 1'), :args => [] } + + assert_equal expected, @cmd.options + end + +end + diff --git a/test/rubygems/test_kernel.rb b/test/rubygems/test_kernel.rb new file mode 100644 index 0000000000..d7d5eaaee2 --- /dev/null +++ b/test/rubygems/test_kernel.rb @@ -0,0 +1,64 @@ +#!/usr/bin/env ruby +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities') + +class TestKernel < RubyGemTestCase + + def setup + super + + @old_path = $:.dup + + util_make_gems + end + + def teardown + super + + $:.replace @old_path + end + + def test_gem + assert gem('a', '= 0.0.1'), "Should load" + assert $:.any? { |p| %r{a-0.0.1/lib} =~ p } + assert $:.any? { |p| %r{a-0.0.1/bin} =~ p } + end + + def test_gem_redundent + assert gem('a', '= 0.0.1'), "Should load" + assert ! gem('a', '= 0.0.1'), "Should not load" + assert_equal 1, $:.select { |p| %r{a-0.0.1/lib} =~ p }.size + assert_equal 1, $:.select { |p| %r{a-0.0.1/bin} =~ p }.size + end + + def test_gem_overlapping + assert gem('a', '= 0.0.1'), "Should load" + assert ! gem('a', '>= 0.0.1'), "Should not load" + assert_equal 1, $:.select { |p| %r{a-0.0.1/lib} =~ p }.size + assert_equal 1, $:.select { |p| %r{a-0.0.1/bin} =~ p }.size + end + + def test_gem_conflicting + assert gem('a', '= 0.0.1'), "Should load" + + ex = assert_raise Gem::Exception do + gem 'a', '= 0.0.2' + end + + assert_match(/activate a \(= 0\.0\.2\)/, ex.message) + assert_match(/activated a-0\.0\.1/, ex.message) + + assert $:.any? { |p| %r{a-0.0.1/lib} =~ p } + assert $:.any? { |p| %r{a-0.0.1/bin} =~ p } + assert ! $:.any? { |p| %r{a-0.0.2/lib} =~ p } + assert ! $:.any? { |p| %r{a-0.0.2/bin} =~ p } + end + +end + diff --git a/test/rubygems/test_open_uri.rb b/test/rubygems/test_open_uri.rb new file mode 100644 index 0000000000..6f18b7bb6b --- /dev/null +++ b/test/rubygems/test_open_uri.rb @@ -0,0 +1,13 @@ +require 'test/unit' +require 'rubygems/gem_open_uri' + +class TestOpenURI < Test::Unit::TestCase + + def test_open_uri_not_broken + assert_nothing_raised do + open __FILE__ do end + end + end + +end + diff --git a/test/rubygems/test_package.rb b/test/rubygems/test_package.rb new file mode 100644 index 0000000000..786400fe0c --- /dev/null +++ b/test/rubygems/test_package.rb @@ -0,0 +1,607 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'test/unit' +require 'stringio' +require 'fileutils' + +require 'rubygems' +require 'rubygems/package' + +class File + + # straight from setup.rb + def self.dir?(path) + # for corrupted windows stat() + File.directory?((path[-1,1] == '/') ? path : path + '/') + end + + def self.read_b(name) + File.open(name, "rb"){|f| f.read} + end + +end + +class TarTestCase < Test::Unit::TestCase + + undef_method :default_test + + def assert_headers_equal(h1, h2) + fields = %w[name 100 mode 8 uid 8 gid 8 size 12 mtime 12 checksum 8 + typeflag 1 linkname 100 magic 6 version 2 uname 32 + gname 32 devmajor 8 devminor 8 prefix 155] + offset = 0 + until fields.empty? + name = fields.shift + length = fields.shift.to_i + if name == "checksum" + chksum_off = offset + offset += length + next + end + assert_equal(h1[offset, length], h2[offset, length], + "Field #{name} of the tar header differs.") + offset += length + end + assert_equal(h1[chksum_off, 8], h2[chksum_off, 8]) + end + + def tar_file_header(fname, dname, mode, length) + h = header("0", fname, dname, length, mode) + checksum = calc_checksum(h) + header("0", fname, dname, length, mode, checksum) + end + + def tar_dir_header(name, prefix, mode) + h = header("5", name, prefix, 0, mode) + checksum = calc_checksum(h) + header("5", name, prefix, 0, mode, checksum) + end + + def header(type, fname, dname, length, mode, checksum = nil) + checksum ||= " " * 8 + + arr = [ # struct tarfile_entry_posix + ASCIIZ(fname, 100), # char name[100]; ASCII + (Z unless filled) + Z(to_oct(mode, 7)), # char mode[8]; 0 padded, octal null + Z(to_oct(0, 7)), # char uid[8]; ditto + Z(to_oct(0, 7)), # char gid[8]; ditto + Z(to_oct(length, 11)), # char size[12]; 0 padded, octal, null + Z(to_oct(0, 11)), # char mtime[12]; 0 padded, octal, null + checksum, # char checksum[8]; 0 padded, octal, null, space + type, # char typeflag[1]; file: "0" dir: "5" + "\0" * 100, # char linkname[100]; ASCII + (Z unless filled) + "ustar\0", # char magic[6]; "ustar\0" + "00", # char version[2]; "00" + ASCIIZ("wheel", 32), # char uname[32]; ASCIIZ + ASCIIZ("wheel", 32), # char gname[32]; ASCIIZ + Z(to_oct(0, 7)), # char devmajor[8]; 0 padded, octal, null + Z(to_oct(0, 7)), # char devminor[8]; 0 padded, octal, null + ASCIIZ(dname, 155) # char prefix[155]; ASCII + (Z unless filled) + ] + + format = "C100C8C8C8C12C12C8CC100C6C2C32C32C8C8C155" + h = if RUBY_VERSION >= "1.9" then + arr.join + else + arr = arr.join("").split(//).map{|x| x[0]} + arr.pack format + end + ret = h + "\0" * (512 - h.size) + assert_equal(512, ret.size) + ret + end + + def calc_checksum(header) + sum = header.unpack("C*").inject{|s,a| s + a} + SP(Z(to_oct(sum, 6))) + end + + def to_oct(n, pad_size) + "%0#{pad_size}o" % n + end + + def ASCIIZ(str, length) + str + "\0" * (length - str.length) + end + + def SP(s) + s + " " + end + + def Z(s) + s + "\0" + end + + def SP_Z(s) + s + " \0" + end + +end + +class TestTarHeader < TarTestCase + + def test_arguments_are_checked + e = ArgumentError + gpth = Gem::Package::TarHeader + assert_raises(e) { gpth.new :name=>"", :size=>"", :mode=>"" } + assert_raises(e) { gpth.new :name=>"", :size=>"", :prefix=>"" } + assert_raises(e) { gpth.new :name=>"", :prefix=>"", :mode=>"" } + assert_raises(e) { gpth.new :prefix=>"", :size=>"", :mode=>"" } + end + + def test_basic_headers + header = Gem::Package::TarHeader.new(:name => "bla", :mode => 012345, + :size => 10, :prefix => "").to_s + assert_headers_equal(tar_file_header("bla", "", 012345, 10), header.to_s) + header = Gem::Package::TarHeader.new(:name => "bla", :mode => 012345, + :size => 0, :prefix => "", + :typeflag => "5" ).to_s + assert_headers_equal(tar_dir_header("bla", "", 012345), header) + end + + def test_long_name_works + header = Gem::Package::TarHeader.new(:name => "a" * 100, :mode => 012345, + :size => 10, :prefix => "").to_s + assert_headers_equal(tar_file_header("a" * 100, "", 012345, 10), header) + + header = Gem::Package::TarHeader.new(:name => "a" * 100, :mode => 012345, + :size => 10, :prefix => "bb" * 60).to_s + assert_headers_equal(tar_file_header("a" * 100, "bb" * 60, 012345, 10), + header) + end + + def test_new_from_stream + header = tar_file_header("a" * 100, "", 012345, 10) + h = nil + header = StringIO.new header + assert_nothing_raised{ h = Gem::Package::TarHeader.new_from_stream header } + assert_equal("a" * 100, h.name) + assert_equal(012345, h.mode) + assert_equal(10, h.size) + assert_equal("", h.prefix) + assert_equal("ustar", h.magic) + end + +end + +class TestTarInput < TarTestCase + + # Sometimes the setgid bit doesn't take. Don't know if this + # is a problem on all systems, or just some. But for now, we + # will ignore it in the tests. + SETGID_BIT = 02000 + + def setup + FileUtils.mkdir_p "data__" + inner_tar = tar_file_header("bla", "", 0612, 10) + inner_tar += "0123456789" + "\0" * 502 + inner_tar += tar_file_header("foo", "", 0636, 5) + inner_tar += "01234" + "\0" * 507 + inner_tar += tar_dir_header("__dir__", "", 0600) + inner_tar += "\0" * 1024 + str = StringIO.new "" + begin + os = Zlib::GzipWriter.new str + os.write inner_tar + ensure + os.finish + end + str.rewind + File.open("data__/bla.tar", "wb") do |f| + f.write tar_file_header("data.tar.gz", "", 0644, str.string.size) + f.write str.string + f.write "\0" * ((512 - (str.string.size % 512)) % 512 ) + @spec = Gem::Specification.new do |spec| + spec.author = "Mauricio :)" + end + meta = @spec.to_yaml + f.write tar_file_header("metadata", "", 0644, meta.size) + f.write meta + "\0" * (1024 - meta.size) + f.write "\0" * 1024 + end + @file = "data__/bla.tar" + @entry_names = %w{bla foo __dir__} + @entry_sizes = [10, 5, 0] + #FIXME: are these modes system dependent? + @entry_modes = [0100612, 0100636, 040600] + @entry_files = %w{data__/bla data__/foo} + @entry_contents = %w[0123456789 01234] + end + + def teardown + # FileUtils.rm_rf "data__" + end + + def test_each_works + Gem::Package::TarInput.open(@file) do |is| + count = 0 + + is.each_with_index do |entry, i| + count = i + + assert_kind_of(Gem::Package::TarReader::Entry, entry) + assert_equal(@entry_names[i], entry.name) + assert_equal(@entry_sizes[i], entry.size) + end + + assert_equal 2, count + + assert_equal @spec, is.metadata + end + end + + def test_extract_entry_works + Gem::Package::TarInput.open(@file) do |is| + assert_equal @spec, is.metadata + count = 0 + + is.each_with_index do |entry, i| + count = i + is.extract_entry "data__", entry + name = File.join("data__", entry.name) + + if entry.is_directory? + assert File.dir?(name) + else + assert File.file?(name) + assert_equal(@entry_sizes[i], File.stat(name).size) + #FIXME: win32? !! + end + + unless ::Config::CONFIG["arch"] =~ /msdos|win32/i + assert_equal(@entry_modes[i], + File.stat(name).mode & (~SETGID_BIT)) + end + end + + assert_equal 2, count + end + + @entry_files.each_with_index do |x, i| + assert(File.file?(x)) + assert_equal(@entry_contents[i], File.read_b(x)) + end + end + +end + +class TestTarOutput < TarTestCase + + def setup + FileUtils.mkdir_p "data__", :verbose=>false + @file = "data__/bla2.tar" + end + + def teardown + FileUtils.rm_rf "data__" + end + + def test_file_looks_good + Gem::Package::TarOutput.open(@file) do |os| + os.metadata = "bla".to_yaml + end + f = File.open(@file, "rb") + Gem::Package::TarReader.new(f) do |is| + i = 0 + is.each do |entry| + case i + when 0 + assert_equal("data.tar.gz", entry.name) + when 1 + assert_equal("metadata.gz", entry.name) + gzis = Zlib::GzipReader.new entry + assert_equal("bla".to_yaml, gzis.read) + gzis.close + end + i += 1 + end + assert_equal(2, i) + end + ensure + f.close + end + +end + +class TestTarReader < TarTestCase + + def test_eof_works + str = tar_file_header("bar", "baz", 0644, 0) + Gem::Package::TarReader.new(StringIO.new(str)) do |is| + is.each_entry do |entry| + assert_kind_of(Gem::Package::TarReader::Entry, entry) + data = entry.read + assert_equal(nil, data) + assert_equal(nil, entry.read(10)) + assert_equal(nil, entry.read) + assert_equal(nil, entry.getc) + assert_equal(true, entry.eof?) + end + end + str = tar_dir_header("foo", "bar", 012345) + Gem::Package::TarReader.new(StringIO.new(str)) do |is| + is.each_entry do |entry| + assert_kind_of(Gem::Package::TarReader::Entry, entry) + data = entry.read + assert_equal(nil, data) + assert_equal(nil, entry.read(10)) + assert_equal(nil, entry.read) + assert_equal(nil, entry.getc) + assert_equal(true, entry.eof?) + end + end + str = tar_dir_header("foo", "bar", 012345) + str += tar_file_header("bar", "baz", 0644, 0) + str += tar_file_header("bar", "baz", 0644, 0) + Gem::Package::TarReader.new(StringIO.new(str)) do |is| + is.each_entry do |entry| + assert_kind_of(Gem::Package::TarReader::Entry, entry) + data = entry.read + assert_equal(nil, data) + assert_equal(nil, entry.read(10)) + assert_equal(nil, entry.read) + assert_equal(nil, entry.getc) + assert_equal(true, entry.eof?) + end + end + end + + def test_multiple_entries + str = tar_file_header("lib/foo", "", 010644, 10) + "\0" * 512 + str += tar_file_header("bar", "baz", 0644, 0) + str += tar_dir_header("foo", "bar", 012345) + str += "\0" * 1024 + names = %w[lib/foo bar foo] + prefixes = ["", "baz", "bar"] + modes = [010644, 0644, 012345] + sizes = [10, 0, 0] + isdir = [false, false, true] + isfile = [true, true, false] + Gem::Package::TarReader.new(StringIO.new(str)) do |is| + i = 0 + is.each_entry do |entry| + assert_kind_of(Gem::Package::TarReader::Entry, entry) + assert_equal(names[i], entry.name) + assert_equal(prefixes[i], entry.prefix) + assert_equal(sizes[i], entry.size) + assert_equal(modes[i], entry.mode) + assert_equal(isdir[i], entry.is_directory?) + assert_equal(isfile[i], entry.is_file?) + if prefixes[i] != "" + assert_equal(File.join(prefixes[i], names[i]), + entry.full_name) + else + assert_equal(names[i], entry.name) + end + i += 1 + end + assert_equal(names.size, i) + end + end + + def test_read_works + contents = ('a'..'z').inject(""){|s,x| s << x * 100} + str = tar_file_header("lib/foo", "", 010644, contents.size) + contents + str += "\0" * (512 - (str.size % 512)) + Gem::Package::TarReader.new(StringIO.new(str)) do |is| + is.each_entry do |entry| + assert_kind_of(Gem::Package::TarReader::Entry, entry) + data = entry.read(3000) # bigger than contents.size + assert_equal(contents, data) + assert_equal(true, entry.eof?) + end + end + Gem::Package::TarReader.new(StringIO.new(str)) do |is| + is.each_entry do |entry| + assert_kind_of(Gem::Package::TarReader::Entry, entry) + data = entry.read(100) + (entry.size - data.size).times {|i| data << entry.getc.chr } + assert_equal(contents, data) + assert_equal(nil, entry.read(10)) + assert_equal(true, entry.eof?) + end + end + Gem::Package::TarReader.new(StringIO.new(str)) do |is| + is.each_entry do |entry| + assert_kind_of(Gem::Package::TarReader::Entry, entry) + data = entry.read + assert_equal(contents, data) + assert_equal(nil, entry.read(10)) + assert_equal(nil, entry.read) + assert_equal(nil, entry.getc) + assert_equal(true, entry.eof?) + end + end + end + + def test_rewind_entry_works + content = ('a'..'z').to_a.join(" ") + str = tar_file_header("lib/foo", "", 010644, content.size) + content + + "\0" * (512 - content.size) + str << "\0" * 1024 + Gem::Package::TarReader.new(StringIO.new(str)) do |is| + is.each_entry do |entry| + 3.times do + entry.rewind + assert_equal(content, entry.read) + assert_equal(content.size, entry.pos) + end + end + end + end + + def test_rewind_works + content = ('a'..'z').to_a.join(" ") + str = tar_file_header("lib/foo", "", 010644, content.size) + content + + "\0" * (512 - content.size) + str << "\0" * 1024 + Gem::Package::TarReader.new(StringIO.new(str)) do |is| + 3.times do + is.rewind + i = 0 + is.each_entry do |entry| + assert_equal(content, entry.read) + i += 1 + end + assert_equal(1, i) + end + end + end + +end + +class TestTarWriter < TarTestCase + + class DummyIO + attr_reader :data + def initialize + @data = "" + end + def write(dat) + data << dat + dat.size + end + def reset + @data = "" + end + end + + def setup + @data = "a" * 10 + @dummyos = DummyIO.new + @os = Gem::Package::TarWriter.new(@dummyos) + end + + def teardown + @os.close + end + + def test_add_file + dummyos = StringIO.new + class << dummyos + def method_missing(meth, *a) + self.string.send(meth, *a) + end + end + os = Gem::Package::TarWriter.new dummyos + content1 = ('a'..'z').to_a.join("") # 26 + content2 = ('aa'..'zz').to_a.join("") # 1352 + Gem::Package::TarWriter.new(dummyos) do |os| + os.add_file("lib/foo/bar", 0644) {|f| f.write "a" * 10 } + os.add_file("lib/bar/baz", 0644) {|f| f.write content1 } + os.add_file("lib/bar/baz", 0644) {|f| f.write content2 } + os.add_file("lib/bar/baz", 0644) {|f| } + end + assert_headers_equal(tar_file_header("lib/foo/bar", "", 0644, 10), + dummyos[0,512]) + assert_equal("a" * 10 + "\0" * 502, dummyos[512,512]) + offset = 512 * 2 + [content1, content2, ""].each do |data| + assert_headers_equal(tar_file_header("lib/bar/baz", "", 0644, + data.size), + dummyos[offset,512]) + offset += 512 + until !data || data == "" + chunk = data[0,512] + data[0,512] = "" + assert_equal(chunk + "\0" * (512-chunk.size), + dummyos[offset,512]) + offset += 512 + end + end + assert_equal("\0" * 1024, dummyos[offset,1024]) + end + + def test_add_file_simple + @dummyos.reset + Gem::Package::TarWriter.new(@dummyos) do |os| + os.add_file_simple("lib/foo/bar", 0644, 10) {|f| f.write "a" * 10 } + os.add_file_simple("lib/bar/baz", 0644, 100) {|f| f.write "fillme"} + end + assert_headers_equal(tar_file_header("lib/foo/bar", "", 0644, 10), + @dummyos.data[0,512]) + assert_equal("a" * 10 + "\0" * 502, @dummyos.data[512,512]) + assert_headers_equal(tar_file_header("lib/bar/baz", "", 0644, 100), + @dummyos.data[512*2,512]) + assert_equal("fillme" + "\0" * 506, @dummyos.data[512*3,512]) + assert_equal("\0" * 512, @dummyos.data[512*4, 512]) + assert_equal("\0" * 512, @dummyos.data[512*5, 512]) + end + + def test_add_file_tests_seekability + assert_raises(Gem::Package::NonSeekableIO) do + @os.add_file("libdfdsfd", 0644) {|f| } + end + end + + def test_file_name_is_split_correctly + # test insane file lengths, and + # a{100}/b{155}, etc + @dummyos.reset + names = ["a" * 155 + '/' + "b" * 100, "a" * 151 + "/" + ("qwer/" * 19) + "bla" ] + o_names = ["b" * 100, "qwer/" * 19 + "bla"] + o_prefixes = ["a" * 155, "a" * 151] + names.each {|name| @os.add_file_simple(name, 0644, 10) { } } + o_names.each_with_index do |nam, i| + assert_headers_equal(tar_file_header(nam, o_prefixes[i], 0644, 10), + @dummyos.data[2*i*512,512]) + end + assert_raises(Gem::Package::TooLongFileName) do + @os.add_file_simple(File.join("a" * 152, "b" * 10, "a" * 92), 0644,10) {} + end + assert_raises(Gem::Package::TooLongFileName) do + @os.add_file_simple(File.join("a" * 162, "b" * 10), 0644,10) {} + end + assert_raises(Gem::Package::TooLongFileName) do + @os.add_file_simple(File.join("a" * 10, "b" * 110), 0644,10) {} + end + end + + def test_file_size_is_checked + @dummyos.reset + assert_raises(Gem::Package::TarWriter::FileOverflow) do + @os.add_file_simple("lib/foo/bar", 0644, 10) {|f| f.write "1" * 100} + end + assert_nothing_raised do + @os.add_file_simple("lib/foo/bar", 0644, 10) {|f| } + end + end + + def test_write_data + @dummyos.reset + @os.add_file_simple("lib/foo/bar", 0644, 10) { |f| f.write @data } + @os.flush + assert_equal(@data + ("\0" * (512-@data.size)), + @dummyos.data[512,512]) + end + + def test_write_header + @dummyos.reset + @os.add_file_simple("lib/foo/bar", 0644, 0) { |f| } + @os.flush + assert_headers_equal(tar_file_header("lib/foo/bar", "", 0644, 0), + @dummyos.data[0,512]) + @dummyos.reset + @os.mkdir("lib/foo", 0644) + assert_headers_equal(tar_dir_header("lib/foo", "", 0644), + @dummyos.data[0,512]) + @os.mkdir("lib/bar", 0644) + assert_headers_equal(tar_dir_header("lib/bar", "", 0644), + @dummyos.data[512*1,512]) + end + + def test_write_operations_fail_after_closed + @dummyos.reset + @os.add_file_simple("sadd", 0644, 20) { |f| } + @os.close + assert_raises(Gem::Package::ClosedIO) { @os.flush } + assert_raises(Gem::Package::ClosedIO) { @os.add_file("dfdsf", 0644){} } + assert_raises(Gem::Package::ClosedIO) { @os.mkdir "sdfdsf", 0644 } + end + +end + |