package org.fcrepo.server.storage; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; import org.apache.http.Header; import org.apache.http.HttpHeaders; import org.fcrepo.common.Constants; import org.fcrepo.common.http.HttpInputStream; import org.fcrepo.common.http.WebClient; import org.fcrepo.common.http.WebClientConfiguration; import org.fcrepo.server.Context; import org.fcrepo.server.Server; import org.fcrepo.server.errors.GeneralException; import org.fcrepo.server.errors.HttpServiceNotFoundException; import org.fcrepo.server.errors.ModuleInitializationException; import org.fcrepo.server.errors.RangeNotSatisfiableException; import org.fcrepo.server.storage.translation.DOTranslationUtility; import org.fcrepo.server.storage.types.MIMETypedStream; import org.fcrepo.server.utilities.ServerUtility; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PowerMockIgnore({"org.slf4j.*", "org.apache.xerces.*", "javax.xml.*", "org.xml.sax.*", "javax.management.*", "javax.net.ssl.*"}) @PrepareForTest({DOTranslationUtility.class, ServerUtility.class}) public class DefaultExternalContentManagerTest { private DefaultExternalContentManager testObj; private static Field webClientField; private static boolean webClientFieldAccessible; private static final String TEST_URL = "http://foo.com/bar"; private static final String HTTP = "http"; @Mock private Server mockServer; @Mock private ContentManagerParams mockParams; @Mock private Context mockContext; @Mock private WebClient mockClient; @Mock private WebClientConfiguration mockClientConfig; @Mock private HttpInputStream mockResponse; @Mock private DOTranslationUtility mockTranslator; @BeforeClass public static void bootstrap() throws NoSuchFieldException, SecurityException { webClientField = DefaultExternalContentManager.class.getDeclaredField("m_http"); webClientFieldAccessible = webClientField.isAccessible(); webClientField.setAccessible(true); } @AfterClass public static void cleanUp() { webClientField.setAccessible(webClientFieldAccessible); } @Before public void setUp() throws ModuleInitializationException, IllegalArgumentException, IllegalAccessException { when(mockServer.getWebClientConfig()).thenReturn(mockClientConfig); testObj = new DefaultExternalContentManager(new HashMap<String, String>(), mockServer, ExternalContentManager.class.getName()); webClientField.set(testObj, mockClient); when(mockParams.getContext()).thenReturn(mockContext); } @Test public void testInit() throws ModuleInitializationException { when(mockClientConfig.getMaxConnPerHost()).thenReturn(5); when(mockClientConfig.getMaxTotalConn()).thenReturn(5); testObj.initModule(); } private void mockResponseFor(String httpMethod) { mockResponseFor(httpMethod, 200); } private void mockResponseFor(String httpMethod, int status) { when(mockParams.getUrl()).thenReturn(TEST_URL); when(mockParams.getProtocol()).thenReturn(HTTP); when(mockContext.getEnvironmentValue(Constants.HTTP_REQUEST.METHOD.attributeId)).thenReturn(httpMethod); String cLen = Long.toString(System.currentTimeMillis()); when(mockResponse.getResponseHeaderValue(HttpHeaders.CONTENT_LENGTH, "-1")).thenReturn(cLen); when(mockResponse.getResponseHeaders()).thenReturn(new Header[0]); when(mockResponse.getStatusCode()).thenReturn(status); when(mockTranslator.makeAbsoluteURLs(TEST_URL)).thenReturn(TEST_URL); when(mockParams.getTranslator()).thenReturn(mockTranslator); mockStatic(ServerUtility.class); when(ServerUtility.isURLFedoraServer(TEST_URL)).thenReturn(false); } @Test public void testPassthroughHeadMethod() throws HttpServiceNotFoundException, GeneralException, IOException, RangeNotSatisfiableException { mockResponseFor("HEAD"); when(mockClient.head(TEST_URL, true, null, null, null, null, null)) .thenReturn(mockResponse); testObj.getExternalContent(mockParams); verify(mockClient).head(TEST_URL, true, null, null, null, null, null); } @Test public void testDefaultToGetMethod() throws HttpServiceNotFoundException, GeneralException, IOException, RangeNotSatisfiableException { mockResponseFor(null); when(mockClient.get(TEST_URL, true, null, null, null, null, null)) .thenReturn(mockResponse); testObj.getExternalContent(mockParams); verify(mockClient).get(TEST_URL, true, null, null, null, null, null); } @Test public void testConditionalGetETagMethod() throws HttpServiceNotFoundException, GeneralException, IOException, RangeNotSatisfiableException { mockResponseFor("GET"); when(mockClient.get(TEST_URL, true, null, null, "LOL", null, null)) .thenReturn(mockResponse); when(mockContext.getHeaderValue(HttpHeaders.IF_NONE_MATCH)).thenReturn("LOL"); testObj.getExternalContent(mockParams); verify(mockClient).get(TEST_URL, true, null, null, "LOL", null, null); } @Test public void testConditionalGetDateMethod() throws HttpServiceNotFoundException, GeneralException, IOException, RangeNotSatisfiableException { mockResponseFor("GET"); when(mockClient.get(TEST_URL, true, null, null, null, "LOL", null)) .thenReturn(mockResponse); when(mockContext.getHeaderValue(HttpHeaders.IF_MODIFIED_SINCE)).thenReturn("LOL"); testObj.getExternalContent(mockParams); verify(mockClient).get(TEST_URL, true, null, null, null, "LOL", null); } @Test public void testConditionalGetRangeMethod() throws HttpServiceNotFoundException, GeneralException, IOException, RangeNotSatisfiableException { mockResponseFor("GET"); when(mockClient.get(TEST_URL, true, null, null, null, null, "LOL")) .thenReturn(mockResponse); when(mockContext.getHeaderValue(HttpHeaders.RANGE)).thenReturn("LOL"); testObj.getExternalContent(mockParams); verify(mockClient).get(TEST_URL, true, null, null, null, null, "LOL"); } @Test public void testConditionalHeadETagMethod() throws HttpServiceNotFoundException, GeneralException, IOException, RangeNotSatisfiableException { mockResponseFor("HEAD",304); when(mockClient.head(TEST_URL, true, null, null, "LOL", null, null)) .thenReturn(mockResponse); when(mockContext.getHeaderValue(HttpHeaders.IF_NONE_MATCH)).thenReturn("LOL"); MIMETypedStream out = testObj.getExternalContent(mockParams); verify(mockClient).head(TEST_URL, true, null, null, "LOL", null, null); assertEquals(304, out.getStatusCode()); } // Supports legacy test runners public static junit.framework.Test suite() { return new junit.framework.JUnit4TestAdapter(DefaultDOManagerTest.class); } }