// Copyright (C) 2019 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.copyright;

import static com.google.common.truth.Truth.assertThat;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_CC;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_FROM;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_REVIEWER;
import static com.googlesource.gerrit.plugins.copyright.TestConfig.LOCAL_BRANCH;

import com.google.common.collect.ImmutableList;
import com.google.common.truth.Correspondence;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.GerritConfigs;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.inject.Inject;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.junit.Before;
import org.junit.Test;

@TestPlugin(name = "copyright", sysModule = "com.googlesource.gerrit.plugins.copyright.Module")
public class CopyrightValidatorIT extends LightweightPluginDaemonTest {
  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushNoLicense() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(author.newIdent(), testRepo, "subject", "filename", "content")
            .to("refs/for/master");

    assertNoReviewerAdded(result);
    assertThat(result.getChange().notes().getComments()).isEmpty();
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushAlwaysReview() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(author.newIdent(), testRepo, "subject", "PATENT", "content")
            .to("refs/for/master");

    assertReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(unresolved("PATENT always requires"));
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushFirstPartyOwner() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(author.newIdent(), testRepo, "subject", "source.cpp", FIRST_PARTY_OWNER)
            .to("refs/for/master");

    assertNoReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(resolved("First-party author or owner"));
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushFirstPartyHeader() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(author.newIdent(), testRepo, "subject", "source.cpp", FIRST_PARTY_HEADER)
            .to("refs/for/master");

    assertNoReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(resolved("First-party license"));
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushFirstPartyOwnerAndHeader() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(
                author.newIdent(),
                testRepo,
                "subject",
                "source.cpp",
                FIRST_PARTY_OWNER + FIRST_PARTY_HEADER)
            .to("refs/for/master");

    assertNoReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(resolved("First-party license")); // owner folds into license
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushFirstPartyHeaderAndOwner() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(
                author.newIdent(),
                testRepo,
                "subject",
                "source.cpp",
                FIRST_PARTY_HEADER + FIRST_PARTY_OWNER)
            .to("refs/for/master");

    assertNoReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(resolved("First-party license")); // owner folds into license
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushNotAContribHeader() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(author.newIdent(), testRepo, "subject", "source.cpp", NOT_A_CONTRIB_HEADER)
            .to("refs/for/master");

    assertReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(resolved("First-party license"), unresolved("Disapproved license"));
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushThirdPartyAllowed() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(author.newIdent(), testRepo, "subject", "LICENSE", THIRD_PARTY_MIT)
            .to("refs/for/master");

    assertNoReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(resolved("Third-party license allowed"));
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushThirdPartyNotAllowed() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(author.newIdent(), testRepo, "subject", "LICENSE", THIRD_PARTY_MIT)
            .to("refs/for/master");

    assertReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(unresolved("Third-party license disallowed"));
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushThirdPartyOwnerAllowed() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(author.newIdent(), testRepo, "subject", "COPYING", THIRD_PARTY_OWNER)
            .to("refs/for/master");

    assertNoReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(resolved("Third-party author or owner allowed"));
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushThirdPartyOwnerNotAllowed() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(author.newIdent(), testRepo, "subject", "COPYING", THIRD_PARTY_OWNER)
            .to("refs/for/master");

    assertReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(unresolved("Third-party author or owner disallowed"));
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushFirstPartyLicenseThirdPartyOwner() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(
                author.newIdent(),
                testRepo,
                "subject",
                "COPYING",
                FIRST_PARTY_HEADER + THIRD_PARTY_OWNER)
            .to("refs/for/master");

    assertNoReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(
            resolved("First-party license"),
            resolved("Third-party author or owner")); // 1p license from 3p author is 1p
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushFirstPartyOwnerThirdPartyOwner() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(
                author.newIdent(),
                testRepo,
                "subject",
                "COPYING",
                FIRST_PARTY_OWNER + THIRD_PARTY_OWNER)
            .to("refs/for/master");

    assertReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(
            resolved("First-party author or owner"),
            unresolved("Third-party author or owner disallowed"));
  }

  @Test
  @GerritConfigs({
    @GerritConfig(name = "plugin.copyright.enable", value = "true"),
    @GerritConfig(name = "plugin.copyright.timeTestMax", value = "0")
  })
  public void testCopyrightValidator_pushThirdPartyLicenseFirstPartyOwner() throws Exception {
    PushOneCommit.Result result =
        pushFactory
            .create(
                author.newIdent(),
                testRepo,
                "subject",
                "COPYING",
                THIRD_PARTY_MIT + FIRST_PARTY_OWNER)
            .to("refs/for/master");

    assertReviewerAdded(result);
    assertThat(result.getChange().notes().getComments().values())
        .comparingElementsUsing(commentContains())
        .containsExactly(
            unresolved("Third-party license disallowed"), resolved("First-party author or owner"));
  }

  private static final String FIRST_PARTY_OWNER =
      "// Copyright (C) 2019 The Android Open Source Project\n";
  private static final String FIRST_PARTY_HEADER =
      "// Licensed under the Apache License, Version 2.0 (the \"License\");\n"
          + "// you may not use this file except in compliance with the License.\n"
          + "// You may obtain a copy of the License at\n//\n"
          + "// http://www.apache.org/licenses/LICENSE-2.0\n//\n"
          + "// Unless required by applicable law or agreed to in writing, software\n"
          + "// distributed under the License is distributed on an \"AS IS\" BASIS,\n"
          + "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
          + "// See the License for the specific language governing permissions and\n"
          + "// limitations under the License.\n";
  private static final String NOT_A_CONTRIB_HEADER = FIRST_PARTY_HEADER + "Not a contribution.\n";
  private static final String THIRD_PARTY_MIT =
      "MIT License\n\nCopyright (c) Jane Doe\n\n"
          + "Permission is hereby granted, free of charge, to any person obtaining a copy\n"
          + "of this software and associated documentation files (the \"Software\"), to deal\n"
          + "in the Software without restriction, including without limitation the rights\n"
          + "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n"
          + "copies of the Software, and to permit persons to whom the Software is\n"
          + "furnished to do so, subject to the following conditions:\n\n"
          + "The above copyright notice and this permission notice shall be included in all\n"
          + "copies or substantial portions of the Software.\n\n"
          + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
          + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
          + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"
          + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
          + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n"
          + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n"
          + "SOFTWARE.\n";
  private static final String THIRD_PARTY_OWNER = "Copyright (c) 2019 Acme Other Corp.\n";

  private static int nextId = 123;

  private GroupInfo botGroup;
  private GroupInfo expertGroup;
  private TestAccount pluginAccount;
  private TestAccount reviewer;
  private TestAccount observer;
  private TestAccount author;
  private String projectConfigContent;

  @Inject GerritApi gApi;

  @Before
  public void setUp() throws Exception {
    botGroup = gApi.groups().id("Non-Interactive Users").detail();
    expertGroup = gApi.groups().create("Copyright Experts").detail();
    pluginAccount =
        accountCreator.create(
            "copyright-scanner",
            "copyright-scanner@example.com",
            "Copyright Scanner",
            "Non-Interactive Users",
            expertGroup.name);
    reviewer =
        accountCreator.create(
            "lawyercat", "legal@example.com", "J. Doe J.D. LL.M. Esq.", expertGroup.name);
    observer = accountCreator.create("my-team", "my-team@example.com", "My Team");
    author = accountCreator.create("author", "author@example.com", "J. Doe");
    TestRepository<InMemoryRepository> testRepo = getTestRepo(allProjects);
    TestConfig testConfig = new TestConfig(allProjects, plugin.getName(), admin, testRepo);
    testConfig.copyLabel("Code-Review", "Copyright-Review");
    testConfig.setVoters(
        RefNames.REFS_HEADS + "*",
        "Copyright-Review",
        new TestConfig.Voter("Administrators", -2, +2),
        new TestConfig.Voter(expertGroup.name, -2, +2),
        new TestConfig.Voter("Registered Users", -2, 0));
    testConfig.addGroups(botGroup, expertGroup);
    testConfig.updatePlugin(
        TestConfig.BASE_CONFIG,
        TestConfig.ENABLE_CONFIG,
        cfg -> {
          cfg.setStringList(KEY_REVIEWER, ImmutableList.of(reviewer.username()));
        },
        cfg -> {
          cfg.setStringList(KEY_CC, ImmutableList.of(observer.username()));
        },
        cfg -> {
          cfg.setInt(KEY_FROM, pluginAccount.id().get());
        });
    PushOneCommit.Result result = testConfig.push(pushFactory);
    result.assertOkStatus();
    assertThat(result.getChange().publishedComments()).isEmpty();
    merge(result);
  }

  private AccountGroup.Id nextGroupId() {
    return AccountGroup.id(nextId++);
  }

  private TestRepository<InMemoryRepository> getTestRepo(Project.NameKey projectName)
      throws Exception {
    TestRepository<InMemoryRepository> testRepo = cloneProject(projectName, admin);
    GitUtil.fetch(testRepo, RefNames.REFS_CONFIG + ":" + LOCAL_BRANCH);
    testRepo.reset(LOCAL_BRANCH);
    return testRepo;
  }

  private void assertReviewerAdded(PushOneCommit.Result result) throws Exception {
    result.assertOkStatus();
    result.assertChange(
        Change.Status.NEW,
        null,
        ImmutableList.of(author, reviewer, pluginAccount),
        ImmutableList.of(observer));
  }

  private void assertNoReviewerAdded(PushOneCommit.Result result) throws Exception {
    result.assertOkStatus();
    result.assertChange(
        Change.Status.NEW, null, ImmutableList.of(author, pluginAccount), ImmutableList.of());
  }

  private CommentMatch resolved(String content) {
    return new CommentMatch(true /* resolved */, content);
  }

  private CommentMatch unresolved(String content) {
    return new CommentMatch(false /* resolved */, content);
  }

  private static Correspondence<Comment, CommentMatch> commentContains() {
    return Correspondence.from(
        (actual, expected) ->
            actual.unresolved != expected.resolved && actual.message.contains(expected.content),
        "comment resolution status and content matches");
  }

  private static class CommentMatch {
    boolean resolved;
    String content;

    CommentMatch(boolean resolved, String content) {
      this.resolved = resolved;
      this.content = content;
    }

    @Override
    public String toString() {
      return (resolved ? "" : "un") + "resolved(\"" + content + "\")";
    }
  }
}
