// Copyright (C) 2020 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.gerritforge.gerrit.globalrefdb.validation;

import static com.google.common.truth.Truth.assertThat;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.json.OutputFormat;
import com.google.gerrit.server.Sequence;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.util.SystemLog;
import com.google.gson.Gson;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.WriterAppender;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;

public class Log4jSharedRefLoggerTest extends AbstractDaemonTest {

  private static final Gson gson = OutputFormat.JSON_COMPACT.newGson();
  private StringWriter logWriter;
  private Log4jSharedRefLogger log4jSharedRefLogger;

  @Before
  public void setUp() throws IOException {
    this.logWriter = new StringWriter();
    this.log4jSharedRefLogger = newLog4jSharedRefLogger();
  }

  @Test
  public void shouldLogProjectDeletion() {
    log4jSharedRefLogger.logProjectDelete(project.get());

    SharedRefLogEntry.DeleteProject gotLogEntry =
        gson.fromJson(logWriter.toString(), SharedRefLogEntry.DeleteProject.class);

    assertThat(gotLogEntry.type).isEqualTo(SharedRefLogEntry.Type.DELETE_PROJECT);
    assertThat(gotLogEntry.projectName).isEqualTo(project.get());
  }

  @Test
  public void shouldLogUpdateRef() throws Exception {
    final String refName = "refs/remotes/origin/master";
    Ref currRef = repo().exactRef(refName);
    PushOneCommit.Result result = pushTo(refName);
    ObjectId newRefValue = result.getCommit().toObjectId();

    log4jSharedRefLogger.logRefUpdate(project.get(), currRef, newRefValue);

    SharedRefLogEntry.UpdateRef gotLogEntry =
        gson.fromJson(logWriter.toString(), SharedRefLogEntry.UpdateRef.class);

    assertThat(gotLogEntry.type).isEqualTo(SharedRefLogEntry.Type.UPDATE_REF);
    assertThat(gotLogEntry.projectName).isEqualTo(project.get());
    assertThat(gotLogEntry.refName).isEqualTo(refName);
    assertThat(gotLogEntry.oldId).isEqualTo(currRef.getObjectId().getName());
    assertThat(gotLogEntry.newId).isEqualTo(newRefValue.getName());
    assertThat(gotLogEntry.comment).isNotNull();
    assertThat(gotLogEntry.committer).isNotNull();
  }

  @Test
  public void shouldLogDeleteRef() throws Exception {
    final String refName = "refs/remotes/origin/master";
    Ref currRef = repo().exactRef(refName);

    log4jSharedRefLogger.logRefUpdate(project.get(), currRef, ObjectId.zeroId());

    SharedRefLogEntry.DeleteRef gotLogEntry =
        gson.fromJson(logWriter.toString(), SharedRefLogEntry.DeleteRef.class);

    assertThat(gotLogEntry.type).isEqualTo(SharedRefLogEntry.Type.DELETE_REF);
    assertThat(gotLogEntry.projectName).isEqualTo(project.get());
    assertThat(gotLogEntry.refName).isEqualTo(refName);
    assertThat(gotLogEntry.oldId).isEqualTo(currRef.getObjectId().getName());
  }

  @Test
  public void shouldLogBlobRefs() throws Exception {
    Repository allUsersRepo = repoManager.openRepository(allUsers);
    String blobRefName = RefNames.REFS_SEQUENCES + Sequence.NAME_ACCOUNTS;
    Ref currRef = allUsersRepo.exactRef(blobRefName);
    log4jSharedRefLogger.logRefUpdate(allUsers.get(), currRef, currRef.getObjectId());

    SharedRefLogEntry.UpdateRef gotLogEntry =
        gson.fromJson(logWriter.toString(), SharedRefLogEntry.UpdateRef.class);

    assertThat(gotLogEntry.type).isEqualTo(SharedRefLogEntry.Type.UPDATE_REF);
    assertThat(gotLogEntry.projectName).isEqualTo(allUsers.get());
    assertThat(gotLogEntry.refName).isEqualTo(blobRefName);
    assertThat(gotLogEntry.oldId).isEqualTo(currRef.getObjectId().getName());
    assertThat(gotLogEntry.newId).isEqualTo(currRef.getObjectId().getName());
    assertThat(gotLogEntry.comment).isNull();
    assertThat(gotLogEntry.committer).isNull();
  }

  @Test
  public void shouldLogLockAcquisition() {
    String refName = "refs/foo/bar";
    log4jSharedRefLogger.logLockAcquisition(project.get(), refName);

    SharedRefLogEntry.LockAcquire gotLogEntry =
        gson.fromJson(logWriter.toString(), SharedRefLogEntry.LockAcquire.class);

    assertThat(gotLogEntry.type).isEqualTo(SharedRefLogEntry.Type.LOCK_ACQUIRE);
    assertThat(gotLogEntry.projectName).isEqualTo(project.get());
    assertThat(gotLogEntry.refName).isEqualTo(refName);
  }

  @Test
  public void shouldLogLockRelease() {
    String refName = "refs/foo/bar";
    log4jSharedRefLogger.logLockRelease(project.get(), refName);

    SharedRefLogEntry.LockAcquire gotLogEntry =
        gson.fromJson(logWriter.toString(), SharedRefLogEntry.LockAcquire.class);

    assertThat(gotLogEntry.type).isEqualTo(SharedRefLogEntry.Type.LOCK_RELEASE);
    assertThat(gotLogEntry.projectName).isEqualTo(project.get());
    assertThat(gotLogEntry.refName).isEqualTo(refName);
  }

  private Log4jSharedRefLogger newLog4jSharedRefLogger() throws IOException {
    final Log4jSharedRefLogger log4jSharedRefLogger =
        new Log4jSharedRefLogger(new SystemLog(new SitePaths(newPath()), baseConfig), repoManager);
    log4jSharedRefLogger.setLogger(logWriterLogger());
    return log4jSharedRefLogger;
  }

  private Logger logWriterLogger() {
    Logger logger = LogManager.getLogger("logWriterLogger");
    logger.addAppender(new WriterAppender(new PatternLayout("%m"), logWriter));
    return logger;
  }

  private static Path newPath() throws IOException {
    Path tmp = Files.createTempFile("gerrit_test_", "_site");
    Files.deleteIfExists(tmp);
    return tmp;
  }
}
