require 'rubygems/test_case' require 'rubygems/request_set' require 'rubygems/request_set/lockfile' class TestGemRequestSetLockfile < Gem::TestCase def setup super Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new util_set_arch 'i686-darwin8.10.1' @set = Gem::RequestSet.new @git_set = Gem::Resolver::GitSet.new @vendor_set = Gem::Resolver::VendorSet.new @set.instance_variable_set :@git_set, @git_set @set.instance_variable_set :@vendor_set, @vendor_set @gem_deps_file = 'gem.deps.rb' @lockfile = Gem::RequestSet::Lockfile.new @set, @gem_deps_file end def write_gem_deps gem_deps open @gem_deps_file, 'w' do |io| io.write gem_deps end end def write_lockfile lockfile @lock_file = File.expand_path "#{@gem_deps_file}.lock" open @lock_file, 'w' do |io| io.write lockfile end end def test_get @lockfile.instance_variable_set :@tokens, [:token] assert_equal :token, @lockfile.get end def test_get_type_mismatch @lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]] e = assert_raises Gem::RequestSet::Lockfile::ParseError do @lockfile.get :text end expected = 'unexpected token [:section, "x"], expected :text (at line 1 column 5)' assert_equal expected, e.message assert_equal 1, e.line assert_equal 5, e.column assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path end def test_get_type_multiple @lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]] assert @lockfile.get [:text, :section] end def test_get_type_value_mismatch @lockfile.instance_variable_set :@tokens, [[:section, 'x', 5, 1]] e = assert_raises Gem::RequestSet::Lockfile::ParseError do @lockfile.get :section, 'y' end expected = 'unexpected token [:section, "x"], expected [:section, "y"] (at line 1 column 5)' assert_equal expected, e.message assert_equal 1, e.line assert_equal 5, e.column assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path end def test_parse write_lockfile <<-LOCKFILE.strip GEM remote: #{@gem_repo} specs: a (2) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a LOCKFILE @lockfile.parse assert_equal [dep('a')], @set.dependencies assert_equal [Gem::Platform::RUBY], @lockfile.platforms lockfile_set = @set.sets.find do |set| Gem::Resolver::LockSet === set end assert lockfile_set, 'could not find a LockSet' assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name } end def test_parse_dependencies write_lockfile <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a (>= 1, <= 2) LOCKFILE @lockfile.parse assert_equal [dep('a', '>= 1', '<= 2')], @set.dependencies assert_equal [Gem::Platform::RUBY], @lockfile.platforms lockfile_set = @set.sets.find do |set| Gem::Resolver::LockSet === set end assert lockfile_set, 'could not find a LockSet' assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name } end def test_parse_GIT write_lockfile <<-LOCKFILE GIT remote: git://example/a.git revision: master specs: a (2) b (>= 3) DEPENDENCIES a! LOCKFILE @lockfile.parse assert_equal [dep('a', '= 2')], @set.dependencies lockfile_set = @set.sets.find do |set| Gem::Resolver::LockSet === set end refute lockfile_set, 'fount a LockSet' git_set = @set.sets.find do |set| Gem::Resolver::GitSet === set end assert git_set, 'could not find a GitSet' assert_equal %w[a-2], git_set.specs.values.map { |s| s.full_name } assert_equal [dep('b', '>= 3')], git_set.specs.values.first.dependencies end def test_parse_PATH _, _, directory = vendor_gem write_lockfile <<-LOCKFILE PATH remote: #{directory} specs: a (1) DEPENDENCIES a! LOCKFILE @lockfile.parse assert_equal [dep('a', '= 1')], @set.dependencies lockfile_set = @set.sets.find do |set| Gem::Resolver::LockSet === set end refute lockfile_set, 'found a LockSet' vendor_set = @set.sets.find do |set| Gem::Resolver::VendorSet === set end assert vendor_set, 'could not find a VendorSet' assert_equal %w[a-1], vendor_set.specs.values.map { |s| s.full_name } end def test_parse_gem_specs_dependency write_lockfile <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2) b (= 3) c (~> 4) d e (~> 5.0, >= 5.0.1) b (3-x86_64-linux) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a LOCKFILE @lockfile.parse assert_equal [dep('a')], @set.dependencies assert_equal [Gem::Platform::RUBY], @lockfile.platforms lockfile_set = @set.sets.find do |set| Gem::Resolver::LockSet === set end assert lockfile_set, 'could not find a LockSet' assert_equal %w[a-2 b-3], lockfile_set.specs.map { |tuple| tuple.full_name } expected = [ Gem::Platform::RUBY, Gem::Platform.new('x86_64-linux'), ] assert_equal expected, lockfile_set.specs.map { |tuple| tuple.platform } spec = lockfile_set.specs.first expected = [ dep('b', '= 3'), dep('c', '~> 4'), dep('d'), dep('e', '~> 5.0', '>= 5.0.1'), ] assert_equal expected, spec.dependencies end def test_parse_missing @lockfile.parse lockfile_set = @set.sets.find do |set| Gem::Resolver::LockSet === set end refute lockfile_set end def test_peek @lockfile.instance_variable_set :@tokens, [:token] assert_equal :token, @lockfile.peek assert_equal :token, @lockfile.get assert_equal [:EOF], @lockfile.peek end def test_skip tokens = [[:token]] @lockfile.instance_variable_set :@tokens, tokens @lockfile.skip :token assert_empty tokens end def test_token_pos assert_equal [5, 0], @lockfile.token_pos(5) @lockfile.instance_variable_set :@line_pos, 2 @lockfile.instance_variable_set :@line, 1 assert_equal [3, 1], @lockfile.token_pos(5) end def test_tokenize write_lockfile <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2) b (= 2) c (!= 3) d (> 4) e (< 5) f (>= 6) g (<= 7) h (~> 8) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a LOCKFILE expected = [ [:section, 'GEM', 0, 0], [:newline, nil, 3, 0], [:entry, 'remote', 2, 1], [:text, @gem_repo, 10, 1], [:newline, nil, 34, 1], [:entry, 'specs', 2, 2], [:newline, nil, 8, 2], [:text, 'a', 4, 3], [:l_paren, nil, 6, 3], [:text, '2', 7, 3], [:r_paren, nil, 8, 3], [:newline, nil, 9, 3], [:text, 'b', 6, 4], [:l_paren, nil, 8, 4], [:requirement, '=', 9, 4], [:text, '2', 11, 4], [:r_paren, nil, 12, 4], [:newline, nil, 13, 4], [:text, 'c', 6, 5], [:l_paren, nil, 8, 5], [:requirement, '!=', 9, 5], [:text, '3', 12, 5], [:r_paren, nil, 13, 5], [:newline, nil, 14, 5], [:text, 'd', 6, 6], [:l_paren, nil, 8, 6], [:requirement, '>', 9, 6], [:text, '4', 11, 6], [:r_paren, nil, 12, 6], [:newline, nil, 13, 6], [:text, 'e', 6, 7], [:l_paren, nil, 8, 7], [:requirement, '<', 9, 7], [:text, '5', 11, 7], [:r_paren, nil, 12, 7], [:newline, nil, 13, 7], [:text, 'f', 6, 8], [:l_paren, nil, 8, 8], [:requirement, '>=', 9, 8], [:text, '6', 12, 8], [:r_paren, nil, 13, 8], [:newline, nil, 14, 8], [:text, 'g', 6, 9], [:l_paren, nil, 8, 9], [:requirement, '<=', 9, 9], [:text, '7', 12, 9], [:r_paren, nil, 13, 9], [:newline, nil, 14, 9], [:text, 'h', 6, 10], [:l_paren, nil, 8, 10], [:requirement, '~>', 9, 10], [:text, '8', 12, 10], [:r_paren, nil, 13, 10], [:newline, nil, 14, 10], [:newline, nil, 0, 11], [:section, 'PLATFORMS', 0, 12], [:newline, nil, 9, 12], [:text, Gem::Platform::RUBY, 2, 13], [:newline, nil, 6, 13], [:newline, nil, 0, 14], [:section, 'DEPENDENCIES', 0, 15], [:newline, nil, 12, 15], [:text, 'a', 2, 16], [:newline, nil, 3, 16], ] assert_equal expected, @lockfile.tokenize end def test_tokenize_capitals write_lockfile <<-LOCKFILE GEM remote: #{@gem_repo} specs: Ab (2) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES Ab LOCKFILE expected = [ [:section, 'GEM', 0, 0], [:newline, nil, 3, 0], [:entry, 'remote', 2, 1], [:text, @gem_repo, 10, 1], [:newline, nil, 34, 1], [:entry, 'specs', 2, 2], [:newline, nil, 8, 2], [:text, 'Ab', 4, 3], [:l_paren, nil, 7, 3], [:text, '2', 8, 3], [:r_paren, nil, 9, 3], [:newline, nil, 10, 3], [:newline, nil, 0, 4], [:section, 'PLATFORMS', 0, 5], [:newline, nil, 9, 5], [:text, Gem::Platform::RUBY, 2, 6], [:newline, nil, 6, 6], [:newline, nil, 0, 7], [:section, 'DEPENDENCIES', 0, 8], [:newline, nil, 12, 8], [:text, 'Ab', 2, 9], [:newline, nil, 4, 9], ] assert_equal expected, @lockfile.tokenize end def test_tokenize_conflict_markers write_lockfile '<<<<<<<' e = assert_raises Gem::RequestSet::Lockfile::ParseError do @lockfile.tokenize end assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)", e.message write_lockfile '|||||||' e = assert_raises Gem::RequestSet::Lockfile::ParseError do @lockfile.tokenize end assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)", e.message write_lockfile '=======' e = assert_raises Gem::RequestSet::Lockfile::ParseError do @lockfile.tokenize end assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)", e.message write_lockfile '>>>>>>>' e = assert_raises Gem::RequestSet::Lockfile::ParseError do @lockfile.tokenize end assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)", e.message end def test_tokenize_git write_lockfile <<-LOCKFILE DEPENDENCIES a! LOCKFILE expected = [ [:section, 'DEPENDENCIES', 0, 0], [:newline, nil, 12, 0], [:text, 'a', 2, 1], [:bang, nil, 3, 1], [:newline, nil, 4, 1], ] assert_equal expected, @lockfile.tokenize end def test_tokenize_missing tokens = @lockfile.tokenize assert_empty tokens end def test_tokenize_multiple write_lockfile <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2) b (~> 3.0, >= 3.0.1) LOCKFILE expected = [ [:section, 'GEM', 0, 0], [:newline, nil, 3, 0], [:entry, 'remote', 2, 1], [:text, @gem_repo, 10, 1], [:newline, nil, 34, 1], [:entry, 'specs', 2, 2], [:newline, nil, 8, 2], [:text, 'a', 4, 3], [:l_paren, nil, 6, 3], [:text, '2', 7, 3], [:r_paren, nil, 8, 3], [:newline, nil, 9, 3], [:text, 'b', 6, 4], [:l_paren, nil, 8, 4], [:requirement, '~>', 9, 4], [:text, '3.0', 12, 4], [:comma, nil, 15, 4], [:requirement, '>=', 17, 4], [:text, '3.0.1', 20, 4], [:r_paren, nil, 25, 4], [:newline, nil, 26, 4], ] assert_equal expected, @lockfile.tokenize end def test_to_s_gem spec_fetcher do |fetcher| fetcher.spec 'a', 2 end @set.gem 'a' expected = <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a LOCKFILE assert_equal expected, @lockfile.to_s end def test_to_s_gem_dependency spec_fetcher do |fetcher| fetcher.spec 'a', 2, 'c' => '>= 0', 'b' => '>= 0' fetcher.spec 'b', 2 fetcher.spec 'c', 2 end @set.gem 'a' expected = <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2) b c b (2) c (2) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a b c LOCKFILE assert_equal expected, @lockfile.to_s end def test_to_s_gem_dependency_non_default spec_fetcher do |fetcher| fetcher.spec 'a', 2, 'b' => '>= 1' fetcher.spec 'b', 2 end @set.gem 'b' @set.gem 'a' expected = <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2) b (>= 1) b (2) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a b LOCKFILE assert_equal expected, @lockfile.to_s end def test_to_s_gem_dependency_requirement spec_fetcher do |fetcher| fetcher.spec 'a', 2, 'b' => '>= 0' fetcher.spec 'b', 2 end @set.gem 'a', '>= 1' expected = <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2) b b (2) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a (>= 1) b LOCKFILE assert_equal expected, @lockfile.to_s end def test_to_s_gem_path name, version, directory = vendor_gem @vendor_set.add_vendor_gem name, directory @set.gem 'a' expected = <<-LOCKFILE PATH remote: #{directory} specs: #{name} (#{version}) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a! LOCKFILE assert_equal expected, @lockfile.to_s end def test_to_s_gem_path_absolute name, version, directory = vendor_gem @vendor_set.add_vendor_gem name, File.expand_path(directory) @set.gem 'a' expected = <<-LOCKFILE PATH remote: #{directory} specs: #{name} (#{version}) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a! LOCKFILE assert_equal expected, @lockfile.to_s end def test_to_s_gem_platform spec_fetcher do |fetcher| fetcher.spec 'a', 2 do |spec| spec.platform = Gem::Platform.local end end @set.gem 'a' expected = <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2-#{Gem::Platform.local}) PLATFORMS #{Gem::Platform.local} DEPENDENCIES a LOCKFILE assert_equal expected, @lockfile.to_s end def test_to_s_gem_source spec_fetcher do |fetcher| fetcher.spec 'a', 2 fetcher.clear end spec_fetcher 'http://other.example/' do |fetcher| fetcher.spec 'b', 2 fetcher.clear end Gem.sources << 'http://other.example/' @set.gem 'a' @set.gem 'b' expected = <<-LOCKFILE GEM remote: #{@gem_repo} specs: a (2) GEM remote: http://other.example/ specs: b (2) PLATFORMS #{Gem::Platform::RUBY} DEPENDENCIES a b LOCKFILE assert_equal expected, @lockfile.to_s end def test_to_s_git _, _, repository, = git_gem head = nil Dir.chdir repository do FileUtils.mkdir 'b' Dir.chdir 'b' do b = Gem::Specification.new 'b', 1 do |s| s.add_dependency 'a', '~> 1.0' s.add_dependency 'c', '~> 1.0' end open 'b.gemspec', 'w' do |io| io.write b.to_ruby end system @git, 'add', 'b.gemspec' system @git, 'commit', '--quiet', '-m', 'add b/b.gemspec' end FileUtils.mkdir 'c' Dir.chdir 'c' do c = Gem::Specification.new 'c', 1 open 'c.gemspec', 'w' do |io| io.write c.to_ruby end system @git, 'add', 'c.gemspec' system @git, 'commit', '--quiet', '-m', 'add c/c.gemspec' end head = `#{@git} rev-parse HEAD`.strip end @git_set.add_git_gem 'a', repository, 'HEAD', true @git_set.add_git_gem 'b', repository, 'HEAD', true @git_set.add_git_gem 'c', repository, 'HEAD', true @set.gem 'b' expected = <<-LOCKFILE GIT remote: #{repository} revision: #{head} specs: a (1) b (1) a (~> 1.0) c (~> 1.0) c (1) PLATFORMS ruby DEPENDENCIES a! b! c! LOCKFILE assert_equal expected, @lockfile.to_s end def test_unget @lockfile.instance_variable_set :@current_token, :token @lockfile.unget assert_equal :token, @lockfile.get end def test_write @lockfile.write gem_deps_lock_file = "#{@gem_deps_file}.lock" assert_path_exists gem_deps_lock_file refute_empty File.read gem_deps_lock_file end end