// 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.google.gerrit.plugins.codeowners.acceptance.api;

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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo.ConsistencyProblemInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerSet;
import com.google.gerrit.plugins.codeowners.backend.findowners.FindOwnersBackend;
import com.google.gerrit.plugins.codeowners.backend.findowners.FindOwnersCodeOwnerConfigParser;
import com.google.gerrit.plugins.codeowners.backend.proto.ProtoBackend;
import com.google.gerrit.plugins.codeowners.backend.proto.ProtoCodeOwnerConfigParser;
import com.google.gerrit.plugins.codeowners.config.BackendConfig;
import com.google.gerrit.plugins.codeowners.util.JgitPath;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Before;
import org.junit.Test;

/**
 * Acceptance test for the {@link
 * com.google.gerrit.plugins.codeowners.restapi.CheckCodeOwnerConfigFilesInRevision} REST endpoint.
 */
public class CheckCodeOwnerConfigFilesInRevisionIT extends AbstractCodeOwnersIT {
  private static final ObjectId TEST_REVISION =
      ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");

  private BackendConfig backendConfig;
  private FindOwnersCodeOwnerConfigParser findOwnersCodeOwnerConfigParser;
  private ProtoCodeOwnerConfigParser protoCodeOwnerConfigParser;

  @Before
  public void setUpCodeOwnersPlugin() throws Exception {
    backendConfig = plugin.getSysInjector().getInstance(BackendConfig.class);
    findOwnersCodeOwnerConfigParser =
        plugin.getSysInjector().getInstance(FindOwnersCodeOwnerConfigParser.class);
    protoCodeOwnerConfigParser =
        plugin.getSysInjector().getInstance(ProtoCodeOwnerConfigParser.class);
  }

