// 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.ericsson.gerrit.plugins.highavailability.websession.file.FileBasedWebsessionCache.TimeMachine;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.httpd.WebSessionManager.Val;
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.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
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";
  private static final String NEW_KEY = "abcde12345";

  @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();
      TimeMachine.useFixedClockAt(
          Instant.ofEpochMilli(existingKeyExpireAt).minus(1, ChronoUnit.HOURS));
      cache.cleanUp();
      assertThat(isDirEmpty(websessionDir)).isFalse();

      TimeMachine.useFixedClockAt(
          Instant.ofEpochMilli(existingKeyExpireAt).plus(1, ChronoUnit.HOURS));
      cache.cleanUp();
      assertThat(isDirEmpty(websessionDir)).isTrue();
    } finally {
      TimeMachine.useSystemDefaultZoneClock();
    }
  }

  @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((Object) 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 = ImmutableList.of(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);
    cache.put(NEW_KEY, val);
    assertThat(cache.getIfPresent(NEW_KEY)).isNotNull();
  }

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

  @Test
  public void putWithErrorsTest() throws Exception {
    loadKeyToCacheDir(EXISTING_KEY);
    Val val = cache.getIfPresent(EXISTING_KEY);
    tempFolder.delete();
    cache.put(NEW_KEY, val);
    assertThat(cache.getIfPresent(NEW_KEY)).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 static 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));
    }
    try (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);
  }
}
