// Copyright (C) 2017 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.googlesource.gerrit.plugins.findowners;

import static com.google.common.truth.Truth.assertThat;
import static com.googlesource.gerrit.plugins.findowners.Config.OWNERS;
import static com.googlesource.gerrit.plugins.findowners.Config.OWNERS_FILE_NAME;
import static com.googlesource.gerrit.plugins.findowners.Config.REJECT_ERROR_IN_OWNERS;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Lists;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.Emails;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Test OwnersValidator, which checks syntax of changed OWNERS files. */
@RunWith(JUnit4.class)
public class OwnersValidatorTest {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
  @Rule public Watcher watcher = new Watcher(logger);

  private static class MockedEmails extends Emails {
    Set<String> registered;

    MockedEmails() {
      super(null, null, null);
      registered =
          ImmutableSet.of(
              "u1@g.com", "u2@g.com", "u2.m@g.com", "user1@google.com", "u1+review@g.com");
    }

    @Override
    public ImmutableSetMultimap<String, Account.Id> getAccountsFor(String... emails) {
      // Used by checkEmails; each email should have exactly one Account.Id
      ImmutableSetMultimap.Builder<String, Account.Id> builder = ImmutableSetMultimap.builder();
      int id = 1000000;
      for (String s : registered) {
        builder.put(s, new Account.Id(++id));
      }
      return builder.build();
    }
  }

  private File repoFolder;
  private Repository repo;

  @Before
  public void init() throws IOException {
    repoFolder = File.createTempFile("Git", "");
    repoFolder.delete();
    repo = FileRepositoryBuilder.create(new File(repoFolder, ".git"));
    repo.create();
  }

  @After
  public void cleanup() throws IOException {
    repo.close();
    if (repoFolder.exists()) {
      FileUtils.deleteDirectory(repoFolder);
    }
  }

  private static final String OWNERS_ANDROID = "OWNERS.android"; // alternative OWNERS file name
  private static final PluginConfig ANDROID_CONFIG = createAndroidConfig(); // use OWNERS_ANDROID
  private static final PluginConfig EMPTY_CONFIG = new PluginConfig("", new Config());
  private static final PluginConfig ENABLED_CONFIG = createEnabledConfig(); // use OWNERS
  private static final PluginConfig DISABLED_CONFIG = createDisabledConfig();

  @Test
  public void chekIsActiveAndFileName() throws Exception {
    // This check should be enabled in project.config, default is not active.
    assertThat(OwnersValidator.isActive(EMPTY_CONFIG)).isFalse();
    assertThat(OwnersValidator.isActive(ENABLED_CONFIG)).isTrue();
    assertThat(OwnersValidator.isActive(ANDROID_CONFIG)).isTrue();
    assertThat(OwnersValidator.isActive(DISABLED_CONFIG)).isFalse();
    // Default file name is "OWNERS".
    assertThat(OwnersValidator.getOwnersFileName(EMPTY_CONFIG)).isEqualTo(OWNERS);
    assertThat(OwnersValidator.getOwnersFileName(ENABLED_CONFIG)).isEqualTo(OWNERS);
    assertThat(OwnersValidator.getOwnersFileName(DISABLED_CONFIG)).isEqualTo(OWNERS);
    assertThat(OwnersValidator.getOwnersFileName(ANDROID_CONFIG)).isEqualTo(OWNERS_ANDROID);
  }

  private static final ImmutableMap<String, String> FILES_WITHOUT_OWNERS =
      ImmutableMap.of("README", "any\n", "d1/test.c", "int x;\n");

