// 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.acceptance.LightweightPluginDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.extensions.api.changes.SubmitInput;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.account.Emails;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.inject.Inject;
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.rules.TestWatcher;
import org.junit.runner.Description;

/** Test OwnersValidator, which checks syntax of changed OWNERS files. */
@TestPlugin(name = "find-owners", sysModule = "com.googlesource.gerrit.plugins.findowners.Module")
public class OwnersValidatorIT extends LightweightPluginDaemonTest {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
  @Rule public Watcher watcher = new Watcher(logger);

  @Inject private ProjectOperations projectOperations;

  protected Project.NameKey newProject(String name) {
    return projectOperations.newProject().parent(new Project.NameKey("All-Projects")).
        name(name).create();
  }

  private void switchProject(Project.NameKey p) throws Exception {
    project = p;
    testRepo = cloneProject(project);
  }

  private void addProjectFile(
      String project, String file, String content) throws Exception {
    switchProject(newProject(project));
    PushOneCommit.Result c = createChange("c", file, content);
    approve(c.getChangeId());
    gApi.changes().id(c.getChangeId()).current().submit(new SubmitInput());
  }

  private static class MockedCommitReceivedEvent extends CommitReceivedEvent {
    MockedCommitReceivedEvent(String project, RevWalk revWalk, RevCommit commit) {
      this.project = new Project(new Project.NameKey(project));
      this.revWalk = revWalk;
      this.commit = commit;
      this.refName = "master";
    }
  }

  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 {
    CommitReceivedEvent event = makeCommitEvent("myTest", "no OWNERS.", FILES_WITHOUT_OWNERS);
    assertThat(validate(event, false, ENABLED_CONFIG)).isEmpty();
    assertThat(validate(event, true, ENABLED_CONFIG)).isEmpty();
  }

  private static final String[] INCLUDE_STMTS = new String[]{
      "  include  p1/p2 : /d1/owners",
      "include  p2/p1://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 ",  // repeated
      "file:  p3/p2://d1/owners #comment",
      "file: ../d2/owners",  // repeated
      "file: //OWNERS",  // recursive inclusion
      "file:///OWNERS.android"};

  private static final ImmutableSet<String> SKIP_INCLUDE_STMTS =
      ImmutableSet.of("  file:   p1/p2 : /d1/owners ", "file: ../d2/owners", "file: //OWNERS");

  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++) {
      if (!SKIP_INCLUDE_STMTS.contains(INCLUDE_STMTS[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: checking " + 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");
    String[] missing = new String[]{
        "p1/p2:OWNERS.android",
        "p1/p2:c++owners",
        "p1/p2:d1/owners",
        "p1/p2:d2/OWNERS.java",
        "p1/p2:d2/owners",
        "p2/p1:d1/owners",
        "p3/p2:d1/owners",
    };
    for (String s : missing) {
      msgs.add("MSG: cannot find file: " + s);
      msgs.add("MSG: check repo file " + s);
    }
    String[] skips = new String[]{
        "p1/p2:OWNERS",
        "p1/p2:d1/owners",
        "p1/p2:d2/owners",
    };
    for (String s : skips) {
      msgs.add("MSG: skip repeated include of " + s);
    }
    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 {
    CommitReceivedEvent event = makeCommitEvent("p1/p2", "good files", FILES_WITH_NO_ERROR);
    assertThat(validate(event, false, ENABLED_CONFIG))
        .containsExactlyElementsIn(EXPECTED_NON_VERBOSE_OUTPUT);
    assertThat(validate(event, 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: checking d2/" + OWNERS,
          "MSG: checking " + 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 {
    CommitReceivedEvent event = makeCommitEvent("p1/p2", "wrong syntax", FILES_WITH_WRONG_SYNTAX);
    assertThat(validate(event, false, ENABLED_CONFIG))
        .containsExactlyElementsIn(EXPECTED_WRONG_SYNTAX);
    assertThat(validate(event, 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: checking d1/" + OWNERS, "MSG: owner: u1@g.com");

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

  @Test
  public void checkWrongEmails() throws Exception {
    CommitReceivedEvent event = makeCommitEvent("test", "default", FILES_WITH_WRONG_EMAILS);
    assertThat(validate(event, true, ENABLED_CONFIG))
        .containsExactlyElementsIn(EXPECTED_VERBOSE_DEFAULT);
  }

  @Test
  public void checkAndroidOwners() throws Exception {
    CommitReceivedEvent event = makeCommitEvent("test", "Android", FILES_WITH_WRONG_EMAILS);
    assertThat(validate(event, true, ANDROID_CONFIG))
        .containsExactlyElementsIn(EXPECTED_VERBOSE_ANDROID);
  }

  @Test
  public void simpleIncludeTest() throws Exception {
    addProjectFile("p1", "d2/owners", "wrong\nxyz\n");
    addProjectFile("p2", "d2/owners", "x@g.com\nerr\ninclude ../d2/owners\n");
    ImmutableMap<String, String> files =
        ImmutableMap.of(
            "d1/" + OWNERS, "include ../d2/owners\ninclude /d2/owners\n"
            + "include p1:/d2/owners\ninclude p2:/d2/owners\n");
    ImmutableSet<String> expected = ImmutableSet.of(
       "ERROR: unknown: x@g.com at p2:d2/owners:1",
       "ERROR: syntax: p2:d2/owners:2: err",
       "ERROR: syntax: d2/owners:1: wrong",
       "ERROR: syntax: d2/owners:2: xyz");
    CommitReceivedEvent event = makeCommitEvent("p1", "T", files);
    assertThat(validate(event, false, ENABLED_CONFIG)).containsExactlyElementsIn(expected);
  }

  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 CommitReceivedEvent makeCommitEvent(
      String project, String message, Map<String, String> fileStrings) throws Exception {
    RevWalk rw = new RevWalk(repo);
    return new MockedCommitReceivedEvent(project, rw, makeCommit(rw, message, fileStrings));
  }

  private List<String> validate(CommitReceivedEvent event, boolean verbose, PluginConfig cfg)
      throws Exception {
    OwnersValidator validator =
        new OwnersValidator("find-owners", pluginConfig, repoManager, new MockedEmails());
    OwnersValidator.Checker checker = validator.new Checker(event, verbose);
    checker.check(OwnersValidator.getOwnersFileName(cfg));
    return transformMessages(checker.messages);
  }

  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);
  }
}
