Skip to content

Commit 926a2f3

Browse files
committed
Add test to search splits contained in time range
1 parent f3ab102 commit 926a2f3

File tree

2 files changed

+126
-3
lines changed

2 files changed

+126
-3
lines changed

quickwit/quickwit-indexing/src/test_utils.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
use std::num::NonZeroUsize;
16+
use std::ops::RangeInclusive;
1617
use std::str::FromStr;
1718
use std::sync::Arc;
1819
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -251,8 +252,16 @@ pub struct MockSplitBuilder {
251252

252253
impl MockSplitBuilder {
253254
pub fn new(split_id: &str) -> Self {
255+
Self::new_with_time_range(split_id, Some(121000..=130198))
256+
}
257+
258+
pub fn new_with_time_range(split_id: &str, time_range: Option<RangeInclusive<i64>>) -> Self {
254259
Self {
255-
split_metadata: mock_split_meta(split_id, &IndexUid::for_test("test-index", 0)),
260+
split_metadata: mock_split_meta(
261+
split_id,
262+
&IndexUid::for_test("test-index", 0),
263+
time_range,
264+
),
256265
}
257266
}
258267

@@ -277,14 +286,18 @@ pub fn mock_split(split_id: &str) -> Split {
277286
}
278287

279288
/// Mock split meta helper.
280-
pub fn mock_split_meta(split_id: &str, index_uid: &IndexUid) -> SplitMetadata {
289+
pub fn mock_split_meta(
290+
split_id: &str,
291+
index_uid: &IndexUid,
292+
time_range: Option<RangeInclusive<i64>>,
293+
) -> SplitMetadata {
281294
SplitMetadata {
282295
index_uid: index_uid.clone(),
283296
split_id: split_id.to_string(),
284297
partition_id: 13u64,
285298
num_docs: if split_id == "split1" { 1_000_000 } else { 10 },
286299
uncompressed_docs_size_in_bytes: 256,
287-
time_range: Some(121000..=130198),
300+
time_range,
288301
create_timestamp: 0,
289302
footer_offsets: 700..800,
290303
..Default::default()

quickwit/quickwit-search/src/root.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5076,4 +5076,114 @@ mod tests {
50765076
assert_eq!(search_response.failed_splits.len(), 1);
50775077
Ok(())
50785078
}
5079+
5080+
#[tokio::test]
5081+
async fn test_count_from_metastore_in_contained_time_range() -> anyhow::Result<()> {
5082+
let search_request = quickwit_proto::search::SearchRequest {
5083+
start_timestamp: Some(122_000),
5084+
end_timestamp: Some(129_000),
5085+
index_id_patterns: vec!["test-index".to_string()],
5086+
query_ast: serde_json::to_string(&QueryAst::MatchAll)
5087+
.expect("MatchAll should be JSON serializable."),
5088+
max_hits: 0,
5089+
..Default::default()
5090+
};
5091+
5092+
let index_metadata = IndexMetadata::for_test("test-index", "ram:///test-index");
5093+
let index_uid = index_metadata.index_uid.clone();
5094+
5095+
let mut mock_metastore = MockMetastoreService::new();
5096+
mock_metastore
5097+
.expect_list_indexes_metadata()
5098+
.returning(move |_q| {
5099+
Ok(ListIndexesMetadataResponse::for_test(vec![
5100+
index_metadata.clone(),
5101+
]))
5102+
});
5103+
mock_metastore.expect_list_splits().returning(move |_req| {
5104+
let splits = vec![
5105+
MockSplitBuilder::new_with_time_range("split_before", Some(100_000..=110_000))
5106+
.with_index_uid(&index_uid)
5107+
.build(),
5108+
MockSplitBuilder::new_with_time_range(
5109+
"split_overlap_start",
5110+
Some(120_000..=123_000),
5111+
)
5112+
.with_index_uid(&index_uid)
5113+
.build(),
5114+
MockSplitBuilder::new_with_time_range("split_overlap_end", Some(128_000..=140_000))
5115+
.with_index_uid(&index_uid)
5116+
.build(),
5117+
MockSplitBuilder::new_with_time_range(
5118+
"split_covering_whole",
5119+
Some(100_000..=200_000),
5120+
)
5121+
.with_index_uid(&index_uid)
5122+
.build(),
5123+
MockSplitBuilder::new_with_time_range("split_inside", Some(124_000..=126_000))
5124+
.with_index_uid(&index_uid)
5125+
.build(),
5126+
];
5127+
let resp = ListSplitsResponse::try_from_splits(splits).unwrap();
5128+
Ok(ServiceStream::from(vec![Ok(resp)]))
5129+
});
5130+
5131+
let mut mock_search = MockSearchService::new();
5132+
mock_search
5133+
.expect_leaf_search()
5134+
.withf(|leaf_search_req| {
5135+
let mut expected = HashSet::new();
5136+
5137+
// Notice split_inside is not included.
5138+
expected.insert("split_before");
5139+
expected.insert("split_covering_whole");
5140+
expected.insert("split_overlap_end");
5141+
expected.insert("split_overlap_start");
5142+
5143+
leaf_search_req.leaf_requests.len() == 1
5144+
&& leaf_search_req.leaf_requests[0]
5145+
.split_offsets
5146+
.iter()
5147+
.map(|s| s.split_id.as_str())
5148+
.collect::<HashSet<&str>>()
5149+
== expected
5150+
})
5151+
.times(1)
5152+
.returning(|req| {
5153+
Ok(quickwit_proto::search::LeafSearchResponse {
5154+
num_hits: req.leaf_requests[0]
5155+
.split_offsets
5156+
.iter()
5157+
.map(|s| s.num_docs)
5158+
.sum(),
5159+
partial_hits: vec![],
5160+
failed_splits: Vec::new(),
5161+
num_attempted_splits: 0,
5162+
..Default::default()
5163+
})
5164+
});
5165+
mock_search.expect_fetch_docs().returning(|fetch_req| {
5166+
Ok(quickwit_proto::search::FetchDocsResponse {
5167+
hits: get_doc_for_fetch_req(fetch_req),
5168+
})
5169+
});
5170+
5171+
let searcher_pool = searcher_pool_for_test([("127.0.0.1:1001", mock_search)]);
5172+
let search_job_placer = SearchJobPlacer::new(searcher_pool);
5173+
let cluster_client = ClusterClient::new(search_job_placer);
5174+
5175+
let ctx = SearcherContext::for_test();
5176+
let resp = root_search(
5177+
&ctx,
5178+
search_request,
5179+
MetastoreServiceClient::from_mock(mock_metastore),
5180+
&cluster_client,
5181+
)
5182+
.await?;
5183+
5184+
assert_eq!(resp.num_hits, 50);
5185+
assert_eq!(resp.hits.len(), 0);
5186+
5187+
Ok(())
5188+
}
50795189
}

0 commit comments

Comments
 (0)