// Copyright (C) 2019 The Android Open Source Project
//
// 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.gerrit.git;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.gerrit.git.ObjectIds.abbreviateName;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;

import java.util.function.Function;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevBlob;
import org.junit.Test;

public class ObjectIdsTest {
  private static final ObjectId ID =
      ObjectId.fromString("0000000000100000000000000000000000000000");
  private static final ObjectId AMBIGUOUS_BLOB_ID =
      ObjectId.fromString("0000000000b36b6aa7ea4b75318ed078f55505c3");
  private static final ObjectId AMBIGUOUS_TREE_ID =
      ObjectId.fromString("0000000000cdcf04beb2fab69e65622616294984");

  @Test
  public void abbreviateNameDefaultLength() throws Exception {
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(null);
        });
    assertThat(abbreviateName(ID)).isEqualTo("0000000");
    assertThat(abbreviateName(AMBIGUOUS_BLOB_ID)).isEqualTo(abbreviateName(ID));
    assertThat(abbreviateName(AMBIGUOUS_TREE_ID)).isEqualTo(abbreviateName(ID));
  }

  @Test
  public void abbreviateNameCustomLength() throws Exception {
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(null, 1);
        });
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(ID, -1);
        });
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(ID, 0);
        });
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(ID, 41);
        });
    assertThat(abbreviateName(ID, 5)).isEqualTo("00000");
    assertThat(abbreviateName(ID, 40)).isEqualTo(ID.name());
  }

  @Test
  public void abbreviateNameDefaultLengthWithReader() throws Exception {
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(ID, null);
        });

    ObjectReader reader = newReaderWithAmbiguousIds();
    assertThat(abbreviateName(ID, reader)).isEqualTo("00000000001");
  }

  @Test
  public void abbreviateNameCustomLengthWithReader() throws Exception {
    ObjectReader reader = newReaderWithAmbiguousIds();
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(ID, -1, reader);
        });
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(ID, 0, reader);
        });
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(ID, 41, reader);
        });
    assertRuntimeException(
        () -> {
          @SuppressWarnings("unused")
          var unused = abbreviateName(ID, 5, null);
        });

    String shortest = "00000000001";
    assertThat(abbreviateName(ID, 1, reader)).isEqualTo(shortest);
    assertThat(abbreviateName(ID, 7, reader)).isEqualTo(shortest);
    assertThat(abbreviateName(ID, shortest.length(), reader)).isEqualTo(shortest);
    assertThat(abbreviateName(ID, shortest.length() + 1, reader)).isEqualTo("000000000010");
  }

  @Test
  public void copyOrNull() throws Exception {
    testCopy(ObjectIds::copyOrNull);
    assertThat(ObjectIds.copyOrNull(null)).isNull();
  }

  @Test
  public void copyOrZero() throws Exception {
    testCopy(ObjectIds::copyOrZero);
    assertThat(ObjectIds.copyOrZero(null)).isEqualTo(ObjectId.zeroId());
  }

  private void testCopy(Function<AnyObjectId, ObjectId> copyFunc) {
    MyObjectId myId = new MyObjectId(ID);
    assertThat(myId).isEqualTo(ID);

    ObjectId copy = copyFunc.apply(myId);
    assertThat(copy).isEqualTo(myId);
    assertThat(copy).isNotSameInstanceAs(myId);
    assertThat(copy.getClass()).isEqualTo(ObjectId.class);
  }

  @Test
  public void matchesAbbreviation() throws Exception {
    assertThat(ObjectIds.matchesAbbreviation(null, "")).isFalse();
    assertThat(ObjectIds.matchesAbbreviation(null, "0")).isFalse();
    assertThat(ObjectIds.matchesAbbreviation(null, "00000")).isFalse();
    assertThat(ObjectIds.matchesAbbreviation(null, "not a SHA-1")).isFalse();
    assertThat(ObjectIds.matchesAbbreviation(null, ID.name())).isFalse();

    assertThat(ObjectIds.matchesAbbreviation(ID, "")).isTrue();
    for (int i = 1; i <= OBJECT_ID_STRING_LENGTH; i++) {
      String prefix = ID.name().substring(0, i);
      assertWithMessage("match %s against %s", ID.name(), prefix)
          .that(ObjectIds.matchesAbbreviation(ID, prefix))
          .isTrue();
    }

    assertThat(ObjectIds.matchesAbbreviation(ID, "1")).isFalse();
    assertThat(ObjectIds.matchesAbbreviation(ID, "x")).isFalse();
    assertThat(ObjectIds.matchesAbbreviation(ID, "not a SHA-1")).isFalse();
    assertThat(ObjectIds.matchesAbbreviation(ID, AMBIGUOUS_BLOB_ID.name())).isFalse();
  }

  @FunctionalInterface
  private interface Func {
    void call() throws Exception;
  }

  private static void assertRuntimeException(Func func) throws Exception {
    assertThrows(RuntimeException.class, () -> func.call());
  }

  private static ObjectReader newReaderWithAmbiguousIds() throws Exception {
    // Recipe for creating ambiguous IDs courtesy of git core:
    // https://github.com/git/git/blob/df799f5d99ac51d4fc791d546de3f936088582fc/t/t1512-rev-parse-disambiguation.sh
    try (TestRepository<Repository> tr =
        new TestRepository<>(new InMemoryRepository(new DfsRepositoryDescription("repo")))) {
      String blobData = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n\nb1rwzyc3\n";
      RevBlob blob = tr.blob(blobData);
      assertThat(blob.name()).isEqualTo(AMBIGUOUS_BLOB_ID.name());
      assertThat(tr.tree(tr.file("a0blgqsjc", blob)).name()).isEqualTo(AMBIGUOUS_TREE_ID.name());
      return tr.getRevWalk().getObjectReader();
    }
  }

  private static class MyObjectId extends ObjectId {
    private static final long serialVersionUID = 1L;

    MyObjectId(AnyObjectId src) {
      super(src);
    }
  }
}
