// 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.common.io.Files;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.changes.SubmitInput;
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 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.Optional;
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;

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

  @Rule public Watcher watcher = new Watcher(logger);

  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 = Project.builder(Project.nameKey(project)).build();
      this.revWalk = revWalk;
      this.commit = commit;
      this.refName = "master";
    }
  }

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

    MockedEmails() {
      super(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, 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 = PluginConfig.create("", new Config(), null);
  private static final PluginConfig ENABLED_CONFIG = createEnabledConfig(); // use OWNERS
  private static final PluginConfig DISABLED_CONFIG = createDisabledConfig();

  private OwnersValidator newOwnersValidator(PluginConfig cfg) {
    return new OwnersValidator(cfg, accountCache, repoManager, new MockedEmails());
  }

  @Test
  public void chekIsActiveAndFileName() throws Exception {
    // This check should be enabled in project.config, default is not active.
    assertThat(newOwnersValidator(EMPTY_CONFIG).isActive()).isFalse();
    assertThat(newOwnersValidator(ENABLED_CONFIG).isActive()).isTrue();
    assertThat(newOwnersValidator(ANDROID_CONFIG).isActive()).isTrue();
    assertThat(newOwnersValidator(DISABLED_CONFIG).isActive()).isFalse();
    // Default file name is "OWNERS".
    assertThat(newOwnersValidator(EMPTY_CONFIG).getOwnersFileName()).isEqualTo(OWNERS);
    assertThat(newOwnersValidator(ENABLED_CONFIG).getOwnersFileName()).isEqualTo(OWNERS);
    assertThat(newOwnersValidator(DISABLED_CONFIG).getOwnersFileName()).isEqualTo(OWNERS);
    assertThat(newOwnersValidator(ANDROID_CONFIG).getOwnersFileName()).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);
  }

  @Test
  public void simpleIncludeACLTest() throws Exception {
    // Even if the user cannot read an included file,
    // the upload validator should still check the included file.
    // Use pA/pB, because addProjectFile cannot create the same project again.
    addProjectFile("pA", "d2/owners", "wrong\nxyz\n");
    addProjectFile("pB", "d2/owners", "x@g.com\nerr\ninclude ../d2/owners\n");
    blockRead(project); // current project is pB; set it to not readable
    ImmutableMap<String, String> files =
        ImmutableMap.of(
            "d1/" + OWNERS,
            "include ../d2/owners\ninclude /d2/owners\n"
                + "include pA:/d2/owners\ninclude pB:/d2/owners\n");
    ImmutableSet<String> expected =
        ImmutableSet.of(
            // "MSG: unchecked: d1/OWNERS:4: include pB:/d2/owners", // cannot read pB
            "ERROR: unknown: x@g.com at pB:d2/owners:1",
            "ERROR: syntax: pB:d2/owners:2: err",
            "ERROR: syntax: d2/owners:1: wrong",
            "ERROR: syntax: d2/owners:2: xyz");
    CommitReceivedEvent event = makeCommitEvent("pA", "T", files);
    assertThat(validate(event, false, ENABLED_CONFIG)).containsExactlyElementsIn(expected);
  }

  private static PluginConfig createEnabledConfig() {
    PluginConfig.Update update = new PluginConfig.Update("", new Config(), Optional.empty());
    update.setBoolean(REJECT_ERROR_IN_OWNERS, true);
    return update.asPluginConfig();
  }

  private static PluginConfig createDisabledConfig() {
    PluginConfig.Update update = new PluginConfig.Update("", new Config(), Optional.empty());
    update.setBoolean(REJECT_ERROR_IN_OWNERS, false);
    return update.asPluginConfig();
  }

  private static PluginConfig createAndroidConfig() {
    PluginConfig.Update update = new PluginConfig.Update("", new Config(), Optional.empty());
    update.setBoolean(REJECT_ERROR_IN_OWNERS, true);
    update.setString(OWNERS_FILE_NAME, OWNERS_ANDROID);
    return update.asPluginConfig();
  }

  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 = newOwnersValidator(cfg);
    OwnersValidator.Checker checker = validator.new Checker(event, verbose);
    checker.check(validator.getOwnersFileName());
    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()) {
        Files.createParentDirs(f);
        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);
  }
}
