chore: initial release v0.1.0
Runtime-agnostic oneshot broadcast channel for Rust.
This commit is contained in:
64 files changed
+23966
No files matched your search
@@ -0,0 +1,163 @@
|
||||
//! Tracing coverage tests
|
||||
//!
|
||||
//! These tests ensure tracing statements are executed during coverage runs.
|
||||
//! They set up a tracing subscriber and exercise all code paths that contain
|
||||
//! tracing statements.
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
#[cfg(test)]
|
||||
mod tracing_tests {
|
||||
use announcement::Announcement;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use tracing::Level;
|
||||
use tracing_subscriber::fmt::format::FmtSpan;
|
||||
|
||||
/// Test: Tracing test: all tracing paths
|
||||
///
|
||||
/// Verifies: Verifies all tracing paths
|
||||
/// Category: tracing
|
||||
/// Test that exercises all tracing statements in src/lib.rs
|
||||
#[test]
|
||||
fn test_all_tracing_paths() {
|
||||
// Set up tracing subscriber to capture all trace/debug messages
|
||||
let subscriber = tracing_subscriber::fmt()
|
||||
.with_max_level(Level::TRACE)
|
||||
.with_span_events(FmtSpan::FULL)
|
||||
.with_test_writer()
|
||||
.finish();
|
||||
|
||||
tracing::subscriber::with_default(subscriber, || {
|
||||
// Test 1: Announcement::new() - covers line 286-287
|
||||
let (announcer, announcement) = Announcement::<i32>::new();
|
||||
|
||||
// Test 2: announce() - covers lines 422-423, 440, 444
|
||||
let listener = announcement.listener();
|
||||
announcer.announce(42).unwrap();
|
||||
assert_eq!(listener.try_listen(), Some(42));
|
||||
|
||||
// Test 3: close() - covers lines 486, 492-493
|
||||
let (announcer2, announcement2) = Announcement::<String>::new();
|
||||
let _listener2 = announcement2.listener();
|
||||
announcer2.close();
|
||||
assert!(announcement2.is_closed());
|
||||
|
||||
// Test 4: Drop (auto-close) - covers lines 531-532, 538-539
|
||||
let (announcer3, announcement3) = Announcement::<Vec<u8>>::new();
|
||||
let _listener3 = announcement3.listener();
|
||||
drop(announcer3); // Triggers Drop impl
|
||||
assert!(announcement3.is_closed());
|
||||
|
||||
// Test 5: listen() async fast path - covers lines 653-654
|
||||
let (announcer4, announcement4) = Announcement::<String>::new();
|
||||
announcer4.announce("fast".to_string()).unwrap();
|
||||
let listener4 = announcement4.listener();
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let result = rt.block_on(async { listener4.listen().await });
|
||||
assert_eq!(result, Ok("fast".to_string()));
|
||||
|
||||
// Test 6: listen() async slow path - covers lines 660-661, 666-667, 675-677, 682-683, 691
|
||||
let (announcer5, announcement5) = Announcement::<i32>::new();
|
||||
let listener5 = announcement5.listener();
|
||||
|
||||
let rt2 = tokio::runtime::Runtime::new().unwrap();
|
||||
rt2.block_on(async {
|
||||
let listen_future = listener5.listen();
|
||||
|
||||
// Spawn a task to announce after a delay
|
||||
let ann5_clone = announcer5;
|
||||
tokio::spawn(async move {
|
||||
tokio::time::sleep(Duration::from_millis(10)).await;
|
||||
ann5_clone.announce(99).unwrap();
|
||||
});
|
||||
|
||||
let result = listen_future.await;
|
||||
assert_eq!(result, Ok(99));
|
||||
});
|
||||
|
||||
// Test 7: listen() async with closed announcer - covers lines 660-661, 666-667, 682-683
|
||||
let (announcer6, announcement6) = Announcement::<String>::new();
|
||||
let listener6 = announcement6.listener();
|
||||
|
||||
let rt3 = tokio::runtime::Runtime::new().unwrap();
|
||||
rt3.block_on(async {
|
||||
let listen_future = listener6.listen();
|
||||
|
||||
// Close the announcer
|
||||
let ann6_clone = announcer6;
|
||||
tokio::spawn(async move {
|
||||
tokio::time::sleep(Duration::from_millis(10)).await;
|
||||
ann6_clone.close();
|
||||
});
|
||||
|
||||
let result = listen_future.await;
|
||||
assert!(result.is_err());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Test: Tracing test: blocking with tracing
|
||||
///
|
||||
/// Verifies: Verifies blocking with tracing
|
||||
/// Category: tracing
|
||||
/// Test blocking operations with tracing
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_blocking_with_tracing() {
|
||||
let subscriber = tracing_subscriber::fmt()
|
||||
.with_max_level(Level::TRACE)
|
||||
.with_test_writer()
|
||||
.finish();
|
||||
|
||||
tracing::subscriber::with_default(subscriber, || {
|
||||
// listen_blocking() - exercises tracing in blocking wait
|
||||
let (announcer, announcement) = Announcement::<i32>::new();
|
||||
let listener = announcement.listener();
|
||||
|
||||
thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
announcer.announce(123).unwrap();
|
||||
});
|
||||
|
||||
let result = listener.listen_blocking();
|
||||
assert_eq!(result, Ok(123));
|
||||
});
|
||||
}
|
||||
|
||||
/// Test: Tracing test: concurrent tracing
|
||||
///
|
||||
/// Verifies: Verifies concurrent tracing
|
||||
/// Category: tracing
|
||||
/// Test concurrent tracing paths
|
||||
#[test]
|
||||
fn test_concurrent_tracing() {
|
||||
let subscriber = tracing_subscriber::fmt()
|
||||
.with_max_level(Level::TRACE)
|
||||
.with_test_writer()
|
||||
.finish();
|
||||
|
||||
tracing::subscriber::with_default(subscriber, || {
|
||||
let (announcer, announcement) = Announcement::<Arc<String>>::new();
|
||||
|
||||
// Announce first
|
||||
announcer
|
||||
.announce(Arc::new("concurrent".to_string()))
|
||||
.unwrap();
|
||||
|
||||
let mut handles = vec![];
|
||||
|
||||
// Create multiple listeners concurrently after announce
|
||||
for _ in 0..10 {
|
||||
let listener = announcement.listener();
|
||||
handles.push(thread::spawn(move || listener.try_listen()));
|
||||
}
|
||||
|
||||
// Verify all threads received the value
|
||||
for handle in handles {
|
||||
let result = handle.join().unwrap();
|
||||
assert_eq!(result, Some(Arc::new("concurrent".to_string())));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user