diff --git a/e2e-test/qa/Makefile b/e2e-test/qa/Makefile index 6b0ac26d4..c8c00a380 100644 --- a/e2e-test/qa/Makefile +++ b/e2e-test/qa/Makefile @@ -17,7 +17,7 @@ help: ## main: output this help .DEFAULT_GOAL := help # $(helpers)/wait-service-to-start.sh -ifeq ($(dc),) +ifeq ($(helpers),) helpers:=$(ROOT_DIR)/qa/.helpers endif diff --git a/e2e-test/qa/search/backup/Makefile b/e2e-test/qa/search/backup/Makefile index c338aaea1..16a5472df 100644 --- a/e2e-test/qa/search/backup/Makefile +++ b/e2e-test/qa/search/backup/Makefile @@ -13,7 +13,7 @@ ifeq ($(dc-backup),) dc-backup:=$(dc) -f ../docker-compose.yml -f docker-compose.backup.yml endif -backup-prepare: ## 1 - prepare backup for testing +backup-prepare: clean ## 1 - prepare backup for testing @echo "Starting Backup Prepare" && \ $(sudo) rm -rf $(HOST_BACKUP_LOCATION) && \ mkdir -p $(HOST_BACKUP_LOCATION)/alf_data && \ @@ -27,12 +27,12 @@ backup-perform: ## 2 - perform the backup of alf_data and db data @echo "Starting Backup Perform" && \ $(sudo) rm -rf $(HOST_BACKUP_LOCATION)_$(SUFIX) && \ $(sudo) chmod -R 777 $(HOST_BACKUP_LOCATION) && \ - docker-compose stop alfresco && \ + $(dc-backup) stop alfresco && \ $(dc-backup) exec postgres bash -c 'pg_dump --dbname=postgresql://alfresco:alfresco@127.0.0.1:5432/alfresco' > $(HOST_BACKUP_LOCATION)/db/alfresco.pg && \ cp -R $(HOST_BACKUP_LOCATION) $(HOST_BACKUP_LOCATION)_$(SUFIX) && \ - docker-compose start alfresco + $(dc-backup) start alfresco -backup-restore: ## 3 - start restoring from backup location +backup-restore: clean ## 3 - start restoring from backup location @echo "Starting Backup Restore" && \ $(sudo) rm -rf $(HOST_BACKUP_LOCATION) && \ mkdir -p $(HOST_BACKUP_LOCATION) && \ @@ -41,20 +41,20 @@ backup-restore: ## 3 - start restoring from backup location cp -rf $(HOST_BACKUP_LOCATION)_$(SUFIX)/solr $(HOST_BACKUP_LOCATION)/solr && \ $(sudo) chmod -R 777 $(HOST_BACKUP_LOCATION) && \ $(dc-backup) up -d postgres && sleep 30 && \ - docker-compose exec postgres bash -c 'psql --dbname=postgresql://alfresco:alfresco@127.0.0.1:5432/alfresco < /backup/db/alfresco.pg' && \ + $(dc-backup) exec postgres bash -c 'psql --dbname=postgresql://alfresco:alfresco@127.0.0.1:5432/alfresco < /backup/db/alfresco.pg' && \ $(dc-backup) up -d all: show-config ## 0 - executes the entire backup process # perform the backup and waits until the server is starting # do some change on backed up data # then restore from backup and check the content is restored as expected - make clean backup-prepare wait && \ + make backup-prepare wait && \ make run-mvn-tests suiteXmlFile=./src/test/resources/search-pre-backup-suite.xml make backup-perform wait && \ make run-mvn-tests suiteXmlFile=./src/test/resources/search-on-backup-suite.xml - make clean backup-restore wait && \ + make backup-restore wait && \ make run-mvn-tests suiteXmlFile=./src/test/resources/search-post-backup-suite.xml show-config: ## show compose configuration diff --git a/e2e-test/qa/search/backup/README.md b/e2e-test/qa/search/backup/README.md index d2c6af69c..2f1679ccc 100644 --- a/e2e-test/qa/search/backup/README.md +++ b/e2e-test/qa/search/backup/README.md @@ -2,6 +2,10 @@ Testing the Backup of SearchService product +**Build Plan:** https://bamboo.alfresco.com/bamboo/browse/SAD-QAB + +![](docs/backup.png?raw=true) + # Steps * **a)** prepare the backup diff --git a/e2e-test/qa/search/backup/docs/backup.png b/e2e-test/qa/search/backup/docs/backup.png new file mode 100644 index 000000000..2bec6377f Binary files /dev/null and b/e2e-test/qa/search/backup/docs/backup.png differ diff --git a/e2e-test/qa/search/upgrade/README.md b/e2e-test/qa/search/upgrade/README.md index 281c70a5a..fae181d47 100644 --- a/e2e-test/qa/search/upgrade/README.md +++ b/e2e-test/qa/search/upgrade/README.md @@ -2,6 +2,10 @@ Testing the Upgrade of SearchService product +**Build Plan:** https://bamboo.alfresco.com/bamboo/browse/SAD-QAUP + +![](docs/upgrade.png?raw=true) + # Steps * **a)** start the initial version diff --git a/e2e-test/qa/search/upgrade/docs/upgrade.png b/e2e-test/qa/search/upgrade/docs/upgrade.png new file mode 100644 index 000000000..3d36c9e54 Binary files /dev/null and b/e2e-test/qa/search/upgrade/docs/upgrade.png differ diff --git a/e2e-test/src/main/resources/model/finance-model.xml b/e2e-test/src/main/resources/model/finance-model.xml index ffef6b056..8e7bee6e8 100644 --- a/e2e-test/src/main/resources/model/finance-model.xml +++ b/e2e-test/src/main/resources/model/finance-model.xml @@ -86,16 +86,14 @@ false - - - - - - - - - Parking Expense - + + CreatedAt + d:datetime + false + + TRUE + + Location d:text @@ -109,6 +107,25 @@ - + + + + + Parking Expense + + + Location + d:text + true + + TRUE + true + + + + + + + \ No newline at end of file diff --git a/e2e-test/src/test/java/org/alfresco/service/search/AbstractSearchServiceE2E.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractSearchServiceE2E.java similarity index 92% rename from e2e-test/src/test/java/org/alfresco/service/search/AbstractSearchServiceE2E.java rename to e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractSearchServiceE2E.java index f0279faf8..1ebf33835 100644 --- a/e2e-test/src/test/java/org/alfresco/service/search/AbstractSearchServiceE2E.java +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/AbstractSearchServiceE2E.java @@ -1,4 +1,4 @@ -package org.alfresco.service.search; +package org.alfresco.service.search.e2e; /* * Copyright 2019 Alfresco Software, Ltd. All rights reserved. @@ -11,11 +11,13 @@ import org.alfresco.cmis.CmisWrapper; import org.alfresco.dataprep.ContentService; import org.alfresco.dataprep.SiteService.Visibility; import org.alfresco.rest.core.RestProperties; +import org.alfresco.rest.core.RestResponse; import org.alfresco.rest.core.RestWrapper; import org.alfresco.rest.search.RestRequestQueryModel; import org.alfresco.rest.search.SearchNodeModel; import org.alfresco.rest.search.SearchRequest; import org.alfresco.rest.search.SearchResponse; +import org.alfresco.rest.search.SearchSqlRequest; import org.alfresco.utility.LogFactory; import org.alfresco.utility.TasProperties; import org.alfresco.utility.Utility; @@ -29,6 +31,7 @@ import org.alfresco.utility.model.UserModel; import org.alfresco.utility.network.ServerHealth; import org.apache.chemistry.opencmis.client.api.CmisObject; import org.apache.chemistry.opencmis.client.api.Session; +import org.hamcrest.Matchers; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -38,6 +41,8 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import lombok.Getter; + +import static java.util.Optional.ofNullable; import static lombok.AccessLevel.PROTECTED; import java.util.List; @@ -257,6 +262,33 @@ public abstract class AbstractSearchServiceE2E extends AbstractTestNGSpringConte } } + /** + * Executes a SQL query and optionally asserts the response cardinality. + * + * @param sql the SQL query. + * @param expectedCardinality if present an additional check is done in order to assert the expected response cardinality. + * @return the {@link RestResponse} instance as result of the query execution. + */ + protected RestResponse testSqlQuery(String sql, Integer expectedCardinality) + { + try { + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(sql); + + RestResponse response = restClient.authenticateUser(testUser).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + + if (ofNullable(expectedCardinality).isPresent()) { + restClient.onResponse().assertThat().body("list.pagination.count", Matchers.equalTo(expectedCardinality)); + } + + return response; + } catch (Exception exception) { + throw new AssertionError(exception); + } + } + /** * Wait for Solr to finish indexing and search to return appropriate results * diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CaseSensitivityInFieldsNamesTest.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CaseSensitivityInFieldsNamesTest.java new file mode 100644 index 000000000..fedeeb243 --- /dev/null +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CaseSensitivityInFieldsNamesTest.java @@ -0,0 +1,257 @@ +/* + * 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.insightEngine.sql; + +import static java.util.Arrays.asList; +import static java.util.stream.IntStream.range; + +import org.alfresco.service.search.e2e.AbstractSearchServiceE2E; +import org.alfresco.utility.LogFactory; +import org.alfresco.utility.model.FileModel; +import org.alfresco.utility.model.FileType; +import org.alfresco.utility.model.FolderModel; +import org.alfresco.utility.model.TestGroup; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.enums.VersioningState; +import org.hamcrest.Matchers; +import org.slf4j.Logger; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Purpose of this TestClass is to test that the fields name follows a given case-sensitive rule in different part of the query. + * Specifically: + * + *
    + *
  • When a field is declared in the field list (e.g. SELECT *a,b,c*) the case matters because a field with + * the exact case will be in the returned tuples. + *
  • + *
  • + * When a field is part of the predicate (e.g. WHERE a=somevalue) the case doesn't matter + *
  • + *
  • + * When a field is part of the expression (e.g. order by, group by) the case doesn't matter. However, specifically + * for aggregation expressions (e.g. group by), the same field with the exact case needs to be in field list (and + * here, see the first point, the case matters). + *
  • + *
