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

3
describe Gitlab::Git::Conflict::Parser do
4
  describe '.parse' do
5
    def parse_text(text)
6
      described_class.parse(text, our_path: 'README.md', their_path: 'README.md')
7 8
    end

9 10 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
    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

87
      let(:lines) do
88 89 90 91
        described_class.parse(text, our_path: 'files/ruby/regex.rb', their_path: 'files/ruby/regex.rb')
      end
      let(:old_line_numbers) do
        lines.select { |line| line[:type] != 'new' }.map { |line| line[:line_old] }
92
      end
93 94 95 96
      let(:new_line_numbers) do
        lines.select { |line| line[:type] != 'old' }.map { |line| line[:line_new] }
      end
      let(:line_indexes) { lines.map { |line| line[:line_obj_index] } }
97 98

      it 'sets our lines as new lines' do
99 100 101
        expect(lines[8..13]).to all(include(type: 'new'))
        expect(lines[26..27]).to all(include(type: 'new'))
        expect(lines[56..57]).to all(include(type: 'new'))
102 103 104
      end

      it 'sets their lines as old lines' do
105 106 107
        expect(lines[14..19]).to all(include(type: 'old'))
        expect(lines[28..29]).to all(include(type: 'old'))
        expect(lines[58..59]).to all(include(type: 'old'))
108 109 110
      end

      it 'sets non-conflicted lines as both' do
111 112 113 114
        expect(lines[0..7]).to all(include(type: nil))
        expect(lines[20..25]).to all(include(type: nil))
        expect(lines[30..55]).to all(include(type: nil))
        expect(lines[60..62]).to all(include(type: nil))
115 116
      end

117 118
      it 'sets consecutive line numbers for line_obj_index, line_old, and line_new' do
        expect(line_indexes).to eq(0.upto(62).to_a)
119 120 121 122 123 124
        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
125 126
      context 'when there is a non-start delimiter first' do
        it 'raises UnexpectedDelimiter when there is a middle delimiter first' do
127
          expect { parse_text('=======') }
128
            .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter)
129 130 131
        end

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

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

142 143 144
      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" }
145

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

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

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

162 163 164
      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" }
165

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

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

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

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

185
        expect { parse_text(start_text) }
186
          .to raise_error(Gitlab::Git::Conflict::Parser::MissingEndDelimiter)
187

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

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

198
        expect { parse_text(nil) }
199
          .to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile)
200 201
      end

S
Sean McGivern 已提交
202
      it 'raises UnmergeableFile when the file is over 200 KB' do
203
        expect { parse_text('a' * 204801) }
204
          .to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile)
205
      end
206

207 208 209 210
      # 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
211 212
          expect { parse_text("Espa\xC3\xB1a".force_encoding(Encoding::ASCII_8BIT)) }
            .not_to raise_error
213 214 215 216 217
        end
      end

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