BigW Consortium Gitlab

parser_spec.rb 6.22 KB
Newer Older
1 2 3 4 5 6
require 'spec_helper'

describe Gitlab::Conflict::Parser, lib: true do
  let(:parser) { Gitlab::Conflict::Parser.new }

  describe '#parse' do
7 8 9 10
    def parse_text(text)
      parser.parse(text, our_path: 'README.md', their_path: 'README.md')
    end

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
    context 'when the file has valid conflicts' do
      let(:text) do
        <<CONFLICT
module Gitlab
  module Regexp
    extend self

    def username_regexp
      default_regexp
    end

<<<<<<< files/ruby/regex.rb
    def project_name_regexp
      /\A[a-zA-Z0-9][a-zA-Z0-9_\-\. ]*\z/
    end

    def name_regexp
      /\A[a-zA-Z0-9_\-\. ]*\z/
=======
    def project_name_regex
      %r{\A[a-zA-Z0-9][a-zA-Z0-9_\-\. ]*\z}
    end

    def name_regex
      %r{\A[a-zA-Z0-9_\-\. ]*\z}
>>>>>>> files/ruby/regex.rb
    end

    def path_regexp
      default_regexp
    end

<<<<<<< files/ruby/regex.rb
    def archive_formats_regexp
      /(zip|tar|7z|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/
=======
    def archive_formats_regex
      %r{(zip|tar|7z|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)}
>>>>>>> files/ruby/regex.rb
    end

    def git_reference_regexp
      # Valid git ref regexp, see:
      # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
      %r{
        (?!
           (?# doesn't begins with)
           \/|                    (?# rule #6)
           (?# doesn't contain)
           .*(?:
              [\/.]\.|            (?# rule #1,3)
              \/\/|               (?# rule #6)
              @\{|                (?# rule #8)
              \\                  (?# rule #9)
           )
        )
        [^\000-\040\177~^:?*\[]+  (?# rule #4-5)
        (?# doesn't end with)
        (?<!\.lock)               (?# rule #1)
        (?<![\/.])                (?# rule #6-7)
      }x
    end

    protected

<<<<<<< files/ruby/regex.rb
    def default_regexp
      /\A[.?]?[a-zA-Z0-9][a-zA-Z0-9_\-\.]*(?<!\.git)\z/
=======
    def default_regex
      %r{\A[.?]?[a-zA-Z0-9][a-zA-Z0-9_\-\.]*(?<!\.git)\z}
>>>>>>> files/ruby/regex.rb
    end
  end
end
CONFLICT
      end

89 90 91
      let(:lines) do
        parser.parse(text, our_path: 'files/ruby/regex.rb', their_path: 'files/ruby/regex.rb')
      end
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172

      it 'sets our lines as new lines' do
        expect(lines[8..13]).to all(have_attributes(type: 'new'))
        expect(lines[26..27]).to all(have_attributes(type: 'new'))
        expect(lines[56..57]).to all(have_attributes(type: 'new'))
      end

      it 'sets their lines as old lines' do
        expect(lines[14..19]).to all(have_attributes(type: 'old'))
        expect(lines[28..29]).to all(have_attributes(type: 'old'))
        expect(lines[58..59]).to all(have_attributes(type: 'old'))
      end

      it 'sets non-conflicted lines as both' do
        expect(lines[0..7]).to all(have_attributes(type: nil))
        expect(lines[20..25]).to all(have_attributes(type: nil))
        expect(lines[30..55]).to all(have_attributes(type: nil))
        expect(lines[60..62]).to all(have_attributes(type: nil))
      end

      it 'sets consecutive line numbers for index, old_pos, and new_pos' do
        old_line_numbers = lines.select { |line| line.type != 'new' }.map(&:old_pos)
        new_line_numbers = lines.select { |line| line.type != 'old' }.map(&:new_pos)

        expect(lines.map(&:index)).to eq(0.upto(62).to_a)
        expect(old_line_numbers).to eq(1.upto(53).to_a)
        expect(new_line_numbers).to eq(1.upto(53).to_a)
      end
    end

    context 'when the file contents include conflict delimiters' do
      it 'raises UnexpectedDelimiter when there is a non-start delimiter first' do
        expect { parse_text('=======') }.
          to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)

        expect { parse_text('>>>>>>> README.md') }.
          to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)

        expect { parse_text('>>>>>>> some-other-path.md') }.
          not_to raise_error
      end

      it 'raises UnexpectedDelimiter when a start delimiter is followed by a non-middle delimiter' do
        start_text = "<<<<<<< README.md\n"
        end_text = "\n=======\n>>>>>>> README.md"

        expect { parse_text(start_text + '>>>>>>> README.md' + end_text) }.
          to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)

        expect { parse_text(start_text + start_text + end_text) }.
          to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)

        expect { parse_text(start_text + '>>>>>>> some-other-path.md' + end_text) }.
          not_to raise_error
      end

      it 'raises UnexpectedDelimiter when a middle delimiter is followed by a non-end delimiter' do
        start_text = "<<<<<<< README.md\n=======\n"
        end_text = "\n>>>>>>> README.md"

        expect { parse_text(start_text + '=======' + end_text) }.
          to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)

        expect { parse_text(start_text + start_text + end_text) }.
          to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)

        expect { parse_text(start_text + '>>>>>>> some-other-path.md' + end_text) }.
          not_to raise_error
      end

      it 'raises MissingEndDelimiter when there is no end delimiter at the end' do
        start_text = "<<<<<<< README.md\n=======\n"

        expect { parse_text(start_text) }.
          to raise_error(Gitlab::Conflict::Parser::MissingEndDelimiter)

        expect { parse_text(start_text + '>>>>>>> some-other-path.md') }.
          to raise_error(Gitlab::Conflict::Parser::MissingEndDelimiter)
      end
    end

173 174 175 176 177 178 179 180 181
    context 'other file types' do
      it 'raises UnmergeableFile when lines is blank, indicating a binary file' do
        expect { parse_text('') }.
          to raise_error(Gitlab::Conflict::Parser::UnmergeableFile)

        expect { parse_text(nil) }.
          to raise_error(Gitlab::Conflict::Parser::UnmergeableFile)
      end

182 183
      it 'raises UnmergeableFile when the file is over 200 KB' do
        expect { parse_text('a' * 204801) }.
184 185
          to raise_error(Gitlab::Conflict::Parser::UnmergeableFile)
      end
186 187 188 189 190

      it 'raises UnsupportedEncoding when the file contains non-UTF-8 characters' do
        expect { parse_text("a\xC4\xFC".force_encoding(Encoding::ASCII_8BIT)) }.
          to raise_error(Gitlab::Conflict::Parser::UnsupportedEncoding)
      end
191 192 193
    end
  end
end