Merge branch 'feature/search-1348' into 'master'

SEARCH-1348 Add basic automated tests for search services using a RM site and a basic file plan.

See merge request search_discovery/SearchAnalyticsE2ETest!30
This commit is contained in:
Cristina Diaconu
2019-03-25 14:36:01 +00:00
7 changed files with 429 additions and 0 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<String> 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;
}
}

View File

@@ -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);
}
}

View File

@@ -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");
}
}

View File

@@ -0,0 +1,9 @@
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="CompatibilitySuite" verbose="6" preserve-order="true">
<test name="SS-With-RM">
<packages>
<package
name="org.alfresco.service.search.e2e.rm.searchServices"></package>
</packages>
</test>
</suite>