// Copyright (C) 2013 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;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.OptionalSubject.optionals;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.entities.Patch.COMMIT_MSG;
import static com.google.gerrit.entities.Patch.MERGE_LIST;
import static com.google.gerrit.extensions.api.changes.SubmittedTogetherOption.NON_VISIBLE_CHANGES;
import static com.google.gerrit.extensions.api.changes.SubmittedTogetherOption.TOPIC_CLOSURE;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.server.project.testing.TestLabels.label;
import static com.google.gerrit.server.project.testing.TestLabels.value;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.testing.TestActionRefUpdateContext.testRefAction;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;
import static org.eclipse.jgit.lib.Constants.HEAD;

import com.github.rholder.retry.BlockStrategy;
import com.google.common.base.Strings;
import com.google.common.base.Ticker;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.primitives.Chars;
import com.google.common.testing.FakeTicker;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.acceptance.PushOneCommit.Result;
import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.entities.AccessSection;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Address;
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.EmailHeader;
import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
import com.google.gerrit.entities.GroupDescription;
import com.google.gerrit.entities.GroupReference;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.entities.LabelFunction;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelValue;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.PermissionRule;
import com.google.gerrit.entities.PermissionRule.Action;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.entities.SubmitRequirement;
import com.google.gerrit.entities.SubmitRequirementExpression;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.RevisionApi;
import com.google.gerrit.extensions.api.changes.SubmittedTogetherInfo;
import com.google.gerrit.extensions.api.changes.SubmittedTogetherOption;
import com.google.gerrit.extensions.api.projects.BranchApi;
import com.google.gerrit.extensions.api.projects.BranchInfo;
import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.api.projects.ProjectInput;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.client.ProjectWatchInfo;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeType;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.DiffInfo;
import com.google.gerrit.extensions.common.EditInfo;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.json.OutputFormat;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.PluginUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.Accounts;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.change.BatchAbandon;
import com.google.gerrit.server.change.ChangeFinder;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.FileContentUtil;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritInstanceId;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.index.account.AccountIndexer;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.notedb.AbstractChangeNotes;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeNotesCommit;
import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
import com.google.gerrit.server.plugins.PluginContentScanner;
import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
import com.google.gerrit.server.plugins.TestServerPlugin;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.restapi.change.Revisions;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gerrit.testing.FakeEmailSender;
import com.google.gerrit.testing.FakeEmailSender.Message;
import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Provider;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.Transport;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;

@RunWith(ConfigSuite.class)
public abstract class AbstractDaemonTest {

  @ClassRule public static TemporaryFolder temporaryFolder = new TemporaryFolder();

  @ConfigSuite.Parameter public Config baseConfig;
  @ConfigSuite.Name public String configName;

  public TestRule testRunner =
      new TestRule() {
        @Override
        public Statement apply(Statement base, Description description) {
          return new Statement() {
            @Override
            public void evaluate() throws Throwable {
              beforeTest(description);
              try (ProjectResetter resetter =
                  server.createProjectResetter(
                      (allProjects, allUsers) -> resetProjects(allProjects, allUsers))) {
                base.evaluate();
              } finally {
                afterTest();
              }
            }
          };
        }
      };

  protected DaemonTestRule daemonTestRule;
  protected TestConfigRule configRule;
  protected ServerTestRule server;
  protected TimeSettingsTestRule timeSettingsRule;

  @Rule public TestRule topLevelTestRule = createTopLevelTestRule();

  /**
   * Creates test rules required for tests.
   *
   * <p>Creating all rules in a single method gives more flexibility in the order of creation and
   * allows additional initialization steps if needed.
   */
  protected TestRule createTopLevelTestRule() {
    daemonTestRule = createDaemonTestRule();
    configRule = daemonTestRule.configRule();
    timeSettingsRule = daemonTestRule.timeSettingsRule();
    server = daemonTestRule.server();
    return daemonTestRule;
  }

  @UsedAt(UsedAt.Project.GOOGLE)
  protected DaemonTestRule createDaemonTestRule() {
    return GerritServerDaemonTestRule.create(this);
  }

  @Inject @CanonicalWebUrl protected Provider<String> canonicalWebUrl;
  @Inject @GerritPersonIdent protected Provider<PersonIdent> serverIdent;
  @Inject @GerritServerConfig protected Config cfg;
  @Inject @GerritInstanceId @Nullable protected String instanceId;
  @Inject protected AccountCache accountCache;
  @Inject protected AccountCreator accountCreator;
  @Inject protected Accounts accounts;
  @Inject protected AllProjectsName allProjects;
  @Inject protected AllUsersName allUsers;
  @Inject protected BatchUpdate.Factory batchUpdateFactory;
  @Inject protected ChangeData.Factory changeDataFactory;
  @Inject protected ChangeFinder changeFinder;
  @Inject protected ChangeIndexer indexer;
  @Inject protected ChangeNoteUtil changeNoteUtil;
  @Inject protected ChangeResource.Factory changeResourceFactory;
  @Inject protected FakeEmailSender sender;
  @Inject protected GerritApi gApi;
  @Inject protected GitRepositoryManager repoManager;
  @Inject protected GroupBackend groupBackend;
  @Inject protected GroupCache groupCache;
  @Inject protected IdentifiedUser.GenericFactory identifiedUserFactory;
  @Inject protected MetaDataUpdate.Server metaDataUpdateFactory;
  @Inject protected PatchSetUtil psUtil;
  @Inject protected ProjectCache projectCache;
  @Inject protected ProjectConfig.Factory projectConfigFactory;
  @Inject protected Provider<InternalChangeQuery> queryProvider;
  @Inject protected PushOneCommit.Factory pushFactory;
  @Inject protected PluginConfigFactory pluginConfig;
  @Inject protected Revisions revisions;
  @Inject protected SystemGroupBackend systemGroupBackend;
  @Inject protected ChangeNotes.Factory notesFactory;
  @Inject protected BatchAbandon batchAbandon;
  @Inject protected TestSshKeys sshKeys;
  @Inject protected TestTicker testTicker;
  @Inject protected ThreadLocalRequestContext localCtx;

  @Nullable public SshSession adminSshSession;

  @Nullable public SshSession userSshSession;

  protected EventRecorder eventRecorder;

  protected Project.NameKey project;
  protected RestSession adminRestSession;
  protected RestSession userRestSession;
  protected RestSession anonymousRestSession;
  protected TestAccount admin;
  protected TestAccount user;
  protected TestRepository<InMemoryRepository> testRepo;
  protected String resourcePrefix;
  protected BlockStrategy noSleepBlockStrategy = t -> {}; // Don't sleep in tests.

  @Inject private AbstractChangeNotes.Args changeNotesArgs;
  @Inject private AccountIndexer accountIndexer;
  @Inject private EventRecorder.Factory eventRecorderFactory;
  @Inject private InProcessProtocol inProcessProtocol;
  @Inject private PluginGuiceEnvironment pluginGuiceEnvironment;
  @Inject private PluginUser.Factory pluginUserFactory;
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private SitePaths sitePaths;
  @Inject private ProjectOperations projectOperations;

  private List<Repository> toClose;

  public String getResourcePrefix() {
    return resourcePrefix;
  }

  public void setResourcePrefix(String resourcePrefix) {
    this.resourcePrefix = resourcePrefix;
  }

  public TestRepository<InMemoryRepository> getTestRepo() {
    return testRepo;
  }

  public void setTestRepo(TestRepository<InMemoryRepository> testRepo) {
    this.testRepo = testRepo;
  }

  public TestAccount getUser() {
    return user;
  }

