/**
*
*/
package org.archive.wayback.accesspoint;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.archive.wayback.QueryRenderer;
import org.archive.wayback.ReplayDispatcher;
import org.archive.wayback.ReplayRenderer;
import org.archive.wayback.ResourceIndex;
import org.archive.wayback.ResourceStore;
import org.archive.wayback.accesscontrol.CollectionContext;
import org.archive.wayback.accesscontrol.ContextExclusionFilterFactory;
import org.archive.wayback.archivalurl.ArchivalUrlRequestParser;
import org.archive.wayback.archivalurl.ArchivalUrlResultURIConverter;
import org.archive.wayback.archivalurl.ArchivalUrlResultURIConverterFactory;
import org.archive.wayback.core.CaptureSearchResult;
import org.archive.wayback.core.CaptureSearchResults;
import org.archive.wayback.core.Resource;
import org.archive.wayback.core.SearchResults;
import org.archive.wayback.core.WaybackRequest;
import org.archive.wayback.replay.html.ContextResultURIConverterFactory;
import org.archive.wayback.resourceindex.filters.ExclusionFilter;
import org.archive.wayback.util.url.KeyMakerUrlCanonicalizer;
import org.archive.wayback.util.webapp.RequestMapper;
import org.archive.wayback.webapp.AccessPointTest;
import org.archive.wayback.webapp.WaybackCollection;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.easymock.LogicalOperator;
/**
* Test for {@link CompositeAccessPoint}.
*/
public class CompositeAccessPointTest extends TestCase {
CompositeAccessPoint cut;
AccessPointConfigs configs;
WaybackCollection collection;
ResourceStore resourceStore;
ResourceIndex resourceIndex;
RequestDispatcher requestDispatcher;
//RequestParser parser;
// ResultURIConverter uriConverter;
QueryRenderer query;
ReplayDispatcher replay;
ReplayRenderer replayRenderer;
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
cut = new CompositeAccessPoint();
// this is passed to ContextResultURIConverterFactory by
// AccessPointAdapter#getUriConverter()
cut.setReplayPrefix("/");
cut.setEnableMemento(false);
configs = new AccessPointConfigs();
AccessPointConfig config1 = new AccessPointConfig();
config1.setBeanName("1001");
AccessPointConfig config2 = new AccessPointConfig();
config2.setBeanName("2604");
HashMap<String, AccessPointConfig> configsMap = new HashMap<String, AccessPointConfig>();
configsMap.put(config1.getBeanName(), config1);
configsMap.put(config2.getBeanName(), config2);
configs.setAccessPointConfigs(configsMap);
cut.setAccessPointConfigs(configs);
// XXX following lines are copied from AccessPointTest#setUp()
// share the code.
KeyMakerUrlCanonicalizer canonicalizer = new KeyMakerUrlCanonicalizer();
cut.setSelfRedirectCanonicalizer(canonicalizer);
resourceStore = EasyMock.createMock(ResourceStore.class);
resourceIndex = EasyMock.createMock(ResourceIndex.class);
collection = new WaybackCollection();
collection.setResourceIndex(resourceIndex);
collection.setResourceStore(resourceStore);
cut.setCollection(collection);
// RequestDispatcher - setup expectations, call replay() and verify() if
// method calls are expected.
requestDispatcher = EasyMock.createMock(RequestDispatcher.class);
// Memento mode - only called when enableMemento==true.
// EasyMock.expect(httpRequest.getHeader(MementoUtils.ACCEPT_DATETIME)).andReturn(null);
ArchivalUrlRequestParser parser = new ArchivalUrlRequestParser();
parser.init();
cut.setParser(parser);
query = EasyMock.createMock(QueryRenderer.class);
cut.setQuery(query);
replay = EasyMock.createMock(ReplayDispatcher.class);
cut.setReplay(replay);
replayRenderer = EasyMock.createMock(ReplayRenderer.class);
// This ResultURIConverter shall be ignored.
{
ArchivalUrlResultURIConverter uc = new ArchivalUrlResultURIConverter();
uc.setReplayURIPrefix("/web/");
cut.setUriConverter(uc);
}
// AccessPointAdapter shall use this ContextResultURIConverterFactory for
// creating per-AccessPoint ResultURIConverter
{
ContextResultURIConverterFactory uriConverterFactory = new ArchivalUrlResultURIConverterFactory();
cut.setUriConverterFactory(uriConverterFactory);
}
}
static final Comparator<CollectionContext> collectionContextComp = new Comparator<CollectionContext>() {
public int compare(CollectionContext o1, CollectionContext o2) {
return o1.getCollectionContextName().compareTo(o2.getCollectionContextName());
};
};
/**
* Test of {@code handleRequest()}.
* Only thing we test here is {@code createExclusionFilter()}.
* @throws Exception
*/
public void testHandleRequest() throws Exception {
HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
EasyMock.expect(request.getAttribute(RequestMapper.REQUEST_CONTEXT_PREFIX)).andStubReturn(null);
// TODO: requestURI can start with "/"
EasyMock.expect(request.getRequestURI()).andStubReturn("2604/2/http://example.com/");
EasyMock.expect(request.getLocale()).andStubReturn(Locale.US);
HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
// Wow, this is way too complex - something must be wrong with the design.
// Looks comples, but the point is to test if collection name is passed
// to ContextExclusionFilterFactory.getExclusionFilter().
CollectionContext expectedContext = new CollectionContext() {
@Override
public String getCollectionContextName() {
return "2604";
}
};
ContextExclusionFilterFactory exclusionFactory = EasyMock.createMock(ContextExclusionFilterFactory.class);
// currently this is invoked twice for a replay request - should be just once.
EasyMock.expect(
exclusionFactory.getExclusionFilter(EasyMock.cmp(expectedContext,
collectionContextComp, LogicalOperator.EQUAL))).andReturn(
new ExclusionFilter() {
@Override
public int filterObject(CaptureSearchResult o) {
return FILTER_INCLUDE;
}
}).atLeastOnce();
cut.setExclusionFactory(exclusionFactory);
Resource resource = AccessPointTest.createTestHtmlResource("http://example.com/", "20140101000000", "<html></html>".getBytes());
final CaptureSearchResults results = AccessPointTest.setupCaptures(resourceIndex, resourceStore, 0, resource);
EasyMock
.expect(resourceIndex.query(EasyMock.<WaybackRequest>notNull()))
.andAnswer(new IAnswer<SearchResults>() {
@Override
public SearchResults answer() throws Throwable {
WaybackRequest wbRequest = (WaybackRequest)EasyMock
.getCurrentArguments()[0];
// This emulates key ResourceIndex behavior
wbRequest.getAccessPoint().createExclusionFilter();
return results;
}
});
EasyMock.expect(replay.getClosest(EasyMock.<WaybackRequest>notNull(), EasyMock.<CaptureSearchResults>notNull())).andReturn(
results.getClosest());
response.setStatus(302);
// Redirect URL shall have collection name, not "web" (see ResultURIConverter setup above).
response.setHeader(EasyMock.matches("(?i)location"),
EasyMock.eq("/2604/20140101000000/http://example.com/"));
// XXX currently Memento is always enabled in AccessPointAdapter
// no matter what value CompositeAccessPoint.enableMemento has.
response.setHeader(EasyMock.matches("(?i)link"), EasyMock.<String>notNull());
EasyMock.expect(response.getWriter()).andReturn(new PrintWriter(new StringWriter()));
EasyMock.replay(request, response, exclusionFactory,
resourceStore, resourceIndex, query, replay, replayRenderer);
cut.handleRequest(request, response);
}
}