// Copyright (C) 2022 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.cache.mem;

import static com.google.common.base.Functions.identity;
import static com.google.common.truth.Truth.assertThat;

import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.Weigher;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.server.cache.CacheDef;
import com.google.inject.TypeLiteral;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.eclipse.jgit.lib.Config;
import org.junit.Before;
import org.junit.Test;

public class DefaultMemoryCacheFactoryTest {

  private static final String TEST_CACHE = "test-cache";
  private static final long TEST_TIMEOUT_SEC = 1;
  private static final int TEST_CACHE_KEY = 1;

  private DefaultMemoryCacheFactory memoryCacheFactory;
  private Config memoryCacheConfig;
  private ScheduledExecutorService executor;
  private CyclicBarrier cacheGetStarted;
  private CyclicBarrier cacheGetCompleted;

  @Before
  public void setUp() {
    memoryCacheConfig = new Config();
    memoryCacheFactory = new DefaultMemoryCacheFactory(memoryCacheConfig, null);
    executor = Executors.newScheduledThreadPool(1);
    cacheGetStarted = new CyclicBarrier(2);
    cacheGetCompleted = new CyclicBarrier(2);
  }

  @Test
  public void shouldNotBlockEvictionsWhenCacheIsDisabledByDefault() throws Exception {
    LoadingCache<Integer, Integer> disabledCache =
        memoryCacheFactory.build(newCacheDef(0), newCacheLoader(identity()));

    assertCacheEvictionIsNotBlocking(disabledCache);
  }

  @Test
  public void shouldNotBlockEvictionsWhenCacheIsDisabledByConfiguration() throws Exception {
    memoryCacheConfig.setInt("cache", TEST_CACHE, "memoryLimit", 0);
    LoadingCache<Integer, Integer> disabledCache =
        memoryCacheFactory.build(newCacheDef(1), newCacheLoader(identity()));

    assertCacheEvictionIsNotBlocking(disabledCache);
  }

  @Test
  public void shouldBlockEvictionsWhenCacheIsEnabled() throws Exception {
    LoadingCache<Integer, Integer> cache =
        memoryCacheFactory.build(newCacheDef(1), newCacheLoader(identity()));

    ScheduledFuture<Integer> cacheValue =
        executor.schedule(() -> cache.getUnchecked(TEST_CACHE_KEY), 0, TimeUnit.SECONDS);

    cacheGetStarted.await(TEST_TIMEOUT_SEC, TimeUnit.SECONDS);
    cache.invalidate(TEST_CACHE_KEY);

    assertThat(cacheValue.isDone()).isTrue();
    assertThat(cacheValue.get()).isEqualTo(TEST_CACHE_KEY);
  }

  @Test
  public void shouldLoadAllKeysWithDisabledCache() throws Exception {
    LoadingCache<Integer, Integer> disabledCache =
        memoryCacheFactory.build(newCacheDef(0), newCacheLoader(identity()));

    List<Integer> keys = Arrays.asList(1, 2);
    ImmutableMap<Integer, Integer> entries = disabledCache.getAll(keys);

    assertThat(entries).containsExactly(1, 1, 2, 2);
  }

  private void assertCacheEvictionIsNotBlocking(LoadingCache<Integer, Integer> disabledCache)
      throws InterruptedException, BrokenBarrierException, TimeoutException, ExecutionException {
    ScheduledFuture<Integer> cacheValue =
        executor.schedule(() -> disabledCache.getUnchecked(TEST_CACHE_KEY), 0, TimeUnit.SECONDS);
    cacheGetStarted.await(TEST_TIMEOUT_SEC, TimeUnit.SECONDS);
    disabledCache.invalidate(TEST_CACHE_KEY);

    // The invalidate did not wait for the cache loader to finish, therefore the cacheValue isn't
    // done yet
    assertThat(cacheValue.isDone()).isFalse();

    // The cache loader completes after the invalidation
    cacheGetCompleted.await(TEST_TIMEOUT_SEC, TimeUnit.SECONDS);
    assertThat(cacheValue.get()).isEqualTo(TEST_CACHE_KEY);
  }

  private CacheLoader<Integer, Integer> newCacheLoader(Function<Integer, Integer> loadFunc) {
    return new CacheLoader<>() {

      @Override
      public Integer load(Integer n) throws Exception {
        Integer v = 0;
        try {
          cacheGetStarted.await(TEST_TIMEOUT_SEC, TimeUnit.SECONDS);
          v = loadFunc.apply(n);
          cacheGetCompleted.await(TEST_TIMEOUT_SEC, TimeUnit.SECONDS);
        } catch (TimeoutException | BrokenBarrierException e) {
          // Just continue
        }
        return v;
      }

      @Override
      public Map<Integer, Integer> loadAll(Iterable<? extends Integer> keys) throws Exception {
        return StreamSupport.stream(keys.spliterator(), false)
            .collect(Collectors.toMap(identity(), identity()));
      }
    };
  }

  private CacheDef<Integer, Integer> newCacheDef(long maximumWeight) {
    return new CacheDef<>() {

      @Override
      public String name() {
        return TEST_CACHE;
      }

      @Override
      public String configKey() {
        return TEST_CACHE;
      }

      @Override
      public TypeLiteral<Integer> keyType() {
        return null;
      }

      @Override
      public TypeLiteral<Integer> valueType() {
        return null;
      }

      @Override
      public long maximumWeight() {
        return maximumWeight;
      }

      @Override
      public Duration expireAfterWrite() {
        return null;
      }

      @Override
      public Duration expireFromMemoryAfterAccess() {
        return null;
      }

      @Override
      public Duration refreshAfterWrite() {
        return null;
      }

      @Override
      public Weigher<Integer, Integer> weigher() {
        return null;
      }

      @Override
      public CacheLoader<Integer, Integer> loader() {
        return null;
      }
    };
  }
}