  public void setUser(TestAccount user) {
    this.user = user;
  }

  public TestAccount getAdmin() {
    return admin;
  }

  public void setAdmin(TestAccount admin) {
    this.admin = admin;
  }

  public Project.NameKey getProject() {
    return project;
  }

  public void setProject(Project.NameKey project) {
    this.project = project;
  }

  @Before
  public void clearSender() {
    if (sender != null) {
      sender.clear();
    }
  }

  @Before
  public void startEventRecorder() {
    if (eventRecorderFactory != null) {
      eventRecorder = eventRecorderFactory.create(admin);
    }
  }

  @After
  public void verifyNoPiiInChangeNotes() throws RestApiException, IOException {
    if (configRule.methodDescription().verifyNoPiiInChangeNotes()) {
      verifyNoAccountDetailsInChangeNotes();
    }
  }

  @After
  public void closeEventRecorder() {
    if (eventRecorder != null) {
      eventRecorder.close();
    }
  }

  @ConfigSuite.AfterConfig
  public static void stopCommonServer() throws Exception {
    GerritServerTestRule.afterConfigChanged();
  }

  /**
   * Controls which project and branches should be reset in the commonServer after each test case.
   *
   * <p>Parameters allProjects and allUsers must refer to the commonServer names - if a test doesn't
   * use commonServer then names in the test can be different from names in commonServer.
   */
  protected ProjectResetter.Config resetProjects(
      AllProjectsName allProjects, AllUsersName allUsers) {
    return new ProjectResetter.Config.Builder()
        // Don't reset all refs so that refs/sequences/changes is not touched and change IDs are
        // not reused.
        .reset(allProjects, RefNames.REFS_CONFIG)
        // Don't reset refs/sequences/accounts so that account IDs are not reused.
        .reset(
            allUsers,
            RefNames.REFS_CONFIG,
            RefNames.REFS_USERS + "*",
            RefNames.REFS_EXTERNAL_IDS,
            RefNames.REFS_GROUPNAMES,
            RefNames.REFS_GROUPS + "*",
            RefNames.REFS_STARRED_CHANGES + "*",
            RefNames.REFS_DRAFT_COMMENTS + "*")
        .build();
  }

  protected void restartAsSlave() throws Exception {
    server.restartAsSlave();
    server.getTestInjector().injectMembers(this);
    updateSshSessions();
  }

  protected void restart() throws Exception {
    server.restart();
    server.getTestInjector().injectMembers(this);
    updateSshSessions();
  }

  public void reindexAccount(Account.Id accountId) {
    accountIndexer.index(accountId);
  }

  protected static Config submitWholeTopicEnabledConfig() {
    Config cfg = new Config();
    cfg.setBoolean("change", null, "submitWholeTopic", true);
    return cfg;
  }

  protected boolean isSubmitWholeTopicEnabled() {
    return cfg.getBoolean("change", null, "submitWholeTopic", false);
  }

  protected boolean isContributorAgreementsEnabled() {
    return cfg.getBoolean("auth", null, "contributorAgreements", false);
  }

  protected void beforeTest(Description description) throws Exception {
    // SystemReader must be overridden before creating any repos, since they read the user/system
    // configs at initialization time, and are then stored in the RepositoryCache forever.

    if (enableExperimentsRejectImplicitMergesOnMerge()) {
      // When changes are merged/submitted - reject the operation if there is an implicit merge (
      // even if rejectImplicitMerges is disabled in the project config).
      baseConfig.setStringList(
          "experiments",
          null,
          "enabled",
          ImmutableList.of(
              "GerritBackendFeature__check_implicit_merges_on_merge",
              "GerritBackendFeature__reject_implicit_merges_on_merge",
              "GerritBackendFeature__always_reject_implicit_merges_on_merge"));
    }

    server.initServer();
    server.getTestInjector().injectMembers(this);

    Transport.register(inProcessProtocol);
    toClose = Collections.synchronizedList(new ArrayList<>());

    setUpDatabase();
    server.initSsh();
    updateSshSessions();
  }

  void updateSshSessions() throws Exception {
    userSshSession = null;
    adminSshSession = null;
    if (server.sshInitialized()) {
      try (ManualRequestContext ctx = requestScopeOperations.setNestedApiUser(user.id())) {
        userSshSession = server.getOrCreateSshSessionForContext(ctx);
        // The session doesn't store any reference to the context and it remains open after the ctx
        // is closed.
        userSshSession.open();
      }

      try (ManualRequestContext ctx = requestScopeOperations.setNestedApiUser(admin.id())) {
        adminSshSession = server.getOrCreateSshSessionForContext(ctx);
        // The session doesn't store any reference to the context and it remains open after the ctx
        // is closed.
        adminSshSession.open();
      }
    }
  }

  protected boolean enableExperimentsRejectImplicitMergesOnMerge() {
    // By default any attempt to make an explicit merge is rejected. This allows to check
    // that existing workflows continue to work even if gerrit rejects implicit merges on merge.
    return true;
  }

  protected void setUpDatabase() throws Exception {
    admin = accountCreator.admin();
    user = accountCreator.user1();

    // Evict and reindex accounts in case tests modify them.
    reindexAccount(admin.id());
    reindexAccount(user.id());

    adminRestSession = server.createRestSession(admin);
    userRestSession = server.createRestSession(user);
    anonymousRestSession = server.createRestSession(null);

    String testMethodName = configRule.description().getMethodName();
    resourcePrefix =
        UNSAFE_PROJECT_NAME
            .matcher(configRule.description().getClassName() + "_" + testMethodName + "_")
            .replaceAll("");

    requestScopeOperations.setApiUser(admin.id());
    ProjectInput in = projectInput(configRule.description());
    gApi.projects().create(in);
    project = Project.nameKey(in.name);
    if (!configRule.classDescription().skipProjectClone()) {
      testRepo = cloneProject(project, getCloneAsAccount(configRule.description()));
    }
  }

  /** Override to bind an additional Guice module */
  public Module createModule() {
    return null;
  }

  /** Override to bind an alternative audit Guice module */
  public Module createAuditModule() {
    return null;
  }

  /** Override to bind an additional Guice module for SSH injector */
  public Module createSshModule() {
    return null;
  }

  protected TestAccount getCloneAsAccount(Description description) {
    TestProjectInput ann = description.getAnnotation(TestProjectInput.class);
    return accountCreator.get(ann != null ? ann.cloneAs() : "admin");
  }

  /** Generate default project properties based on test description */
  public ProjectInput projectInput(Description description) {
    ProjectInput in = new ProjectInput();
    TestProjectInput ann = description.getAnnotation(TestProjectInput.class);
    in.name = name("project");
    in.branches = ImmutableList.of(Constants.R_HEADS + Constants.MASTER);
    if (ann != null) {
      in.parent = Strings.emptyToNull(ann.parent());
      in.description = Strings.emptyToNull(ann.description());
      in.createEmptyCommit = ann.createEmptyCommit();
      in.submitType = ann.submitType();
      in.useContentMerge = ann.useContributorAgreements();
      in.useSignedOffBy = ann.useSignedOffBy();
      in.useContentMerge = ann.useContentMerge();
      in.rejectEmptyCommit = ann.rejectEmptyCommit();
      in.enableSignedPush = ann.enableSignedPush();
      in.requireSignedPush = ann.requireSignedPush();
    } else {
      // Defaults should match TestProjectConfig, omitting nullable values.
      in.createEmptyCommit = true;
    }
    updateProjectInput(in);
    return in;
  }

