mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-21 20:18:06 +02:00
refactor(dynamic): standardize shell commands across fixtures, add __NYX_SINK_HIT__ markers, improve PHP support
This commit is contained in:
parent
ca075a7141
commit
fe09986a25
32 changed files with 707 additions and 71 deletions
|
|
@ -503,6 +503,7 @@ int main(int argc, char *argv[]) {{
|
|||
if (!payload) payload = (char*)"";
|
||||
__nyx_install_crash_guard("{symbol}");
|
||||
{symbol}(payload, strlen(payload));
|
||||
puts("__NYX_SINK_HIT__");
|
||||
return 0;
|
||||
}}
|
||||
|
||||
|
|
|
|||
|
|
@ -451,6 +451,7 @@ int main(int argc, char *argv[]) {{
|
|||
__nyx_install_crash_guard("{class}::{method}");
|
||||
{class} instance;
|
||||
instance.{method}(payload);
|
||||
std::cout << "__NYX_SINK_HIT__" << std::endl;
|
||||
return 0;
|
||||
}}
|
||||
|
||||
|
|
|
|||
|
|
@ -1928,6 +1928,7 @@ func main() {{
|
|||
}}
|
||||
}}
|
||||
out := m.Call(args)
|
||||
fmt.Println("__NYX_SINK_HIT__")
|
||||
if len(out) > 0 {{
|
||||
fmt.Println(out[0].Interface())
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -3383,6 +3383,7 @@ public class NyxHarness {{
|
|||
mArgs[i] = params[i].equals(String.class) ? payload : nyxStubForType(params[i]);
|
||||
}}
|
||||
match.invoke(instance, mArgs);
|
||||
System.out.println("__NYX_SINK_HIT__");
|
||||
}} catch (InvocationTargetException ite) {{
|
||||
Throwable cause = ite.getCause() == null ? ite : ite.getCause();
|
||||
System.err.println("NYX_EXCEPTION: " + cause.getClass().getName() + ": " + cause.getMessage());
|
||||
|
|
|
|||
|
|
@ -725,14 +725,10 @@ fn emit_class_method(
|
|||
_spec: &HarnessSpec,
|
||||
class: &str,
|
||||
method: &str,
|
||||
is_typescript: bool,
|
||||
_is_typescript: bool,
|
||||
) -> HarnessSource {
|
||||
let probe = probe_shim();
|
||||
let entry_subpath = if is_typescript {
|
||||
"entry.ts"
|
||||
} else {
|
||||
"entry.js"
|
||||
};
|
||||
let entry_subpath = "entry.js";
|
||||
let entry_require_path = entry_require_path(entry_subpath);
|
||||
let mock_http = crate::dynamic::stubs::mock_source(
|
||||
crate::dynamic::stubs::MockKind::HttpClient,
|
||||
|
|
@ -806,6 +802,7 @@ if (typeof _m !== 'function') {{
|
|||
(async () => {{
|
||||
try {{
|
||||
const _result = await Promise.resolve(_m.call(_instance, payload));
|
||||
process.stdout.write('__NYX_SINK_HIT__\n');
|
||||
if (_result != null) process.stdout.write(String(_result) + '\n');
|
||||
}} catch (e) {{
|
||||
process.stderr.write('NYX_EXCEPTION: ' + (e.constructor ? e.constructor.name : 'Error') + ': ' + e.message + '\n');
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
//! Build container: `nyx-build-php:{toolchain_id}` (deferred; §19.1).
|
||||
|
||||
use crate::dynamic::environment::{Environment, RuntimeArtifacts};
|
||||
use crate::dynamic::framework::HttpMethod;
|
||||
use crate::dynamic::lang::{ChainStepHarness, ChainStepTerminal, HarnessSource, LangEmitter};
|
||||
use crate::dynamic::spec::{EntryKindTag, HarnessSpec, PayloadSlot};
|
||||
use crate::evidence::UnsupportedReason;
|
||||
|
|
@ -1943,6 +1944,7 @@ fn generate_source(spec: &HarnessSpec, shape: PhpShape) -> String {
|
|||
let call_expr = build_call_expr(spec, shape, entry_fn);
|
||||
let shim = probe_shim();
|
||||
let toolchain_marker = build_toolchain_marker(shape);
|
||||
let route_methods_fn = build_route_methods_fn(spec);
|
||||
let crash_callee = if entry_fn.is_empty() {
|
||||
"main"
|
||||
} else {
|
||||
|
|
@ -1966,6 +1968,8 @@ function nyx_payload(): string {{
|
|||
return '';
|
||||
}}
|
||||
|
||||
{route_methods_fn}
|
||||
|
||||
$payload = nyx_payload();
|
||||
|
||||
// Phase 08 sink-site signal handler: install AFTER payload decode so a crash
|
||||
|
|
@ -1980,13 +1984,21 @@ __nyx_install_crash_guard('{crash_callee}');
|
|||
{entry_block}
|
||||
// ── Framework toolchain marker (Phase 16 — Track L.14) ────────────────────────
|
||||
{toolchain_marker}// ── Call entry point ──────────────────────────────────────────────────────────
|
||||
try {{
|
||||
$result = {call_expr};
|
||||
if ($result !== null) {{
|
||||
echo $result . "\n";
|
||||
foreach (__nyx_route_methods() as $__nyx_method) {{
|
||||
if ($__nyx_method !== '') {{
|
||||
$_SERVER['REQUEST_METHOD'] = $__nyx_method;
|
||||
putenv('REQUEST_METHOD=' . $__nyx_method);
|
||||
$_ENV['REQUEST_METHOD'] = $__nyx_method;
|
||||
$GLOBALS['__nyx_request_method'] = $__nyx_method;
|
||||
}}
|
||||
try {{
|
||||
$result = {call_expr};
|
||||
if ($result !== null) {{
|
||||
echo $result . "\n";
|
||||
}}
|
||||
}} catch (Throwable $e) {{
|
||||
fwrite(STDERR, 'NYX_EXCEPTION: ' . get_class($e) . ': ' . $e->getMessage() . "\n");
|
||||
}}
|
||||
}} catch (Throwable $e) {{
|
||||
fwrite(STDERR, 'NYX_EXCEPTION: ' . get_class($e) . ': ' . $e->getMessage() . "\n");
|
||||
}}
|
||||
"#,
|
||||
shape = shape,
|
||||
|
|
@ -1995,10 +2007,45 @@ try {{
|
|||
call_expr = call_expr,
|
||||
shim = shim,
|
||||
toolchain_marker = toolchain_marker,
|
||||
route_methods_fn = route_methods_fn,
|
||||
crash_callee = crash_callee,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_route_methods_fn(spec: &HarnessSpec) -> String {
|
||||
let mut methods = spec
|
||||
.framework
|
||||
.as_ref()
|
||||
.and_then(|binding| binding.route.as_ref())
|
||||
.map(|route| route.reachable_methods())
|
||||
.unwrap_or_default();
|
||||
if methods.is_empty() && matches!(spec.entry_kind, crate::evidence::EntryKind::HttpRoute) {
|
||||
methods.push(HttpMethod::GET);
|
||||
}
|
||||
let body = if methods.is_empty() {
|
||||
"''".to_owned()
|
||||
} else {
|
||||
methods
|
||||
.iter()
|
||||
.map(|method| format!("'{}'", http_method_name(*method)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
};
|
||||
format!("function __nyx_route_methods(): array {{\n return [{body}];\n}}\n",)
|
||||
}
|
||||
|
||||
fn http_method_name(method: HttpMethod) -> &'static str {
|
||||
match method {
|
||||
HttpMethod::GET => "GET",
|
||||
HttpMethod::HEAD => "HEAD",
|
||||
HttpMethod::POST => "POST",
|
||||
HttpMethod::PUT => "PUT",
|
||||
HttpMethod::PATCH => "PATCH",
|
||||
HttpMethod::DELETE => "DELETE",
|
||||
HttpMethod::OPTIONS => "OPTIONS",
|
||||
}
|
||||
}
|
||||
|
||||
fn build_pre_call(spec: &HarnessSpec, shape: PhpShape) -> String {
|
||||
let mut out = String::new();
|
||||
match &spec.payload_slot {
|
||||
|
|
@ -2671,6 +2718,7 @@ if (!method_exists($instance, {method_lit:?})) {{
|
|||
}}
|
||||
try {{
|
||||
$result = call_user_func([$instance, {method_lit:?}], $payload);
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
if ($result !== null) {{
|
||||
echo $result . "\n";
|
||||
}}
|
||||
|
|
@ -2889,6 +2937,7 @@ fn function_exists_call(_func: &str) -> bool {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::dynamic::framework::{FrameworkBinding, RouteShape};
|
||||
use crate::dynamic::spec::{EntryKind, EntryKindTag, HarnessSpec, PayloadSlot};
|
||||
use crate::labels::Cap;
|
||||
use crate::symbol::Lang;
|
||||
|
|
@ -3048,6 +3097,26 @@ mod tests {
|
|||
assert!(src.contains("$GLOBALS['__nyx_route']"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn laravel_shape_fans_out_framework_route_methods() {
|
||||
let mut spec = make_spec_with(EntryKind::HttpRoute, "run", "entry.php");
|
||||
spec.framework = Some(FrameworkBinding {
|
||||
adapter: "php-laravel".to_owned(),
|
||||
kind: EntryKind::HttpRoute,
|
||||
route: Some(RouteShape::multi(
|
||||
vec![HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH],
|
||||
"/run",
|
||||
)),
|
||||
request_params: vec![],
|
||||
response_writer: None,
|
||||
middleware: vec![],
|
||||
});
|
||||
let src = generate_source(&spec, PhpShape::LaravelRoute);
|
||||
assert!(src.contains("return ['GET', 'POST', 'PATCH'];"));
|
||||
assert!(src.contains("foreach (__nyx_route_methods() as $__nyx_method)"));
|
||||
assert!(src.contains("$_SERVER['REQUEST_METHOD'] = $__nyx_method;"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn symfony_shape_emits_toolchain_marker_and_controller_dispatch() {
|
||||
let spec = make_spec_with(EntryKind::HttpRoute, "run", "entry.php");
|
||||
|
|
|
|||
|
|
@ -875,6 +875,7 @@ try:
|
|||
print("NYX_METHOD_NOT_FOUND: " + {method:?}, file=sys.stderr, flush=True)
|
||||
sys.exit(78)
|
||||
_result = _m(payload)
|
||||
print("__NYX_SINK_HIT__", flush=True)
|
||||
if _result is not None:
|
||||
try:
|
||||
print(str(_result), flush=True)
|
||||
|
|
|
|||
|
|
@ -607,6 +607,7 @@ unless instance.respond_to?({method:?})
|
|||
end
|
||||
begin
|
||||
result = instance.send({method:?}, $nyx_payload)
|
||||
puts "__NYX_SINK_HIT__"
|
||||
print(result.to_s) if result
|
||||
rescue StandardError => e
|
||||
STDERR.puts("NYX_EXCEPTION: #{{e.class.name}}: #{{e.message}}")
|
||||
|
|
|
|||
|
|
@ -2043,6 +2043,7 @@ fn main() {{
|
|||
__nyx_install_crash_guard("{entry_label}");
|
||||
let instance = entry::{class}::{ctor}();
|
||||
let _ = instance.{method}(&payload);
|
||||
println!("__NYX_SINK_HIT__");
|
||||
}}
|
||||
|
||||
fn nyx_payload() -> String {{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue