// 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.config.SitePaths;
import com.google.gerrit.server.notedb.Sequences;
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.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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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 + Sequences.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() {
    org.apache.log4j.Logger logger = LogManager.getLogger("logWriterLogger");
    logger.addAppender(new WriterAppender(new PatternLayout("%m"), logWriter));
    return LoggerFactory.getLogger("logWriterLogger");
  }

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