  /**
   * Modify a project input before creating the initial test project.
   *
   * @param in input; may be modified in place.
   */
  protected void updateProjectInput(ProjectInput in) {
    // Default implementation does nothing.
  }

  public static final Pattern UNSAFE_PROJECT_NAME = Pattern.compile("[^a-zA-Z0-9._/-]+");

  protected Git git() {
    return testRepo.git();
  }

  protected InMemoryRepository repo() {
    return testRepo.getRepository();
  }

  /**
   * Return a resource name scoped to this test method.
   *
   * <p>Test methods in a single class by default share a running server. For any resource name you
   * require to be unique to a test method, wrap it in a call to this method.
   *
   * @param name resource name (group, project, topic, etc.)
   * @return name prefixed by a string unique to this test method.
   */
  protected String name(String name) {
    return daemonTestRule.name(name);
  }

  @CanIgnoreReturnValue
  protected Project.NameKey createProjectOverAPI(
      String nameSuffix,
      @Nullable Project.NameKey parent,
      boolean createEmptyCommit,
      @Nullable SubmitType submitType)
      throws RestApiException {
    ProjectInput in = new ProjectInput();
    in.name = name(nameSuffix);
    in.parent = parent != null ? parent.get() : null;
    in.submitType = submitType;
    in.createEmptyCommit = createEmptyCommit;
    gApi.projects().create(in);
    return Project.nameKey(in.name);
  }

  protected TestRepository<InMemoryRepository> cloneProject(Project.NameKey p) throws Exception {
    return cloneProject(p, admin);
  }

  protected TestRepository<InMemoryRepository> cloneProject(
      Project.NameKey p, TestAccount testAccount) throws Exception {
    return daemonTestRule.cloneProject(p, testAccount);
  }

  /**
   * Register a repository connection over the test protocol.
   *
   * @return a URI string that can be used to connect to this repository for both fetch and push.
   */
  String registerRepoConnection(Project.NameKey p, TestAccount testAccount) throws Exception {
    InProcessProtocol.Context ctx =
        new InProcessProtocol.Context(identifiedUserFactory, testAccount.id(), p);
    Repository repo = repoManager.openRepository(p);
    toClose.add(repo);
    return inProcessProtocol.register(ctx, repo).toString();
  }

  protected void afterTest() throws Exception {
    Transport.unregister(inProcessProtocol);
    for (Repository repo : toClose) {
      repo.close();
    }

    // Set useDefaultTicker in afterTest, so the next beforeTest will use the default ticker
    testTicker.useDefaultTicker();
  }

  /**
   * Verify that NoteDB commits do not persist user-sensitive information, by running checks for all
   * commits in {@link RefNames#changeMetaRef} for all changes, created during the test.
   *
   * <p>These tests prevent regression, assuming appropriate test coverage for new features. The
   * verification is disabled by default and can be enabled using {@link VerifyNoPiiInChangeNotes}
   * annotation either on test class or method.
   */
  protected void verifyNoAccountDetailsInChangeNotes() throws RestApiException, IOException {
    List<ChangeInfo> allChanges = gApi.changes().query().get();

    List<AccountState> allAccounts = accounts.all();
    for (ChangeInfo change : allChanges) {
      try (Repository repo = repoManager.openRepository(Project.nameKey(change.project))) {
        String metaRefName =
            RefNames.changeMetaRef(Change.Id.tryParse(change._number.toString()).get());
        ObjectId metaTip = repo.getRefDatabase().exactRef(metaRefName).getObjectId();
        ChangeNotesRevWalk revWalk = ChangeNotesCommit.newRevWalk(repo);
        revWalk.reset();
        revWalk.markStart(revWalk.parseCommit(metaTip));
        ChangeNotesCommit commit;
        while ((commit = revWalk.next()) != null) {
          String fullMessage = commit.getFullMessage();
          for (AccountState accountState : allAccounts) {
            Account account = accountState.account();
            assertThat(fullMessage).doesNotContain(account.getName());
            if (account.fullName() != null) {
              assertThat(fullMessage).doesNotContain(account.fullName());
            }
            if (account.displayName() != null) {
              assertThat(fullMessage).doesNotContain(account.displayName());
            }
            if (account.preferredEmail() != null) {
              assertThat(fullMessage).doesNotContain(account.preferredEmail());
            }
            if (accountState.userName().isPresent()) {
              assertThat(fullMessage).doesNotContain(accountState.userName().get());
            }
            ImmutableList<String> allEmails =
                accountState.externalIds().stream()
                    .map(ExternalId::email)
                    .filter(Objects::nonNull)
                    .collect(toImmutableList());
            for (String email : allEmails) {
              assertThat(fullMessage).doesNotContain(email);
            }
          }
        }
      }
    }
  }

  protected TestRepository<?>.CommitBuilder commitBuilder() throws Exception {
    return testRepo.branch("HEAD").commit().insertChangeId();
  }

