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
//! Shared test harness for the Noesis integration tests.
//!
//! A `tests/common/` module (not `tests/common.rs`) is *not* compiled as its own
//! test binary; each test file pulls it in with `mod common;` and uses only the
//! helpers it needs (hence the crate-level `dead_code` allow).
//!
//! Two app shapes:
//! * [`headless_app`] — `MinimalPlugins` + `AssetPlugin` + `InputPlugin` + the
//! Noesis bridges + [`NoesisHeadlessPlugin`]. No `RenderPlugin`, no render
//! graph, no pipeline compilation: bridge tests that assert messages (not
//! pixels) run here, and never risk the teardown SIGSEGV that a
//! mid-compile process exit causes (see `tests/render_suite/headless_bake_label.rs`).
//! * [`render_app`] — the real `DefaultPlugins` engine, for the few tests that
//! need the actual render graph. Drive it with [`run_until`] then [`settle`].
//!
//! Drive every app with [`run_until`] (stepping `app.update()`, no sleep), never
//! `app.run()`: Noesis is process-global and thread-affine, so it stays one
//! `#[test]` per process.
use ;
use ;
use AssetPlugin;
use InputPlugin;
use *;
use ;
use ;
/// One-Noesis-init-per-process interlock. Noesis' class/resource registration is
/// process-global and thread-affine, so two Noesis tests sharing a process is
/// undefined behavior (the teardown SIGSEGV). nextest runs each `#[test]` in its
/// own process, which resets this to `false`. Under a plain `cargo test`, every
/// `#[test]` in a suite binary shares one process, so the second Noesis init
/// trips this and fails loudly with instructions instead of crashing.
static NOESIS_CLAIMED: AtomicBool = new;
/// Claim this process for a single Noesis-initializing test. Every entry point
/// that brings up the runtime calls it first; the second call in one process
/// panics. See [`NOESIS_CLAIMED`].
/// The Noesis license from `NOESIS_LICENSE_NAME` / `NOESIS_LICENSE_KEY`, or
/// `None` (trial mode). Threaded into whichever plugin brings up the runtime.
/// Build a headless bridge-test app: every Noesis bridge driven against a
/// directly-requested wgpu device, with no `bevy_render` render graph.
///
/// `InputPlugin` registers the input message streams the input forwarders read;
/// the forwarders that also want a primary window are simply skipped (there is
/// none), exactly as under the old `WindowPlugin { primary_window: None }` setup.
/// Tests feed input through `NoesisInputQueue` directly instead.
/// Build a full-engine app for the few tests that need the real render graph
/// (`DefaultPlugins`, winit disabled, no primary window). Drive it with
/// [`run_until`] then [`settle`] so any in-flight pipeline compile drains before
/// the app drops.
/// Finalize plugin setup the way `App::run` would, but for a manually-stepped
/// app: wait out any async plugin readiness (the render device on
/// `DefaultPlugins`), then `finish` + `cleanup` exactly once. `App::update` does
/// not do this itself, and without it `NoesisHeadlessPlugin::finish` never runs,
/// so `NoesisRenderState` is never inserted. Idempotent: once cleaned, a no-op.
/// Step `app.update()` up to `max_frames` times with no sleep, stopping as soon
/// as `pred` returns `true` (checked after each update). Returns whether the
/// predicate ever passed, so callers can `assert!(run_until(...))` on a real
/// condition instead of padding a fixed frame count.
/// Pump `frames` extra `app.update()`s after a [`render_app`] test's assertion
/// has been satisfied. This is the pipeline-compile drain guard: a
/// `DefaultPlugins` app can have async render-pipeline compiles still running on
/// driver threads, and dropping the app mid-compile is the documented teardown
/// SIGSEGV. Headless tests compile no pipelines and do not need this.