Skip to content

Commit 5cc1ba3

Browse files
committed
future: add tests for callbacks
1 parent e250bac commit 5cc1ba3

File tree

1 file changed

+79
-2
lines changed

1 file changed

+79
-2
lines changed

scylla-rust-wrapper/src/future.rs

Lines changed: 79 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,77 @@ 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+
const ERROR_MSG: &str = "NOBODY EXPECTED SPANISH INQUISITION";
407+
let fut = async move {
408+
tokio::time::sleep(Duration::from_micros(HUNDRED_MILLIS_IN_MICROS)).await;
409+
Err((CassError::CASS_OK, ERROR_MSG.into()))
410+
};
411+
let cass_fut = CassFuture::make_raw(fut);
412+
let flag = Box::new(false);
413+
let flag_ptr = Box::into_raw(flag);
414+
415+
assert_cass_error_eq!(
416+
cass_future_set_callback(cass_fut, Some(mark_flag_cb), flag_ptr as *mut c_void),
417+
CassError::CASS_OK
418+
);
419+
420+
(cass_fut, flag_ptr)
421+
};
422+
423+
// Callback executed after awaiting.
424+
{
425+
let (cass_fut, flag_ptr) = create_future_and_flag();
426+
cass_future_wait(cass_fut);
427+
428+
assert_cass_future_error_message_eq!(cass_fut, Some(ERROR_MSG));
429+
assert!(*flag_ptr);
430+
431+
cass_future_free(cass_fut);
432+
let _ = Box::from_raw(flag_ptr);
433+
}
434+
435+
// Callback executed after timeouts.
436+
{
437+
let (cass_fut, flag_ptr) = create_future_and_flag();
438+
439+
// This should timeout on tokio::time::timeout.
440+
let timed_result = cass_future_wait_timed(cass_fut, HUNDRED_MILLIS_IN_MICROS / 5);
441+
assert_eq!(0, timed_result);
442+
// This should timeout on cond variable (previous call consumed JoinHandle).
443+
let timed_result = cass_future_wait_timed(cass_fut, HUNDRED_MILLIS_IN_MICROS / 5);
444+
assert_eq!(0, timed_result);
445+
assert_cass_future_error_message_eq!(cass_fut, Some(ERROR_MSG));
446+
assert!(*flag_ptr);
447+
448+
cass_future_free(cass_fut);
449+
let _ = Box::from_raw(flag_ptr);
450+
}
451+
452+
// Don't await the future. Just sleep.
453+
{
454+
let (cass_fut, flag_ptr) = create_future_and_flag();
455+
456+
std::thread::sleep(Duration::from_micros(HUNDRED_MILLIS_IN_MICROS + 10 * 1000));
457+
458+
assert!(*flag_ptr);
459+
460+
cass_future_free(cass_fut);
461+
let _ = Box::from_raw(flag_ptr);
462+
}
463+
}
464+
}
388465
}

0 commit comments

Comments
 (0)