  protected TestRepository<?>.CommitBuilder amendBuilder() throws Exception {
    ObjectId head = repo().exactRef("HEAD").getObjectId();
    TestRepository<?>.CommitBuilder b = testRepo.amendRef("HEAD");
    Optional<String> id = GitUtil.getChangeId(testRepo, head);
    // TestRepository behaves like "git commit --amend -m foo", which does not
    // preserve an existing Change-Id. Tests probably want this.
    if (id.isPresent()) {
      b.insertChangeId(id.get().substring(1));
    } else {
      b.insertChangeId();
    }
    return b;
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createChange() throws Exception {
    return createChange("refs/for/master");
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createChange(String ref) throws Exception {
    PushOneCommit push = pushFactory.create(admin.newIdent(), testRepo);
    PushOneCommit.Result result = push.to(ref);
    result.assertOkStatus();
    return result;
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createChange(TestRepository<InMemoryRepository> repo)
      throws Exception {
    PushOneCommit push = pushFactory.create(admin.newIdent(), repo);
    PushOneCommit.Result result = push.to("refs/for/master");
    result.assertOkStatus();
    return result;
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createMergeCommitChange(String ref) throws Exception {
    return createMergeCommitChange(ref, "foo");
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createMergeCommitChange(String ref, String file) throws Exception {
    ObjectId initial = repo().exactRef(HEAD).getLeaf().getObjectId();

    PushOneCommit.Result p1 =
        pushFactory
            .create(
                admin.newIdent(),
                testRepo,
                "parent 1",
                ImmutableMap.of(file, "foo-1", "bar", "bar-1"))
            .to(ref);

    // reset HEAD in order to create a sibling of the first change
    testRepo.reset(initial);

    PushOneCommit.Result p2 =
        pushFactory
            .create(
                admin.newIdent(),
                testRepo,
                "parent 2",
                ImmutableMap.of(file, "foo-2", "bar", "bar-2"))
            .to(ref);

    PushOneCommit m =
        pushFactory.create(
            admin.newIdent(), testRepo, "merge", ImmutableMap.of(file, "foo-1", "bar", "bar-2"));
    m.setParents(ImmutableList.of(p1.getCommit(), p2.getCommit()));
    PushOneCommit.Result result = m.to(ref);
    result.assertOkStatus();
    return result;
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createNParentsMergeCommitChange(String ref, List<String> fileNames)
      throws Exception {
    // This method creates n different commits and creates a merge commit pointing to all n parents.
    // Each commit will contain all the fileNames. Commit i will have the following file names and
    // their contents:
    // {$file_1_name, ${file_1_name}-1}
    // {$file_2_name, ${file_2_name}-1}, etc...
    // The merge commit will have:
    // {$file_1_name, ${file_1_name}-1}
    // {$file_2_name, ${file_2_name}-2},
    // {$file_3_name, ${file_3_name}-3}, etc...
    // i.e. taking the ith file from the ith commit.
    int n = fileNames.size();
    ObjectId initial = repo().exactRef(HEAD).getLeaf().getObjectId();

    List<PushOneCommit.Result> pushResults = new ArrayList<>();

    for (int i = 1; i <= n; i++) {
      int finalI = i;
      pushResults.add(
          pushFactory
              .create(
                  admin.newIdent(),
                  testRepo,
                  "parent " + i,
                  fileNames.stream().collect(Collectors.toMap(f -> f, f -> f + "-" + finalI)))
              .to(ref));

      // reset HEAD in order to create a sibling of the first change
      if (i < n) {
        testRepo.reset(initial);
      }
    }

    PushOneCommit m =
        pushFactory.create(
            admin.newIdent(),
            testRepo,
            "merge",
            IntStream.range(1, n + 1)
                .boxed()
                .collect(
                    Collectors.toMap(
                        i -> fileNames.get(i - 1), i -> fileNames.get(i - 1) + "-" + i)));

    m.setParents(pushResults.stream().map(PushOneCommit.Result::getCommit).collect(toList()));
    PushOneCommit.Result result = m.to(ref);
    result.assertOkStatus();
    return result;
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createCommitAndPush(
      TestRepository<InMemoryRepository> repo,
      String ref,
      String commitMsg,
      String fileName,
      String content)
      throws Exception {
    PushOneCommit.Result result =
        pushFactory.create(admin.newIdent(), repo, commitMsg, fileName, content).to(ref);
    result.assertOkStatus();
    return result;
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createChangeWithTopic(
      TestRepository<InMemoryRepository> repo,
      String topic,
      String commitMsg,
      String fileName,
      String content)
      throws Exception {
    assertThat(topic).isNotEmpty();
    return createCommitAndPush(
        repo, "refs/for/master%topic=" + name(topic), commitMsg, fileName, content);
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createChange(String subject, String fileName, String content)
      throws Exception {
    PushOneCommit push = pushFactory.create(admin.newIdent(), testRepo, subject, fileName, content);
    return push.to("refs/for/master");
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result createChange(
      TestRepository<?> repo,
      String branch,
      String subject,
      String fileName,
      String content,
      @Nullable String topic)
      throws Exception {
    PushOneCommit push = pushFactory.create(admin.newIdent(), repo, subject, fileName, content);
    return push.to(
        "refs/for/" + branch + (Strings.isNullOrEmpty(topic) ? "" : "%topic=" + name(topic)));
  }

  @CanIgnoreReturnValue
  protected BranchApi createBranch(BranchNameKey branch) throws Exception {
    return gApi.projects()
        .name(branch.project().get())
        .branch(branch.branch())
        .create(new BranchInput());
  }

  @CanIgnoreReturnValue
  protected BranchApi createBranchWithRevision(BranchNameKey branch, String revision)
      throws Exception {
    BranchInput in = new BranchInput();
    in.revision = revision;
    return gApi.projects().name(branch.project().get()).branch(branch.branch()).create(in);
  }

  private static final List<Character> RANDOM =
      Chars.asList('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');

  @CanIgnoreReturnValue
  protected PushOneCommit.Result amendChangeWithUploader(
      PushOneCommit.Result change, Project.NameKey projectName, TestAccount account)
      throws Exception {
    TestRepository<InMemoryRepository> repo = cloneProject(projectName, account);
    GitUtil.fetch(repo, "refs/*:refs/*");
    repo.reset(change.getCommit());
    PushOneCommit.Result result =
        amendChange(
            change.getChangeId(),
            "refs/for/master",
            account,
            repo,
            "new subject",
            "new file",
            "new content " + UUID.randomUUID());
    return result;
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result amendChange(String changeId) throws Exception {
    return amendChange(changeId, "refs/for/master", admin, testRepo);
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result amendChange(
      String changeId, String ref, TestAccount testAccount, TestRepository<?> repo)
      throws Exception {
    Collections.shuffle(RANDOM);
    return amendChange(
        changeId,
        ref,
        testAccount,
        repo,
        PushOneCommit.SUBJECT,
        PushOneCommit.FILE_NAME,
        new String(Chars.toArray(RANDOM)));
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result amendChange(
      String changeId, String subject, String fileName, String content) throws Exception {
    return amendChange(changeId, "refs/for/master", admin, testRepo, subject, fileName, content);
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result amendChange(
      String changeId,
      String ref,
      TestAccount testAccount,
      TestRepository<?> repo,
      String subject,
      String fileName,
      String content)
      throws Exception {
    PushOneCommit push =
        pushFactory.create(testAccount.newIdent(), repo, subject, fileName, content, changeId);
    return push.to(ref);
  }

  protected void merge(PushOneCommit.Result r) throws Exception {
    revision(r).review(ReviewInput.approve());
    revision(r).submit();
  }

  protected ChangeInfo info(String id) throws RestApiException {
    return gApi.changes().id(id).info();
  }

  protected ChangeApi change(Result r) throws RestApiException {
    return gApi.changes().id(r.getChange().getId().get());
  }

  protected Optional<EditInfo> getEdit(String id) throws RestApiException {
    return gApi.changes().id(id).edit().get();
  }

  protected ChangeInfo get(String id, ListChangesOption... options) throws RestApiException {
    return gApi.changes().id(id).get(options);
  }

  protected AccountInfo getAccountInfo(Account.Id accountId) throws RestApiException {
    return gApi.accounts().id(accountId.get()).get();
  }

  protected List<ChangeInfo> query(String q) throws RestApiException {
    return gApi.changes().query(q).get();
  }

  protected Account getAccount(Account.Id accountId) {
    return getAccountState(accountId).account();
  }

  protected AccountState getAccountState(Account.Id accountId) {
    Optional<AccountState> accountState = accountCache.get(accountId);
    assertWithMessage("account %s", accountId.get())
        .about(optionals())
        .that(accountState)
        .isPresent();
    return accountState.get();
  }

  protected AutoCloseable disableNoteDb() {
    changeNotesArgs.failOnLoadForTest.set(true);
    return () -> {
      changeNotesArgs.failOnLoadForTest.set(false);
    };
  }

  protected static Gson newGson() {
    return OutputFormat.JSON_COMPACT.newGson();
  }

  protected RevisionApi revision(PushOneCommit.Result r) throws Exception {
    return gApi.changes().id(r.getChangeId()).current();
  }

  protected void setUseSignedOffBy(InheritableBoolean value) throws Exception {
    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
      ProjectConfig config = projectConfigFactory.read(md);
      config.updateProject(p -> p.setBooleanConfig(BooleanProjectConfig.USE_SIGNED_OFF_BY, value));
      config.commit(md);
      projectCache.evictAndReindex(config.getProject());
    }
  }

  protected void setRequireChangeId(InheritableBoolean value) throws Exception {
    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
      ProjectConfig config = projectConfigFactory.read(md);
      config.updateProject(p -> p.setBooleanConfig(BooleanProjectConfig.REQUIRE_CHANGE_ID, value));
      config.commit(md);
      projectCache.evictAndReindex(config.getProject());
    }
  }

  protected void setSkipAddingAuthorAndCommitterAsReviewers(InheritableBoolean value)
      throws Exception {
    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
      ProjectConfig config = projectConfigFactory.read(md);
      config.updateProject(
          p ->
              p.setBooleanConfig(
                  BooleanProjectConfig.SKIP_ADDING_AUTHOR_AND_COMMITTER_AS_REVIEWERS, value));
      config.commit(md);
      projectCache.evictAndReindex(config.getProject());
    }
  }

  protected void blockAnonymousRead() throws Exception {
    String allRefs = RefNames.REFS + "*";
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(Permission.READ).ref(allRefs).group(ANONYMOUS_USERS))
        .add(allow(Permission.READ).ref(allRefs).group(REGISTERED_USERS))
        .update();
  }

  @CanIgnoreReturnValue
  protected PushOneCommit.Result pushTo(String ref) throws Exception {
    PushOneCommit push = pushFactory.create(admin.newIdent(), testRepo);
    return push.to(ref);
  }

  protected void approve(String id) throws Exception {
    gApi.changes().id(id).current().review(ReviewInput.approve());
  }

  protected void recommend(String id) throws Exception {
    gApi.changes().id(id).current().review(ReviewInput.recommend());
  }

  protected void assertThatAccountIsNotVisible(TestAccount... testAccounts) {
    for (TestAccount testAccount : testAccounts) {
      assertThrows(
          ResourceNotFoundException.class, () -> gApi.accounts().id(testAccount.id().get()).get());
    }
  }

  protected void assertReviewers(String changeId, TestAccount... expectedReviewers)
      throws RestApiException {
    Map<ReviewerState, Collection<AccountInfo>> reviewerMap =
        gApi.changes().id(changeId).get().reviewers;
    assertThat(reviewerMap).containsKey(ReviewerState.REVIEWER);
    List<Integer> reviewers =
        reviewerMap.get(ReviewerState.REVIEWER).stream().map(a -> a._accountId).collect(toList());
    assertThat(reviewers)
        .containsExactlyElementsIn(
            Arrays.stream(expectedReviewers).map(a -> a.id().get()).collect(toList()));
  }

  protected void assertCcs(String changeId, TestAccount... expectedCcs) throws RestApiException {
    Map<ReviewerState, Collection<AccountInfo>> reviewerMap =
        gApi.changes().id(changeId).get().reviewers;
    assertThat(reviewerMap).containsKey(ReviewerState.CC);
    List<Integer> ccs =
        reviewerMap.get(ReviewerState.CC).stream().map(a -> a._accountId).collect(toList());
    assertThat(ccs)
        .containsExactlyElementsIn(
            Arrays.stream(expectedCcs).map(a -> a.id().get()).collect(toList()));
  }

  protected void assertNoCcs(String changeId) throws RestApiException {
    Map<ReviewerState, Collection<AccountInfo>> reviewerMap =
        gApi.changes().id(changeId).get().reviewers;
    assertThat(reviewerMap).doesNotContainKey(ReviewerState.CC);
  }

  protected void assertSubmittedTogether(String chId, String... expected) throws Exception {
    assertSubmittedTogether(chId, ImmutableSet.of(), expected);
  }

  protected void assertSubmittedTogetherWithTopicClosure(String chId, String... expected)
      throws Exception {
    assertSubmittedTogether(chId, ImmutableSet.of(TOPIC_CLOSURE), expected);
  }

  protected void assertSubmittedTogether(
      String chId,
      ImmutableSet<SubmittedTogetherOption> submittedTogetherOptions,
      String... expected)
      throws Exception {
    // This does not include NON_VISIBILE_CHANGES
    List<ChangeInfo> actual =
        submittedTogetherOptions.isEmpty()
            ? gApi.changes().id(chId).submittedTogether()
            : gApi.changes()
                .id(chId)
                .submittedTogether(EnumSet.copyOf(submittedTogetherOptions))
                .changes;

    EnumSet<SubmittedTogetherOption> enumSetIncludingNonVisibleChanges =
        submittedTogetherOptions.isEmpty()
            ? EnumSet.of(NON_VISIBLE_CHANGES)
            : EnumSet.copyOf(submittedTogetherOptions);
    enumSetIncludingNonVisibleChanges.add(NON_VISIBLE_CHANGES);

    // This includes NON_VISIBLE_CHANGES for comparison.
    SubmittedTogetherInfo info =
        gApi.changes().id(chId).submittedTogether(enumSetIncludingNonVisibleChanges);

    assertThat(info.nonVisibleChanges).isEqualTo(0);
    assertThat(Iterables.transform(actual, i1 -> i1.changeId))
        .containsExactly((Object[]) expected)
        .inOrder();
    assertThat(Iterables.transform(info.changes, i -> i.changeId))
        .containsExactly((Object[]) expected)
        .inOrder();
  }

  protected PatchSet getPatchSet(PatchSet.Id psId) {
    return changeDataFactory.create(project, psId.changeId()).patchSet(psId);
  }

  protected IdentifiedUser user(TestAccount testAccount) {
    return identifiedUserFactory.create(testAccount.id());
  }

  protected RevisionResource parseCurrentRevisionResource(String changeId) throws Exception {
    ChangeResource cr = parseChangeResource(changeId);
    int psId = cr.getChange().currentPatchSetId().get();
    return revisions.parse(cr, IdString.fromDecoded(Integer.toString(psId)));
  }

  protected RevisionResource parseRevisionResource(String changeId, int n) throws Exception {
    return revisions.parse(
        parseChangeResource(changeId), IdString.fromDecoded(Integer.toString(n)));
  }

  protected RevisionResource parseRevisionResource(PushOneCommit.Result r) throws Exception {
    PatchSet.Id psId = r.getPatchSetId();
    return parseRevisionResource(psId.changeId().toString(), psId.get());
  }

  protected ChangeResource parseChangeResource(String changeId) throws Exception {
    List<ChangeNotes> notes = changeFinder.find(changeId);
    assertThat(notes).hasSize(1);
    return changeResourceFactory.create(notes.get(0), localCtx.getContext().getUser());
  }

  protected RevCommit getHead(Repository repo, String name) throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      Ref r = repo.exactRef(name);
      return rw.parseCommit(r.getObjectId());
    }
  }

  protected void assertMailReplyTo(Message message, String email) throws Exception {
    assertThat(message.headers()).containsKey("Reply-To");
    StringEmailHeader replyTo = (StringEmailHeader) message.headers().get("Reply-To");
    assertThat(replyTo.getString()).contains(email);
  }

  protected void assertMailNotReplyTo(Message message, String email) throws Exception {
    assertThat(message.headers()).containsKey("Reply-To");
    StringEmailHeader replyTo = (StringEmailHeader) message.headers().get("Reply-To");
    assertThat(replyTo.getString()).doesNotContain(email);
  }

  /** Assert that the given branches have the given tree ids. */
  protected void assertTrees(Project.NameKey proj, Map<BranchNameKey, ObjectId> trees)
      throws Exception {
    TestRepository<?> localRepo = cloneProject(proj);
    GitUtil.fetch(localRepo, "refs/*:refs/*");
    Map<BranchNameKey, RevTree> refValues = new HashMap<>();

    for (BranchNameKey b : trees.keySet()) {
      if (!b.project().equals(proj)) {
        continue;
      }

      Ref r = localRepo.getRepository().exactRef(b.branch());
      assertThat(r).isNotNull();
      RevWalk rw = localRepo.getRevWalk();
      RevCommit c = rw.parseCommit(r.getObjectId());
      refValues.put(b, c.getTree());

      assertThat(trees.get(b)).isEqualTo(refValues.get(b));
    }
    assertThat(refValues.keySet()).containsAnyIn(trees.keySet());
  }

  protected void assertDiffForFullyModifiedFile(
      DiffInfo diff,
      String commitName,
      String path,
      String expectedContentSideA,
      String expectedContentSideB)
      throws Exception {
    assertDiffForFile(diff, commitName, path);

    ImmutableList<String> expectedOldLines =
        ImmutableList.copyOf(expectedContentSideA.split("\n", -1));
    ImmutableList<String> expectedNewLines =
        ImmutableList.copyOf(expectedContentSideB.split("\n", -1));

    assertThat(diff.changeType).isEqualTo(ChangeType.MODIFIED);

    assertThat(diff.metaA).isNotNull();
    assertThat(diff.metaB).isNotNull();

    assertThat(diff.metaA.name).isEqualTo(path);
    assertThat(diff.metaA.lines).isEqualTo(expectedOldLines.size());
    assertThat(diff.metaB.name).isEqualTo(path);
    assertThat(diff.metaB.lines).isEqualTo(expectedNewLines.size());

    DiffInfo.ContentEntry contentEntry = diff.content.get(0);
    assertThat(contentEntry.a).containsExactlyElementsIn(expectedOldLines).inOrder();
    assertThat(contentEntry.b).containsExactlyElementsIn(expectedNewLines).inOrder();
    assertThat(contentEntry.ab).isNull();
    assertThat(contentEntry.common).isNull();
    assertThat(contentEntry.editA).isNull();
    assertThat(contentEntry.editB).isNull();
    assertThat(contentEntry.skip).isNull();
  }

  protected void assertDiffForNewFile(
      DiffInfo diff, @Nullable RevCommit commit, String path, String expectedContentSideB)
      throws Exception {
    assertDiffForNewFile(diff, commit.name(), path, expectedContentSideB);
  }

  protected void assertDiffForNewFile(
      DiffInfo diff, String commitName, String path, String expectedContentSideB) throws Exception {
    assertDiffForFile(diff, commitName, path);

    ImmutableList<String> expectedLines =
        ImmutableList.copyOf(expectedContentSideB.split("\n", -1));

    assertThat(diff.changeType).isEqualTo(ChangeType.ADDED);

    assertThat(diff.metaA).isNull();
    assertThat(diff.metaB).isNotNull();

    assertThat(diff.metaB.name).isEqualTo(path);
    assertThat(diff.metaB.lines).isEqualTo(expectedLines.size());

    DiffInfo.ContentEntry contentEntry = diff.content.get(0);
    assertThat(contentEntry.b).containsExactlyElementsIn(expectedLines).inOrder();
    assertThat(contentEntry.a).isNull();
    assertThat(contentEntry.ab).isNull();
    assertThat(contentEntry.common).isNull();
    assertThat(contentEntry.editA).isNull();
    assertThat(contentEntry.editB).isNull();
    assertThat(contentEntry.skip).isNull();
  }

  protected void assertDiffForDeletedFile(DiffInfo diff, String path, String expectedContentSideA)
      throws Exception {
    assertDiffHeaders(diff);

    ImmutableList<String> expectedOriginalLines =
        ImmutableList.copyOf(expectedContentSideA.split("\n", -1));

    assertThat(diff.changeType).isEqualTo(ChangeType.DELETED);

    assertThat(diff.metaA).isNotNull();
    assertThat(diff.metaB).isNull();

    assertThat(diff.metaA.name).isEqualTo(path);
    assertThat(diff.metaA.lines).isEqualTo(expectedOriginalLines.size());

    DiffInfo.ContentEntry contentEntry = diff.content.get(0);
    assertThat(contentEntry.a).containsExactlyElementsIn(expectedOriginalLines).inOrder();
    assertThat(contentEntry.b).isNull();
    assertThat(contentEntry.ab).isNull();
    assertThat(contentEntry.common).isNull();
    assertThat(contentEntry.editA).isNull();
    assertThat(contentEntry.editB).isNull();
    assertThat(contentEntry.skip).isNull();
  }

  private void assertDiffForFile(DiffInfo diff, String commitName, String path) throws Exception {
    assertDiffHeaders(diff);

    assertThat(diff.metaB.commitId).isEqualTo(commitName);

    String expectedContentType = "text/plain";
    if (COMMIT_MSG.equals(path)) {
      expectedContentType = FileContentUtil.TEXT_X_GERRIT_COMMIT_MESSAGE;
    } else if (MERGE_LIST.equals(path)) {
      expectedContentType = FileContentUtil.TEXT_X_GERRIT_MERGE_LIST;
    }

    assertThat(diff.metaB.contentType).isEqualTo(expectedContentType);

    assertThat(diff.metaB.name).isEqualTo(path);
    assertThat(diff.metaB.webLinks).isNull();
  }

  private void assertDiffHeaders(DiffInfo diff) throws Exception {
    assertThat(diff.binary).isNull();
    assertThat(diff.diffHeader).isNotNull();
    assertThat(diff.intralineStatus).isNull();
    assertThat(diff.webLinks).isNull();
    assertThat(diff.editWebLinks).isNull();
  }

  protected void assertPermitted(ChangeInfo info, String label, Integer... expected) {
    assertThat(info.permittedLabels).isNotNull();
    Collection<String> strs = info.permittedLabels.get(label);
    if (expected.length == 0) {
      assertThat(strs).isNull();
    } else {
      assertThat(strs.stream().map(s -> Integer.valueOf(s.trim())).collect(toList()))
          .containsExactlyElementsIn(Arrays.asList(expected));
    }
  }

  protected void assertOnlyRemovableLabel(
      ChangeInfo info, String labelId, String labelValue, TestAccount reviewer) {
    assertThat(info.removableLabels).hasSize(1);
    assertThat(info.removableLabels).containsKey(labelId);
    assertThat(info.removableLabels.get(labelId)).hasSize(1);
    assertThat(info.removableLabels.get(labelId)).containsKey(labelValue);
    assertThat(info.removableLabels.get(labelId).get(labelValue)).hasSize(1);
    assertThat(info.removableLabels.get(labelId).get(labelValue).get(0).email)
        .isEqualTo(reviewer.email());
  }

  protected void assertPermissions(
      Project.NameKey project,
      GroupReference groupReference,
      String ref,
      boolean exclusive,
      String... permissionNames) {
    Optional<AccessSection> accessSection =
        projectCache
            .get(project)
            .orElseThrow(illegalState(project))
            .getConfig()
            .getAccessSection(ref);
    assertThat(accessSection).isPresent();
    for (String permissionName : permissionNames) {
      Permission permission = accessSection.get().getPermission(permissionName);
      assertPermission(permission, permissionName, exclusive, null);
      assertPermissionRule(
          permission.getRule(groupReference), groupReference, Action.ALLOW, false, 0, 0);
    }
  }

  protected void assertPermission(
      Permission permission,
      String expectedName,
      boolean expectedExclusive,
      @Nullable String expectedLabelName) {
    assertThat(permission).isNotNull();
    assertThat(permission.getName()).isEqualTo(expectedName);
    assertThat(permission.getExclusiveGroup()).isEqualTo(expectedExclusive);
    assertThat(permission.getLabel()).isEqualTo(expectedLabelName);
  }

  protected void assertPermissionRule(
      PermissionRule rule,
      GroupReference expectedGroupReference,
      Action expectedAction,
      boolean expectedForce,
      int expectedMin,
      int expectedMax) {
    assertThat(rule.getGroup()).isEqualTo(expectedGroupReference);
    assertThat(rule.getAction()).isEqualTo(expectedAction);
    assertThat(rule.getForce()).isEqualTo(expectedForce);
    assertThat(rule.getMin()).isEqualTo(expectedMin);
    assertThat(rule.getMax()).isEqualTo(expectedMax);
  }

  protected void assertHead(String projectName, String expectedRef) throws Exception {
    // Assert gerrit's project head points to the correct branch
    assertThat(getProjectBranches(projectName).get(Constants.HEAD).revision)
        .isEqualTo(RefNames.shortName(expectedRef));
    // Assert git head points to the correct branch
    try (Repository repo = repoManager.openRepository(Project.nameKey(projectName))) {
      assertThat(repo.exactRef(Constants.HEAD).getTarget().getName()).isEqualTo(expectedRef);
    }
  }

  protected InternalGroup group(AccountGroup.UUID groupUuid) {
    InternalGroup group = groupCache.get(groupUuid).orElse(null);
    assertWithMessage(groupUuid.get()).that(group).isNotNull();
    return group;
  }

  protected GroupReference groupRef(AccountGroup.UUID groupUuid) {
    GroupDescription.Basic groupDescription = groupBackend.get(groupUuid);
    return GroupReference.create(groupDescription.getGroupUUID(), groupDescription.getName());
  }

  protected InternalGroup group(String groupName) {
    InternalGroup group = groupCache.get(AccountGroup.nameKey(groupName)).orElse(null);
    assertWithMessage(groupName).that(group).isNotNull();
    return group;
  }

  protected GroupReference groupRef(String groupName) {
    InternalGroup group = groupCache.get(AccountGroup.nameKey(groupName)).orElse(null);
    assertThat(group).isNotNull();
    return GroupReference.create(group.getGroupUUID(), group.getName());
  }

  protected AccountGroup.UUID groupUuid(String groupName) {
    return group(groupName).getGroupUUID();
  }

  protected InternalGroup adminGroup() {
    return group("Administrators");
  }

  protected GroupReference adminGroupRef() {
    return groupRef("Administrators");
  }

  protected AccountGroup.UUID adminGroupUuid() {
    return groupUuid("Administrators");
  }

  protected void assertGroupDoesNotExist(String groupName) {
    InternalGroup group = groupCache.get(AccountGroup.nameKey(groupName)).orElse(null);
    assertWithMessage(groupName).that(group).isNull();
  }

  protected void assertNotifyTo(TestAccount expected) {
    assertNotifyTo(expected.email(), expected.fullName());
  }

  protected void assertNotifyTo(String expectedEmail, String expectedFullname) {
    Address expectedAddress = Address.create(expectedFullname, expectedEmail);
    assertThat(sender.getMessages()).hasSize(1);
    Message m = sender.getMessages().get(0);
    assertThat(m.rcpt()).containsExactly(expectedAddress);
    assertThat(((EmailHeader.AddressList) m.headers().get("To")).getAddressList())
        .containsExactly(expectedAddress);
    assertThat(m.headers().get("Cc").isEmpty()).isTrue();
  }

  protected void assertNotifyCc(TestAccount expected) {
    assertNotifyCc(expected.getNameEmail());
  }

  protected void assertNotifyCc(String expectedEmail, String expectedFullname) {
    Address expectedAddress = Address.create(expectedFullname, expectedEmail);
    assertNotifyCc(expectedAddress);
  }

  protected void assertNotifyCc(Address expectedAddress) {
    assertThat(sender.getMessages()).hasSize(1);
    Message m = sender.getMessages().get(0);
    assertThat(m.rcpt()).containsExactly(expectedAddress);
    assertThat(m.headers().get("To").isEmpty()).isTrue();
    assertThat(((EmailHeader.AddressList) m.headers().get("Cc")).getAddressList())
        .containsExactly(expectedAddress);
  }

  protected void assertNotifyBcc(TestAccount expected) {
    assertThat(sender.getMessages()).hasSize(1);
    Message m = sender.getMessages().get(0);
    assertThat(m.rcpt()).containsExactly(expected.getNameEmail());
    assertThat(m.headers().get("To").isEmpty()).isTrue();
    assertThat(m.headers().get("Cc").isEmpty()).isTrue();
  }

  protected void assertNotifyBcc(String expectedEmail, String expectedFullName) {
    assertThat(sender.getMessages()).hasSize(1);
    Message m = sender.getMessages().get(0);
    assertThat(m.rcpt()).containsExactly(Address.create(expectedFullName, expectedEmail));
    assertThat(m.headers().get("To").isEmpty()).isTrue();
    assertThat(m.headers().get("Cc").isEmpty()).isTrue();
  }

  protected interface ProjectWatchInfoConfiguration {
    void configure(ProjectWatchInfo pwi);
  }

  protected void watch(String project, ProjectWatchInfoConfiguration config)
      throws RestApiException {
    ProjectWatchInfo pwi = new ProjectWatchInfo();
    pwi.project = project;
    config.configure(pwi);
    gApi.accounts().self().setWatchedProjects(ImmutableList.of(pwi));
  }

  protected void watch(PushOneCommit.Result r, ProjectWatchInfoConfiguration config)
      throws RestApiException {
    watch(r.getChange().project().get(), config);
  }

  protected void watch(String project, String filter) throws RestApiException {
    watch(
        project,
        pwi -> {
          pwi.filter = filter;
          pwi.notifyAbandonedChanges = true;
          pwi.notifyNewChanges = true;
          pwi.notifyNewPatchSets = true;
          pwi.notifyAllComments = true;
        });
  }

  protected void watch(String project) throws RestApiException {
    watch(project, (String) null);
  }

  protected void assertContent(PushOneCommit.Result pushResult, String path, String expectedContent)
      throws Exception {
    BinaryResult bin =
        gApi.changes()
            .id(pushResult.getChangeId())
            .revision(pushResult.getCommit().name())
            .file(path)
            .content();
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    bin.writeTo(os);
    String res = new String(os.toByteArray(), UTF_8);
    assertThat(res).isEqualTo(expectedContent);
  }

  protected void assertLastCommitAuthorAndShortMessage(
      String refName, String expectedAuthor, String expectedShortMessage) throws Exception {
    try (Repository repo = repoManager.openRepository(project);
        RevWalk rw = new RevWalk(repo)) {
      Ref exactRef = repo.exactRef(refName);
      RevCommit revCommit = rw.parseCommit(exactRef.getObjectId());
      assertThat(revCommit.getAuthorIdent().getName()).isEqualTo(expectedAuthor);
      assertThat(revCommit.getShortMessage()).isEqualTo(expectedShortMessage);
    }
  }

  @CanIgnoreReturnValue
  protected RevCommit createNewCommitWithoutChangeId(String branch, String file, String content)
      throws Exception {
    try (Repository repo = repoManager.openRepository(project);
        RevWalk walk = new RevWalk(repo)) {
      Ref ref = repo.exactRef(branch);
      RevCommit tip = null;
      if (ref != null) {
        tip = walk.parseCommit(ref.getObjectId());
      }
      TestRepository<?> testSrcRepo = new TestRepository<>(repo);
      TestRepository<?>.BranchBuilder builder = testSrcRepo.branch(branch);
      RevCommit revCommit =
          tip == null
              ? builder.commit().message("commit 1").add(file, content).create()
              : builder.commit().parent(tip).message("commit 1").add(file, content).create();
      assertThat(GitUtil.getChangeId(testSrcRepo, revCommit)).isEmpty();
      return revCommit;
    }
  }

  protected RevCommit parseCurrentRevision(RevWalk rw, String changeId) throws Exception {
    return rw.parseCommit(
        ObjectId.fromString(get(changeId, ListChangesOption.CURRENT_REVISION).currentRevision));
  }

  /** Creates a submit requirement with all required field. */
  protected void configSubmitRequirement(Project.NameKey project, String name) throws Exception {
    configSubmitRequirement(
        project,
        SubmitRequirement.builder()
            .setName(name)
            .setAllowOverrideInChildProjects(true)
            .setSubmittabilityExpression(
                SubmitRequirementExpression.create("-label:Code-Review=MIN"))
            .build());
  }

  protected void configSubmitRequirement(
      Project.NameKey project, SubmitRequirement submitRequirement) throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().upsertSubmitRequirement(submitRequirement);
      u.save();
    }
  }

  protected void clearSubmitRequirements(Project.NameKey project) throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig().clearSubmitRequirements();
      u.save();
    }
  }

  protected void configLabel(String label, LabelFunction func) throws Exception {
    configLabel(label, func, ImmutableList.of());
  }

  protected void configLabel(String label, LabelFunction func, List<String> refPatterns)
      throws Exception {
    configLabel(
        project,
        label,
        func,
        refPatterns,
        value(1, "Passes"),
        value(0, "No score"),
        value(-1, "Failed"));
  }

  protected void configLabel(
      Project.NameKey project, String label, LabelFunction func, LabelValue... value)
      throws Exception {
    configLabel(project, label, func, ImmutableList.of(), value);
  }

  @SuppressWarnings("deprecation")
  private void configLabel(
      Project.NameKey project,
      String label,
      LabelFunction func,
      List<String> refPatterns,
      LabelValue... value)
      throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      LabelType.Builder labelType = label(label, value).toBuilder();
      labelType.setFunction(func);
      labelType.setRefPatterns(ImmutableList.copyOf(refPatterns));
      u.getConfig().upsertLabelType(labelType.build());
      u.save();
    }
  }

  protected void enableCreateNewChangeForAllNotInTarget() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig()
          .updateProject(
              p ->
                  p.setBooleanConfig(
                      BooleanProjectConfig.CREATE_NEW_CHANGE_FOR_ALL_NOT_IN_TARGET,
                      InheritableBoolean.TRUE));
      u.save();
    }
  }

