// Copyright 2011 Google Inc.
//
// 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.connector.util.filter;
import com.google.enterprise.connector.spi.Document;
import com.google.enterprise.connector.spi.Property;
import com.google.enterprise.connector.spi.RepositoryException;
import com.google.enterprise.connector.spi.SimpleDocument;
import com.google.enterprise.connector.spi.SimpleProperty;
import com.google.enterprise.connector.spi.SkippedDocumentException;
import com.google.enterprise.connector.spi.Value;
import com.google.enterprise.connector.test.ConnectorTestUtils;
import java.util.List;
import java.util.Map;
/**
* Tests SkipDocumentFilter.
*/
public class SkipDocumentFilterTest extends DocumentFilterTest {
/** Creates a SkipDocumentFilter. */
private Document createFilter(
String propName, String pattern, boolean skipOnMatch)
throws Exception {
return createFilter(propName, pattern, skipOnMatch, createDocument());
}
/** Creates a SkipDocumentFilter. */
private Document createFilter(
String propName, String pattern, boolean skipOnMatch, Document source)
throws Exception {
SkipDocumentFilter factory = new SkipDocumentFilter();
factory.setPropertyName(propName);
factory.setPattern(pattern);
factory.setSkipOnMatch(skipOnMatch);
return factory.newDocumentFilter(source);
}
/** Creates a Properties subset with specified properties removed. */
private Map<String, List<Value>> createPropertiesSubset(
String... names) {
Map<String, List<Value>> props = createProperties();
for (String name : names) {
props.remove(name);
}
return props;
}
/** Reads all values of a property. */
private static void checkProperty(Property property)
throws RepositoryException {
assertNotNull(property);
while(property.nextValue() != null);
}
/** Tests the Factory setters with illegal arguments. */
public void testFactoryIllegalSetterArgs() throws Exception {
SkipDocumentFilter factory = new SkipDocumentFilter();
try {
factory.setPropertyName(null);
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException expected) {
// Expected.
}
try {
factory.setPropertyName("");
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException expected) {
// Expected.
}
// Null or empty patterns are OK.
factory.setPattern(null);
factory.setPattern("");
}
/** Tests illegal state if configuration setters are not called. */
public void testFactoryIllegalState() throws Exception {
checkIllegalStateFindProperty(new SkipDocumentFilter());
}
/** Tests that non-existent property should skip if skipOnMatch is false. */
public void testSkipNonExistentProperty() throws Exception {
Document filter = createFilter("nonExistentProperty", null, false);
try {
filter.findProperty("nonExistentProperty");
fail("SkippedDocumentException expected");
} catch (SkippedDocumentException expected) {
// Expected.
}
checkDocument(filter, createProperties(), "nonExistentProperty");
}
/** Tests that non-existent property should not skip if skipOnMatch is true */
public void testNoSkipNonExistentProperty() throws Exception {
Document filter = createFilter("nonExistentProperty", null, true);
assertNull(filter.findProperty("nonExistentProperty"));
checkDocument(filter, createProperties(), "nonExistentProperty");
}
/** Tests that existing property should skip if skipOnMatch is true. */
public void testSkipExistingProperty() throws Exception {
Document filter = createFilter(PROP3, null, true);
try {
filter.findProperty(PROP3);
fail("SkippedDocumentException expected");
} catch (SkippedDocumentException expected) {
// Expected.
}
checkDocumentProperties(filter, createPropertiesSubset(PROP3));
}
/** Tests that existing property should not skip if skipOnMatch is false. */
public void testNoSkipExistingProperty() throws Exception {
Document filter = createFilter(PROP3, null, false);
assertNotNull(filter.findProperty(PROP3));
checkDocument(filter, createProperties());
}
/** Tests that the filter doesn't skip if no values match. */
public void testNoSkipNoMatchingValues() throws Exception {
Document filter = createFilter(PROP1, "nonExistentPattern", true);
checkDocument(filter, createProperties());
}
/** Tests that the filter doesn't skip if another property's values match. */
public void testNoSkipOtherMatchingValues() throws Exception {
Document filter = createFilter(PROP4, PATTERN, true);
checkDocument(filter, createProperties());
}
/** Tests that the filter does skip if values match. */
public void testSkipOnMatchingSingleValue() throws Exception {
Document filter = createFilter(PROP1, PATTERN, true);
try {
checkProperty(filter.findProperty(PROP1));
fail("SkippedDocumentException expected");
} catch (SkippedDocumentException expected) {
// Expected.
}
checkDocumentProperties(filter, createPropertiesSubset(PROP1));
}
/** Tests that the filter does skip if values match. */
public void testSkipOnMatchingMultipleValues() throws Exception {
Document filter = createFilter(PROP5, PATTERN, true);
try {
checkProperty(filter.findProperty(PROP5));
fail("SkippedDocumentException expected");
} catch (SkippedDocumentException expected) {
// Expected.
}
checkDocumentProperties(filter, createPropertiesSubset(PROP5));
}
/** Tests that the filter doesn't skip if values do match and skipOnMatch
is false. */
public void testNoSkipOnMatchingSingleValue() throws Exception {
Document filter = createFilter(PROP1, PATTERN, false);
checkDocument(filter, createProperties());
}
/** Tests that the filter doesn't skip if values do match and skipOnMatch
is false. */
public void testNoSkipOnMatchingMultipleValues() throws Exception {
Document filter = createFilter(PROP6, PATTERN, false);
checkDocument(filter, createProperties());
}
/** Test that the filter doesn't skip if a value is null. */
public void testNoSkipOnNullValue() throws Exception {
Map<String, List<Value>> props = createPropertiesSubset(PROP1);
props.put(PROP1, valueList((String) null));
Document filter =
createFilter(PROP1, PATTERN, true, new SimpleDocument(props));
checkDocument(filter, props);
}
/** Test that null values match an empty pattern. */
public void testSkipOnNullValue() throws Exception {
Map<String, List<Value>> props = createPropertiesSubset(PROP1);
props.put(PROP1, valueList((String) null));
Document filter =
createFilter(PROP1, "\\A\\Z", true, new SimpleDocument(props));
try {
checkProperty(filter.findProperty(PROP1));
fail("SkippedDocumentException expected");
} catch (SkippedDocumentException expected) {
// Expected.
}
checkDocumentProperties(filter, createPropertiesSubset(PROP1));
}
/** Test toString(). */
public void testToString() {
SkipDocumentFilter factory = new SkipDocumentFilter();
factory.setPropertyName("foo");
factory.setPattern("bar");
factory.setSkipOnMatch(true);
assertEquals("SkipDocumentFilter: (foo , \"bar\" , true)",
factory.toString());
}
/**
* Tests that an unpublished property with a null value is skipped if
* skipOnMatch is true.
*/
public void testSkipUnpublishedNullProperty() throws Exception {
Document filter = createFilter("nonExistentProperty", null, true,
createDocumentWithUnpublishedProperty());
try {
filter.findProperty("nonExistentProperty");
fail("SkippedDocumentException expected");
} catch (SkippedDocumentException expected) {
// Expected.
}
}
/**
* Tests that an unpublished property with a null value is not skipped if
* skipOnMatch is false.
*/
public void testNoSkipUnpublishedNullProperty() throws Exception {
Document filter = createFilter("nonExistentProperty", null, false,
createDocumentWithUnpublishedProperty());
assertNotNull(filter.findProperty("nonExistentProperty"));
}
/** Tests that an unpublished property is skipped if skipOnMatch is true. */
public void testSkipUnpublishedProperty() throws Exception {
Document filter = createFilter("nonExistentProperty", "dummy", true,
createDocumentWithUnpublishedProperty());
try {
checkProperty(filter.findProperty("nonExistentProperty"));
fail("SkippedDocumentException expected");
} catch (SkippedDocumentException expected) {
// Expected.
}
}
/**
* Tests that an unpublished property is not skipped if skipOnMatch is false.
*/
public void testNoSkipUnpublishedProperty() throws Exception {
Document filter = createFilter("nonExistentProperty", "dummy", false,
createDocumentWithUnpublishedProperty());
assertNotNull(filter.findProperty("nonExistentProperty"));
}
/**
* Tests that an unpublished property is not return in
* Document.getPropertyNames and is return in
* SkipDocumentFilter.getPropertyNames with a value of empty string.
*/
public void testUnpublishedPropertyInFilterNotDocument() throws Exception {
Document doc = createDocumentWithUnpublishedProperty();
assertFalse(doc.getPropertyNames().toString(),
doc.getPropertyNames().contains("nonExistentProperty"));
Document filter = createFilter("nonExistentProperty", "nondummy", true,
doc);
assertTrue(filter.getPropertyNames().toString(),
filter.getPropertyNames().contains("nonExistentProperty"));
Property unpublished = filter.findProperty("nonExistentProperty");
assertNotNull(unpublished);
assertEquals("", unpublished.nextValue().toString());
assertNull(unpublished.nextValue());
}
/**
* Creates a {@link SimpleDocument} with the id of "dummy" and the
* non-public property "nonExistentProperty" that has the value "dummy".
*/
private SimpleDocument createDocumentWithUnpublishedProperty() {
Map<String, Object> props =
ConnectorTestUtils.createSimpleDocumentBasicProperties("dummy");
return new SimpleDocument(ConnectorTestUtils.createSpiProperties(props)) {
@Override
public Property findProperty(String name) {
if (name.equals("nonExistentProperty")) {
return new SimpleProperty(valueList("dummy"));
} else {
return super.findProperty(name);
}
}
};
}
}