@@ -214,33 +214,34 @@ Result<std::string> download_link(std::string_view link) {
214214 return http_client->Get (link.substr (link.find (" /links/" )));
215215}
216216
217-
218- TEST_CASE (" reduct::IBucket should create a query link" , " [bucket_api][1_17]" ) {
217+ TEST_CASE (" reduct::IBucket should create a query link" , " [bucket_api][1_19]" ) {
219218 Fixture ctx;
220219 auto [bucket, _] = ctx.client ->GetBucket (" test_bucket_1" );
221220
222- auto [link, err] = bucket->CreateQueryLink (" entry-1" , IBucket::QueryLinkOptions{});
221+ auto [link, err] = bucket->CreateQueryLink (
222+ " entry-1" , IBucket::QueryLinkOptions{.record_entry = " entry-1" , .record_timestamp = IBucket::Time () + s (1 )});
223223 REQUIRE (err == Error::kOk );
224224
225225 auto [data, http_err] = download_link (link);
226226 REQUIRE (http_err == Error::kOk );
227227 REQUIRE (data == " data-1" );
228228}
229229
230- TEST_CASE (" reduct::IBucket should create a query link for multiple entries" , " [bucket_api][1_18 ]" ) {
230+ TEST_CASE (" reduct::IBucket should create a query link for multiple entries" , " [bucket_api][1_19 ]" ) {
231231 Fixture ctx;
232232 auto [bucket, _] = ctx.client ->GetBucket (" test_bucket_1" );
233233
234- auto [link, err] = bucket->CreateQueryLink (std::vector<std::string>{" entry-1" , " entry-2" },
235- IBucket::QueryLinkOptions{});
234+ auto [link, err] = bucket->CreateQueryLink (
235+ std::vector<std::string>{" entry-1" , " entry-2" },
236+ IBucket::QueryLinkOptions{.record_entry = " entry-1" , .record_timestamp = IBucket::Time () + s (1 )});
236237 REQUIRE (err == Error::kOk );
237238
238239 auto [data, http_err] = download_link (link);
239240 REQUIRE (http_err == Error::kOk );
240241 REQUIRE (data == " data-1" );
241242}
242243
243- TEST_CASE (" reduct::IBucket should reject empty entry list for query link" , " [bucket_api][1_18 ]" ) {
244+ TEST_CASE (" reduct::IBucket should reject empty entry list for query link" , " [bucket_api][1_19 ]" ) {
244245 Fixture ctx;
245246 auto [bucket, _] = ctx.client ->GetBucket (" test_bucket_1" );
246247
@@ -249,39 +250,76 @@ TEST_CASE("reduct::IBucket should reject empty entry list for query link", "[buc
249250 REQUIRE (link.empty ());
250251}
251252
252- TEST_CASE (" reduct::IBucket should create a query link with index " , " [bucket_api][1_17 ]" ) {
253+ TEST_CASE (" reduct::IBucket should create a query link with file name " , " [bucket_api][1_19 ]" ) {
253254 Fixture ctx;
254255 auto [bucket, _] = ctx.client ->GetBucket (" test_bucket_1" );
255256
256- auto [link, err] = bucket->CreateQueryLink (" entry-1" , IBucket::QueryLinkOptions{.record_index = 1 });
257- REQUIRE (err == Error::kOk );
257+ IBucket::QueryLinkOptions options{
258+ .record_entry = " entry-1" ,
259+ .record_timestamp = IBucket::Time () + s (1 ),
260+ .file_name = " my_file.txt" ,
261+ };
258262
259- auto [data, http_err ] = download_link (link );
260- REQUIRE (http_err == Error::kOk );
261- REQUIRE (data == " data-2 " );
263+ auto [link, err ] = bucket-> CreateQueryLink ( " entry-1 " , options );
264+ REQUIRE (err == Error::kOk );
265+ REQUIRE (link. find ( " /links/my_file.txt " ) != std::string::npos );
262266}
263267
264- TEST_CASE (" reduct::IBucket should create a query link with file name " , " [bucket_api][1_17 ]" ) {
268+ TEST_CASE (" reduct::IBucket should create a query link with expire time " , " [bucket_api][1_19 ]" ) {
265269 Fixture ctx;
266270 auto [bucket, _] = ctx.client ->GetBucket (" test_bucket_1" );
267271
268- auto [link, err] = bucket->CreateQueryLink (" entry-1" , IBucket::QueryLinkOptions{
269- .file_name = " my_file.txt" ,
270- });
272+ IBucket::QueryLinkOptions options{
273+ .record_entry = " entry-1" ,
274+ .record_timestamp = IBucket::Time () + s (1 ),
275+ .expire_at = IBucket::Time::clock::now () - std::chrono::hours (1 ),
276+ };
277+
278+ auto [link, err] = bucket->CreateQueryLink (" entry-1" , options);
271279 REQUIRE (err == Error::kOk );
272- REQUIRE (link.find (" /links/my_file.txt" ) != std::string::npos);
280+
281+ auto [_data, http_err] = download_link (link);
282+ REQUIRE (http_err.code == 422 );
273283}
274284
275- TEST_CASE (" reduct::IBucket should create a query link with expire time " , " [bucket_api][1_17 ]" ) {
285+ TEST_CASE (" reduct::IBucket should create a query link with explicit record identity " , " [bucket_api][1_19 ]" ) {
276286 Fixture ctx;
277287 auto [bucket, _] = ctx.client ->GetBucket (" test_bucket_1" );
278288
279- auto [link, err] =
280- bucket->CreateQueryLink (" entry-1" , IBucket::QueryLinkOptions{
281- .expire_at = IBucket::Time::clock::now () - std::chrono::hours (1 ),
282- });
289+ auto [link, err] = bucket->CreateQueryLink (
290+ " entry-2" , IBucket::QueryLinkOptions{.record_entry = " entry-2" , .record_timestamp = IBucket::Time () + s (4 )});
283291 REQUIRE (err == Error::kOk );
284292
285- auto [_data, http_err] = download_link (link);
286- REQUIRE (http_err.code == 422 );
293+ auto [data, http_err] = download_link (link);
294+ REQUIRE (http_err == Error::kOk );
295+ REQUIRE (data == " data-4" );
296+ }
297+
298+ TEST_CASE (" reduct::IBucket should validate query link record identity selector" , " [bucket_api][1_19]" ) {
299+ Fixture ctx;
300+ auto [bucket, _] = ctx.client ->GetBucket (" test_bucket_1" );
301+
302+ SECTION (" record_entry without record_timestamp" ) {
303+ auto [link, err] = bucket->CreateQueryLink (" entry-1" , IBucket::QueryLinkOptions{.record_entry = " entry-1" });
304+ REQUIRE (link.empty ());
305+ REQUIRE (err.code == -1 );
306+ REQUIRE (err.message .find (" record_timestamp must be provided" ) != std::string::npos);
307+ }
308+
309+ SECTION (" record_timestamp defaults record_entry for one explicit entry" ) {
310+ auto [link, err] =
311+ bucket->CreateQueryLink (" entry-2" , IBucket::QueryLinkOptions{.record_timestamp = IBucket::Time () + s (4 )});
312+ REQUIRE (err == Error::kOk );
313+ auto [data, http_err] = download_link (link);
314+ REQUIRE (http_err == Error::kOk );
315+ REQUIRE (data == " data-4" );
316+ }
317+
318+ SECTION (" record_timestamp with wildcard entry requires record_entry" ) {
319+ auto [link, err] =
320+ bucket->CreateQueryLink (" entry-*" , IBucket::QueryLinkOptions{.record_timestamp = IBucket::Time () + s (4 )});
321+ REQUIRE (link.empty ());
322+ REQUIRE (err.code == -1 );
323+ REQUIRE (err.message .find (" record_entry must be provided" ) != std::string::npos);
324+ }
287325}
0 commit comments