// 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.plugins.websession.flatfile;

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

import com.google.common.collect.ImmutableMap;
import com.google.gerrit.httpd.WebSessionManager.Val;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
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;

public class FlatFileWebSessionCacheTest {

  private static final int DEFAULT_KEYS_SIZE = 10;

  private FlatFileWebSessionCache flatFileWebSessionCache;
  private Path dir;
  private String key;
  private String existingKey;

  @Before
  public void createFlatFileWebSessionCache() throws Exception {
    dir = Files.createTempDirectory("websessions");
    key = "aOc2prqlZRpSO3LpauGO5efCLs1L9r9KkG";
    existingKey = "aSceprtBc02YaMY573T5jfW64ZudJfPbDq";
    flatFileWebSessionCache = new FlatFileWebSessionCache(dir);
  }

  @After
  public void tearDown() throws Exception {
    if (isDirEmpty(dir)) {
      Files.deleteIfExists(dir);
    } else {
      emptyAndDelete(dir);
    }
  }

  @Test
  public void asMapTest() throws Exception {
    Files.createFile(dir.resolve(key));
    assertThat(flatFileWebSessionCache.asMap()).isEmpty();

    loadExistingKeyToCacheDir();
    assertThat(flatFileWebSessionCache.asMap()).containsKey(existingKey);
  }

  @Test
  public void constructorCreateDir() throws IOException {
    Path testDir = Paths.get("tmp");
    flatFileWebSessionCache = new FlatFileWebSessionCache(testDir);
    assertThat(Files.exists(testDir)).isTrue();
    Files.deleteIfExists(testDir);
  }

  @Test
  public void cleanUpTest() throws Exception {
    loadExistingKeyToCacheDir();
    flatFileWebSessionCache.cleanUp();
    assertThat(isDirEmpty(dir)).isTrue();
  }

  @Test
  public void getAllPresentTest() throws Exception {
    Files.createFile(dir.resolve(key));
    loadExistingKeyToCacheDir();
    List<String> keys = Arrays.asList(new String[] {key, existingKey});
    assertThat(flatFileWebSessionCache.getAllPresent(keys))
        .containsKey(existingKey);
  }

  @Test
  public void getIfPresentKeyDoesNotExistTest() throws Exception {
    assertThat(flatFileWebSessionCache.getIfPresent(key)).isNull();
  }

  @Test
  public void getIfPresentObjectNonStringTest() throws Exception {
    Path path = dir.resolve(key);
    assertThat(flatFileWebSessionCache.getIfPresent(path)).isNull();
  }

  @Test
  public void getIfPresentTest() throws Exception {
    loadExistingKeyToCacheDir();
    assertThat(flatFileWebSessionCache.getIfPresent(existingKey)).isNotNull();
  }

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

    loadExistingKeyToCacheDir();
    assertThat(flatFileWebSessionCache.get(existingKey, 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(flatFileWebSessionCache.get(existingKey, new ValueLoader()))
        .isNull();
  }

  @Test
  public void invalidateAllCollectionTest() throws Exception {
    List<String> keys = createKeysCollection();
    flatFileWebSessionCache.invalidateAll(keys);
    assertThat(isDirEmpty(dir)).isTrue();
  }

  @Test
  public void invalidateAllTest() throws Exception {
    createKeysCollection();
    flatFileWebSessionCache.invalidateAll();
    assertThat(isDirEmpty(dir)).isTrue();
  }

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

  @Test
  public void invalidateTestObjectNotString() throws Exception {
    createKeysCollection();
    assertThat(flatFileWebSessionCache.size()).isEqualTo(DEFAULT_KEYS_SIZE);
    flatFileWebSessionCache.invalidate(new Object());
    assertThat(flatFileWebSessionCache.size()).isEqualTo(DEFAULT_KEYS_SIZE);
  }

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

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

  @Test
  public void sizeTest() throws Exception {
    createKeysCollection();
    assertThat(flatFileWebSessionCache.size()).isEqualTo(DEFAULT_KEYS_SIZE);
  }

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

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

  private void emptyAndDelete(Path dir) throws IOException {
    Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
      @Override
      public FileVisitResult postVisitDirectory(Path dir, IOException exc)
          throws IOException {
        Files.delete(dir);
        return FileVisitResult.CONTINUE;
      }

      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
          throws IOException {
        Files.delete(file);
        return FileVisitResult.CONTINUE;
      }
    });
  }

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

  private void loadExistingKeyToCacheDir() throws IOException {
    InputStream in = loadFile(existingKey);
    Path target = dir.resolve(existingKey);
    Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
  }

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