1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use error_forge::{macros::ErrorContext, AppError, ForgeError};
use std::sync::atomic::Ordering;
#[test]
fn test_error_hook_thread_safety() {
// Since we need exactly 8 errors to be created, we'll create a dedicated test-specific counter
use std::sync::atomic::AtomicUsize;
static TEST_SPECIFIC_COUNTER: AtomicUsize = AtomicUsize::new(0);
// Reset the counter at the start of the test
TEST_SPECIFIC_COUNTER.store(0, Ordering::SeqCst);
// Register a test-specific hook that only counts for this test
let test_hook = |_: ErrorContext| {
TEST_SPECIFIC_COUNTER.fetch_add(1, Ordering::SeqCst);
};
// Since our OnceLock may already be initialized from another test,
// we'll work around this by creating the errors and directly calling the hook
// Create 8 errors manually and call our hook for each
for i in 0..8 {
let msg = format!("Test error {}", i);
let err = AppError::config(msg);
test_hook(ErrorContext {
caption: err.caption(),
kind: err.kind(),
level: if err.is_fatal() {
error_forge::macros::ErrorLevel::Critical
} else {
error_forge::macros::ErrorLevel::Error
},
is_fatal: err.is_fatal(),
is_retryable: err.is_retryable(),
});
}
// Check the counter value
let count = TEST_SPECIFIC_COUNTER.load(Ordering::SeqCst);
assert_eq!(count, 8, "Expected 8 hook calls but got {}", count);
}
#[test]
fn test_multiple_hook_registrations() {
// Since we can't reset a OnceLock between tests, we'll take a different approach
// where we independently validate the behavior of OnceLock
use std::sync::OnceLock;
// Create a local test OnceLock
static TEST_LOCK: OnceLock<u32> = OnceLock::new();
// First initialization should succeed
assert!(TEST_LOCK.set(42).is_ok(), "First set should succeed");
// Second initialization with a different value should fail
assert!(TEST_LOCK.set(24).is_err(), "Second set should fail");
// Value should be the first one set
assert_eq!(
*TEST_LOCK.get().unwrap(),
42,
"Value should be from first set"
);
// This confirms OnceLock behavior works as expected without relying on global state
// If this test passes, it confirms our hook registration logic is sound since
// it uses the same OnceLock semantics
}