+ * + * @author agazzarini + * {@link https://issues.alfresco.com/jira/browse/SEARCH-1491} + */ +public class CaseSensitivityInFieldsNamesTest extends AbstractSearchServiceE2E +{ + private static Logger LOG = LogFactory.getLogger(); + + /** + * Creates the test dataset that will be used in this test case. + */ + @BeforeClass(alwaysRun = true) + public void setupEnvironment() throws Exception + { + serverHealth.assertServerIsOnline(); + + super.springTestContextPrepareTestInstance(); + + try + { + deployCustomModel("model/expense-model.xml"); + } + catch (Exception e) + { + LOG.warn("Error Loading Expense Model", e); + } + + FolderModel testFolder = dataContent.usingSite(testSite).usingUser(testUser).createFolder(); + + createAndAddNewFile(testFolder, 1, "Maidenhead", "GBP", 10.2); + createAndAddNewFile(testFolder, 2, "London", "GBP", 100.4); + createAndAddNewFile(testFolder, 3, "Manchester", "GBP", 1737.22); + FileModel lastFile = createAndAddNewFile(testFolder, 4, "Liverpool", "GBP", 445.9); + + waitForIndexing(lastFile.getName(), true); + } + + @Test(groups = { TestGroup.INSIGHT_11 }) + public void fieldsInSelectListAreCaseSensitive() + { + List selectLists = + asList("EXPENSE_LOCATION,cm_name,expense_Currency", + "Expense_Currency,CM_NAME,ExPenSe_LOCATion", + "expense_location,expense_currency,cM_NaMe"); + + int expectedNumberOfResults = 4; + + selectLists.forEach(fields -> { + String query = "select " + fields + " from alfresco where expense_Currency='GBP' and TYPE = 'expense:expenseReport'"; + + testSqlQuery(query, expectedNumberOfResults); + + String[] expectedNames = fields.split(","); + + range(0, expectedNames.length) + .forEach(labelIndex -> { + String expectedName = expectedNames[labelIndex]; + + for (int entryIndex = 0; entryIndex < expectedNumberOfResults; entryIndex++) + restClient.onResponse() + .assertThat() + .body("list.entries.entry[" + entryIndex + "][" + labelIndex + "].label", Matchers.equalTo(expectedName)); + }); + }); + } + + @Test(groups = { TestGroup.INSIGHT_11 }) + public void fieldsInCountListAreCaseInsensitive() + { + List selectLists = + asList("cm_name", "CM_NAME","cM_NaMe", "expense_Currency","EXPENSE_CURRENCY"); + + selectLists.forEach(field -> { + String query = "select count(" + field + ") from alfresco where expense_Currency='GBP' and TYPE = 'expense:expenseReport'"; + + testSqlQuery(query, 1); + + restClient.onResponse().assertThat().body("list.entries.entry[0][0].label", Matchers.equalTo("EXPR$0")); + restClient.onResponse().assertThat().body("list.entries.entry[0][0].value", Matchers.equalTo("4")); + }); + } + + @Test(groups = { TestGroup.INSIGHT_11 }) + public void fieldsInPredicateAreCaseInsensitive() + { + List queries = + asList("select TYPE from alfresco where expense_Currency='GBP' and type = 'expense:expenseReport'", + "select TYPE from alfresco where EXPENSE_CURRENCY='GBP' and TYPE = 'expense:expenseReport'", + "select TYPE from alfresco where ExPeNsE_CurrENCY='GBP' and TyPe = 'expense:expenseReport'"); + + int expectedNumberOfResults = 4; + + queries.forEach(query -> { + testSqlQuery(query, expectedNumberOfResults); + + range(0, expectedNumberOfResults) + .forEach(entryIndex -> { + restClient.onResponse().assertThat().body("list.entries.entry[" + entryIndex + "][0].label", Matchers.equalTo("TYPE")); + restClient.onResponse().assertThat().body("list.entries.entry[" + entryIndex + "][0].value", Matchers.equalTo("{http://www.mycompany.com/model/expense/1.0}expenseReport")); + }); + }); + } + + @Test(groups = { TestGroup.INSIGHT_11 }) + public void fieldsInExpressionsAreCaseInsensitive() + { + List fieldNames = asList("expense_Currency", "EXPENSE_CURRENCY", "ExPeNsE_CurrENCY"); + List queries = fieldNames.stream() + .map(fieldName -> asList( + "select " + fieldName + " from alfresco where TYPE = 'expense:expenseReport' group by " + fieldName + " having sum(EXPENSE_AMOUNT) > 0", + "select " + fieldName + " from alfresco where TYPE = 'expense:expenseReport' group by " + fieldName + " having sum(expense_Amount) > 0", + "select " + fieldName + " from alfresco where TYPE = 'expense:expenseReport' group by " + fieldName + " having sum(expense_amount) > 0")) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + + queries.forEach(query -> { + testSqlQuery(query, 1); + restClient.onResponse().assertThat().body("list.entries.entry[0][0].label", Matchers.equalToIgnoringCase("expense_Currency")); + restClient.onResponse().assertThat().body("list.entries.entry[0][0].value", Matchers.equalTo("GBP")); + }); + } + + @Test(groups = { TestGroup.INSIGHT_11 }) + public void fieldsInSortExpressionAreCaseInsensitive_descendingOrder() + { + List queries = + asList("select expense_Id from alfresco where expense_Currency='GBP' and type = 'expense:expenseReport' order by expense_id desc", + "select expense_Id from alfresco where expense_Currency='GBP' and TYPE = 'expense:expenseReport' order by expense_id desc", + "select expense_Id from alfresco where expense_Currency='GBP' and TyPe = 'expense:expenseReport' order by expense_id desc"); + + int expectedNumberOfResults = 4; + + queries.forEach(query -> { + testSqlQuery(query, expectedNumberOfResults); + restClient.onResponse().assertThat().body("list.entries.entry[0][0].label", Matchers.equalToIgnoringCase("expense_Id")); + restClient.onResponse().assertThat().body("list.entries.entry[0][0].value", Matchers.equalTo("4")); + + restClient.onResponse().assertThat().body("list.entries.entry[1][0].label", Matchers.equalToIgnoringCase("expense_Id")); + restClient.onResponse().assertThat().body("list.entries.entry[1][0].value", Matchers.equalTo("3")); + + restClient.onResponse().assertThat().body("list.entries.entry[2][0].label", Matchers.equalToIgnoringCase("expense_Id")); + restClient.onResponse().assertThat().body("list.entries.entry[2][0].value", Matchers.equalTo("2")); + + restClient.onResponse().assertThat().body("list.entries.entry[3][0].label", Matchers.equalToIgnoringCase("expense_Id")); + restClient.onResponse().assertThat().body("list.entries.entry[3][0].value", Matchers.equalTo("1")); + }); + } + + @Test(groups = { TestGroup.INSIGHT_11 }) + public void fieldsInSortExpressionAreCaseInsensitive_ascendingOrder() + { + List queries = + asList("select expense_Id from alfresco where expense_Currency='GBP' and type = 'expense:expenseReport' order by expense_id asc", + "select expense_Id from alfresco where expense_Currency='GBP' and TYPE = 'expense:expenseReport' order by expense_id asc", + "select expense_Id from alfresco where expense_Currency='GBP' and TyPe = 'expense:expenseReport' order by expense_id asc", + "select expense_Id from alfresco where expense_Currency='GBP' and TYPE = 'expense:expenseReport' order by expense_id asc"); + + int expectedNumberOfResults = 4; + + queries.forEach(query -> { + testSqlQuery(query, expectedNumberOfResults); + restClient.onResponse().assertThat().body("list.entries.entry[0][0].label", Matchers.equalToIgnoringCase("expense_Id")); + restClient.onResponse().assertThat().body("list.entries.entry[0][0].value", Matchers.equalTo("1")); + + restClient.onResponse().assertThat().body("list.entries.entry[1][0].label", Matchers.equalToIgnoringCase("expense_Id")); + restClient.onResponse().assertThat().body("list.entries.entry[1][0].value", Matchers.equalTo("2")); + + restClient.onResponse().assertThat().body("list.entries.entry[2][0].label", Matchers.equalToIgnoringCase("expense_Id")); + restClient.onResponse().assertThat().body("list.entries.entry[2][0].value", Matchers.equalTo("3")); + + restClient.onResponse().assertThat().body("list.entries.entry[3][0].label", Matchers.equalToIgnoringCase("expense_Id")); + restClient.onResponse().assertThat().body("list.entries.entry[3][0].value", Matchers.equalTo("4")); + }); + } + + /** + * Internal method used for creating a sample file, with some data used within the tests. + * + * @param parentFolder the parent folder. + * @param id the file identifier. + * @param location the location (a String property) + * @param currency the currency (another String property) + * @param amount the amount + * @return the just created {@link FileModel} instance. + */ + private FileModel createAndAddNewFile(final FolderModel parentFolder, int id, String location, String currency, double amount) throws Exception + { + FileModel file = FileModel.getRandomFileModel(FileType.TEXT_PLAIN, "content #" + System.currentTimeMillis()); + file.setName("file-"+ file.getName()); + + Map properties = new HashMap<>(); + properties.put(PropertyIds.OBJECT_TYPE_ID, "D:expense:expenseReport"); + properties.put(PropertyIds.NAME, file.getName()); + properties.put("expense:id", id); + properties.put("expense:Location", location); + properties.put("expense:Currency", currency); + properties.put("expense:Approved", true); + properties.put("expense:Amount", amount); + + cmisApi.authenticateUser(testUser) + .usingSite(testSite) + .usingResource(parentFolder) + .createFile(file, properties, VersioningState.MAJOR) + .assertThat() + .existsInRepo(); + + return file; + } +} \ No newline at end of file diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustoModelGroupByFacetableTest.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustoModelGroupByFacetableTest.java index 96408bab2..3cb9752a1 100644 --- a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustoModelGroupByFacetableTest.java +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustoModelGroupByFacetableTest.java @@ -2,7 +2,7 @@ package org.alfresco.service.search.e2e.insightEngine.sql; import org.alfresco.rest.core.RestResponse; import org.alfresco.rest.search.SearchSqlRequest; -import org.alfresco.service.search.AbstractSearchServiceE2E; +import org.alfresco.service.search.e2e.AbstractSearchServiceE2E; import org.alfresco.utility.constants.UserRole; import org.alfresco.utility.model.*; import org.apache.chemistry.opencmis.commons.PropertyIds; diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustomModelChangesTest.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustomModelChangesTest.java index 8b4b02597..6c1359852 100644 --- a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustomModelChangesTest.java +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustomModelChangesTest.java @@ -12,7 +12,7 @@ import java.util.Map; import org.alfresco.rest.core.RestResponse; import org.alfresco.rest.search.SearchSqlRequest; -import org.alfresco.service.search.AbstractSearchServiceE2E; +import org.alfresco.service.search.e2e.AbstractSearchServiceE2E; import org.alfresco.utility.constants.UserRole; import org.alfresco.utility.model.FileModel; import org.alfresco.utility.model.FileType; diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustomModelTest.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustomModelTest.java index 6c905e536..5035929eb 100644 --- a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustomModelTest.java +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/CustomModelTest.java @@ -12,7 +12,7 @@ import java.util.Map; import org.alfresco.rest.core.RestResponse; import org.alfresco.rest.search.SearchSqlRequest; -import org.alfresco.service.search.AbstractSearchServiceE2E; +import org.alfresco.service.search.e2e.AbstractSearchServiceE2E; import org.alfresco.utility.constants.UserRole; import org.alfresco.utility.data.DataContent; import org.alfresco.utility.data.DataSite; diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/SelectStarTest.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/SelectStarTest.java index 5dde66b72..cbe7b4f06 100644 --- a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/SelectStarTest.java +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/SelectStarTest.java @@ -15,9 +15,7 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; -import org.alfresco.rest.core.RestResponse; -import org.alfresco.rest.search.SearchSqlRequest; -import org.alfresco.service.search.AbstractSearchServiceE2E; +import org.alfresco.service.search.e2e.AbstractSearchServiceE2E; import org.alfresco.utility.LogFactory; import org.alfresco.utility.data.DataContent; import org.alfresco.utility.data.DataSite; @@ -27,10 +25,8 @@ import org.alfresco.utility.model.FolderModel; import org.alfresco.utility.model.TestGroup; import org.apache.chemistry.opencmis.commons.PropertyIds; import org.apache.chemistry.opencmis.commons.enums.VersioningState; -import org.hamcrest.Matchers; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -231,7 +227,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 1, groups = { TestGroup.INSIGHT_11 }) - public void testTextField() throws Exception + public void testTextField() { testSqlQuery("select * from alfresco where `expense:Location` = 'london'", 2); testSqlQuery("select * from alfresco where `expense:Location` >= 'London'", 3); @@ -241,7 +237,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E testSqlQuery("select * from alfresco where `expense:Location` <> 'london' and TYPE = 'expense:expenseReport'", 3); testSqlQuery("select * from alfresco where `expense:Location` = 'Reading'", 0); testSqlQuery("select * from alfresco where `expense:Location` != 'Reading' and TYPE = 'expense:expenseReport'", 5); - testSqlQuery("select * from alfresco where `expense:Location` not in ('Paris', 'Reading') and TYPE = 'expense:expenseReport'", 4); + testSqlQuery("select * from alfresco where `expense:Location` not in ('Paris', 'Reading') and TYPE = 'expense:expenseReport'", 4); testSqlQuery("select * from alfresco where `expense:Location` not in ('Paris', 'Reading') and `expense:Location` in ('london')", 2); // Field name with _ @@ -250,7 +246,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E // TODO: Enable when fixed: Bug: Search-1457 @Test(priority = 2, groups = { TestGroup.INSIGHT_11 }, enabled = false) - public void testTextFieldNullValues() throws Exception + public void testTextFieldNullValues() { testSqlQuery("select * from alfresco where `expense:Location` = '*' and TYPE = 'expense:expenseReport'", 3); //4 or 3 testSqlQuery("select * from alfresco where `expense:Location` != '*' and TYPE = 'expense:expenseReport'", 2); //0 or 1 or 2 @@ -263,7 +259,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 3, groups = { TestGroup.INSIGHT_11 }) - public void testMLTextField() throws Exception + public void testMLTextField() { testSqlQuery("select * from alfresco where `expense:Notes` = 'London is a busy'", 2); testSqlQuery("select * from alfresco where `expense:Notes` = 'london'", 2); @@ -278,7 +274,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 4, groups = { TestGroup.INSIGHT_11 }, enabled=false) - public void testMLTextFieldNullValues() throws Exception + public void testMLTextFieldNullValues() { testSqlQuery("select * from alfresco where `expense:Notes` = '*' and TYPE = 'expense:expenseReport'", 3); //4 testSqlQuery("select * from alfresco where `expense:Notes` != '*' and TYPE = 'expense:expenseReport'", 2); //0 or 1 @@ -291,7 +287,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 5, groups = { TestGroup.INSIGHT_11 }) - public void testIntegerField() throws Exception + public void testIntegerField() { testSqlQuery("select * from alfresco where `expense:id` >= '10'", 3); testSqlQuery("select * from alfresco where `expense:id` > 10", 2); @@ -307,7 +303,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 6, groups = { TestGroup.INSIGHT_11 }, enabled = false) - public void testIntegerFieldNullValues() throws Exception + public void testIntegerFieldNullValues() { testSqlQuery("select * from alfresco where `expense:id` = '*' and TYPE = 'expense:expenseReport'", 3); testSqlQuery("select * from alfresco where `expense:id` != '*' and TYPE = 'expense:expenseReport'", 2); @@ -320,7 +316,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 7, groups = { TestGroup.INSIGHT_11 }) - public void testLongField() throws Exception + public void testLongField() { testSqlQuery("select * from alfresco where `expense:EmpNo` >= '000001'", 3); testSqlQuery("select * from alfresco where `expense:EmpNo` >=000001", 3); @@ -335,7 +331,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 8, groups = { TestGroup.INSIGHT_11 }, enabled=false) - public void testLongFieldNullValues() throws Exception + public void testLongFieldNullValues() { testSqlQuery("select * from alfresco where `expense:EmpNo` = '*' and TYPE = 'expense:expenseReport'", 3); //4 testSqlQuery("select * from alfresco where `expense:EmpNo` != '*' and TYPE = 'expense:expenseReport'", 1); //0 @@ -348,7 +344,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 9, groups = { TestGroup.INSIGHT_11 }) - public void testDoubleField() throws Exception + public void testDoubleField() { testSqlQuery("select * from alfresco where `expense:ExchangeRate` >= '12'", 2); testSqlQuery("select * from alfresco where `expense:ExchangeRate` >= 12.5", 1); @@ -362,7 +358,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 10, groups = { TestGroup.INSIGHT_11 }, enabled = false) - public void testDoubleFieldNullValues() throws Exception + public void testDoubleFieldNullValues() { testSqlQuery("select * from alfresco where `expense:ExchangeRate` = '*' and TYPE = 'expense:expenseReport'", 3); //4 testSqlQuery("select * from alfresco where `expense:ExchangeRate` != '*' and TYPE = 'expense:expenseReport'", 2); //0 @@ -371,11 +367,11 @@ public class SelectStarTest extends AbstractSearchServiceE2E testSqlQuery("select * from alfresco where `expense:ExchangeRate` not in (12.5, 100, null) and TYPE = 'expense:expenseReport'", 1); testSqlQuery("select * from alfresco where `expense:ExchangeRate` is null and TYPE = 'expense:expenseReport'", 2); - testSqlQuery("select * from alfresco where `expense:ExchangeRate` is not null and TYPE = 'expense:expenseReport'", 3); + testSqlQuery("select * from alfresco where `expense:ExchangeRate` is not null and TYPE = 'expense:expenseReport'", 3); } @Test(priority = 11, groups = { TestGroup.INSIGHT_11 }) - public void testFloatField() throws Exception + public void testFloatField() { testSqlQuery("select * from alfresco where `expense:amount` >= '60.50'", 2); testSqlQuery("select * from alfresco where `expense:amount` >= 60", 3); @@ -390,7 +386,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 12, groups = { TestGroup.INSIGHT_11 }, enabled=false) - public void testFloatFieldNullValues() throws Exception + public void testFloatFieldNullValues() { testSqlQuery("select * from alfresco where `expense:amount` >= '60.50'", 2); testSqlQuery("select * from alfresco where `expense:amount` >= 60", 3); @@ -403,7 +399,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 13, groups = { TestGroup.INSIGHT_11 }) - public void testBooleanField() throws Exception + public void testBooleanField() { testSqlQuery("select * from alfresco where `expense:Approved` = 'true'", 2); testSqlQuery("select * from alfresco where `expense:Approved` = 'false'", 2); @@ -414,7 +410,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 14, groups = { TestGroup.INSIGHT_11 }, enabled = false) - public void testBooleanFieldNullValues() throws Exception + public void testBooleanFieldNullValues() { testSqlQuery("select * from alfresco where `expense:Approved` = '*' and TYPE = 'expense:expenseReport'", 3); //4 testSqlQuery("select * from alfresco where `expense:Approved` != '*' and TYPE = 'expense:expenseReport'", 1); //0 @@ -427,7 +423,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 15, groups = { TestGroup.INSIGHT_11 }) - public void testDateField() throws Exception + public void testDateField() { testSqlQuery("select * from alfresco where `expense:ExpenseDate` <'" + DT_NOW + "'", 2); testSqlQuery("select * from alfresco where `expense:ExpenseDate` < '" + DT_NOW + "'", 2); @@ -453,7 +449,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 16, groups = { TestGroup.INSIGHT_11 }, enabled = false) - public void testDateFieldNullValues() throws Exception + public void testDateFieldNullValues() { testSqlQuery("select * from alfresco where `expense:ExpenseDate` = '*' and TYPE = 'expense:expenseReport'", 3); //4 testSqlQuery("select * from alfresco where `expense:ExpenseDate` != '*' and TYPE = 'expense:expenseReport'", 2); //0 @@ -466,7 +462,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 17, groups = { TestGroup.INSIGHT_11 }) - public void testDateTimeField() throws Exception + public void testDateTimeField() { testSqlQuery("select * from alfresco where `expense:Recorded_At` <'NOW-1MONTH' and TYPE = 'expense:expenseReport'", 2); testSqlQuery("select * from alfresco where `expense:Recorded_At` < 'NOW/DAY' and TYPE = 'expense:expenseReport'", 2); @@ -485,7 +481,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 18, groups = { TestGroup.INSIGHT_11 }, enabled = false) - public void testDateTimeFieldNullValues() throws Exception + public void testDateTimeFieldNullValues() { testSqlQuery("select * from alfresco where `expense:Recorded_At` = '*' and TYPE = 'expense:expenseReport'", 3); //4 testSqlQuery("select * from alfresco where `expense:Recorded_At` != '*' and TYPE = 'expense:expenseReport'", 1); //0 @@ -499,7 +495,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E // TODO: Search-1477: Enable, Uncomment Tests when bug is fixed @Test(priority = 19, groups = { TestGroup.INSIGHT_11 }, enabled = false) - public void testVirtualTimeDimensions() throws Exception + public void testVirtualTimeDimensions() { testSqlQuery("select * from alfresco where TYPE = 'expense:expenseReport' order by cm_created desc", 5); @@ -523,7 +519,7 @@ public class SelectStarTest extends AbstractSearchServiceE2E } @Test(priority = 20, groups = { TestGroup.INSIGHT_11 }) - public void testFieldNameWithUnderscore() throws Exception + public void testFieldNameWithUnderscore() { // Field name with _: in where clause testSqlQuery("select * from alfresco where `expense:CostCentre__1` = '750' AND TYPE = 'expense:expenseReport' order by cm_created desc", 2); @@ -540,23 +536,4 @@ public class SelectStarTest extends AbstractSearchServiceE2E // + " group by expense_Recorded_At_year" // + " order by expense_Recorded_At desc", 5); } - - private RestResponse testSqlQuery(String sql, Integer entriesCount) throws Exception - { - SearchSqlRequest sqlRequest = new SearchSqlRequest(); - sqlRequest.setSql(sql); - - RestResponse response = restClient.authenticateUser(testUser).withSearchSqlAPI().searchSql(sqlRequest); - - restClient.assertStatusCodeIs(HttpStatus.OK); - - if (entriesCount != null) - { - restClient.onResponse().assertThat().body("list.pagination.count", Matchers.equalTo(entriesCount)); - // To check the label: Use the json path in body: list.entries.entry[0][0].label - // To check the value: Use the json path in body: list.entries.entry[0][0].value - } - - return response; - } } diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/TimeSeriesAggrTest.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/TimeSeriesAggrTest.java new file mode 100644 index 000000000..0b2459305 --- /dev/null +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/insightEngine/sql/TimeSeriesAggrTest.java @@ -0,0 +1,672 @@ +/* + * Copyright 2018 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.insightEngine.sql; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import javax.json.Json; +import javax.json.JsonObject; + +import org.alfresco.dataprep.SiteService.Visibility; +import org.alfresco.rest.core.RestResponse; +import org.alfresco.rest.search.SearchSqlRequest; +import org.alfresco.service.search.e2e.AbstractSearchServiceE2E; +import org.alfresco.utility.constants.UserRole; +import org.alfresco.utility.data.DataContent; +import org.alfresco.utility.data.DataSite; +import org.alfresco.utility.data.RandomData; +import org.alfresco.utility.model.FileModel; +import org.alfresco.utility.model.FileType; +import org.alfresco.utility.model.FolderModel; +import org.alfresco.utility.model.SiteModel; +import org.alfresco.utility.model.TestGroup; +import org.alfresco.utility.model.UserModel; +import org.alfresco.utility.report.Bug; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.enums.VersioningState; +import org.hamcrest.Matchers; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * Purpose of this TestClass is to test that the TimeSeries Aggregation works with/out Nulls and when values are not available + * + * @author meenal bhave + */ + +public class TimeSeriesAggrTest extends AbstractSearchServiceE2E +{ + @Autowired + protected DataSite dataSite; + + @Autowired + protected DataContent dataContent; + + protected SiteModel testSite; + + private UserModel testExpenseUser1, testExpenseAdmin; + + private FolderModel testFolderUser1, testFolderAdmin; + + private FileModel expense1, expense2, expense3, expense4; + + private Long uniqueRef; + + /** + * sql query to retrieve aggregated results based on Virtual Time Dimension _day + */ + private static final String VIRTUAL_TIME_DIMENTION_DAY = "" + + "select " + + "finance_CreatedAt_day, " + + "count(*) as ExpensesCount, " + + "sum(finance_amount) as TotalExpenses, avg(finance_amount) as AvgExpenses, " + + "min(finance_amount) as MinExpenses, max(finance_amount) as MaxExpenses " + + "from alfresco " + + "group by finance_CreatedAt_day"; + + /** + * sql query to retrieve aggregated results based on Virtual Time Dimension _month + */ + private static final String VIRTUAL_TIME_DIMENTION_MONTH = "" + + "select " + + "finance_CreatedAt_month, " + + "count(*) as ExpensesCount, " + + "sum(finance_amount) as TotalExpenses, avg(finance_amount) as AvgExpenses, " + + "min(finance_amount) as MinExpenses, max(finance_amount) as MaxExpenses " + + "from alfresco " + + "group by finance_CreatedAt_month"; + + /** + * sql query to retrieve aggregated results based on Virtual Time Dimension _year + * Includes order by desc: order by virtual time dimension _year + */ + private static final String VIRTUAL_TIME_DIMENTION_YEAR = "" + + "select " + + "finance_CreatedAt_year, " + + "count(*) as ExpensesCount, " + + "sum(finance_amount) as TotalExpenses, avg(finance_amount) as AvgExpenses, " + + "min(finance_amount) as MinExpenses, max(finance_amount) as MaxExpenses " + + "from alfresco " + + "group by finance_CreatedAt_Year " + + "order by finance_CreatedAt_YEAR desc"; + + /** + * String that adds having clause based on min amount to the query + */ + private static final String HAVING_MIN_AMOUNT = " having min(finance_amount) > 0"; + + /** + * String that adds having clause based on count to the query + */ + private static final String HAVING_COUNT = " having count(*) >= 1"; + + /** + * String that adds order by desc clause to the query + */ + private static final String ORDER_BY_DESC = " order by finance_CreatedAt_month desc"; + + /** + * LocalDateTime that represents date 1 month ago + */ + private static final LocalDateTime dateLastMonth = LocalDateTime.now().minusMonths(1); + + @BeforeClass(alwaysRun = true) + public void setupEnvironment() throws Exception + { + serverHealth.assertServerIsOnline(); + + // Create test users + testExpenseUser1 = dataUser.createRandomTestUser(); + testExpenseAdmin = dataUser.createRandomTestUser(); + + // Create private test site as testExpenseUser1 and add testExpenseAdmin + testSite = new SiteModel(RandomData.getRandomName("SiteFinance1")); + testSite.setVisibility(Visibility.PRIVATE); + + testSite = dataSite.usingUser(testExpenseUser1).createSite(testSite); + + dataUser.addUserToSite(testExpenseAdmin, testSite, UserRole.SiteContributor); + + // Create test folders for users + testFolderUser1 = dataContent.usingSite(testSite).usingUser(testExpenseUser1).createFolder(); + testFolderAdmin = dataContent.usingSite(testSite).usingUser(testExpenseAdmin).createFolder(); + + // Set Node Permissions for testFolder2, to deny access to testExpenseUser1 + JsonObject userPermission = Json + .createObjectBuilder() + .add("permissions", + Json.createObjectBuilder() + .add("isInheritanceEnabled", false) + .add("locallySet", + Json.createObjectBuilder() + .add("authorityId", testExpenseUser1.getUsername()) + .add("name", "SiteManager") + .add("accessStatus", "DENIED") + )).build(); + + String putBody = userPermission.toString(); + + restClient.authenticateUser(testExpenseAdmin).withCoreAPI().usingNode(testFolderAdmin).updateNode(putBody); + + uniqueRef = System.currentTimeMillis(); + + createTestData(); + } + + private void createTestData() throws Exception + { + // testExpenseUser1 has 2 expenses, testExpenseAdmin has 2 expense, userAdmin can see all expenses + + // Expense1 for testExpenseUser1 dated today: Amount 100 + expense1 = FileModel.getRandomFileModel(FileType.TEXT_PLAIN, "custom content"); + expense1.setName("ex-"+ expense1.getName()); + Map properties = new HashMap(); + properties.put(PropertyIds.OBJECT_TYPE_ID, "D:finance:Expense"); + properties.put(PropertyIds.NAME, expense1.getName()); + properties.put("finance:No", uniqueRef); + properties.put("finance:Emp", testExpenseUser1.getUsername()); + properties.put("finance:amount", 100); + properties.put("finance:CreatedAt", Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC))); + properties.put("finance:Location", "Reading"); + + cmisApi.authenticateUser(testExpenseUser1).usingSite(testSite).usingResource(testFolderUser1) + .createFile(expense1, properties, VersioningState.MAJOR).assertThat().existsInRepo(); + + // Expense2 for testExpenseUser1 dated : Amount 50 + expense2 = FileModel.getRandomFileModel(FileType.TEXT_PLAIN, "custom content"); + expense2.setName("ex-"+ expense2.getName()); + properties = new HashMap(); + properties.put(PropertyIds.OBJECT_TYPE_ID, "D:finance:Expense"); + properties.put(PropertyIds.NAME, expense2.getName()); + properties.put("finance:No", uniqueRef+1); + properties.put("finance:Emp", testExpenseUser1.getUsername()); + properties.put("finance:amount", 50); + properties.put("finance:CreatedAt", Date.from(dateLastMonth.toInstant(ZoneOffset.UTC))); + properties.put("finance:Location", "London"); + + cmisApi.authenticateUser(testExpenseUser1).usingSite(testSite).usingResource(testFolderUser1) + .createFile(expense2, properties, VersioningState.MAJOR).assertThat().existsInRepo(); + + // Expense1 for testExpenseAdmin dated : Amount 400 + expense3 = FileModel.getRandomFileModel(FileType.TEXT_PLAIN, "custom content"); + expense3.setName("ex-"+ expense3.getName()); + properties = new HashMap(); + properties.put(PropertyIds.OBJECT_TYPE_ID, "D:finance:Expense"); + properties.put(PropertyIds.NAME, expense3.getName()); + properties.put("finance:No", uniqueRef+3); + properties.put("finance:Emp", testExpenseAdmin.getUsername()); + properties.put("finance:amount", 400); + properties.put("finance:CreatedAt", Date.from(dateLastMonth.toInstant(ZoneOffset.UTC))); + properties.put("finance:Location", "London"); + + cmisApi.authenticateUser(testExpenseAdmin).usingSite(testSite).usingResource(testFolderAdmin) + .createFile(expense3, properties, VersioningState.MAJOR).assertThat().existsInRepo(); + + // Expense2 for testExpenseAdmin dated : Amount Not specified / Null + expense4 = FileModel.getRandomFileModel(FileType.TEXT_PLAIN, "custom content"); + expense4.setName("ex-"+ expense4.getName()); + properties = new HashMap(); + properties.put(PropertyIds.OBJECT_TYPE_ID, "D:finance:Expense"); + properties.put(PropertyIds.NAME, expense4.getName()); + properties.put("finance:No", uniqueRef+4); + properties.put("finance:Emp", testExpenseAdmin.getUsername()); + properties.put("finance:CreatedAt", Date.from(dateLastMonth.plusDays(1).toInstant(ZoneOffset.UTC))); + properties.put("finance:Location", "Maidenhead"); + + cmisApi.authenticateUser(testExpenseAdmin).usingSite(testSite).usingResource(testFolderAdmin) + .createFile(expense4, properties, VersioningState.MAJOR).assertThat().existsInRepo(); + + // Wait for the content to be indexed + waitForIndexing(expense4.getName(), true); + } + + /** + * Test that Virtual time series aggregation works for _day + * Format appears as yyyy + * Data shows results for [Current full day - 1 month] as default + * Values are correctly aggregated for _year dimension + * Order is correct + */ + @Test(priority = 1, groups = { TestGroup.INSIGHT_10 }) + public void testBasicTimeSeriesAggrDay() throws Exception + { + // Select Data for TimeSeriesAggr: json format + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(VIRTUAL_TIME_DIMENTION_DAY); + sqlRequest.setFormat("json"); + + RestResponse response = + restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + restClient.assertStatusCodeIs(HttpStatus.OK); + + // Check that response includes the details for expense dated + int noOfDays = LocalDateTime.now().getDayOfYear() - dateLastMonth.getDayOfYear(); + response.assertThat().body("list.pagination.count", Matchers.equalTo(noOfDays + 1)); + + // Execute in solr format + sqlRequest.setFormat("solr"); + + response = restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + restClient.assertStatusCodeIs(HttpStatus.OK); + + response.assertThat().body("result-set.docs", Matchers.notNullValue()); + + // Check the results are in ascending order of date, starting with + restClient.onResponse().assertThat().body("result-set.docs[0].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + + // last date available in the results set is today + restClient.onResponse().assertThat().body("result-set.docs[" + noOfDays + "].finance_CreatedAt_day", Matchers + .equalTo(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + + } + + /** + * Test that Virtual time series aggregation works for _day + * Format appears as yyyy + * Data shows results for [Current full day - 1 month] as default + * Values are correctly aggregated for _year dimension + * Order is correct + */ + @Test(priority = 2, groups = { TestGroup.INSIGHT_10 }) + public void testBasicTimeSeriesAggrDayWithHavingClause() throws Exception + { + // Select Data for TimeSeriesAggr: json format + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(VIRTUAL_TIME_DIMENTION_DAY + HAVING_MIN_AMOUNT); + sqlRequest.setFormat("json"); + + RestResponse response = + restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + + // Check Count + response.assertThat().body("list.pagination.count", Matchers.equalTo(2)); + + // Execute in solr format + sqlRequest.setFormat("solr"); + + response = restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + response.assertThat().body("result-set.docs", Matchers.notNullValue()); + + restClient.onResponse().assertThat().body("result-set.docs[0].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[0].ExpensesCount", Matchers.equalTo(1)); + restClient.onResponse().assertThat().body("result-set.docs[0].MinExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].MaxExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].TotalExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].AvgExpenses", Matchers.equalTo(50)); + + // Check that response includes the details for expense dated + restClient.onResponse().assertThat().body("result-set.docs[1].finance_CreatedAt_day", Matchers + .equalTo(LocalDateTime.now().minusMonths(0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[1].ExpensesCount", Matchers.equalTo(1)); + restClient.onResponse().assertThat().body("result-set.docs[1].MinExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[1].MaxExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[1].TotalExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[1].AvgExpenses", Matchers.equalTo(100)); + } + + /** + * Test that Virtual time series aggregation works for _month + * Format appears as yyyy-mm + * Data shows results for [Current month - 24 months] as default + * Values are correctly aggregated for _month dimension + * Order is correct + */ + @Test(priority = 3, groups = { TestGroup.INSIGHT_10 }) + public void testBasicTimeSeriesAggrMonth() throws Exception + { + // Select Data for TimeSeriesAggr: json format + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(VIRTUAL_TIME_DIMENTION_MONTH + ORDER_BY_DESC); + sqlRequest.setFormat("json"); + + RestResponse response = + restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + + // Check Count for Month Aggregation is 25: Current month minus 24 months + response.assertThat().body("list.pagination.count", Matchers.equalTo(25)); + + // Execute in solr format + sqlRequest.setFormat("solr"); + + response = restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + response.assertThat().body("result-set.docs", Matchers.notNullValue()); + + // Check that response includes the details for expense dated : Order By desc + restClient.onResponse().assertThat().body("result-set.docs[0].finance_CreatedAt_month", Matchers + .equalTo(LocalDateTime.now().minusMonths(0).format(DateTimeFormatter.ofPattern("yyyy-MM")))); + restClient.onResponse().assertThat().body("result-set.docs[0].ExpensesCount", Matchers.equalTo(1)); + restClient.onResponse().assertThat().body("result-set.docs[0].MinExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[0].MaxExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[0].TotalExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[0].AvgExpenses", Matchers.equalTo(100)); + + // Check that response includes the details for expense dated + restClient.onResponse().assertThat().body("result-set.docs[1].finance_CreatedAt_month", Matchers + .equalTo(dateLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM")))); + restClient.onResponse().assertThat().body("result-set.docs[1].ExpensesCount", Matchers.equalTo(1)); + restClient.onResponse().assertThat().body("result-set.docs[1].MinExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[1].MaxExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[1].TotalExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[1].AvgExpenses", Matchers.equalTo(50)); + } + + /** + * Test that Virtual time series aggregation works for _year + * Format appears as yyyy + * Data shows results for [Current year - 5 years] as default + * Values are correctly aggregated for _year dimension + * Order is correct + */ + @Test(priority = 4, groups = { TestGroup.INSIGHT_10 }) + public void testBasicTimeSeriesAggrYear() throws Exception + { + // Select Data for TimeSeriesAggr: json format + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(VIRTUAL_TIME_DIMENTION_YEAR); + sqlRequest.setFormat("json"); + + RestResponse response = + restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + + // Check Count for Year Aggregation is 25: Current year minus 5 years + response.assertThat().body("list.pagination.count", Matchers.equalTo(6)); + + // Execute in solr format + sqlRequest.setFormat("solr"); + + response = restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + response.assertThat().body("result-set.docs", Matchers.notNullValue()); + + // Check that response includes the details for expense dated : Order By desc + restClient.onResponse().assertThat().body("result-set.docs[0].finance_CreatedAt_year", Matchers + .equalTo(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy")))); + restClient.onResponse().assertThat().body("result-set.docs[0].ExpensesCount", Matchers.equalTo(2)); + restClient.onResponse().assertThat().body("result-set.docs[0].MinExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].MaxExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[0].TotalExpenses", Matchers.equalTo(150)); + restClient.onResponse().assertThat().body("result-set.docs[0].AvgExpenses", Matchers.equalTo(75)); + + // Check that response includes the details for expense dated + restClient.onResponse().assertThat().body("result-set.docs[1].finance_CreatedAt_year", Matchers + .equalTo(LocalDateTime.now().minusYears(1).format(DateTimeFormatter.ofPattern("yyyy")))); + restClient.onResponse().assertThat().body("result-set.docs[1].ExpensesCount", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].MinExpenses", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].MaxExpenses", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].TotalExpenses", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].AvgExpenses", Matchers.equalTo(0)); + } + + /** + * Test that Aggregation Values appear as 0 when not available for a time dimension + */ + @Test(priority = 5, groups = { TestGroup.INSIGHT_10 }) + public void testNoValuesAggregateAsZero() throws Exception + { + // Select Data for TimeSeriesAggr: json format + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(VIRTUAL_TIME_DIMENTION_DAY); + sqlRequest.setFormat("json"); + + RestResponse response = + restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + + // Check Count + response.assertThat().body("list.pagination.count", Matchers.greaterThanOrEqualTo(28)); + + // Execute in solr format + sqlRequest.setFormat("solr"); + + response = restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + response.assertThat().body("result-set.docs", Matchers.notNullValue()); + + // Check that response includes the details for expense dated + restClient.onResponse().assertThat().body("result-set.docs[0].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[0].ExpensesCount", Matchers.equalTo(1)); + restClient.onResponse().assertThat().body("result-set.docs[0].MinExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].MaxExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].TotalExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].AvgExpenses", Matchers.equalTo(50)); + + // Check that response includes expense dated : Aggregations = 0, when ! specified + restClient.onResponse().assertThat().body("result-set.docs[1].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[1].ExpensesCount", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].MinExpenses", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].MaxExpenses", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].TotalExpenses", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].AvgExpenses", Matchers.equalTo(0)); + } + + /** + * Test that Aggregation Values appear as 0 when null for any time dimension + */ + @Test(priority = 6, groups = { TestGroup.INSIGHT_10 }) + public void testNullValuesAggregateAsZero() throws Exception + { + // Select Data for TimeSeriesAggr: json format + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(VIRTUAL_TIME_DIMENTION_DAY); + sqlRequest.setFormat("json"); + + RestResponse response = + restClient.authenticateUser(testExpenseAdmin).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + + // Check Count + response.assertThat().body("list.pagination.count", Matchers.greaterThanOrEqualTo(29)); + + // Execute in solr format + sqlRequest.setFormat("solr"); + + response = restClient.authenticateUser(testExpenseUser1).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + response.assertThat().body("result-set.docs", Matchers.notNullValue()); + + // Check that response includes the details for expense dated + restClient.onResponse().assertThat().body("result-set.docs[0].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[0].ExpensesCount", Matchers.equalTo(1)); + restClient.onResponse().assertThat().body("result-set.docs[0].MinExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].MaxExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].TotalExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].AvgExpenses", Matchers.equalTo(50)); + + // Check that response includes expense dated : Aggregations = 0, when ! specified + restClient.onResponse().assertThat().body("result-set.docs[1].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[1].ExpensesCount", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].MinExpenses", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].MaxExpenses", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].TotalExpenses", Matchers.equalTo(0)); + restClient.onResponse().assertThat().body("result-set.docs[1].AvgExpenses", Matchers.equalTo(0)); + } + + /** + * Test that aggregation produces correct results in-spite of changing null to zeroes + */ + @Test(priority = 7, groups = { TestGroup.INSIGHT_10 }) + public void testAggregationsInclNulls() throws Exception + { + // Select Data for TimeSeriesAggr: json format + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(VIRTUAL_TIME_DIMENTION_MONTH + HAVING_COUNT); + sqlRequest.setFormat("solr"); + + // User2 can see aggr results for All 4 Content + RestResponse response = + restClient.authenticateUser(testExpenseAdmin).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + response.assertThat().body("result-set.docs", Matchers.notNullValue()); + + restClient.onResponse().assertThat().body("result-set.docs[0].finance_CreatedAt_month", Matchers + .equalTo(dateLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM")))); + restClient.onResponse().assertThat().body("result-set.docs[0].ExpensesCount", Matchers.equalTo(3)); + restClient.onResponse().assertThat().body("result-set.docs[0].MinExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].MaxExpenses", Matchers.equalTo(400)); + restClient.onResponse().assertThat().body("result-set.docs[0].TotalExpenses", Matchers.equalTo(450)); + restClient.onResponse().assertThat().body("result-set.docs[0].AvgExpenses", Matchers.equalTo(225)); + + restClient.onResponse().assertThat().body("result-set.docs[1].finance_CreatedAt_month", Matchers + .equalTo(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM")))); + restClient.onResponse().assertThat().body("result-set.docs[1].ExpensesCount", Matchers.equalTo(1)); + restClient.onResponse().assertThat().body("result-set.docs[1].MinExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[1].MaxExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[1].TotalExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[1].AvgExpenses", Matchers.equalTo(100)); + } + + /** + * Test that aggregation produces correct results for admin, aggregating data from different users + * Aggregated Values appear as 0 when actual values include a mix of null and non nul values + * Results don't show 0 entries: when having clause filters them out + */ + @Bug(id = "Search-927", status=Bug.Status.OPENED) + @Test(priority = 8, groups = { TestGroup.INSIGHT_10 }) + public void testAggregationsForOtherUser() throws Exception + { + String timeSeriesSqlDayAdmin = "" + + "select " + + "finance_CreatedAt_day, " + + "count(*) as ExpensesCount, " + + "sum(finance_amount) as TotalExpenses, avg(finance_amount) as AvgExpenses, " + + "min(finance_amount) as MinExpenses, max(finance_amount) as MaxExpenses " + + "from alfresco " + + "where SITE = '" + testSite.getId() + "'" + + "group by finance_CreatedAt_day"; + + // Select Data for TimeSeriesAggr: json format + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(timeSeriesSqlDayAdmin + HAVING_COUNT); + sqlRequest.setFormat("solr"); + + // admin can see aggregation results for All 4 Content added to the Site + RestResponse response = + restClient.authenticateUser(dataUser.getAdminUser()).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + response.assertThat().body("result-set.docs", Matchers.notNullValue()); + + restClient.onResponse().assertThat().body("result-set.docs[0].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[0].ExpensesCount", Matchers.equalTo(2)); + restClient.onResponse().assertThat().body("result-set.docs[0].MinExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[0].MaxExpenses", Matchers.equalTo(400)); + restClient.onResponse().assertThat().body("result-set.docs[0].TotalExpenses", Matchers.equalTo(450)); + restClient.onResponse().assertThat().body("result-set.docs[0].AvgExpenses", Matchers.equalTo(225)); + + restClient.onResponse().assertThat().body("result-set.docs[1].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[1].ExpensesCount", Matchers.equalTo(1)); + + // TODO: Search-927: NaN: Uncomment the following steps when Search-927 is resolved + // restClient.onResponse().assertThat().body("result-set.docs[1].MinExpenses", Matchers.equalTo(00)); + // restClient.onResponse().assertThat().body("result-set.docs[1].MaxExpenses", Matchers.equalTo(00)); + + restClient.onResponse().assertThat().body("result-set.docs[1].TotalExpenses", Matchers.equalTo(00)); + restClient.onResponse().assertThat().body("result-set.docs[1].AvgExpenses", Matchers.equalTo(0)); + + restClient.onResponse().assertThat().body("result-set.docs[2].finance_CreatedAt_day", Matchers + .equalTo(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[2].ExpensesCount", Matchers.equalTo(1)); + restClient.onResponse().assertThat().body("result-set.docs[2].MinExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[2].MaxExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[2].TotalExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[2].AvgExpenses", Matchers.equalTo(100)); + } + + /** + * Test that aggregation produces correct results for admin, aggregating data from different users + * Aggregated Values appear as 0 when actual values include a mix of null and non nul values + * Results show 0 entries: when having clause does not filter them out + * Order by desc shows the same results as above query in a desc order + */ + @Bug(id = "Search-927", status=Bug.Status.OPENED) + @Test(priority = 9, groups = { TestGroup.INSIGHT_10 }) + public void testAggregationsForOtherUserOrderByDesc() throws Exception + { + String timeSeriesSqlDayAdmin = "" + + "select " + + "finance_CreatedAt_day, " + + "count(*) as ExpensesCount, " + + "sum(finance_amount) as TotalExpenses, avg(finance_amount) as AvgExpenses, " + + "min(finance_amount) as MinExpenses, max(finance_amount) as MaxExpenses " + + "from alfresco " + + "where SITE = '" + testSite.getId() + "'" + + "group by finance_CreatedAt_day " + + "having count(*) >= 1 " + + "order by finance_CreatedAt_day desc"; + + // Select Data for TimeSeriesAggr: json format + SearchSqlRequest sqlRequest = new SearchSqlRequest(); + sqlRequest.setSql(timeSeriesSqlDayAdmin); + sqlRequest.setFormat("solr"); + + // admin can see aggregation results for All 4 Content added to the Site + RestResponse response = + restClient.authenticateUser(dataUser.getAdminUser()).withSearchSqlAPI().searchSql(sqlRequest); + + restClient.assertStatusCodeIs(HttpStatus.OK); + response.assertThat().body("result-set.docs", Matchers.notNullValue()); + + restClient.onResponse().assertThat().body("result-set.docs[0].finance_CreatedAt_day", Matchers + .equalTo(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[0].ExpensesCount", Matchers.equalTo(1)); + restClient.onResponse().assertThat().body("result-set.docs[0].MinExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[0].MaxExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[0].TotalExpenses", Matchers.equalTo(100)); + restClient.onResponse().assertThat().body("result-set.docs[0].AvgExpenses", Matchers.equalTo(100)); + + restClient.onResponse().assertThat().body("result-set.docs[1].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[1].ExpensesCount", Matchers.equalTo(1)); + + // TODO: Search-927: NaN: Uncomment the following steps when Search-927 is resolved + // restClient.onResponse().assertThat().body("result-set.docs[1].MinExpenses", Matchers.equalTo(00)); + // restClient.onResponse().assertThat().body("result-set.docs[1].MaxExpenses", Matchers.equalTo(00)); + + restClient.onResponse().assertThat().body("result-set.docs[1].TotalExpenses", Matchers.equalTo(00)); + restClient.onResponse().assertThat().body("result-set.docs[1].AvgExpenses", Matchers.equalTo(0)); + + restClient.onResponse().assertThat().body("result-set.docs[2].finance_CreatedAt_day", Matchers + .equalTo(dateLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))); + restClient.onResponse().assertThat().body("result-set.docs[2].ExpensesCount", Matchers.equalTo(2)); + restClient.onResponse().assertThat().body("result-set.docs[2].MinExpenses", Matchers.equalTo(50)); + restClient.onResponse().assertThat().body("result-set.docs[2].MaxExpenses", Matchers.equalTo(400)); + restClient.onResponse().assertThat().body("result-set.docs[2].TotalExpenses", Matchers.equalTo(450)); + restClient.onResponse().assertThat().body("result-set.docs[2].AvgExpenses", Matchers.equalTo(225)); + } +} diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/searchservices/SearchWithCustomModelTest.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/searchservices/SearchWithCustomModelTest.java index f5e355e87..3f40736c8 100644 --- a/e2e-test/src/test/java/org/alfresco/service/search/e2e/searchservices/SearchWithCustomModelTest.java +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/searchservices/SearchWithCustomModelTest.java @@ -11,7 +11,7 @@ import java.util.HashMap; import java.util.Map; import org.alfresco.rest.search.SearchResponse; -import org.alfresco.service.search.AbstractSearchServiceE2E; +import org.alfresco.service.search.e2e.AbstractSearchServiceE2E; import org.alfresco.utility.constants.UserRole; import org.alfresco.utility.data.DataContent; import org.alfresco.utility.data.DataSite; @@ -72,7 +72,7 @@ public class SearchWithCustomModelTest extends AbstractSearchServiceE2E // Location value is set to London cmisApi.authenticateUser(testUser).usingResource(expenseLondon).addSecondaryTypes("P:finance:ParkEx").assertThat() .secondaryTypeIsAvailable("P:finance:ParkEx"); - cmisApi.authenticateUser(testUser).usingResource(expenseLondon).updateProperty("finance:Location", "London"); + cmisApi.authenticateUser(testUser).usingResource(expenseLondon).updateProperty("finance:ParkingLocation", "London"); expenseParis = FileModel.getRandomFileModel(FileType.TEXT_PLAIN, "Expense"); expenseParis.setName("fin2-" + expenseParis.getName()); @@ -92,7 +92,7 @@ public class SearchWithCustomModelTest extends AbstractSearchServiceE2E // Location value is set to Paris cmisApi.authenticateUser(testUser).usingResource(expenseParis).addSecondaryTypes("P:finance:ParkEx").assertThat() .secondaryTypeIsAvailable("P:finance:ParkEx"); - cmisApi.authenticateUser(testUser).usingResource(expenseParis).updateProperty("finance:Location", "Paris"); + cmisApi.authenticateUser(testUser).usingResource(expenseParis).updateProperty("finance:ParkingLocation", "Paris"); expenseNoLocation = FileModel.getRandomFileModel(FileType.TEXT_PLAIN, "receipt"); expenseNoLocation.setName("fin3-" + expenseNoLocation.getName()); @@ -122,22 +122,22 @@ public class SearchWithCustomModelTest extends AbstractSearchServiceE2E public void testRangeQueryTextField() throws Exception { // Search Range Query - SearchResponse response = queryAsUser(testUser, "finance_Location:[* TO London]"); + SearchResponse response = queryAsUser(testUser, "finance_ParkingLocation:[* TO London]"); restClient.assertStatusCodeIs(HttpStatus.OK); // Content where Location = London is returned, If property is not set, its ignored. Assert.assertEquals(response.getPagination().getCount(), 1); - response = queryAsUser(testUser, "finance_Location:[London TO *]"); + response = queryAsUser(testUser, "finance_ParkingLocation:[London TO *]"); restClient.assertStatusCodeIs(HttpStatus.OK); // Content where Location = London, Paris is returned, If property is not set, its ignored. Assert.assertEquals(response.getPagination().getCount(), 2); - response = queryAsUser(testUser, "finance_Location:[London To Paris]"); + response = queryAsUser(testUser, "finance_ParkingLocation:[London To Paris]"); restClient.assertStatusCodeIs(HttpStatus.OK); Assert.assertEquals(response.getPagination().getCount(), 2); - response = queryAsUser(testUser, "finance_Location:[* To *]"); + response = queryAsUser(testUser, "finance_ParkingLocation:[* To *]"); restClient.assertStatusCodeIs(HttpStatus.OK); Assert.assertEquals(response.getPagination().getCount(), 2); } diff --git a/e2e-test/src/test/java/org/alfresco/service/search/e2e/searchservices/tracker/CascadingTrackerIntegrationTest.java b/e2e-test/src/test/java/org/alfresco/service/search/e2e/searchservices/tracker/CascadingTrackerIntegrationTest.java index 59e9b8b78..3a6b8247b 100644 --- a/e2e-test/src/test/java/org/alfresco/service/search/e2e/searchservices/tracker/CascadingTrackerIntegrationTest.java +++ b/e2e-test/src/test/java/org/alfresco/service/search/e2e/searchservices/tracker/CascadingTrackerIntegrationTest.java @@ -9,7 +9,7 @@ package org.alfresco.service.search.e2e.searchservices.tracker; import java.util.HashMap; import java.util.Map; -import org.alfresco.service.search.AbstractSearchServiceE2E; +import org.alfresco.service.search.e2e.AbstractSearchServiceE2E; import org.alfresco.utility.data.DataContent; import org.alfresco.utility.model.ContentModel; import org.alfresco.utility.model.FileModel; diff --git a/e2e-test/src/test/java/org/alfresco/service/search/unit/SetupTest.java b/e2e-test/src/test/java/org/alfresco/service/search/unit/SetupTest.java index 064f054f2..54cb99ff6 100644 --- a/e2e-test/src/test/java/org/alfresco/service/search/unit/SetupTest.java +++ b/e2e-test/src/test/java/org/alfresco/service/search/unit/SetupTest.java @@ -15,7 +15,7 @@ import org.alfresco.dataprep.SiteService.Visibility; import org.alfresco.rest.core.RestResponse; import org.alfresco.rest.search.SearchSqlJDBCRequest; import org.alfresco.rest.search.SearchSqlRequest; -import org.alfresco.service.search.AbstractSearchServiceE2E; +import org.alfresco.service.search.e2e.AbstractSearchServiceE2E; import org.alfresco.utility.constants.UserRole; import org.alfresco.utility.data.DataContent; import org.alfresco.utility.data.DataSite; @@ -123,9 +123,21 @@ public class SetupTest extends AbstractSearchServiceE2E @Test(priority = 4, groups = { TestGroup.SANITY, TestGroup.INSIGHT_10 }) public void testSQLAPICanBeUsed() throws Exception { - // Select distinct site: json format + FileModel customFile = FileModel.getRandomFileModel(FileType.TEXT_PLAIN, "searchContent-finance2"); + Map properties = new HashMap(); + properties.put(PropertyIds.OBJECT_TYPE_ID, "D:finance:Receipt"); + properties.put(PropertyIds.NAME, customFile.getName()); + properties.put("finance:ReceiptNo", 2); + properties.put("finance:ReceiptValue", 50); + + cmisApi.authenticateUser(testUser).usingSite(testSite) + .usingResource(testFolder) + .createFile(customFile, properties, VersioningState.MAJOR) + .assertThat().existsInRepo(); + + // Select distinct site: json format SearchSqlRequest sqlRequest = new SearchSqlRequest(); - sqlRequest.setSql("select cm_name from alfresco where finance_ReceiptValue > 0"); + sqlRequest.setSql("select cm_name from alfresco where TYPE = 'financeReceipt'"); sqlRequest.setLimit(10); RestResponse response = restClient.authenticateUser(testUser).withSearchSqlAPI().searchSql(sqlRequest);