From 9ac48379ed7f999a5a2893e21e4670c99e8bc694 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 10 Mar 2026 09:47:19 +0000 Subject: [PATCH] Conformance Regression Suite Fault Status --- .../prometeu-hal/src/syscalls/tests.rs | 43 +++++ .../src/virtual_machine_runtime/tests.rs | 173 ++++++++++++++++++ ...nformance-regression-suite-fault-status.md | 42 ----- docs/runtime/pull-requests/README.md | 14 -- 4 files changed, 216 insertions(+), 56 deletions(-) delete mode 100644 docs/runtime/pull-requests/PR006-conformance-regression-suite-fault-status.md diff --git a/crates/console/prometeu-hal/src/syscalls/tests.rs b/crates/console/prometeu-hal/src/syscalls/tests.rs index 4d44c4d9..35e8b737 100644 --- a/crates/console/prometeu-hal/src/syscalls/tests.rs +++ b/crates/console/prometeu-hal/src/syscalls/tests.rs @@ -300,6 +300,49 @@ fn declared_resolver_rejects_legacy_status_first_signatures() { } } +#[test] +fn declared_resolver_accepts_mixed_status_first_surface_as_a_single_module() { + let declared = vec![ + prometeu_bytecode::SyscallDecl { + module: "gfx".into(), + name: "set_sprite".into(), + version: 1, + arg_slots: 10, + ret_slots: 1, + }, + prometeu_bytecode::SyscallDecl { + module: "audio".into(), + name: "play".into(), + version: 1, + arg_slots: 7, + ret_slots: 1, + }, + prometeu_bytecode::SyscallDecl { + module: "asset".into(), + name: "load".into(), + version: 1, + arg_slots: 3, + ret_slots: 2, + }, + prometeu_bytecode::SyscallDecl { + module: "asset".into(), + name: "commit".into(), + version: 1, + arg_slots: 1, + ret_slots: 1, + }, + ]; + + let resolved = resolve_declared_program_syscalls(&declared, caps::GFX | caps::AUDIO | caps::ASSET) + .expect("mixed status-first surface must resolve together"); + + assert_eq!(resolved.len(), declared.len()); + assert_eq!(resolved[0].meta.ret_slots, 1); + assert_eq!(resolved[1].meta.ret_slots, 1); + assert_eq!(resolved[2].meta.ret_slots, 2); + assert_eq!(resolved[3].meta.ret_slots, 1); +} + #[test] fn memcard_syscall_signatures_are_pinned() { let slot_count = meta_for(Syscall::MemSlotCount); diff --git a/crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs b/crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs index 249184cc..b76fdb95 100644 --- a/crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs +++ b/crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs @@ -770,6 +770,179 @@ fn tick_asset_commit_invalid_transition_returns_status_not_crash() { assert_eq!(vm.operand_stack_top(1), vec![Value::Int64(AssetOpStatus::InvalidState as i64)]); } +#[test] +fn tick_asset_cancel_unknown_handle_returns_status_not_crash() { + let mut runtime = VirtualMachineRuntime::new(None); + let mut vm = VirtualMachine::default(); + let mut hardware = Hardware::new(); + let signals = InputSignals::default(); + let code = assemble("PUSH_I32 999\nHOSTCALL 0\nHALT").expect("assemble"); + let program = serialized_single_function_module( + code, + vec![SyscallDecl { + module: "asset".into(), + name: "cancel".into(), + version: 1, + arg_slots: 1, + ret_slots: 1, + }], + ); + let cartridge = cartridge_with_program(program, caps::ASSET); + + runtime.initialize_vm(&mut vm, &cartridge).expect("runtime must initialize"); + let report = runtime.tick(&mut vm, &signals, &mut hardware); + assert!(report.is_none(), "unknown handle cancel must not crash"); + assert!(vm.is_halted()); + assert_eq!(vm.operand_stack_top(1), vec![Value::Int64(AssetOpStatus::UnknownHandle as i64)]); +} + +#[test] +fn tick_asset_cancel_invalid_transition_returns_status_not_crash() { + let mut runtime = VirtualMachineRuntime::new(None); + let mut vm = VirtualMachine::default(); + let mut hardware = Hardware::new(); + let signals = InputSignals::default(); + let code = assemble("PUSH_I32 1\nHOSTCALL 0\nHALT").expect("assemble"); + let program = serialized_single_function_module( + code, + vec![SyscallDecl { + module: "asset".into(), + name: "cancel".into(), + version: 1, + arg_slots: 1, + ret_slots: 1, + }], + ); + let cartridge = cartridge_with_program(program, caps::ASSET); + + let asset_data = test_tile_asset_data(); + hardware.assets.initialize_for_cartridge( + vec![test_tile_asset_entry("tile_asset", asset_data.len())], + vec![], + asset_data, + ); + let handle = hardware + .assets + .load("tile_asset", prometeu_hal::asset::SlotRef::gfx(0)) + .expect("asset handle must be allocated"); + + runtime.initialize_vm(&mut vm, &cartridge).expect("runtime must initialize"); + + loop { + match hardware.assets.status(handle) { + LoadStatus::READY => break, + LoadStatus::PENDING | LoadStatus::LOADING => { + std::thread::sleep(std::time::Duration::from_millis(1)); + } + other => panic!("unexpected asset status before commit: {:?}", other), + } + } + + assert_eq!(hardware.assets.commit(handle), AssetOpStatus::Ok); + hardware.assets.apply_commits(); + assert_eq!(hardware.assets.status(handle), LoadStatus::COMMITTED); + + let report = runtime.tick(&mut vm, &signals, &mut hardware); + assert!(report.is_none(), "cancel after commit must not crash"); + assert!(vm.is_halted()); + assert_eq!(vm.operand_stack_top(1), vec![Value::Int64(AssetOpStatus::InvalidState as i64)]); +} + +#[test] +fn tick_asset_load_invalid_kind_surfaces_trap_not_panic() { + let mut runtime = VirtualMachineRuntime::new(None); + let mut vm = VirtualMachine::default(); + let mut hardware = Hardware::new(); + let signals = InputSignals::default(); + let code = assemble("PUSH_CONST 0\nPUSH_I32 2\nPUSH_I32 0\nHOSTCALL 0\nHALT").expect("assemble"); + let program = serialized_single_function_module_with_consts( + code, + vec![ConstantPoolEntry::String("tile_asset".into())], + vec![SyscallDecl { + module: "asset".into(), + name: "load".into(), + version: 1, + arg_slots: 3, + ret_slots: 2, + }], + ); + let cartridge = cartridge_with_program(program, caps::ASSET); + + runtime.initialize_vm(&mut vm, &cartridge).expect("runtime must initialize"); + let report = runtime + .tick(&mut vm, &signals, &mut hardware) + .expect("invalid asset kind must surface as trap"); + match report { + CrashReport::VmTrap { trap } => { + assert_eq!(trap.code, TRAP_TYPE); + assert!(trap.message.contains("Invalid asset type")); + } + other => panic!("expected VmTrap crash report, got {:?}", other), + } + assert!(matches!(runtime.last_crash_report, Some(CrashReport::VmTrap { .. }))); +} + +#[test] +fn tick_status_first_surface_smoke_across_gfx_audio_and_asset() { + let mut runtime = VirtualMachineRuntime::new(None); + let mut vm = VirtualMachine::default(); + let mut hardware = Hardware::new(); + let signals = InputSignals::default(); + let code = assemble( + "PUSH_CONST 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_BOOL 1\nPUSH_BOOL 0\nPUSH_BOOL 0\nPUSH_I32 0\nHOSTCALL 0\n\ + PUSH_CONST 1\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 255\nPUSH_I32 128\nPUSH_I32 1\nPUSH_I32 0\nHOSTCALL 1\n\ + PUSH_CONST 2\nPUSH_I32 0\nPUSH_I32 0\nHOSTCALL 2\n\ + HALT" + ) + .expect("assemble"); + let program = serialized_single_function_module_with_consts( + code, + vec![ + ConstantPoolEntry::String("missing_tile_bank".into()), + ConstantPoolEntry::String("missing_sound_bank".into()), + ConstantPoolEntry::String("missing_asset".into()), + ], + vec![ + SyscallDecl { + module: "gfx".into(), + name: "set_sprite".into(), + version: 1, + arg_slots: 10, + ret_slots: 1, + }, + SyscallDecl { + module: "audio".into(), + name: "play".into(), + version: 1, + arg_slots: 7, + ret_slots: 1, + }, + SyscallDecl { + module: "asset".into(), + name: "load".into(), + version: 1, + arg_slots: 3, + ret_slots: 2, + }, + ], + ); + let cartridge = cartridge_with_program(program, caps::GFX | caps::AUDIO | caps::ASSET); + + runtime.initialize_vm(&mut vm, &cartridge).expect("runtime must initialize"); + let report = runtime.tick(&mut vm, &signals, &mut hardware); + assert!(report.is_none(), "mixed status-first surface must not crash"); + assert!(vm.is_halted()); + assert_eq!( + vm.operand_stack_top(4), + vec![ + Value::Int64(0), + Value::Int64(AssetLoadError::AssetNotFound as i64), + Value::Int64(AudioOpStatus::AssetNotFound as i64), + Value::Int64(GfxOpStatus::AssetNotFound as i64), + ] + ); +} + #[test] fn tick_gfx_set_sprite_type_mismatch_surfaces_trap_not_panic() { let mut runtime = VirtualMachineRuntime::new(None); diff --git a/docs/runtime/pull-requests/PR006-conformance-regression-suite-fault-status.md b/docs/runtime/pull-requests/PR006-conformance-regression-suite-fault-status.md deleted file mode 100644 index 88473a84..00000000 --- a/docs/runtime/pull-requests/PR006-conformance-regression-suite-fault-status.md +++ /dev/null @@ -1,42 +0,0 @@ -# PR006 - Conformance Regression Suite Fault Status - -## Briefing - -Depois de migrar `gfx`, `audio` e `asset` para status-first, precisamos blindar regressao. - -Esta PR fecha cobertura de conformidade para fronteira `status`/`Trap`/`Panic`. - -## Alvo - -Adicionar/ajustar suite de testes para garantir que o contrato decidido continue estavel. - -Arquivos principais (esperados): - -- testes de `crates/console/prometeu-system/src/virtual_machine_runtime/` -- testes de `crates/console/prometeu-vm/src/virtual_machine.rs` -- testes de `crates/console/prometeu-hal/src/syscalls/tests.rs` - -## Escopo Funcional - -- testes negativos: erro operacional nao pode virar `Panic`; -- testes de shape ABI: aridade/tipo/capability continuam `Trap`; -- testes para proibicao de no-op silencioso nos dominios atualizados; -- smoke de interoperacao entre registry, loader e dispatch apos migracao. - -## Fora de Escopo - -- cobertura exaustiva de performance; -- novos dominios alem de `gfx`, `audio`, `asset`. - -## Critérios de Aceite - -- matriz minima de cenarios `status`/`Trap`/`Panic` coberta por dominio; -- regressao de panic operacional bloqueada por teste; -- execucao dos pacotes de teste alvo sem falha. - -## Tests - -- `cargo test -p prometeu-hal` -- `cargo test -p prometeu-vm` -- `cargo test -p prometeu-system` -- `cargo test -p prometeu-drivers` diff --git a/docs/runtime/pull-requests/README.md b/docs/runtime/pull-requests/README.md index 2863a953..b4b19f41 100644 --- a/docs/runtime/pull-requests/README.md +++ b/docs/runtime/pull-requests/README.md @@ -37,17 +37,3 @@ Uma PR deste diretório deve: ## Roadmap Publicado PRs propostas para execucao da rodada atual: - -1. `PR001-spec-core-sync-16-and-16a.md` -2. `PR002-gfx-status-first-surface-and-fault-matrix.md` -3. `PR003-audio-status-first-surface-and-fault-matrix.md` -4. `PR004-asset-status-first-surface-and-lifecycle.md` -5. `PR005-abi-verifier-loader-and-stress-regeneration.md` -6. `PR006-conformance-regression-suite-fault-status.md` - -Sequenciamento recomendado: - -- `PR001` primeiro; -- `PR002`, `PR003` e `PR004` em paralelo; -- `PR005` depois das tres verticais; -- `PR006` por ultimo para consolidacao de regressao.