BigW Consortium Gitlab

parser_spec.rb 7.45 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

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

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

        it 'does not raise when there is an end delimiter for a different path first' do
          expect { parse_text('>>>>>>> some-other-path.md') }.
            not_to raise_error
        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 145 146 147
        it 'raises UnexpectedDelimiter when it is followed by an end delimiter' do
          expect { parse_text(start_text + '>>>>>>> README.md' + end_text) }.
            to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
        end
148

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

154 155 156 157
        it 'does not raise when it is followed by a start delimiter for a different path' do
          expect { parse_text(start_text + '>>>>>>> some-other-path.md' + end_text) }.
            not_to raise_error
        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 165 166 167
        it 'raises UnexpectedDelimiter when it is followed by another middle delimiter' do
          expect { parse_text(start_text + '=======' + end_text) }.
            to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter)
        end
168

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

174 175 176 177
        it 'does not raise when it is followed by a start delimiter for another path' do
          expect { parse_text(start_text + '<<<<<<< some-other-path.md' + end_text) }.
            not_to raise_error
        end
178 179 180 181 182 183 184 185 186 187 188 189 190
      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

191 192 193 194 195 196 197 198 199
    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

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

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

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