// 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 com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.git.LockFailureException;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.truth.OptionalSubject;
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 {
    OptionalSubject.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"));
    OptionalSubject.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 "));
    OptionalSubject.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);
    OptionalSubject.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);
    OptionalSubject.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);
    OptionalSubject.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);
    OptionalSubject.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);
    OptionalSubject.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);
    OptionalSubject.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);
    OptionalSubject.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");
    OptionalSubject.assertThat(IntBlob.parse(repo, refName)).isEmpty();
  }

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