// 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 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);
  }
}
