package com.bazaarvoice.auth.hmac.server; import com.bazaarvoice.auth.hmac.common.Credentials; import org.junit.Test; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static com.bazaarvoice.auth.hmac.server.TestCredentials.createCredentials; import static org.junit.Assert.assertEquals; public class AbstractCachingAuthenticatorTest { public static final Credentials aCredentials = createCredentials("a", "a"); public static final Credentials bCredentials = createCredentials("b", "b"); public static final Credentials cCredentials = createCredentials("c", "c"); @Test public void testCacheWorks() { // do two requests for 'a', three requests for 'b', one request for 'c'; make sure we get only three calls to load Authenticator unit = new Authenticator(5000, 20); unit.authenticate(aCredentials); unit.authenticate(aCredentials); unit.authenticate(bCredentials); unit.authenticate(bCredentials); unit.authenticate(bCredentials); unit.authenticate(cCredentials); assertEquals(3, unit.getNumLoads()); } @Test public void testClearCache() { // do three requests for 'b', followed by a cache clear, then two requests for 'b'; ensure we get only 2 calls to load Authenticator unit = new Authenticator(5000, 20); unit.authenticate(bCredentials); unit.authenticate(bCredentials); unit.authenticate(bCredentials); unit.clearCache(); unit.authenticate(bCredentials); unit.authenticate(bCredentials); assertEquals(2, unit.getNumLoads()); } @Test public void testCacheSize() { // do a request for each of 'a', 'b', 'c' in a cache that can't hold that many, and do it several times; // ensure that the cache was never used Authenticator unit = new Authenticator(5000, 2); // only holds 2 things unit.authenticate(aCredentials); unit.authenticate(bCredentials); unit.authenticate(cCredentials); unit.authenticate(aCredentials); unit.authenticate(bCredentials); unit.authenticate(cCredentials); unit.authenticate(aCredentials); unit.authenticate(bCredentials); unit.authenticate(cCredentials); assertEquals(9, unit.getNumLoads()); } @Test public void testCacheExpiration() throws InterruptedException { // do a request for each of 'a', 'b', 'c' a few times, then sleep a bit longer than the cache timeout; // ensure that the cache was invalidated appropriately Authenticator unit = new Authenticator(300, 20); unit.authenticate(aCredentials); unit.authenticate(bCredentials); unit.authenticate(cCredentials); unit.authenticate(aCredentials); unit.authenticate(bCredentials); unit.authenticate(cCredentials); Thread.sleep(310); unit.authenticate(aCredentials); unit.authenticate(aCredentials); unit.authenticate(aCredentials); unit.authenticate(bCredentials); unit.authenticate(bCredentials); unit.authenticate(bCredentials); unit.authenticate(cCredentials); unit.authenticate(cCredentials); unit.authenticate(cCredentials); assertEquals(6, unit.getNumLoads()); } @Test public void testApiKeyIsTheKey() throws InterruptedException { // two requests that are different in time or path alone should still resolve to the same cache Authenticator unit = new Authenticator(300, 20); unit.authenticate(aCredentials); Thread.sleep(10); unit.authenticate(createCredentials("a", "a")); assertEquals(1, unit.getNumLoads()); } @Test public void testPrecache() { Authenticator unit = new Authenticator(300, 20); unit.cachePrincipal(aCredentials.getApiKey(), new SimplePrincipal("a")); unit.cachePrincipal(bCredentials.getApiKey(), new SimplePrincipal("b")); unit.authenticate(aCredentials); unit.authenticate(bCredentials); assertEquals(0, unit.getNumLoads()); } private static class Authenticator extends AbstractCachingAuthenticator<SimplePrincipal> { private final AtomicInteger numLoads = new AtomicInteger(0); public int getNumLoads() { return numLoads.get(); } public Authenticator(int cacheTimeoutMillis, int maxCacheElements) { super(5000, cacheTimeoutMillis, TimeUnit.MILLISECONDS, maxCacheElements); } @Override protected SimplePrincipal loadPrincipal(Credentials credentials) { numLoads.incrementAndGet(); return new SimplePrincipal(credentials.getApiKey()); } @Override protected String getSecretKeyFromPrincipal(SimplePrincipal principal) { return principal.id; } } static class SimplePrincipal { private final String id; SimplePrincipal(String id) { this.id = id; } } }