// 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.ericsson.gerrit.plugins.highavailability.websession.file;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.ImmutableMap;
import com.google.gerrit.httpd.WebSessionManager.Val;
import com.google.gerrit.testing.TestTimeUtil;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

public class FileBasedWebSessionCacheTest {

  private static final String EXISTING_KEY = "aSceprtBc02YaMY573T5jfW64ZudJfPbDq";
  private static final String EMPTY_KEY = "aOc2prqlZRpSO3LpauGO5efCLs1L9r9KkG";
  private static final String INVALID_KEY = "aOFdpHriBM6dN055M13PjDdTZagl5r5aSG";

  @Rule public TemporaryFolder tempFolder = new TemporaryFolder();

  private FileBasedWebsessionCache cache;
  private Path websessionDir;

  @Before
  public void setUp() throws Exception {
    websessionDir = tempFolder.newFolder("websessions").toPath();
    cache = new FileBasedWebsessionCache(tempFolder.getRoot().toPath());
  }

  @Test
  public void asMapTest() throws Exception {
    loadKeyToCacheDir(EMPTY_KEY);
    assertThat(cache.asMap()).isEmpty();

    loadKeyToCacheDir(INVALID_KEY);
    assertThat(cache.asMap()).isEmpty();

    loadKeyToCacheDir(EXISTING_KEY);
    assertThat(cache.asMap()).containsKey(EXISTING_KEY);
  }

  @Test
  public void constructorCreateDir() throws IOException {
    assertThat(websessionDir.toFile().delete()).isTrue();
    cache = new FileBasedWebsessionCache(tempFolder.getRoot().toPath());
    assertThat(websessionDir.toFile().exists()).isTrue();
  }