  protected ProjectConfigUpdate updateProject(Project.NameKey projectName) throws Exception {
    return new ProjectConfigUpdate(projectName);
  }

  public class ProjectConfigUpdate implements AutoCloseable {
    private final ProjectConfig projectConfig;
    private MetaDataUpdate metaDataUpdate;

    private ProjectConfigUpdate(Project.NameKey projectName) throws Exception {
      metaDataUpdate = metaDataUpdateFactory.create(projectName);
      projectConfig = projectConfigFactory.read(metaDataUpdate);
    }

    public ProjectConfig getConfig() {
      return projectConfig;
    }

    public void save() throws Exception {
      testRefAction(
          () -> {
            metaDataUpdate.setAuthor(identifiedUserFactory.create(admin.id()));
            projectConfig.commit(metaDataUpdate);
            metaDataUpdate.close();
            metaDataUpdate = null;
            projectCache.evictAndReindex(projectConfig.getProject());
          });
    }

    @Override
    public void close() {
      if (metaDataUpdate != null) {
        metaDataUpdate.close();
      }
    }
  }

  protected List<RevCommit> getChangeMetaCommitsInReverseOrder(Change.Id changeId)
      throws IOException {
    try (Repository repo = repoManager.openRepository(project);
        RevWalk revWalk = new RevWalk(repo)) {
      revWalk.sort(RevSort.TOPO);
      revWalk.sort(RevSort.REVERSE);
      Ref metaRef = repo.exactRef(RefNames.changeMetaRef(changeId));
      revWalk.markStart(revWalk.parseCommit(metaRef.getObjectId()));
      return Lists.newArrayList(revWalk);
    }
  }

