@SuppressWarnings("unchecked")
  @Test
  public void setSearchRequestIndicesAndTypes_sysTypeFilter() throws ReflectiveOperationException {
    ConfigService configService = mockConfigurationService();

    SearchService tested = getTested(configService);
    Mockito.when(tested.authenticationUtilService.isAuthenticatedUser()).thenReturn(false);

    QuerySettings querySettings = new QuerySettings();
    Filters filters = new Filters();
    querySettings.setFilters(filters);

    tested.parsedFilterConfigService.prepareFiltersForRequest(filters);

    SearchRequestBuilder searchRequestBuilderMock = Mockito.mock(SearchRequestBuilder.class);

    filters = new Filters();
    querySettings.setFilters(filters);
    // case - sys_type filter used
    {
      Mockito.reset(tested.providerService, searchRequestBuilderMock, tested.indexNamesCache);
      Mockito.when(tested.indexNamesCache.get(Mockito.anyString())).thenReturn(null);
      Set<String> sysTypesRequested = new HashSet<>();
      sysTypesRequested.add("issue");
      filters.acknowledgeUrlFilterCandidate("sys_type", new ArrayList<>(sysTypesRequested));
      tested.parsedFilterConfigService.prepareFiltersForRequest(filters);

      mockProviderConfiguration(tested, "/search/provider_1.json", "/search/provider_2.json");

      tested.setSearchRequestIndicesAndTypes(querySettings, searchRequestBuilderMock);
      Mockito.verify(tested.indexNamesCache)
          .get(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false));
      Mockito.verify(tested.indexNamesCache)
          .put(
              Mockito.eq(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false)),
              Mockito.anySet());
      Mockito.verifyNoMoreInteractions(tested.indexNamesCache);
      Mockito.verify(tested.providerService).getAll();
      Mockito.verify(searchRequestBuilderMock)
          .setIndices("idx_provider1_issue", "idx_provider2_issue1", "idx_provider2_issue2");
      Mockito.verifyNoMoreInteractions(searchRequestBuilderMock);
    }

    // case - sys_type filter used but unknown
    {
      Mockito.reset(tested.providerService, searchRequestBuilderMock, tested.indexNamesCache);
      Mockito.when(tested.indexNamesCache.get(Mockito.anyString())).thenReturn(null);
      Set<String> sysTypesRequested = new HashSet<>();
      sysTypesRequested.add("unknowntype");
      filters.acknowledgeUrlFilterCandidate("sys_type", new ArrayList<>(sysTypesRequested));
      tested.parsedFilterConfigService.prepareFiltersForRequest(filters);

      mockProviderConfiguration(tested, "/search/provider_1.json", "/search/provider_2.json");
      try {
        tested.setSearchRequestIndicesAndTypes(querySettings, searchRequestBuilderMock);
        Assert.fail("IllegalArgumentException expected");
      } catch (IllegalArgumentException e) {
        Assert.assertEquals("Unsupported content sys_type", e.getMessage());
        Mockito.verify(tested.indexNamesCache)
            .get(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false));
        Mockito.verify(tested.providerService).getAll();
        Mockito.verifyNoMoreInteractions(
            searchRequestBuilderMock, tested.providerService, tested.indexNamesCache);
      }
    }

    // case - sys_type filter used - type with search_all_excluded=true can be used if named
    {
      Mockito.reset(tested.providerService, searchRequestBuilderMock, tested.indexNamesCache);
      Mockito.when(tested.indexNamesCache.get(Mockito.anyString())).thenReturn(null);
      Set<String> sysTypesRequested = new HashSet<>();
      sysTypesRequested.add("cosi");
      filters.acknowledgeUrlFilterCandidate("sys_type", new ArrayList<>(sysTypesRequested));
      tested.parsedFilterConfigService.prepareFiltersForRequest(filters);
      mockProviderConfiguration(tested, "/search/provider_1.json", "/search/provider_2.json");

      tested.setSearchRequestIndicesAndTypes(querySettings, searchRequestBuilderMock);
      Mockito.verify(tested.indexNamesCache)
          .get(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false));
      Mockito.verify(tested.indexNamesCache)
          .put(
              Mockito.eq(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false)),
              Mockito.anySet());
      Mockito.verifyNoMoreInteractions(tested.indexNamesCache);
      Mockito.verify(tested.providerService).getAll();
      Mockito.verify(searchRequestBuilderMock)
          .setIndices(
              "idx_provider1_cosi1",
              "idx_provider1_cosi2",
              "idx_provider2_cosi1",
              "idx_provider2_cosi2");
      Mockito.verifyNoMoreInteractions(searchRequestBuilderMock);
    }

    // case - sys_type filter used with multiple values, no facet
    {
      Mockito.reset(tested.providerService, searchRequestBuilderMock, tested.indexNamesCache);
      Mockito.when(tested.indexNamesCache.get(Mockito.anyString())).thenReturn(null);
      Set<String> sysTypesRequested = new HashSet<>();
      sysTypesRequested.add("issue");
      sysTypesRequested.add("cosi");
      filters.acknowledgeUrlFilterCandidate("sys_type", new ArrayList<>(sysTypesRequested));
      tested.parsedFilterConfigService.prepareFiltersForRequest(filters);
      mockProviderConfiguration(tested, "/search/provider_1.json", "/search/provider_2.json");

      tested.setSearchRequestIndicesAndTypes(querySettings, searchRequestBuilderMock);
      Mockito.verify(tested.indexNamesCache)
          .get(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false));
      Mockito.verify(tested.indexNamesCache)
          .put(
              Mockito.eq(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false)),
              Mockito.anySet());
      Mockito.verifyNoMoreInteractions(tested.indexNamesCache);
      Mockito.verify(tested.providerService).getAll();
      Mockito.verify(searchRequestBuilderMock)
          .setIndices(
              "idx_provider1_issue",
              "idx_provider1_cosi1",
              "idx_provider1_cosi2",
              "idx_provider2_issue1",
              "idx_provider2_issue2",
              "idx_provider2_cosi1",
              "idx_provider2_cosi2");
      Mockito.verifyNoMoreInteractions(searchRequestBuilderMock);
    }

    // case - sys_type filter used with PER_SYS_TYPE_COUNTS facet. 'cosi' indexes are not included
    // because
    // "search_all_excluded" : "true"
    {
      Mockito.reset(tested.providerService, searchRequestBuilderMock, tested.indexNamesCache);
      Mockito.when(tested.indexNamesCache.get(Mockito.anyString())).thenReturn(null);
      Set<String> sysTypesRequested = new HashSet<>();
      sysTypesRequested.add("issue");
      filters.acknowledgeUrlFilterCandidate("sys_type", new ArrayList<>(sysTypesRequested));
      tested.parsedFilterConfigService.prepareFiltersForRequest(filters);
      querySettings.addFacet("per_sys_type_counts");
      mockProviderConfiguration(tested, "/search/provider_1.json", "/search/provider_2.json");

      tested.setSearchRequestIndicesAndTypes(querySettings, searchRequestBuilderMock);
      Mockito.verify(tested.indexNamesCache)
          .get(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, true));
      Mockito.verify(tested.indexNamesCache)
          .put(
              Mockito.eq(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, true)),
              Mockito.anySet());
      Mockito.verifyNoMoreInteractions(tested.indexNamesCache);
      Mockito.verify(tested.providerService).getAll();
      Mockito.verify(searchRequestBuilderMock)
          .setIndices(
              "idx_provider1_issue",
              "idx_provider1_mailing1",
              "idx_provider1_mailing2",
              "idx_provider2_issue1",
              "idx_provider2_issue2",
              "idx_provider2_mailing");
      Mockito.verifyNoMoreInteractions(searchRequestBuilderMock);
      querySettings.getFacets().clear();
    }

    // case - sys_type filter used with PER_SYS_TYPE_COUNTS facet. 'cosi' indexes included even
    // "search_all_excluded" : "true" because requested
    {
      Mockito.reset(tested.providerService, searchRequestBuilderMock, tested.indexNamesCache);
      Mockito.when(tested.indexNamesCache.get(Mockito.anyString())).thenReturn(null);
      Set<String> sysTypesRequested = new HashSet<>();
      sysTypesRequested.add("issue");
      sysTypesRequested.add("cosi");
      filters.acknowledgeUrlFilterCandidate("sys_type", new ArrayList<>(sysTypesRequested));
      tested.parsedFilterConfigService.prepareFiltersForRequest(filters);
      querySettings.addFacet("per_sys_type_counts");
      mockProviderConfiguration(tested, "/search/provider_1.json", "/search/provider_2.json");

      tested.setSearchRequestIndicesAndTypes(querySettings, searchRequestBuilderMock);
      Mockito.verify(tested.indexNamesCache)
          .get(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, true));
      Mockito.verify(tested.indexNamesCache)
          .put(
              Mockito.eq(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, true)),
              Mockito.anySet());
      Mockito.verifyNoMoreInteractions(tested.indexNamesCache);
      Mockito.verify(tested.providerService).getAll();
      Mockito.verify(searchRequestBuilderMock)
          .setIndices(
              "idx_provider1_issue",
              "idx_provider1_mailing1",
              "idx_provider1_mailing2",
              "idx_provider1_cosi1",
              "idx_provider1_cosi2",
              "idx_provider2_issue1",
              "idx_provider2_issue2",
              "idx_provider2_mailing",
              "idx_provider2_cosi1",
              "idx_provider2_cosi2");
      Mockito.verifyNoMoreInteractions(searchRequestBuilderMock);
      querySettings.getFacets().clear();
    }

    // case - sys_type filter used with multiple values - cache hit
    {
      Mockito.reset(tested.providerService, searchRequestBuilderMock, tested.indexNamesCache);
      Set<String> cachedIdxNames = new HashSet<>();
      cachedIdxNames.add("idx_provider1_cosi1");
      cachedIdxNames.add("idx_provider1_cosi2");
      cachedIdxNames.add("idx_provider1_issue");
      Mockito.when(tested.indexNamesCache.get(Mockito.anyString())).thenReturn(cachedIdxNames);
      Set<String> sysTypesRequested = new HashSet<>();
      sysTypesRequested.add("issue");
      sysTypesRequested.add("cosi");
      filters.acknowledgeUrlFilterCandidate("sys_type", new ArrayList<>(sysTypesRequested));
      tested.parsedFilterConfigService.prepareFiltersForRequest(filters);
      mockProviderConfiguration(tested, "/search/provider_1.json", "/search/provider_2.json");

      tested.setSearchRequestIndicesAndTypes(querySettings, searchRequestBuilderMock);

      Mockito.verify(tested.indexNamesCache)
          .get(SearchService.prepareIndexNamesCacheKey(sysTypesRequested, false));
      Mockito.verifyNoMoreInteractions(tested.indexNamesCache);
      Mockito.verifyZeroInteractions(tested.providerService);
      Mockito.verify(searchRequestBuilderMock)
          .setIndices("idx_provider1_cosi1", "idx_provider1_cosi2", "idx_provider1_issue");
      Mockito.verifyNoMoreInteractions(searchRequestBuilderMock);
    }
  }