// Copyright (C) 2015 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.modules.cache.chroniclemap;

import static com.google.common.truth.Truth.assertThat;
import static com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheConfig.Defaults.DEFAULT_AVG_KEY_SIZE;
import static com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheConfig.Defaults.DEFAULT_AVG_VALUE_SIZE;
import static com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheConfig.Defaults.DEFAULT_MAX_BLOAT_FACTOR;
import static com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheConfig.Defaults.DEFAULT_MAX_ENTRIES;
import static com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheConfig.Defaults.DEFAULT_PERCENTAGE_FREE_SPACE_EVICTION_THRESHOLD;
import static com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheConfig.Defaults.DEFAULT_PERSIST_INDEX_EVERY;
import static com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheFactory.PRUNE_DELAY;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

import com.google.gerrit.server.config.SitePaths;
import java.io.File;
import java.nio.file.Files;
import java.time.Duration;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ChronicleMapCacheConfigTest {

  private final String cacheDirectory = ".";
  private final String cacheName = "foobar-cache";
  private final String cacheKey = "foobar-cache-key";
  private final int version = 1;
  private final Duration expireAfterWrite = Duration.ofSeconds(10_000);
  private final Duration refreshAfterWrite = Duration.ofSeconds(20_000);

  @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
  private SitePaths sitePaths;
  private StoredConfig gerritConfig;

  @Mock CachesWithoutChronicleMapConfigMetric cachesWithoutConfigMetricMock;

  @Before
  public void setUp() throws Exception {
    sitePaths = new SitePaths(temporaryFolder.newFolder().toPath());
    Files.createDirectories(sitePaths.etc_dir);

    gerritConfig =
        new FileBasedConfig(
            sitePaths.resolve("etc").resolve("gerrit.config").toFile(), FS.DETECTED);
    gerritConfig.load();
    gerritConfig.setString("cache", null, "directory", cacheDirectory);
    gerritConfig.save();
  }

  @Test
  public void shouldProvideCacheFile() throws Exception {
    assertThat(
            configUnderTest(gerritConfig)
                .getCacheFile()
                .toPath()
                .getParent()
                .toRealPath()
                .toString())
        .isEqualTo(sitePaths.resolve(cacheDirectory).toRealPath().toString());
  }

  @Test
  public void shouldProvideIndexFileThatIsRelatedToCacheFile() {
    ChronicleMapCacheConfig config = configUnderTest(gerritConfig);
    File cacheFile = config.getCacheFile();
    File indexFile = config.getIndexFile();

    assertThat(indexFile.getParentFile()).isEqualTo(cacheFile.getParentFile());
    String cacheFileName = cacheFile.getName();
    assertThat(indexFile.getName())
        .isEqualTo(
            String.format("%s.index", cacheFileName.substring(0, cacheFileName.indexOf(".dat"))));
  }

  @Test
  public void shouldProvideConfiguredMaxEntriesWhenDefined() throws Exception {
    long maxEntries = 10;
    gerritConfig.setLong("cache", cacheKey, "maxEntries", maxEntries);
    gerritConfig.save();

    assertThat(configUnderTest(gerritConfig).getMaxEntries()).isEqualTo(maxEntries);
  }

  @Test
  public void shouldProvideDefaultMaxEntriesWhenNotConfigured() throws Exception {
    assertThat(configUnderTest(gerritConfig).getMaxEntries()).isEqualTo(DEFAULT_MAX_ENTRIES);
  }

  @Test
  public void shouldProvideAverageKeySizeWhenConfigured() throws Exception {
    long averageKeySize = 5;
    gerritConfig.setLong("cache", cacheKey, "avgKeySize", averageKeySize);
    gerritConfig.save();

    assertThat(configUnderTest(gerritConfig).getAverageKeySize()).isEqualTo(averageKeySize);
  }

  @Test
  public void shouldProvideDefaultAverageKeySizeWhenNotConfigured() throws Exception {
    assertThat(configUnderTest(gerritConfig).getAverageKeySize()).isEqualTo(DEFAULT_AVG_KEY_SIZE);
  }

  @Test
  public void shouldProvideAverageValueSizeWhenConfigured() throws Exception {
    long averageValueSize = 6;
    gerritConfig.setLong("cache", cacheKey, "avgValueSize", averageValueSize);
    gerritConfig.save();

    assertThat(configUnderTest(gerritConfig).getAverageValueSize()).isEqualTo(averageValueSize);
  }

  @Test
  public void shouldProvideDefaultAverageValueSizeWhenNotConfigured() throws Exception {
    assertThat(configUnderTest(gerritConfig).getAverageValueSize())
        .isEqualTo(DEFAULT_AVG_VALUE_SIZE);
  }

  @Test
  public void shouldProvideMaxDefaultBloatFactorWhenNotConfigured() throws Exception {
    assertThat(configUnderTest(gerritConfig).getMaxBloatFactor())
        .isEqualTo(DEFAULT_MAX_BLOAT_FACTOR);
  }

  @Test
  public void shouldProvideMaxBloatFactorWhenConfigured() throws Exception {
    int bloatFactor = 3;
    gerritConfig.setInt("cache", cacheKey, "maxBloatFactor", bloatFactor);
    gerritConfig.save();

    assertThat(configUnderTest(gerritConfig).getMaxBloatFactor()).isEqualTo(bloatFactor);
  }

  @Test
  public void shouldProvideExpireAfterWriteWhenMaxAgeIsConfgured() throws Exception {
    String maxAge = "3 minutes";
    gerritConfig.setString("cache", cacheKey, "maxAge", maxAge);
    gerritConfig.save();

    assertThat(configUnderTest(gerritConfig).getExpireAfterWrite())
        .isEqualTo(Duration.ofSeconds(180));
  }

  @Test
  public void shouldProvideDefinitionExpireAfterWriteWhenNotConfigured() throws Exception {
    assertThat(configUnderTest(gerritConfig).getExpireAfterWrite()).isEqualTo(expireAfterWrite);
  }

  @Test
  public void shouldProvideRefreshAfterWriteWhenConfigured() throws Exception {
    String refreshAfterWrite = "6 minutes";
    gerritConfig.setString("cache", cacheKey, "refreshAfterWrite", refreshAfterWrite);
    gerritConfig.save();

    assertThat(configUnderTest(gerritConfig).getRefreshAfterWrite())
        .isEqualTo(Duration.ofSeconds(360));
  }

  @Test
  public void shouldProvideDefinitionRefreshAfterWriteWhenNotConfigured() throws Exception {
    assertThat(configUnderTest(gerritConfig).getRefreshAfterWrite()).isEqualTo(refreshAfterWrite);
  }

  @Test
  public void shouldProvidePercentageFreeSpaceEvictionThresholdWhenConfigured() throws Exception {
    int percentageFreeThreshold = 70;
    gerritConfig.setInt(
        "cache", cacheKey, "percentageFreeSpaceEvictionThreshold", percentageFreeThreshold);
    gerritConfig.save();

    assertThat(configUnderTest(gerritConfig).getPercentageFreeSpaceEvictionThreshold())
        .isEqualTo(percentageFreeThreshold);
  }

  @Test
  public void shouldProvidePercentageFreeSpaceEvictionThresholdDefault() throws Exception {
    assertThat(configUnderTest(gerritConfig).getPercentageFreeSpaceEvictionThreshold())
        .isEqualTo(DEFAULT_PERCENTAGE_FREE_SPACE_EVICTION_THRESHOLD);
  }

  @Test
  public void shouldProvideDefaultIndexPersistEveryValuesWhenNotConfigured() {
    ChronicleMapCacheConfig configUnderTest = configUnderTest(gerritConfig);
    assertThat(configUnderTest.getPersistIndexEvery()).isEqualTo(DEFAULT_PERSIST_INDEX_EVERY);
    assertThat(configUnderTest.getPersistIndexEveryNthPrune()).isEqualTo(30L);
  }

  @Test
  public void shouldPersistIndexEveryBePruneDelayWhenPersistIndexEveryIsLowerThanPruneDelay() {
    gerritConfig.setString(
        "cache", null, "persistIndexEvery", String.format("%ds", PRUNE_DELAY - 1L));
    ChronicleMapCacheConfig configUnderTest = configUnderTest(gerritConfig);
    assertThat(configUnderTest.getPersistIndexEvery()).isEqualTo(Duration.ofSeconds(PRUNE_DELAY));
    assertThat(configUnderTest.getPersistIndexEveryNthPrune()).isEqualTo(1L);
  }

  @Test
  public void shouldPersistIndexEveryBeRoundedDownToAMultiplyOfPruneDelay() {
    gerritConfig.setString(
        "cache", null, "persistIndexEvery", String.format("%ds", 2L * PRUNE_DELAY + 1L));
    ChronicleMapCacheConfig configUnderTest = configUnderTest(gerritConfig);
    assertThat(configUnderTest.getPersistIndexEvery())
        .isEqualTo(Duration.ofSeconds(2L * PRUNE_DELAY));
    assertThat(configUnderTest.getPersistIndexEveryNthPrune()).isEqualTo(2L);
  }

  @Test
  public void shouldIncrementCacheMetricWhenCacheHasNoDedicatedConfiguration() {
    configUnderTest(gerritConfig);

    verify(cachesWithoutConfigMetricMock, atLeastOnce()).incrementForCache(cacheKey);
  }

  @Test
  public void shouldNotIncrementCacheMetricWhenCacheHasAtLeastSingleParameterConfigured() {
    gerritConfig.setLong("cache", cacheKey, "maxEntries", 1L);
    configUnderTest(gerritConfig);

    verify(cachesWithoutConfigMetricMock, never()).incrementForCache(cacheName);
  }

  private ChronicleMapCacheConfig configUnderTest(StoredConfig gerritConfig) {
    File cacheFile =
        ChronicleMapCacheFactory.fileName(
            sitePaths.site_path.resolve(cacheDirectory), cacheName, version);
    sitePaths
        .resolve(cacheDirectory)
        .resolve(String.format("%s_%s.dat", cacheName, version))
        .toFile();

    return new ChronicleMapCacheConfig(
        gerritConfig,
        cachesWithoutConfigMetricMock,
        cacheKey,
        cacheFile,
        expireAfterWrite,
        refreshAfterWrite);
  }
}
