diff --git a/e2e-test/pom.xml b/e2e-test/pom.xml
index 187ee9212..c7911ea2a 100644
--- a/e2e-test/pom.xml
+++ b/e2e-test/pom.xml
@@ -11,9 +11,9 @@
Search Analytics E2E Tests
Test Project to test Search Service and Analytics Features on a complete setup of Alfresco, Share
- 1.18
- 1.10
- 3.0.15
+ 1.20
+ 1.11
+ 3.0.16
3.2.0
src/test/resources/SearchSuite.xml
diff --git a/e2e-test/src/main/java/org/alfresco/search/TestGroup.java b/e2e-test/src/main/java/org/alfresco/search/TestGroup.java
index a149ab6f7..fbb90a64e 100644
--- a/e2e-test/src/main/java/org/alfresco/search/TestGroup.java
+++ b/e2e-test/src/main/java/org/alfresco/search/TestGroup.java
@@ -38,6 +38,7 @@ public class TestGroup
public static final String ACS_61n = "ACS_61n"; // Alfresco Content Services 6.1 or above
public static final String ACS_611n = "ACS_611n"; // Alfresco Content Services 6.1.1 or above
public static final String ACS_62n = "ACS_62n"; // Alfresco Content Services 6.2 or above
+ public static final String ACS_63n = "ACS_63n"; // Alfresco Content Services 6.3 or above
public static final String AGS_302 = "AGS_302"; // Alfresco governance Services 3.0.2 or above
diff --git a/e2e-test/src/test/java/org/alfresco/test/search/functional/AbstractE2EFunctionalTest.java b/e2e-test/src/test/java/org/alfresco/test/search/functional/AbstractE2EFunctionalTest.java
index 705fb848d..8073d003d 100644
--- a/e2e-test/src/test/java/org/alfresco/test/search/functional/AbstractE2EFunctionalTest.java
+++ b/e2e-test/src/test/java/org/alfresco/test/search/functional/AbstractE2EFunctionalTest.java
@@ -6,6 +6,16 @@
*/
package org.alfresco.test.search.functional;
+import static java.util.Optional.ofNullable;
+
+import static lombok.AccessLevel.PROTECTED;
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import lombok.Getter;
import org.alfresco.cmis.CmisWrapper;
import org.alfresco.dataprep.ContentService;
import org.alfresco.dataprep.SiteService.Visibility;
@@ -38,15 +48,10 @@ import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
-import lombok.Getter;
-
-import static java.util.Optional.ofNullable;
-import static lombok.AccessLevel.PROTECTED;
-
/**
* @author meenal bhave
*/
-@ContextConfiguration("classpath:alfresco-search-e2e-context.xml")
+@ContextConfiguration ("classpath:alfresco-search-e2e-context.xml")
public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringContextTests
{
/** The number of retries that a query will be tried before giving up. */
@@ -76,26 +81,26 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
protected CmisWrapper cmisApi;
@Autowired
- // @Getter(value = PROTECTED)
+ // @Getter(value = PROTECTED)
protected DataUser dataUser;
@Autowired
- @Getter(value = PROTECTED)
+ @Getter (value = PROTECTED)
private ContentService contentService;
protected UserModel testUser, adminUserModel, testUser2;
protected SiteModel testSite, testSite2;
protected static String unique_searchString;
-
+
protected static final String SEARCH_LANGUAGE_CMIS = "cmis";
-
+
protected enum SearchLanguage {
CMIS,
AFTS
- }
+ }
- @BeforeSuite(alwaysRun = true)
+ @BeforeSuite (alwaysRun = true)
public void beforeSuite() throws Exception
{
super.springTestContextPrepareTestInstance();
@@ -104,7 +109,7 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
deployCustomModel("model/finance-model.xml");
}
- @BeforeClass(alwaysRun = true)
+ @BeforeClass (alwaysRun = true)
public void setup()
{
serverHealth.assertServerIsOnline();
@@ -209,7 +214,7 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
customModel.setNodeRef(modelInRepo.getId());
customModel.setNodeRef(customModel.getNodeRefWithoutVersion());
customModel.setCmisLocation(String.format("/Data Dictionary/Models/%s", fileName));
- LOGGER.info("Custom Model file: " + customModel.getCmisLocation());
+ LOGGER.info("Custom Model file: " + customModel.getCmisLocation());
}
else
{
@@ -239,9 +244,9 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
/**
* Wait for Solr to finish indexing and search to return appropriate results
- *
- * @param userQuery Search Query
- * @param contentToFind that's expected to be included / excluded from the results
+ *
+ * @param userQuery Search Query
+ * @param contentToFind that's expected to be included / excluded from the results
* @param expectedInResults Whether we expect the content in the results or not.
* @return true if search returns expected results, i.e. is given content is found or excluded from the results
*/
@@ -277,25 +282,25 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
return false;
}
-
+
/**
* Method to check if the contentName is returned in the SearchResponse.
*
- * @param response the search response
+ * @param response the search response
* @param contentName the text we are using as matching/verifying criteria.
* @return true if if the item with the contentName text is returned in the SearchResponse.
*/
- public boolean isContentInSearchResponse(SearchResponse response, String contentName)
+ public boolean isContentInSearchResponse(SearchResponse response, String contentName)
{
return response.getEntries().stream()
- .map(entry -> entry.getModel().getName())
- .anyMatch(name -> name.equalsIgnoreCase(contentName) || contentName.isBlank());
+ .map(entry -> entry.getModel().getName())
+ .anyMatch(name -> name.equalsIgnoreCase(contentName) || contentName.isBlank());
}
/**
* Wait for Solr to finish indexing: Indexing has caught up = true if search returns appropriate results
- *
- * @param userQuery: search query, this can include the fieldname, unique search string will guarantee accurate results
+ *
+ * @param userQuery: search query, this can include the fieldname, unique search string will guarantee accurate results
* @param expectedInResults, true if entry is expected in the results set
* @return true (indexing is finished) if search returns appropriate results
*/
@@ -307,7 +312,7 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
/**
* waitForIndexing method that matches / waits for filename, metadata to be indexed.
- *
+ *
* @param userQuery
* @param expectedInResults
* @return
@@ -320,7 +325,7 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
/**
* waitForIndexing method that matches / waits for content to be indexed, this can take longer than metadata indexing.
* Since Metadata is indexed first, use this method where tests, queries need content to be indexed too.
- *
+ *
* @param userQuery
* @param expectedInResults
* @return
@@ -332,9 +337,9 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
/**
* Wait for Solr to finish indexing: Indexing has caught up = true if search returns appropriate results
- *
- * @param fieldName: specific field to search for, e.g. name. When specified, the query will become: name:'userQuery'
- * @param userQuery: search string, unique search string will guarantee accurate results
+ *
+ * @param fieldName: specific field to search for, e.g. name. When specified, the query will become: name:'userQuery'
+ * @param userQuery: search string, unique search string will guarantee accurate results
* @param expectedInResults, true if entry is expected in the results set
* @return true (indexing is finished) if search returns appropriate results
*/
@@ -347,7 +352,7 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
/**
* Run a search as admin user and return the response
- *
+ *
* @param queryString: string to search for, unique search string will guarantee accurate results
* @return the search response from the API
*/
@@ -358,8 +363,8 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
/**
* Run a search as given user and return the response
- *
- * @param user: UserModel for the user you wish to run the query as
+ *
+ * @param user: UserModel for the user you wish to run the query as
* @param queryString: string to search for, unique search string will guarantee accurate results
* @return the search response from the API
*/
@@ -371,11 +376,11 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
searchRequest.setQuery(queryModel);
return restClient.authenticateUser(user).withSearchAPI().search(searchRequest);
}
-
+
/**
* Run a search with Spellcheck as given user and return the response
- * @param user UserModel for the user you wish to run the query as
- * @param queryModel The queryModel to search for, containing the query
+ * @param user UserModel for the user you wish to run the query as
+ * @param queryModel The queryModel to search for, containing the query
* @param spellcheckQuery The Spellcheck Model containing the query
* @return the search response from the API
*/
@@ -416,31 +421,22 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
query.setQuery(queryReq);
return query;
}
-
+
protected DataUser getDataUser()
{
return dataUser;
}
-
+
/**
* Helper method to test if the search query works and count matches where provided
- * @param query: AFTS or cmis query string
+ *
+ * @param query: AFTS or cmis query string
* @param expectedCount: Only successful response is checked, when expectedCount is null (can not be exactly specified),
* @return SearchResponse
*/
protected SearchResponse testSearchQuery(String query, Integer expectedCount, SearchLanguage queryLanguage)
{
- RestRequestQueryModel queryModel = new RestRequestQueryModel();
- queryModel.setQuery(query);
-
- if (ofNullable(queryLanguage).isPresent())
- {
- queryModel.setLanguage(queryLanguage.toString());
- }
-
- SearchResponse response = queryAsUser(testUser, queryModel);
-
- restClient.assertStatusCodeIs(HttpStatus.OK);
+ SearchResponse response = performSearch(testUser, query, queryLanguage);
if (ofNullable(expectedCount).isPresent())
{
@@ -449,7 +445,64 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
return response;
}
+
+ /**
+ * Helper method to test if the search query returns the expected results in the order given.
+ *
+ * @param query: AFTS or cmis query string
+ * @param expectedNames: The ordered list of names expected to be returned,
+ * @return SearchResponse
+ */
+ protected SearchResponse testSearchQueryOrdered(String query, List expectedNames, SearchLanguage queryLanguage)
+ {
+ SearchResponse response = performSearch(testUser, query, queryLanguage);
+
+ List names = response.getEntries().stream().map(s -> s.getModel().getName()).collect(Collectors.toList());
+
+ // Include lists in failure message as TestNG won't do this for lists.
+ assertEquals(names, expectedNames, "Unexpected results for query: " + query + " Expected: " + expectedNames + " but got " + names);
+ return response;
+ }
+
+ /**
+ * Helper method to test if the search query returns the expected set of results.
+ *
+ * @param query: AFTS or cmis query string
+ * @param expectedNames: The ordered list of names expected to be returned,
+ * @return SearchResponse
+ */
+ protected SearchResponse testSearchQueryUnordered(String query, Set expectedNames, SearchLanguage queryLanguage)
+ {
+ SearchResponse response = performSearch(testUser, query, queryLanguage);
+
+ Set names = response.getEntries().stream().map(s -> s.getModel().getName()).collect(Collectors.toSet());
+
+ assertEquals(names, expectedNames, "Unexpected results for query: " + query);
+
+ return response;
+ }
+
+ private SearchResponse performSearch(UserModel asUser, String query, SearchLanguage queryLanguage)
+ {
+ RestRequestQueryModel queryModel = new RestRequestQueryModel();
+ queryModel.setQuery(query);
+
+ if (!ofNullable(asUser).isPresent())
+ {
+ asUser = testUser;
+ }
+
+ if (ofNullable(queryLanguage).isPresent())
+ {
+ queryModel.setLanguage(queryLanguage.toString());
+ }
+
+ SearchResponse response = queryAsUser(asUser, queryModel);
+
+ return response;
+ }
+
/**
* Method to create and run a simple spellcheck query
* When a spellcheck query is run a user, the query inputed and the user query is inputted
@@ -461,8 +514,8 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
{
RestRequestSpellcheckModel spellCheck = new RestRequestSpellcheckModel();
spellCheck.setQuery(userQuery);
-
- UserModel searchUser = ofNullable(user).isPresent()? user: testUser;
+
+ UserModel searchUser = ofNullable(user).isPresent() ? user : testUser;
SearchRequest searchReq = new SearchRequest();
RestRequestQueryModel queryReq = new RestRequestQueryModel();
queryReq.setQuery(query);
@@ -475,8 +528,8 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
/**
* Method to check the spellcheck object returned in the Search Response
- * @param response SearchResponse
- * @param spellCheckType String Values: searchInsteadFor, didYouMean or null
+ * @param response SearchResponse
+ * @param spellCheckType String Values: searchInsteadFor, didYouMean or null
* @param spellCheckSuggestion String Values: suggestion string or null
*/
public void testSearchSpellcheckResponse(SearchResponse response, String spellCheckType, String spellCheckSuggestion)
@@ -495,6 +548,6 @@ public abstract class AbstractE2EFunctionalTest extends AbstractTestNGSpringCont
{
response.getContext().assertThat().field("spellCheck").isNotEmpty();
response.getContext().getSpellCheck().assertThat().field("suggestions").contains(spellCheckSuggestion);
- }
+ }
}
}
diff --git a/e2e-test/src/test/java/org/alfresco/test/search/functional/searchServices/search/SearchAFTSInFieldTest.java b/e2e-test/src/test/java/org/alfresco/test/search/functional/searchServices/search/SearchAFTSInFieldTest.java
new file mode 100644
index 000000000..987f141d1
--- /dev/null
+++ b/e2e-test/src/test/java/org/alfresco/test/search/functional/searchServices/search/SearchAFTSInFieldTest.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2019 Alfresco Software, Ltd. All rights reserved.
+ * License rights for this program may be obtained from Alfresco Software, Ltd.
+ * pursuant to a written agreement and any use of this program without such an
+ * agreement is prohibited.
+ */
+
+package org.alfresco.test.search.functional.searchServices.search;
+
+import static java.util.List.of;
+
+import static jersey.repackaged.com.google.common.collect.Sets.newHashSet;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.alfresco.rest.model.RestNodeAssociationModelCollection;
+import org.alfresco.rest.model.RestNodeChildAssociationModel;
+import org.alfresco.rest.search.SearchResponse;
+import org.alfresco.search.TestGroup;
+import org.alfresco.test.search.functional.AbstractE2EFunctionalTest;
+import org.alfresco.utility.model.FileModel;
+import org.alfresco.utility.model.FileType;
+import org.alfresco.utility.model.FolderModel;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Test class tests AFTS Search In Field works
+ * Created for Search-840
+ *
+ * @author Meenal Bhave
+ */
+public class SearchAFTSInFieldTest extends AbstractE2EFunctionalTest
+{
+ private FolderModel folder1, folder2;
+ private FileModel file1, file2, file3, file4, file5;
+
+ @BeforeClass(alwaysRun = true)
+ public void dataPreparation()
+ {
+ // Create Folders:
+ // Folder1: Expected to be found with file.txt
+ folder1 = new FolderModel("file txt folder");
+ dataContent.usingUser(testUser).usingSite(testSite).createFolder(folder1);
+
+ // Folder2: Not expected to be found with file.txt
+ folder2 = new FolderModel("txt files folder");
+ dataContent.usingUser(testUser).usingSite(testSite).createFolder(folder2);
+
+ // Create File(s): Expected to be found with file.txt
+ file1 = new FileModel("file.txt", "file.txt", "", FileType.TEXT_PLAIN, "file.txt");
+
+ file2 = new FileModel("1-file.txt", "1-file.txt", "", FileType.TEXT_PLAIN, "1-file.txt");
+
+ file3 = new FileModel("file1.txt", "file1.txt", "", FileType.TEXT_PLAIN, "file1.txt");
+
+ file4 = new FileModel("txt file", "txt file", "", FileType.TEXT_PLAIN, "txt file");
+
+ // Not Expected to be found with file.txt
+ file5 = new FileModel("txt files", "txt files", "", FileType.TEXT_PLAIN, "txt files");
+
+ of(file1, file2, file3, file4, file5).forEach(
+ f -> dataContent.usingUser(testUser).usingSite(testSite).usingResource(folder1).createContent(f));
+
+ waitForContentIndexing(file5.getContent(), true);
+ }
+
+ @Test(priority = 1, groups = { TestGroup.ACS_63n })
+ public void testSearchInFieldName()
+ {
+ // Field names in various formats
+ Stream fieldNames = Stream.of("{http://www.alfresco.org/model/content/1.0}name",
+ "@{http://www.alfresco.org/model/content/1.0}name",
+ "cm_name",
+ "cm:name",
+ "@cm:name",
+ "name");
+
+ // For each field name, check that queries return consistent results with / out ''
+ fieldNames.forEach(fieldName ->
+ {
+ // Query string without quotes
+ String query = fieldName + ":file.txt";
+
+ Set expectedNames = newHashSet();
+ expectedNames.add("file.txt"); // file1
+ expectedNames.add("1-file.txt"); // file2
+ expectedNames.add("file1.txt"); // file3
+ expectedNames.add("txt file"); // file4
+ expectedNames.add("file txt folder"); // folder1
+
+ testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
+
+ // Query string in single quotes
+ query = fieldName + ":'file.txt'";
+ testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
+ });
+ }
+
+ @Test(priority = 2, groups = { TestGroup.ACS_63n })
+ public void testSearchInFieldTitle()
+ {
+ // Field names in various formats
+ Stream fieldNames = Stream.of("{http://www.alfresco.org/model/content/1.0}title",
+ "@{http://www.alfresco.org/model/content/1.0}title",
+ "cm_title",
+ "cm:title",
+ "@cm:title");
+
+ // For each field name, check that queries return consistent results with / out ''
+ fieldNames.forEach(fieldName ->
+ {
+ String query = fieldName + ":" + file2.getName();
+ boolean fileFound = isContentInSearchResults(query, file2.getName(), true);
+ Assert.assertTrue(fileFound, "File Not found for query: " + query);
+
+ testSearchQuery(query, 1, SearchLanguage.AFTS);
+
+ query = fieldName + ":'" + file2.getName() + "\'";
+ fileFound = isContentInSearchResults(query, file2.getName(), true);
+ Assert.assertTrue(fileFound, "File Not found for query: " + query);
+
+ testSearchQuery(query, 1, SearchLanguage.AFTS);
+ });
+ }
+
+ @Test(priority = 3, groups = { TestGroup.ACS_63n })
+ public void testSearchInFieldContent()
+ {
+ // Field names in various formats
+ List fieldNames = new ArrayList<>();
+ fieldNames.add("TEXT");
+ fieldNames.add("{http://www.alfresco.org/model/dictionary/1.0}content");
+ fieldNames.add("cm:content");
+ fieldNames.add("d:content");
+
+ // For each field name, check that queries return consistent results with / out ''
+ fieldNames.forEach(fieldName ->
+ {
+ String query = fieldName + ":" + file3.getContent();
+ boolean fileFound = isContentInSearchResults(query, file3.getName(), true);
+ Assert.assertTrue(fileFound, "File Not found for query: " + query);
+
+ Integer resultCount1 = testSearchQuery(query, null, SearchLanguage.AFTS).getPagination().getTotalItems();
+
+ query = fieldName + ":'" + file3.getContent() + "\'";
+ fileFound = isContentInSearchResults(query, file3.getName(), true);
+ Assert.assertTrue(fileFound, "File Not found for query: " + query);
+
+ testSearchQuery(query, resultCount1, SearchLanguage.AFTS).getPagination().getTotalItems();
+ });
+ }
+
+ @Test(priority = 4)
+ public void testSearchInFieldSITE()
+ {
+ String query = "SITE:" + testSite.getId();
+ boolean fileFound = isContentInSearchResults(query, folder1.getName(), true);
+ Assert.assertTrue(fileFound, "Site Not found for query: " + query);
+
+ Integer resultCount1 = testSearchQuery(query, 8, SearchLanguage.AFTS).getPagination().getTotalItems();
+
+ query = "SITE:'" + testSite.getId() + "\'";
+ fileFound = isContentInSearchResults(query, folder1.getName(), true);
+ Assert.assertTrue(fileFound, "Site Not found for query: " + query);
+
+ testSearchQuery(query, resultCount1, SearchLanguage.AFTS).getPagination().getTotalItems();
+ }
+
+ @Test(priority = 5)
+ public void testSearchInFieldTYPE()
+ {
+ // Field names in various formats
+ List fieldNames = new ArrayList<>();
+ fieldNames.add("TYPE");
+ fieldNames.add("EXACTTYPE");
+
+ // For each field name, check that queries return consistent results with / out ''
+ fieldNames.forEach(fieldName -> {
+
+ String query = fieldName + ":cm\\:content" + " and =cm:name:" + file1.getName();
+ boolean fileFound = isContentInSearchResults(query, file1.getName(), true);
+ Assert.assertTrue(fileFound, "Content Not found for query: " + query);
+
+ Integer resultCount1 = testSearchQuery(query, 1, SearchLanguage.AFTS).getPagination().getTotalItems();
+
+ query = fieldName + ":'cm:content'" + " and =cm:name:" + file1.getName();
+ fileFound = isContentInSearchResults(query, file1.getName(), true);
+ Assert.assertTrue(fileFound, "Content Not found for query: " + query);
+
+ testSearchQuery(query, resultCount1, SearchLanguage.AFTS).getPagination().getTotalItems();
+ });
+ }
+
+ @Test(priority = 6)
+ public void testSearchInFieldID() throws Exception
+ {
+ String query = "ID:'workspace://SpacesStore/" + file1.getNodeRefWithoutVersion() + "'";
+ boolean fileFound = isContentInSearchResults(query, file1.getName(), true);
+ Assert.assertTrue(fileFound, "Content Not found for query: " + query);
+
+ testSearchQuery(query, 1, SearchLanguage.AFTS).getPagination().getTotalItems();
+ }
+
+ @Test(priority = 7)
+ public void testSearchInFieldPARENT()
+ {
+ String query = "PARENT:" + folder1.getNodeRefWithoutVersion();
+
+ Set expectedNames = newHashSet();
+ expectedNames.add(file1.getName());
+ expectedNames.add(file2.getName());
+ expectedNames.add(file3.getName());
+ expectedNames.add(file4.getName());
+ expectedNames.add(file5.getName());
+
+ testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
+
+ query = "PARENT:'" + folder1.getNodeRefWithoutVersion() + "\'";
+
+ testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
+ }
+
+ @Test(priority = 8)
+ public void testSearchInFieldPRIMARYPARENT() throws Exception
+ {
+ // Create Secondary association in testFolder2
+ RestNodeChildAssociationModel childAssoc1 = new RestNodeChildAssociationModel(file1.getNodeRefWithoutVersion(), "cm:contains");
+ String secondaryChildrenBody = "[" + childAssoc1.toJson() + "]";
+
+ restClient.authenticateUser(testUser).withCoreAPI().usingResource(folder2).createSecondaryChildren(secondaryChildrenBody);
+ RestNodeAssociationModelCollection secondaryChildren = restClient.authenticateUser(testUser).withCoreAPI().usingResource(folder2).getSecondaryChildren();
+ secondaryChildren.getEntryByIndex(0).assertThat().field("id").is(file1.getNodeRefWithoutVersion());
+
+ String query = "PRIMARYPARENT:'workspace://SpacesStore/" + folder1.getNodeRef() + "'";
+
+ Set expectedNames = newHashSet();
+ expectedNames.add(file1.getName());
+ expectedNames.add(file2.getName());
+ expectedNames.add(file3.getName());
+ expectedNames.add(file4.getName());
+ expectedNames.add(file5.getName());
+
+ testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
+
+ query = "PARENT:'workspace://SpacesStore/" + folder2.getNodeRef() + "'";
+ boolean fileFound = isContentInSearchResults(query, file1.getName(), true);
+ Assert.assertTrue(fileFound, "Expected Content Not found for query: " + query);
+
+ testSearchQuery(query, 1, SearchLanguage.AFTS);
+ }
+
+ @Test(priority = 9, groups = { TestGroup.ACS_63n })
+ public void testSearchInFieldNameExactMatch()
+ {
+ // Check that queries return consistent results with / out ''
+ String query = "=name:" + file1.getName();
+ boolean fileFound = isContentInSearchResults(query, file1.getName(), true);
+ Assert.assertTrue(fileFound, "File Not found for query: " + query);
+
+ Integer resultCount1 = testSearchQuery(query, 1, SearchLanguage.AFTS).getPagination().getTotalItems();
+ Assert.assertSame(resultCount1, 1, "File count does not match for query: " + query);
+
+ query = "=name:'" + file1.getName() + "\'";
+ fileFound = isContentInSearchResults(query, file1.getName(), true);
+ Assert.assertTrue(fileFound, "File Not found for query: " + query);
+
+ testSearchQuery(query, resultCount1, SearchLanguage.AFTS).getPagination().getTotalItems();
+ }
+
+ @Test(priority = 10, groups = { TestGroup.ACS_63n })
+ public void testSearchInFieldNameQueryExpansion()
+ {
+ // Check that queries return consistent results with / out ''
+ String query = "~name:" + file1.getName();
+
+ Set expectedNames = newHashSet();
+ expectedNames.add(file1.getName());
+ expectedNames.add(file2.getName());
+ expectedNames.add(file3.getName());
+ expectedNames.add(file4.getName());
+ expectedNames.add(folder1.getName());
+
+ testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
+
+ query = "~name:'" + file1.getName() + "\'";
+ testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
+ }
+
+ @Test(priority = 11, groups = { TestGroup.ACS_63n })
+ public void testWithConjunctionDisjunctionAndNegation()
+ {
+ // Query string to include Conjunction, Disjunction and Negation
+
+ String query1 = "~name:" + file1.getName(); // Query expected to return 5 results
+ String query2 = "=name:" + file2.getName(); // Query expected to return 1 result
+ String query3 = "=name:" + file3.getName(); // Query expected to return 1 result
+
+ // Check Query with Conjunction, Negation, Disjunction: returns right results
+ // "~name:file.txt and ! (=name:1-file.txt or =name:file1.txt)"
+ String query = query1 + " and ! (" + query2 + " or " + query3 + ")";
+
+ // Check that expected files are included in the results
+ Set expectedNames = newHashSet();
+ expectedNames.add("file.txt"); // file1
+ expectedNames.add("txt file"); // file4
+ expectedNames.add("file txt folder"); // folder1
+
+ SearchResponse response = testSearchQueryUnordered(query, expectedNames, SearchLanguage.AFTS);
+
+ // Check result count is 5-(1+1)=3
+ int resultCount = response.getPagination().getTotalItems();
+ Assert.assertEquals(resultCount, 3, "File count does not match for query: " + query);
+
+ // Check that file2 and file3 are excluded from the results
+ boolean fileFound = isContentInSearchResponse(response, file2.getName());
+ Assert.assertFalse(fileFound, "File2 found for query: " + query);
+
+ fileFound = isContentInSearchResponse(response, file3.getName());
+ Assert.assertFalse(fileFound, "File3 found for query: " + query);
+ }
+}
diff --git a/search-services/alfresco-solrclient-lib/pom.xml b/search-services/alfresco-solrclient-lib/pom.xml
index 9438343fb..eb8c5dd03 100644
--- a/search-services/alfresco-solrclient-lib/pom.xml
+++ b/search-services/alfresco-solrclient-lib/pom.xml
@@ -22,7 +22,7 @@
- 8.57
+ 8.60
2.10.1
diff --git a/search-services/packaging/src/docker/Dockerfile b/search-services/packaging/src/docker/Dockerfile
index 852223ecf..ea60bca76 100644
--- a/search-services/packaging/src/docker/Dockerfile
+++ b/search-services/packaging/src/docker/Dockerfile
@@ -1,6 +1,6 @@
# Alfresco Search Services ${project.version} Docker Image
-FROM alfresco/alfresco-base-java:11.0.1-openjdk-centos-7-6784d76a7b81
+FROM alfresco/alfresco-base-java:11.0.1-openjdk-centos-7-7a6031154417
LABEL creator="Gethin James" maintainer="Alfresco Search Services Team"
ENV DIST_DIR /opt/alfresco-search-services
diff --git a/search-services/packaging/src/main/resources/licenses/notice.txt b/search-services/packaging/src/main/resources/licenses/notice.txt
index 423541459..ce669d559 100644
--- a/search-services/packaging/src/main/resources/licenses/notice.txt
+++ b/search-services/packaging/src/main/resources/licenses/notice.txt
@@ -58,16 +58,16 @@ jackson-core-2.10.1.jar https://github.com/FasterXML/jackson
jackson-annotations-2.10.1.jar https://github.com/FasterXML/jackson
jackson-databind-2.10.1.jar https://github.com/FasterXML/jackson
commons-httpclient-3.1-HTTPCLIENT-1265.jar http://jakarta.apache.org/commons/
-spring-aop-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
-spring-beans-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
-spring-context-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
-spring-context-support-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
-spring-core-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
-spring-expression-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
-spring-jdbc-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
-spring-orm-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
-spring-tx-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
-spring-web-5.1.8.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-aop-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-beans-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-context-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-context-support-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-core-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-expression-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-jdbc-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-orm-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-tx-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
+spring-web-5.2.2.RELEASE.jar http://projects.spring.io/spring-framework/
xercesImpl-2.12.0-alfresco-patched-20191004.jar http://xerces.apache.org/xerces2-j
guessencoding-1.4.jar http://docs.codehaus.org/display/GUESSENC/
xml-apis-1.4.01.jar https://github.com/FasterXML/jackson