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