@@ -320,10 +320,14 @@ pub unsafe extern "C" fn cass_future_tracing_id(
320
320
321
321
#[ cfg( test) ]
322
322
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} ;
324
324
325
325
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
+ } ;
327
331
328
332
// This is not a particularly smart test, but if some thread is granted access the value
329
333
// before it is truly computed, then weird things should happen, even a segfault.
@@ -385,4 +389,76 @@ mod tests {
385
389
cass_future_free ( cass_fut) ;
386
390
}
387
391
}
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
+ }
388
464
}
0 commit comments