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

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.gerrit.server.cache.PerThreadCache.Key;
import com.google.gerrit.server.cache.PerThreadCache.ReadonlyRequestWindow;
import com.google.gerrit.server.git.RefCache;
import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Test;

public class PerThreadCacheTest {
  @Test
  public void key_respectsClass() {
    assertThat(PerThreadCache.Key.create(String.class))
        .isEqualTo(PerThreadCache.Key.create(String.class));
    assertThat(PerThreadCache.Key.create(String.class))
        .isNotEqualTo(PerThreadCache.Key.create(Integer.class));
  }

  @Test
  public void key_respectsIdentifiers() {
    assertThat(PerThreadCache.Key.create(String.class, "id1"))
        .isEqualTo(PerThreadCache.Key.create(String.class, "id1"));
    assertThat(PerThreadCache.Key.create(String.class, "id1"))
        .isNotEqualTo(PerThreadCache.Key.create(String.class, "id2"));
  }

  @Test
  public void endToEndCache() {
    try (PerThreadCache ignored = PerThreadCache.create(null)) {
      PerThreadCache cache = PerThreadCache.get();
      PerThreadCache.Key<String> key1 = PerThreadCache.Key.create(String.class);

      assertThat(cache.getWithLoader(key1, () -> "value1", null)).hasValue("value1");

      Supplier<String> neverCalled =
          () -> {
            throw new IllegalStateException("this method must not be called");
          };
      assertThat(cache.getWithLoader(key1, neverCalled, null)).hasValue("value1");
    }
  }

  @Test
  public void cleanUp() {
    PerThreadCache.Key<String> key = PerThreadCache.Key.create(String.class);
    try (PerThreadCache ignored = PerThreadCache.create(null)) {
      PerThreadCache cache = PerThreadCache.get();
      assertThat(cache.getWithLoader(key, () -> "value1", null)).hasValue("value1");
    }

    // Create a second cache and assert that it is not connected to the first one.
    // This ensures that the cleanup is actually working.
    try (PerThreadCache ignored = PerThreadCache.create(null)) {
      PerThreadCache cache = PerThreadCache.get();
      assertThat(cache.getWithLoader(key, () -> "value2", null)).hasValue("value2");
    }
  }

  @Test
  public void unloaderCalledUponCleanup() {
    AtomicBoolean unloaderCalled = new AtomicBoolean();
    PerThreadCache.Key<String> key = PerThreadCache.Key.create(String.class);
    try (PerThreadCache ignored = PerThreadCache.create(null)) {
      PerThreadCache cache = PerThreadCache.get();
      cache.getWithLoader(key, () -> "value1", v -> unloaderCalled.set(true));
      assertThat(unloaderCalled.get()).isFalse();
    }
    assertThat(unloaderCalled.get()).isTrue();
  }

  @Test
  public void doubleInstantiationFails() {
    try (PerThreadCache ignored = PerThreadCache.create(null)) {
      IllegalStateException thrown =
          assertThrows(IllegalStateException.class, () -> PerThreadCache.create(null));
      assertThat(thrown).hasMessageThat().contains("called create() twice on the same request");
    }
  }

  @Test
  public void isAssociatedWithHttpReadonlyRequest() {
    HttpServletRequest getRequest = new FakeHttpServletRequest();
    try (PerThreadCache cache = PerThreadCache.create(getRequest)) {
      assertThat(cache.allowRefCache()).isTrue();
    }
  }

  @Test
  public void isAssociatedWithHttpWriteRequest() {
    HttpServletRequest putRequest =
        new HttpServletRequestWrapper(new FakeHttpServletRequest()) {
          @Override
          public String getMethod() {
            return "PUT";
          }
        };
    try (PerThreadCache cache = PerThreadCache.create(putRequest)) {
      assertThat(cache.allowRefCache()).isFalse();
    }
  }

  @Test
  public void isNotAssociatedWithHttpRequest() {
    try (PerThreadCache cache = PerThreadCache.create(null)) {
      assertThat(cache.allowRefCache()).isFalse();
    }
  }

  @Test
  public void isAssociatedWithReadonlyRequest() {
    try (PerThreadCache cache = PerThreadCache.createReadOnly()) {
      assertThat(cache.allowRefCache()).isTrue();
    }
  }

  @Test
  public void openNestedTemporaryReadonlyWindows() throws Exception {

    try (PerThreadCache cache = PerThreadCache.create(null)) {
      assertThat(cache.allowRefCache()).isFalse();

      try (ReadonlyRequestWindow outerWindow = PerThreadCache.openReadonlyRequestWindow()) {
        assertThat(cache.allowRefCache()).isTrue();

        try (ReadonlyRequestWindow innerWindow = PerThreadCache.openReadonlyRequestWindow()) {
          assertThat(cache.allowRefCache()).isTrue();
        }

        assertThat(cache.allowRefCache()).isTrue();
      }

      assertThat(cache.allowRefCache()).isFalse();
    }
  }

  static class TestCacheValue implements RefCache {
    public static final String STALENESS_FAILED_MESSAGE = "Staleness check failed";

    private final String value;

    public TestCacheValue(String value) {
      this.value = value;
    }

    @Override
    public String toString() {
      return value;
    }

    @Override
    public boolean equals(Object obj) {
      return obj != null
          && (obj instanceof TestCacheValue)
          && ((TestCacheValue) obj).value.equals(value);
    }

    @Override
    public int hashCode() {
      return value.hashCode();
    }

    public void checkStaleness() throws IllegalStateException {
      throw new IllegalStateException(STALENESS_FAILED_MESSAGE);
    }

