// 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(() -> 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(() -> abbreviateName(null, 1));
    assertRuntimeException(() -> abbreviateName(ID, -1));
    assertRuntimeException(() -> abbreviateName(ID, 0));
    assertRuntimeException(() -> abbreviateName(ID, 41));
    assertThat(abbreviateName(ID, 5)).isEqualTo("00000");
    assertThat(abbreviateName(ID, 40)).isEqualTo(ID.name());
  }

  @Test
  public void abbreviateNameDefaultLengthWithReader() throws Exception {
    assertRuntimeException(() -> abbreviateName(ID, null));

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

  @Test
  public void abbreviateNameCustomLengthWithReader() throws Exception {
    ObjectReader reader = newReaderWithAmbiguousIds();
    assertRuntimeException(() -> abbreviateName(ID, -1, reader));
    assertRuntimeException(() -> abbreviateName(ID, 0, reader));
    assertRuntimeException(() -> abbreviateName(ID, 41, reader));
    assertRuntimeException(() -> 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);
    }
  }
}