  @Test
  public void cleanUpTest() throws Exception {
    loadKeyToCacheDir(EXISTING_KEY);
    try {
      long existingKeyExpireAt = cache.getIfPresent(EXISTING_KEY).getExpiresAt();
      TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);
      TestTimeUtil.setClock(
          new Timestamp(
              Instant.ofEpochMilli(existingKeyExpireAt).minus(1, ChronoUnit.HOURS).toEpochMilli()));
      cache.cleanUp();
      assertThat(isDirEmpty(websessionDir)).isFalse();
      TestTimeUtil.setClock(
          new Timestamp(
              Instant.ofEpochMilli(existingKeyExpireAt).plus(1, ChronoUnit.HOURS).toEpochMilli()));
      cache.cleanUp();
      assertThat(isDirEmpty(websessionDir)).isTrue();
    } finally {
      TestTimeUtil.useSystemTime();
    }
  }

  @Test
  public void cleanUpWithErrorsWhileListingFilesTest() throws Exception {
    tempFolder.delete();
    cache.cleanUp();
    assertThat(cache.size()).isEqualTo(0);
  }

  @Test
  public void cleanUpWithErrorsWhileDeleteFileTest() throws Exception {
    loadKeyToCacheDir(EXISTING_KEY);
    try {
      websessionDir.toFile().setWritable(false);
      cache.cleanUp();
      assertThat(cache.size()).isEqualTo(1);
    } finally {
      websessionDir.toFile().setWritable(true);
    }
  }

  @Test
  public void getIfPresentEmptyKeyTest() throws Exception {
    assertThat(cache.getIfPresent(EMPTY_KEY)).isNull();
  }

  @Test
  public void getIfPresentObjectNonStringTest() throws Exception {
    assertThat(cache.getIfPresent(new Object())).isNull();
  }

  @Test
  public void getIfPresentInvalidKeyTest() throws Exception {
    loadKeyToCacheDir(INVALID_KEY);
    Path path = websessionDir.resolve(INVALID_KEY);
    assertThat(cache.getIfPresent(path)).isNull();
  }

  @Test
  public void getIfPresentTest() throws Exception {
    loadKeyToCacheDir(EXISTING_KEY);
    assertThat(cache.getIfPresent(EXISTING_KEY)).isNotNull();
  }

  @Test
  public void getAllPresentTest() throws Exception {
    loadKeyToCacheDir(EMPTY_KEY);
    loadKeyToCacheDir(INVALID_KEY);
    loadKeyToCacheDir(EXISTING_KEY);
    List<String> keys = Arrays.asList(new String[] {EMPTY_KEY, EXISTING_KEY});
    assertThat(cache.getAllPresent(keys).size()).isEqualTo(1);
    assertThat(cache.getAllPresent(keys)).containsKey(EXISTING_KEY);
  }

  @Test
  public void getTest() throws Exception {
    class ValueLoader implements Callable<Val> {
      @Override
      public Val call() throws Exception {
        return null;
      }
    }
    assertThat(cache.get(EXISTING_KEY, new ValueLoader())).isNull();

    loadKeyToCacheDir(EXISTING_KEY);
    assertThat(cache.get(EXISTING_KEY, new ValueLoader())).isNotNull();
  }

  @Test(expected = ExecutionException.class)
  public void getTestCallableThrowsException() throws Exception {
    class ValueLoader implements Callable<Val> {
      @Override
      public Val call() throws Exception {
        throw new Exception();
      }
    }
    assertThat(cache.get(EXISTING_KEY, new ValueLoader())).isNull();
  }

  @Test
  public void invalidateAllCollectionTest() throws Exception {
    int numberOfKeys = 15;
    List<String> keys = loadKeysToCacheDir(numberOfKeys);
    assertThat(cache.size()).isEqualTo(numberOfKeys);
    assertThat(isDirEmpty(websessionDir)).isFalse();

    cache.invalidateAll(keys);
    assertThat(cache.size()).isEqualTo(0);
    assertThat(isDirEmpty(websessionDir)).isTrue();
  }

  @Test
  public void invalidateAllTest() throws Exception {
    int numberOfKeys = 5;
    loadKeysToCacheDir(numberOfKeys);
    assertThat(cache.size()).isEqualTo(numberOfKeys);
    assertThat(isDirEmpty(websessionDir)).isFalse();

    cache.invalidateAll();
    assertThat(cache.size()).isEqualTo(0);
    assertThat(isDirEmpty(websessionDir)).isTrue();
  }

  @Test
  public void invalidateTest() throws Exception {
    Path fileToDelete = Files.createFile(websessionDir.resolve(EXISTING_KEY));
    assertThat(Files.exists(fileToDelete)).isTrue();
    cache.invalidate(EXISTING_KEY);
    assertThat(Files.exists(fileToDelete)).isFalse();
  }

  @Test
  public void invalidateTestObjectNotString() throws Exception {
    loadKeyToCacheDir(EXISTING_KEY);
    assertThat(cache.size()).isEqualTo(1);
    cache.invalidate(new Object());
    assertThat(cache.size()).isEqualTo(1);
  }

  @Test
  public void putTest() throws Exception {
    loadKeyToCacheDir(EXISTING_KEY);
    Val val = cache.getIfPresent(EXISTING_KEY);
    String newKey = "abcde12345";
    cache.put(newKey, val);
    assertThat(cache.getIfPresent(newKey)).isNotNull();
  }

  @Test
  public void putAllTest() throws Exception {
    loadKeyToCacheDir(EXISTING_KEY);
    Val val = cache.getIfPresent(EXISTING_KEY);
    String newKey = "abcde12345";
    Map<String, Val> sessions = ImmutableMap.of(newKey, val);
    cache.putAll(sessions);
    assertThat(cache.asMap()).containsKey(newKey);
  }

  @Test
  public void putWithErrorsTest() throws Exception {
    loadKeyToCacheDir(EXISTING_KEY);
    Val val = cache.getIfPresent(EXISTING_KEY);
    String newKey = "abcde12345";
    tempFolder.delete();
    cache.put(newKey, val);
    assertThat(cache.getIfPresent(newKey)).isNull();
  }

  @Test
  public void sizeTest() throws Exception {
    int numberOfKeys = 10;
    loadKeysToCacheDir(numberOfKeys);
    assertThat(cache.size()).isEqualTo(numberOfKeys);
  }

  @Test
  public void statTest() throws Exception {
    assertThat(cache.stats()).isNull();
  }

  private List<String> loadKeysToCacheDir(int number) throws IOException {
    List<String> keys = new ArrayList<>();
    for (int i = 0; i < number; i++) {
      Path tmp = Files.createTempFile(websessionDir, "cache", null);
      keys.add(tmp.getFileName().toString());
    }
    return keys;
  }

  private boolean isDirEmpty(final Path dir) throws IOException {
    try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dir)) {
      return !dirStream.iterator().hasNext();
    }
  }

  private Path loadKeyToCacheDir(String key) throws IOException {
    if (key.equals(EMPTY_KEY)) {
      return Files.createFile(websessionDir.resolve(EMPTY_KEY));
    }
    InputStream in = loadFile(key);
    Path target = websessionDir.resolve(key);
    Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
    return target;
  }

  private InputStream loadFile(String file) {
    return this.getClass().getResourceAsStream("/" + file);
  }
}
