// 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 new Correspondence<Comment, CommentMatch>() {
      @Override
      public boolean compare(Comment actual, CommentMatch expected) {
        return actual.unresolved != expected.resolved && actual.message.contains(expected.content);
      }

      @Override
      public String toString() {
        return "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 + "\")";
    }
  }
}
