Skip to content

Commit 2edd845

Browse files
committed
future: add tests for callbacks
1 parent e250bac commit 2edd845

File tree

1 file changed

+78
-2
lines changed

1 file changed

+78
-2
lines changed

scylla-rust-wrapper/src/future.rs

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

321321
#[cfg(test)]
322322
mod tests {
323-
use crate::testing::assert_cass_future_error_message_eq;
323+
use crate::testing::{assert_cass_error_eq, assert_cass_future_error_message_eq};
324324

325325
use super::*;
326-
use std::{os::raw::c_char, thread, time::Duration};
326+
use std::{
327+
os::raw::c_char,
328+
thread::{self},
329+
time::Duration,
330+
};
327331

328332
// This is not a particularly smart test, but if some thread is granted access the value
329333
// before it is truly computed, then weird things should happen, even a segfault.
@@ -385,4 +389,76 @@ mod tests {
385389
cass_future_free(cass_fut);
386390
}
387391
}
392+
393+
#[test]
394+
#[ntest::timeout(500)]
395+
fn test_cass_future_callback() {
396+
unsafe {
397+
const ERROR_MSG: &str = "NOBODY EXPECTED SPANISH INQUISITION";
398+
const HUNDRED_MILLIS_IN_MICROS: u64 = 100 * 1000;
399+
400+
let create_future_and_flag = || {
401+
unsafe extern "C" fn mark_flag_cb(_fut: *const CassFuture, data: *mut c_void) {
402+
let flag = data as *mut bool;
403+
*flag = true;
404+
}
405+
406+
let fut = async move {
407+
tokio::time::sleep(Duration::from_micros(HUNDRED_MILLIS_IN_MICROS)).await;
408+
Err((CassError::CASS_OK, ERROR_MSG.into()))
409+
};
410+
let cass_fut = CassFuture::make_raw(fut);
411+
let flag = Box::new(false);
412+
let flag_ptr = Box::into_raw(flag);
413+
414+
assert_cass_error_eq!(
415+
cass_future_set_callback(cass_fut, Some(mark_flag_cb), flag_ptr as *mut c_void),
416+
CassError::CASS_OK
417+
);
418+
419+
(cass_fut, flag_ptr)
420+
};
421+
422+
// Callback executed after awaiting.
423+
{
424+
let (cass_fut, flag_ptr) = create_future_and_flag();
425+
cass_future_wait(cass_fut);
426+
427+
assert_cass_future_error_message_eq!(cass_fut, Some(ERROR_MSG));
428+
assert!(*flag_ptr);
429+
430+
cass_future_free(cass_fut);
431+
let _ = Box::from_raw(flag_ptr);
432+
}
433+
434+
// Callback executed after timeouts.
435+
{
436+
let (cass_fut, flag_ptr) = create_future_and_flag();
437+
438+
// This should timeout on tokio::time::timeout.
439+
let timed_result = cass_future_wait_timed(cass_fut, HUNDRED_MILLIS_IN_MICROS / 5);
440+
assert_eq!(0, timed_result);
441+
// This should timeout on cond variable (previous call consumed JoinHandle).
442+
let timed_result = cass_future_wait_timed(cass_fut, HUNDRED_MILLIS_IN_MICROS / 5);
443+
assert_eq!(0, timed_result);
444+
assert_cass_future_error_message_eq!(cass_fut, Some(ERROR_MSG));
445+
assert!(*flag_ptr);
446+
447+
cass_future_free(cass_fut);
448+
let _ = Box::from_raw(flag_ptr);
449+
}
450+
451+
// Don't await the future. Just sleep.
452+
{
453+
let (cass_fut, flag_ptr) = create_future_and_flag();
454+
455+
std::thread::sleep(Duration::from_micros(HUNDRED_MILLIS_IN_MICROS + 10 * 1000));
456+
457+
assert!(*flag_ptr);
458+
459+
cass_future_free(cass_fut);
460+
let _ = Box::from_raw(flag_ptr);
461+
}
462+
}
463+
}
388464
}

0 commit comments

Comments
 (0)