/** * Copyright (c) 2009 - 2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.common.resteasy.filter; import static org.junit.Assert.*; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.*; import org.candlepin.common.config.Configuration; import org.candlepin.common.config.MapConfiguration; import org.candlepin.common.paging.Page; import org.candlepin.common.paging.PageRequest; import org.jboss.resteasy.core.ServerResponse; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.specimpl.MultivaluedMapImpl; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.net.URI; import java.util.HashMap; import javax.servlet.ServletContext; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriBuilder; public class LinkHeaderResponseFilterTest { @Mock private Configuration config; @Mock private ServerResponse response; @Mock private Page<Object> page; @Mock private PageRequest pageRequest; @Mock private ContainerRequestContext mockRequestContext; @Mock private ContainerResponseContext mockResponseContext; @Mock private ServletContext mockServletContext; private MockHttpRequest mockReq; private String apiUrlPrefixKey; private LinkHeaderResponseFilter interceptor; /* We do not want to load candlepin.conf off the filesystem which is what * happens in Config's constructor. Therefore, we subclass. */ private static class ConfigForTesting extends MapConfiguration { public ConfigForTesting() { super(new HashMap<String, String>() { /* constructor */ { this.put("test_prefix_key", "localhost:8443/candlepin"); } }); } } @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); this.apiUrlPrefixKey = "test_prefix_key"; when(mockServletContext.getContextPath()).thenReturn("/candlepin"); ResteasyProviderFactory.pushContext(ServletContext.class, mockServletContext); interceptor = new LinkHeaderResponseFilter(config, apiUrlPrefixKey); } @After public void tearDown() throws Exception { ResteasyProviderFactory.clearContextData(); } @Test public void testBuildBaseUrlWithConfigPropertyEmpty() throws Exception { when(config.containsKey(eq(this.apiUrlPrefixKey))).thenReturn(true); when(config.getString(eq(this.apiUrlPrefixKey))).thenReturn(""); mockReq = MockHttpRequest.get("https://example.com/candlepin"); when(mockRequestContext.getUriInfo()).thenReturn(mockReq.getUri()); UriBuilder builder = interceptor.buildBaseUrl(mockRequestContext); assertEquals("https://example.com/candlepin", builder.build().toString()); } @Test public void testBuildBaseUrlWithNoConfigProperty() throws Exception { when(config.containsKey(eq(this.apiUrlPrefixKey))).thenReturn(false); mockReq = MockHttpRequest.get("https://example.com/candlepin"); when(mockRequestContext.getUriInfo()).thenReturn(mockReq.getUri()); UriBuilder builder = interceptor.buildBaseUrl(mockRequestContext); assertEquals("https://example.com/candlepin", builder.build().toString()); } @Test public void testBuildBaseUrlWithConfigDefault() throws Exception { mockReq = MockHttpRequest.get("https://example.com/candlepin/resource"); when(mockRequestContext.getUriInfo()).thenReturn(mockReq.getUri()); LinkHeaderResponseFilter interceptorWithDefault = new LinkHeaderResponseFilter(new ConfigForTesting(), this.apiUrlPrefixKey); UriBuilder builder = interceptorWithDefault.buildBaseUrl(mockRequestContext); assertEquals("https://localhost:8443/candlepin/resource", builder.build().toString()); } @Test public void testBuildBaseUrlWithNoSchemeProvided() throws Exception { when(config.containsKey(eq(this.apiUrlPrefixKey))).thenReturn(true); when(config.getString(eq(this.apiUrlPrefixKey))).thenReturn( "localhost:8443/candlepin"); mockReq = MockHttpRequest.get("https://example.com/candlepin/resource"); when(mockRequestContext.getUriInfo()).thenReturn(mockReq.getUri()); UriBuilder builder = interceptor.buildBaseUrl(mockRequestContext); assertEquals("https://localhost:8443/candlepin/resource", builder.build().toString()); } @Test public void testBuildBaseUrlWithBadConfigReturnsNull() throws Exception { when(config.containsKey(eq(this.apiUrlPrefixKey))).thenReturn(true); when(config.getString(eq(this.apiUrlPrefixKey))).thenReturn("localhost:8443/subscriptions"); mockReq = MockHttpRequest.get("https://example.com/candlepin"); when(mockRequestContext.getUriInfo()).thenReturn(mockReq.getUri()); when(mockServletContext.getContextPath()).thenReturn("/subscriptions"); interceptor = new LinkHeaderResponseFilter(config, apiUrlPrefixKey); UriBuilder builder = interceptor.buildBaseUrl(mockRequestContext); assertNull(builder); } @Test public void testAddsUnchangingQueryParameters() { MultivaluedMap<String, String> map = new MultivaluedMapImpl<String, String>(); map.add("baz", "qu=ux"); UriBuilder bu = UriBuilder.fromUri("https://localhost:8443/candlepin/resource"); URI returned = interceptor.addUnchangingQueryParams(bu, map).build(); assertEquals(URI.create("https://localhost:8443/candlepin/resource?baz=qu%3Dux"), returned); } @Test public void testDoesNotAddChangingQueryParameters() { MultivaluedMap<String, String> map = new MultivaluedMapImpl<String, String>(); map.add("page", "10"); UriBuilder bu = UriBuilder.fromUri("https://localhost:8443/candlepin/resource"); URI returned = interceptor.addUnchangingQueryParams(bu, map).build(); assertEquals(URI.create("https://localhost:8443/candlepin/resource"), returned); } @Test public void testDoesNotAddAnythingWhenNoQueryParameters() { UriBuilder bu = UriBuilder.fromUri("https://localhost:8443/candlepin/resource"); URI returned = interceptor.addUnchangingQueryParams(bu, null).build(); assertEquals(URI.create("https://localhost:8443/candlepin/resource"), returned); } @Test public void testBuildPageLink() { UriBuilder bu = UriBuilder.fromUri("https://localhost:8443/candlepin/resource"); assertEquals("https://localhost:8443/candlepin/resource?page=5", interceptor.buildPageLink(bu, 5)); } @Test public void testGetPrevPage() { Page<Object> p = new Page<Object>(); p.setMaxRecords(55); PageRequest pr = new PageRequest(); p.setPageRequest(pr); pr.setPerPage(10); pr.setPage(3); assertEquals(Integer.valueOf(2), interceptor.getPrevPage(p)); } @Test public void testGetPrevPageWhenOnFirstPage() { Page<Object> p = new Page<Object>(); p.setMaxRecords(55); PageRequest pr = new PageRequest(); p.setPageRequest(pr); pr.setPerPage(10); pr.setPage(1); assertNull(interceptor.getPrevPage(p)); } @Test public void testGetNextPage() { Page<Object> p = new Page<Object>(); p.setMaxRecords(55); PageRequest pr = new PageRequest(); p.setPageRequest(pr); pr.setPerPage(10); pr.setPage(3); assertEquals(Integer.valueOf(4), interceptor.getNextPage(p)); } @Test public void testGetNextPageWhenNoNextAvailable() { Page<Object> p = new Page<Object>(); p.setMaxRecords(55); PageRequest pr = new PageRequest(); p.setPageRequest(pr); pr.setPerPage(10); pr.setPage(6); assertNull(interceptor.getNextPage(p)); } @Test public void testGetLastPage() { Page<Object> p = new Page<Object>(); p.setMaxRecords(55); PageRequest pr = new PageRequest(); p.setPageRequest(pr); pr.setPerPage(10); pr.setPage(1); assertEquals(Integer.valueOf(6), interceptor.getLastPage(p)); } @Test public void testGetLastPageWhenMaxRecordsLessThanLimit() { Page<Object> p = new Page<Object>(); p.setMaxRecords(8); PageRequest pr = new PageRequest(); p.setPageRequest(pr); pr.setPerPage(10); pr.setPage(1); assertEquals(Integer.valueOf(1), interceptor.getLastPage(p)); } @Test public void testGetLastPageWhenEvenlyDivisible() { Page<Object> p = new Page<Object>(); p.setMaxRecords(10); PageRequest pr = new PageRequest(); p.setPageRequest(pr); pr.setPerPage(10); pr.setPage(1); assertEquals(Integer.valueOf(1), interceptor.getLastPage(p)); } @Test public void testPagesWithOutOfBoundsInitialPage() { Page<Object> p = new Page<Object>(); p.setMaxRecords(8); PageRequest pr = new PageRequest(); p.setPageRequest(pr); pr.setPerPage(10); pr.setPage(2); assertNull(interceptor.getPrevPage(p)); assertNull(interceptor.getNextPage(p)); assertEquals(Integer.valueOf(1), interceptor.getLastPage(p)); } @Test public void testPostProcessWithNullPage() { // Should just not throw an exception interceptor.filter(mockRequestContext, mockResponseContext); } @Test public void testPostProcessWithNullPageRequest() { ResteasyProviderFactory.pushContext(Page.class, page); when(page.getPageRequest()).thenReturn(null); interceptor.filter(mockRequestContext, mockResponseContext); verify(page).getPageRequest(); } @Test public void testPostProcessWithNonPagingPresentation() { when(page.getPageRequest()).thenReturn(pageRequest); when(pageRequest.isPaging()).thenReturn(false); ResteasyProviderFactory.pushContext(Page.class, page); interceptor.filter(mockRequestContext, mockResponseContext); verify(page, times(2)).getPageRequest(); verify(pageRequest).isPaging(); } @Test public void testPostProcessWithPaging() throws Exception { when(page.getPageRequest()).thenReturn(pageRequest); when(page.getMaxRecords()).thenReturn(15); when(pageRequest.isPaging()).thenReturn(true); when(pageRequest.getPage()).thenReturn(2); when(pageRequest.getPerPage()).thenReturn(5); // We're going to take the quick path through buildBaseUrl. when(config.containsKey(eq(this.apiUrlPrefixKey))).thenReturn(false); MultivaluedMap<String, Object> map = new MultivaluedMapImpl<String, Object>(); when(response.getMetadata()).thenReturn(map); ResteasyProviderFactory.pushContext(Page.class, page); mockReq = MockHttpRequest.create("GET", new URI("/candlepin/resource?order=asc&page=1&per_page=10"), new URI("https://example.com")); when(mockRequestContext.getUriInfo()).thenReturn(mockReq.getUri()); when(mockResponseContext.getHeaders()).thenReturn(map); interceptor.filter(mockRequestContext, mockResponseContext); String header = (String) map.getFirst(LinkHeaderResponseFilter.LINK_HEADER); // It would be a bit much to parse the entire header, so let's just make // sure that we have first, last, next, and prev links. assertTrue(header.contains("rel=\"first\"")); assertTrue(header.contains("rel=\"last\"")); assertTrue(header.contains("rel=\"next\"")); assertTrue(header.contains("rel=\"prev\"")); } }