Skip to content

Commit 053c2b3

Browse files
committed
future: add tests for callbacks
1 parent 9e66cfa commit 053c2b3

File tree

1 file changed

+86
-2
lines changed

1 file changed

+86
-2
lines changed

scylla-rust-wrapper/src/future.rs

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,14 @@ pub unsafe extern "C" fn cass_future_tracing_id(
385385

386386
#[cfg(test)]
387387
mod tests {
388-
use crate::testing::assert_cass_future_error_message_eq;
388+
use crate::testing::{assert_cass_error_eq, assert_cass_future_error_message_eq};
389389

390390
use super::*;
391-
use std::{os::raw::c_char, thread, time::Duration};
391+
use std::{
392+
os::raw::c_char,
393+
thread::{self},
394+
time::Duration,
395+
};
392396

393397
// This is not a particularly smart test, but if some thread is granted access the value
394398
// before it is truly computed, then weird things should happen, even a segfault.
@@ -450,4 +454,84 @@ mod tests {
450454
cass_future_free(cass_fut);
451455
}
452456
}
457+
458+
// This test checks whether the future callback is executed correctly when:
459+
// - a future is awaited indefinitely
460+
// - a future is awaited, after the timeout appeared (_wait_timed)
461+
// - a future is not awaited. We simply sleep, and let the tokio runtime resolve
462+
// the future, and execute its callback
463+
#[test]
464+
#[ntest::timeout(500)]
465+
fn test_cass_future_callback() {
466+
unsafe {
467+
const ERROR_MSG: &str = "NOBODY EXPECTED SPANISH INQUISITION";
468+
const HUNDRED_MILLIS_IN_MICROS: u64 = 100 * 1000;
469+
470+
let create_future_and_flag = || {
471+
unsafe extern "C" fn mark_flag_cb(_fut: *const CassFuture, data: *mut c_void) {
472+
let flag = data as *mut bool;
473+
*flag = true;
474+
}
475+
476+
let fut = async move {
477+
tokio::time::sleep(Duration::from_micros(HUNDRED_MILLIS_IN_MICROS)).await;
478+
Err((CassError::CASS_OK, ERROR_MSG.into()))
479+
};
480+
let cass_fut = CassFuture::make_raw(fut);
481+
let flag = Box::new(false);
482+
let flag_ptr = Box::into_raw(flag);
483+
484+
assert_cass_error_eq!(
485+
cass_future_set_callback(cass_fut, Some(mark_flag_cb), flag_ptr as *mut c_void),
486+
CassError::CASS_OK
487+
);
488+
489+
(cass_fut, flag_ptr)
490+
};
491+
492+
// Callback executed after awaiting.
493+
{
494+
let (cass_fut, flag_ptr) = create_future_and_flag();
495+
cass_future_wait(cass_fut);
496+
497+
assert_cass_future_error_message_eq!(cass_fut, Some(ERROR_MSG));
498+
assert!(*flag_ptr);
499+
500+
cass_future_free(cass_fut);
501+
let _ = Box::from_raw(flag_ptr);
502+
}
503+
504+
// Callback executed after timeouts.
505+
{
506+
let (cass_fut, flag_ptr) = create_future_and_flag();
507+
508+
// This should timeout on tokio::time::timeout.
509+
let timed_result = cass_future_wait_timed(cass_fut, HUNDRED_MILLIS_IN_MICROS / 5);
510+
assert_eq!(0, timed_result);
511+
// This should timeout on cond variable (previous call consumed JoinHandle).
512+
let timed_result = cass_future_wait_timed(cass_fut, HUNDRED_MILLIS_IN_MICROS / 5);
513+
assert_eq!(0, timed_result);
514+
assert_cass_future_error_message_eq!(cass_fut, Some(ERROR_MSG));
515+
assert!(*flag_ptr);
516+
517+
cass_future_free(cass_fut);
518+
let _ = Box::from_raw(flag_ptr);
519+
}
520+
521+
// Don't await the future. Just sleep.
522+
{
523+
let (cass_fut, flag_ptr) = create_future_and_flag();
524+
525+
RUNTIME.block_on(async {
526+
tokio::time::sleep(Duration::from_micros(HUNDRED_MILLIS_IN_MICROS + 10 * 1000))
527+
.await
528+
});
529+
530+
assert!(*flag_ptr);
531+
532+
cass_future_free(cass_fut);
533+
let _ = Box::from_raw(flag_ptr);
534+
}
535+
}
536+
}
453537
}

0 commit comments

Comments
 (0)