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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Test registration mechanism.
//!
//! This module provides the unified registration system for tests.
//!
//! ## Registration Patterns
//!
//! ### Vanilla tests (`#[test]`)
//! - No registration, runs directly via libtest
//! - Standard sync test execution
//!
//! ### Beet tests (`#[beet::test]`)
//! - Unified registration via `register_test()`
//! - Registers both `TestCaseParams` AND test future in a single call
//! - Thread-local storage allows opaque `fn()` from libtest to provide async tests
//! - Params are available before awaiting the future, enabling:
//! - Per-test timeout configuration
//! - Future extensibility (retries, resource limits, etc.)
//! - ECS component inspection before test execution
//!
//! ## Design Philosophy
//!
//! The key insight is separating params from execution. By registering both together
//! but extracting them separately, we can inspect/use params before running the test.
//! This is crucial for features like timeout enforcement where we need to know the
//! timeout value before starting the async test.
//!
//! ## How it works
//!
//! 1. `#[beet_core::test]` macro generates code calling `register_test(params, async_body)`
//! 2. Both params and test are stored together in thread-local `REGISTERED_TEST`
//! 3. Test runner calls `try_run_async()` which:
//! - Invokes the test function (triggering registration)
//! - Extracts both params and async test from thread-local
//! - Returns `TestRunResult { maybe_async, params }`
//! 4. Params are inserted as ECS components and used immediately
//! 5. Test future is awaited separately with params already available
use crate*;
use crate*;
use crate*;
use RefCell;
use Pin;
thread_local!
/// Registration data for a test, containing both the test future and params
/// Unified registration for tests - registers both params and test future.
///
/// Called by the `#[beet_core::test]` macro to register test configuration and the
/// async test body in a single call. This ensures params are available before
/// the test future is awaited, enabling future extensibility (e.g., conditional
/// execution, resource allocation, etc.).
///
/// ## Example
///
/// The macro:
/// ```ignore
/// #[beet_core::test(timeout_ms = 1000)]
/// async fn my_test() {
/// assert!(true);
/// }
/// ```
///
/// Expands to:
/// ```ignore
/// #[test]
/// fn my_test() {
/// beet_core::testing::register_test(
/// beet_core::testing::TestCaseParams::new().with_timeout_ms(1000),
/// async { assert!(true); }
/// );
/// }
/// ```
///
/// This allows the test runner to:
/// 1. Extract params before awaiting the future
/// 2. Use params for timeout enforcement, retries, etc.
/// 3. Insert params as ECS components for system access
/// Represents either an async test that is still running,
/// or a synchronous test that has finished.
pub
/// Result of running a test function, including both outcome and params
pub
/// Attempts to run the provided function as a synchronous test.
/// If the function registers a test via `register_test` or legacy methods,
/// returns the async test future and params. Otherwise runs as sync test.
///
/// ## Panics
/// Panics if a test is already registered outside of a test run.
pub
// see run_tests.rs for tests