// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.data.cache;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import org.apache.commons.jcs.access.behavior.ICacheAccess;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.cache.ICachedLoaderListener.LoadResult;
import org.openstreetmap.josm.testutils.JOSMTestRules;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Unit tests for class {@link JCSCachedTileLoaderJob}.
*/
public class JCSCachedTileLoaderJobTest {
private static class TestCachedTileLoaderJob extends JCSCachedTileLoaderJob<String, CacheEntry> {
private String url;
private String key;
TestCachedTileLoaderJob(String url, String key) throws IOException {
super(getCache(), 30000, 30000, null);
this.url = url;
this.key = key;
}
@Override
public String getCacheKey() {
return key;
}
@Override
public URL getUrl() {
try {
return new URL(url);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
@Override
protected CacheEntry createCacheEntry(byte[] content) {
return new CacheEntry("dummy".getBytes(StandardCharsets.UTF_8));
}
}
private static class Listener implements ICachedLoaderListener {
private CacheEntryAttributes attributes;
private boolean ready;
private LoadResult result;
@Override
public synchronized void loadingFinished(CacheEntry data, CacheEntryAttributes attributes, LoadResult result) {
this.attributes = attributes;
this.ready = true;
this.result = result;
this.notifyAll();
}
}
/**
* Setup test.
*/
@Rule
@SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
public JOSMTestRules test = new JOSMTestRules().preferences();
/**
* Always clear cache before tests
* @throws Exception when clearing fails
*/
@Before
public void clearCache() throws Exception {
getCache().clear();
}
/**
* Test status codes
* @throws InterruptedException in case of thread interruption
* @throws IOException in case of I/O error
*/
@Test
public void testStatusCodes() throws IOException, InterruptedException {
doTestStatusCode(200);
// can't test for 3xx, as httpstat.us redirects finally to 200 page
doTestStatusCode(401);
doTestStatusCode(402);
doTestStatusCode(403);
doTestStatusCode(404);
doTestStatusCode(405);
doTestStatusCode(500);
doTestStatusCode(501);
doTestStatusCode(502);
}
/**
* Test unknown host
* @throws IOException in case of I/O error
*/
@Test
public void testUnknownHost() throws IOException {
String key = "key_unknown_host";
TestCachedTileLoaderJob job = new TestCachedTileLoaderJob("http://unkownhost.unkownhost/unkown", key);
Listener listener = new Listener();
job.submit(listener, true);
synchronized (listener) {
while (!listener.ready) {
try {
listener.wait();
} catch (InterruptedException e1) {
// do nothing, still wait
Main.trace(e1);
}
}
}
assertEquals(LoadResult.FAILURE, listener.result); // because response will be cached, and that is checked below
assertEquals("java.net.UnknownHostException: unkownhost.unkownhost", listener.attributes.getErrorMessage());
ICacheAccess<String, CacheEntry> cache = getCache();
CacheEntry e = new CacheEntry(new byte[]{0, 1, 2, 3});
CacheEntryAttributes attributes = new CacheEntryAttributes();
attributes.setExpirationTime(2);
cache.put(key, e, attributes);
job = new TestCachedTileLoaderJob("http://unkownhost.unkownhost/unkown", key);
listener = new Listener();
job.submit(listener, true);
synchronized (listener) {
while (!listener.ready) {
try {
listener.wait();
} catch (InterruptedException e1) {
// do nothing, wait
Main.trace(e1);
}
}
}
assertEquals(LoadResult.SUCCESS, listener.result);
assertFalse(job.isCacheElementValid());
}
@SuppressFBWarnings(value = "WA_NOT_IN_LOOP")
private void doTestStatusCode(int responseCode) throws IOException, InterruptedException {
TestCachedTileLoaderJob job = getStatusLoaderJob(responseCode);
Listener listener = new Listener();
job.submit(listener, true);
synchronized (listener) {
if (!listener.ready) {
listener.wait();
}
}
assertEquals(responseCode, listener.attributes.getResponseCode());
}
private static TestCachedTileLoaderJob getStatusLoaderJob(int responseCode) throws IOException {
return new TestCachedTileLoaderJob("http://httpstat.us/" + responseCode, "key_" + responseCode);
}
private static ICacheAccess<String, CacheEntry> getCache() throws IOException {
return JCSCacheManager.getCache("test");
}
}