blob: c7a7fc6670c97de74f1b92c6932e4602353b42a4 [file] [log] [blame]
// 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.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.httpd.WebSessionManager.Val;
import com.googlesource.gerrit.plugins.websession.flatfile.FlatFileWebSessionCache.TimeMachine;
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 FlatFileWebSessionCacheTest {
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 FlatFileWebSessionCache flatFileWebSessionCache;
private Path dir;
@Before
public void createFlatFileWebSessionCache() throws Exception {
dir = tempFolder.newFolder("websessions").toPath();
flatFileWebSessionCache = new FlatFileWebSessionCache(dir);
}
@Test
public void asMapTest() throws Exception {
loadKeyToCacheDir(EMPTY_KEY);
assertThat(flatFileWebSessionCache.asMap()).isEmpty();
loadKeyToCacheDir(INVALID_KEY);
assertThat(flatFileWebSessionCache.asMap()).isEmpty();
loadKeyToCacheDir(EXISTING_KEY);
assertThat(flatFileWebSessionCache.asMap()).containsKey(EXISTING_KEY);
}
@Test
public void constructorCreateDir() throws IOException {
assertThat(dir.toFile().delete()).isTrue();
flatFileWebSessionCache = new FlatFileWebSessionCache(dir);
assertThat(dir.toFile().exists()).isTrue();
}
@Test
public void cleanUpTest() throws Exception {
loadKeyToCacheDir(EXISTING_KEY);
try {
long existingKeyExpireAt = flatFileWebSessionCache.getIfPresent(EXISTING_KEY).getExpiresAt();
TimeMachine.useFixedClockAt(
Instant.ofEpochMilli(existingKeyExpireAt).minus(1, ChronoUnit.HOURS));
flatFileWebSessionCache.cleanUp();
assertThat(isDirEmpty(dir)).isFalse();
TimeMachine.useFixedClockAt(
Instant.ofEpochMilli(existingKeyExpireAt).plus(1, ChronoUnit.HOURS));
flatFileWebSessionCache.cleanUp();
assertThat(isDirEmpty(dir)).isTrue();
} finally {
TimeMachine.useSystemDefaultZoneClock();
}
}
@Test
public void cleanUpWithErrorsWhileListingFilesTest() throws Exception {
tempFolder.delete();
flatFileWebSessionCache.cleanUp();
assertThat(flatFileWebSessionCache.size()).isEqualTo(0);
}
@Test
public void cleanUpWithErrorsWhileDeleteFileTest() throws Exception {
loadKeyToCacheDir(EXISTING_KEY);
try {
dir.toFile().setWritable(false);
flatFileWebSessionCache.cleanUp();
assertThat(flatFileWebSessionCache.size()).isEqualTo(1);
} finally {
dir.toFile().setWritable(true);
}
}
@Test
public void getIfPresentEmptyKeyTest() throws Exception {
assertThat(flatFileWebSessionCache.getIfPresent(EMPTY_KEY)).isNull();
}
@Test
public void getIfPresentObjectNonStringTest() throws Exception {
assertThat(flatFileWebSessionCache.getIfPresent(new Object())).isNull();
}
@Test
public void getIfPresentInvalidKeyTest() throws Exception {
loadKeyToCacheDir(INVALID_KEY);
Path path = dir.resolve(INVALID_KEY);
assertThat(flatFileWebSessionCache.getIfPresent(path.toString())).isNull();
}
@Test
public void getIfPresentTest() throws Exception {
loadKeyToCacheDir(EXISTING_KEY);
assertThat(flatFileWebSessionCache.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(flatFileWebSessionCache.getAllPresent(keys).size()).isEqualTo(1);
assertThat(flatFileWebSessionCache.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(flatFileWebSessionCache.get(EXISTING_KEY, new ValueLoader())).isNull();
loadKeyToCacheDir(EXISTING_KEY);
assertThat(flatFileWebSessionCache.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(flatFileWebSessionCache.get(EXISTING_KEY, new ValueLoader())).isNull();
}
@Test
public void invalidateAllCollectionTest() throws Exception {
int numberOfKeys = 15;
List<String> keys = loadKeysToCacheDir(numberOfKeys);
assertThat(flatFileWebSessionCache.size()).isEqualTo(numberOfKeys);
assertThat(isDirEmpty(dir)).isFalse();
flatFileWebSessionCache.invalidateAll(keys);
assertThat(flatFileWebSessionCache.size()).isEqualTo(0);
assertThat(isDirEmpty(dir)).isTrue();
}
@Test
public void invalidateAllTest() throws Exception {
int numberOfKeys = 5;
loadKeysToCacheDir(numberOfKeys);
assertThat(flatFileWebSessionCache.size()).isEqualTo(numberOfKeys);
assertThat(isDirEmpty(dir)).isFalse();
flatFileWebSessionCache.invalidateAll();
assertThat(flatFileWebSessionCache.size()).isEqualTo(0);
assertThat(isDirEmpty(dir)).isTrue();
}
@Test
public void invalidateTest() throws Exception {
Path fileToDelete = Files.createFile(dir.resolve(EXISTING_KEY));
assertThat(Files.exists(fileToDelete)).isTrue();
flatFileWebSessionCache.invalidate(EXISTING_KEY);
assertThat(Files.exists(fileToDelete)).isFalse();
}
@Test
public void invalidateTestObjectNotString() throws Exception {
loadKeyToCacheDir(EXISTING_KEY);
assertThat(flatFileWebSessionCache.size()).isEqualTo(1);
flatFileWebSessionCache.invalidate(new Object());
assertThat(flatFileWebSessionCache.size()).isEqualTo(1);
}
@Test
public void putTest() throws Exception {
loadKeyToCacheDir(EXISTING_KEY);
Val val = flatFileWebSessionCache.getIfPresent(EXISTING_KEY);
flatFileWebSessionCache.put(NEW_KEY, val);
assertThat(flatFileWebSessionCache.getIfPresent(NEW_KEY)).isNotNull();
}
@Test
public void putAllTest() throws Exception {
loadKeyToCacheDir(EXISTING_KEY);
Val val = flatFileWebSessionCache.getIfPresent(EXISTING_KEY);
Map<String, Val> sessions = ImmutableMap.of(NEW_KEY, val);
flatFileWebSessionCache.putAll(sessions);
assertThat(flatFileWebSessionCache.asMap()).containsKey(NEW_KEY);
}
@Test
public void putWithErrorsTest() throws Exception {
loadKeyToCacheDir(EXISTING_KEY);
Val val = flatFileWebSessionCache.getIfPresent(EXISTING_KEY);
tempFolder.delete();
flatFileWebSessionCache.put(NEW_KEY, val);
assertThat(flatFileWebSessionCache.getIfPresent(NEW_KEY)).isNull();
}
@Test
public void sizeTest() throws Exception {
int numberOfKeys = 10;
loadKeysToCacheDir(numberOfKeys);
assertThat(flatFileWebSessionCache.size()).isEqualTo(numberOfKeys);
}
@Test
public void statTest() throws Exception {
assertThat(flatFileWebSessionCache.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(dir, "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(dir.resolve(EMPTY_KEY));
}
try (InputStream in = loadFile(key)) {
Path target = dir.resolve(key);
Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
return target;
}
}
private InputStream loadFile(String file) {
return this.getClass().getResourceAsStream("/" + file);
}
}