  protected List<CommentInfo> getChangeSortedComments(int changeNum) throws Exception {
    List<CommentInfo> comments = new ArrayList<>();
    Map<String, List<CommentInfo>> commentsMap =
        gApi.changes().id(changeNum).commentsRequest().get();
    for (Map.Entry<String, List<CommentInfo>> e : commentsMap.entrySet()) {
      for (CommentInfo c : e.getValue()) {
        c.path = e.getKey(); // Set the comment's path field.
        comments.add(c);
      }
    }
    comments.sort(Comparator.comparing(c -> c.id));
    return comments;
  }

  protected ImmutableMap<String, BranchInfo> getProjectBranches(String projectName)
      throws RestApiException {
    return gApi.projects().name(projectName).branches().get().stream()
        .collect(ImmutableMap.toImmutableMap(branch -> branch.ref, branch -> branch));
  }

  protected void createRefLogFileIfMissing(Repository repo, String ref) throws IOException {
    File log = new File(repo.getDirectory(), "logs/" + ref);
    if (!log.exists()) {
      log.getParentFile().mkdirs();
      assertThat(log.createNewFile()).isTrue();
    }
  }

  protected AutoCloseable installPlugin(String pluginName, Class<? extends Module> sysModuleClass)
      throws Exception {
    return installPlugin(pluginName, sysModuleClass, null, null);
  }

