1#![allow( 2 clippy::assertions_on_constants, 3 clippy::assertions_on_result_states, 4 clippy::cast_possible_truncation, 5 clippy::cast_possible_wrap, 6 clippy::float_cmp, 7 clippy::needless_pass_by_value, 8 clippy::unit_cmp, 9 clippy::unseparated_literal_suffix 10)] 11 12use cxx::SharedPtr; 13use cxx_test_suite::module::ffi2; 14use cxx_test_suite::{cast, ffi, R}; 15use std::cell::Cell; 16use std::ffi::CStr; 17 18thread_local! { 19 static CORRECT: Cell<bool> = Cell::new(false); 20} 21 22#[no_mangle] 23extern "C" fn cxx_test_suite_set_correct() { 24 CORRECT.with(|correct| correct.set(true)); 25} 26 27macro_rules! check { 28 ($run:expr) => {{ 29 CORRECT.with(|correct| correct.set(false)); 30 $run; 31 assert!(CORRECT.with(Cell::get), "{}", stringify!($run)); 32 }}; 33} 34 35#[test] 36fn test_c_return() { 37 let shared = ffi::Shared { z: 2020 }; 38 let ns_shared = ffi::AShared { z: 2020 }; 39 let nested_ns_shared = ffi::ABShared { z: 2020 }; 40 41 assert_eq!(2020, ffi::c_return_primitive()); 42 assert_eq!(2020, ffi::c_return_shared().z); 43 assert_eq!(2020, ffi::c_return_box().0); 44 ffi::c_return_unique_ptr(); 45 ffi2::c_return_ns_unique_ptr(); 46 assert_eq!(2020, *ffi::c_return_ref(&shared)); 47 assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared)); 48 assert_eq!(2020, *ffi::c_return_nested_ns_ref(&nested_ns_shared)); 49 assert_eq!("2020", ffi::c_return_str(&shared)); 50 assert_eq!( 51 b"2020\0", 52 cast::c_char_to_unsigned(ffi::c_return_slice_char(&shared)), 53 ); 54 assert_eq!("2020", ffi::c_return_rust_string()); 55 assert_eq!("Hello \u{fffd}World", ffi::c_return_rust_string_lossy()); 56 assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap()); 57 assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().len()); 58 assert_eq!( 59 200_u8, 60 ffi::c_return_unique_ptr_vector_u8().into_iter().sum(), 61 ); 62 assert_eq!( 63 200.5_f64, 64 ffi::c_return_unique_ptr_vector_f64().into_iter().sum(), 65 ); 66 assert_eq!(2, ffi::c_return_unique_ptr_vector_shared().len()); 67 assert_eq!( 68 2021_usize, 69 ffi::c_return_unique_ptr_vector_shared() 70 .into_iter() 71 .map(|o| o.z) 72 .sum(), 73 ); 74 assert_eq!(b"\x02\0\x02\0"[..], ffi::c_return_rust_vec_u8()); 75 assert_eq!([true, true, false][..], ffi::c_return_rust_vec_bool()); 76 assert_eq!(2020, ffi::c_return_identity(2020)); 77 assert_eq!(2021, ffi::c_return_sum(2020, 1)); 78 match ffi::c_return_enum(0) { 79 enm @ ffi::Enum::AVal => assert_eq!(0, enm.repr), 80 _ => assert!(false), 81 } 82 match ffi::c_return_enum(1) { 83 enm @ ffi::Enum::BVal => assert_eq!(2020, enm.repr), 84 _ => assert!(false), 85 } 86 match ffi::c_return_enum(2021) { 87 enm @ ffi::Enum::LastVal => assert_eq!(2021, enm.repr), 88 _ => assert!(false), 89 } 90 match ffi::c_return_ns_enum(0) { 91 enm @ ffi::AEnum::AAVal => assert_eq!(0, enm.repr), 92 _ => assert!(false), 93 } 94 match ffi::c_return_nested_ns_enum(0) { 95 enm @ ffi::ABEnum::ABAVal => assert_eq!(0, enm.repr), 96 _ => assert!(false), 97 } 98} 99 100#[test] 101fn test_c_try_return() { 102 assert_eq!((), ffi::c_try_return_void().unwrap()); 103 assert_eq!(2020, ffi::c_try_return_primitive().unwrap()); 104 assert_eq!( 105 "logic error", 106 ffi::c_fail_return_primitive().unwrap_err().what(), 107 ); 108 assert_eq!(2020, ffi::c_try_return_box().unwrap().0); 109 assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap()); 110 assert_eq!("2020", ffi::c_try_return_str("2020").unwrap()); 111 assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap()); 112 assert_eq!("2020", ffi::c_try_return_rust_string().unwrap()); 113 assert_eq!("2020", &*ffi::c_try_return_unique_ptr_string().unwrap()); 114} 115 116#[test] 117fn test_c_take() { 118 let unique_ptr = ffi::c_return_unique_ptr(); 119 let unique_ptr_ns = ffi2::c_return_ns_unique_ptr(); 120 121 check!(ffi::c_take_primitive(2020)); 122 check!(ffi::c_take_shared(ffi::Shared { z: 2020 })); 123 check!(ffi::c_take_ns_shared(ffi::AShared { z: 2020 })); 124 check!(ffi::ns_c_take_ns_shared(ffi::AShared { z: 2020 })); 125 check!(ffi::c_take_nested_ns_shared(ffi::ABShared { z: 2020 })); 126 check!(ffi::c_take_box(Box::new(R(2020)))); 127 check!(ffi::c_take_ref_c(&unique_ptr)); 128 check!(ffi2::c_take_ref_ns_c(&unique_ptr_ns)); 129 check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr)); 130 check!(ffi::c_take_str("2020")); 131 check!(ffi::c_take_slice_char(cast::unsigned_to_c_char(b"2020"))); 132 check!(ffi::c_take_slice_shared(&[ 133 ffi::Shared { z: 2020 }, 134 ffi::Shared { z: 2021 }, 135 ])); 136 let shared_sort_slice = &mut [ 137 ffi::Shared { z: 2 }, 138 ffi::Shared { z: 0 }, 139 ffi::Shared { z: 7 }, 140 ffi::Shared { z: 4 }, 141 ]; 142 check!(ffi::c_take_slice_shared_sort(shared_sort_slice)); 143 assert_eq!(shared_sort_slice[0].z, 0); 144 assert_eq!(shared_sort_slice[1].z, 2); 145 assert_eq!(shared_sort_slice[2].z, 4); 146 assert_eq!(shared_sort_slice[3].z, 7); 147 let r_sort_slice = &mut [R(2020), R(2050), R(2021)]; 148 check!(ffi::c_take_slice_r(r_sort_slice)); 149 check!(ffi::c_take_slice_r_sort(r_sort_slice)); 150 assert_eq!(r_sort_slice[0].0, 2020); 151 assert_eq!(r_sort_slice[1].0, 2021); 152 assert_eq!(r_sort_slice[2].0, 2050); 153 check!(ffi::c_take_rust_string("2020".to_owned())); 154 check!(ffi::c_take_unique_ptr_string( 155 ffi::c_return_unique_ptr_string() 156 )); 157 let mut vector = ffi::c_return_unique_ptr_vector_u8(); 158 assert_eq!(vector.pin_mut().pop(), Some(9)); 159 check!(ffi::c_take_unique_ptr_vector_u8(vector)); 160 let mut vector = ffi::c_return_unique_ptr_vector_f64(); 161 vector.pin_mut().push(9.0); 162 check!(ffi::c_take_unique_ptr_vector_f64(vector)); 163 let mut vector = ffi::c_return_unique_ptr_vector_shared(); 164 vector.pin_mut().push(ffi::Shared { z: 9 }); 165 check!(ffi::c_take_unique_ptr_vector_shared(vector)); 166 check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8())); 167 let test_vec = [86_u8, 75_u8, 30_u8, 9_u8].to_vec(); 168 check!(ffi::c_take_rust_vec(test_vec.clone())); 169 check!(ffi::c_take_rust_vec_index(test_vec.clone())); 170 let shared_test_vec = vec![ffi::Shared { z: 1010 }, ffi::Shared { z: 1011 }]; 171 check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone())); 172 check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone())); 173 check!(ffi::c_take_rust_vec_shared_push(shared_test_vec.clone())); 174 check!(ffi::c_take_rust_vec_shared_truncate( 175 shared_test_vec.clone() 176 )); 177 check!(ffi::c_take_rust_vec_shared_clear(shared_test_vec.clone())); 178 check!(ffi::c_take_rust_vec_shared_forward_iterator( 179 shared_test_vec, 180 )); 181 let shared_sort_vec = vec![ 182 ffi::Shared { z: 2 }, 183 ffi::Shared { z: 0 }, 184 ffi::Shared { z: 7 }, 185 ffi::Shared { z: 4 }, 186 ]; 187 check!(ffi::c_take_rust_vec_shared_sort(shared_sort_vec)); 188 check!(ffi::c_take_ref_rust_vec(&test_vec)); 189 check!(ffi::c_take_ref_rust_vec_index(&test_vec)); 190 check!(ffi::c_take_ref_rust_vec_copy(&test_vec)); 191 check!(ffi::c_take_ref_shared_string(&ffi::SharedString { 192 msg: "2020".to_owned() 193 })); 194 let ns_shared_test_vec = vec![ffi::AShared { z: 1010 }, ffi::AShared { z: 1011 }]; 195 check!(ffi::c_take_rust_vec_ns_shared(ns_shared_test_vec)); 196 let nested_ns_shared_test_vec = vec![ffi::ABShared { z: 1010 }, ffi::ABShared { z: 1011 }]; 197 check!(ffi::c_take_rust_vec_nested_ns_shared( 198 nested_ns_shared_test_vec 199 )); 200 201 check!(ffi::c_take_enum(ffi::Enum::AVal)); 202 check!(ffi::c_take_ns_enum(ffi::AEnum::AAVal)); 203 check!(ffi::c_take_nested_ns_enum(ffi::ABEnum::ABAVal)); 204} 205 206#[test] 207fn test_c_callback() { 208 fn callback(s: String) -> usize { 209 if s == "2020" { 210 cxx_test_suite_set_correct(); 211 } 212 0 213 } 214 215 #[allow(clippy::ptr_arg)] 216 fn callback_ref(s: &String) { 217 if s == "2020" { 218 cxx_test_suite_set_correct(); 219 } 220 } 221 222 fn callback_mut(s: &mut String) { 223 if s == "2020" { 224 cxx_test_suite_set_correct(); 225 } 226 } 227 228 check!(ffi::c_take_callback(callback)); 229 check!(ffi::c_take_callback_ref(callback_ref)); 230 check!(ffi::c_take_callback_ref_lifetime(callback_ref)); 231 check!(ffi::c_take_callback_mut(callback_mut)); 232} 233 234#[test] 235fn test_c_call_r() { 236 fn cxx_run_test() { 237 extern "C" { 238 fn cxx_run_test() -> *const i8; 239 } 240 let failure = unsafe { cxx_run_test() }; 241 if !failure.is_null() { 242 let msg = unsafe { CStr::from_ptr(failure as *mut std::os::raw::c_char) }; 243 eprintln!("{}", msg.to_string_lossy()); 244 } 245 } 246 check!(cxx_run_test()); 247} 248 249#[test] 250fn test_c_method_calls() { 251 let mut unique_ptr = ffi::c_return_unique_ptr(); 252 253 let old_value = unique_ptr.get(); 254 assert_eq!(2020, old_value); 255 assert_eq!(2021, unique_ptr.pin_mut().set(2021)); 256 assert_eq!(2021, unique_ptr.get()); 257 assert_eq!(2021, unique_ptr.get2()); 258 assert_eq!(2021, *unique_ptr.getRef()); 259 assert_eq!(2021, *unique_ptr.pin_mut().getMut()); 260 assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap()); 261 assert!(unique_ptr.pin_mut().get_fail().is_err()); 262 assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared()); 263 assert_eq!(2022, *ffi::Shared { z: 2022 }.c_method_ref_on_shared()); 264 assert_eq!(2023, *ffi::Shared { z: 2023 }.c_method_mut_on_shared()); 265 266 let val = 42; 267 let mut array = ffi::Array { 268 a: [0, 0, 0, 0], 269 b: ffi::Buffer::default(), 270 }; 271 array.c_set_array(val); 272 assert_eq!(array.a.len() as i32 * val, array.r_get_array_sum()); 273} 274 275#[test] 276fn test_shared_ptr_weak_ptr() { 277 let shared_ptr = ffi::c_return_shared_ptr(); 278 let weak_ptr = SharedPtr::downgrade(&shared_ptr); 279 assert_eq!(1, ffi::c_get_use_count(&weak_ptr)); 280 281 assert!(!weak_ptr.upgrade().is_null()); 282 assert_eq!(1, ffi::c_get_use_count(&weak_ptr)); 283 284 drop(shared_ptr); 285 assert_eq!(0, ffi::c_get_use_count(&weak_ptr)); 286 assert!(weak_ptr.upgrade().is_null()); 287} 288 289#[test] 290fn test_c_ns_method_calls() { 291 let unique_ptr = ffi2::ns_c_return_unique_ptr_ns(); 292 293 let old_value = unique_ptr.get(); 294 assert_eq!(1000, old_value); 295} 296 297#[test] 298fn test_enum_representations() { 299 assert_eq!(0, ffi::Enum::AVal.repr); 300 assert_eq!(2020, ffi::Enum::BVal.repr); 301 assert_eq!(2021, ffi::Enum::LastVal.repr); 302} 303 304#[test] 305fn test_debug() { 306 assert_eq!("Shared { z: 1 }", format!("{:?}", ffi::Shared { z: 1 })); 307 assert_eq!("BVal", format!("{:?}", ffi::Enum::BVal)); 308 assert_eq!("Enum(9)", format!("{:?}", ffi::Enum { repr: 9 })); 309} 310 311#[no_mangle] 312extern "C" fn cxx_test_suite_get_box() -> *mut R { 313 Box::into_raw(Box::new(R(2020usize))) 314} 315 316#[no_mangle] 317unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const R) -> bool { 318 (*r).0 == 2020 319} 320 321#[test] 322fn test_rust_name_attribute() { 323 assert_eq!("2020", ffi::i32_overloaded_function(2020)); 324 assert_eq!("2020", ffi::str_overloaded_function("2020")); 325 let unique_ptr = ffi::c_return_unique_ptr(); 326 assert_eq!("2020", unique_ptr.i32_overloaded_method(2020)); 327 assert_eq!("2020", unique_ptr.str_overloaded_method("2020")); 328} 329 330#[test] 331fn test_extern_trivial() { 332 let mut d = ffi2::c_return_trivial(); 333 check!(ffi2::c_take_trivial_ref(&d)); 334 check!(d.c_take_trivial_ref_method()); 335 check!(d.c_take_trivial_mut_ref_method()); 336 check!(ffi2::c_take_trivial(d)); 337 let mut d = ffi2::c_return_trivial_ptr(); 338 check!(d.c_take_trivial_ref_method()); 339 check!(d.c_take_trivial_mut_ref_method()); 340 check!(ffi2::c_take_trivial_ptr(d)); 341 cxx::UniquePtr::new(ffi2::D { d: 42 }); 342 let d = ffi2::ns_c_return_trivial(); 343 check!(ffi2::ns_c_take_trivial(d)); 344 345 let g = ffi2::c_return_trivial_ns(); 346 check!(ffi2::c_take_trivial_ns_ref(&g)); 347 check!(ffi2::c_take_trivial_ns(g)); 348 let g = ffi2::c_return_trivial_ns_ptr(); 349 check!(ffi2::c_take_trivial_ns_ptr(g)); 350 cxx::UniquePtr::new(ffi2::G { g: 42 }); 351} 352 353#[test] 354fn test_extern_opaque() { 355 let mut e = ffi2::c_return_opaque_ptr(); 356 check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap())); 357 check!(e.c_take_opaque_ref_method()); 358 check!(e.pin_mut().c_take_opaque_mut_ref_method()); 359 check!(ffi2::c_take_opaque_ptr(e)); 360 361 let f = ffi2::c_return_ns_opaque_ptr(); 362 check!(ffi2::c_take_opaque_ns_ref(f.as_ref().unwrap())); 363 check!(ffi2::c_take_opaque_ns_ptr(f)); 364} 365 366#[test] 367fn test_raw_ptr() { 368 let c = ffi::c_return_mut_ptr(2023); 369 let mut c_unique = unsafe { cxx::UniquePtr::from_raw(c) }; 370 assert_eq!(2023, c_unique.pin_mut().set_succeed(2023).unwrap()); 371 // c will be dropped as it's now in a UniquePtr 372 373 let c2 = ffi::c_return_mut_ptr(2024); 374 assert_eq!(2024, unsafe { ffi::c_take_const_ptr(c2) }); 375 assert_eq!(2024, unsafe { ffi::c_take_mut_ptr(c2) }); // deletes c2 376 377 let c3 = ffi::c_return_const_ptr(2025); 378 assert_eq!(2025, unsafe { ffi::c_take_const_ptr(c3) }); 379 assert_eq!(2025, unsafe { ffi::c_take_mut_ptr(c3 as *mut ffi::C) }); // deletes c3 380} 381