// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.rules.apple;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;

import com.google.common.testing.EqualsTester;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link DottedVersion}.
 */
@RunWith(JUnit4.class)
public class DottedVersionTest {

  @Test
  public void testCompareTo() throws Exception {
    new ComparatorTester()
        .addEqualityGroup(DottedVersion.fromString("0"), DottedVersion.fromString("0.0.0"))
        .addEqualityGroup(DottedVersion.fromString("0.1"), DottedVersion.fromString("0.01"))
        .addEqualityGroup(DottedVersion.fromString("0.2"), DottedVersion.fromString("0.2.0"))
        .addEqualityGroup(DottedVersion.fromString("0.2.1"))
        .addEqualityGroup(DottedVersion.fromString("1.2alpha"))
        .addEqualityGroup(DottedVersion.fromString("1.2alpha1"))
        .addEqualityGroup(DottedVersion.fromString("1.2alpha2"))
        .addEqualityGroup(DottedVersion.fromString("1.2beta1"))
        .addEqualityGroup(DottedVersion.fromString("1.2beta12"))
        .addEqualityGroup(DottedVersion.fromString("1.2beta12.1"))
        .addEqualityGroup(DottedVersion.fromString("1.2.0"), DottedVersion.fromString("1.2"))
        .addEqualityGroup(DottedVersion.fromString("1.20"))
        .addEqualityGroup(DottedVersion.fromString("10"), DottedVersion.fromString("10.0"))
        .addEqualityGroup(DottedVersion.fromString("10.0.0.10A255"))
        .addEqualityGroup(DottedVersion.fromString("10.2"))
        .addEqualityGroup(DottedVersion.fromString("10.2.0.10P99q"))
        .testCompare();
  }

  @Test
  public void testEquals() throws Exception {
    new EqualsTester()
        .addEqualityGroup(DottedVersion.fromString("0"), DottedVersion.fromString("0.0.0"))
        .addEqualityGroup(DottedVersion.fromString("0.1"), DottedVersion.fromString("0.01"))
        .addEqualityGroup(DottedVersion.fromString("0.2"), DottedVersion.fromString("0.2.0"))
        .addEqualityGroup(DottedVersion.fromString("1.2xy2"), DottedVersion.fromString("1.2xy2"))
        .addEqualityGroup(
            DottedVersion.fromString("10.2.0.10P99q"), DottedVersion.fromString("10.2.0.10P99q0"))
        .addEqualityGroup(
            DottedVersion.fromString("1.2x"),
            DottedVersion.fromString("1.2x0"),
            DottedVersion.fromString("1.2x0.0"))
        .testEquals();
  }

  @Test
  public void testToStringWithComponents() throws Exception {
    DottedVersion dottedVersion = DottedVersion.fromString("42.8");
    assertThat(dottedVersion.toStringWithComponents(1)).isEqualTo("42");
    assertThat(dottedVersion.toStringWithComponents(2)).isEqualTo("42.8");
    assertThat(dottedVersion.toStringWithComponents(3)).isEqualTo("42.8.0");
    assertThat(dottedVersion.toStringWithComponents(4)).isEqualTo("42.8.0.0");
  }

  @Test
  public void testToStringWithComponents_trailingZero() throws Exception {
    DottedVersion dottedVersion = DottedVersion.fromString("4.3alpha3.0");
    assertThat(dottedVersion.toStringWithComponents(1)).isEqualTo("4");
    assertThat(dottedVersion.toStringWithComponents(2)).isEqualTo("4.3alpha3");
    assertThat(dottedVersion.toStringWithComponents(3)).isEqualTo("4.3alpha3.0");
    assertThat(dottedVersion.toStringWithComponents(4)).isEqualTo("4.3alpha3.0.0");
    assertThat(dottedVersion.toStringWithComponents(5)).isEqualTo("4.3alpha3.0.0.0");
  }

  @Test
  public void testToStringWithComponents_zeroComponent() throws Exception {
    DottedVersion zeroComponent = DottedVersion.fromString("0");
    assertThat(zeroComponent.toStringWithComponents(1)).isEqualTo("0");
    assertThat(zeroComponent.toStringWithComponents(2)).isEqualTo("0.0");
    assertThat(zeroComponent.toStringWithComponents(3)).isEqualTo("0.0.0");
  }

  @Test
  public void testToStringWithMinimumComponent() throws Exception {
    DottedVersion dottedVersion = DottedVersion.fromString("42.8");
    assertThat(dottedVersion.toStringWithMinimumComponents(0)).isEqualTo("42.8");
    assertThat(dottedVersion.toStringWithMinimumComponents(1)).isEqualTo("42.8");
    assertThat(dottedVersion.toStringWithMinimumComponents(2)).isEqualTo("42.8");
    assertThat(dottedVersion.toStringWithMinimumComponents(3)).isEqualTo("42.8.0");
    assertThat(dottedVersion.toStringWithMinimumComponents(4)).isEqualTo("42.8.0.0");
  }

  @Test
  public void testToStringWithMinimumComponent_trailingZero() throws Exception {
    DottedVersion dottedVersion = DottedVersion.fromString("4.3alpha3.0");
    assertThat(dottedVersion.toStringWithMinimumComponents(0)).isEqualTo("4.3alpha3.0");
    assertThat(dottedVersion.toStringWithMinimumComponents(1)).isEqualTo("4.3alpha3.0");
    assertThat(dottedVersion.toStringWithMinimumComponents(2)).isEqualTo("4.3alpha3.0");
    assertThat(dottedVersion.toStringWithMinimumComponents(3)).isEqualTo("4.3alpha3.0");
    assertThat(dottedVersion.toStringWithMinimumComponents(4)).isEqualTo("4.3alpha3.0.0");
    assertThat(dottedVersion.toStringWithMinimumComponents(5)).isEqualTo("4.3alpha3.0.0.0");
  }

  @Test
  public void testToStringWithMinimumComponents_zeroComponent() throws Exception {
    DottedVersion zeroComponent = DottedVersion.fromString("0");
    assertThat(zeroComponent.toStringWithMinimumComponents(0)).isEqualTo("0");
    assertThat(zeroComponent.toStringWithMinimumComponents(1)).isEqualTo("0");
    assertThat(zeroComponent.toStringWithMinimumComponents(2)).isEqualTo("0.0");
    assertThat(zeroComponent.toStringWithMinimumComponents(3)).isEqualTo("0.0.0");
  }

  @Test
  public void testIllegalVersion_noLeadingInteger() throws Exception {
    Throwable expected =
        assertThrows(
            DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString("a"));
    assertThat(expected).hasMessageThat().contains("a");
  }

  @Test
  public void testIllegalVersion_empty() throws Exception {
    assertThrows(
        DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString(""));
  }

  @Test
  public void testIllegalVersion_punctuation() throws Exception {
    assertThrows(
        DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString("2:3"));
  }

  @Test
  public void testIllegalVersion_emptyComponent() throws Exception {
    assertThrows(
        DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString("1..3"));
  }

  @Test
  public void testIllegalVersion_negativeComponent() throws Exception {
    assertThrows(
        DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString("1.-1"));
  }
}
