diff --git a/e2e-test/qa/compatibility/.env b/e2e-test/qa/compatibility/.env new file mode 100644 index 000000000..be96f1b9c --- /dev/null +++ b/e2e-test/qa/compatibility/.env @@ -0,0 +1,11 @@ +# docker-compose related environments +ALFRESCO_IMAGE=quay.io/alfresco/alfresco-governance-repository-enterprise +ALFRESCO_TAG=latest +SHARE_IMAGE=quay.io/alfresco/alfresco-governance-share-enterprise +SHARE_TAG=latest +POSTGRES_IMAGE=postgres +POSTGRES_TAG=10.1 +SEARCH_IMAGE=quay.io/alfresco/insight-engine +SEARCH_TAG=latest +ACTIVEMQ_IMAGE=alfresco/alfresco-activemq +ACTIVEMQ_TAG=5.15.6 \ No newline at end of file diff --git a/e2e-test/qa/compatibility/Makefile b/e2e-test/qa/compatibility/Makefile new file mode 100644 index 000000000..2844d8cb6 --- /dev/null +++ b/e2e-test/qa/compatibility/Makefile @@ -0,0 +1,9 @@ +include ../Makefile +include .env + +# CURRENT_DIR is the folder where this Makefile is saved +CURRENT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) + +start: ## 0 - starts search service with SSL enabled + $(dc) config && $(dc) up -d && \ + make wait \ No newline at end of file diff --git a/e2e-test/qa/compatibility/docker-compose.yml b/e2e-test/qa/compatibility/docker-compose.yml new file mode 100644 index 000000000..6c07160e3 --- /dev/null +++ b/e2e-test/qa/compatibility/docker-compose.yml @@ -0,0 +1,65 @@ +version: '3' +services: + alfresco: + image: ${ALFRESCO_IMAGE}:${ALFRESCO_TAG} + environment: + JAVA_OPTS : " + -Ddb.driver=org.postgresql.Driver + -Ddb.username=alfresco + -Ddb.password=alfresco + -Ddb.url=jdbc:postgresql://postgres:5432/alfresco + -Dsolr.host=search + -Dsolr.port=8983 + -Dsolr.secureComms=none + -Dsolr.base.url=/solr + -Dindex.subsystem.name=solr6 + -Dalfresco.restApi.basicAuthScheme=true + -Ddeployment.method=DOCKER_COMPOSE + -Dcsrf.filter.enabled=false + -Dmessaging.broker.url=\"failover:(nio://activemq:61616)?timeout=3000&jms.useCompression=true\" + -Xms1g -Xmx1g + " + ports: + - "7203:7203" #JMX connect via service:jmx:rmi:///jndi/rmi://localhost:7203/jmxrmi + - "5005:5005" #Java debugging + - "8081:8080" #Browser port for Alfresco + + share: + image: ${SHARE_IMAGE}:${SHARE_TAG} + environment: + - REPO_HOST=alfresco + - REPO_PORT=8080 + - "CATALINA_OPTS= -Xms500m -Xmx500m" + ports: + - 8082:8080 #Browser port for Share + + postgres: + image: ${POSTGRES_IMAGE}:${POSTGRES_TAG} + environment: + - POSTGRES_PASSWORD=alfresco + - POSTGRES_USER=alfresco + - POSTGRES_DB=alfresco + ports: + - 5432:5432 + + search: + image: ${SEARCH_IMAGE}:${SEARCH_TAG} + environment: + #Solr needs to know how to register itself with Alfresco + - SOLR_ALFRESCO_HOST=alfresco + - SOLR_ALFRESCO_PORT=8080 + #Alfresco needs to know how to call solr + - SOLR_SOLR_HOST=search + - SOLR_SOLR_PORT=8983 + #Create the default alfresco and archive cores + - SOLR_CREATE_ALFRESCO_DEFAULTS=alfresco,archive + ports: + - 8083:8983 #Browser port + + activemq: + image: ${ACTIVEMQ_IMAGE}:${ACTIVEMQ_TAG} + ports: + - 8161:8161 # Web Console + - 5672:5672 # AMQP + - 61616:61616 # OpenWire + - 61613:61613 # STOMP diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractRMSearchServiceE2E.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractRMSearchServiceE2E.java new file mode 100644 index 000000000..d97104759 --- /dev/null +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractRMSearchServiceE2E.java @@ -0,0 +1,262 @@ +/* + * 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.service.search.e2e; + +import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordCategoryChildModel; +import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordCategoryModel; + +import java.util.List; + +import org.alfresco.dataprep.SiteService.RMSiteCompliance; +import org.alfresco.rest.core.RestAPIFactory; +import org.alfresco.rest.rm.community.model.record.Record; +import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory; +import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild; +import org.alfresco.rest.rm.community.requests.gscore.api.RMSiteAPI; +import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI; +import org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI; +import org.alfresco.utility.data.RandomData; +import org.alfresco.utility.model.SiteModel; +import org.alfresco.utility.model.UserModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; + +/** + * Base test class for RM tests. + * + * @author Cristina Diaconu + */ +public class AbstractRMSearchServiceE2E extends AbstractSearchServiceE2E +{ + protected static final String FILE_PLAN_ALIAS = "-filePlan-"; + protected static final String RECORD_TYPE = "rma:record"; + protected static final String RECORD_FOLDER_TYPE = "rma:recordFolder"; + protected static final String RECORD_CATEGORY_TYPE = "rma:recordCategory"; + protected static final String CONTENT_TYPE = "cm:content"; + protected static final String ASPECTS_COMPLETED_RECORD = "rma:declaredRecord"; + protected static final String NON_ELECTRONIC_RECORD_TYPE = "rma:nonElectronicDocument"; + protected static final String RECORD_CATEGORY_TITLE = "RM_CATEGORY_TITLE"; + + protected static final String ROOT_CATEGORY_NAME = RandomData.getRandomName("RM_Cat"); + protected static final String CATEGORY1 = RandomData.getRandomName("RM_child_cat1"); + protected static final String CATEGORY2 = RandomData.getRandomName("RM_child_cat2"); + protected static final String FOLDER1 = RandomData.getRandomName("RM_folder1"); + protected static final String FOLDER2 = RandomData.getRandomName("RM_folder2"); + protected static final String ELECTRONIC_FILE = RandomData.getRandomName("RM_electonic_file"); + protected static final String NON_ELECTRONIC_FILE = RandomData.getRandomName("RM_nonelectonic_file"); + protected static final String SEARCH_LANGUAGE = "cmis"; + + @Autowired + protected RestAPIFactory restAPIFactory; + + @BeforeClass(alwaysRun = true) + public void dataPreparation() throws Exception + { + serverHealth.assertServerIsOnline(); + + testSite = createRMSite(); + + // create the Root category + RecordCategory rootCategory = createRootCategory(ROOT_CATEGORY_NAME); + Assert.assertNotNull(rootCategory, "Root category was not created!"); + + // Add two children (categories) on Root category + RecordCategoryChild childCategory1 = createRecordCategoryChild(rootCategory.getId(), CATEGORY1); + Assert.assertNotNull(childCategory1, "Child category 1 was not created!"); + + RecordCategoryChild childCategory2 = createRecordCategoryChild(rootCategory.getId(), CATEGORY2); + Assert.assertNotNull(childCategory2, "Child category 2 was not created!"); + + // Create two folders with records (electronic and nonElectronic files) on Child category 1 + RecordCategoryChild folder1 = createRecordFolder(childCategory1.getId(), FOLDER1); + RecordCategoryChild folder2 = createRecordFolder(childCategory1.getId(), FOLDER2); + + // Create two folders on Child Category2 + createRecordFolder(childCategory2.getId(), FOLDER1); + createRecordFolder(childCategory2.getId(), FOLDER2); + + // Complete a file + Record electronicRecord = createElectronicRecord(folder1.getId(), ELECTRONIC_FILE); + completeRecord(electronicRecord.getId()); + createNonElectronicRecord(folder1.getId(), NON_ELECTRONIC_FILE); + + // Add an electronic record on folder2 + createElectronicRecord(folder2.getId(), ELECTRONIC_FILE); + } + + /** + * Create a new RM Site. If the site already exists then remove it and create a new one. + */ + public SiteModel createRMSite() throws Exception + { + RMSiteAPI rmSiteAPI = restAPIFactory.getRMSiteAPI(); + + if (rmSiteAPI.existsRMSite()) + { + rmSiteAPI.deleteRMSite(); + } + + return dataSite.createRMSite(RMSiteCompliance.STANDARD); + } + + /** + * Helper method to create root category as the admin user + * + * @param categoryName The name of the category + * @return The created category + * @throws Exception on unsuccessful component creation + */ + public RecordCategory createRootCategory(String categoryName) throws Exception + { + return createRootCategory(dataUser.getAdminUser(), categoryName, RECORD_CATEGORY_TITLE); + } + + /** + * Helper method to create root category + * + * @param userModel The user under whose privileges this structure is going to be created + * @param categoryName The name of the category + * @param categoryTitle The title of the category + * @return The created category + * @throws Exception on unsuccessful component creation + */ + public RecordCategory createRootCategory(UserModel userModel, String categoryName, String categoryTitle) + throws Exception + { + RecordCategory recordCategoryModel = createRecordCategoryModel(categoryName, categoryTitle); + return restAPIFactory.getFilePlansAPI(userModel).createRootRecordCategory(recordCategoryModel, FILE_PLAN_ALIAS); + } + + /** + * Helper method to create a record category as the admin user + * + * @param recordCategoryId The id of the record category + * @param name The name of the record category child + * @return The created child category + * @throws Exception on unsuccessful component creation + */ + public RecordCategoryChild createRecordCategoryChild(String recordCategoryId, String name) throws Exception + { + return createRecordCategoryChild(dataUser.getAdminUser(), recordCategoryId, name, RECORD_CATEGORY_TYPE); + } + + /** + * Helper method to create a record category child + * + * @param user The user under whose privileges the node is going to be created + * @param recordCategoryId The id of the record category + * @param name The name of the record category child + * @param type The type of the record category child + * @return The created child category + * @throws Exception on unsuccessful component creation + */ + public RecordCategoryChild createRecordCategoryChild(UserModel user, String recordCategoryId, String name, + String type) throws Exception + { + RecordCategoryChild recordCategoryChildModel = createRecordCategoryChildModel(name, type); + return restAPIFactory.getRecordCategoryAPI(user).createRecordCategoryChild(recordCategoryChildModel, + recordCategoryId); + } + + /** + * Helper method to create a record folder as the admin user + * + * @param recordCategoryId The id of the record category + * @param name The name of the record category child + * @return The created record folder. + * @throws Exception on unsuccessful component creation + */ + public RecordCategoryChild createRecordFolder(String recordCategoryId, String name) throws Exception + { + return createRecordCategoryChild(dataUser.getAdminUser(), recordCategoryId, name, RECORD_FOLDER_TYPE); + } + + /** + * Create an electronic record + * + * @param parentId The id of the parent + * @param name The name of the record + * @return The created record + * @throws Exception on unsuccessful component creation + */ + public Record createElectronicRecord(String parentId, String name) throws Exception + { + return createElectronicRecord(parentId, name, null); + } + + /** + * Create an electronic record + * + * @param parentId The id of the parent + * @param name The name of the record + * @return The created electronic record + * @throws Exception on unsuccessful component creation + */ + public Record createElectronicRecord(String parentId, String name, UserModel user) throws Exception + { + RecordFolderAPI recordFolderAPI = restAPIFactory.getRecordFolderAPI(user); + Record recordModel = Record.builder().name(name).nodeType(CONTENT_TYPE).build(); + return recordFolderAPI.createRecord(recordModel, parentId); + } + + /** + * Create a non-electronic record + * + * @param parentId The id of the parent + * @param name The name of the record + * @return The created non electronic record + * @throws Exception on unsuccessful component creation + */ + public Record createNonElectronicRecord(String parentId, String name) throws Exception + { + return createNonElectronicRecord(parentId, name, null); + } + + /** + * Create a non-electronic record + * + * @param parentId The id of the parent + * @param name The name of the record + * @param user The user who creates the non-electronic record + * @return The created non electronic record + * @throws Exception on unsuccessful component creation + */ + public Record createNonElectronicRecord(String parentId, String name, UserModel user) throws Exception + { + RecordFolderAPI recordFolderAPI = restAPIFactory.getRecordFolderAPI(user); + Record recordModel = Record.builder().name(name).nodeType(NON_ELECTRONIC_RECORD_TYPE).build(); + return recordFolderAPI.createRecord(recordModel, parentId); + } + + /** + * Helper method to complete record + * + * @param recordId The id of the record to complete + * @return The completed record + * @throws Exception on unsuccessful component creation + */ + public Record completeRecord(String recordId) throws Exception + { + RecordsAPI recordsAPI = restAPIFactory.getRecordsAPI(); + List aspects = recordsAPI.getRecord(recordId).getAspectNames(); + + // this operation is only valid for records + Assert.assertTrue(aspects.contains(RECORD_TYPE)); + // a record mustn't be completed + Assert.assertFalse(aspects.contains(ASPECTS_COMPLETED_RECORD)); + // add completed record aspect + aspects.add(ASPECTS_COMPLETED_RECORD); + + Record updateRecord = recordsAPI.updateRecord(Record.builder().aspectNames(aspects).build(), recordId); + restAPIFactory.getRmRestWrapper().assertStatusCodeIs(HttpStatus.OK); + + return updateRecord; + } +} diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractSearchServiceE2E.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractSearchServiceE2E.java index 1ebf33835..97847c024 100644 --- a/e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractSearchServiceE2E.java +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractSearchServiceE2E.java @@ -454,4 +454,20 @@ public abstract class AbstractSearchServiceE2E extends AbstractTestNGSpringConte searchRequest.setQuery(queryModel); return restClient.authenticateUser(user).withSearchAPI().search(searchRequest); } + + /** + * Run a search 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 + * @return the search response from the API + * @throws Exception + */ + public SearchResponse queryAsUser(UserModel user, RestRequestQueryModel queryModel) throws Exception + { + SearchRequest searchRequest = new SearchRequest(); + searchRequest.setQuery(queryModel); + + return restClient.authenticateUser(user).withSearchAPI().search(searchRequest); + } } diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/rm/searchServices/SearchServicesRME2ETest.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/rm/searchServices/SearchServicesRME2ETest.java new file mode 100644 index 000000000..ddcfdf09e --- /dev/null +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/rm/searchServices/SearchServicesRME2ETest.java @@ -0,0 +1,57 @@ +/* + * 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.service.search.e2e.rm.searchServices; + +import org.alfresco.rest.search.RestRequestQueryModel; +import org.alfresco.rest.search.SearchResponse; +import org.alfresco.service.search.e2e.AbstractRMSearchServiceE2E; +import org.alfresco.utility.model.TestGroup; +import org.springframework.http.HttpStatus; +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * The purpose of this test is to create basic queries using a RM site and a basic file plan. + * + * @author Cristina Diaconu + */ +public class SearchServicesRME2ETest extends AbstractRMSearchServiceE2E +{ + + @Test(priority = 1, groups = { TestGroup.ASS_14 }) + public void testBasicSearch() throws Exception + { + + // Search for a folder name + String query = "select * from cmis:folder where cmis:name='" + FOLDER1 + "'"; + + RestRequestQueryModel queryModel = new RestRequestQueryModel(); + queryModel.setQuery(query); + queryModel.setLanguage(SEARCH_LANGUAGE); + + SearchResponse response = queryAsUser(dataUser.getAdminUser(), queryModel); + restClient.assertStatusCodeIs(HttpStatus.OK); + + Assert.assertEquals(response.getPagination().getCount(), 2, + "Wrong number of search elements, expected two folders."); + + // Search for a file name + query = "select * from cmis:document where cmis:name like '" + NON_ELECTRONIC_FILE + "%'"; + + queryModel = new RestRequestQueryModel(); + queryModel.setQuery(query); + queryModel.setLanguage(SEARCH_LANGUAGE); + + response = queryAsUser(dataUser.getAdminUser(), queryModel); + restClient.assertStatusCodeIs(HttpStatus.OK); + + Assert.assertEquals(response.getPagination().getCount(), 1, + "Wrong number of search elements, expected 1 non electronic file"); + } + +} diff --git a/e2e-test/src/test/resources/search-compatibility-with-RM-suite.xml b/e2e-test/src/test/resources/search-compatibility-with-RM-suite.xml new file mode 100644 index 000000000..0816d4daf --- /dev/null +++ b/e2e-test/src/test/resources/search-compatibility-with-RM-suite.xml @@ -0,0 +1,9 @@ + + + + + + + +