// 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.google.gerrit.server.account.externalids;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.metrics.DisabledMetricMaker;
import com.google.gerrit.server.account.externalids.testing.ExternalIdTestUtil;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.AllUsersNameProvider;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.testing.InMemoryRepositoryManager;
import com.google.inject.util.Providers;
import java.io.IOException;
import java.util.function.Consumer;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ExternalIDCacheLoaderTest {
  private static AllUsersName ALL_USERS = new AllUsersName(AllUsersNameProvider.DEFAULT);

  private Cache<ObjectId, AllExternalIds> externalIdCache;
  private ExternalIdCacheLoader loader;
  private GitRepositoryManager repoManager = new InMemoryRepositoryManager();
  private ExternalIdReader externalIdReader;
  private ExternalIdReader externalIdReaderSpy;

  @Before
  public void setUp() throws Exception {
    externalIdCache = CacheBuilder.newBuilder().build();
    repoManager.createRepository(ALL_USERS).close();
    externalIdReader = new ExternalIdReader(repoManager, ALL_USERS, new DisabledMetricMaker());
    externalIdReaderSpy = Mockito.spy(externalIdReader);
    loader = createLoader(true);
  }

  @Test
  public void worksOnSingleCommit() throws Exception {
    ObjectId firstState = insertExternalId(1, 1);
    assertThat(loader.load(firstState)).isEqualTo(allFromGit(firstState));
    verify(externalIdReaderSpy, times(1)).all(firstState);
  }

  @Test
  public void reloadsSingleUpdateUsingPartialReload() throws Exception {
    ObjectId firstState = insertExternalId(1, 1);
    ObjectId head = insertExternalId(2, 2);
    externalIdCache.put(firstState, allFromGit(firstState));

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verifyNoInteractions(externalIdReaderSpy);
  }

  @Test
  public void reloadsMultipleUpdatesUsingPartialReload() throws Exception {
    ObjectId firstState = insertExternalId(1, 1);
    insertExternalId(2, 2);
    insertExternalId(3, 3);
    ObjectId head = insertExternalId(4, 4);
    externalIdCache.put(firstState, allFromGit(firstState));

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verifyNoInteractions(externalIdReaderSpy);
  }

  @Test
  public void reloadsAllExternalIdsWhenNoOldStateIsCached() throws Exception {
    insertExternalId(1, 1);
    ObjectId head = insertExternalId(2, 2);

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verify(externalIdReaderSpy, times(1)).all(head);
  }

  @Test
  public void partialReloadingDisabledAlwaysTriggersFullReload() throws Exception {
    loader = createLoader(false);
    insertExternalId(1, 1);
    ObjectId head = insertExternalId(2, 2);

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verify(externalIdReaderSpy, times(1)).all(head);
  }

  @Test
  public void fallsBackToFullReloadOnManyUpdatesOnBranch() throws Exception {
    insertExternalId(1, 1);
    ObjectId head = null;
    for (int i = 2; i < 20; i++) {
      head = insertExternalId(i, i);
    }

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verify(externalIdReaderSpy, times(1)).all(head);
  }

  @Test
  public void doesFullReloadWhenNoCacheStateIsFound() throws Exception {
    ObjectId head = insertExternalId(1, 1);

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verify(externalIdReaderSpy, times(1)).all(head);
  }

  @Test
  public void handlesDeletionInPartialReload() throws Exception {
    ObjectId firstState = insertExternalId(1, 1);
    ObjectId head = deleteExternalId(1, 1);
    assertThat(allFromGit(head).byAccount().size()).isEqualTo(0);
    externalIdCache.put(firstState, allFromGit(firstState));

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verifyNoInteractions(externalIdReaderSpy);
  }

  @Test
  public void handlesModifyInPartialReload() throws Exception {
    ObjectId firstState = insertExternalId(1, 1);
    ObjectId head =
        modifyExternalId(
            externalId(1, 1),
            ExternalId.create("fooschema", "bar1", Account.id(1), "foo@bar.com", "password"));
    assertThat(allFromGit(head).byAccount().size()).isEqualTo(1);
    externalIdCache.put(firstState, allFromGit(firstState));

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verifyNoInteractions(externalIdReaderSpy);
  }

  @Test
  public void ignoresInvalidExternalId() throws Exception {
    ObjectId firstState = insertExternalId(1, 1);
    ObjectId head;
    try (Repository repo = repoManager.openRepository(ALL_USERS);
        RevWalk rw = new RevWalk(repo)) {
      ExternalIdTestUtil.insertExternalIdWithKeyThatDoesntMatchNoteId(
          repo, rw, new PersonIdent("foo", "foo@bar.com"), Account.id(2), "test");
      head = repo.exactRef(RefNames.REFS_EXTERNAL_IDS).getObjectId();
    }

    externalIdCache.put(firstState, allFromGit(firstState));

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verifyNoInteractions(externalIdReaderSpy);
  }

  @Test
  public void handlesTreePrefixesInDifferentialReload() throws Exception {
    // Create more than 256 notes (NoteMap's current sharding limit) and check that we really have
    // created a situation where NoteNames are sharded.
    ObjectId oldState = inserExternalIds(257);
    assertAllFilesHaveSlashesInPath();
    ObjectId head = insertExternalId(500, 500);
    externalIdCache.put(oldState, allFromGit(oldState));

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verifyNoInteractions(externalIdReaderSpy);
  }

  @Test
  public void handlesReshard() throws Exception {
    // Create 256 notes (NoteMap's current sharding limit) and check that we are not yet sharding
    ObjectId oldState = inserExternalIds(256);
    assertNoFilesHaveSlashesInPath();
    // Create one more external ID and then have the Loader compute the new state
    ObjectId head = insertExternalId(500, 500);
    assertAllFilesHaveSlashesInPath(); // NoteMap resharded
    externalIdCache.put(oldState, allFromGit(oldState));

    assertThat(loader.load(head)).isEqualTo(allFromGit(head));
    verifyNoInteractions(externalIdReaderSpy);
  }

  private ExternalIdCacheLoader createLoader(boolean allowPartial) {
    Config cfg = new Config();
    cfg.setBoolean("cache", "external_ids_map", "enablePartialReloads", allowPartial);
    return new ExternalIdCacheLoader(
        repoManager,
        ALL_USERS,
        externalIdReaderSpy,
        Providers.of(externalIdCache),
        new DisabledMetricMaker(),
        cfg);
  }

  private AllExternalIds allFromGit(ObjectId revision) throws Exception {
    return AllExternalIds.create(externalIdReader.all(revision));
  }

  private ObjectId inserExternalIds(int numberOfIdsToInsert) throws Exception {
    ObjectId oldState = null;
    // Create more than 256 notes (NoteMap's current sharding limit) and check that we really have
    // created a situation where NoteNames are sharded.
    for (int i = 0; i < numberOfIdsToInsert; i++) {
      oldState = insertExternalId(i, i);
    }
    return oldState;
  }

  private ObjectId insertExternalId(int key, int accountId) throws Exception {
    return performExternalIdUpdate(
        u -> {
          try {
            u.insert(externalId(key, accountId));
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        });
  }

  private ObjectId modifyExternalId(ExternalId oldId, ExternalId newId) throws Exception {
    return performExternalIdUpdate(
        u -> {
          try {
            u.replace(oldId, newId);
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        });
  }

  private ObjectId deleteExternalId(int key, int accountId) throws Exception {
    return performExternalIdUpdate(u -> u.delete(externalId(key, accountId)));
  }

  private ExternalId externalId(int key, int accountId) {
    return ExternalId.create("fooschema", "bar" + key, Account.id(accountId));
  }

  private ObjectId performExternalIdUpdate(Consumer<ExternalIdNotes> update) throws Exception {
    try (Repository repo = repoManager.openRepository(ALL_USERS)) {
      PersonIdent updater = new PersonIdent("Foo bar", "foo@bar.com");
      ExternalIdNotes extIdNotes = ExternalIdNotes.loadNoCacheUpdate(ALL_USERS, repo);
      update.accept(extIdNotes);
      try (MetaDataUpdate metaDataUpdate =
          new MetaDataUpdate(GitReferenceUpdated.DISABLED, null, repo)) {
        metaDataUpdate.getCommitBuilder().setAuthor(updater);
        metaDataUpdate.getCommitBuilder().setCommitter(updater);
        return extIdNotes.commit(metaDataUpdate).getId();
      }
    }
  }

  private void assertAllFilesHaveSlashesInPath() throws Exception {
    assertThat(allFilesInExternalIdRef().stream().allMatch(f -> f.contains("/"))).isTrue();
  }

  private void assertNoFilesHaveSlashesInPath() throws Exception {
    assertThat(allFilesInExternalIdRef().stream().noneMatch(f -> f.contains("/"))).isTrue();
  }

  private ImmutableList<String> allFilesInExternalIdRef() throws Exception {
    try (Repository repo = repoManager.openRepository(ALL_USERS);
        TreeWalk treeWalk = new TreeWalk(repo);
        RevWalk rw = new RevWalk(repo)) {
      treeWalk.reset(
          rw.parseCommit(repo.exactRef(RefNames.REFS_EXTERNAL_IDS).getObjectId()).getTree());
      treeWalk.setRecursive(true);
      ImmutableList.Builder<String> allPaths = ImmutableList.builder();
      while (treeWalk.next()) {
        allPaths.add(treeWalk.getPathString());
      }
      return allPaths.build();
    }
  }
}
