From 88ba8d3860ee78de617b052086fa9fa5e6fec360 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Mon, 14 Oct 2024 01:18:22 +0900
Subject: [PATCH] Fix tests on Rust 1.81.0

Unwinding across functions with the extern "C" ABI is UB, but previously
worked. See: https://github.com/rust-lang/rust/issues/74990

Redo the tests so they don't rely on panics at all, using a
reference-counted counter instead.

Signed-off-by: Hector Martin <marcan@marcan.st>
---
 src/lib.rs | 84 +++++++++++++++--------------------------------
 1 file changed, 26 insertions(+), 58 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs
index 7b2ef1d..0895cfc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -480,29 +480,23 @@ mod tests {
     use std::mem;
     use std::ops;
     use std::ptr;
+    use std::sync::atomic::{AtomicU32, Ordering};
+    use std::sync::Arc;
 
     // structure to test drooping issue
     struct HasDrop {
-        drop_count: u32,
-        drop_limit: u32,
+        drop_count: Arc<AtomicU32>,
     }
 
     impl HasDrop {
-        fn new(val: u32) -> Self {
-            Self {
-                drop_count: 0,
-                drop_limit: val,
-            }
+        fn new(val: Arc<AtomicU32>) -> Self {
+            Self { drop_count: val }
         }
     }
 
     impl ops::Drop for HasDrop {
         fn drop(&mut self) {
-            if self.drop_count >= self.drop_limit {
-                panic!("Dropped more than {} time", self.drop_limit);
-            } else {
-                self.drop_count += 1;
-            }
+            self.drop_count.fetch_add(1, Ordering::Relaxed);
         }
     }
 
@@ -588,7 +582,8 @@ mod tests {
 
     #[test]
     fn schedule_must_not_drop() {
-        let hd = HasDrop::new(0);
+        let ctr = Arc::new(AtomicU32::new(0));
+        let hd = HasDrop::new(ctr.clone());
         let internal = lv2_sys::LV2_Worker_Schedule {
             handle: ptr::null_mut(),
             schedule_work: Some(extern_schedule),
@@ -598,12 +593,13 @@ mod tests {
             phantom: PhantomData::<*const TestDropWorker>,
         };
         let _ = schedule.schedule_work(hd);
+        assert_eq!(ctr.load(Ordering::Relaxed), 0);
     }
 
     #[test]
-    #[should_panic(expected = "Dropped")]
     fn schedule_must_enable_drop_on_error() {
-        let hd = HasDrop::new(0);
+        let ctr = Arc::new(AtomicU32::new(0));
+        let hd = HasDrop::new(ctr.clone());
         let internal = lv2_sys::LV2_Worker_Schedule {
             handle: ptr::null_mut(),
             schedule_work: Some(faulty_schedule),
@@ -613,35 +609,39 @@ mod tests {
             phantom: PhantomData::<*const TestDropWorker>,
         };
         let _ = schedule.schedule_work(hd);
+        assert_eq!(ctr.load(Ordering::Relaxed), 1);
     }
 
     #[test]
     fn respond_must_not_drop() {
-        let hd = HasDrop::new(0);
+        let ctr = Arc::new(AtomicU32::new(0));
+        let hd = HasDrop::new(ctr.clone());
         let respond = ResponseHandler {
             response_function: Some(extern_respond),
             respond_handle: ptr::null_mut(),
             phantom: PhantomData::<TestDropWorker>,
         };
         let _ = respond.respond(hd);
+        assert_eq!(ctr.load(Ordering::Relaxed), 0);
     }
 
     #[test]
-    #[should_panic(expected = "Dropped")]
     fn respond_must_enable_drop_on_error() {
-        let hd = HasDrop::new(0);
+        let ctr = Arc::new(AtomicU32::new(0));
+        let hd = HasDrop::new(ctr.clone());
         let respond = ResponseHandler {
             response_function: Some(faulty_respond),
             respond_handle: ptr::null_mut(),
             phantom: PhantomData::<TestDropWorker>,
         };
         let _ = respond.respond(hd);
+        assert_eq!(ctr.load(Ordering::Relaxed), 1);
     }
 
     #[test]
-    #[should_panic(expected = "Dropped")]
-    fn extern_work_should_drop() {
-        let hd = mem::ManuallyDrop::new(HasDrop::new(0));
+    fn extern_work_should_drop_once() {
+        let ctr = Arc::new(AtomicU32::new(0));
+        let hd = mem::ManuallyDrop::new(HasDrop::new(ctr.clone()));
         let ptr_hd = &hd as *const _ as *const c_void;
         let size = mem::size_of_val(&hd) as u32;
         let mut tdw = TestDropWorker {};
@@ -657,46 +657,13 @@ mod tests {
                 ptr_hd,
             );
         }
+        assert_eq!(ctr.load(Ordering::Relaxed), 1);
     }
 
     #[test]
-    fn extern_work_should_not_drop_twice() {
-        let hd = mem::ManuallyDrop::new(HasDrop::new(1));
-        let ptr_hd = &hd as *const _ as *const c_void;
-        let size = mem::size_of_val(&hd) as u32;
-        let mut tdw = TestDropWorker {};
-
-        let ptr_tdw = &mut tdw as *mut _ as *mut c_void;
-        //trash trick i use Plugin ptr insteas of Pluginstance ptr
-        unsafe {
-            WorkerDescriptor::<TestDropWorker>::extern_work(
-                ptr_tdw,
-                Some(extern_respond),
-                ptr::null_mut(),
-                size,
-                ptr_hd,
-            );
-        }
-    }
-
-    #[test]
-    #[should_panic(expected = "Dropped")]
-    fn extern_work_response_should_drop() {
-        let hd = mem::ManuallyDrop::new(HasDrop::new(0));
-        let ptr_hd = &hd as *const _ as *const c_void;
-        let size = mem::size_of_val(&hd) as u32;
-        let mut tdw = TestDropWorker {};
-
-        let ptr_tdw = &mut tdw as *mut _ as *mut c_void;
-        //trash trick i use Plugin ptr insteas of Pluginstance ptr
-        unsafe {
-            WorkerDescriptor::<TestDropWorker>::extern_work_response(ptr_tdw, size, ptr_hd);
-        }
-    }
-
-    #[test]
-    fn extern_work_response_should_not_drop_twice() {
-        let hd = mem::ManuallyDrop::new(HasDrop::new(1));
+    fn extern_work_response_should_drop_once() {
+        let ctr = Arc::new(AtomicU32::new(0));
+        let hd = mem::ManuallyDrop::new(HasDrop::new(ctr.clone()));
         let ptr_hd = &hd as *const _ as *const c_void;
         let size = mem::size_of_val(&hd) as u32;
         let mut tdw = TestDropWorker {};
@@ -706,5 +673,6 @@ mod tests {
         unsafe {
             WorkerDescriptor::<TestDropWorker>::extern_work_response(ptr_tdw, size, ptr_hd);
         }
+        assert_eq!(ctr.load(Ordering::Relaxed), 1);
     }
 }
-- 
2.45.2

