Files

2142 lines
58 KiB
Rust

//! Extreme edge case tests for the announcement crate.
//! Testing 100+ edge cases that could break the implementation.
use announcement::{AnnounceError, Announcement, Listener};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::mem;
use std::sync::{Arc, Mutex, RwLock};
use std::thread;
use std::time::Duration;
/// Test: Edge case: Announce at the exact moment of listener creation
///
/// Verifies: Handles edge case: announce at the exact moment of listener creation
/// Category: edge
#[test]
fn test_announce_during_listener_creation() {
for _ in 0..1000 {
let (announcer, announcement) = Announcement::new();
let announcement_clone = announcement.clone();
let handle = thread::spawn(move || {
announcer.announce(42).unwrap();
});
let listener = announcement_clone.listener();
handle.join().unwrap();
// Should always receive the value
assert!(listener.try_listen().is_some());
}
}
/// Test: Edge case: Rapid creation and dropping of listeners
///
/// Verifies: Handles edge case: rapid creation and dropping of listeners
/// Category: edge
#[test]
fn test_rapid_listener_churn() {
let (announcer, announcement) = Announcement::new();
// Create and drop 10000 listeners rapidly
for _ in 0..10000 {
let _ = announcement.listener();
}
let final_listener = announcement.listener();
announcer.announce(999).unwrap();
assert_eq!(final_listener.try_listen(), Some(999));
}
/// Test: Edge case: Announcer dropped without announcing
///
/// Verifies: Handles edge case: announcer dropped without announcing
/// Category: edge
#[test]
fn test_announcer_dropped_without_announce() {
let (announcer, announcement) = Announcement::<i32>::new();
let listener = announcement.listener();
drop(announcer);
// Listener should never receive a value
assert_eq!(listener.try_listen(), None);
}
/// Test: Edge case: All listeners dropped before announcing
///
/// Verifies: Handles edge case: all listeners dropped before announcing
/// Category: edge
#[test]
fn test_all_listeners_dropped_before_announce() {
let (announcer, announcement) = Announcement::new();
{
let _l1 = announcement.listener();
let _l2 = announcement.listener();
let _l3 = announcement.listener();
// All listeners dropped here
}
// Should still succeed
announcer.announce(42).unwrap();
// New listener should get the value
let new_listener = announcement.listener();
assert_eq!(new_listener.try_listen(), Some(42));
}
/// Test: Edge case: Zero-sized types
///
/// Verifies: Handles edge case: zero-sized types
/// Category: edge
#[test]
fn test_zero_sized_type() {
let (announcer, announcement) = Announcement::<()>::new();
let listener = announcement.listener();
announcer.announce(()).unwrap();
assert_eq!(listener.try_listen(), Some(()));
}
/// Test: Edge case: Very large types (1MB+)
///
/// Verifies: Handles edge case: very large types (1mb+)
/// Category: edge
#[test]
fn test_very_large_type() {
#[derive(Clone, Debug, PartialEq)]
struct LargeType {
data: Vec<u8>,
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let large = LargeType {
data: vec![0u8; 1024 * 1024], // 1MB
};
announcer.announce(large.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.data.len(), 1024 * 1024);
}
/// Test: Edge case: Recursive types with Arc
///
/// Verifies: Handles edge case: recursive types with arc
/// Category: edge
#[test]
fn test_recursive_type_with_arc() {
#[derive(Clone, Debug)]
struct Node {
value: i32,
next: Option<Arc<Node>>,
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let node = Arc::new(Node {
value: 42,
next: Some(Arc::new(Node {
value: 43,
next: None,
})),
});
announcer.announce(node.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.value, 42);
assert_eq!(received.next.as_ref().unwrap().value, 43);
}
/// Test: Edge case: Empty announcements (unit type)
///
/// Verifies: Handles edge case: empty announcements (unit type)
/// Category: edge
#[test]
fn test_empty_announcement() {
let (announcer, announcement) = Announcement::<()>::new();
let listeners: Vec<_> = (0..100).map(|_| announcement.listener()).collect();
announcer.announce(()).unwrap();
for listener in &listeners {
assert_eq!(listener.try_listen(), Some(()));
}
}
/// Test: Edge case: Nested announcement channels - using Arc to share announcer
///
/// Verifies: Handles edge case: nested announcement channels - using arc to share announcer
/// Category: edge
#[test]
fn test_nested_announcements() {
let (outer_announcer, outer) = Announcement::<i32>::new();
let (_inner_announcer, inner) = Announcement::<i32>::new();
let outer_listener = outer.listener();
let _inner_listener: announcement::Listener<i32> = inner.listener();
// Announce a simple value instead of trying to pass the announcer
outer_announcer.announce(42).unwrap();
let value = outer_listener.try_listen().unwrap();
// Create a new announcer for the inner channel
let (inner_announcer2, inner2) = Announcement::<i32>::new();
let inner_listener2 = inner2.listener();
inner_announcer2.announce(value).unwrap();
assert_eq!(inner_listener2.try_listen(), Some(42));
}
/// Test: Edge case: Announcement with HashMap
///
/// Verifies: Handles edge case: announcement with hashmap
/// Category: edge
#[test]
fn test_announcement_with_hashmap() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let mut map = HashMap::new();
map.insert("key1", vec![1, 2, 3]);
map.insert("key2", vec![4, 5, 6]);
announcer.announce(map.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received["key1"], vec![1, 2, 3]);
assert_eq!(received["key2"], vec![4, 5, 6]);
}
/// Test: Edge case: Announcement with HashSet
///
/// Verifies: Handles edge case: announcement with hashset
/// Category: edge
#[test]
fn test_announcement_with_hashset() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let mut set = HashSet::new();
set.insert(1);
set.insert(2);
set.insert(3);
announcer.announce(set.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.len(), 3);
assert!(received.contains(&1));
}
/// Test: Edge case: Announcement with BTreeMap
///
/// Verifies: Handles edge case: announcement with btreemap
/// Category: edge
#[test]
fn test_announcement_with_btreemap() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let mut map = BTreeMap::new();
map.insert(3, "three");
map.insert(1, "one");
map.insert(2, "two");
announcer.announce(map.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received[&1], "one");
}
/// Test: Edge case: Announcement with BTreeSet
///
/// Verifies: Handles edge case: announcement with btreeset
/// Category: edge
#[test]
fn test_announcement_with_btreeset() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let mut set = BTreeSet::new();
set.insert("apple");
set.insert("banana");
set.insert("cherry");
announcer.announce(set.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.len(), 3);
}
/// Test: Edge case: Option<T> types
///
/// Verifies: Handles edge case: option<t> types
/// Category: edge
#[test]
fn test_option_none() {
let (announcer, announcement) = Announcement::<Option<i32>>::new();
let listener = announcement.listener();
announcer.announce(None).unwrap();
assert_eq!(listener.try_listen(), Some(None));
}
/// Test: Option type: option some
///
/// Verifies: Handles Option::Some values
/// Category: edge
#[test]
fn test_option_some() {
let (announcer, announcement) = Announcement::<Option<String>>::new();
let listener = announcement.listener();
announcer.announce(Some("Hello".to_string())).unwrap();
assert_eq!(listener.try_listen(), Some(Some("Hello".to_string())));
}
/// Test: Edge case: Result<T, E> types
///
/// Verifies: Handles edge case: result<t, e> types
/// Category: edge
#[test]
fn test_result_ok() {
let (announcer, announcement) = Announcement::<Result<i32, String>>::new();
let listener = announcement.listener();
announcer.announce(Ok(42)).unwrap();
assert_eq!(listener.try_listen(), Some(Ok(42)));
}
/// Test: Result type: result err
///
/// Verifies: Handles Result::Err values
/// Category: edge
#[test]
fn test_result_err() {
let (announcer, announcement) = Announcement::<Result<i32, String>>::new();
let listener = announcement.listener();
announcer.announce(Err("Error".to_string())).unwrap();
assert_eq!(listener.try_listen(), Some(Err("Error".to_string())));
}
/// Test: Edge case: Box<T> types
///
/// Verifies: Handles edge case: box<t> types
/// Category: edge
#[test]
fn test_boxed_type() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let boxed: Box<Vec<i32>> = Box::new(vec![1, 2, 3, 4, 5]);
announcer.announce(boxed.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(boxed));
}
/// Test: Edge case: Arc with interior mutability
///
/// Verifies: Handles edge case: arc with interior mutability
/// Category: edge
#[test]
fn test_arc_mutex() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let data = Arc::new(Mutex::new(42));
announcer.announce(data.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(*received.lock().unwrap(), 42);
}
/// Test: Interior mutability: Arc<Rwlock<T>>
///
/// Verifies: Handles Arc-wrapped rwlock correctly
/// Category: edge
#[test]
fn test_arc_rwlock() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let data = Arc::new(RwLock::new(vec![1, 2, 3]));
announcer.announce(data.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(*received.read().unwrap(), vec![1, 2, 3]);
}
/// Test: Edge case: Empty strings and vectors
///
/// Verifies: Handles edge case: empty strings and vectors
/// Category: edge
#[test]
fn test_empty_string() {
let (announcer, announcement) = Announcement::<String>::new();
let listener = announcement.listener();
announcer.announce(String::new()).unwrap();
assert_eq!(listener.try_listen(), Some(String::new()));
}
/// Test: Empty collection: empty vec
///
/// Verifies: Handles empty vec correctly
/// Category: edge
#[test]
fn test_empty_vec() {
let (announcer, announcement) = Announcement::<Vec<i32>>::new();
let listener = announcement.listener();
announcer.announce(Vec::new()).unwrap();
assert_eq!(listener.try_listen(), Some(Vec::new()));
}
/// Test: Edge case: Very long strings
///
/// Verifies: Handles edge case: very long strings
/// Category: edge
#[test]
fn test_very_long_string() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let long_string = "x".repeat(10_000_000); // 10MB string
announcer.announce(long_string.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.len(), 10_000_000);
}
/// Test: Edge case: Arrays of different sizes
///
/// Verifies: Handles edge case: arrays of different sizes
/// Category: edge
#[test]
fn test_zero_sized_array() {
let (announcer, announcement) = Announcement::<[u8; 0]>::new();
let listener = announcement.listener();
announcer.announce([]).unwrap();
assert_eq!(listener.try_listen(), Some([]));
}
/// Test: Array: small fixed-size array
///
/// Verifies: Handles small fixed-size arrays
/// Category: edge
#[test]
fn test_small_array() {
let (announcer, announcement) = Announcement::<[i32; 3]>::new();
let listener = announcement.listener();
announcer.announce([1, 2, 3]).unwrap();
assert_eq!(listener.try_listen(), Some([1, 2, 3]));
}
/// Test: Array: large fixed-size array (1KB)
///
/// Verifies: Handles large fixed-size arrays
/// Category: edge
#[test]
fn test_large_array() {
let (announcer, announcement) = Announcement::<[u8; 1024]>::new();
let listener = announcement.listener();
let array = [42u8; 1024];
announcer.announce(array).unwrap();
assert_eq!(listener.try_listen(), Some(array));
}
/// Test: Edge case: Tuples
///
/// Verifies: Handles edge case: tuples
/// Category: edge
#[test]
fn test_simple_tuple() {
let (announcer, announcement) = Announcement::<(i32, i32)>::new();
let listener = announcement.listener();
announcer.announce((1, 2)).unwrap();
assert_eq!(listener.try_listen(), Some((1, 2)));
}
/// Test: Tuple: complex tuple
///
/// Verifies: Handles complex tuple correctly
/// Category: edge
#[test]
fn test_complex_tuple() {
let (announcer, announcement) = Announcement::<(String, Vec<u8>, i32, Option<bool>)>::new();
let listener = announcement.listener();
let tuple = ("hello".to_string(), vec![1, 2, 3], 42, Some(true));
announcer.announce(tuple.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(tuple));
}
/// Test: Edge case: Custom struct with Drop
///
/// Verifies: Handles edge case: custom struct with drop
/// Category: edge
#[test]
fn test_struct_with_drop() {
static DROP_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
#[derive(Clone, Debug)]
#[allow(dead_code)]
struct DropCounter {
value: i32,
}
impl Drop for DropCounter {
fn drop(&mut self) {
DROP_COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
}
}
DROP_COUNT.store(0, std::sync::atomic::Ordering::SeqCst);
{
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let counter = DropCounter { value: 42 };
announcer.announce(counter).unwrap();
let _received = listener.try_listen();
}
// Check that drops happened
assert!(DROP_COUNT.load(std::sync::atomic::Ordering::SeqCst) > 0);
}
/// Test: Edge case: Enums
///
/// Verifies: Handles edge case: enums
/// Category: edge
#[test]
fn test_simple_enum() {
#[derive(Clone, Debug, PartialEq)]
#[allow(dead_code)]
enum SimpleEnum {
A,
B,
C,
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(SimpleEnum::B).unwrap();
assert_eq!(listener.try_listen(), Some(SimpleEnum::B));
}
/// Test: Enum: complex enum
///
/// Verifies: Handles complex enum with variants correctly
/// Category: edge
#[test]
fn test_complex_enum() {
#[derive(Clone, Debug, PartialEq)]
#[allow(dead_code)]
enum ComplexEnum {
Empty,
Value(i32),
Tuple(String, Vec<u8>),
Struct { x: f64, y: f64 },
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let val = ComplexEnum::Tuple("test".to_string(), vec![1, 2, 3]);
announcer.announce(val.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(val));
}
/// Test: Edge case: PhantomData
///
/// Verifies: Handles edge case: phantomdata
/// Category: edge
#[test]
fn test_phantom_data() {
use std::marker::PhantomData;
#[derive(Clone, Debug)]
struct Phantom<T> {
value: i32,
_phantom: PhantomData<T>,
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let phantom: Phantom<String> = Phantom {
value: 42,
_phantom: PhantomData,
};
announcer.announce(phantom).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.value, 42);
}
/// Test: Edge case: Function pointers
///
/// Verifies: Handles edge case: function pointers
/// Category: edge
#[test]
fn test_function_pointer() {
fn example_fn() -> i32 {
42
}
let (announcer, announcement) = Announcement::<fn() -> i32>::new();
let listener = announcement.listener();
announcer.announce(example_fn).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received(), 42);
}
/// Test: Edge case: Trait objects
///
/// Verifies: Handles edge case: trait objects
/// Category: edge
#[test]
fn test_trait_object() {
trait MyTrait: Send + Sync {
fn value(&self) -> i32;
}
#[derive(Clone)]
struct MyStruct(i32);
impl MyTrait for MyStruct {
fn value(&self) -> i32 {
self.0
}
}
let (announcer, announcement) = Announcement::<Arc<dyn MyTrait>>::new();
let listener = announcement.listener();
let obj: Arc<dyn MyTrait> = Arc::new(MyStruct(42));
let _ = announcer.announce(obj); // Can't use unwrap because dyn MyTrait doesn't implement Debug
let received = listener.try_listen().unwrap();
assert_eq!(received.value(), 42);
}
/// Test: Edge case: Deeply nested structures
///
/// Verifies: Handles edge case: deeply nested structures
/// Category: edge
#[test]
fn test_deeply_nested_structure() {
#[derive(Clone, Debug)]
struct Level1(Level2);
#[derive(Clone, Debug)]
struct Level2(Level3);
#[derive(Clone, Debug)]
struct Level3(Level4);
#[derive(Clone, Debug)]
struct Level4(Level5);
#[derive(Clone, Debug)]
struct Level5(Level6);
#[derive(Clone, Debug)]
struct Level6(Level7);
#[derive(Clone, Debug)]
struct Level7(Level8);
#[derive(Clone, Debug)]
struct Level8(Level9);
#[derive(Clone, Debug)]
struct Level9(Level10);
#[derive(Clone, Debug)]
struct Level10(i32);
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let nested = Level1(Level2(Level3(Level4(Level5(Level6(Level7(Level8(
Level9(Level10(42)),
))))))));
announcer.announce(nested).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.0 .0 .0 .0 .0 .0 .0 .0 .0 .0, 42);
}
/// Test: Edge case: Listener created after drop of announcer
///
/// Verifies: Handles edge case: listener created after drop of announcer
/// Category: edge
#[test]
fn test_listener_after_announcer_drop() {
let announcement = {
let (announcer, announcement) = Announcement::<i32>::new();
drop(announcer);
announcement
};
let listener = announcement.listener();
assert_eq!(listener.try_listen(), None);
}
/// Test: Edge case: Clone announcement after announce
///
/// Verifies: Handles edge case: clone announcement after announce
/// Category: edge
#[test]
fn test_clone_announcement_after_announce() {
let (announcer, announcement) = Announcement::new();
announcer.announce(42).unwrap();
let cloned = announcement.clone();
let listener = cloned.listener();
assert_eq!(listener.try_listen(), Some(42));
}
/// Test: Edge case: Many threads creating listeners simultaneously
///
/// Verifies: Handles edge case: many threads creating listeners simultaneously
/// Category: edge
#[test]
fn test_concurrent_listener_creation() {
let (announcer, announcement) = Announcement::new();
let mut handles = vec![];
for _ in 0..100 {
let announcement_clone = announcement.clone();
handles.push(thread::spawn(move || announcement_clone.listener()));
}
let listeners: Vec<_> = handles.into_iter().map(|h| h.join().unwrap()).collect();
announcer.announce(42).unwrap();
for listener in &listeners {
assert_eq!(listener.try_listen(), Some(42));
}
}
/// Test: Edge case: Maximum value sizes
///
/// Verifies: Handles edge case: maximum value sizes
/// Category: edge
#[test]
fn test_max_u128() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(u128::MAX).unwrap();
assert_eq!(listener.try_listen(), Some(u128::MAX));
}
/// Test: Numeric boundary: i128::MIN
///
/// Verifies: Handles minimum signed 128-bit integer value
/// Category: edge
#[test]
fn test_min_i128() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(i128::MIN).unwrap();
assert_eq!(listener.try_listen(), Some(i128::MIN));
}
/// Test: Edge case: NaN and infinity for floats
///
/// Verifies: Handles edge case: nan and infinity for floats
/// Category: edge
#[test]
fn test_nan_f64() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(f64::NAN).unwrap();
let received = listener.try_listen().unwrap();
assert!(received.is_nan());
}
/// Test: Special value: floating point infinity
///
/// Verifies: Handles positive/negative infinity correctly
/// Category: edge
#[test]
fn test_infinity_f32() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(f32::INFINITY).unwrap();
assert_eq!(listener.try_listen(), Some(f32::INFINITY));
}
/// Test: Special value: floating point infinity
///
/// Verifies: Handles positive/negative infinity correctly
/// Category: edge
#[test]
fn test_neg_infinity_f64() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(f64::NEG_INFINITY).unwrap();
assert_eq!(listener.try_listen(), Some(f64::NEG_INFINITY));
}
/// Test: Edge case: Unicode strings
///
/// Verifies: Handles edge case: unicode strings
/// Category: edge
#[test]
fn test_unicode_emoji() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let emoji_string = "Hello 👋 World 🌍 🦀".to_string();
announcer.announce(emoji_string.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(emoji_string));
}
/// Test: Unicode: unicode rtl
///
/// Verifies: Handles unicode rtl correctly
/// Category: edge
#[test]
fn test_unicode_rtl() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let rtl_string = "مرحبا بالعالم".to_string();
announcer.announce(rtl_string.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(rtl_string));
}
/// Test: Unicode: unicode combining
///
/// Verifies: Handles unicode combining correctly
/// Category: edge
#[test]
fn test_unicode_combining() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let combining = "e\u{0301}".to_string(); // é as e + combining accent
announcer.announce(combining.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(combining));
}
/// Test: Edge case: Memory size checks
///
/// Verifies: Handles edge case: memory size checks
/// Category: edge
#[test]
fn test_announcement_memory_size() {
let size = mem::size_of::<Announcement<i32>>();
// Should be relatively small (just Arc pointers)
// Two Arc pointers on 64-bit: inner + event
assert!(size <= 16);
}
/// Test: Memory efficiency: Listener<T> size
///
/// Verifies: Verifies Listener type has minimal memory footprint
/// Category: edge
#[test]
fn test_listener_memory_size() {
let size = mem::size_of::<Listener<i32>>();
// Should be same as Announcement
// Two Arc pointers on 64-bit: inner + event
assert!(size <= 16);
}
/// Test: Edge case: Listener dropped immediately after creation
///
/// Verifies: Handles edge case: listener dropped immediately after creation
/// Category: edge
#[test]
fn test_listener_immediate_drop() {
let (announcer, announcement) = Announcement::new();
for _ in 0..1000 {
drop(announcement.listener());
}
announcer.announce(42).unwrap();
// Should still work with new listener
let listener = announcement.listener();
assert_eq!(listener.try_listen(), Some(42));
}
/// Test: Edge case: Announcement with closure
///
/// Verifies: Handles edge case: announcement with closure
/// Category: edge
#[test]
fn test_announcement_with_closure() {
let (announcer, announcement) = Announcement::<Arc<dyn Fn() -> i32 + Send + Sync>>::new();
let listener = announcement.listener();
let closure = Arc::new(|| 42) as Arc<dyn Fn() -> i32 + Send + Sync>;
let _ = announcer.announce(closure); // Can't use unwrap because dyn Fn doesn't implement Debug
let received = listener.try_listen().unwrap();
assert_eq!(received(), 42);
}
/// Test: Edge case: Announcement channel dropped before listeners
///
/// Verifies: Handles edge case: announcement channel dropped before listeners
/// Category: edge
#[test]
fn test_announcement_dropped_before_listeners() {
let listener = {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(42).unwrap();
drop(announcement);
listener
};
assert_eq!(listener.try_listen(), Some(42));
}
/// Test: Edge case: Multiple announcement channels at once
///
/// Verifies: Handles edge case: multiple announcement channels at once
/// Category: edge
#[test]
fn test_multiple_channels() {
let (a1, ann1) = Announcement::<i32>::new();
let (a2, ann2) = Announcement::<String>::new();
let (a3, ann3) = Announcement::<Vec<u8>>::new();
let l1 = ann1.listener();
let l2 = ann2.listener();
let l3 = ann3.listener();
a1.announce(42).unwrap();
a2.announce("hello".to_string()).unwrap();
a3.announce(vec![1, 2, 3]).unwrap();
assert_eq!(l1.try_listen(), Some(42));
assert_eq!(l2.try_listen(), Some("hello".to_string()));
assert_eq!(l3.try_listen(), Some(vec![1, 2, 3]));
}
/// Test: Edge case: Char boundary cases
///
/// Verifies: Handles edge case: char boundary cases
/// Category: edge
#[test]
fn test_char_boundaries() {
let (announcer, announcement) = Announcement::<char>::new();
let listener = announcement.listener();
announcer.announce('\0').unwrap();
assert_eq!(listener.try_listen(), Some('\0'));
let (announcer2, announcement2) = Announcement::<char>::new();
let listener2 = announcement2.listener();
announcer2.announce('\u{10FFFF}').unwrap();
assert_eq!(listener2.try_listen(), Some('\u{10FFFF}'));
}
/// Test: Edge case: Bool values
///
/// Verifies: Handles edge case: bool values
/// Category: edge
#[test]
fn test_bool_true() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(true).unwrap();
assert_eq!(listener.try_listen(), Some(true));
}
/// Test: Boolean: bool false
///
/// Verifies: Handles boolean false value
/// Category: edge
#[test]
fn test_bool_false() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(false).unwrap();
assert_eq!(listener.try_listen(), Some(false));
}
/// Test: Edge case: Nested Options
///
/// Verifies: Handles edge case: nested options
/// Category: edge
#[test]
fn test_nested_options() {
type NestedOption = Option<Option<Option<i32>>>;
let (announcer, announcement) = Announcement::<NestedOption>::new();
let listener = announcement.listener();
announcer.announce(Some(Some(Some(42)))).unwrap();
assert_eq!(listener.try_listen(), Some(Some(Some(Some(42)))));
}
/// Test: Edge case: Nested Results
///
/// Verifies: Handles edge case: nested results
/// Category: edge
#[test]
fn test_nested_results() {
type NestedResult = Result<Result<i32, String>, Vec<u8>>;
let (announcer, announcement) = Announcement::<NestedResult>::new();
let listener = announcement.listener();
announcer.announce(Ok(Ok(42))).unwrap();
assert_eq!(listener.try_listen(), Some(Ok(Ok(42))));
}
/// Test: Edge case: Empty collections
///
/// Verifies: Handles edge case: empty collections
/// Category: edge
#[test]
fn test_empty_hashmap() {
let (announcer, announcement) = Announcement::<HashMap<String, i32>>::new();
let listener = announcement.listener();
announcer.announce(HashMap::new()).unwrap();
assert_eq!(listener.try_listen(), Some(HashMap::new()));
}
/// Test: Empty collection: empty btreemap
///
/// Verifies: Handles empty btreemap correctly
/// Category: edge
#[test]
fn test_empty_btreemap() {
let (announcer, announcement) = Announcement::<BTreeMap<i32, String>>::new();
let listener = announcement.listener();
announcer.announce(BTreeMap::new()).unwrap();
assert_eq!(listener.try_listen(), Some(BTreeMap::new()));
}
/// Test: Edge case: Single element collections
///
/// Verifies: Handles edge case: single element collections
/// Category: edge
#[test]
fn test_single_element_vec() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(vec![42]).unwrap();
assert_eq!(listener.try_listen(), Some(vec![42]));
}
/// Test: Collection boundary: single element collections
///
/// Verifies: Handles collections with exactly one element
/// Category: edge
#[test]
fn test_single_element_hashset() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let mut set = HashSet::new();
set.insert("only");
announcer.announce(set.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(set));
}
/// Test: Edge case: Reference counting edge cases
///
/// Verifies: Handles edge case: reference counting edge cases
/// Category: edge
#[test]
fn test_arc_refcount_after_announce() {
let (announcer, announcement) = Announcement::new();
let data = Arc::new(42);
let initial_count = Arc::strong_count(&data);
let l1 = announcement.listener();
let l2 = announcement.listener();
announcer.announce(data.clone()).unwrap();
let r1 = l1.try_listen().unwrap();
let _r2 = l2.try_listen().unwrap();
// Should be: original + internal + r1 + r2
assert_eq!(Arc::strong_count(&r1), initial_count + 3);
}
/// Test: Edge case: Path-like strings
///
/// Verifies: Handles edge case: path-like strings
/// Category: edge
#[test]
fn test_path_strings() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let path = "/usr/local/bin/../../lib".to_string();
announcer.announce(path.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(path));
}
/// Test: Edge case: SQL injection attempt strings
///
/// Verifies: Handles edge case: sql injection attempt strings
/// Category: edge
#[test]
fn test_sql_injection_string() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let sql = "'; DROP TABLE users; --".to_string();
announcer.announce(sql.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(sql));
}
/// Test: Edge case: Listener cloned multiple times
///
/// Verifies: Handles edge case: listener cloned multiple times
/// Category: edge
#[test]
fn test_listener_clone_chain() {
let (announcer, announcement) = Announcement::new();
let l1 = announcement.listener();
let l2 = l1.clone();
let l3 = l2.clone();
let l4 = l3.clone();
announcer.announce(42).unwrap();
assert_eq!(l1.try_listen(), Some(42));
assert_eq!(l2.try_listen(), Some(42));
assert_eq!(l3.try_listen(), Some(42));
assert_eq!(l4.try_listen(), Some(42));
}
/// Test: Edge case: Announcement cloned multiple times
///
/// Verifies: Handles edge case: announcement cloned multiple times
/// Category: edge
#[test]
fn test_announcement_clone_chain() {
let (announcer, announcement) = Announcement::new();
let a2 = announcement.clone();
let a3 = a2.clone();
let a4 = a3.clone();
let l1 = announcement.listener();
let l2 = a2.listener();
let l3 = a3.listener();
let l4 = a4.listener();
announcer.announce(42).unwrap();
assert_eq!(l1.try_listen(), Some(42));
assert_eq!(l2.try_listen(), Some(42));
assert_eq!(l3.try_listen(), Some(42));
assert_eq!(l4.try_listen(), Some(42));
}
/// Test: Edge case: Mixed listener creation timing
///
/// Verifies: Handles edge case: mixed listener creation timing
/// Category: edge
#[test]
fn test_mixed_timing_listeners() {
let (announcer, announcement) = Announcement::new();
let before1 = announcement.listener();
let before2 = announcement.listener();
announcer.announce(42).unwrap();
let after1 = announcement.listener();
let after2 = announcement.listener();
assert_eq!(before1.try_listen(), Some(42));
assert_eq!(before2.try_listen(), Some(42));
assert_eq!(after1.try_listen(), Some(42));
assert_eq!(after2.try_listen(), Some(42));
}
/// Test: Edge case: Thread-local storage interaction
///
/// Verifies: Handles edge case: thread-local storage interaction
/// Category: edge
#[test]
fn test_thread_local_interaction() {
thread_local! {
static COUNTER: std::cell::Cell<i32> = const { std::cell::Cell::new(0) };
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
COUNTER.with(|c| c.set(100));
announcer.announce(42).unwrap();
assert_eq!(listener.try_listen(), Some(42));
assert_eq!(COUNTER.with(|c| c.get()), 100);
}
/// Test: Edge case: Panic safety - announcer panics before announce
///
/// Verifies: Handles edge case: panic safety - announcer panics before announce
/// Category: edge
#[test]
fn test_panic_before_announce() {
let result = std::panic::catch_unwind(|| {
let (_announcer, announcement) = Announcement::<i32>::new();
let _listener = announcement.listener();
panic!("Intentional panic");
#[allow(unreachable_code)]
_announcer.announce(42).unwrap();
});
assert!(result.is_err());
}
/// Test: Edge case: Maximum listeners on single announcement
///
/// Verifies: Handles edge case: maximum listeners on single announcement
/// Category: edge
#[test]
fn test_max_listeners_single_announcement() {
let (announcer, announcement) = Announcement::new();
let mut listeners = Vec::new();
for _ in 0..10000 {
listeners.push(announcement.listener());
}
announcer.announce(42).unwrap();
// Sample check
assert_eq!(listeners[0].try_listen(), Some(42));
assert_eq!(listeners[5000].try_listen(), Some(42));
assert_eq!(listeners[9999].try_listen(), Some(42));
}
/// Test: Edge case: Alternating operations
///
/// Verifies: Handles edge case: alternating operations
/// Category: edge
#[test]
fn test_alternating_operations() {
let (announcer, announcement) = Announcement::new();
let _l1 = announcement.listener();
assert!(!announcement.is_announced());
let _l2 = announcement.listener();
assert!(!announcement.is_announced());
let _l3 = announcement.listener();
assert!(!announcement.is_announced());
announcer.announce(42).unwrap();
assert!(announcement.is_announced());
let l4 = announcement.listener();
assert!(announcement.is_announced());
assert_eq!(l4.try_listen(), Some(42));
}
/// Test: Edge case: Error type validation
///
/// Verifies: Handles edge case: error type validation
/// Category: edge
#[test]
fn test_error_types() {
let err = AnnounceError::AlreadyAnnounced(42);
assert_eq!(format!("{}", err), "a value has already been announced");
assert_eq!(format!("{:?}", err), "AlreadyAnnounced(42)");
}
/// Test: Edge case: Boundary timing test
///
/// Verifies: Handles edge case: boundary timing test
/// Category: edge
#[test]
fn test_announce_exactly_with_try_listen() {
for _ in 0..100 {
let (announcer, announcement) = Announcement::new();
let announcement2 = announcement.clone();
let handle = thread::spawn(move || announcement2.listener().try_listen());
// Try to announce at nearly the same time
announcer.announce(42).unwrap();
let result = handle.join().unwrap();
// Could be Some or None depending on exact timing
assert!(result.is_none() || result == Some(42));
}
}
/// Test: Edge case: String with null bytes
///
/// Verifies: Handles edge case: string with null bytes
/// Category: edge
#[test]
fn test_string_with_nulls() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let s = "hello\0world\0test".to_string();
announcer.announce(s.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(s));
}
/// Test: Edge case: Maximum tuple size
///
/// Verifies: Handles edge case: maximum tuple size
/// Category: edge
#[test]
fn test_12_tuple() {
type BigTuple = (i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32);
let (announcer, announcement) = Announcement::<BigTuple>::new();
let listener = announcement.listener();
let tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
announcer.announce(tuple).unwrap();
assert_eq!(listener.try_listen(), Some(tuple));
}
/// Test: Edge case: Negative array indices simulation
///
/// Verifies: Handles edge case: negative array indices simulation
/// Category: edge
#[test]
fn test_vec_with_negative_pattern() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
// Simulate negative indexing pattern
let vec = vec![-1, -2, -3, 0, 1, 2, 3];
announcer.announce(vec.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(vec));
}
/// Test: Edge case: Floating point special values
///
/// Verifies: Handles edge case: floating point special values
/// Category: edge
#[test]
fn test_float_special_values() {
let (announcer, announcement) = Announcement::<Vec<f64>>::new();
let listener = announcement.listener();
let specials = vec![
0.0,
-0.0,
f64::MIN_POSITIVE,
f64::MAX,
f64::MIN,
f64::EPSILON,
];
announcer.announce(specials.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(specials));
}
/// Test: Edge case: UTF-8 boundary test
///
/// Verifies: Handles edge case: utf-8 boundary test
/// Category: edge
#[test]
fn test_utf8_boundaries() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
// Various UTF-8 sequences
let s = "A೻ಇ👍🏿Z".to_string();
announcer.announce(s.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(s));
}
/// Test: Edge case: Lifetime boundary with static
///
/// Verifies: Handles edge case: lifetime boundary with static
/// Category: edge
#[test]
fn test_static_str() {
let (announcer, announcement) = Announcement::<&'static str>::new();
let listener = announcement.listener();
announcer.announce("static string").unwrap();
assert_eq!(listener.try_listen(), Some("static string"));
}
/// Test: Edge case: Very fast repeated checks
///
/// Verifies: Handles edge case: very fast repeated checks
/// Category: edge
#[test]
fn test_spin_wait_pattern() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let announcement_clone = announcement.clone();
thread::spawn(move || {
thread::sleep(Duration::from_millis(1));
announcer.announce(42).unwrap();
});
// Spin wait
while listener.try_listen().is_none() {
std::hint::spin_loop();
}
assert_eq!(listener.try_listen(), Some(42));
assert!(announcement_clone.is_announced());
}
/// Test: Edge case: Memory ordering stress
///
/// Verifies: Handles edge case: memory ordering stress
/// Category: edge
#[test]
fn test_memory_ordering_stress() {
use std::sync::atomic::{AtomicBool, Ordering};
let (announcer, announcement) = Announcement::new();
let flag = Arc::new(AtomicBool::new(false));
let listener = announcement.listener();
let flag_clone = flag.clone();
thread::spawn(move || {
flag_clone.store(true, Ordering::Release);
announcer.announce(42).unwrap();
});
while !flag.load(Ordering::Acquire) {
thread::yield_now();
}
// Flag is set, announcement should be visible soon
thread::sleep(Duration::from_millis(1));
assert_eq!(listener.try_listen(), Some(42));
}
/// Test: Edge case: Drop order testing
///
/// Verifies: Handles edge case: drop order testing
/// Category: edge
#[test]
fn test_drop_order() {
use std::sync::atomic::{AtomicUsize, Ordering};
static DROP_ORDER: AtomicUsize = AtomicUsize::new(0);
#[derive(Clone, Debug)]
struct DropOrderTest(usize);
impl Drop for DropOrderTest {
fn drop(&mut self) {
DROP_ORDER.fetch_add(self.0, Ordering::SeqCst);
}
}
DROP_ORDER.store(0, Ordering::SeqCst);
{
let (announcer, announcement) = Announcement::new();
let _listener = announcement.listener();
announcer.announce(DropOrderTest(1)).unwrap();
}
assert!(DROP_ORDER.load(Ordering::SeqCst) > 0);
}
/// Test: Edge case: Const array patterns
///
/// Verifies: Handles edge case: const array patterns
/// Category: edge
#[test]
fn test_const_array() {
const ARRAY: [i32; 5] = [1, 2, 3, 4, 5];
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(ARRAY).unwrap();
assert_eq!(listener.try_listen(), Some(ARRAY));
}
/// Test: Edge case: Mixed collection types
///
/// Verifies: Handles edge case: mixed collection types
/// Category: edge
#[test]
fn test_vec_of_hashmaps() {
let (announcer, announcement) = Announcement::<Vec<HashMap<String, i32>>>::new();
let listener = announcement.listener();
let mut map1 = HashMap::new();
map1.insert("a".to_string(), 1);
let mut map2 = HashMap::new();
map2.insert("b".to_string(), 2);
let vec = vec![map1, map2];
announcer.announce(vec.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(vec));
}
/// Test: Edge case: Hashmap with complex values
///
/// Verifies: Handles edge case: hashmap with complex values
/// Category: edge
#[test]
fn test_hashmap_complex_values() {
let (announcer, announcement) = Announcement::<HashMap<String, Vec<Option<i32>>>>::new();
let listener = announcement.listener();
let mut map = HashMap::new();
map.insert("key1".to_string(), vec![Some(1), None, Some(2)]);
map.insert("key2".to_string(), vec![]);
announcer.announce(map.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(map));
}
/// Test: Edge case: Maximum safe integer boundaries
///
/// Verifies: Handles edge case: maximum safe integer boundaries
/// Category: edge
#[test]
fn test_safe_integer_boundaries() {
// JavaScript MAX_SAFE_INTEGER equivalent
const MAX_SAFE: i64 = 9_007_199_254_740_991;
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(MAX_SAFE).unwrap();
assert_eq!(listener.try_listen(), Some(MAX_SAFE));
}
/// Test: Edge case: Bitwise patterns
///
/// Verifies: Handles edge case: bitwise patterns
/// Category: edge
#[test]
fn test_bitwise_patterns() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let pattern: u64 = 0xDEADBEEF_CAFEBABE;
announcer.announce(pattern).unwrap();
assert_eq!(listener.try_listen(), Some(pattern));
}
/// Test: Edge case: String escaping patterns
///
/// Verifies: Handles edge case: string escaping patterns
/// Category: edge
#[test]
fn test_string_escaping() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let s = "\"Hello\"\n\r\t\\World\\".to_string();
announcer.announce(s.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(s));
}
/// Test: Edge case: Recursive enum
///
/// Verifies: Handles edge case: recursive enum
/// Category: edge
#[test]
fn test_recursive_enum() {
#[derive(Clone, Debug, PartialEq)]
enum Tree {
Leaf(i32),
Node(Box<Tree>, Box<Tree>),
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let tree = Tree::Node(
Box::new(Tree::Leaf(1)),
Box::new(Tree::Node(Box::new(Tree::Leaf(2)), Box::new(Tree::Leaf(3)))),
);
announcer.announce(tree.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(tree));
}
/// Test: Edge case: Type with lifetime parameter via Arc
///
/// Verifies: Handles edge case: type with lifetime parameter via arc
/// Category: edge
#[test]
fn test_type_with_lifetime() {
#[derive(Clone, Debug)]
struct WithData {
text: String,
number: i32,
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let data = Arc::new(WithData {
text: "test".to_string(),
number: 42,
});
announcer.announce(data.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.text, "test");
assert_eq!(received.number, 42);
}
/// Test: Edge case: Mixed sync primitives
///
/// Verifies: Handles edge case: mixed sync primitives
/// Category: edge
#[test]
fn test_mixed_sync_primitives() {
use std::sync::RwLock;
#[derive(Clone, Debug)]
struct MixedSync {
mutex_data: Arc<Mutex<i32>>,
rwlock_data: Arc<RwLock<String>>,
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let mixed = MixedSync {
mutex_data: Arc::new(Mutex::new(42)),
rwlock_data: Arc::new(RwLock::new("test".to_string())),
};
announcer.announce(mixed.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(*received.mutex_data.lock().unwrap(), 42);
assert_eq!(*received.rwlock_data.read().unwrap(), "test");
}
/// Test: Edge case: Whitespace strings
///
/// Verifies: Handles edge case: whitespace strings
/// Category: edge
#[test]
fn test_whitespace_strings() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let whitespace = " \t\n\r\u{00A0}\u{2003} ".to_string();
announcer.announce(whitespace.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(whitespace));
}
/// Test: Edge case: Binary data patterns
///
/// Verifies: Handles edge case: binary data patterns
/// Category: edge
#[test]
fn test_binary_patterns() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let binary = vec![0x00, 0xFF, 0xAA, 0x55, 0x0F, 0xF0];
announcer.announce(binary.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(binary));
}
/// Test: Edge case: HashMap with collision-prone keys
///
/// Verifies: Handles edge case: hashmap with collision-prone keys
/// Category: edge
#[test]
fn test_hashmap_collision_keys() {
let (announcer, announcement) = Announcement::<HashMap<i32, String>>::new();
let listener = announcement.listener();
let mut map = HashMap::new();
// These might cause collisions in some hash implementations
for i in 0..100 {
map.insert(i * 65536, format!("value_{}", i));
}
announcer.announce(map.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.len(), 100);
}
/// Test: Edge case: Partial move semantics
///
/// Verifies: Handles edge case: partial move semantics
/// Category: edge
#[test]
fn test_partial_struct() {
#[derive(Clone, Debug)]
struct Partial {
owned: String,
reference: i32,
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let partial = Partial {
owned: "owned data".to_string(),
reference: 42,
};
announcer.announce(partial.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert_eq!(received.owned, "owned data");
assert_eq!(received.reference, 42);
}
/// Test: Edge case: Extreme thread contention
///
/// Verifies: Handles edge case: extreme thread contention
/// Category: edge
#[test]
fn test_extreme_thread_contention() {
let (announcer, announcement) = Announcement::new();
let mut handles = vec![];
// 50 threads all trying to check at once
for _ in 0..50 {
let ann = announcement.clone();
handles.push(thread::spawn(move || {
for _ in 0..1000 {
let _ = ann.is_announced();
}
}));
}
thread::sleep(Duration::from_millis(10));
announcer.announce(42).unwrap();
for handle in handles {
handle.join().unwrap();
}
assert!(announcement.is_announced());
}
/// Test: Edge case: Cross-thread announcement verification
///
/// Verifies: Handles edge case: cross-thread announcement verification
/// Category: edge
#[test]
fn test_cross_thread_verification() {
let (announcer, announcement) = Announcement::new();
let ann1 = announcement.clone();
let ann2 = announcement.clone();
let h1 = thread::spawn(move || ann1.is_announced());
let h2 = thread::spawn(move || {
announcer.announce(42).unwrap();
});
h2.join().unwrap();
thread::sleep(Duration::from_millis(1));
let h3 = thread::spawn(move || ann2.is_announced());
let _ = h1.join().unwrap(); // May or may not see it
assert!(h3.join().unwrap()); // Must see it
}
/// Test: Edge case: Zero capacity collections
///
/// Verifies: Handles edge case: zero capacity collections
/// Category: edge
#[test]
fn test_zero_capacity_vec() {
let (announcer, announcement) = Announcement::<Vec<i32>>::new();
let listener = announcement.listener();
let vec = Vec::with_capacity(0);
announcer.announce(vec.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(vec));
}
/// Test: Edge case: Enum with many variants
///
/// Verifies: Handles edge case: enum with many variants
/// Category: edge
#[test]
fn test_large_enum() {
#[derive(Clone, Debug, PartialEq)]
#[allow(dead_code)]
enum LargeEnum {
V1,
V2,
V3,
V4,
V5,
V6,
V7,
V8,
V9,
V10,
V11,
V12,
V13,
V14,
V15,
V16,
V17,
V18,
V19,
V20,
V21(i32),
V22(String),
V23(Vec<u8>),
}
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(LargeEnum::V23(vec![1, 2, 3])).unwrap();
assert_eq!(listener.try_listen(), Some(LargeEnum::V23(vec![1, 2, 3])));
}
/// Test: Edge case: Thread priority interactions
///
/// Verifies: Handles edge case: thread priority interactions
/// Category: edge
#[test]
#[cfg(not(target_os = "macos"))]
fn test_thread_yield_pattern() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
thread::spawn(move || {
for _ in 0..100 {
thread::yield_now();
}
announcer.announce(42).unwrap();
});
thread::sleep(Duration::from_millis(50));
assert_eq!(listener.try_listen(), Some(42));
}
/// Test: Edge case: Poisoned mutex in announced value
///
/// Verifies: Handles edge case: poisoned mutex in announced value
/// Category: edge
#[test]
fn test_poisoned_mutex() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let mutex = Arc::new(Mutex::new(42));
// Poison the mutex
let mutex_clone = mutex.clone();
let _ = thread::spawn(move || {
let _guard = mutex_clone.lock().unwrap();
panic!("Intentional panic to poison mutex");
})
.join();
announcer.announce(mutex.clone()).unwrap();
let received = listener.try_listen().unwrap();
assert!(received.lock().is_err()); // Should be poisoned
}
/// Test: Edge case: Special filesystem characters in strings
///
/// Verifies: Handles edge case: special filesystem characters in strings
/// Category: edge
#[test]
fn test_filesystem_special_chars() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let special = "../../../etc/passwd\0.txt".to_string();
announcer.announce(special.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(special));
}
/// Test: Edge case: Integer overflow patterns
///
/// Verifies: Handles edge case: integer overflow patterns
/// Category: edge
#[test]
fn test_overflow_patterns() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let values = vec![u32::MAX, u32::MAX - 1, 0, 1, u32::MAX / 2];
announcer.announce(values.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(values));
}
/// Test: Edge case: Negative zero float
///
/// Verifies: Handles edge case: negative zero float
/// Category: edge
#[test]
fn test_negative_zero() {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
let neg_zero = -0.0_f64;
announcer.announce(neg_zero).unwrap();
let received = listener.try_listen().unwrap();
assert!(received.is_sign_negative());
assert_eq!(received, 0.0);
}
/// Test: Edge case: Complex generic nesting
///
/// Verifies: Handles edge case: complex generic nesting
/// Category: edge
#[test]
fn test_complex_generics() {
type Complex = HashMap<String, Vec<Option<Result<i32, String>>>>;
let (announcer, announcement) = Announcement::<Complex>::new();
let listener = announcement.listener();
let mut complex = HashMap::new();
complex.insert(
"key".to_string(),
vec![Some(Ok(1)), None, Some(Err("error".to_string()))],
);
announcer.announce(complex.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(complex));
}
/// Test: Edge case: Many small announcements sequentially
///
/// Verifies: Handles edge case: many small announcements sequentially
/// Category: edge
#[test]
fn test_sequential_small_announcements() {
for i in 0..100 {
let (announcer, announcement) = Announcement::new();
let listener = announcement.listener();
announcer.announce(i).unwrap();
assert_eq!(listener.try_listen(), Some(i));
}
}
/// Test: Edge case: Listener after multiple is_announced checks
///
/// Verifies: Handles edge case: listener after multiple is_announced checks
/// Category: edge
#[test]
fn test_listener_after_many_checks() {
let (announcer, announcement) = Announcement::new();
for _ in 0..1000 {
assert!(!announcement.is_announced());
}
let listener = announcement.listener();
announcer.announce(42).unwrap();
for _ in 0..1000 {
assert!(announcement.is_announced());
}
assert_eq!(listener.try_listen(), Some(42));
}
/// Test: Edge case: Type aliases
///
/// Verifies: Handles edge case: type aliases
/// Category: edge
#[test]
fn test_type_aliases() {
type MyString = String;
type MyVec = Vec<MyString>;
let (announcer, announcement) = Announcement::<MyVec>::new();
let listener = announcement.listener();
let data: MyVec = vec!["a".to_string(), "b".to_string()];
announcer.announce(data.clone()).unwrap();
assert_eq!(listener.try_listen(), Some(data));
}
/// Test: Edge case: Final edge case - announcement reuse attempt
///
/// Verifies: Handles edge case: final edge case - announcement reuse attempt
/// Category: edge
#[test]
fn test_cannot_reuse_consumed_announcer() {
let (announcer, announcement) = Announcement::new();
let _listener = announcement.listener();
// Announcer is consumed here
announcer.announce(42).unwrap();
// Cannot use announcer again - it's been consumed
// This is enforced at compile time by Rust's ownership system
// Create a new one to verify the pattern
let (announcer2, announcement2) = Announcement::new();
let listener2 = announcement2.listener();
announcer2.announce(99).unwrap();
assert_eq!(listener2.try_listen(), Some(99));
}
/// Test: Edge case: Extreme rapid fire operations
///
/// Verifies: Handles edge case: extreme rapid fire operations
/// Category: edge
#[test]
fn test_rapid_fire_all_operations() {
let (announcer, announcement) = Announcement::new();
let ann1 = announcement.clone();
let ann2 = announcement.clone();
let ann3 = announcement.clone();
let h1 = thread::spawn(move || {
for _ in 0..10000 {
let _ = ann1.listener();
}
});
let h2 = thread::spawn(move || {
for _ in 0..10000 {
let _ = ann2.is_announced();
}
});
let h3 = thread::spawn(move || {
for _ in 0..10000 {
let l = ann3.listener();
let _ = l.try_listen();
}
});
thread::sleep(Duration::from_millis(10));
announcer.announce(42).unwrap();
h1.join().unwrap();
h2.join().unwrap();
h3.join().unwrap();
}
// Additional edge cases for zero-listener scenarios
/// Test: Edge case: Edge case - announce to 0 listeners with ~0ns overhead
///
/// Verifies: Handles edge case: edge case - announce to 0 listeners with ~0ns overhead
/// Category: edge
#[test]
fn test_announce_zero_listeners_minimal_overhead() {
use std::time::Instant;
// Warm up
for _ in 0..100 {
let (announcer, _) = Announcement::<i32>::new();
announcer.announce(42).unwrap();
}
// Measure single announcement to no listeners
let start = Instant::now();
let (announcer, _announcement) = Announcement::<i32>::new();
announcer.announce(42).unwrap();
let duration = start.elapsed();
// Should be extremely fast (nanoseconds)
assert!(
duration.as_nanos() < 10_000,
"Single announcement to 0 listeners should have near-zero overhead, was {:?}",
duration
);
}
/// Test: Edge case: Stress test - alternating announce/no-listeners pattern
///
/// Verifies: Handles edge case: stress test - alternating announce/no-listeners pattern
/// Category: edge
#[test]
fn test_edge_case_alternating_listener_pattern() {
for i in 0..1000 {
let (announcer, announcement) = Announcement::<i32>::new();
if i % 2 == 0 {
// Even: create listeners then drop them before announce
let listeners: Vec<_> = (0..10).map(|_| announcement.listener()).collect();
drop(listeners);
}
// Odd: no listeners at all
announcer.announce(i).unwrap();
// Verify late listener still works
if i % 3 == 0 {
let late_listener = announcement.listener();
assert_eq!(late_listener.try_listen(), Some(i));
}
}
}