Files
announcement/tests/trait_impl_tests.rs
swaits e8e55b7676 chore: initial release v0.1.0
Runtime-agnostic oneshot broadcast channel for Rust.
2025-10-13 19:36:37 -06:00

336 lines
9.8 KiB
Rust

//! Tests for trait implementations (Display, Error, Debug, etc.)
//!
//! These tests ensure that all trait implementations are properly covered
//! by the test suite, particularly for error types.
use announcement::{AnnounceError, Announcement, ListenError};
use std::error::Error;
// =============================================================================
// AnnounceError Trait Implementation Tests
// =============================================================================
/// Test: Trait test: announce error display
///
/// Verifies: Verifies announce error display
/// Category: trait
#[test]
fn test_announce_error_display() {
let err = AnnounceError::AlreadyAnnounced(42);
let display_str = format!("{}", err);
assert_eq!(display_str, "a value has already been announced");
}
/// Test: Trait test: announce error display string type
///
/// Verifies: Verifies announce error display string type
/// Category: trait
#[test]
fn test_announce_error_display_string_type() {
let err = AnnounceError::AlreadyAnnounced("test".to_string());
let display_str = format!("{}", err);
assert_eq!(display_str, "a value has already been announced");
}
/// Test: Trait test: announce error to string
///
/// Verifies: Verifies announce error to string
/// Category: trait
#[test]
fn test_announce_error_to_string() {
let err = AnnounceError::AlreadyAnnounced(99);
assert_eq!(err.to_string(), "a value has already been announced");
}
/// Test: Trait test: announce error std error trait
///
/// Verifies: Verifies announce error std error trait
/// Category: trait
#[test]
fn test_announce_error_std_error_trait() {
let err = AnnounceError::AlreadyAnnounced(42);
// Verify it implements std::error::Error by using it as a trait object
let _err_ref: &dyn Error = &err;
// Verify source() returns None (default implementation)
assert!(err.source().is_none());
}
/// Test: Trait test: announce error debug
///
/// Verifies: Verifies announce error debug
/// Category: trait
#[test]
fn test_announce_error_debug() {
let err = AnnounceError::AlreadyAnnounced(42);
let debug_str = format!("{:?}", err);
assert!(debug_str.contains("AlreadyAnnounced"));
assert!(debug_str.contains("42"));
}
// =============================================================================
// ListenError Trait Implementation Tests
// =============================================================================
/// Test: Trait test: listen error timeout display
///
/// Verifies: Verifies listen error timeout display
/// Category: trait
#[test]
fn test_listen_error_timeout_display() {
let err = ListenError::Timeout;
let display_str = format!("{}", err);
assert_eq!(
display_str,
"timeout elapsed while waiting for announcement"
);
}
/// Test: Trait test: listen error closed display
///
/// Verifies: Verifies listen error closed display
/// Category: trait
#[test]
fn test_listen_error_closed_display() {
let err = ListenError::Closed;
let display_str = format!("{}", err);
assert_eq!(display_str, "announcer was dropped without announcing");
}
/// Test: Trait test: listen error timeout to string
///
/// Verifies: Verifies listen error timeout to string
/// Category: trait
#[test]
fn test_listen_error_timeout_to_string() {
let err = ListenError::Timeout;
assert_eq!(
err.to_string(),
"timeout elapsed while waiting for announcement"
);
}
/// Test: Trait test: listen error closed to string
///
/// Verifies: Verifies listen error closed to string
/// Category: trait
#[test]
fn test_listen_error_closed_to_string() {
let err = ListenError::Closed;
assert_eq!(err.to_string(), "announcer was dropped without announcing");
}
/// Test: Trait test: listen error std error trait
///
/// Verifies: Verifies listen error std error trait
/// Category: trait
#[test]
fn test_listen_error_std_error_trait() {
let err = ListenError::Timeout;
// Verify it implements std::error::Error by using it as a trait object
let _err_ref: &dyn Error = &err;
// Verify source() returns None (default implementation)
assert!(err.source().is_none());
}
/// Test: Trait test: listen error debug
///
/// Verifies: Verifies listen error debug
/// Category: trait
#[test]
fn test_listen_error_debug() {
let timeout_err = ListenError::Timeout;
let closed_err = ListenError::Closed;
let timeout_debug = format!("{:?}", timeout_err);
let closed_debug = format!("{:?}", closed_err);
assert!(timeout_debug.contains("Timeout"));
assert!(closed_debug.contains("Closed"));
}
// =============================================================================
// Clone and PartialEq Tests for Error Types
// =============================================================================
/// Test: Trait test: announce error clone
///
/// Verifies: Verifies announce error clone
/// Category: trait
#[test]
fn test_announce_error_clone() {
let err1 = AnnounceError::AlreadyAnnounced(42);
let err2 = err1.clone();
assert_eq!(err1, err2);
}
/// Test: Trait test: announce error partial eq
///
/// Verifies: Verifies announce error partial eq
/// Category: trait
#[test]
fn test_announce_error_partial_eq() {
let err1 = AnnounceError::AlreadyAnnounced(42);
let err2 = AnnounceError::AlreadyAnnounced(42);
let err3 = AnnounceError::AlreadyAnnounced(99);
assert_eq!(err1, err2);
assert_ne!(err1, err3);
}
/// Test: Trait test: listen error clone
///
/// Verifies: Verifies listen error clone
/// Category: trait
#[test]
fn test_listen_error_clone() {
let err1 = ListenError::Timeout;
let err2 = err1; // Copy trait is used here, not Clone
assert_eq!(err1, err2);
}
/// Test: Trait test: listen error partial eq
///
/// Verifies: Verifies listen error partial eq
/// Category: trait
#[test]
fn test_listen_error_partial_eq() {
let timeout1 = ListenError::Timeout;
let timeout2 = ListenError::Timeout;
let closed = ListenError::Closed;
assert_eq!(timeout1, timeout2);
assert_ne!(timeout1, closed);
}
// =============================================================================
// Error Usage in Result Context Tests
// =============================================================================
/// Test: Trait test: announce error in result
///
/// Verifies: Verifies announce error in result
/// Category: trait
#[test]
fn test_announce_error_in_result() {
/// Test: Trait test: returns error
///
/// Verifies: Verifies returns error
/// Category: trait
fn returns_error() -> Result<(), AnnounceError<i32>> {
Err(AnnounceError::AlreadyAnnounced(42))
}
let result = returns_error();
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(format!("{}", err), "a value has already been announced");
}
/// Test: Trait test: listen error in result
///
/// Verifies: Verifies listen error in result
/// Category: trait
#[test]
fn test_listen_error_in_result() {
/// Test: Trait test: returns timeout
///
/// Verifies: Verifies returns timeout
/// Category: trait
fn returns_timeout() -> Result<i32, ListenError> {
Err(ListenError::Timeout)
}
/// Test: Trait test: returns closed
///
/// Verifies: Verifies returns closed
/// Category: trait
fn returns_closed() -> Result<i32, ListenError> {
Err(ListenError::Closed)
}
let timeout_result = returns_timeout();
assert!(timeout_result.is_err());
assert_eq!(
format!("{}", timeout_result.unwrap_err()),
"timeout elapsed while waiting for announcement"
);
let closed_result = returns_closed();
assert!(closed_result.is_err());
assert_eq!(
format!("{}", closed_result.unwrap_err()),
"announcer was dropped without announcing"
);
}
// =============================================================================
// Real-World Error Scenario Tests
// =============================================================================
/// Test: Trait test: listen error closed from dropped announcer
///
/// Verifies: Verifies listen error closed from dropped announcer
/// Category: trait
#[tokio::test]
async fn test_listen_error_closed_from_dropped_announcer() {
let (announcer, announcement) = Announcement::<i32>::new();
let listener = announcement.listener();
// Drop announcer to trigger Closed error
drop(announcer);
let result = listener.listen().await;
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err, ListenError::Closed);
assert_eq!(
format!("{}", err),
"announcer was dropped without announcing"
);
// Verify Error trait methods
assert!(err.source().is_none());
}
/// Test: Trait test: listen error timeout from timeout blocking
///
/// Verifies: Verifies listen error timeout from timeout blocking
/// Category: trait
#[cfg(feature = "std")]
#[test]
fn test_listen_error_timeout_from_timeout_blocking() {
use std::time::Duration;
let (_announcer, announcement) = Announcement::<i32>::new();
let listener = announcement.listener();
// Try to listen with a very short timeout (will timeout)
let result = listener.listen_timeout_blocking(Duration::from_millis(1));
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err, ListenError::Timeout);
assert_eq!(
format!("{}", err),
"timeout elapsed while waiting for announcement"
);
// Verify Error trait methods
assert!(err.source().is_none());
}
/// Test: Trait test: announce error into inner preserves value
///
/// Verifies: Verifies announce error into inner preserves value
/// Category: trait
#[test]
fn test_announce_error_into_inner_preserves_value() {
let original_value = vec![1, 2, 3, 4, 5];
let err = AnnounceError::AlreadyAnnounced(original_value.clone());
let recovered_value = err.into_inner();
assert_eq!(recovered_value, original_value);
}