// Copyright (C) 2018 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.server.notedb;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.truth.OptionalSubject.assertThat;

import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.git.LockFailureException;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import java.io.IOException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
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.ObjectId;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;

public class IntBlobTest {
  // Note: Can't easily test GitRefUpdated behavior, since binding GitRefUpdated requires a thick
  // stack of dependencies, and it's not just a simple interface or abstract class.

  private Project.NameKey projectName;
  private InMemoryRepository repo;
  private TestRepository<InMemoryRepository> tr;
  private RevWalk rw;

  @Before
  public void setUp() throws Exception {
    projectName = Project.nameKey("repo");
    repo = new InMemoryRepository(new DfsRepositoryDescription(projectName.get()));
    tr = new TestRepository<>(repo);
    rw = tr.getRevWalk();
  }

  @Test
  public void parseNoRef() throws Exception {
    assertThat(IntBlob.parse(repo, "refs/nothing")).isEmpty();
  }

  @Test
  public void parseNonBlob() throws Exception {
    String refName = "refs/foo/master";
    tr.branch(refName).commit().create();
    assertThrows(IncorrectObjectTypeException.class, () -> IntBlob.parse(repo, refName));
  }

  @Test
  public void parseValid() throws Exception {
    String refName = "refs/foo";
    ObjectId id = tr.update(refName, tr.blob("123"));
    assertThat(IntBlob.parse(repo, refName)).value().isEqualTo(IntBlob.create(id, 123));
  }

  @Test
  public void parseWithWhitespace() throws Exception {
    String refName = "refs/foo";
    ObjectId id = tr.update(refName, tr.blob(" 123 "));
    assertThat(IntBlob.parse(repo, refName)).value().isEqualTo(IntBlob.create(id, 123));
  }

  @Test
  public void parseInvalid() throws Exception {
    String refName = "refs/foo";
    ObjectId id = tr.update(refName, tr.blob("1 2 3"));
    StorageException thrown =
        assertThrows(StorageException.class, () -> IntBlob.parse(repo, refName));
    assertThat(thrown).hasMessageThat().isEqualTo("invalid value in refs/foo blob at " + id.name());
  }

  @Test
  public void tryStoreNoOldId() throws Exception {
    String refName = "refs/foo";
    RefUpdate ru =
        IntBlob.tryStore(repo, rw, projectName, refName, null, 123, GitReferenceUpdated.DISABLED);
    assertThat(ru.getResult()).isEqualTo(RefUpdate.Result.NEW);
    assertThat(ru.getName()).isEqualTo(refName);
    assertThat(IntBlob.parse(repo, refName))
        .value()
        .isEqualTo(IntBlob.create(ru.getNewObjectId(), 123));
  }

  @Test
  public void tryStoreOldIdZero() throws Exception {
    String refName = "refs/foo";
    RefUpdate ru =
        IntBlob.tryStore(
            repo, rw, projectName, refName, ObjectId.zeroId(), 123, GitReferenceUpdated.DISABLED);
    assertThat(ru.getResult()).isEqualTo(RefUpdate.Result.NEW);
    assertThat(ru.getName()).isEqualTo(refName);
    assertThat(IntBlob.parse(repo, refName))
        .value()
        .isEqualTo(IntBlob.create(ru.getNewObjectId(), 123));
  }

  @Test
  public void tryStoreCorrectOldId() throws Exception {
    String refName = "refs/foo";
    ObjectId id = tr.update(refName, tr.blob("123"));
    RefUpdate ru =
        IntBlob.tryStore(repo, rw, projectName, refName, id, 456, GitReferenceUpdated.DISABLED);
    assertThat(ru.getResult()).isEqualTo(RefUpdate.Result.FORCED);
    assertThat(ru.getName()).isEqualTo(refName);
    assertThat(IntBlob.parse(repo, refName))
        .value()
        .isEqualTo(IntBlob.create(ru.getNewObjectId(), 456));
  }

  @Test
  public void tryStoreWrongOldId() throws Exception {
    String refName = "refs/foo";
    RefUpdate ru =
        IntBlob.tryStore(
            repo,
            rw,
            projectName,
            refName,
            ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
            123,
            GitReferenceUpdated.DISABLED);
    assertThat(ru.getResult()).isEqualTo(RefUpdate.Result.LOCK_FAILURE);
    assertThat(ru.getName()).isEqualTo(refName);
    assertThat(IntBlob.parse(repo, refName)).isEmpty();
  }

  @Test
  public void storeNoOldId() throws Exception {
    String refName = "refs/foo";
    IntBlob.store(repo, rw, projectName, refName, null, 123, GitReferenceUpdated.DISABLED);
    assertThat(IntBlob.parse(repo, refName))
        .value()
        .isEqualTo(IntBlob.create(getRef(refName), 123));
  }

  @Test
  public void storeOldIdZero() throws Exception {
    String refName = "refs/foo";
    IntBlob.store(
        repo, rw, projectName, refName, ObjectId.zeroId(), 123, GitReferenceUpdated.DISABLED);
    assertThat(IntBlob.parse(repo, refName))
        .value()
        .isEqualTo(IntBlob.create(getRef(refName), 123));
  }

  @Test
  public void storeCorrectOldId() throws Exception {
    String refName = "refs/foo";
    ObjectId id = tr.update(refName, tr.blob("123"));
    IntBlob.store(repo, rw, projectName, refName, id, 456, GitReferenceUpdated.DISABLED);
    assertThat(IntBlob.parse(repo, refName))
        .value()
        .isEqualTo(IntBlob.create(getRef(refName), 456));
  }

  @Test
  public void storeWrongOldId() throws Exception {
    String refName = "refs/foo";
    LockFailureException thrown =
        assertThrows(
            LockFailureException.class,
            () ->
                IntBlob.store(
                    repo,
                    rw,
                    projectName,
                    refName,
                    ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
                    123,
                    GitReferenceUpdated.DISABLED));
    assertThat(thrown.getFailedRefs()).containsExactly("refs/foo");
    assertThat(IntBlob.parse(repo, refName)).isEmpty();
  }

  private ObjectId getRef(String refName) throws IOException {
    return repo.exactRef(refName).getObjectId();
  }
}
