org.opencms.search.TestCmsSearchAdvancedFeatures Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* For further information about Alkacon Software GmbH & Co. KG, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.search;
import org.opencms.file.CmsFile;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsPropertyDefinition;
import org.opencms.file.types.CmsResourceTypeBinary;
import org.opencms.file.types.CmsResourceTypePlain;
import org.opencms.main.OpenCms;
import org.opencms.report.CmsShellReport;
import org.opencms.report.I_CmsReport;
import org.opencms.search.fields.CmsSearchField;
import org.opencms.search.fields.CmsSearchFieldConfigurationOldCategories;
import org.opencms.test.OpenCmsTestCase;
import org.opencms.test.OpenCmsTestProperties;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import junit.extensions.TestSetup;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Unit test for advanced search features.
*
*/
public class TestCmsSearchAdvancedFeatures extends OpenCmsTestCase {
/** Name of the index used for testing. */
public static final String INDEX_OFFLINE = "Offline project (VFS)";
/** The index used for testing. */
public static final String INDEX_ONLINE = "Online project (VFS)";
/**
* Default JUnit constructor.
*
* @param arg0 JUnit parameters
*/
public TestCmsSearchAdvancedFeatures(String arg0) {
super(arg0);
}
/**
* Test suite for this test class.
*
* @return the test suite
*/
public static Test suite() {
OpenCmsTestProperties.initialize(org.opencms.test.AllTests.TEST_PROPERTIES_PATH);
TestSuite suite = new TestSuite();
suite.setName(TestCmsSearchAdvancedFeatures.class.getName());
suite.addTest(new TestCmsSearchAdvancedFeatures("testSortSearchResults"));
suite.addTest(new TestCmsSearchAdvancedFeatures("testSearchCategories"));
suite.addTest(new TestCmsSearchAdvancedFeatures("testMultipleSearchRoots"));
suite.addTest(new TestCmsSearchAdvancedFeatures("testSearchRestriction"));
suite.addTest(new TestCmsSearchAdvancedFeatures("testLimitTimeRanges"));
suite.addTest(new TestCmsSearchAdvancedFeatures("testLimitTimeRangesOptimized"));
suite.addTest(new TestCmsSearchAdvancedFeatures("testOnlyFilterSearch"));
TestSetup wrapper = new TestSetup(suite) {
@Override
protected void setUp() {
setupOpenCms("simpletest", "/");
}
@Override
protected void tearDown() {
removeOpenCms();
}
};
return wrapper;
}
/**
* Tests searching with limiting the time ranges.
*
* @throws Exception if the test fails
*/
public void testLimitTimeRanges() throws Exception {
CmsObject cms = getCmsObject();
echo("Testing searching with limiting to time ranges");
CmsSearchIndex index = OpenCms.getSearchManager().getIndex(INDEX_OFFLINE);
index.addConfigurationParameter(CmsSearchIndex.TIME_RANGE, "true");
assertTrue("Index '" + INDEX_OFFLINE + "' not checking time range as expected", index.isCheckingTimeRange());
CmsSearch searchBean = new CmsSearch();
List searchResult;
String query = "OpenCms";
searchBean.init(cms);
searchBean.setIndex(INDEX_OFFLINE);
searchBean.setMatchesPerPage(1000);
searchBean.setQuery(query);
searchResult = searchBean.getSearchResult();
int orgCount = searchResult.size();
// check min date created
Date stamp = new Date();
searchBean.getParameters().setMinDateCreated(stamp.getTime());
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(0, searchResult.size());
String resName = "search_new.txt";
cms.createResource(resName, CmsResourceTypePlain.getStaticTypeId(), "OpenCms".getBytes(), null);
I_CmsReport report = new CmsShellReport(cms.getRequestContext().getLocale());
OpenCms.getSearchManager().rebuildIndex(INDEX_OFFLINE, report);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(1, searchResult.size());
// check max date created
searchBean.getParameters().setMaxDateCreated(stamp.getTime() - 1000);
searchBean.getParameters().setMinDateCreated(Long.MIN_VALUE);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(orgCount, searchResult.size());
searchBean.getParameters().setMaxDateCreated(Long.MAX_VALUE);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(orgCount + 1, searchResult.size());
// check min date last modified
stamp = new Date();
searchBean.getParameters().setMinDateLastModified(stamp.getTime());
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(0, searchResult.size());
CmsFile file = cms.readFile(resName);
file.setContents("OpenCms ist toll".getBytes());
cms.writeFile(file);
report = new CmsShellReport(cms.getRequestContext().getLocale());
OpenCms.getSearchManager().rebuildIndex(INDEX_OFFLINE, report);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(1, searchResult.size());
// check max date last modified
searchBean.getParameters().setMaxDateLastModified(stamp.getTime() - 1000);
searchBean.getParameters().setMinDateLastModified(Long.MIN_VALUE);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(orgCount, searchResult.size());
searchBean.getParameters().setMaxDateLastModified(Long.MAX_VALUE);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(orgCount + 1, searchResult.size());
}
/**
* Tests searching with optimized limiting the time ranges.
*
* @throws Exception if the test fails
*/
public void testLimitTimeRangesOptimized() throws Exception {
CmsObject cms = getCmsObject();
echo("Testing searching with optimized limiting to time ranges");
CmsSearchIndex index = OpenCms.getSearchManager().getIndex(INDEX_OFFLINE);
index.addConfigurationParameter(CmsSearchIndex.TIME_RANGE, "false");
assertFalse("Index '" + INDEX_OFFLINE + "' checking time range but should not", index.isCheckingTimeRange());
CmsSearch searchBean = new CmsSearch();
List searchResult;
String query = "OpenCms";
searchBean.init(cms);
searchBean.setIndex(INDEX_OFFLINE);
searchBean.setMatchesPerPage(1000);
searchBean.setQuery(query);
searchResult = searchBean.getSearchResult();
// do a search and store the result count
int orgCount = searchResult.size();
// check min date created
Date stamp = new Date();
searchBean.getParameters().setMinDateCreated(stamp.getTime() - 1000);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
// we must find one match because of the previous time range test
assertEquals(1, searchResult.size());
String resName = "search_new_2.txt";
cms.createResource(resName, CmsResourceTypePlain.getStaticTypeId(), "OpenCms".getBytes(), null);
I_CmsReport report = new CmsShellReport(cms.getRequestContext().getLocale());
OpenCms.getSearchManager().rebuildIndex(INDEX_OFFLINE, report);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
// now we must find 2 results
assertEquals(2, searchResult.size());
// check max date created (must move back one day because of granularity level in optimized date range search)
searchBean.getParameters().setMaxDateCreated(stamp.getTime() - (1000 * 60 * 60 * 24));
searchBean.getParameters().setMinDateCreated(Long.MIN_VALUE);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
// we will find one result less then before because of the previous date range rest
assertEquals(orgCount - 1, searchResult.size());
searchBean.getParameters().setMaxDateCreated(stamp.getTime());
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(orgCount + 1, searchResult.size());
// check min date last modified
stamp = new Date();
// move to tomorrow because of granularity level in optimized date search
searchBean.getParameters().setMinDateLastModified(stamp.getTime() + (1000 * 60 * 60 * 24));
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(0, searchResult.size());
CmsFile file = cms.readFile(resName);
file.setContents("OpenCms ist toll".getBytes());
cms.writeFile(file);
report = new CmsShellReport(cms.getRequestContext().getLocale());
OpenCms.getSearchManager().rebuildIndex(INDEX_OFFLINE, report);
searchBean.getParameters().setMinDateLastModified(stamp.getTime());
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
// TODO Why runs this test successfully? The result size should be 1
assertEquals(2, searchResult.size());
// check max date last modified
searchBean.getParameters().setMaxDateLastModified(stamp.getTime() - (1000 * 60 * 60 * 24));
searchBean.getParameters().setMinDateLastModified(Long.MIN_VALUE);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(orgCount - 1, searchResult.size());
searchBean.getParameters().setMaxDateLastModified(Long.MAX_VALUE);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(orgCount + 1, searchResult.size());
}
/**
* Tests searching without a query only using a filter.
*
* @throws Exception if the test fails
*/
public void testOnlyFilterSearch() throws Exception {
CmsObject cms = getCmsObject();
echo("Testing searching without a query only using a filter");
CmsSearchIndex index = OpenCms.getSearchManager().getIndex(INDEX_OFFLINE);
index.addConfigurationParameter(CmsSearchIndex.TIME_RANGE, "false");
assertFalse("Index '" + INDEX_OFFLINE + "' checking time range but should not", index.isCheckingTimeRange());
CmsSearch searchBean = new CmsSearch();
List searchResult;
searchBean.init(cms);
searchBean.setIndex(INDEX_OFFLINE);
searchBean.setMatchesPerPage(1000);
searchBean.getParameters().setIgnoreQuery(true);
// query all files created since yesterday, this should be 2 because of previous tests
Date stamp = new Date();
searchBean.getParameters().setMinDateCreated(stamp.getTime() - (1000 * 60 * 60 * 24));
searchResult = searchBean.getSearchResult();
assertEquals(2, searchResult.size());
// now do a search for all documents of type "plain"
searchBean.getParameters().setMinDateCreated(Long.MIN_VALUE);
searchBean.setResourceType(CmsResourceTypePlain.getStaticTypeName());
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(7, searchResult.size());
// now do a search for all documents of type "plain" created since yesterday
searchBean.setResourceType(CmsResourceTypePlain.getStaticTypeName());
searchBean.getParameters().setMinDateCreated(stamp.getTime() - (1000 * 60 * 60 * 24));
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(2, searchResult.size());
// now do a search for all documents of type "binary" created since yesterday
searchBean.setResourceType(CmsResourceTypeBinary.getStaticTypeName());
searchBean.getParameters().setMinDateCreated(stamp.getTime() - (1000 * 60 * 60 * 24));
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(0, searchResult.size());
// now do a search for all documents
searchBean.getParameters().setMinDateCreated(Long.MIN_VALUE);
searchBean.setResourceTypes(null);
searchBean.init(cms);
searchResult = searchBean.getSearchResult();
assertEquals(48, searchResult.size());
}
/**
* Tests searching with multiple search roots.
*
* @throws Exception if the test fails
*/
public void testMultipleSearchRoots() throws Exception {
CmsObject cms = getCmsObject();
echo("Testing searching with multiple search roots");
CmsSearch searchBean = new CmsSearch();
List searchResult;
String query = "OpenCms";
searchBean.init(cms);
searchBean.setIndex(INDEX_OFFLINE);
searchBean.setMatchesPerPage(1000);
searchBean.setQuery(query);
String[][] roots = new String[][] {
new String[] {"/folder1/"},
new String[] {"/folder2/"},
new String[] {"/types/"},
new String[] {"/folder2/", "/types/"},
new String[] {"/folder1/", "/types/"},
new String[] {"/folder1/", "/folder2/"},
new String[] {"/folder1/", "/folder2/", "/types/"}};
int[] expected = new int[] {7, 4, 1, 5, 8, 11, 12};
for (int i = 0; i < expected.length; i++) {
int expect = expected[i];
String[] rootList = roots[i];
searchBean.setSearchRoots(rootList);
searchResult = searchBean.getSearchResult();
System.out.println(
"Result for search " + i + " (found " + searchResult.size() + ", expected " + expect + ")");
TestCmsSearch.printResults(searchResult, cms);
assertEquals(expect, searchResult.size());
}
}
/**
* Tests search category grouping.
*
* @throws Exception if the test fails
*/
public void testSearchCategories() throws Exception {
CmsObject cms = getCmsObject();
echo("Testing searching for categories");
CmsSearchIndex index = OpenCms.getSearchManager().getIndex(INDEX_OFFLINE);
assertTrue(index.getFieldConfiguration() instanceof CmsSearchFieldConfigurationOldCategories);
// perform a search on the newly generated index
CmsSearch searchBean = new CmsSearch();
List searchResult;
String query = "OpenCms";
// apply search categories to some folders
CmsProperty cat1 = new CmsProperty(CmsPropertyDefinition.PROPERTY_SEARCH_CATEGORY, "category_1", null, true);
CmsProperty cat2 = new CmsProperty(CmsPropertyDefinition.PROPERTY_SEARCH_CATEGORY, "category_2", null, true);
CmsProperty cat3 = new CmsProperty(CmsPropertyDefinition.PROPERTY_SEARCH_CATEGORY, "category_3", null, true);
cms.lockResource("/folder1/");
cms.writePropertyObject("/folder1/", cat1);
cms.unlockResource("/folder1/");
cms.lockResource("/folder2/");
cms.writePropertyObject("/folder2/", cat2);
cms.unlockResource("/folder2/");
cms.lockResource("/types/");
cms.writePropertyObject("/types/", cat3);
cms.unlockResource("/types/");
// update the search index used
OpenCms.getSearchManager().rebuildIndex(INDEX_OFFLINE, new CmsShellReport(cms.getRequestContext().getLocale()));
searchBean.init(cms);
searchBean.setIndex(INDEX_OFFLINE);
searchBean.setQuery(query);
searchBean.setMatchesPerPage(1000);
searchBean.setCalculateCategories(true);
// first run is default sort order
searchResult = searchBean.getSearchResult();
System.out.println("Result sorted by relevance:");
TestCmsSearch.printResults(searchResult, cms);
assertEquals(13, searchResult.size());
Map categories = searchBean.getSearchResultCategories();
// make sure categories where found
assertNotNull(categories);
// print the categories
System.out.println(CmsSearchCategoryCollector.formatCategoryMap(categories));
// make sure the results are as expected
assertTrue(categories.containsKey(cat1.getValue()));
assertTrue(categories.containsKey(cat2.getValue()));
assertTrue(categories.containsKey(cat3.getValue()));
assertTrue(categories.containsKey(CmsSearchCategoryCollector.UNKNOWN_CATEGORY));
// result must be all 3 categories plus 1 for "unknown"
assertEquals(4, categories.size());
// assert result count
assertEquals(new Integer(7), categories.get(cat1.getValue()));
assertEquals(new Integer(4), categories.get(cat2.getValue()));
assertEquals(new Integer(1), categories.get(cat3.getValue()));
assertEquals(new Integer(1), categories.get(CmsSearchCategoryCollector.UNKNOWN_CATEGORY));
// count the category results
searchBean.setCalculateCategories(false);
String[][] cats = new String[][] {
new String[] {cat1.getValue()},
new String[] {cat2.getValue()},
new String[] {cat3.getValue()},
new String[] {cat1.getValue(), cat3.getValue()},
new String[] {cat2.getValue(), cat3.getValue()},
new String[] {cat1.getValue(), cat2.getValue()},
new String[] {cat1.getValue(), cat2.getValue(), cat3.getValue()}};
int[] expected = new int[] {7, 4, 1, 8, 5, 11, 12};
for (int k = 0; k < expected.length; k++) {
int expect = expected[k];
String[] catList = cats[k];
searchBean.setCategories(catList);
searchResult = searchBean.getSearchResult();
System.out.println(
"Result for search " + k + " (found " + searchResult.size() + ", expected " + expect + ")");
TestCmsSearch.printResults(searchResult, cms);
assertEquals(expect, searchResult.size());
}
}
/**
* Tests searching with restrictions.
*
* @throws Exception if the test fails
*/
public void testSearchRestriction() throws Exception {
CmsObject cms = getCmsObject();
echo("Testing searching in search results");
CmsSearch searchBean = new CmsSearch();
List searchResult;
String query = "OpenCms";
searchBean.init(cms);
searchBean.setIndex(INDEX_OFFLINE);
searchBean.setMatchesPerPage(1000);
searchBean.setQuery(query);
// first part of the rest is identical to "testMultipleSearchRoots()"
String[][] roots = new String[][] {
new String[] {"/folder1/"},
new String[] {"/folder2/"},
new String[] {"/types/"},
new String[] {"/folder2/", "/types/"},
new String[] {"/folder1/", "/types/"},
new String[] {"/folder1/", "/folder2/"},
new String[] {"/folder1/", "/folder2/", "/types/"}};
int[] expected = new int[] {7, 4, 1, 5, 8, 11, 12};
for (int i = 0; i < expected.length; i++) {
int expect = expected[i];
String[] rootList = roots[i];
searchBean.setSearchRoots(rootList);
searchResult = searchBean.getSearchResult();
System.out.println(
"Result for search " + i + " (found " + searchResult.size() + ", expected " + expect + ")");
TestCmsSearch.printResults(searchResult, cms);
assertEquals(expect, searchResult.size());
}
// now create a restriction to search for an additional "Alkacon" (effectivly searching for "OpenCms Alkacon")
CmsSearchParameters restriction;
restriction = new CmsSearchParameters("Alkacon", null, null, null, null, false, null);
expected = new int[] {3, 2, 1, 3, 4, 5, 6};
for (int i = 0; i < expected.length; i++) {
int expect = expected[i];
String[] rootList = roots[i];
searchBean.setSearchRoots(rootList);
searchBean.setResultRestriction(restriction);
searchResult = searchBean.getSearchResult();
System.out.println(
"Result for search " + i + " (found " + searchResult.size() + ", expected " + expect + ")");
TestCmsSearch.printResults(searchResult, cms);
assertEquals(expect, searchResult.size());
}
// another run of tests using searching only in the "meta" field
restriction = new CmsSearchParameters(
"Alkacon",
Arrays.asList(new String[] {"meta"}),
null,
null,
null,
false,
null);
expected = new int[] {0, 0, 1, 1, 1, 0, 1};
for (int i = 0; i < expected.length; i++) {
int expect = expected[i];
String[] rootList = roots[i];
searchBean.setSearchRoots(rootList);
searchBean.setResultRestriction(restriction);
searchResult = searchBean.getSearchResult();
System.out.println(
"Result for search " + i + " (found " + searchResult.size() + ", expected " + expect + ")");
TestCmsSearch.printResults(searchResult, cms);
assertEquals(expect, searchResult.size());
}
// another run of tests using categories that have been defined in "testSearchCategories()"
// reset search bean settings (restriction changed them) to initial values (see start of method)
searchBean = new CmsSearch();
searchBean.init(cms);
searchBean.setIndex(INDEX_OFFLINE);
searchBean.setMatchesPerPage(1000);
searchBean.setQuery(query);
restriction = new CmsSearchParameters(
null,
null,
null,
Arrays.asList(new String[] {"category_1", "category_3"}),
null,
false,
null);
expected = new int[] {7, 0, 1, 1, 8, 7, 8};
for (int i = 0; i < expected.length; i++) {
int expect = expected[i];
String[] rootList = roots[i];
searchBean.setSearchRoots(rootList);
searchBean.setResultRestriction(restriction);
searchResult = searchBean.getSearchResult();
System.out.println(
"Result for search " + i + " (found " + searchResult.size() + ", expected " + expect + ")");
TestCmsSearch.printResults(searchResult, cms);
assertEquals(expect, searchResult.size());
}
}
/**
* Tests sorting of search results.
*
* @throws Exception if the test fails
*/
public void testSortSearchResults() throws Exception {
CmsObject cms = getCmsObject();
echo("Testing sorting of search results");
// perform a search on the newly generated index
CmsSearch searchBean = new CmsSearch();
List searchResult;
String query = "OpenCms";
// update the search index used
OpenCms.getSearchManager().rebuildIndex(INDEX_OFFLINE, new CmsShellReport(cms.getRequestContext().getLocale()));
searchBean.init(cms);
searchBean.setIndex(INDEX_OFFLINE);
searchBean.setQuery(query);
searchBean.setMatchesPerPage(50);
// first run is default sort order
searchResult = searchBean.getSearchResult();
System.out.println("Result sorted by relevance:");
TestCmsSearch.printResults(searchResult, cms);
assertTrue(
"Best match by sore must always be 100 but is " + searchResult.get(0).getScore(),
searchResult.get(0).getScore() == 100);
for (int i = 1; i < searchResult.size(); i++) {
assertTrue(
"Resource "
+ searchResult.get(i - 1).getPath()
+ " not sorted as expected - index ["
+ (i - 1)
+ "/"
+ i
+ "]",
searchResult.get(i - 1).getScore() >= searchResult.get(i).getScore());
}
// second run use Title sort order
String lastTitle = null;
searchBean.setSortOrder(CmsSearchParameters.SORT_TITLE);
searchResult = searchBean.getSearchResult();
System.out.println("Result sorted by title:");
TestCmsSearch.printResults(searchResult, cms);
Iterator i = searchResult.iterator();
while (i.hasNext()) {
CmsSearchResult res = i.next();
if (lastTitle != null) {
// make sure result is sorted correctly
assertTrue(lastTitle.compareTo(res.getField(CmsSearchField.FIELD_TITLE)) <= 0);
}
lastTitle = res.getField(CmsSearchField.FIELD_TITLE);
}
// third run use date last modified
long lastTime = 0;
searchBean.setSortOrder(CmsSearchParameters.SORT_DATE_LASTMODIFIED);
searchResult = searchBean.getSearchResult();
System.out.println("Result sorted by date last modified:");
TestCmsSearch.printResults(searchResult, cms);
i = searchResult.iterator();
while (i.hasNext()) {
CmsSearchResult res = i.next();
if (lastTime > 0) {
// make sure result is sorted correctly
assertTrue(lastTime >= res.getDateLastModified().getTime());
assertTrue(res.getScore() <= 100);
}
lastTime = res.getDateLastModified().getTime();
}
assertNull(searchBean.getSearchResultCategories());
}
}