Skip to content

Commit 2a6a590

Browse files
committed
Add tests to search splits contained in time range
1 parent 0348405 commit 2a6a590

File tree

3 files changed

+147
-3
lines changed

3 files changed

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

quickwit/rest-api-tests/scenarii/qw_search_api/0001_ts_range.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,27 @@ params:
3434
query: "ts:>=1684993002 AND ts:<1684993004"
3535
expected:
3636
num_hits: 2
37+
---
38+
endpoint: simple/search
39+
params:
40+
query: "*"
41+
start_timestamp: 1684993000
42+
end_timestamp: 1684993004
43+
expected:
44+
num_hits: 3
45+
---
46+
endpoint: simple/search
47+
params:
48+
query: "*"
49+
start_timestamp: 1684993001
50+
end_timestamp: 1684993005
51+
expected:
52+
num_hits: 3
53+
---
54+
endpoint: simple/search
55+
params:
56+
query: "*"
57+
start_timestamp: 1684992999
58+
end_timestamp: 1684993003
59+
expected:
60+
num_hits: 3

0 commit comments

Comments
 (0)