/**
* Copyright (c) Codice Foundation
*
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*
**/
package net.di2e.ecdr.federation;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.util.ThreadContext;
import org.geotools.filter.FilterFactoryImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.sort.SortOrder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.data.ContentType;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.Result;
import ddf.catalog.data.defaultvalues.DefaultAttributeValueRegistryImpl;
import ddf.catalog.data.impl.MetacardImpl;
import ddf.catalog.federation.FederationException;
import ddf.catalog.federation.base.AbstractFederationStrategy;
import ddf.catalog.history.Historian;
import ddf.catalog.impl.CatalogFrameworkImpl;
import ddf.catalog.impl.FrameworkProperties;
import ddf.catalog.impl.MockDelayProvider;
import ddf.catalog.operation.CreateResponse;
import ddf.catalog.operation.Query;
import ddf.catalog.operation.QueryRequest;
import ddf.catalog.operation.QueryResponse;
import ddf.catalog.operation.SourceResponse;
import ddf.catalog.operation.impl.CreateRequestImpl;
import ddf.catalog.operation.impl.QueryImpl;
import ddf.catalog.operation.impl.QueryRequestImpl;
import ddf.catalog.operation.impl.QueryResponseImpl;
import ddf.catalog.plugin.PostFederatedQueryPlugin;
import ddf.catalog.plugin.PreFederatedQueryPlugin;
import ddf.catalog.source.CatalogProvider;
import ddf.catalog.source.IngestException;
import ddf.catalog.source.Source;
import ddf.catalog.source.SourceUnavailableException;
import ddf.catalog.source.UnsupportedQueryException;
import ddf.catalog.util.impl.SourcePoller;
import ddf.catalog.util.impl.SourcePollerRunner;
import ddf.security.service.SecurityManager;
import ddf.security.service.SecurityServiceException;
import ddf.security.Subject;
import net.di2e.ecdr.commons.constants.SearchConstants;
@RunWith( PowerMockRunner.class )
@PrepareForTest( AbstractFederationStrategy.class )
public class FederationStrategyTest {
private static final long SHORT_TIMEOUT = 25;
private static final long LONG_TIMEOUT = 100;
private static final FilterFactory FILTER_FACTORY = new FilterFactoryImpl();
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool( 2 );
private static final Logger LOGGER = LoggerFactory.getLogger( FederationStrategyTest.class.getName() );
/**
* Tests that the framework properly times out using the default federation strategy.
*/
//@Test
public void testQueryTimeout() throws SecurityServiceException{
long queryDelay = 100;
MockDelayProvider provider = new MockDelayProvider( "Provider", "Provider", "v1.0", "DDF", new HashSet<ContentType>(), true, new Date() );
provider.setQueryDelayMillis( queryDelay );
// Mock register the provider in the container
SourcePollerRunner runner = new SourcePollerRunner();
SourcePoller poller = new SourcePoller( runner );
runner.bind( provider );
// Must have more than one thread or sleeps will block the monitor
NormalizingSortedFederationStrategy fedStrategy = new NormalizingSortedFederationStrategy( EXECUTOR, new ArrayList<PreFederatedQueryPlugin>(), new ArrayList<PostFederatedQueryPlugin>(), null );
fedStrategy.setNormalizeResults( false );
FrameworkProperties fwProps = new FrameworkProperties();
fwProps.setCatalogProviders( Collections.singletonList( (CatalogProvider) provider ) );
fwProps.setFederationStrategy( fedStrategy );
fwProps.setSourcePoller( poller );
fwProps.setDefaultAttributeValueRegistry( new DefaultAttributeValueRegistryImpl() );
SecurityManager sm = mock(SecurityManager.class);
Subject smSubject = mock(Subject.class);
when(sm.getSubject(any())).thenReturn(smSubject);
CatalogFrameworkImpl framework = new CatalogFrameworkImpl( fwProps );
framework.setHistorian( new Historian() );
framework.bind( provider );
ThreadContext.bind( new DefaultSecurityManager() );
List<Metacard> metacards = new ArrayList<Metacard>();
MetacardImpl newCard = new MetacardImpl();
newCard.setId( "12345" );
metacards.add( newCard );
CreateResponse createResponse = null;
try {
createResponse = framework.create( new CreateRequestImpl( metacards ) );
} catch ( IngestException e1 ) {
fail();
} catch ( SourceUnavailableException e1 ) {
fail();
}
assertEquals( createResponse.getCreatedMetacards().size(), provider.size() );
for ( Metacard curCard : createResponse.getCreatedMetacards() ) {
assertNotNull( curCard.getId() );
}
QueryImpl query = new QueryImpl( FILTER_FACTORY.equals( FILTER_FACTORY.property( Metacard.ID ), FILTER_FACTORY.literal( createResponse.getCreatedMetacards().get( 0 ).getId() ) ) );
query.setTimeoutMillis( SHORT_TIMEOUT );
query.setSortBy( new FilterFactoryImpl().sort( Result.RELEVANCE, SortOrder.ASCENDING ) );
QueryRequest fedQueryRequest = new QueryRequestImpl( query );
try {
QueryResponse response = framework.query( fedQueryRequest );
assertEquals( "Timeout should happen before results return", 0, response.getHits() );
} catch ( UnsupportedQueryException e ) {
fail();
} catch ( FederationException e ) {
LOGGER.error( "Unexpected federation exception during test", e );
fail();
}
}
@Test
public void testNegativePageSizeQuery() throws Exception {
Query query = mock( Query.class );
when( query.getPageSize() ).thenReturn( -1 );
when( query.getTimeoutMillis() ).thenReturn( LONG_TIMEOUT );
QueryRequest fedQueryRequest = mock( QueryRequest.class );
when( fedQueryRequest.getQuery() ).thenReturn( query );
Result mockResult = mock( Result.class );
SourceResponse mockResponse = mock( SourceResponse.class );
List<Result> results = Arrays.asList( mockResult );
when( mockResponse.getHits() ).thenReturn( (long) results.size() );
when( mockResponse.getResults() ).thenReturn( results );
CatalogProvider mockProvider = mock( CatalogProvider.class );
when( mockProvider.query( any( QueryRequest.class ) ) ).thenReturn( mockResponse );
when( mockProvider.getId() ).thenReturn( "mock provider" );
List<Source> sources = new ArrayList<Source>();
sources.add( mockProvider );
NormalizingSortedFederationStrategy sortedStrategy = new NormalizingSortedFederationStrategy( EXECUTOR, new ArrayList<PreFederatedQueryPlugin>(), new ArrayList<PostFederatedQueryPlugin>(), null );
sortedStrategy.setNormalizeResults( false );
QueryResponse fedResponse = sortedStrategy.federate( sources, fedQueryRequest );
assertEquals( 1, fedResponse.getResults().size() );
}
/**
* Verify that a modified version of the query passed into {@link
* ddf.catalog.federation.AbstractFederationStrategy#federate(List<Source>, QueryRequest)} is used by the sources.
*
* Special results handling done by OffsetResultsHandler.
*
*/
@Test
public void testFederateTwoSourcesOffsetTwoPageSizeThree() throws Exception {
LOGGER.debug( "testFederate_TwoSources_OffsetTwo_PageSizeThree()" );
// Test Setup
Query mockQuery = mock( QueryImpl.class );
// Offset of 2
when( mockQuery.getStartIndex() ).thenReturn( 2 );
// Page size of 3
when( mockQuery.getPageSize() ).thenReturn( 3 );
QueryRequest queryRequest = mock( QueryRequest.class );
when( queryRequest.getQuery() ).thenReturn( mockQuery );
ArgumentCaptor<QueryRequest> argument1 = ArgumentCaptor.forClass( QueryRequest.class );
ArgumentCaptor<QueryRequest> argument2 = ArgumentCaptor.forClass( QueryRequest.class );
/**
* When using a modified query to query the sources, the desired offset and page size are NOT used. So, the
* results returned by each source start at index 1 and end at (offset + pageSize - 1).
*
* Number of results returned by each source = offset + pageSize - 1 4 = 2 + 3 - 1
*/
Result mockSource1Result1 = mock( Result.class );
Result mockSource1Result2 = mock( Result.class );
Result mockSource1Result3 = mock( Result.class );
Result mockSource1Result4 = mock( Result.class );
SourceResponse mockSource1Response = mock( SourceResponse.class );
List<Result> mockSource1Results = Arrays.asList( mockSource1Result1, mockSource1Result2, mockSource1Result3, mockSource1Result4 );
when( mockSource1Response.getResults() ).thenReturn( mockSource1Results );
Source mockSource1 = mock( Source.class );
when( mockSource1.query( any( QueryRequest.class ) ) ).thenReturn( mockSource1Response );
when( mockSource1.getId() ).thenReturn( "####### MOCK SOURCE 1.3 #######" );
/**
* When using a modified query to query the sources, the desired offset and page size are NOT used. So, the
* results returned by each source start at index 1 and end at (offset + pageSize - 1).
*
* Number of results returned by each source = offset + pageSize - 1 4 = 2 + 3 - 1
*/
Result mockSource2Result1 = mock( Result.class );
Result mockSource2Result2 = mock( Result.class );
Result mockSource2Result3 = mock( Result.class );
Result mockSource2Result4 = mock( Result.class );
SourceResponse mockSource2Response = mock( SourceResponse.class );
List<Result> mockSource2Results = Arrays.asList( mockSource2Result1, mockSource2Result2, mockSource2Result3, mockSource2Result4 );
when( mockSource2Response.getResults() ).thenReturn( mockSource2Results );
Source mockSource2 = mock( Source.class );
when( mockSource2.query( any( QueryRequest.class ) ) ).thenReturn( mockSource2Response );
when( mockSource2.getId() ).thenReturn( "####### MOCK SOURCE 2.3 #######" );
// Two sources
List<Source> sources = new ArrayList<Source>( 2 );
sources.add( mockSource1 );
sources.add( mockSource2 );
Result mockSortedResult1 = mock( Result.class );
Result mockSortedResult2 = mock( Result.class );
Result mockSortedResult3 = mock( Result.class );
Result mockSortedResult4 = mock( Result.class );
Result mockSortedResult5 = mock( Result.class );
Result mockSortedResult6 = mock( Result.class );
Result mockSortedResult7 = mock( Result.class );
Result mockSortedResult8 = mock( Result.class );
List<Result> mockSortedResults = Arrays.asList( mockSortedResult1, mockSortedResult2, mockSortedResult3, mockSortedResult4, mockSortedResult5, mockSortedResult6, mockSortedResult7,
mockSortedResult8 );
QueryResponseImpl mockOriginalResults = Mockito.mock( QueryResponseImpl.class );
// Return true for the number of mockSortedResults
Mockito.when( mockOriginalResults.hasMoreResults() ).thenReturn( true, true, true, true, true, true, true, true, false );
Mockito.when( mockOriginalResults.getResults() ).thenReturn( mockSortedResults );
// Returns the sorted results from both sources (4 + 4 = 8)
Mockito.when( mockOriginalResults.take() ).thenReturn( mockSortedResult1, mockSortedResult2, mockSortedResult3, mockSortedResult4, mockSortedResult5, mockSortedResult6, mockSortedResult7,
mockSortedResult8 );
QueryResponseImpl offsetResultQueue = new QueryResponseImpl( queryRequest, null );
PowerMockito.whenNew( QueryResponseImpl.class ).withArguments( queryRequest, (Map<String, Serializable>) null ).thenReturn( mockOriginalResults, offsetResultQueue );
NormalizingSortedFederationStrategy strategy = new NormalizingSortedFederationStrategy( EXECUTOR, new ArrayList<PreFederatedQueryPlugin>(), new ArrayList<PostFederatedQueryPlugin>(), null );
strategy.setNormalizeResults( false );
// Run Test
QueryResponse federatedResponse = strategy.federate( sources, queryRequest );
// Verification
assertNotNull( federatedResponse );
verify( mockSource1 ).query( argument1.capture() );
// The modified query should have a start index of 1 and an end index of offset + pageSize -
// 1
assertEquals( 1, argument1.getValue().getQuery().getStartIndex() );
assertEquals( 4, argument1.getValue().getQuery().getPageSize() );
verify( mockSource2 ).query( argument2.capture() );
assertThat( mockQuery, not( argument2.getValue().getQuery() ) );
// The modified query should have a start index of 1 and an end index of offset + pageSize -
// 1
assertEquals( 1, argument2.getValue().getQuery().getStartIndex() );
assertEquals( 4, argument2.getValue().getQuery().getPageSize() );
/**
* Verify three results (page size) are returned. The sorted results returned by the sources do NOT have the
* offset and page size taken into account, so the offset and page size are applied to the sorted results in the
* OffsetResultHandler.
*
* Offset of 2 (start at result 2) and page size of 3 (end at result 4).
*/
LOGGER.debug( "mockSortedResult1: " + mockSortedResult1 );
LOGGER.debug( "mockSortedResult2: " + mockSortedResult2 );
LOGGER.debug( "mockSortedResult3: " + mockSortedResult3 );
LOGGER.debug( "mockSortedResult4: " + mockSortedResult4 );
assertEquals( 3, federatedResponse.getResults().size() );
assertEquals( mockSortedResult2, federatedResponse.getResults().get( 0 ) );
assertEquals( mockSortedResult3, federatedResponse.getResults().get( 1 ) );
assertEquals( mockSortedResult4, federatedResponse.getResults().get( 2 ) );
for ( Result result : federatedResponse.getResults() ) {
LOGGER.debug( "federated response result: " + result );
}
}
/**
* Verify that the original query passed into {@link
* ddf.catalog.federation.AbstractFederationStrategy#federate(List<Source>, QueryRequest)} is used by the source.
*
* No special results handling done by OffsetResultsHandler.
*/
@Test
public void testFederateOneSourceOffsetTwoPageSizeTwo() throws Exception {
LOGGER.debug( "testFederate_OneSource_OffsetTwo_PageSizeTwo()" );
// Test Setup
Query mockQuery = mock( QueryImpl.class );
// Offset of 2
when( mockQuery.getStartIndex() ).thenReturn( 2 );
// Page size of 2
when( mockQuery.getPageSize() ).thenReturn( 2 );
QueryRequest queryRequest = mock( QueryRequest.class );
when( queryRequest.getQuery() ).thenReturn( mockQuery );
// ArgumentCaptor<QueryRequest> argument = ArgumentCaptor.forClass(QueryRequest.class);
/**
* When using the original query to query the source, the desired offset and page size are used. So, the results
* returned by the source already have the offset and page size taken into account.
*/
Result mockResult1 = mock( Result.class );
Result mockResult2 = mock( Result.class );
SourceResponse mockSourceResponse = mock( SourceResponse.class );
List<Result> results = Arrays.asList( mockResult1, mockResult2 );
when( mockSourceResponse.getResults() ).thenReturn( results );
Source mockSource1 = mock( Source.class );
when( mockSource1.query( any( QueryRequest.class ) ) ).thenReturn( mockSourceResponse );
when( mockSource1.getId() ).thenReturn( "####### MOCK SOURCE 1.1 #######" );
// Only one source
List<Source> sources = new ArrayList<Source>( 1 );
sources.add( mockSource1 );
NormalizingSortedFederationStrategy strategy = new NormalizingSortedFederationStrategy( EXECUTOR, new ArrayList<PreFederatedQueryPlugin>(), new ArrayList<PostFederatedQueryPlugin>(), null );
strategy.setNormalizeResults( false );
// Run Test
QueryResponse federatedResponse = strategy.federate( sources, queryRequest );
// Verification
assertNotNull( federatedResponse );
LOGGER.debug( "Federated response result size: " + federatedResponse.getResults().size() );
/**
* Verify two results (page size) are returned. The results returned by the source already have the offset and
* page size taken into account, so we can verify that the lists match.
*/
assertEquals( 2, federatedResponse.getResults().size() );
assertEquals( mockResult1, federatedResponse.getResults().get( 0 ) );
assertEquals( mockResult2, federatedResponse.getResults().get( 1 ) );
LOGGER.debug( "mockResult1: " + mockResult1 );
LOGGER.debug( "mockResult2: " + mockResult2 );
for ( Result result : federatedResponse.getResults() ) {
LOGGER.debug( "result: " + result );
}
}
/**
* Verify that the original query passed into {@link
* ddf.catalog.federation.AbstractFederationStrategy#federate(List<Source>, QueryRequest)} is used by the sources.
*
* No special results handling done by OffsetResultsHandler.
*/
@Test
public void testFederateTwoSourcesOffsetOnePageSizeThree() throws Exception {
LOGGER.debug( "testFederate_TwoSources_OffsetOne_PageSizeThree()" );
// Test Setup
Query mockQuery = mock( QueryImpl.class );
// Offset of 1
when( mockQuery.getStartIndex() ).thenReturn( 1 );
// Page size of 3
when( mockQuery.getPageSize() ).thenReturn( 3 );
QueryRequest queryRequest = mock( QueryRequest.class );
when( queryRequest.getQuery() ).thenReturn( mockQuery );
/**
* When using the original query to query the sources, the desired offset and page size are used. So, the
* results returned by the sources already have the offset and page size taken into account.
*/
Result mockSource1Result1 = mock( Result.class );
Mockito.when( mockSource1Result1.getRelevanceScore() ).thenReturn( 0.7 );
Result mockSource1Result2 = mock( Result.class );
Mockito.when( mockSource1Result2.getRelevanceScore() ).thenReturn( 0.5 );
Result mockSource1Result3 = mock( Result.class );
Mockito.when( mockSource1Result3.getRelevanceScore() ).thenReturn( 0.3 );
Result mockSource1Result4 = mock( Result.class );
Mockito.when( mockSource1Result4.getRelevanceScore() ).thenReturn( 0.1 );
SourceResponse mockSource1Response = mock( SourceResponse.class );
List<Result> mockSource1Results = Arrays.asList( mockSource1Result1, mockSource1Result2, mockSource1Result3, mockSource1Result4 );
when( mockSource1Response.getResults() ).thenReturn( mockSource1Results );
Source mockSource1 = mock( Source.class );
when( mockSource1.query( any( QueryRequest.class ) ) ).thenReturn( mockSource1Response );
when( mockSource1.getId() ).thenReturn( "####### MOCK SOURCE 1.4 #######" );
Result mockSource2Result1 = mock( Result.class );
Mockito.when( mockSource2Result1.getRelevanceScore() ).thenReturn( 0.8 );
Result mockSource2Result2 = mock( Result.class );
Mockito.when( mockSource2Result2.getRelevanceScore() ).thenReturn( 0.6 );
Result mockSource2Result3 = mock( Result.class );
Mockito.when( mockSource2Result3.getRelevanceScore() ).thenReturn( 0.4 );
Result mockSource2Result4 = mock( Result.class );
Mockito.when( mockSource2Result4.getRelevanceScore() ).thenReturn( 0.2 );
SourceResponse mockSource2Response = mock( SourceResponse.class );
List<Result> mockSource2Results = Arrays.asList( mockSource2Result1, mockSource2Result2, mockSource2Result3, mockSource2Result4 );
when( mockSource2Response.getResults() ).thenReturn( mockSource2Results );
Source mockSource2 = mock( Source.class );
when( mockSource2.query( any( QueryRequest.class ) ) ).thenReturn( mockSource2Response );
when( mockSource2.getId() ).thenReturn( "####### MOCK SOURCE 2.4 #######" );
// Two sources
List<Source> sources = new ArrayList<Source>( 2 );
sources.add( mockSource1 );
sources.add( mockSource2 );
NormalizingSortedFederationStrategy strategy = new NormalizingSortedFederationStrategy( EXECUTOR, new ArrayList<PreFederatedQueryPlugin>(), new ArrayList<PostFederatedQueryPlugin>(), null );
strategy.setNormalizeResults( false );
// Run Test
QueryResponse federatedResponse = strategy.federate( sources, queryRequest );
// Verification
assertNotNull( federatedResponse );
LOGGER.debug( "Federated response result size: " + federatedResponse.getResults().size() );
/**
* Verify three results (page size) are returned. Since we are using mock Results, the relevance score is 0.0,
* and the merged and sorted results of both sources is mockSource2Result1, mockSource1Result1,
* mockSource2Result2, mockSource1Result2, mockSource2Result3, mockSource1Result3, mockSource2Result4,
* mockSource1Result4. So, the results are mockSource2Result1, mockSource1Result1, mockSource2Result2. No need
* to use OffsetResultHander in this case.
*/
assertEquals( 3, federatedResponse.getResults().size() );
assertEquals( mockSource2Result1, federatedResponse.getResults().get( 0 ) );
assertEquals( mockSource1Result1, federatedResponse.getResults().get( 1 ) );
assertEquals( mockSource2Result2, federatedResponse.getResults().get( 2 ) );
LOGGER.debug( "mockSource2Result1: " + mockSource2Result1 );
LOGGER.debug( "mockSource1Result1: " + mockSource1Result1 );
LOGGER.debug( "mockSource2Result2: " + mockSource2Result2 );
for ( Result result : federatedResponse.getResults() ) {
LOGGER.debug( "federated response result: " + result );
}
// Check the responseProperties
List<String> siteList = (List) federatedResponse.getPropertyValue( SearchConstants.SITE_LIST );
assertTrue( siteList.contains( "####### MOCK SOURCE 2.4 #######" ) );
Map<String, Serializable> siteProperties = (Map) federatedResponse.getPropertyValue( "####### MOCK SOURCE 2.4 #######" );
assertNotNull( siteProperties.get( SearchConstants.TOTAL_HITS ) );
assertNotNull( siteProperties.get( SearchConstants.TOTAL_RESULTS_RETURNED ) );
assertTrue( siteList.contains( "####### MOCK SOURCE 2.4 #######" ) );
siteProperties = (Map) federatedResponse.getPropertyValue( "####### MOCK SOURCE 1.4 #######" );
assertNotNull( siteProperties.get( SearchConstants.TOTAL_HITS ) );
assertNotNull( siteProperties.get( SearchConstants.TOTAL_RESULTS_RETURNED ) );
}
/**
* Verify that the original query passed into {@link
* ddf.catalog.federation.AbstractFederationStrategy#federate(List<Source>, QueryRequest)} is used by the source.
*
* No special results handling done by OffsetResultsHandler.
*/
@Test
public void testFederateOneSourceOffsetOnePageSizeTwo() throws Exception {
LOGGER.debug( "testFederate_OneSource_OffsetOne_PageSizeTwo()" );
// Test Setup
Query mockQuery = mock( QueryImpl.class );
// Offset of 1
when( mockQuery.getStartIndex() ).thenReturn( 1 );
// Page size of 2
when( mockQuery.getPageSize() ).thenReturn( 2 );
QueryRequest queryRequest = mock( QueryRequest.class );
when( queryRequest.getQuery() ).thenReturn( mockQuery );
/**
* When using the original query to query the source, the desired offset and page size are used. So, the results
* returned by the source already have the offset and page size taken into account.
*/
Result mockResult1 = mock( Result.class );
Result mockResult2 = mock( Result.class );
SourceResponse mockSourceResponse = mock( SourceResponse.class );
List<Result> results = Arrays.asList( mockResult1, mockResult2 );
when( mockSourceResponse.getResults() ).thenReturn( results );
Source mockSource1 = mock( Source.class );
when( mockSource1.query( any( QueryRequest.class ) ) ).thenReturn( mockSourceResponse );
when( mockSource1.getId() ).thenReturn( "####### MOCK SOURCE 1.2 #######" );
// Only one source
List<Source> sources = new ArrayList<Source>( 1 );
sources.add( mockSource1 );
NormalizingSortedFederationStrategy strategy = new NormalizingSortedFederationStrategy( EXECUTOR, new ArrayList<PreFederatedQueryPlugin>(), new ArrayList<PostFederatedQueryPlugin>(), null );
strategy.setNormalizeResults( false );
// Run Test
QueryResponse federatedResponse = strategy.federate( sources, queryRequest );
// Verification
assertNotNull( federatedResponse );
LOGGER.debug( "Federated response result size: " + federatedResponse.getResults().size() );
/**
* Verify two results (page size) are returned. The results returned by the source already have the offset and
* page size taken into account, so we can verify that the lists match.
*/
assertEquals( 2, federatedResponse.getResults().size() );
assertEquals( mockResult1, federatedResponse.getResults().get( 0 ) );
assertEquals( mockResult2, federatedResponse.getResults().get( 1 ) );
LOGGER.debug( "mockResult1: " + mockResult1 );
LOGGER.debug( "mockResult2: " + mockResult2 );
for ( Result result : federatedResponse.getResults() ) {
LOGGER.debug( "result: " + result );
}
// Check the responseProperties
assertEquals( "####### MOCK SOURCE 1.2 #######", ((List) federatedResponse.getPropertyValue( SearchConstants.SITE_LIST )).get( 0 ) );
Map<String, Serializable> siteProperties = (Map) federatedResponse.getPropertyValue( "####### MOCK SOURCE 1.2 #######" );
assertNotNull( siteProperties.get( SearchConstants.TOTAL_HITS ) );
assertNotNull( siteProperties.get( SearchConstants.TOTAL_RESULTS_RETURNED ) );
}
private void configureMockForSecurityManager(SecurityManager sm) {
mockStatic(FrameworkUtil.class);
Bundle bundle = mock(Bundle.class);
when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(bundle);
BundleContext bc = mock(BundleContext.class);
when(bundle.getBundleContext()).thenReturn(bc);
ServiceReference ref = mock(ServiceReference.class);
when(bc.getServiceReference(any(Class.class))).thenReturn(ref);
when(bc.getService(ref)).thenReturn( sm);
}
}