/**
* 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.resteasy.filter;
import static org.mockito.AdditionalAnswers.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.candlepin.common.paging.PageRequest;
import org.candlepin.model.Owner;
import org.candlepin.resteasy.JsonProvider;
import org.candlepin.test.DatabaseTestFixture;
import org.candlepin.test.SessionWrapper;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import com.google.inject.Provider;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import javax.persistence.EntityManager;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.StreamingOutput;
@RunWith(JUnitParamsRunner.class)
public class CandlepinQueryInterceptorTest extends DatabaseTestFixture {
private static Logger log = LoggerFactory.getLogger(CandlepinQueryInterceptorTest.class);
protected JsonProvider mockJsonProvider;
protected JsonFactory mockJsonFactory;
protected JsonGenerator mockJsonGenerator;
protected ObjectMapper mockObjectMapper;
protected OutputStream mockOutputStream;
protected Provider<EntityManager> emProvider;
@Override
public void init() throws Exception {
super.init();
this.mockJsonProvider = mock(JsonProvider.class);
this.mockJsonFactory = mock(JsonFactory.class);
this.mockJsonGenerator = mock(JsonGenerator.class);
this.mockObjectMapper = mock(ObjectMapper.class);
this.mockOutputStream = mock(OutputStream.class);
try {
when(this.mockJsonProvider.locateMapper(any(Class.class), any(MediaType.class)))
.thenReturn(this.mockObjectMapper);
when(this.mockObjectMapper.getJsonFactory()).thenReturn(this.mockJsonFactory);
when(this.mockJsonFactory.createGenerator(eq(this.mockOutputStream)))
.thenReturn(this.mockJsonGenerator);
}
catch (Exception e) {
throw new RuntimeException(e);
}
// This entire block of mock objects is present to workaround a deadlock issue that occurs
// when attempting to execute two queries against the same table with cursors and lazy
// properties via hsqldb.
this.emProvider = mock(Provider.class);
Session currentSession = (Session) this.getEntityManager().getDelegate();
Session wrappedSession = spy(new SessionWrapper(currentSession));
EntityManager mockEntityManager = mock(EntityManager.class);
Session mockSession = mock(Session.class);
SessionFactory mockSessionFactory = mock(SessionFactory.class);
when(this.emProvider.get()).thenReturn(mockEntityManager);
when(mockEntityManager.getDelegate()).thenReturn(mockSession);
when(mockSession.getSessionFactory()).thenReturn(mockSessionFactory);
when(mockSessionFactory.openSession()).thenReturn(wrappedSession);
doNothing().when(wrappedSession).close();
// Create some owners to play with
for (int i = 0; i < 5; ++i) {
this.createOwner("test-owner-" + (i + 1), "Test Owner " + (i + 1));
}
// Make sure we don't leave any page request on the context to muck with other tests
ResteasyProviderFactory.popContextData(PageRequest.class);
}
@Test
public void testWriteCandlepinQueryContents() throws IOException {
List<Owner> owners = this.ownerCurator.listAll().list();
CandlepinQueryInterceptor cqi = new CandlepinQueryInterceptor(this.mockJsonProvider, this.emProvider);
ServerResponse response = new ServerResponse();
response.setEntity(this.ownerCurator.listAll());
cqi.postProcess(response);
assertTrue(response.getEntity() instanceof StreamingOutput);
((StreamingOutput) response.getEntity()).write(this.mockOutputStream);
verify(this.mockJsonGenerator, times(1)).writeStartArray();
for (Owner owner : owners) {
verify(this.mockObjectMapper, times(1)).writeValue(eq(this.mockJsonGenerator), eq(owner));
}
verify(this.mockJsonGenerator, times(1)).writeEndArray();
}
private Object[][] paramsForPaginatedContentTest() {
return new Object[][] {
new Object[] { 1, 5, "key", PageRequest.Order.ASCENDING },
new Object[] { 1, 5, "key", PageRequest.Order.DESCENDING },
new Object[] { 1, 1, "key", PageRequest.Order.ASCENDING },
new Object[] { 1, 1, "key", PageRequest.Order.DESCENDING },
new Object[] { 2, 2, "key", PageRequest.Order.ASCENDING },
new Object[] { 2, 2, "key", PageRequest.Order.DESCENDING },
new Object[] { 5, 10, "key", PageRequest.Order.ASCENDING },
new Object[] { 5, 10, "key", PageRequest.Order.DESCENDING },
};
}
@Test
@Parameters(method = "paramsForPaginatedContentTest")
public void testWritePaginatedCandlepinQueryContents(int page, int perPage, String sortBy,
PageRequest.Order order) throws IOException {
int offset = (page - 1) * perPage;
int end = offset + perPage;
List<Owner> owners = this.ownerCurator.listAll()
.addOrder(order == PageRequest.Order.ASCENDING ? Order.asc(sortBy) : Order.desc(sortBy))
.list();
PageRequest pageRequest = new PageRequest();
pageRequest.setPage(page);
pageRequest.setPerPage(perPage);
pageRequest.setSortBy(sortBy);
pageRequest.setOrder(order);
CandlepinQueryInterceptor cqi = new CandlepinQueryInterceptor(this.mockJsonProvider, this.emProvider);
ServerResponse response = new ServerResponse();
response.setEntity(this.ownerCurator.listAll());
ResteasyProviderFactory.pushContext(PageRequest.class, pageRequest);
cqi.postProcess(response);
assertTrue(response.getEntity() instanceof StreamingOutput);
((StreamingOutput) response.getEntity()).write(this.mockOutputStream);
verify(this.mockJsonGenerator, times(1)).writeStartArray();
for (int i = 0; i < owners.size(); ++i) {
Owner owner = owners.get(i);
if (i < offset || i >= end) {
verify(this.mockObjectMapper, never()).writeValue(eq(this.mockJsonGenerator), eq(owner));
}
else {
verify(this.mockObjectMapper, times(1)).writeValue(eq(this.mockJsonGenerator), eq(owner));
}
}
verify(this.mockJsonGenerator, times(1)).writeEndArray();
}
@Test
public void testNonCandlepinQueryObjectsAreIgnored() {
// This test can't possibly be all-inclusive, so we'll just test most our common cases
// List of entities
List<Owner> owners = this.ownerCurator.listAll().list();
CandlepinQueryInterceptor cqi = new CandlepinQueryInterceptor(this.mockJsonProvider, this.emProvider);
ServerResponse response = new ServerResponse();
response.setEntity(owners);
cqi.postProcess(response);
assertSame(owners, response.getEntity());
// Single entity
Owner owner = owners.get(0);
response.setEntity(owner);
cqi.postProcess(response);
assertSame(owner, response.getEntity());
}
}