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

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo.ConsistencyProblemInfo;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInput;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.group.db.GroupConfig;
import com.google.gerrit.server.group.db.GroupNameNotes;
import com.google.gerrit.server.group.db.testing.GroupTestUtil;
import com.google.inject.Inject;
import java.util.List;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.RefRename;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;

/**
 * Checks that invalid group configurations are flagged. Since the inconsistencies are global to the
 * test server configuration, and leak from one test method into the next one, there is no way for
 * this test to not be sandboxed.
 */
@Sandboxed
@NoHttpd
public class GroupsConsistencyIT extends AbstractDaemonTest {

  @Inject protected GroupOperations groupOperations;
  private GroupInfo gAdmin;
  private GroupInfo g1;
  private GroupInfo g2;

  private static final String BOGUS_UUID = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";

  @Before
  public void basicSetup() throws Exception {
    allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);

    String name1 = groupOperations.newGroup().name("g1").create().get();
    String name2 = groupOperations.newGroup().name("g2").create().get();

    gApi.groups().id(name1).addMembers(user.fullName());
    gApi.groups().id(name2).addMembers(admin.fullName());
    gApi.groups().id(name1).addGroups(name2);

    this.g1 = gApi.groups().id(name1).detail();
    this.g2 = gApi.groups().id(name2).detail();
    this.gAdmin = gApi.groups().id("Administrators").detail();
  }

  @Test
  public void allGood() throws Exception {
    assertThat(check()).isEmpty();
  }

  @Test
  public void missingGroupNameRef() throws Exception {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      RefUpdate ru = repo.updateRef(RefNames.REFS_GROUPNAMES);
      ru.setForceUpdate(true);
      RefUpdate.Result result = ru.delete();
      assertThat(result).isEqualTo(Result.FORCED);
    }

    assertError("refs/meta/group-names does not exist");
  }

  @Test
  public void missingGroupRef() throws Exception {

    try (Repository repo = repoManager.openRepository(allUsers)) {
      RefUpdate ru = repo.updateRef(RefNames.refsGroups(new AccountGroup.UUID(g1.id)));
      ru.setForceUpdate(true);
      RefUpdate.Result result = ru.delete();
      assertThat(result).isEqualTo(Result.FORCED);
    }

    assertError("missing as group ref");
  }

  @Test
  public void parseGroupRef() throws Exception {

    try (Repository repo = repoManager.openRepository(allUsers)) {
      RefRename ru =
          repo.renameRef(
              RefNames.refsGroups(new AccountGroup.UUID(g1.id)), RefNames.REFS_GROUPS + BOGUS_UUID);
      RefUpdate.Result result = ru.rename();
      assertThat(result).isEqualTo(Result.RENAMED);
    }

    assertError("null UUID from");
  }

  @Test
  public void missingNameEntry() throws Exception {

    try (Repository repo = repoManager.openRepository(allUsers)) {
      RefRename ru =
          repo.renameRef(
              RefNames.refsGroups(new AccountGroup.UUID(g1.id)),
              RefNames.refsGroups(new AccountGroup.UUID(BOGUS_UUID)));
      RefUpdate.Result result = ru.rename();
      assertThat(result).isEqualTo(Result.RENAMED);
    }

    assertError("group " + BOGUS_UUID + " has no entry in name map");
  }

  @Test
  public void groupRefDoesNotParse() throws Exception {
    updateGroupFile(
        RefNames.refsGroups(new AccountGroup.UUID(g1.id)),
        GroupConfig.GROUP_CONFIG_FILE,
        "[this is not valid\n");
    assertError("does not parse");
  }

  @Test
  public void nameRefDoesNotParse() throws Exception {
    updateGroupFile(
        RefNames.REFS_GROUPNAMES,
        GroupNameNotes.getNoteKey(new AccountGroup.NameKey(g1.name)).getName(),
        "[this is not valid\n");
    assertError("does not parse");
  }

  @Test
  public void inconsistentName() throws Exception {
    Config cfg = new Config();
    cfg.setString("group", null, "name", "not really");
    cfg.setString("group", null, "id", "42");
    cfg.setString("group", null, "ownerGroupUuid", gAdmin.id);

    updateGroupFile(
        RefNames.refsGroups(new AccountGroup.UUID(g1.id)),
        GroupConfig.GROUP_CONFIG_FILE,
        cfg.toText());
    assertError("inconsistent name");
  }

  @Test
  public void sharedGroupID() throws Exception {
    Config cfg = new Config();
    cfg.setString("group", null, "name", g1.name);
    cfg.setInt("group", null, "id", g2.groupId);
    cfg.setString("group", null, "ownerGroupUuid", gAdmin.id);

    updateGroupFile(
        RefNames.refsGroups(new AccountGroup.UUID(g1.id)),
        GroupConfig.GROUP_CONFIG_FILE,
        cfg.toText());
    assertError("shared group id");
  }

  @Test
  public void unknownOwnerGroup() throws Exception {
    Config cfg = new Config();
    cfg.setString("group", null, "name", g1.name);
    cfg.setInt("group", null, "id", g1.groupId);
    cfg.setString("group", null, "ownerGroupUuid", BOGUS_UUID);

    updateGroupFile(
        RefNames.refsGroups(new AccountGroup.UUID(g1.id)),
        GroupConfig.GROUP_CONFIG_FILE,
        cfg.toText());
    assertError("nonexistent owner group");
  }

  @Test
  public void nameWithoutGroupRef() throws Exception {
    String bogusName = "bogus name";
    Config config = new Config();
    config.setString("group", null, "uuid", BOGUS_UUID);
    config.setString("group", null, "name", bogusName);

    updateGroupFile(
        RefNames.REFS_GROUPNAMES,
        GroupNameNotes.getNoteKey(new AccountGroup.NameKey(bogusName)).getName(),
        config.toText());
    assertError("entry missing as group ref");
  }

  @Test
  public void nonexistentMember() throws Exception {
    updateGroupFile(RefNames.refsGroups(new AccountGroup.UUID(g1.id)), "members", "314159265\n");
    assertError("nonexistent member 314159265");
  }

  @Test
  public void nonexistentSubgroup() throws Exception {
    updateGroupFile(
        RefNames.refsGroups(new AccountGroup.UUID(g1.id)), "subgroups", BOGUS_UUID + "\n");
    assertError("has nonexistent subgroup");
  }

  @Test
  public void cyclicSubgroup() throws Exception {
    updateGroupFile(RefNames.refsGroups(new AccountGroup.UUID(g1.id)), "subgroups", g1.id + "\n");
    assertWarning("cycle");
  }

  private void assertError(String msg) throws Exception {
    assertConsistency(msg, ConsistencyProblemInfo.Status.ERROR);
  }

  private void assertWarning(String msg) throws Exception {
    assertConsistency(msg, ConsistencyProblemInfo.Status.WARNING);
  }

  private List<ConsistencyProblemInfo> check() throws Exception {
    ConsistencyCheckInput in = new ConsistencyCheckInput();
    in.checkGroups = new ConsistencyCheckInput.CheckGroupsInput();
    ConsistencyCheckInfo info = gApi.config().server().checkConsistency(in);
    return info.checkGroupsResult.problems;
  }

  private void assertConsistency(String msg, ConsistencyProblemInfo.Status want) throws Exception {
    List<ConsistencyProblemInfo> problems = check();

    for (ConsistencyProblemInfo i : problems) {
      if (!i.status.equals(want)) {
        continue;
      }
      if (i.message.contains(msg)) {
        return;
      }
    }

    fail(String.format("could not find %s substring '%s' in %s", want, msg, problems));
  }

  private void updateGroupFile(String refName, String fileName, String content) throws Exception {
    GroupTestUtil.updateGroupFile(
        repoManager, allUsers, serverIdent.get(), refName, fileName, content);
  }
}