  @Test
  public void testNoOwners() throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      RevCommit c = makeCommit(rw, "Commit no OWNERS.", FILES_WITHOUT_OWNERS);
      assertThat(validate(rw, c, false, ENABLED_CONFIG)).isEmpty();
      assertThat(validate(rw, c, true, ENABLED_CONFIG)).isEmpty();
    }
  }

  private static final String[] INCLUDE_STMTS = new String[]{
      "  include  p1/p2 : /d1/owners",
      "include  p1/p2://d1/owners #comment",
      "include ../d2/owners",
      " per-file *.java = file:  //d2/OWNERS.java #",
      "per-file *.cpp,*cc=file:p1/p2:/c++owners",
      "  file:   p1/p2 : /d1/owners ",
      "file:  p1/p2://d1/owners #comment",
      "file: ../d2/owners",
      "file: //OWNERS",
      "file:///OWNERS.android"};

  private static String allIncludeStatements() {
    String statement = "";
    for (String s: INCLUDE_STMTS) {
      statement += s + "\n";
    }
    return statement;
  };

  private static Set<String> allIncludeMsgs() {
    Set<String> msgs = new HashSet<>();
    for (int i = 0; i < INCLUDE_STMTS.length; i++) {
      msgs.add("MSG: unchecked: OWNERS:" + (i + 1)
          + ": " + Parser.getIncludeOrFile(INCLUDE_STMTS[i]));
    }
    return msgs;
  };

  private static final ImmutableMap<String, String> FILES_WITH_NO_ERROR =
      ImmutableMap.of(
          OWNERS,
          allIncludeStatements()
              + "\n\n#comments ...\n  ###  more comments\n"
              + "   user1@google.com # comment\n"
              + "u1+review@g.com###\n"
              + " * # everyone can approve\n"
              + "per-file   *.py=u2.m@g.com   \n"
              + "per-file *.c, *.java ,A*bp = u1@g.com, u1+review@g.com  ,u2.m@g.com#comment\n"
              + "  per-file *.txt = * # everyone can approve #  \n"
              + "per-file *.java = set noparent #  \n"
              + "  set   noparent  # comment#\n");

  private static Set<String> allVerboseMsgs() {
    Set<String> msgs = allIncludeMsgs();
    msgs.add("MSG: validate: " + OWNERS);
    msgs.add("MSG: owner: u1+review@g.com");
    msgs.add("MSG: owner: u1@g.com");
    msgs.add("MSG: owner: u2.m@g.com");
    msgs.add("MSG: owner: user1@google.com");
    return msgs;
  };

  private static final ImmutableSet<String> EXPECTED_VERBOSE_OUTPUT =
      ImmutableSet.copyOf(allVerboseMsgs());
  private static final ImmutableSet<String> EXPECTED_NON_VERBOSE_OUTPUT =
      ImmutableSet.copyOf(allIncludeMsgs());

  @Test
  public void testGoodInput() throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      RevCommit c = makeCommit(rw, "Commit good files", FILES_WITH_NO_ERROR);
      assertThat(validate(rw, c, false, ENABLED_CONFIG))
          .containsExactlyElementsIn(EXPECTED_NON_VERBOSE_OUTPUT);
      assertThat(validate(rw, c, true, ENABLED_CONFIG))
          .containsExactlyElementsIn(EXPECTED_VERBOSE_OUTPUT);
    }
  }

  private static final ImmutableMap<String, String> FILES_WITH_WRONG_SYNTAX =
      ImmutableMap.of(
          "README",
          "# some content\nu2@g.com\n",
          OWNERS,
          "\n\n\nwrong syntax\n#comment\nuser1@google.com\n",
          "d2/" + OWNERS,
          "u1@g.com\n\nu3@g.com\n*\n");


  private static final ImmutableSet<String> EXPECTED_WRONG_SYNTAX =
      ImmutableSet.of(
          "ERROR: syntax: " + OWNERS + ":4: wrong syntax",
          "ERROR: unknown: u3@g.com at d2/" + OWNERS + ":3");

  private static final ImmutableSet<String> EXPECTED_VERBOSE_WRONG_SYNTAX =
      ImmutableSet.of(
          "MSG: validate: d2/" + OWNERS,
          "MSG: validate: " + OWNERS,
          "MSG: owner: user1@google.com",
          "MSG: owner: u1@g.com",
          "MSG: owner: u3@g.com",
          "ERROR: syntax: " + OWNERS + ":4: wrong syntax",
          "ERROR: unknown: u3@g.com at d2/" + OWNERS + ":3");

  @Test
  public void testWrongSyntax() throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      RevCommit c = makeCommit(rw, "Commit wrong syntax", FILES_WITH_WRONG_SYNTAX);
      assertThat(validate(rw, c, false, ENABLED_CONFIG))
          .containsExactlyElementsIn(EXPECTED_WRONG_SYNTAX);
      assertThat(validate(rw, c, true, ENABLED_CONFIG))
          .containsExactlyElementsIn(EXPECTED_VERBOSE_WRONG_SYNTAX);
    }
  }

  private static final ImmutableMap<String, String> FILES_WITH_WRONG_EMAILS =
      ImmutableMap.of("d1/" + OWNERS, "u1@g.com\n", "d2/" + OWNERS_ANDROID, "u2@g.com\n");

  private static final ImmutableSet<String> EXPECTED_VERBOSE_DEFAULT =
      ImmutableSet.of("MSG: validate: d1/" + OWNERS, "MSG: owner: u1@g.com");

  private static final ImmutableSet<String> EXPECTED_VERBOSE_ANDROID =
      ImmutableSet.of("MSG: validate: d2/" + OWNERS_ANDROID, "MSG: owner: u2@g.com");

  @Test
  public void checkWrongEmails() throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      RevCommit c = makeCommit(rw, "Commit Default", FILES_WITH_WRONG_EMAILS);
      assertThat(validate(rw, c, true, ENABLED_CONFIG))
          .containsExactlyElementsIn(EXPECTED_VERBOSE_DEFAULT);
    }
  }

  @Test
  public void checkAndroidOwners() throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      RevCommit c = makeCommit(rw, "Commit Android", FILES_WITH_WRONG_EMAILS);
      assertThat(validate(rw, c, true, ANDROID_CONFIG))
          .containsExactlyElementsIn(EXPECTED_VERBOSE_ANDROID);
    }
  }

  private static PluginConfig createEnabledConfig() {
    PluginConfig c = new PluginConfig("", new Config());
    c.setBoolean(REJECT_ERROR_IN_OWNERS, true);
    return c;
  }

  private static PluginConfig createDisabledConfig() {
    PluginConfig c = new PluginConfig("", new Config());
    c.setBoolean(REJECT_ERROR_IN_OWNERS, false);
    return c;
  }

  private static PluginConfig createAndroidConfig() {
    PluginConfig c = createEnabledConfig();
    c.setString(OWNERS_FILE_NAME, OWNERS_ANDROID);
    return c;
  }

  private RevCommit makeCommit(RevWalk rw, String message, Map<String, String> fileStrings)
      throws IOException, GitAPIException {
    Map<File, byte[]> fileBytes = new HashMap<>();
    for (String path : fileStrings.keySet()) {
      fileBytes.put(
          new File(repo.getDirectory().getParent(), path),
          fileStrings.get(path).getBytes(StandardCharsets.UTF_8));
    }
    return makeCommit(rw, repo, message, fileBytes);
  }

  private static RevCommit makeCommit(
      RevWalk rw, Repository repo, String message, Map<File, byte[]> files)
      throws IOException, GitAPIException {
    try (Git git = new Git(repo)) {
      if (files != null) {
        addFiles(git, files);
      }
      return rw.parseCommit(git.commit().setMessage(message).call());
    }
  }

  private List<String> validate(RevWalk rw, RevCommit c, boolean verbose, PluginConfig cfg)
      throws Exception {
    MockedEmails myEmails = new MockedEmails();
    OwnersValidator validator = new OwnersValidator(null, null, myEmails);
    String ownersFileName = OwnersValidator.getOwnersFileName(cfg);
    List<CommitValidationMessage> m = validator.performValidation(c, rw, ownersFileName, verbose);
    return transformMessages(m);
  }

  private static String generateFilePattern(File f, Git git) {
    return f.getAbsolutePath()
        .replace(git.getRepository().getWorkTree().getAbsolutePath(), "")
        .substring(1);
  }

  private static void addFiles(Git git, Map<File, byte[]> files)
      throws IOException, GitAPIException {
    AddCommand ac = git.add();
    for (File f : files.keySet()) {
      if (!f.exists()) {
        FileUtils.touch(f);
      }
      if (files.get(f) != null) {
        FileUtils.writeByteArrayToFile(f, files.get(f));
      }
      ac = ac.addFilepattern(generateFilePattern(f, git));
    }
    ac.call();
  }

  private static List<String> transformMessages(List<CommitValidationMessage> messages) {
    return Lists.transform(
        messages,
        new Function<CommitValidationMessage, String>() {
          @Override
          public String apply(CommitValidationMessage input) {
            String pre = input.isError() ? "ERROR: " : "MSG: ";
            return pre + input.getMessage();
          }
        });
  }

  @Test
  public void testTransformer() {
    List<CommitValidationMessage> messages = new ArrayList<>();
    messages.add(new CommitValidationMessage("a message", false));
    messages.add(new CommitValidationMessage("an error", true));
    Set<String> expected = ImmutableSet.of("ERROR: an error", "MSG: a message");
    assertThat(transformMessages(messages)).containsExactlyElementsIn(expected);
  }
}