  protected AutoCloseable installPlugin(
      String pluginName,
      @Nullable Class<? extends Module> sysModuleClass,
      @Nullable Class<? extends Module> httpModuleClass,
      @Nullable Class<? extends Module> sshModuleClass)
      throws Exception {
    return installPlugin(pluginName, sysModuleClass, httpModuleClass, sshModuleClass, null);
  }

  protected AutoCloseable installPlugin(
      String pluginName,
      @Nullable Class<? extends Module> sysModuleClass,
      @Nullable Class<? extends Module> httpModuleClass,
      @Nullable Class<? extends Module> sshModuleClass,
      PluginContentScanner scanner)
      throws Exception {
    checkStatic(sysModuleClass);
    checkStatic(httpModuleClass);
    checkStatic(sshModuleClass);
    TestServerPlugin plugin =
        new TestServerPlugin(
            pluginName,
            "http://example.com/" + pluginName,
            pluginUserFactory.create(pluginName),
            scanner,
            getClass().getClassLoader(),
            sysModuleClass != null ? sysModuleClass.getName() : null,
            httpModuleClass != null ? httpModuleClass.getName() : null,
            sshModuleClass != null ? sshModuleClass.getName() : null,
            sitePaths.data_dir.resolve(pluginName));
    plugin.start(pluginGuiceEnvironment);
    pluginGuiceEnvironment.onStartPlugin(plugin);
    return () -> {
      plugin.stop(pluginGuiceEnvironment);
      pluginGuiceEnvironment.onStopPlugin(plugin);
    };
  }

  private static void checkStatic(@Nullable Class<? extends Module> moduleClass) {
    if (moduleClass != null) {
      checkArgument(
          (moduleClass.getModifiers() & Modifier.STATIC) != 0,
          "module must be static: %s",
          moduleClass.getName());
    }
  }

  /** {@link Ticker} implementation for mocking without restarting GerritServer */
  public static class TestTicker extends Ticker {
    Ticker actualTicker;

    public TestTicker() {
      useDefaultTicker();
    }

    /** Switches to system ticker */
    @CanIgnoreReturnValue
    public Ticker useDefaultTicker() {
      this.actualTicker = Ticker.systemTicker();
      return actualTicker;
    }

    /** Switches to {@link FakeTicker} */
    @CanIgnoreReturnValue
    public FakeTicker useFakeTicker() {
      if (!(this.actualTicker instanceof FakeTicker)) {
        this.actualTicker = new FakeTicker();
      }
      return (FakeTicker) actualTicker;
    }

    @Override
    public long read() {
      return actualTicker.read();
    }
  }
}