  @Test
  public void noCodeOwnerConfigFile() throws Exception {
    assertThat(checkCodeOwnerConfigFilesIn(createChange().getChangeId())).isEmpty();
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabledBranch", value = "refs/heads/master")
  public void noCodeOwnerConfigFile_codeOwnersFunctionalityIsDisabled() throws Exception {
    assertThat(checkCodeOwnerConfigFilesIn(createChange().getChangeId())).isEmpty();
  }

  @Test
  public void codeOwnerConfigFileWithoutIssues() throws Exception {
    testCodeOwnerConfigFileWithoutIssues();
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabledBranch", value = "refs/heads/master")
  public void codeOwnerConfigFileWithoutIssues_codeOwnersFunctionalityIsDisabled()
      throws Exception {
    testCodeOwnerConfigFileWithoutIssues();
  }

  private void testCodeOwnerConfigFileWithoutIssues() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
    String codeOwnerConfigPath =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath();
    String changeId =
        createChange(
                "Add code owners",
                JgitPath.of(codeOwnerConfigPath).get(),
                format(
                    CodeOwnerConfig.builder(codeOwnerConfigKey, TEST_REVISION)
                        .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email()))
                        .build()))
            .getChangeId();
    assertThat(checkCodeOwnerConfigFilesIn(changeId))
        .containsExactly(codeOwnerConfigPath, ImmutableList.of());
  }

  @Test
  public void nonParseableCodeOwnerConfigFile() throws Exception {
    testNonParseableCodeOwnerConfigFile();
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabledBranch", value = "refs/heads/master")
  public void nonParseableCodeOwnerConfigFile_codeOwnersFunctionalityIsDisabled() throws Exception {
    testNonParseableCodeOwnerConfigFile();
  }

  private void testNonParseableCodeOwnerConfigFile() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
    String codeOwnerConfigPath =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath();

    disableCodeOwnersForProject(project);
    String changeId =
        createChange("Add code owners", JgitPath.of(codeOwnerConfigPath).get(), "INVALID")
            .getChangeId();
    enableCodeOwnersForProject(project);

    assertThat(checkCodeOwnerConfigFilesIn(changeId))
        .containsExactly(
            codeOwnerConfigPath,
            ImmutableList.of(
                fatal(
                    String.format(
                        "invalid code owner config file '%s':\n  %s",
                        codeOwnerConfigPath,
                        getParsingErrorMessage(
                            ImmutableMap.of(
                                FindOwnersBackend.class,
                                "invalid line: INVALID",
                                ProtoBackend.class,
                                "1:8: Expected \"{\"."))))));
  }

  @Test
  public void codeOwnerConfigFileWithIssues() throws Exception {
    testCodeOwnerConfigFileWithIssues();
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabledBranch", value = "refs/heads/master")
  public void codeOwnerConfigFileWithIssues_codeOwnersFunctionalityIsDisabled() throws Exception {
    testCodeOwnerConfigFileWithIssues();
  }

  private void testCodeOwnerConfigFileWithIssues() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
    String codeOwnerConfigPath =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath();
    String unknownEmail1 = "non-existing-email@example.com";
    String unknownEmail2 = "another-unknown-email@example.com";

    disableCodeOwnersForProject(project);
    String changeId =
        createChange(
                "Add code owners",
                JgitPath.of(codeOwnerConfigPath).get(),
                format(
                    CodeOwnerConfig.builder(codeOwnerConfigKey, TEST_REVISION)
                        .addCodeOwnerSet(
                            CodeOwnerSet.createWithoutPathExpressions(
                                unknownEmail1, admin.email(), unknownEmail2))
                        .build()))
            .getChangeId();
    enableCodeOwnersForProject(project);

    Map<String, List<ConsistencyProblemInfo>> problemsByPath =
        checkCodeOwnerConfigFilesIn(changeId);
    assertThat(problemsByPath.keySet()).containsExactly(codeOwnerConfigPath);
    assertThat(problemsByPath.get(codeOwnerConfigPath))
        .containsExactly(
            error(
                String.format(
                    "code owner email '%s' in '%s' cannot be" + " resolved for admin",
                    unknownEmail1, codeOwnerConfigPath)),
            error(
                String.format(
                    "code owner email '%s' in '%s' cannot be" + " resolved for admin",
                    unknownEmail2, codeOwnerConfigPath)));
  }

  @Test
  @GerritConfig(name = "accounts.visibility", value = "SAME_GROUP")
  public void validationIsDoneFromThePerspectiveOfTheUploader() throws Exception {
    // Create a new user that is not a member of any group. This means 'user' and 'admin' are not
    // visible to this user since they do not share any group.
    TestAccount user2 = accountCreator.user2();

    CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
    String codeOwnerConfigPath =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath();

    // Upload the change as user2 who cannot see 'admin' and 'user'.
    disableCodeOwnersForProject(project);
    String changeId =
        createChange(
                user2,
                "Add code owners",
                JgitPath.of(codeOwnerConfigPath).get(),
                format(
                    CodeOwnerConfig.builder(codeOwnerConfigKey, TEST_REVISION)
                        .addCodeOwnerSet(
                            CodeOwnerSet.createWithoutPathExpressions(admin.email(), user.email()))
                        .build()))
            .getChangeId();
    enableCodeOwnersForProject(project);

    // The validation request is done by 'admin' which can see 'admin' and 'user', however the
    // validation is performed from the perspective of the uploader which is 'user2' and 'user2'
    // cannot see 'admin' and 'user.
    Map<String, List<ConsistencyProblemInfo>> problemsByPath =
        checkCodeOwnerConfigFilesIn(changeId);
    assertThat(problemsByPath.keySet()).containsExactly(codeOwnerConfigPath);
    assertThat(problemsByPath.get(codeOwnerConfigPath))
        .containsExactly(
            error(
                String.format(
                    "code owner email '%s' in '%s' cannot be" + " resolved for user2",
                    admin.email(), codeOwnerConfigPath)),
            error(
                String.format(
                    "code owner email '%s' in '%s' cannot be" + " resolved for user2",
                    user.email(), codeOwnerConfigPath)));
  }

  @Test
  public void nonModifiedCodeOwnerConfigFilesAreNotValidated() throws Exception {
    // Create a code owner config file with issues in the repository.
    CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
    String codeOwnerConfigPath =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath();
    String unknownEmail1 = "non-existing-email@example.com";
    String unknownEmail2 = "another-unknown-email@example.com";
    disableCodeOwnersForProject(project);
    String changeId =
        createChange(
                "Add code owners",
                JgitPath.of(codeOwnerConfigPath).get(),
                format(
                    CodeOwnerConfig.builder(codeOwnerConfigKey, TEST_REVISION)
                        .addCodeOwnerSet(
                            CodeOwnerSet.createWithoutPathExpressions(
                                unknownEmail1, admin.email(), unknownEmail2))
                        .build()))
            .getChangeId();
    approve(changeId);
    gApi.changes().id(changeId).current().submit();
    enableCodeOwnersForProject(project);

    // Create a change that adds another code owner config file without issues.
    CodeOwnerConfig.Key codeOwnerConfigKey2 = createCodeOwnerConfigKey("/foo/");
    String codeOwnerConfigPath2 =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getFilePath();
    String changeId2 =
        createChange(
                "Add code owners",
                JgitPath.of(codeOwnerConfigPath2).get(),
                format(
                    CodeOwnerConfig.builder(codeOwnerConfigKey2, TEST_REVISION)
                        .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email()))
                        .build()))
            .getChangeId();
    assertThat(checkCodeOwnerConfigFilesIn(changeId2))
        .containsExactly(codeOwnerConfigPath2, ImmutableList.of());
  }

  @Test
  public void deletedCodeOwnerConfigFilesAreNotValidated() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = createCodeOwnerConfigKey("/");
    String codeOwnerConfigPath =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath();
    disableCodeOwnersForProject(project);
    String changeId = createChangeWithFileDeletion(codeOwnerConfigPath);
    enableCodeOwnersForProject(project);
    assertThat(checkCodeOwnerConfigFilesIn(changeId)).isEmpty();
  }

  @Test
  public void validateExactFile() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey1 = createCodeOwnerConfigKey("/");
    CodeOwnerConfig.Key codeOwnerConfigKey2 = createCodeOwnerConfigKey("/foo/");
    String codeOwnerConfigPath1 =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).getFilePath();
    String codeOwnerConfigPath2 =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getFilePath();
    String unknownEmail1 = "non-existing-email@example.com";
    String unknownEmail2 = "another-unknown-email@example.com";

    disableCodeOwnersForProject(project);
    String changeId =
        createChange(
                "Add code owners",
                ImmutableMap.of(
                    JgitPath.of(codeOwnerConfigPath1).get(),
                    format(
                        CodeOwnerConfig.builder(codeOwnerConfigKey1, TEST_REVISION)
                            .addCodeOwnerSet(
                                CodeOwnerSet.createWithoutPathExpressions(
                                    unknownEmail1, admin.email()))
                            .build()),
                    JgitPath.of(codeOwnerConfigPath2).get(),
                    format(
                        CodeOwnerConfig.builder(codeOwnerConfigKey2, TEST_REVISION)
                            .addCodeOwnerSet(
                                CodeOwnerSet.createWithoutPathExpressions(
                                    unknownEmail2, admin.email()))
                            .build())))
            .getChangeId();
    enableCodeOwnersForProject(project);

    Map<String, List<ConsistencyProblemInfo>> problemsByPath =
        changeCodeOwnersApiFactory
            .change(changeId)
            .current()
            .checkCodeOwnerConfigFiles()
            .setPath(codeOwnerConfigPath1)
            .check();
    assertThat(problemsByPath)
        .containsExactly(
            codeOwnerConfigPath1,
            ImmutableList.of(
                error(
                    String.format(
                        "code owner email '%s' in '%s' cannot be" + " resolved for admin",
                        unknownEmail1, codeOwnerConfigPath1))));
  }

  @Test
  public void validateFilesMatchingGlob() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey1 = createCodeOwnerConfigKey("/");
    CodeOwnerConfig.Key codeOwnerConfigKey2 = createCodeOwnerConfigKey("/foo/");
    CodeOwnerConfig.Key codeOwnerConfigKey3 = createCodeOwnerConfigKey("/foo/bar/");
    String codeOwnerConfigPath1 =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).getFilePath();
    String codeOwnerConfigPath2 =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getFilePath();
    String codeOwnerConfigPath3 =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey3).getFilePath();
    String unknownEmail1 = "non-existing-email@example.com";
    String unknownEmail2 = "another-unknown-email@example.com";
    String unknownEmail3 = "yet-another-unknown-email@example.com";

    disableCodeOwnersForProject(project);
    String changeId =
        createChange(
                "Add code owners",
                ImmutableMap.of(
                    JgitPath.of(codeOwnerConfigPath1).get(),
                    format(
                        CodeOwnerConfig.builder(codeOwnerConfigKey1, TEST_REVISION)
                            .addCodeOwnerSet(
                                CodeOwnerSet.createWithoutPathExpressions(
                                    unknownEmail1, admin.email()))
                            .build()),
                    JgitPath.of(codeOwnerConfigPath2).get(),
                    format(
                        CodeOwnerConfig.builder(codeOwnerConfigKey2, TEST_REVISION)
                            .addCodeOwnerSet(
                                CodeOwnerSet.createWithoutPathExpressions(
                                    unknownEmail2, admin.email()))
                            .build()),
                    JgitPath.of(codeOwnerConfigPath3).get(),
                    format(
                        CodeOwnerConfig.builder(codeOwnerConfigKey3, TEST_REVISION)
                            .addCodeOwnerSet(
                                CodeOwnerSet.createWithoutPathExpressions(
                                    unknownEmail3, admin.email()))
                            .build())))
            .getChangeId();
    enableCodeOwnersForProject(project);

    Map<String, List<ConsistencyProblemInfo>> problemsByPath =
        changeCodeOwnersApiFactory
            .change(changeId)
            .current()
            .checkCodeOwnerConfigFiles()
            .setPath("/foo/**")
            .check();
    assertThat(problemsByPath)
        .containsExactly(
            codeOwnerConfigPath2,
            ImmutableList.of(
                error(
                    String.format(
                        "code owner email '%s' in '%s' cannot be" + " resolved for admin",
                        unknownEmail2, codeOwnerConfigPath2))),
            codeOwnerConfigPath3,
            ImmutableList.of(
                error(
                    String.format(
                        "code owner email '%s' in '%s' cannot be" + " resolved for admin",
                        unknownEmail3, codeOwnerConfigPath3))));
  }

  @Test
  public void allIssuesAreReturnedIfNoLevelIsSpecified() throws Exception {
    testIssuesAreFilteredByVerbosity(
        /** verbosity */
        null);
  }

  @Test
  public void allIssuesAreReturnedIfLevelIsSetToWarning() throws Exception {
    testIssuesAreFilteredByVerbosity(ConsistencyProblemInfo.Status.WARNING);
  }

  @Test
  public void onlyFatalAndErrorIssuesAreReturnedIfLevelIsSetToError() throws Exception {
    testIssuesAreFilteredByVerbosity(ConsistencyProblemInfo.Status.ERROR);
  }

  @Test
  public void onlyFatalIssuesAreReturnedIfLevelIsSetToFatal() throws Exception {
    testIssuesAreFilteredByVerbosity(ConsistencyProblemInfo.Status.FATAL);
  }

  private void testIssuesAreFilteredByVerbosity(@Nullable ConsistencyProblemInfo.Status verbosity)
      throws Exception {
    CodeOwnerConfig.Key keyOfNonParseableCodeOwnerConfig = createCodeOwnerConfigKey("/");
    String pathOfNonParseableCodeOwnerConfig =
        codeOwnerConfigOperations.codeOwnerConfig(keyOfNonParseableCodeOwnerConfig).getFilePath();

    CodeOwnerConfig.Key keyOfInvalidCodeOwnerConfig = createCodeOwnerConfigKey("/foo/");
    String pathOfInvalidCodeOwnerConfig =
        codeOwnerConfigOperations.codeOwnerConfig(keyOfInvalidCodeOwnerConfig).getFilePath();
    String unknownEmail = "unknown@example.com";

    // create a change with a) a non-parseable code owner config that will be reported as fatal and
    // b) an invalid code owner config with an unknown email that will be reported as error
    // (there is currently nothing that triggers a warning)
    disableCodeOwnersForProject(project);
    String changeId =
        createChange(
                "Add code owners",
                ImmutableMap.of(
                    JgitPath.of(pathOfNonParseableCodeOwnerConfig).get(),
                    "INVALID",
                    JgitPath.of(pathOfInvalidCodeOwnerConfig).get(),
                    format(
                        CodeOwnerConfig.builder(keyOfInvalidCodeOwnerConfig, TEST_REVISION)
                            .addCodeOwnerSet(
                                CodeOwnerSet.createWithoutPathExpressions(unknownEmail))
                            .build())))
            .getChangeId();
    enableCodeOwnersForProject(project);

    Map<String, List<ConsistencyProblemInfo>> expectedIssues = new HashMap<>();
    // the fatal issue is always expected
    expectedIssues.put(
        pathOfNonParseableCodeOwnerConfig,
        ImmutableList.of(
            fatal(
                String.format(
                    "invalid code owner config file '%s':\n  %s",
                    pathOfNonParseableCodeOwnerConfig,
                    getParsingErrorMessage(
                        ImmutableMap.of(
                            FindOwnersBackend.class,
                            "invalid line: INVALID",
                            ProtoBackend.class,
                            "1:8: Expected \"{\"."))))));
    if (verbosity == null
        || ConsistencyProblemInfo.Status.ERROR.equals(verbosity)
        || ConsistencyProblemInfo.Status.WARNING.equals(verbosity)) {
      expectedIssues.put(
          pathOfInvalidCodeOwnerConfig,
          ImmutableList.of(
              error(
                  String.format(
                      "code owner email '%s' in '%s' cannot be" + " resolved for admin",
                      unknownEmail, pathOfInvalidCodeOwnerConfig))));
    } else {
      expectedIssues.put(pathOfInvalidCodeOwnerConfig, ImmutableList.of());
    }

    Map<String, List<ConsistencyProblemInfo>> result =
        changeCodeOwnersApiFactory
            .change(changeId)
            .current()
            .checkCodeOwnerConfigFiles()
            .setVerbosity(verbosity)
            .check();
    assertThat(result).isEqualTo(expectedIssues);
  }

  private ConsistencyProblemInfo fatal(String message) {
    return new ConsistencyProblemInfo(ConsistencyProblemInfo.Status.FATAL, message);
  }

  private ConsistencyProblemInfo error(String message) {
    return new ConsistencyProblemInfo(ConsistencyProblemInfo.Status.ERROR, message);
  }

  private Map<String, List<ConsistencyProblemInfo>> checkCodeOwnerConfigFilesIn(String changeId)
      throws RestApiException {
    return changeCodeOwnersApiFactory
        .change(changeId)
        .current()
        .checkCodeOwnerConfigFiles()
        .check();
  }

  private CodeOwnerConfig.Key createCodeOwnerConfigKey(String folderPath) {
    return CodeOwnerConfig.Key.create(project, "master", folderPath);
  }

  private String format(CodeOwnerConfig codeOwnerConfig) throws Exception {
    if (backendConfig.getDefaultBackend() instanceof FindOwnersBackend) {
      return findOwnersCodeOwnerConfigParser.formatAsString(codeOwnerConfig);
    } else if (backendConfig.getDefaultBackend() instanceof ProtoBackend) {
      return protoCodeOwnerConfigParser.formatAsString(codeOwnerConfig);
    }

    throw new IllegalStateException(
        String.format(
            "unknown code owner backend: %s",
            backendConfig.getDefaultBackend().getClass().getName()));
  }

  private String getParsingErrorMessage(
      ImmutableMap<Class<? extends CodeOwnerBackend>, String> messagesByBackend) {
    CodeOwnerBackend codeOwnerBackend = backendConfig.getDefaultBackend();
    assertThat(messagesByBackend).containsKey(codeOwnerBackend.getClass());
    return messagesByBackend.get(codeOwnerBackend.getClass());
  }
}
