blob: d545d9c3c55438634c116276f247013045a691a5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.manifoldcf.crawler.connectors.alfrescowebscript;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.alfresco.consulting.indexer.client.AlfrescoClient;
import org.alfresco.consulting.indexer.client.AlfrescoFilters;
import org.alfresco.consulting.indexer.client.AlfrescoResponse;
import org.apache.manifoldcf.agents.interfaces.RepositoryDocument;
import org.apache.manifoldcf.core.interfaces.ManifoldCFException;
import org.apache.manifoldcf.core.interfaces.Specification;
import org.apache.manifoldcf.crawler.connectors.BaseRepositoryConnector;
import org.apache.manifoldcf.crawler.connectors.alfrescowebscript.AlfrescoConnector;
import org.apache.manifoldcf.crawler.interfaces.IExistingVersions;
import org.apache.manifoldcf.crawler.interfaces.IProcessActivity;
import org.apache.manifoldcf.crawler.system.SeedingActivity;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class AlfrescoConnectorTest {
@Mock
private AlfrescoClient client;
private AlfrescoConnector connector;
@Before
public void setup() throws Exception {
connector = new AlfrescoConnector();
connector.setClient(client);
when(client.fetchNodes(anyInt(), anyInt(), Mockito.any(AlfrescoFilters.class)))
.thenReturn(new AlfrescoResponse(
0, 0, "", "", Collections.<Map<String, Object>>emptyList()));
}
@Test
public void whenAddingSeedDocumentTheAlfrescoClientShouldBeUsed() throws Exception {
SeedingActivity activities = mock(SeedingActivity.class);
Specification spec = new Specification();
long seedTime = 0;
connector.addSeedDocuments(activities, spec, "", seedTime, BaseRepositoryConnector.JOBMODE_ONCEONLY);
verify(client).fetchNodes(anyInt(), anyInt(), Mockito.any(AlfrescoFilters.class));
}
@Test
public void whenTheClientIsCalledItShouldUseThePreviouslySentLastTransactionId() throws
Exception {
long firstTransactionId = 0;
long lastTransactionId = 5;
long firstAclChangesetId = 0;
long lastAclChangesetId = 5;
when(client.fetchNodes(anyInt(), anyInt(), Mockito.any(AlfrescoFilters.class)))
.thenReturn(new AlfrescoResponse(
lastTransactionId, lastAclChangesetId));
connector.addSeedDocuments(mock(SeedingActivity.class),
new Specification(), "", 0, BaseRepositoryConnector.JOBMODE_ONCEONLY);
verify(client, times(1)).fetchNodes(eq(firstTransactionId), eq(firstAclChangesetId), Mockito.any(AlfrescoFilters.class));
verify(client, times(1)).fetchNodes(eq(lastTransactionId), eq(lastAclChangesetId), Mockito.any(AlfrescoFilters.class));
}
@Test
public void whenADocumentIsReturnedItShouldBeAddedToManifold() throws Exception {
TestDocument testDocument = new TestDocument();
when(client.fetchNodes(anyInt(), anyInt(), Mockito.any(AlfrescoFilters.class)))
.thenReturn(new AlfrescoResponse(0, 0, "", "",
Arrays.<Map<String, Object>>asList(testDocument)));
SeedingActivity seedingActivity = mock(SeedingActivity.class);
connector.addSeedDocuments(seedingActivity, new Specification(), "", 0, BaseRepositoryConnector.JOBMODE_ONCEONLY);
verify(seedingActivity).addSeedDocument(eq(TestDocument.uuid));
}
@Test
public void whenProcessingDocumentsNodeRefsAreUsedAsDocumentURI() throws Exception {
TestDocument testDocument = new TestDocument();
testDocument.put("cm:modified","2014-10-02T16:15:25.124Z");
testDocument.put("size","115");
testDocument.put("mimetype","text/plain");
IProcessActivity activities = mock(IProcessActivity.class);
when(activities.checkDocumentNeedsReindexing(anyString(),anyString()))
.thenReturn(true);
when(activities.checkLengthIndexable(anyLong()))
.thenReturn(true);
when(activities.checkMimeTypeIndexable(anyString()))
.thenReturn(true);
IExistingVersions statuses = mock(IExistingVersions.class);
when(client.fetchNode(anyString()))
.thenReturn(new AlfrescoResponse(0, 0, "", "",
Arrays.<Map<String, Object>>asList(testDocument)));
when(client.fetchMetadata(anyString()))
.thenReturn(testDocument);
// processDocuments(String[] documentIdentifiers, IExistingVersions statuses, Specification spec,
// IProcessActivity activities, int jobMode, boolean usesDefaultAuthority)
connector.processDocuments(new String[]{TestDocument.uuid}, statuses, new Specification(), activities, 0, true);
ArgumentCaptor<RepositoryDocument> rd = ArgumentCaptor.forClass(RepositoryDocument.class);
verify(activities)
.checkDocumentNeedsReindexing(eq(TestDocument.uuid), eq("1412266525124"));
verify(activities)
.checkLengthIndexable(eq(115L));
verify(activities)
.checkMimeTypeIndexable(eq("text/plain"));
verify(activities)
.ingestDocumentWithException(eq(TestDocument.uuid), anyString(),
eq(TestDocument.nodeRef), rd.capture());
Iterator<String> i = rd.getValue().getFields();
while(i.hasNext()) {
String fieldName = i.next();
Object value1 = rd.getValue().getField(fieldName)[0];
Object[] values = testDocument.getRepositoryDocument().getField(fieldName);
if (values == null) {
System.out.println("field "+fieldName+"has no value in testDocument");
continue;
}
Object value2 = testDocument.getRepositoryDocument().getField(fieldName)[0];
assert value1.equals(value2);
}
}
@Test
public void whenProcessingDeletionShouldBeRegisteredAsDeletions() throws Exception {
TestDocument testDocument = new TestDocument();
testDocument.setDeleted(true);
when(client.fetchNode(anyString()))
.thenReturn(new AlfrescoResponse(0, 0, "", "",
Arrays.<Map<String, Object>>asList(testDocument)));
IProcessActivity activities = mock(IProcessActivity.class);
IExistingVersions statuses = mock(IExistingVersions.class);
connector.processDocuments(new String[]{TestDocument.uuid}, statuses, new Specification(), activities, 0, true);
verify(activities).deleteDocument(eq(TestDocument.uuid));
verify(activities, never()).ingestDocumentWithException(eq(TestDocument.uuid), anyString(), anyString(),
any(RepositoryDocument.class));
}
@SuppressWarnings("serial")
private class TestDocument extends HashMap<String, Object> {
static final String uuid = "abc123";
static final String type = "cm:content";
static final String nodeRef = "workspace://abc123";
static final boolean deleted = false;
static final String storeId = "SpacesStore";
static final String storeProtocol = "workspace";
static final String name = "test";
public TestDocument() {
super();
put("uuid", uuid);
put("type", type);
put("deleted", deleted);
put("store_id", storeId);
put("store_protocol", storeProtocol);
put("nodeRef", nodeRef);
put("name", name);
}
public void setDeleted(boolean deleted) {
put("deleted", deleted);
}
public RepositoryDocument getRepositoryDocument() throws ManifoldCFException {
RepositoryDocument rd = new RepositoryDocument();
rd.setFileName(uuid);
for(String property : keySet()) {
rd.addField(property,get(property).toString());
}
return rd;
}
}
}