# frozen_string_literal: true

require_relative 'rpm_test_cases'

RSpec.describe SemverDialects::Rpm::Version do
  describe '#<=>' do
    # https://github.com/knqyf263/go-rpm-version/blob/631e686d1075673d95a2eb26ebda195e9d31360b/version_test.go#L183-L281
    # Note that the tests imported from rpmvercmp.at have been excluded as they are repeated below
    context 'consistency with TestParseAndCompare of go-rpm-version' do
      GO_RPM_TEST_PARSE_AND_COMPARE_TEST_CASES.each do |a, expected, b|
        context "a=#{a}, b=#{b}" do
          subject { v1.<=>(v2) }

          let(:v1) { SemverDialects::Rpm::VersionParser.parse(a) }
          let(:v2) { SemverDialects::Rpm::VersionParser.parse(b) }

          it {
            is_expected.to eq(expected)
          }
        end
      end
    end

    # https://github.com/rpm-software-management/rpm/blob/e8a252dca9f0731dc5f24d91447a6906363ff9ec/tests/rpmvercmp.at
    context 'consistency with rpmvercpm tests of rpm' do
      RPMVERCMP_TEST_CASES.each do |a, b, expected|
        context "a=#{a}, b=#{b}" do
          subject { v1.<=>(v2) }

          let(:v1) { SemverDialects::Rpm::VersionParser.parse(a) }
          let(:v2) { SemverDialects::Rpm::VersionParser.parse(b) }

          it {
            is_expected.to eq(expected)
          }
        end
      end
    end
  end
end

RSpec.describe SemverDialects::Rpm::VersionParser do
  describe '.parse' do
    let(:version) { described_class.parse(input) }

    context 'with valid versions' do
      using RSpec::Parameterized::TableSyntax

      where(:input, :rpm_version) do
        '1.2' | SemverDialects::Rpm::Version.new([1, 2])
        '0:1.2' | SemverDialects::Rpm::Version.new([1, 2], epoch: 0)
        '0:1.2-rc1' | SemverDialects::Rpm::Version.new([1, 2], epoch: 0,
                                                               release_tag: SemverDialects::Rpm::ReleaseTag.new(['rc', 1])) # rubocop:disable Layout/LineLength
        '1.2-rc1' | SemverDialects::Rpm::Version.new([1, 2],
                                                     release_tag: SemverDialects::Rpm::ReleaseTag.new(['rc', 1]))
        '1.2-rc1-2' | SemverDialects::Rpm::Version.new([1, 2],
                                                       release_tag: SemverDialects::Rpm::ReleaseTag.new(['rc', 1, 2]))
        '1.2.3~1' | SemverDialects::Rpm::Version.new([1, 2, 3, '~', 1])
        '1.0~rc1' | SemverDialects::Rpm::Version.new([1, 0, '~', 'rc', 1])
        '1b.fc17' | SemverDialects::Rpm::Version.new([1, 'b', 'fc', 17])
        # Caret parsing not supported at the moment, remove test below once we add support for caret parsing
        '1.2^' | SemverDialects::Rpm::Version.new([1, 2])
        # Segments containing alphabets and numbers are split before comparison
        # More details in this comment https://gitlab.com/gitlab-org/gitlab/-/issues/428941#note_1882343489
        '1.1a' | SemverDialects::Rpm::Version.new([1, 1, 'a'])
        '1.1.a' | SemverDialects::Rpm::Version.new([1, 1, 'a'])
      end

      with_them do
        it 'returns a version that parses epoch, version and release accurately' do
          expect(version).to eq(rpm_version)
        end
      end
    end

    context 'with invalid versions' do
      using RSpec::Parameterized::TableSyntax

      where(:input) do
        [
          ' 1.1.a',
          '1.1.a ',
          '1.1. a',
          "\t1.1.a",
          "\n1.1.a",
          "\r\n1.1.a",
          "\f1.1.a",
          "\v1.1.a"
        ]
      end

      with_them do
        it 'raises an error' do
          expect { described_class.parse(input) }
            .to raise_error(SemverDialects::InvalidVersionError, "invalid version '#{input}'")
        end
      end
    end
  end
end
