/* 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 org.riotfamily.common.web.cache.annotation; import static org.junit.Assert.*; import java.io.Writer; import java.lang.reflect.Method; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import org.junit.Before; import org.junit.Test; import org.riotfamily.cachius.CacheContext; import org.riotfamily.cachius.CacheService; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletConfig; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.util.NestedServletException; public class CacheAnnotationTests { private DispatcherServlet servlet; @Before public void initServlet() throws ServletException { servlet = new DispatcherServlet() { @Override protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) { GenericWebApplicationContext wac = new GenericWebApplicationContext(); CacheService cacheService = new CacheService(); CacheAnnotationHandlerAdapter handlerAdapter = new CacheAnnotationHandlerAdapter(cacheService, null); wac.getBeanFactory().initializeBean(handlerAdapter, "handlerAdapter"); wac.getBeanFactory().registerSingleton("handlerAdapter", handlerAdapter); wac.registerBeanDefinition("controller1", new RootBeanDefinition(TimeController.class)); wac.registerBeanDefinition("controller2", new RootBeanDefinition(CacheKeyController.class)); wac.registerBeanDefinition("controller3", new RootBeanDefinition(CustomCacheKeyController.class)); wac.registerBeanDefinition("controller4", new RootBeanDefinition(PathVariableController.class)); wac.refresh(); return wac; } }; servlet.init(new MockServletConfig()); } @Test public void uncached() throws Exception { String t1 = get("/time/uncached"); assertTrue("Result must start with 'Uncached'", t1.startsWith("Uncached")); Thread.sleep(10); String t2 = get("/time/uncached"); assertTrue("The two uncached results must differ", !t1.equals(t2)); } @Test public void cached() throws Exception { String t1 = get("/time/cached"); assertTrue("Result must start with 'Cached'", t1.startsWith("Cached")); Thread.sleep(10); String t2 = get("/time/cached"); assertEquals(t1, t2); } @Test public void lastModified() throws Exception { String t1 = get("/time/interval"); assertTrue("Result must start with 'Cached'", t1.startsWith("Interval")); Thread.sleep(10); String t2 = get("/time/interval"); assertEquals(t1, t2); TimeController.lastModified = System.currentTimeMillis(); t2 = get("/time/interval"); assertTrue("Result must differ after changing lastModified: " + t1, !t1.equals(t2)); } @Test public void key() throws Exception { String key = get("/key/generated", "name", "world"); assertTrue(key.endsWith("{world;}")); } @Test(expected=NestedServletException.class) public void invalidArgument() throws Exception { get("/key/invalid"); } @Test public void customKey() throws Exception { String key = get("/key/custom", "name", "world"); assertTrue(key.contains("custom=world")); } @Test public void customPrefix() throws Exception { String key = get("/custom/cached"); assertTrue(key, key.startsWith("custom-cached")); } @Test public void nullPrefix() throws Exception { String t1 = get("/custom/uncached"); assertTrue("Result must start with 'Uncached'", t1.startsWith("Uncached")); Thread.sleep(10); String t2 = get("/custom/uncached"); assertTrue("The two uncached results must differ", !t1.equals(t2)); } @Test public void pathVariable() throws Exception { assertEquals("bar", get("/path/foo/bar")); } public String get(String url, String... params) throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("GET", url); for (int i = 0; i < params.length; i += 2) { request.setParameter(params[i], params[i+1]); } MockHttpServletResponse response = new MockHttpServletResponse(); servlet.service(request, response); return response.getContentAsString(); } @Controller @RequestMapping("/time/*") public static class TimeController { public static long lastModified = System.currentTimeMillis(); @RequestMapping public void uncached(Writer out) throws Exception { out.write("Uncached: " + String.valueOf(System.currentTimeMillis())); } @Cache @RequestMapping public void cached(Writer out) throws Exception { out.write("Cached: " + String.valueOf(System.currentTimeMillis())); } @Cache @RequestMapping public void interval(Writer out) throws Exception { out.write("Interval: " + String.valueOf(System.currentTimeMillis())); } public long getLastModifiedForInterval(Writer out) throws Exception { return lastModified; } } @Controller @RequestMapping("/key/*") public static class CacheKeyController { @Cache @RequestMapping public void generated(Writer out, @RequestParam String name) throws Exception { out.write(CacheContext.getCacheKey()); } @Cache @RequestMapping public void invalid(Writer out, HttpServletRequest request) throws Exception { } @Cache @RequestMapping public void custom(Writer out, @RequestParam String name) throws Exception { out.write(CacheContext.getCacheKey()); } public String getCacheKeyForCustom(Writer out, @RequestParam String name) { return "custom=" + name; } } @Controller @RequestMapping("/custom/*") public static class CustomCacheKeyController { public String getCacheKey(HttpServletRequest request, Method handlerMethod) { if (handlerMethod.getName().equals("uncached")) { return null; } return "custom-" + handlerMethod.getName(); } @Cache @RequestMapping public void uncached(Writer out) throws Exception { out.write("Uncached: " + String.valueOf(System.currentTimeMillis())); } @Cache @RequestMapping public void cached(Writer out) throws Exception { out.write(CacheContext.getCacheKey()); } } @Controller @RequestMapping("/path/*") public static class PathVariableController { @Cache @RequestMapping("foo/{bar}") public void foo(@PathVariable String bar, Writer out) throws Exception { out.write(bar); } } }