/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package org.fcrepo.server.access;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.fcrepo.server.Context;
import org.fcrepo.server.Module;
import org.fcrepo.server.ReadOnlyContext;
import org.fcrepo.server.Server;
import org.fcrepo.server.errors.DatastreamNotFoundException;
import org.fcrepo.server.errors.ServerException;
import org.fcrepo.server.errors.StreamIOException;
import org.fcrepo.server.security.Authorization;
import org.fcrepo.server.security.DefaultAuthorization;
import org.fcrepo.server.storage.DOReader;
import org.fcrepo.server.storage.DefaultDOManager;
import org.fcrepo.server.storage.types.DatastreamManagedContent;
import org.fcrepo.server.storage.types.MIMETypedStream;
import org.fcrepo.utilities.io.NullInputStream;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import junit.framework.JUnit4TestAdapter;
@RunWith(MockitoJUnitRunner.class)
public class DefaultAccessTest {
private static final String TEST_PID = "lol:wut";
private static final String TEST_DSID = "foo";
private static final String TEST_ETAG_CHECKSUM = "checksum";
@Mock
private Server mockServer;
@Mock
private DefaultAuthorization mockAuthz;
@Mock
private DefaultDOManager mockManager;
@Mock
private Module mockOai;
@Mock
private DOReader mockReader;
private DefaultAccess test;
@Before
public void setUp() throws ServerException {
when(mockServer.getBean("org.fcrepo.server.security.Authorization", Authorization.class)).thenReturn(mockAuthz);
when(mockServer.getModule("org.fcrepo.server.storage.DOManager")).thenReturn(mockManager);
when(mockServer.getModule("org.fcrepo.oai.OAIProvider")).thenReturn(mockOai);
when(mockOai.getParameter("repositoryDomainName")).thenReturn("lol.edu");
when(mockManager.getReader(any(Boolean.class), any(Context.class), any(String.class))).thenReturn(mockReader);
HashMap<String, String> parms = new HashMap<String, String>();
parms.put("doMediateDatastreams", "ok");
test = new DefaultAccess(parms, mockServer, Access.class.getName());
test.initModule();test.postInitModule();
}
private DatastreamManagedContent mockDatastream() throws StreamIOException {
return mockDatastream(NullInputStream.NULL_STREAM, 0);
}
private DatastreamManagedContent mockDatastream(String data) throws StreamIOException {
byte[] bytes = data.getBytes();
return mockDatastream(new ByteArrayInputStream(bytes), bytes.length);
}
private DatastreamManagedContent mockDatastream(InputStream content, long size) throws StreamIOException {
DatastreamManagedContent mock = mock(DatastreamManagedContent.class);
mock.DatastreamID = TEST_DSID;
mock.DSChecksum = TEST_ETAG_CHECKSUM;
mock.DSCreateDT = new Date(System.currentTimeMillis() - 1000);
mock.DSSize = size;
when(mock.getContentStream(any(Context.class))).thenReturn(content);
when(mock.isRepositoryManaged()).thenReturn(true);
return mock;
}
@Test
public void testNormalDatastreamDissemination() throws Exception {
DatastreamManagedContent ds = mockDatastream();
when(mockReader.GetDatastream(any(String.class), any(Date.class))).thenReturn(ds);
Context context = getContext();
MIMETypedStream output = test.getDatastreamDissemination(context, TEST_PID, TEST_DSID, null);
assertEquals(HttpStatus.SC_OK, output.getStatusCode());
}
@Test(expected=DatastreamNotFoundException.class)
public void testMissingDatastreamDissemination() throws Exception {
Context context = getContext();
test.getDatastreamDissemination(context, TEST_PID, TEST_DSID, null);
}
@Test
public void testCachedDatastreamDissemination() throws Exception {
DatastreamManagedContent ds = mockDatastream();
when(mockReader.GetDatastream(any(String.class), any(Date.class))).thenReturn(ds);
Context context = getContext();
// header names are stored and compared lower-cased in ReadOnlyContext
context.getHeaders().set(HttpHeaders.IF_NONE_MATCH.toLowerCase(), TEST_ETAG_CHECKSUM);
MIMETypedStream output = test.getDatastreamDissemination(context, TEST_PID, TEST_DSID, null);
assertEquals(HttpStatus.SC_NOT_MODIFIED, output.getStatusCode());
}
@Test
public void testPartialDatastreamDissemination() throws Exception {
DatastreamManagedContent ds = mockDatastream("0123456789abcdef");
when(mockReader.GetDatastream(any(String.class), any(Date.class))).thenReturn(ds);
Context context = getContext();
// header names are stored and compared lower-cased in ReadOnlyContext
context.getHeaders().set(HttpHeaders.RANGE.toLowerCase(), "bytes=0-12");
MIMETypedStream output = test.getDatastreamDissemination(context, TEST_PID, TEST_DSID, null);
assertEquals(13l,output.getSize());
assertEquals("0123456789abc", IOUtils.toString(output.getStream()));
assertEquals(HttpStatus.SC_PARTIAL_CONTENT, output.getStatusCode());
}
private Context getContext() throws Exception {
return ReadOnlyContext.getContext("http", "lolUser", "wutPassword", false);
}
public static junit.framework.Test suite() {
return new JUnit4TestAdapter(DefaultAccessTest.class);
}
}