/* (C) 2015 - 2016 Open Source Geospatial Foundation. All rights reserved. * (C) 2007 - 2014 GeoSolutions S.A.S. * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.geofence; import java.util.logging.Level; import java.util.logging.Logger; import org.geoserver.geofence.cache.CacheConfiguration; import org.geoserver.geofence.cache.CachedRuleReader; import org.geoserver.geofence.config.GeoFencePropertyPlaceholderConfigurer; import org.geoserver.geofence.services.RuleReaderService; import org.geoserver.geofence.services.dto.AccessInfo; import org.geoserver.geofence.services.dto.RuleFilter; import org.geotools.util.logging.Logging; import org.springframework.core.io.UrlResource; import com.google.common.base.Ticker; /** * * @author ETj (etj at geo-solutions.it) */ public class CacheReaderTest extends GeofenceBaseTest { static final Logger LOGGER = Logging.getLogger(CacheReaderTest.class); private RuleReaderService realReader; private GeoFencePropertyPlaceholderConfigurer configurer; @Override protected void setUpInternal() throws Exception { super.setUpInternal(); configurer = (GeoFencePropertyPlaceholderConfigurer) applicationContext.getBean("geofence-configurer"); configurer.setLocation(new UrlResource(this.getClass().getResource("/test-cache-config.properties"))); realReader = applicationContext.getBean("remoteReaderService", RuleReaderService.class); } static class CustomTicker extends Ticker { private long nano = 0; @Override public long read() { return nano; } public void setMillisec(long milli) { this.nano = milli * 1000000; } } public void IGNOREtestSize() { CustomTicker ticker = new CustomTicker(); CacheConfiguration config = new CacheConfiguration(); config.setSize(2); config.setRefreshMilliSec(500); config.setExpireMilliSec(1000); config.setCustomTicker(ticker); configManager.setCacheConfiguration(config); CachedRuleReader cachedRuleReader = new CachedRuleReader(configManager); cachedRuleReader.setRealRuleReaderService(realReader); System.out.println(cachedRuleReader.getStats()); assertEquals(0, cachedRuleReader.getStats().hitCount()); assertEquals(0, cachedRuleReader.getStats().missCount()); assertEquals(0, cachedRuleReader.getStats().evictionCount()); RuleFilter filter1 = new RuleFilter(); filter1.setUser("test_1"); RuleFilter filter2 = new RuleFilter(); filter2.setUser("test_2"); RuleFilter filter3 = new RuleFilter(); filter3.setUser("test_3"); assertNotSame(filter1, filter2); // expected stats int hitExp = 0; int missExp = 0; int evictExp = 0; // first loading, obviously a miss AccessInfo ai1_1= cachedRuleReader.getAccessInfo(filter1); System.out.println(cachedRuleReader.getStats()); assertEquals(hitExp, cachedRuleReader.getStats().hitCount()); assertEquals(++missExp, cachedRuleReader.getStats().missCount()); assertEquals(evictExp, cachedRuleReader.getStats().evictionCount()); // second loading with the same rule, should be a hit ticker.setMillisec(1); AccessInfo ai1_2= cachedRuleReader.getAccessInfo(filter1); System.out.println(cachedRuleReader.getStats()); assertEquals(++hitExp, cachedRuleReader.getStats().hitCount()); assertEquals(missExp, cachedRuleReader.getStats().missCount()); assertEquals(evictExp, cachedRuleReader.getStats().evictionCount()); assertEquals(ai1_1, ai1_2); // loading a different filter, a miss again ticker.setMillisec(2); AccessInfo ai2= cachedRuleReader.getAccessInfo(filter2); System.out.println(cachedRuleReader.getStats()); assertEquals(hitExp, cachedRuleReader.getStats().hitCount()); assertEquals(++missExp, cachedRuleReader.getStats().missCount()); assertEquals(evictExp, cachedRuleReader.getStats().evictionCount()); // yet another different filter. we expect a miss, and an eviction ticker.setMillisec(3); AccessInfo ai3= cachedRuleReader.getAccessInfo(filter3); System.out.println(cachedRuleReader.getStats()); assertEquals(hitExp, cachedRuleReader.getStats().hitCount()); assertEquals(++missExp, cachedRuleReader.getStats().missCount()); assertEquals(++evictExp, cachedRuleReader.getStats().evictionCount()); // filter1 is the oldest one: ticker.setMillisec(4); cachedRuleReader.getAccessInfo(filter2); System.out.println(cachedRuleReader.getStats()); assertEquals(++hitExp, cachedRuleReader.getStats().hitCount()); ticker.setMillisec(5); cachedRuleReader.getAccessInfo(filter3); System.out.println(cachedRuleReader.getStats()); assertEquals(++hitExp, cachedRuleReader.getStats().hitCount()); // reload filter1, ==> filter 2 should be evicted ticker.setMillisec(6); cachedRuleReader.getAccessInfo(filter1); System.out.println(cachedRuleReader.getStats()); assertEquals(hitExp, cachedRuleReader.getStats().hitCount()); assertEquals(++missExp, cachedRuleReader.getStats().missCount()); assertEquals(++evictExp, cachedRuleReader.getStats().evictionCount()); } public void testExpire() throws InterruptedException { CustomTicker ticker = new CustomTicker(); CacheConfiguration config = new CacheConfiguration(); config.setSize(100); config.setRefreshMilliSec(500); config.setExpireMilliSec(1000); config.setCustomTicker(ticker); configManager.setCacheConfiguration(config); CachedRuleReader cachedRuleReader = new CachedRuleReader(configManager); cachedRuleReader.setRealRuleReaderService(realReader); cachedRuleReader.getCacheInitParams().setSize(100); cachedRuleReader.getCacheInitParams().setRefreshMilliSec(500); cachedRuleReader.getCacheInitParams().setExpireMilliSec(1000); cachedRuleReader.getCacheInitParams().setCustomTicker(ticker); cachedRuleReader.init(); System.out.println(cachedRuleReader.getStats()); assertEquals(0, cachedRuleReader.getStats().hitCount()); assertEquals(0, cachedRuleReader.getStats().missCount()); assertEquals(0, cachedRuleReader.getStats().evictionCount()); RuleFilter filter1 = new RuleFilter(); filter1.setUser("test_1"); RuleFilter filter2 = new RuleFilter(); filter2.setUser("test_2"); RuleFilter filter3 = new RuleFilter(); filter3.setUser("test_3"); int hitExp = 0; int missExp = 0; int evictExp = 0; // first loading AccessInfo ai1_1= cachedRuleReader.getAccessInfo(filter1); System.out.println(cachedRuleReader.getStats()); assertEquals(hitExp, cachedRuleReader.getStats().hitCount()); assertEquals(++missExp, cachedRuleReader.getStats().missCount()); assertEquals(evictExp, cachedRuleReader.getStats().evictionCount()); // second loading with the same rule, should be a hit ticker.setMillisec(1); AccessInfo ai1_2= cachedRuleReader.getAccessInfo(filter1); System.out.println(cachedRuleReader.getStats()); assertEquals(++hitExp, cachedRuleReader.getStats().hitCount()); assertEquals(missExp, cachedRuleReader.getStats().missCount()); assertEquals(evictExp, cachedRuleReader.getStats().evictionCount()); assertEquals(1, cachedRuleReader.getStats().loadSuccessCount()); assertEquals(ai1_1, ai1_2); // loading the same filter, after the refresh time ticker.setMillisec(600); // LOGGER.log(Level.INFO, "We expect a reload() now...."); System.out.println("---> We expect a reload() now...."); AccessInfo ai1_3= cachedRuleReader.getAccessInfo(filter1); System.out.println(cachedRuleReader.getStats()); assertEquals(++hitExp, cachedRuleReader.getStats().hitCount()); assertEquals(missExp, cachedRuleReader.getStats().missCount()); assertEquals(evictExp, cachedRuleReader.getStats().evictionCount()); // assertEquals(2, cachedRuleReader.getStats().loadSuccessCount()); // dunno if load is made asynch or not // reloading should have been triggered ticker.setMillisec(700); System.out.println("sleeping..."); Thread.sleep(500); System.out.println(cachedRuleReader.getStats()); assertEquals(hitExp, cachedRuleReader.getStats().hitCount()); assertEquals(missExp, cachedRuleReader.getStats().missCount()); assertEquals(evictExp, cachedRuleReader.getStats().evictionCount()); // assertEquals(2, cachedRuleReader.getStats().loadSuccessCount()); // uhm, this does not work if(2!=cachedRuleReader.getStats().loadSuccessCount()) LOGGER.log(Level.SEVERE, "*** Bad successCount check, expected 2, found {0}", cachedRuleReader.getStats().loadSuccessCount()); ticker.setMillisec(800); cachedRuleReader.getAccessInfo(filter1); System.out.println(cachedRuleReader.getStats()); ticker.setMillisec(2000); cachedRuleReader.getAccessInfo(filter1); System.out.println(cachedRuleReader.getStats()); } // public void testSave() throws IOException, URISyntaxException { // GeofenceTestUtils.emptyFile("test-cache-config.properties"); // // CacheConfiguration params = new CacheConfiguration(); // params.setSize(100); // params.setRefreshMilliSec(500); // params.setExpireMilliSec(1000); // // configManager.setCacheConfiguration(params); // // CachedRuleReader cachedRuleReader = new CachedRuleReader(configManager); // // // cachedRuleReader.saveConfiguration(params); // String content = GeofenceTestUtils.readConfig("test-cache-config.properties"); // assertEquals("cacheSize=100cacheRefresh=500cacheExpire=1000", content); // } }