Browse Source

Add tests to Carrier.

Jing Yang 4 years ago
parent
commit
1e211fce26
1 changed files with 79 additions and 2 deletions
  1. 79 2
      src/carrier/mod.rs

+ 79 - 2
src/carrier/mod.rs

@@ -17,7 +17,8 @@ use std::time::Duration;
 /// carry out clean-ups or any other type of work that requires an owned
 /// instance of type `T`.
 pub struct Carrier<T> {
-    template: Arc<CarrierTarget<T>>,
+    // Visible to tests.
+    pub(self) template: Arc<CarrierTarget<T>>,
     shutdown: AtomicBool,
 }
 
@@ -51,7 +52,11 @@ impl<T> Carrier<T> {
 
     fn unwrap_or_panic(self) -> T {
         let arc = self.template;
-        assert_eq!(Arc::strong_count(&arc), 1);
+        assert_eq!(
+            Arc::strong_count(&arc),
+            1,
+            "The carrier should not more than one outstanding Arc"
+        );
 
         match Arc::try_unwrap(arc) {
             Ok(t) => t.target,
@@ -164,3 +169,75 @@ impl<T> Drop for CarrierRef<T> {
         self.delete()
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use crate::Carrier;
+    use std::cell::RefCell;
+    use std::time::Duration;
+
+    #[test]
+    fn test_basics() {
+        let carrier = Carrier::new(7usize);
+
+        let ref_one = carrier.create_ref().unwrap();
+        let ref_two = carrier.create_ref().unwrap();
+        // Carrier should be send.
+        let (ref_three, carrier) =
+            std::thread::spawn(|| (carrier.create_ref(), carrier))
+                .join()
+                .expect("Thread creation should never fail");
+        let ref_three = ref_three.unwrap();
+
+        assert_eq!(*ref_one, 7usize);
+        assert_eq!(*ref_two, 7usize);
+        assert_eq!(*ref_three, 7usize);
+
+        carrier.close();
+        // Double close is OK.
+        carrier.close();
+
+        assert!(carrier.create_ref().is_none());
+        // Create should always fail.
+        assert!(carrier.create_ref().is_none());
+
+        assert_eq!(carrier.ref_count(), 3);
+
+        let carrier =
+            carrier.wait_timeout(Duration::from_micros(1)).expect_err(
+                "Wait should not be successful \
+                since there are outstanding references",
+            );
+
+        drop(ref_one);
+        assert_eq!(carrier.ref_count(), 2);
+        drop(ref_two);
+        assert_eq!(carrier.ref_count(), 1);
+        drop(ref_three);
+        assert_eq!(carrier.ref_count(), 0);
+        assert_eq!(carrier.wait(), 7usize);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_panic_outstanding_arc() {
+        let carrier = Carrier::new(7usize);
+        let _outstanding_ref = carrier.template.clone();
+
+        // Carrier should panic when it sees an outstanding Arc.
+        carrier.wait();
+    }
+
+    #[test]
+    fn test_ref() {
+        let carrier = Carrier::new(RefCell::new(7usize));
+        let ref_one = carrier.create_ref().unwrap();
+        let ref_two = carrier.create_ref().unwrap();
+
+        *ref_two.borrow_mut() += 1;
+        assert_eq!(8, *ref_one.borrow());
+
+        *ref_one.borrow_mut() += 1;
+        assert_eq!(9, *ref_two.borrow());
+    }
+}