@@ -5060,4 +5060,111 @@ mod tests {
50605060 assert_eq ! ( search_response. failed_splits. len( ) , 1 ) ;
50615061 Ok ( ( ) )
50625062 }
5063+
5064+ #[ tokio:: test]
5065+ async fn test_count_from_metastore_in_contained_time_range ( ) -> anyhow:: Result < ( ) > {
5066+ let search_request = quickwit_proto:: search:: SearchRequest {
5067+ start_timestamp : Some ( 122_000 ) ,
5068+ end_timestamp : Some ( 129_000 ) ,
5069+ index_id_patterns : vec ! [ "test-index" . to_string( ) ] ,
5070+ query_ast : serde_json:: to_string ( & QueryAst :: MatchAll )
5071+ . expect ( "MatchAll should be JSON serializable." ) ,
5072+ max_hits : 0 ,
5073+ ..Default :: default ( )
5074+ } ;
5075+
5076+ let index_metadata = IndexMetadata :: for_test ( "test-index" , "ram:///test-index" ) ;
5077+ let index_uid = index_metadata. index_uid . clone ( ) ;
5078+
5079+ let mut mock_metastore = MockMetastoreService :: new ( ) ;
5080+ mock_metastore
5081+ . expect_list_indexes_metadata ( )
5082+ . returning ( move |_q| {
5083+ Ok ( ListIndexesMetadataResponse :: for_test ( vec ! [
5084+ index_metadata. clone( ) ,
5085+ ] ) )
5086+ } ) ;
5087+ mock_metastore. expect_list_splits ( ) . returning ( move |_req| {
5088+ let splits = vec ! [
5089+ MockSplitBuilder :: new_with_time_range( "split_before" , Some ( 100_000 ..=110_000 ) )
5090+ . with_index_uid( & index_uid)
5091+ . build( ) ,
5092+ MockSplitBuilder :: new_with_time_range(
5093+ "split_overlap_start" ,
5094+ Some ( 120_000 ..=123_000 ) ,
5095+ )
5096+ . with_index_uid( & index_uid)
5097+ . build( ) ,
5098+ MockSplitBuilder :: new_with_time_range( "split_overlap_end" , Some ( 128_000 ..=140_000 ) )
5099+ . with_index_uid( & index_uid)
5100+ . build( ) ,
5101+ MockSplitBuilder :: new_with_time_range(
5102+ "split_covering_whole" ,
5103+ Some ( 100_000 ..=200_000 ) ,
5104+ )
5105+ . with_index_uid( & index_uid)
5106+ . build( ) ,
5107+ MockSplitBuilder :: new_with_time_range( "split_inside" , Some ( 124_000 ..=126_000 ) )
5108+ . with_index_uid( & index_uid)
5109+ . build( ) ,
5110+ ] ;
5111+ let resp = ListSplitsResponse :: try_from_splits ( splits) . unwrap ( ) ;
5112+ Ok ( ServiceStream :: from ( vec ! [ Ok ( resp) ] ) )
5113+ } ) ;
5114+
5115+ let mut mock_search = MockSearchService :: new ( ) ;
5116+ mock_search
5117+ . expect_leaf_search ( )
5118+ . withf ( |leaf_search_req| {
5119+ let mut expected = HashSet :: new ( ) ;
5120+
5121+ // Notice split_inside is not included.
5122+ expected. insert ( "split_before" ) ;
5123+ expected. insert ( "split_covering_whole" ) ;
5124+ expected. insert ( "split_overlap_end" ) ;
5125+ expected. insert ( "split_overlap_start" ) ;
5126+
5127+ leaf_search_req. leaf_requests . len ( ) == 1
5128+ && leaf_search_req. leaf_requests [ 0 ]
5129+ . split_offsets
5130+ . iter ( )
5131+ . map ( |s| s. split_id . as_str ( ) )
5132+ . collect :: < HashSet < & str > > ( )
5133+ == expected
5134+ } )
5135+ . times ( 1 )
5136+ . returning ( |_| {
5137+ Ok ( quickwit_proto:: search:: LeafSearchResponse {
5138+ num_hits : 5 ,
5139+ partial_hits : vec ! [ ] ,
5140+ failed_splits : Vec :: new ( ) ,
5141+ num_attempted_splits : 0 ,
5142+ ..Default :: default ( )
5143+ } )
5144+ } ) ;
5145+ mock_search. expect_fetch_docs ( ) . returning ( |fetch_req| {
5146+ Ok ( quickwit_proto:: search:: FetchDocsResponse {
5147+ hits : get_doc_for_fetch_req ( fetch_req) ,
5148+ } )
5149+ } ) ;
5150+
5151+ let searcher_pool = searcher_pool_for_test ( [ ( "127.0.0.1:1001" , mock_search) ] ) ;
5152+ let search_job_placer = SearchJobPlacer :: new ( searcher_pool) ;
5153+ let cluster_client = ClusterClient :: new ( search_job_placer) ;
5154+
5155+ let ctx = SearcherContext :: for_test ( ) ;
5156+ let resp = root_search (
5157+ & ctx,
5158+ search_request,
5159+ MetastoreServiceClient :: from_mock ( mock_metastore) ,
5160+ & cluster_client,
5161+ )
5162+ . await ?;
5163+
5164+ assert_eq ! ( resp. num_hits, 15 ) ;
5165+ assert_eq ! ( resp. hits. len( ) , 0 ) ;
5166+ assert_eq ! ( resp. num_successful_splits, 1 ) ;
5167+
5168+ Ok ( ( ) )
5169+ }
50635170}
0 commit comments