#![no_main] use libfuzzer_sys::fuzz_target; use announcement::Announcement; fuzz_target!(|data: &[u8]| { if data.is_empty() { return; } let action = data[0] % 4; match action { 0 => { // Test drop without announce let (announcer, announcement) = Announcement::::new(); let listener = announcement.listener(); assert!(!announcement.is_closed()); drop(announcer); // Should be closed now assert!(announcement.is_closed()); assert!(listener.is_closed()); } 1 => { // Test explicit close let (announcer, announcement) = Announcement::::new(); let listener = announcement.listener(); assert!(!announcement.is_closed()); announcer.close(); // Should be closed now assert!(announcement.is_closed()); assert!(listener.is_closed()); } 2 => { // Test announce then drop (should not be closed) let (announcer, announcement) = Announcement::new(); let listener = announcement.listener(); let _ = announcer.announce(42u32); // announcer is consumed by announce(), no need to drop // Should NOT be closed (announced successfully) assert!(!announcement.is_closed()); assert!(!listener.is_closed()); // Listener should get value assert_eq!(listener.try_listen(), Some(42u32)); } _ => { // Test listener created after close let (announcer, announcement) = Announcement::::new(); announcer.close(); // Create listener after close let listener = announcement.listener(); // Should immediately know it's closed assert!(listener.is_closed()); } } // Test with multiple listeners if data.len() >= 2 { let num_listeners = (data[1] % 10) as usize + 1; // 1-10 listeners let (announcer, announcement) = Announcement::::new(); let listeners: Vec<_> = (0..num_listeners) .map(|_| announcement.listener()) .collect(); // Drop announcer drop(announcer); // All should see closed state for listener in listeners { assert!(listener.is_closed()); } } });