content: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   * <p>
   * http://www.apache.org/licenses/LICENSE-2.0
   * <p>
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.atlas.discovery;
  
  import org.apache.atlas.ApplicationProperties;
  import org.apache.atlas.AtlasClient;
  import org.apache.atlas.BasicTestSetup;
  import org.apache.atlas.SortOrder;
  import org.apache.atlas.TestModules;
  import org.apache.atlas.exception.AtlasBaseException;
  import org.apache.atlas.model.discovery.AtlasAggregationEntry;
  import org.apache.atlas.model.discovery.AtlasQuickSearchResult;
  import org.apache.atlas.model.discovery.AtlasSearchResult;
  import org.apache.atlas.model.discovery.QuickSearchParameters;
  import org.apache.atlas.model.discovery.RelationshipSearchParameters;
  import org.apache.atlas.model.discovery.SearchParameters;
  import org.apache.atlas.model.instance.AtlasClassification;
  import org.apache.atlas.model.instance.AtlasEntity;
  import org.apache.atlas.model.instance.AtlasEntityHeader;
  import org.apache.atlas.model.instance.EntityMutationResponse;
  import org.apache.atlas.repository.graph.AtlasGraphProvider;
  import org.apache.atlas.repository.store.graph.v2.AtlasEntityStream;
  import org.apache.commons.collections.CollectionUtils;
  import org.apache.commons.lang.StringUtils;
  import org.testng.annotations.AfterClass;
  import org.testng.annotations.BeforeClass;
  import org.testng.annotations.DataProvider;
  import org.testng.annotations.Guice;
  import org.testng.annotations.Test;
  
  import javax.inject.Inject;
  
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  
  import static org.apache.atlas.model.discovery.SearchParameters.ALL_CLASSIFICATION_TYPES;
  import static org.apache.atlas.model.discovery.SearchParameters.ALL_ENTITY_TYPES;
  import static org.apache.atlas.model.discovery.SearchParameters.NO_CLASSIFICATIONS;
  import static org.apache.atlas.model.discovery.SearchParameters.Operator;
  import static org.testng.Assert.assertEquals;
  import static org.testng.Assert.assertNotNull;
  import static org.testng.Assert.assertNull;
  import static org.testng.Assert.assertSame;
  import static org.testng.Assert.assertTrue;
  
  @Guice(modules = TestModules.TestOnlyModule.class)
  public class AtlasDiscoveryServiceTest extends BasicTestSetup {
      String salesFactGuid;
      String spChar1 = "default.test_dot_name";
      String spChar2 = "default.test_dot_name@db.test_db";
      String spChar3  = "default.test_dot_name_12.col1@db1";
      String spChar4  = "default_.test_dot_name";
      String spChar5  = "default.test_colon_name:test_db";
      String spChar6  = "default.test_colon_name:-test_db";
      String spChar7  = "crn:def:default:name-76778-87e7-23@test";
      String spChar8  = "default.:test_db_name";
      String spChar9  = "default.customer's_name";
      String spChar10 = "default.customers'_data_name";
      String spChar11 = "search_with space@name";
      String spChar12 = "search_with space 123@name";
      String spChar13 = "search_with_special-char#having$and%inthename=attr";
      String spChar14 = "search_with_specialChar!name";
      String spChar15 = "search_with_star*in_name";
      String spChar16 = "search_with_star5.*5_inname";
      String spChar17 = "search_quest?n_name";
      String spChar18 = "/warehouse/tablespace/external/hive/name/hortonia_bank";
      String spChar19 = "/warehouse/tablespace/external/hive/name/exis_bank";
      String spChar20 = "search_name_with nameblank@namecluster";
  
      @Inject
      private AtlasDiscoveryService discoveryService;
  
      @BeforeClass
      public void setup() throws Exception {
          super.initialize();
  
          ApplicationProperties.get().setProperty(ApplicationProperties.ENABLE_FREETEXT_SEARCH_CONF, true);
  
          setupTestData();
  
          createDimensionalTaggedEntity("sales");
          createSpecialCharTestEntities();
          setupRelationshipTestData();
          createJapaneseEntityWithDescription();
      }
  
      @Test
      public void term() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTermName(SALES_TERM + "@" + SALES_GLOSSARY);
  
          assertSearchProcessorWithoutMarker(params, 10);
      }
  
      // TSP execute and CSP,ESP filter
      @Test
      public void termTag() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTermName(SALES_TERM + "@" + SALES_GLOSSARY);
          params.setClassification(METRIC_CLASSIFICATION);
  
          assertSearchProcessorWithoutMarker(params, 4);
      }
  
      @Test
      public void termEntity() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTermName(SALES_TERM + "@" + SALES_GLOSSARY);
          params.setTypeName(HIVE_TABLE_TYPE);
  
          assertSearchProcessorWithoutMarker(params, 10);
      }
  
      @Test
      public void termEntityTag() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTermName(SALES_TERM + "@" + SALES_GLOSSARY);
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setClassification(DIMENSIONAL_CLASSIFICATION);
  
          List<AtlasEntityHeader> entityHeaders = discoveryService.searchWithParameters(params).getEntities();
  
          assertTrue(CollectionUtils.isEmpty(entityHeaders));
      }
  
      //FSP execute and CSP,ESP filter
      @Test
      public void queryALLTag() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setClassification(ALL_CLASSIFICATION_TYPES);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 5);
      }
  
      @Test
      public void queryALLTagTagFilter() throws AtlasBaseException {
          SearchParameters.FilterCriteria fc     = getSingleFilterCondition("__typeName", Operator.NOT_CONTAINS, METRIC_CLASSIFICATION);
          SearchParameters                params = new SearchParameters();
  
          params.setClassification(ALL_CLASSIFICATION_TYPES);
          //typeName will check for only classification name not propogated classification
          params.setTagFilters(fc);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 4);
      }
  
      @Test
      public void queryNOTCLASSIFIEDTag() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setClassification(NO_CLASSIFICATIONS);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 11);
      }
  
      @Test
      public void queryALLWildcardTag() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setClassification("*");
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 5);
      }
  
      @Test
      public void queryWildcardTag() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setClassification("Dimen*on");
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 2);
      }
  
      @Test
      public void queryTag() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setClassification(METRIC_CLASSIFICATION);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 3);
      }
  
      @Test
      public void queryTagTagFilter() throws AtlasBaseException {
          SearchParameters.FilterCriteria fc     = getSingleFilterCondition("__timestamp", SearchParameters.Operator.LT, String.valueOf(System.currentTimeMillis()));
          SearchParameters                params = new SearchParameters();
  
          params.setClassification(METRIC_CLASSIFICATION);
          params.setTagFilters(fc);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 3);
      }
  
      @Test
      public void queryEntity() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 4);
      }
  
      @Test
      public void queryEntityEntityFilter() throws AtlasBaseException {
          SearchParameters.FilterCriteria fc     = getSingleFilterCondition("tableType", Operator.NOT_NULL, "null");
          SearchParameters                params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(fc);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 3);
      }
  
      @Test
      public void queryEntityEntityFilterTag() throws AtlasBaseException {
          SearchParameters.FilterCriteria fc     = getSingleFilterCondition("tableType", Operator.IS_NULL, "null");
          SearchParameters                params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(fc);
          params.setClassification(DIMENSIONAL_CLASSIFICATION);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 1);
      }
  
      @Test
      public void queryEntityEntityFilterTagTagFilter() throws AtlasBaseException {
          SearchParameters.FilterCriteria fcE    = getSingleFilterCondition("tableType", Operator.IS_NULL, "null");
          SearchParameters.FilterCriteria fcC    = getSingleFilterCondition("attr1", Operator.EQ, "value1");
          SearchParameters                params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(fcE);
          params.setClassification(DIMENSIONAL_CLASSIFICATION);
          params.setQuery("sales");
          params.setTagFilters(fcC);
  
          assertSearchProcessorWithoutMarker(params, 1);
      }
  
      @Test
      public void queryEntityTagTagFilter() throws AtlasBaseException {
          SearchParameters.FilterCriteria fc     = getSingleFilterCondition("__timestamp", SearchParameters.Operator.LT, String.valueOf(System.currentTimeMillis()));
          SearchParameters                params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setClassification(METRIC_CLASSIFICATION);
          params.setTagFilters(fc);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 2);
      }
  
      @Test
      public void queryEntityTag() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setClassification(METRIC_CLASSIFICATION);
          params.setQuery("sales");
  
          assertSearchProcessorWithoutMarker(params, 2);
      }
  
      // CSP Execute and ESP filter
      @Test
      public void entityEntityFilterTagTagFilter() throws AtlasBaseException {
          SearchParameters.FilterCriteria fcE    = getSingleFilterCondition("tableType", Operator.EQ, "Managed");
          SearchParameters.FilterCriteria fcC    = getSingleFilterCondition("__timestamp", SearchParameters.Operator.LT, String.valueOf(System.currentTimeMillis()));
          SearchParameters                params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(fcE);
          params.setClassification(METRIC_CLASSIFICATION);
          params.setTagFilters(fcC);
  
          assertSearchProcessorWithoutMarker(params, 4);
      }
  
      @Test
      public void entityTagTagFilter() throws AtlasBaseException {
          SearchParameters.FilterCriteria fc     = getSingleFilterCondition("__timestamp", SearchParameters.Operator.LT, String.valueOf(System.currentTimeMillis()));
          SearchParameters                params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setClassification(METRIC_CLASSIFICATION);
          params.setTagFilters(fc);
  
          assertSearchProcessorWithoutMarker(params, 4);
      }
  
      @Test
      public void searchWith0offsetMarker() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setOffset(0);
          params.setMarker(SearchContext.MarkerUtil.MARKER_START);
          params.setLimit(5);
  
          assertSearchProcessorWithMarker(params, 5);
      }
  
      @Test
      public void searchWithNoOffsetMarker() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setMarker(SearchContext.MarkerUtil.MARKER_START);
          params.setLimit(5);
  
          assertSearchProcessorWithMarker(params, 5);
      }
  
      @Test
      public void searchWithGreaterThan0OffsetBlankMarker() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setOffset(1);
          params.setMarker("");
          params.setLimit(5);
  
          assertSearchProcessorWithoutMarker(params, 5);
      }
  
      @Test(expectedExceptions = AtlasBaseException.class, expectedExceptionsMessageRegExp = "Marker can be used only if offset=0.")
      public void searchWithGreaterThan0OffsetMarker() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setOffset(1);
          params.setMarker(SearchContext.MarkerUtil.MARKER_START);
          params.setLimit(5);
  
          List<AtlasEntityHeader> entityHeaders = discoveryService.searchWithParameters(params).getEntities();
  
          assertNotNull(entityHeaders);
      }
  
      @Test
      public void searchWithMarkerSet() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setMarker(SearchContext.MarkerUtil.MARKER_START);
          params.setLimit(5);
  
          AtlasSearchResult       searchResult  = discoveryService.searchWithParameters(params);
          List<AtlasEntityHeader> entityHeaders = searchResult.getEntities();
  
          assertTrue(CollectionUtils.isNotEmpty(entityHeaders));
          assertEquals(entityHeaders.size(), 5);
          assertTrue(StringUtils.isNotEmpty(searchResult.getNextMarker()));
  
          //get next marker and set in marker of subsequent request
          params.setMarker(searchResult.getNextMarker());
  
          AtlasSearchResult       nextsearchResult  = discoveryService.searchWithParameters(params);
          List<AtlasEntityHeader> nextentityHeaders = nextsearchResult.getEntities();
  
          assertTrue(CollectionUtils.isNotEmpty(nextentityHeaders));
          assertTrue(StringUtils.isNotEmpty(nextsearchResult.getNextMarker()));
  
          if (entityHeaders.size() < params.getLimit()) {
              assertSame(nextsearchResult.getNextMarker(), String.valueOf(-1));
          }
      }
  
      @Test(expectedExceptions = AtlasBaseException.class, expectedExceptionsMessageRegExp = "Invalid marker!")
      public void searchWithInvalidMarker() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setMarker(SearchContext.MarkerUtil.MARKER_START);
          params.setLimit(5);
  
          AtlasSearchResult       searchResult  = discoveryService.searchWithParameters(params);
          List<AtlasEntityHeader> entityHeaders = searchResult.getEntities();
  
          assertTrue(CollectionUtils.isNotEmpty(entityHeaders));
          assertEquals(entityHeaders.size(), 5);
          assertTrue(StringUtils.isNotEmpty(searchResult.getNextMarker()));
  
          //get next marker and set in marker of subsequent request
          params.setMarker(searchResult.getNextMarker() + "abc");
  
          discoveryService.searchWithParameters(params);
      }
  
      @Test
      public void searchWithLastPageMarker() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setExcludeDeletedEntities(true);
          params.setMarker(SearchContext.MarkerUtil.MARKER_START);
  
          int totalCount = discoveryService.searchWithParameters(params).getEntities().size();
  
          params.setMarker(SearchContext.MarkerUtil.MARKER_START);
          params.setLimit(5);
  
          AtlasSearchResult       searchResult  = discoveryService.searchWithParameters(params);
          List<AtlasEntityHeader> entityHeaders = searchResult.getEntities();
  
          assertTrue(CollectionUtils.isNotEmpty(entityHeaders));
          assertEquals(entityHeaders.size(), 5);
          assertTrue(StringUtils.isNotEmpty(searchResult.getNextMarker()));
  
          //get next marker and set in marker of subsequent request
          params.setMarker(SearchContext.MarkerUtil.MARKER_START);
          params.setLimit(totalCount + 10);
  
          AtlasSearchResult nextsearchResult = discoveryService.searchWithParameters(params);
  
          assertEquals(nextsearchResult.getNextMarker(), "-1");
      }
  
      @Test //marker functionality is not supported
      public void termMarker() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTermName(SALES_TERM + "@" + SALES_GLOSSARY);
          params.setMarker("*");
  
          assertSearchProcessorWithoutMarker(params, 10);
      }
  
      @Test
      public void queryEntityTagMarker() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setClassification(METRIC_CLASSIFICATION);
          params.setQuery("sales");
          params.setMarker("*");
          params.setLimit(5);
  
          assertSearchProcessorWithMarker(params, 2);
      }
  
      // CSP Execute and ESP filter
      @Test
      public void entityEntityFilterTagTagFilterMarker() throws AtlasBaseException {
          SearchParameters.FilterCriteria fcE    = getSingleFilterCondition("tableType", Operator.EQ, "Managed");
          SearchParameters.FilterCriteria fcC    = getSingleFilterCondition("__timestamp", SearchParameters.Operator.LT, String.valueOf(System.currentTimeMillis()));
          SearchParameters                params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(fcE);
          params.setClassification(METRIC_CLASSIFICATION);
          params.setTagFilters(fcC);
          params.setMarker("*");
  
          assertSearchProcessorWithoutMarker(params, 4);
      }
  
      public void createSpecialCharTestEntities() throws AtlasBaseException {
          List<String> nameList = Arrays.asList(spChar1, spChar2, spChar3, spChar4, spChar5, spChar6, spChar7, spChar8, spChar9, spChar10, spChar11, spChar12, spChar13, spChar14, spChar15, spChar16, spChar17, spChar18, spChar19, spChar20);
  
          for (String nameStr : nameList) {
              AtlasEntity entityToDelete = new AtlasEntity(HIVE_TABLE_TYPE);
  
              entityToDelete.setAttribute("name", nameStr);
              entityToDelete.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, "qualifiedName" + System.currentTimeMillis());
  
              //create entity
              entityStore.createOrUpdate(new AtlasEntityStream(new AtlasEntity.AtlasEntitiesWithExtInfo(entityToDelete)), false);
          }
  
          List<String> qfList = nameList;
  
          for (String qfStr : qfList) {
              qfStr = qfStr.replace("name", "qf");
  
              AtlasEntity entityToDelete = new AtlasEntity(HIVE_TABLE_TYPE);
  
              entityToDelete.setAttribute("name", "name" + System.currentTimeMillis());
              entityToDelete.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, qfStr);
  
              //create entity
              entityStore.createOrUpdate(new AtlasEntityStream(new AtlasEntity.AtlasEntitiesWithExtInfo(entityToDelete)), false);
          }
      }
  
      @Test(dataProvider = "specialCharSearchEQ")
      public void specialCharSearchAssertEq(String attrName, SearchParameters.Operator operator, String attrValue, int expected) throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition(attrName, operator, attrValue);
          SearchParameters                params         = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(filterCriteria);
          params.setLimit(20);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
  
          assertSearchResult(searchResult, expected, attrValue);
      }
  
      @Test(dataProvider = "specialCharSearchContains")
      public void specialCharSearchAssertContains(String attrName, SearchParameters.Operator operator, String attrValue, int expected) throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition(attrName, operator, attrValue);
          SearchParameters                params         = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(filterCriteria);
          params.setLimit(20);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
  
          assertSearchResult(searchResult, expected, attrValue);
      }
  
      @Test(dataProvider = "specialCharSearchContains")
      public void specialCharQuickSearchAssertContains(String attrName, SearchParameters.Operator operator, String attrValue, int expected) throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition(attrName, operator, attrValue);
          QuickSearchParameters           params         = new QuickSearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(filterCriteria);
          params.setLimit(20);
  
          AtlasQuickSearchResult searchResult = discoveryService.quickSearch(params);
  
          assertSearchResult(searchResult.getSearchResults(), expected, attrValue);
  
          List<String> failedCases = Arrays.asList("def:default:qf-", "star*in", "ith spac", "778-87");
  
          if (attrName.equals("qualifiedName") && failedCases.contains(attrValue)) {
              expected = 0;
          }
  
          if (expected > 0) {
              assertAggregationMetrics(searchResult);
          }
      }
  
      @Test(dataProvider = "specialCharSearchName")
      public void specialCharSearchAssertName(String attrName, SearchParameters.Operator operator, String attrValue, int expected) throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition(attrName, operator, attrValue);
          SearchParameters                params         = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(filterCriteria);
          params.setLimit(20);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
  
          assertSearchResult(searchResult, expected, attrValue);
      }
  
      @Test(dataProvider = "specialCharSearchName")
      public void specialCharQuickSearchAssertName(String attrName, SearchParameters.Operator operator, String attrValue, int expected) throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition(attrName, operator, attrValue);
          QuickSearchParameters           params         = new QuickSearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(filterCriteria);
          params.setLimit(20);
  
          AtlasQuickSearchResult searchResult = discoveryService.quickSearch(params);
  
          assertSearchResult(searchResult.getSearchResults(), expected, attrValue);
  
          if (expected > 0) {
              assertAggregationMetrics(searchResult);
          }
      }
  
      @Test(dataProvider = "specialCharSearchQFName")
      public void specialCharSearchAssertQFName(String attrName, SearchParameters.Operator operator, String attrValue, int expected) throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition(attrName, operator, attrValue);
          SearchParameters                params         = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(filterCriteria);
          params.setLimit(20);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
  
          assertSearchResult(searchResult, expected, attrValue);
      }
  
      @Test(dataProvider = "specialCharSearchQFName")
      public void specialCharQuickSearchAssertQFName(String attrName, SearchParameters.Operator operator, String attrValue, int expected) throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition(attrName, operator, attrValue);
          QuickSearchParameters           params         = new QuickSearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setEntityFilters(filterCriteria);
          params.setLimit(20);
  
          AtlasQuickSearchResult searchResult = discoveryService.quickSearch(params);
  
          assertSearchResult(searchResult.getSearchResults(), expected, attrValue);
  
          if (expected > 0) {
              assertAggregationMetrics(searchResult);
          }
      }
  
      @Test(dataProvider = "specialCharQuickSearch")
      public void specialCharQuickSearch(String searchValue, int expected) throws AtlasBaseException {
          QuickSearchParameters params = new QuickSearchParameters();
  
          params.setQuery(searchValue);
          params.setLimit(5);
          params.setOffset(0);
  
          AtlasQuickSearchResult searchResult = discoveryService.quickSearch(params);
  
          assertSearchResult(searchResult.getSearchResults(), expected, searchValue);
  
          if (expected > 0) {
              assertAggregationMetrics(searchResult);
          }
      }
  
      @Test
      public void searchWithEntityQuickSearchSortAsc() throws AtlasBaseException {
          QuickSearchParameters params = new QuickSearchParameters();
  
          params.setTypeName("hive_table");
          params.setQuery("sales");
          params.setExcludeDeletedEntities(true);
          params.setLimit(3);
          params.setSortBy("owner");
          params.setSortOrder(SortOrder.ASCENDING);
  
          AtlasQuickSearchResult  searchResult = discoveryService.quickSearch(params);
          List<AtlasEntityHeader> list         = searchResult.getSearchResults().getEntities();
  
          assertTrue(CollectionUtils.isNotEmpty(list));
          assertEquals(list.size(), 3);
          assertTrue(list.get(0).getAttribute("owner").toString().equalsIgnoreCase("Jane BI"));
          assertTrue(list.get(1).getAttribute("owner").toString().equalsIgnoreCase("Joe"));
      }
  
      @Test
      public void searchWithEntityQuickSearchSortDesc() throws AtlasBaseException {
          QuickSearchParameters params = new QuickSearchParameters();
  
          params.setTypeName("hive_table");
          params.setQuery("sales");
          params.setExcludeDeletedEntities(true);
          params.setLimit(3);
          params.setSortBy("name");
          params.setSortOrder(SortOrder.DESCENDING);
  
          AtlasQuickSearchResult  searchResult = discoveryService.quickSearch(params);
          List<AtlasEntityHeader> list         = searchResult.getSearchResults().getEntities();
  
          assertTrue(CollectionUtils.isNotEmpty(list));
          assertEquals(list.size(), 3);
          assertTrue(list.get(0).getDisplayText().equalsIgnoreCase("time_dim"));
          assertTrue(list.get(1).getDisplayText().equalsIgnoreCase("sales_fact_monthly_mv"));
      }
  
      @Test
      public void searchRelatedEntitiesSortAsc() throws AtlasBaseException {
          String           guid   = gethiveTableSalesFactGuid();
          SearchParameters params = new SearchParameters();
  
          params.setLimit(10);
  
          AtlasSearchResult       relResult = discoveryService.searchRelatedEntities(guid, "__hive_table.columns", false, params);
          List<AtlasEntityHeader> list      = relResult.getEntities();
  
          assertTrue(CollectionUtils.isNotEmpty(list));
          assertEquals(list.size(), 6);
          assertTrue(list.get(0).getDisplayText().equalsIgnoreCase("customer_id"));
          assertTrue(list.get(5).getDisplayText().equalsIgnoreCase("time_id"));
      }
  
      @Test
      public void searchRelatedEntitiesSortDesc() throws AtlasBaseException {
          String           guid   = gethiveTableSalesFactGuid();
          SearchParameters params = new SearchParameters();
  
          params.setLimit(10);
          params.setSortOrder(SortOrder.DESCENDING);
  
          AtlasSearchResult       relResult = discoveryService.searchRelatedEntities(guid, "columns", false, params);
          List<AtlasEntityHeader> list      = relResult.getEntities();
  
          assertTrue(CollectionUtils.isNotEmpty(list));
          assertEquals(list.size(), 6);
          assertTrue(list.get(5).getDisplayText().equalsIgnoreCase("customer_id"));
          assertTrue(list.get(0).getDisplayText().equalsIgnoreCase("time_id"));
      }
  
      //test excludeHeaderAttributes
      @Test
      public void excludeHeaderAttributesStringAttr() throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition("tableType", Operator.EQ, "Managed");
          SearchParameters                params         = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setExcludeHeaderAttributes(true);
          params.setEntityFilters(filterCriteria);
          params.setSortBy("name");
          params.setAttributes(new HashSet<>(Collections.singletonList("name")));
          params.setLimit(1);
  
          AtlasSearchResult                       searchResult = discoveryService.searchWithParameters(params);
          AtlasSearchResult.AttributeSearchResult expected     = new AtlasSearchResult.AttributeSearchResult();
  
          expected.setName(Collections.singletonList("name"));
          expected.setValues(Collections.singletonList(Collections.singletonList("log_fact_daily_mv")));
  
          assertSearchResult(searchResult, expected);
      }
  
      @Test
      public void excludeHeaderAttributesRelationAttr() throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition("name", Operator.EQ, "time_dim");
          SearchParameters                params         = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setExcludeHeaderAttributes(true);
          params.setEntityFilters(filterCriteria);
          params.setAttributes(new HashSet<>(Arrays.asList("name", "db")));
          params.setLimit(1);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
  
          assertNotNull(searchResult);
          assertNotNull(searchResult.getEntities());
          assertNotNull(searchResult.getReferredEntities());
      }
  
      @Test
      public void excludeHeaderAttributesSystemAttr() throws AtlasBaseException {
          SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition("tableType", Operator.EQ, "Managed");
          SearchParameters                params         = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setExcludeHeaderAttributes(true);
          params.setAttributes(new HashSet<>(Arrays.asList("name", "__state")));
          params.setLimit(1);
          params.setEntityFilters(filterCriteria);
          params.setSortBy("name");
  
          AtlasSearchResult                       searchResult = discoveryService.searchWithParameters(params);
          AtlasSearchResult.AttributeSearchResult expected     = new AtlasSearchResult.AttributeSearchResult();
  
          expected.setName(Arrays.asList("name", "__state"));
          expected.setValues(Arrays.asList(Arrays.asList("log_fact_daily_mv", "ACTIVE")));
  
          assertSearchResult(searchResult, expected);
      }
  
      @Test
      public void excludeHeaderAttributesAllEntityTypeSysAttr() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE + "," + ALL_ENTITY_TYPES);
          params.setExcludeHeaderAttributes(true);
          params.setAttributes(new HashSet<>(Collections.singletonList("__state")));
          params.setLimit(2);
  
          AtlasSearchResult                       searchResult = discoveryService.searchWithParameters(params);
          AtlasSearchResult.AttributeSearchResult expected     = new AtlasSearchResult.AttributeSearchResult();
  
          expected.setName(Arrays.asList("__state"));
          expected.setValues(Arrays.asList(Arrays.asList("ACTIVE"), Arrays.asList("ACTIVE")));
  
          assertSearchResult(searchResult, expected);
      }
  
      @Test
      public void excludeHeaderAttributesAllEntityTypeSysAttrs() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE + "," + ALL_ENTITY_TYPES);
          params.setExcludeHeaderAttributes(true);
          params.setAttributes(new HashSet<>(Arrays.asList("__state", "__guid")));
          params.setLimit(2);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
          assertEquals(searchResult.getAttributes().getValues().size(), 2);
      }
  
      @Test(expectedExceptions = AtlasBaseException.class, expectedExceptionsMessageRegExp = "Attribute name not found for type __ENTITY_ROOT")
      public void excludeHeaderAttributesAllEntityType() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE + "," + ALL_ENTITY_TYPES);
          params.setExcludeHeaderAttributes(true);
          params.setAttributes(new HashSet<>(Collections.singletonList("name")));
          params.setLimit(1);
  
          discoveryService.searchWithParameters(params);
      }
  
      @Test(expectedExceptions = AtlasBaseException.class, expectedExceptionsMessageRegExp = "Attribute name1 not found for type hive_table")
      public void excludeHeaderAttributesInvalidAttr() throws AtlasBaseException {
          SearchParameters params = new SearchParameters();
  
          params.setTypeName(HIVE_TABLE_TYPE);
          params.setExcludeHeaderAttributes(true);
          params.setAttributes(new HashSet<>(Collections.singletonList("name1")));
          params.setLimit(1);
  
          discoveryService.searchWithParameters(params);
      }
  
      @Test
      public void searchRelations() throws AtlasBaseException {
          RelationshipSearchParameters sp = new RelationshipSearchParameters();
          sp.setRelationshipName("highlight_post");
          sp.setMarker("*");
          sp.setLimit(10);
          sp.setRelationshipFilters(getSingleFilterCondition("highlight_name", Operator.EQ, "year2021@Ajay"));
  
          AtlasSearchResult sr = discoveryService.searchRelationsWithParameters(sp);
          assertEquals(sr.getRelations().size(), 4);
      }
  
      @Test
      public void cjkCharQuickSearch() throws AtlasBaseException {
          addLabels();
          String searchValue = "你";
          int    expected    = 1;
  
          QuickSearchParameters params = new QuickSearchParameters();
          params.setQuery(searchValue);
          params.setLimit(5);
          params.setOffset(0);
  
          AtlasQuickSearchResult searchResult = discoveryService.quickSearch(params);
          assertSearchResult(searchResult.getSearchResults(), expected, searchValue);
      }
  
      @Test(dependsOnMethods = "cjkCharQuickSearch")
      public void cjkCharBasicSearch() throws AtlasBaseException {
          String searchValue = "你好";
          int    expected    = 1;
  
          SearchParameters params = new SearchParameters();
          params.setQuery(searchValue);
          params.setLimit(5);
          params.setOffset(0);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
          assertSearchResult(searchResult, expected, searchValue);
      }
  
      @Test
      public void japaneseReceiptStarSearch() throws AtlasBaseException {
          String searchValue = "レシート";
          int    expected    = 1;
  
          SearchParameters params = new SearchParameters();
          params.setQuery(searchValue);
          params.setTypeName(HDFS_PATH);
          params.setLimit(5);
          params.setOffset(0);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
          assertSearchResult(searchResult, expected, searchValue);
      }
  
      @Test
      public void japaneseLedgerSearch() throws AtlasBaseException {
          String searchValue = "元帳";
          int    expected    = 2;
  
          SearchParameters params = new SearchParameters();
          params.setQuery(searchValue);
          params.setLimit(5);
          params.setOffset(0);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
          assertSearchResult(searchResult, expected, searchValue);
      }
  
      @Test
      public void japaneseLedgerStarSearch() throws AtlasBaseException {
          String searchValue = "の台*";
          int    expected    = 1;
  
          SearchParameters params = new SearchParameters();
          params.setQuery(searchValue);
          params.setLimit(5);
          params.setOffset(0);
  
          AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
          assertSearchResult(searchResult, expected, searchValue);
      }
  
      @AfterClass
      public void teardown() throws Exception {
          AtlasGraphProvider.cleanup();
  
          super.cleanup();
      }
  
      @DataProvider(name = "specialCharSearchContains")
      private Object[][] specialCharSearchContains() {
          return new Object[][] {
                  {"name", Operator.CONTAINS, "test_dot", 4},
                  {"name", Operator.CONTAINS, "test_dot_name_", 1},
                  {"name", Operator.CONTAINS, "test_colon_name", 2},
                  {"name", Operator.CONTAINS, "def:default:name", 1},
                  {"name", Operator.CONTAINS, "space 12", 1},
                  {"name", Operator.CONTAINS, "with space", 2},
                  {"name", Operator.CONTAINS, "Char!name", 1},
                  {"name", Operator.CONTAINS, "with_star", 2},
                  {"name", Operator.CONTAINS, "/external/hive/name/", 2},
  
                  {"name", Operator.CONTAINS, "test_dot_name@db", 1},
                  {"name", Operator.CONTAINS, "name@db", 1},
                  {"name", Operator.CONTAINS, "def:default:name-", 1},
                  {"name", Operator.CONTAINS, "star*in", 1},
                  {"name", Operator.CONTAINS, "Char!na", 1},
                  {"name", Operator.CONTAINS, "ith spac", 2},
                  {"name", Operator.CONTAINS, "778-87", 1},
  
                  {"qualifiedName", Operator.CONTAINS, "test_dot", 4},
                  {"qualifiedName", Operator.CONTAINS, "test_dot_qf_", 1},
                  {"qualifiedName", Operator.CONTAINS, "test_colon_qf", 2},
                  {"qualifiedName", Operator.CONTAINS, "def:default:qf", 1},
                  {"qualifiedName", Operator.CONTAINS, "space 12", 1},
                  {"qualifiedName", Operator.CONTAINS, "with space", 2},
                  {"qualifiedName", Operator.CONTAINS, "Char!qf", 1},
                  {"qualifiedName", Operator.CONTAINS, "with_star", 2},
                  {"qualifiedName", Operator.CONTAINS, "/external/hive/qf/", 2},
  
                  {"qualifiedName", Operator.CONTAINS, "test_dot_qf@db", 1},
                  {"qualifiedName", Operator.CONTAINS, "qf@db", 1},
                  {"qualifiedName", Operator.CONTAINS, "def:default:qf-", 1},
                  {"qualifiedName", Operator.CONTAINS, "star*in", 1},
                  {"qualifiedName", Operator.CONTAINS, "Char!q", 1},
                  {"qualifiedName", Operator.CONTAINS, "ith spac", 2},
                  {"qualifiedName", Operator.CONTAINS, "778-87", 1},
          };
      }
  
      @DataProvider(name = "specialCharSearchName")
      private Object[][] specialCharSearchName() {
          return new Object[][] {
                  {"name", Operator.STARTS_WITH, "default.test_dot_", 3},
  
                  {"name", Operator.STARTS_WITH, "default.test_dot_name@db.test", 1},
                  {"name", Operator.STARTS_WITH, "default.test_dot_name@db.", 1},
                  {"name", Operator.STARTS_WITH, "default.test_dot_name", 3},
                  {"name", Operator.ENDS_WITH, "test_db", 3},
  
                  {"name", Operator.STARTS_WITH, "default.test_dot_name_12.col1@db", 1},
                  {"name", Operator.STARTS_WITH, "default.test_dot_name_12.col1@", 1},
                  {"name", Operator.STARTS_WITH, "default.test_dot_name_12.col1", 1},
                  {"name", Operator.STARTS_WITH, "default.test_dot_name_12.col", 1},
                  {"name", Operator.STARTS_WITH, "default.test_dot_name_12.", 1},
                  {"name", Operator.STARTS_WITH, "default.test_dot_name_12", 1},
                  {"name", Operator.ENDS_WITH, "col1@db1", 1},
  
                  {"name", Operator.STARTS_WITH, "default_.test_dot", 1},
                  {"name", Operator.ENDS_WITH, "test_dot_name", 2},
  
                  {"name", Operator.STARTS_WITH, "default.test_colon_name:test_", 1},
  
                  {"name", Operator.STARTS_WITH, "default.test_colon_name:-test_", 1},
                  {"name", Operator.STARTS_WITH, "default.test_colon_name:-", 1},
                  {"name", Operator.STARTS_WITH, "default.test_colon", 2},
  
                  {"name", Operator.STARTS_WITH, "crn:def:default:name-76778-87e7-23@", 1},
                  {"name", Operator.STARTS_WITH, "crn:def:default:name-76778-87e7-", 1},
                  {"name", Operator.STARTS_WITH, "crn:def:default:", 1},
  
                  {"name", Operator.STARTS_WITH, "default.:test_db", 1},
                  {"name", Operator.ENDS_WITH, "test_db_name", 1},
  
                  {"name", Operator.STARTS_WITH, "default.customer's", 1},
                  {"name", Operator.ENDS_WITH, "mer's_name", 1},
  
                  {"name", Operator.STARTS_WITH, "default.customers'_data", 1},
                  {"name", Operator.ENDS_WITH, "customers'_data_name", 1},
  
                  {"name", Operator.STARTS_WITH, "search_with space", 2},
                  {"name", Operator.STARTS_WITH, "search_with space ", 1},
                  {"name", Operator.STARTS_WITH, "search_with space 123@", 1},
                  {"name", Operator.STARTS_WITH, "search_with space 1", 1},
  
                  {"name", Operator.STARTS_WITH, "search_with_special-char#having$and%inthename=", 1},
                  {"name", Operator.STARTS_WITH, "search_with_special-char#having$and%in", 1},
                  {"name", Operator.STARTS_WITH, "search_with_special-char#having$", 1},
                  {"name", Operator.STARTS_WITH, "search_with_special-char#h", 1},
                  {"name", Operator.STARTS_WITH, "search_with_special", 2},
                  {"name", Operator.STARTS_WITH, "search_with_spe", 2},
  
                  {"name", Operator.STARTS_WITH, "search_with_specialChar!", 1},
  
                  {"name", Operator.STARTS_WITH, "search_with_star*in", 1},
  
                  {"name", Operator.ENDS_WITH, "5.*5_inname", 1},
                  {"name", Operator.STARTS_WITH, "search_with_star5.*5_", 1},
  
                  {"name", Operator.STARTS_WITH, "search_quest?n_", 1},
  
                  {"name", Operator.STARTS_WITH, "/warehouse/tablespace/external/hive/name/hortonia", 1},
                  {"name", Operator.STARTS_WITH, "/warehouse/tablespace/external/hive/name/", 2},
          };
      }
  
      @DataProvider(name = "specialCharSearchQFName")
      private Object[][] specialCharSearchQFName() {
          return new Object[][] {
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_", 3},
  
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_qf@db.test", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_qf@db.", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_qf", 3},
                  {"qualifiedName", Operator.ENDS_WITH, "test_db", 3},
  
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_qf_12.col1@db", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_qf_12.col1@", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_qf_12.col1", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_qf_12.col", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_qf_12.", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_dot_qf_12", 1},
                  {"qualifiedName", Operator.ENDS_WITH, "col1@db1", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "default_.test_dot", 1},
                  {"qualifiedName", Operator.ENDS_WITH, "test_dot_qf", 2},
  
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_colon_qf:test_", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_colon_qf:-test_", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_colon_qf:-", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "default.test_colon", 2},
  
                  {"qualifiedName", Operator.STARTS_WITH, "crn:def:default:qf-76778-87e7-23@", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "crn:def:default:qf-76778-87e7-", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "crn:def:default:", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "default.:test_db", 1},
                  {"qualifiedName", Operator.ENDS_WITH, "test_db_qf", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "default.customer's", 1},
                  {"qualifiedName", Operator.ENDS_WITH, "mer's_qf", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "default.customers'_data", 1},
                  {"qualifiedName", Operator.ENDS_WITH, "customers'_data_qf", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "search_with space", 2},
                  {"qualifiedName", Operator.STARTS_WITH, "search_with space ", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "search_with space 123@", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "search_with space 1", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "search_with_special-char#having$and%intheqf=", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "search_with_special-char#having$and%in", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "search_with_special-char#having$", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "search_with_special-char#h", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "search_with_special", 2},
                  {"qualifiedName", Operator.STARTS_WITH, "search_with_spe", 2},
  
                  {"qualifiedName", Operator.STARTS_WITH, "search_with_specialChar!", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "search_with_star*in", 1},
  
                  {"qualifiedName", Operator.ENDS_WITH, "5.*5_inqf", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "search_with_star5.*5_", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "search_quest?n_", 1},
  
                  {"qualifiedName", Operator.STARTS_WITH, "/warehouse/tablespace/external/hive/qf/hortonia", 1},
                  {"qualifiedName", Operator.STARTS_WITH, "/warehouse/tablespace/external/hive/qf/", 2},
          };
      }
  
      @DataProvider(name = "specialCharSearchEQ")
      private Object[][] specialCharSearch() {
          return new Object[][] {
                  {"name", Operator.EQ, spChar1, 1},
                  {"name", Operator.EQ, spChar2, 1},
                  {"name", Operator.EQ, spChar3, 1},
                  {"name", Operator.EQ, spChar4, 1},
                  {"name", Operator.EQ, spChar5, 1},
                  {"name", Operator.EQ, spChar6, 1},
                  {"name", Operator.EQ, spChar7, 1},
                  {"name", Operator.EQ, spChar8, 1},
                  {"name", Operator.EQ, spChar9, 1},
                  {"name", Operator.EQ, spChar10, 1},
                  {"name", Operator.EQ, spChar11, 1},
                  {"name", Operator.EQ, spChar12, 1},
                  {"name", Operator.EQ, spChar13, 1},
                  {"name", Operator.EQ, spChar14, 1},
                  {"name", Operator.EQ, spChar15, 1},
                  {"name", Operator.EQ, spChar16, 1},
                  {"name", Operator.EQ, spChar17, 1},
                  {"name", Operator.EQ, spChar18, 1},
                  {"name", Operator.EQ, spChar19, 1},
  
                  {"qualifiedName", Operator.EQ, spChar1.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar2.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar3.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar4.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar5.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar6.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar7.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar8.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar9.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar10.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar11.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar12.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar13.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar14.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar15.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar16.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar17.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar18.replace("name", "qf"), 1},
                  {"qualifiedName", Operator.EQ, spChar19.replace("name", "qf"), 1},
          };
      }
  
      @DataProvider(name = "specialCharQuickSearch")
      private Object[][] specialCharQuickSearch() {
          return new Object[][] {
                  {"default.test_dot_name", 3},
                  {"default.test_dot_name*", 3},
                  {"test_dot_name", 0},
                  {"*test_dot_name", 2},
                  {"*test_dot_name*", 4},
                  {"default.test_dot_name\\*", 0},
  
                  {"default.test_dot_qf", 3},
                  {"default.test_dot_qf*", 3},
                  {"test_dot_qf", 1},
                  {"*test_dot_qf", 3},
                  {"*test_dot_qf*", 4},
                  {"default.test_dot_qf\\*", 2},
  
                  {"default.test_dot_name_12.col1", 1},
                  {"default.test_dot_name_12.col1*", 1},
                  {"default.test_dot_name_12.col", 0},
                  {"default.test_dot_name_12.col*", 1},
                  {"default.test_dot_qf_12.col1", 1},
                  {"default.test_dot_qf_12.col1*", 0},
  
                  {"default.test_dot_name_12*", 1},
                  {"default.test_dot_qf_12*", 1},
  
                  //space gets tokenized, hence whenever user searches for 'STRING' type attribute, space needs to be escaped
                  {"search_name_with nameblank@namecluster", 0},
                  //{"search_name_with nameblank@name", 0}, commenting as there are some entities created from other class with same name
                  {"search_name_with nameblank*", 0},
                  {"search_name_with\\ nameblank@namecluster", 1},
                  {"search_name_with\\ nameblank*", 1},
  
                  //if we escape it will consider as single string, hence * will act as character not as wildcard
                  {"search_qf_with\\ qfblank*", 0},
                  {"search_qf_with\\ qfblank@qfcluster", 1},
                  {"search_qf_with qfblank@qfcluster", 1},
                  {"search_qf_with qfblank@q", 1},
                  {"search_qf_with qfblank*", 1},
          };
      }
  
      private String gethiveTableSalesFactGuid() throws AtlasBaseException {
          if (salesFactGuid == null) {
              SearchParameters params = new SearchParameters();
              params.setTypeName(HIVE_TABLE_TYPE);
              SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition("name", Operator.EQ, "sales_fact");
              params.setEntityFilters(filterCriteria);
              AtlasSearchResult result = discoveryService.searchWithParameters(params);
  
              if (result != null && CollectionUtils.isNotEmpty(result.getEntities())) {
                  salesFactGuid = result.getEntities().get(0).getGuid();
              }
          }
          return salesFactGuid;
      }
  
      private void assertSearchResult(AtlasSearchResult searchResult, int expected, String query) {
          assertNotNull(searchResult);
          if (expected == 0) {
              assertTrue(searchResult.getAttributes() == null || CollectionUtils.isEmpty(searchResult.getAttributes().getValues()));
              assertNull(searchResult.getEntities(), query);
          } else if (searchResult.getEntities() != null) {
              assertEquals(searchResult.getEntities().size(), expected, query);
          } else {
              assertNotNull(searchResult.getAttributes());
              assertNotNull(searchResult.getAttributes().getValues());
              assertEquals(searchResult.getAttributes().getValues().size(), expected, query);
          }
      }
  
      private void assertSearchResult(AtlasSearchResult searchResult, AtlasSearchResult.AttributeSearchResult expected) {
          assertNotNull(searchResult);
          AtlasSearchResult.AttributeSearchResult result = searchResult.getAttributes();
          assertNotNull(result);
          assertTrue(result.getName().containsAll(expected.getName()));
          int i = 0;
          for (List<Object> value : result.getValues()) {
              assertTrue(value.containsAll(expected.getValues().get(i)));
              i++;
          }
      }
  
      private void assertAggregationMetrics(AtlasQuickSearchResult searchResult) {
          Map<String, List<AtlasAggregationEntry>> agg = searchResult.getAggregationMetrics();
          assertTrue(CollectionUtils.isNotEmpty(agg.get("__typeName")));
  
          AtlasAggregationEntry entry = agg.get("__typeName").get(0);
          assertTrue(entry != null && entry.getCount() > 0);
      }
  
      private void createDimensionalTaggedEntity(String name) throws AtlasBaseException {
          EntityMutationResponse  resp         = createDummyEntity(name, HIVE_TABLE_TYPE);
          AtlasEntityHeader       entityHeader = resp.getCreatedEntities().get(0);
          String                  guid         = entityHeader.getGuid();
          HashMap<String, Object> attr         = new HashMap<>();
          attr.put("attr1", "value1");
          entityStore.addClassification(Arrays.asList(guid), new AtlasClassification(DIMENSIONAL_CLASSIFICATION, attr));
      }
  
      private void createJapaneseEntityWithDescription() throws AtlasBaseException {
          AtlasEntity entity = new AtlasEntity(HDFS_PATH);
          entity.setAttribute("name", "元帳");
          entity.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, "レシート");
          entity.setAttribute("path", "レシート");
  
          entityStore.createOrUpdate(new AtlasEntityStream(new AtlasEntity.AtlasEntitiesWithExtInfo(entity)), false);
  
          AtlasEntity entity2 = new AtlasEntity(HDFS_PATH);
          entity2.setAttribute("name", "cjk");
          entity2.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, "の台帳");
          entity2.setAttribute("path", "cjk");
  
          entityStore.createOrUpdate(new AtlasEntityStream(new AtlasEntity.AtlasEntitiesWithExtInfo(entity2)), false);
      }
  
      private void assertSearchProcessorWithoutMarker(SearchParameters params, int expected) throws AtlasBaseException {
          assertSearchProcessor(params, expected, false);
      }
  
      private void assertSearchProcessorWithMarker(SearchParameters params, int expected) throws AtlasBaseException {
          assertSearchProcessor(params, expected, true);
      }
  
      private void assertSearchProcessor(SearchParameters params, int expected, boolean checkMarker) throws AtlasBaseException {
          AtlasSearchResult       searchResult  = discoveryService.searchWithParameters(params);
          List<AtlasEntityHeader> entityHeaders = searchResult.getEntities();
  
          assertTrue(CollectionUtils.isNotEmpty(entityHeaders));
          assertEquals(entityHeaders.size(), expected);
  
          if (checkMarker) {
              assertTrue(StringUtils.isNotEmpty(searchResult.getNextMarker()));
          } else {
              assertTrue(StringUtils.isEmpty(searchResult.getNextMarker()));
          }
      }
  }
  