blob: 3063de45e7fa388ccf4ff5ea3e77028645279fd0 [file] [log] [blame]
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed 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 com.google.enterprise.adaptor.prebuilt;
import static com.google.enterprise.adaptor.TestHelper.getDocIds;
import static java.util.Map.Entry;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import com.google.enterprise.adaptor.Acl;
import com.google.enterprise.adaptor.AuthnIdentity;
import com.google.enterprise.adaptor.AuthzStatus;
import com.google.enterprise.adaptor.DocId;
import com.google.enterprise.adaptor.GroupPrincipal;
import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.Request;
import com.google.enterprise.adaptor.Response;
import com.google.enterprise.adaptor.UserPrincipal;
import com.google.enterprise.adaptor.prebuilt.StreamingCommand.InputSource;
import com.google.enterprise.adaptor.prebuilt.StreamingCommand.OutputSink;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* Tests for {@link CommandLineAdaptor}.
*/
public class CommandLineAdaptorTest {
private final Charset charset = Charset.forName("US-ASCII");
private static class CommandLineAdaptorTestMock extends CommandLineAdaptor {
static final List<DocId> original = Arrays.asList(new DocId[] {
new DocId("1001"),
new DocId("1002"),
new DocId("1003"),
});
@Override
public int executeLister(String[] command, InputSource stdin, final OutputSink stdout,
OutputSink stderr) throws IOException, InterruptedException {
assertEquals(command[0], "./lister_cmd.sh");
assertEquals(command[1], "lister_arg1");
final StringBuilder result = new StringBuilder();
result.append("GSA Adaptor Data Version 1 [\n]\n");
for (DocId docId : original) {
result.append("id=").append(docId.getUniqueId()).append("\n");
}
Thread out = new Thread() {
@Override
public void run() {
try {
stdout.sink(new ByteArrayInputStream(result.toString().getBytes()));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
};
out.start();
out.join();
return 0;
}
private static final Map<String, String> ID_TO_CONTENT;
private static final Map<String, String> ID_TO_MIME_TYPE;
private static final Map<String, Date> ID_TO_LAST_MODIFIED;
private static final Map<String, Date> ID_TO_LAST_CRAWLED;
private static final Map<String, Metadata> ID_TO_METADATA;
static {
Map<String, String> idToContent = new HashMap<String, String>();
idToContent.put("1002", "Content of document 1002");
idToContent.put("1003", "Content of document 1003");
ID_TO_CONTENT = Collections.unmodifiableMap(idToContent);
Map<String, String> idToMimeType = new HashMap<String, String>();
idToMimeType.put("1002", "application/pdf");
idToMimeType.put("1003", "text/plain");
ID_TO_MIME_TYPE = Collections.unmodifiableMap(idToMimeType);
Map<String, Date> idToLastModified = new HashMap<String, Date>();
idToLastModified.put("1001", new Date(50));
idToLastModified.put("1002", new Date(100));
idToLastModified.put("1003", new Date(8000));
ID_TO_LAST_MODIFIED = Collections.unmodifiableMap(idToLastModified);
Map<String, Date> idToLastCrawled = new HashMap<String, Date>();
idToLastCrawled.put("1001", new Date(100));
idToLastCrawled.put("1002", new Date(99));
idToLastCrawled.put("1003", new Date(5000));
ID_TO_LAST_CRAWLED = Collections.unmodifiableMap(idToLastCrawled);
Metadata id1002Metadata = new Metadata();
id1002Metadata.add("metaname-1002a", "metavalue-1002a");
id1002Metadata.add("metaname-1002b", "metavalue-1002b");
Metadata id1003Metadata = new Metadata();
id1003Metadata.add("metaname-1003", "metavalue-1003");
Map<String, Metadata> idToMetadata = new HashMap<String, Metadata>();
idToMetadata.put("1002", id1002Metadata.unmodifiableView());
idToMetadata.put("1003", id1003Metadata.unmodifiableView());
ID_TO_METADATA = Collections.unmodifiableMap(idToMetadata);
}
@Override
public int executeRetriever(String[] command, InputSource stdin, final OutputSink stdout,
OutputSink stderr) throws IOException, InterruptedException {
assertEquals(command[0], "./retriever_cmd.sh");
assertEquals(command[1], "retriever_arg1");
assertEquals(command[2], "retriever_arg2");
String docId = command[3];
String content = ID_TO_CONTENT.get(docId);
Metadata metadata = ID_TO_METADATA.get(docId);
Date lastModified = ID_TO_LAST_MODIFIED.get(docId);
Date lastCrawled = ID_TO_LAST_CRAWLED.get(docId);
String mimeType = ID_TO_MIME_TYPE.get(docId);
final StringBuffer result = new StringBuffer();
result.append("GSA Adaptor Data Version 1 [\n]\n");
result.append("id=").append(docId).append("\n");
if (lastCrawled.after(lastModified)) {
result.append("up-to-date").append("\n");
}
if (mimeType != null) {
result.append("mime-type=").append(mimeType).append("\n");
}
if (metadata != null) {
for (Map.Entry<String, String> item : metadata) {
result.append("meta-name=").append(item.getKey()).append("\n");
result.append("meta-value=").append(item.getValue()).append("\n");
}
}
if (content != null) {
result.append("content").append("\n");
result.append(content);
}
Thread out = new Thread() {
@Override
public void run() {
try {
stdout.sink(new ByteArrayInputStream(result.toString().getBytes()));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
};
out.start();
out.join();
return 0;
}
private static final Map<String, String> ID_TO_AUTHZ_STATUS;
static {
Map<String, String> idToAuthzStatus = new HashMap<String, String>();
idToAuthzStatus.put("1001", "PERMIT");
idToAuthzStatus.put("1002", "DENY");
idToAuthzStatus.put("1003", "INDETERMINATE");
ID_TO_AUTHZ_STATUS = Collections.unmodifiableMap(idToAuthzStatus);
}
@Override
public Command.Result executeAuthorizer(String[] command, byte[] stdin)
throws UnsupportedEncodingException{
assertEquals(command[0], "./authorizer_cmd.sh");
String expectedText = "GSA Adaptor Data Version 1 [\n]\n"
+ "username=user1\n"
+ "password=password1\n"
+ "group=group1\n"
+ "group=group2\n"
+ "id=1001\n"
+ "id=1002\n"
+ "id=1003\n"
+ "id=1004\n";
assertEquals(expectedText, new String(stdin, "UTF-8"));
StringBuffer result = new StringBuffer();
result.append("GSA Adaptor Data Version 1 [\n]\n");
result.append("id=1001").append("\n");
result.append("authz-status=PERMIT").append("\n");
result.append("id=1002").append("\n");
result.append("authz-status=DENY").append("\n");
result.append("id=1003").append("\n");
result.append("authz-status=INDETERMINATE").append("\n");
byte[] stdout = result.toString().getBytes();
return new Command.Result(0, stdout, new byte[0]);
}
}
private static class ContentsRequestTestMock implements Request {
private DocId docId;
private Date lastCrawled;
public ContentsRequestTestMock(DocId docId) {
this.docId = docId;
}
@Override
public boolean hasChangedSinceLastAccess(Date lastModified) {
Date date = getLastAccessTime();
if (date == null) {
return true;
}
return date.before(lastModified);
}
@Override
public Date getLastAccessTime() {
return lastCrawled;
}
@Override
public DocId getDocId() {
return docId;
}
}
private static class ContentsResponseTestMock implements Response {
private OutputStream os;
private String contentType;
private Date lastModified;
private Metadata metadata = new Metadata();
private Acl acl;
private boolean secure;
private List<URI> anchorUris = new ArrayList<URI>();
private List<String> anchorTexts = new ArrayList<String>();
private boolean notModified;
private boolean notFound;
private boolean noIndex;
private boolean noFollow;
private boolean noArchive;
private URI displayUrl;
private boolean crawlOnce;
private boolean lock;
private Map<String, Acl> fragments = new TreeMap<String, Acl>();
public ContentsResponseTestMock(OutputStream os) {
this.os = os;
notModified = false;
}
@Override
public void respondNotModified() {
notModified = true;
}
@Override
public void respondNotFound() {
notFound = true;
}
@Override
public OutputStream getOutputStream() {
return os;
}
@Override
public void setContentType(String contentType) {
this.contentType = contentType;
}
@Override
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
@Override
public void addMetadata(String key, String value) {
this.metadata.add(key, value);
}
@Override
public void setAcl(Acl acl) {
this.acl = acl;
}
@Override
public void putNamedResource(String fname, Acl facl) {
this.fragments.put(fname, facl);
}
@Override
public void setSecure(boolean secure) {
this.secure = secure;
}
@Override
public void addAnchor(URI uri, String text) {
anchorUris.add(uri);
anchorTexts.add(text);
}
@Override
public void setNoIndex(boolean noIndex) {
this.noIndex = noIndex;
}
@Override
public void setNoFollow(boolean noFollow) {
this.noFollow = noFollow;
}
@Override
public void setNoArchive(boolean noArchive) {
this.noArchive = noArchive;
}
@Override
public void setDisplayUrl(URI displayUrl) {
this.displayUrl = displayUrl;
}
@Override
public void setCrawlOnce(boolean crawlOnce) {
this.crawlOnce = crawlOnce;
}
@Override
public void setLock(boolean lock) {
this.lock = lock;
}
public String getContentType() {
return contentType;
}
public Date getLastModified() {
return lastModified;
}
/** Returns unmodifibale view of metadata. */
Metadata getMetadata() {
return metadata.unmodifiableView();
}
public Acl getAcl() {
return acl;
}
public boolean getNotModified() {
return notModified;
}
public boolean getNotFound() {
return notFound;
}
public boolean isNoIndex() {
return noIndex;
}
public boolean isNoFollow() {
return noFollow;
}
public boolean isNoArchive() {
return noArchive;
}
public URI getDisplayUrl() {
return displayUrl;
}
public boolean isCrawlOnce() {
return crawlOnce;
}
public boolean isLock() {
return lock;
}
}
@Test
public void testListerAndRetriever() throws Exception {
CommandLineAdaptor adaptor = new CommandLineAdaptorTestMock();
Map<String, String> config = new HashMap<String, String>();
config.put("commandline.lister.cmd", "./lister_cmd.sh");
config.put("commandline.lister.arg1", "lister_arg1");
config.put("commandline.retriever.cmd", "./retriever_cmd.sh");
config.put("commandline.retriever.arg1", "retriever_arg1");
config.put("commandline.retriever.arg2", "retriever_arg2");
config.put("commandline.authorizer.cmd", "./authorizer_cmd.sh");
config.put("commandline.authorizer.arg1", "authorizer_arg1");
config.put("commandline.authorizer.delimeter", "\n");
// Test lister
List<DocId> idList = getDocIds(adaptor, config);
assertEquals(CommandLineAdaptorTestMock.original, idList);
// Test authorizer
final UserPrincipal user = new UserPrincipal("user1");
final String password = "password1";
final Set<GroupPrincipal> groups = new TreeSet<GroupPrincipal>();
groups.add(new GroupPrincipal("group1"));
groups.add(new GroupPrincipal("group2"));
AuthnIdentity authnIdentity = new AuthnIdentity() {
@Override
public UserPrincipal getUser() {
return user;
}
@Override
public String getPassword() {
return password;
}
@Override
public Set<GroupPrincipal> getGroups() {
return groups;
}
};
Map<DocId, AuthzStatus> expectedAuthzResult = new HashMap<DocId, AuthzStatus>();
expectedAuthzResult.put(new DocId("1001"), AuthzStatus.PERMIT);
expectedAuthzResult.put(new DocId("1002"), AuthzStatus.DENY);
expectedAuthzResult.put(new DocId("1003"), AuthzStatus.INDETERMINATE);
final List<DocId> docIds = Arrays.asList(new DocId("1001"), new DocId("1002"),
new DocId("1003"), new DocId("1004"));
Map<DocId, AuthzStatus> authzResult = adaptor.isUserAuthorized(authnIdentity, docIds);
assertEquals(expectedAuthzResult, authzResult);
// Test retriever
for (DocId docId : idList) {
ContentsRequestTestMock request = new ContentsRequestTestMock(docId);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ContentsResponseTestMock response = new ContentsResponseTestMock(baos);
adaptor.getDocContent(request, response);
boolean notModified = !CommandLineAdaptorTestMock.ID_TO_LAST_MODIFIED.get(docId.getUniqueId())
.after(CommandLineAdaptorTestMock.ID_TO_LAST_CRAWLED.get(docId.getUniqueId()));
assertEquals(notModified, response.getNotModified());
if (!notModified) {
assertEquals(CommandLineAdaptorTestMock.ID_TO_MIME_TYPE.get(docId.getUniqueId()),
response.getContentType());
assertEquals(CommandLineAdaptorTestMock.ID_TO_METADATA.get(docId.getUniqueId()),
response.getMetadata());
byte[] expected = CommandLineAdaptorTestMock.ID_TO_CONTENT.get(
docId.getUniqueId()).getBytes();
byte[] actual = baos.toByteArray();
String expectedString = new String(expected);
String actualString = new String(actual);
assertArrayEquals(
CommandLineAdaptorTestMock.ID_TO_CONTENT.get(docId.getUniqueId()).getBytes(),
baos.toByteArray());
}
}
}
}