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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//! `mock.*` request-count virtual field assertion rendering for C e2e tests (alef issue #443).
//!
//! Mirrors `java::assertion_mock_capture` / `csharp::assertion_mock_capture`: `mock.*` fields
//! (see `mock_assertions::model`) resolve against the generated mock server's own request log
//! through the once-per-suite helper `mock_assertions::render_helper` emits into the file (see
//! [`append_helper_if_referenced`], called from `c::render_test_file`), not a struct field.
//!
//! ~keep This backend has FAR more call sites than the one- or three-site backends wired so far,
//! because C's `test_function.rs`/`call_patterns.rs` do not funnel every fixture through a single
//! `render_assertion` the way most backends do. The full inventory, found by grepping every
//! `fixture.assertions` reference under `src/e2e/codegen/c/` (not just the streaming one the
//! issue's own intel table names):
//!
//! 1. `assertions::render_assertion` -- the ordinary field-access oracle every plain (opaque
//! struct result) fixture goes through. Must intercept first, exactly like every other backend.
//! 2. `streaming::emit_chat_stream_assertion` -- chat-stream fixtures never reach (1); named in
//! the issue's own split-dispatch intel as the one site that made `c` a required lane.
//! 3. `test_function::render_test_function_impl`'s "raw C result type" path (functions returning
//! `char*`/`int32_t`/`uintptr_t` directly) has its OWN bespoke `match assertion.assertion_type`
//! keyed off the bare `result_var`, never `assertion.field` -- unintercepted, a `mock.*`
//! assertion here would compile and silently assert the wrong thing (the raw result compared
//! against the mock count) rather than skip or fail loudly.
//! 4. `call_patterns::render_bytes_test_function` -- byte-buffer methods have their own bespoke
//! assertion loop that only understands `not_error`/`not_empty`/`not_null`; every other type,
//! `mock.*` included, previously fell into a "not meaningful on raw byte buffer" comment.
//! 5. (and 6.) `test_function.rs`'s TWO per-fixture field-EXTRACTION loops (client-factory path and the
//! second/legacy path) have no `field_resolver.is_valid_for_result` guard at all, unlike (7)
//! below -- left alone, they walk `mock.requests.total` as if it were a real nested field path
//! and either emit a bogus `{prefix}_{type}_mock(...)` accessor call or `bail!` generation
//! outright via `ensure_leaf_field_exists`/`emit_nested_accessor`'s own diagnostics. These two
//! loops must skip `mock.*` fields entirely (see `is_mock_virtual_field` calls in
//! `test_function.rs`), leaving the field's actual rendering to (1).
//! 7. `call_patterns::render_engine_factory_test_function`'s field-extraction loop already guards
//! on `field_resolver.is_valid_for_result`, so `mock.*` is naturally skipped there with no
//! change needed -- but its separate `has_active_assertions` pre-check used the same
//! "valid for result type" test to decide whether to render assertions AT ALL. A fixture whose
//! ONLY assertion is `mock.*` would have measured zero active assertions and taken the
//! soft-null-guard branch that renders no assertions whatsoever -- a silent full drop, not
//! even the `FieldSkip::NotAvailableOnResultType` misattribution `ensure_capture_declared`'s
//! own doc warns about. Fixed by counting `is_mock_virtual_field` fields as active too.
//!
//! `c::visitor` (the visitor-pattern file generator) is NOT intercepted: visitor fixtures require
//! a matching typed call (`c_visitor_fixture_has_typed_call`) and are a fundamentally different,
//! callback-driven code shape with no per-fixture HTTP-round-trip assertion story today -- the
//! same class of "architecture, not a gap" the module doc already carves out for HTTP-fixture
//! early-returns. Left unaudited beyond this note.
use Write as FmtWrite;
use crate;
use crateAssertion;
/// C expression for the mock server's base URL -- the same bare `getenv("MOCK_SERVER_URL")` every
/// other mock-server call site in this backend already reads (`call_patterns.rs`,
/// `test_function.rs`; see those files' `mock_base`/`base_url` locals). The introspection
/// endpoints (`/__alef/requests/*`) are served by the mock binary's SHARED listener, never a
/// per-fixture one, so the bare env var -- not a fixture-derived `base_url` -- is always the
/// right root to query, exactly like every other wired backend already does. ~keep
const MOCK_SERVER_URL_EXPR: &str = "getenv(\"MOCK_SERVER_URL\")";
/// Renders an assertion against a `mock.*` virtual field into `out` and returns `true` when
/// `assertion.field` names one (and the assertion was handled), signaling the caller to skip
/// every other branch rather than fall through to ordinary field resolution.
pub
/// Feed the mock-request-count `expr` (an `int`) into the same `assert(<cond> && "<message>")`
/// idiom every other numeric comparison in this backend already uses (see
/// `test_function.rs`'s "Other assertions" loop for the identical wording on `equals` /
/// `greater_than_or_equal`). Unlike Java's counterpart, the field name is not embedded in the
/// message: no other assertion message in this backend's generated C does that either, and
/// skipping it means the message never needs `escape_c` for a field carrying literal `"`
/// characters (`mock.requests["POST /v1/chat"]`).
/// POSIX headers the emitted helper needs beyond this file's unconditional fixed includes
/// (`assert.h`/`stdint.h`/`string.h`/`stdio.h`/`stdlib.h`, written by `c::render_test_file`
/// before any fixture body) -- inserted only when the helper is actually referenced, so a
/// generated file with no `mock.*` assertion gets no new header dependency. Every other wired
/// backend needs no equivalent because each already has a standard-library HTTP client
/// (`java.net.http`, `HttpClient`, `net/http`, ...); C alone speaks the raw POSIX socket API,
/// which lives behind headers this file does not otherwise include. ~keep
///
/// ~keep The `_WIN32` guard leads, before the first `#include`, and that order is the whole
/// point: on Windows these three headers do not exist, so without the guard the build fails
/// with a cascade of missing-header errors followed by every socket symbol being undeclared --
/// a failure whose text names nothing that would lead a reader to the cause. The `#error` names
/// the issue instead. It is deliberately not a Winsock implementation (alef issue #468): a
/// `WSAStartup`/`SOCKET`/`closesocket` branch written without a Windows machine to compile it on
/// would be unverified platform code presented as coverage, which is strictly worse than a
/// legible refusal. Alef's own CI `test` matrix runs `windows-latest`, but it exercises the Rust
/// generator, never a compiled generated C suite, so nothing here would have caught it.
const MOCK_HELPER_INCLUDES: &str = concat!;
/// Appends the once-per-suite mock-request-count helper -- and the socket headers it needs -- to
/// `out` iff a fixture already rendered into it actually calls the helper. `includes_offset` is
/// the byte offset right after this file's fixed `#include` block (captured by
/// `c::render_test_file` before any fixture body is appended): the extra includes must land
/// there, not at the end, because C requires every `#include` to precede its first use. Mirrors
/// `csharp::assertion_mock_capture::append_helper_if_referenced`'s helper-only version of this
/// gate, extended with the include injection this backend alone needs (see
/// [`MOCK_HELPER_INCLUDES`]).
pub