BigW Consortium Gitlab

parser_spec.rb 7.43 KB
Newer Older
1 2
require 'spec_helper'

3
describe Gitlab::Conflict::Parser do
4
  let(:parser) { described_class.new }
5 6

  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

      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
123 124
      context 'when there is a non-start delimiter first' do
        it 'raises UnexpectedDelimiter when there is a middle delimiter first' do
125 126
          expect { parse_text('=======') }
            .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
127 128 129
        end

        it 'raises UnexpectedDelimiter when there is an end delimiter first' do
130 131
          expect { parse_text('>>>>>>> README.md') }
            .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
132 133 134
        end

        it 'does not raise when there is an end delimiter for a different path first' do
135 136
          expect { parse_text('>>>>>>> some-other-path.md') }
            .not_to raise_error
137
        end
138 139
      end

140 141 142
      context 'when a start delimiter is followed by a non-middle delimiter' do
        let(:start_text) { "<<<<<<< README.md\n" }
        let(:end_text) { "\n=======\n>>>>>>> README.md" }
143

144
        it 'raises UnexpectedDelimiter when it is followed by an end delimiter' do
145 146
          expect { parse_text(start_text + '>>>>>>> README.md' + end_text) }
            .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
147
        end
148

149
        it 'raises UnexpectedDelimiter when it is followed by another start delimiter' do
150 151
          expect { parse_text(start_text + start_text + end_text) }
            .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
152
        end
153

154
        it 'does not raise when it is followed by a start delimiter for a different path' do
155 156
          expect { parse_text(start_text + '>>>>>>> some-other-path.md' + end_text) }
            .not_to raise_error
157
        end
158 159
      end

160 161 162
      context 'when a middle delimiter is followed by a non-end delimiter' do
        let(:start_text) { "<<<<<<< README.md\n=======\n" }
        let(:end_text) { "\n>>>>>>> README.md" }
163

164
        it 'raises UnexpectedDelimiter when it is followed by another middle delimiter' do
165 166
          expect { parse_text(start_text + '=======' + end_text) }
            .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
167
        end
168

169
        it 'raises UnexpectedDelimiter when it is followed by a start delimiter' do
170 171
          expect { parse_text(start_text + start_text + end_text) }
            .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
172
        end
173

174
        it 'does not raise when it is followed by a start delimiter for another path' do
175 176
          expect { parse_text(start_text + '<<<<<<< some-other-path.md' + end_text) }
            .not_to raise_error
177
        end
178 179 180 181 182
      end

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

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

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

191 192
    context 'other file types' do
      it 'raises UnmergeableFile when lines is blank, indicating a binary file' do
193 194
        expect { parse_text('') }
          .to raise_error(Gitlab::Conflict::Parser::UnmergeableFile)
195

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

200
      it 'raises UnmergeableFile when the file is over 200 KB' do
201 202
        expect { parse_text('a' * 204801) }
          .to raise_error(Gitlab::Conflict::Parser::UnmergeableFile)
203
      end
204

205 206 207 208
      # All text from Rugged has an encoding of ASCII_8BIT, so force that in
      # these strings.
      context 'when the file contains UTF-8 characters' do
        it 'does not raise' do
209 210
          expect { parse_text("Espa\xC3\xB1a".force_encoding(Encoding::ASCII_8BIT)) }
            .not_to raise_error
211 212 213 214 215
        end
      end

      context 'when the file contains non-UTF-8 characters' do
        it 'raises UnsupportedEncoding' do
216 217
          expect { parse_text("a\xC4\xFC".force_encoding(Encoding::ASCII_8BIT)) }
            .to raise_error(Gitlab::Conflict::Parser::UnsupportedEncoding)
218
        end
219
      end
220 221 222
    end
  end
end