    @Override
    public Optional<ObjectId> get(String refName) throws IOException {
      return Optional.empty();
    }

    @Override
    public void close() {}
  }

  @Test
  public void clearOutStaleEntriesAfterReadonlyWindow() throws Exception {
    Key<TestCacheValue> key = PerThreadCache.Key.create(TestCacheValue.class, "key");
    TestCacheValue cachedValue = new TestCacheValue("cached value");
    TestCacheValue updatedValue = new TestCacheValue("updated value");

    try (PerThreadCache cache = PerThreadCache.create(null)) {
      try (ReadonlyRequestWindow outerWindow = PerThreadCache.openReadonlyRequestWindow()) {
        assertThat(PerThreadCache.get(key, () -> cachedValue, v -> {})).hasValue(cachedValue);
        assertThat(PerThreadCache.get(key, () -> updatedValue, v -> {})).hasValue(cachedValue);
      }

      assertThat(PerThreadCache.get(key, () -> updatedValue, v -> {})).hasValue(updatedValue);
    }
  }

  @Test
  public void checkForStaleEntriesAfterReadonlyWindow() {
    Key<TestCacheValue> key = PerThreadCache.Key.create(TestCacheValue.class, "key");

    try (PerThreadCache cache = PerThreadCache.create(null)) {
      IllegalStateException thrown =
          assertThrows(
              IllegalStateException.class,
              () -> {
                try (ReadonlyRequestWindow outerWindow =
                    PerThreadCache.openReadonlyRequestWindow()) {
                  PerThreadCache.get(
                      key, () -> new TestCacheValue(""), TestCacheValue::checkStaleness);
                }
              });
      assertThat(thrown).hasMessageThat().isEqualTo(TestCacheValue.STALENESS_FAILED_MESSAGE);
    }
  }

  @Test
  public void allowStaleEntriesAfterReadonlyWindow() {
    Key<TestCacheValue> key = PerThreadCache.Key.create(TestCacheValue.class, "key");
    TestCacheValue value = new TestCacheValue("");
    Optional<TestCacheValue> cachedValue;

    try (PerThreadCache cache = PerThreadCache.create(null)) {
      try (ReadonlyRequestWindow window = PerThreadCache.openReadonlyRequestWindow()) {

        cachedValue = PerThreadCache.get(key, () -> value, null);
      }
    }

    assertThat(cachedValue).hasValue(value);
  }

  @SuppressWarnings("deprecation")
  @Test
  public void disableCachingForSpecificTypes() {
    System.setProperty(
        PerThreadCache.PER_THREAD_CACHE_DISABLED_TYPES_PROPERTY,
        String.class.getCanonicalName() + "," + Integer.class.getCanonicalName());
    try {
      try (PerThreadCache cache = PerThreadCache.createReadOnly()) {
        assertThat(
                PerThreadCache.get(
                    PerThreadCache.Key.create(String.class, "key"), () -> "oldValue", null))
            .isEmpty();
        assertThat(
                PerThreadCache.getOrCompute(
                    PerThreadCache.Key.create(String.class, "key"), () -> "newValue"))
            .isEqualTo("newValue");

        assertThat(
                PerThreadCache.get(PerThreadCache.Key.create(Integer.class, "key"), () -> 1, null))
            .isEmpty();
        assertThat(
                PerThreadCache.getOrCompute(
                    PerThreadCache.Key.create(Integer.class, "key"), () -> 2))
            .isEqualTo(2);

        assertThat(PerThreadCache.get(PerThreadCache.Key.create(Long.class, "key"), () -> 1L, null))
            .hasValue(1L);
        assertThat(
                PerThreadCache.getOrCompute(PerThreadCache.Key.create(Long.class, "key"), () -> 2L))
            .isEqualTo(1L);
      }
    } finally {
      System.setProperty(PerThreadCache.PER_THREAD_CACHE_DISABLED_TYPES_PROPERTY, "");
    }
  }

  @SuppressWarnings("deprecation")
  @Test
  public void enforceMaxSize() {
    try (PerThreadCache cache = PerThreadCache.create(null)) {
      fillTheCache(cache);

      // Assert that the value was not persisted
      PerThreadCache.Key<String> key = PerThreadCache.Key.create(String.class, 1000);
      assertThat(cache.getWithLoader(key, () -> "new value", null)).isEmpty();
      String value = cache.get(key, () -> "directly served");
      assertThat(value).isEqualTo("directly served");
    }
  }

  @Test
  public void returnEmptyWhenCacheIsFull() {
    try (PerThreadCache cache = PerThreadCache.create(null)) {
      fillTheCache(cache);

      PerThreadCache.Key<String> key = PerThreadCache.Key.create(String.class, 1000);
      assertThat(cache.getWithLoader(key, () -> "new value", null)).isEmpty();
    }
  }

  @Test
  public void unloaderNotCalledUponCleanupIfCacheWasFull() {
    AtomicBoolean unloaderCalled = new AtomicBoolean();
    PerThreadCache.Key<String> key = PerThreadCache.Key.create(String.class);
    try (PerThreadCache ignored = PerThreadCache.create(null)) {
      PerThreadCache cache = PerThreadCache.get();
      fillTheCache(cache);

      cache.getWithLoader(key, () -> "value1", v -> unloaderCalled.set(true));
    }
    assertThat(unloaderCalled.get()).isFalse();
  }

  private void fillTheCache(PerThreadCache cache) {
    for (int i = 0; i < 50; i++) {
      PerThreadCache.Key<String> key = PerThreadCache.Key.create(String.class, i);
      cache.getWithLoader(key, () -> "cached value", null);
    }
  }
}
