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