use tensor_wasm_jit::ir::{ElemType, GridHint, TensorWasmKernelBlueprint, TensorWasmOp};
use tensor_wasm_jit::ptx_emit::{emit, is_valid_ptx_identifier, EmitError, MAX_PTX_IDENTIFIER_LEN};
#[test]
fn validator_accepts_canonical_identifiers() {
assert!(is_valid_ptx_identifier("func0"));
assert!(is_valid_ptx_identifier("_kernel"));
assert!(is_valid_ptx_identifier("my$kernel"));
assert!(is_valid_ptx_identifier("a"));
assert!(is_valid_ptx_identifier("A_b_C_1_2_3"));
}
#[test]
fn validator_rejects_invalid_identifiers() {
assert!(!is_valid_ptx_identifier(""));
assert!(!is_valid_ptx_identifier("0starts_with_digit"));
assert!(!is_valid_ptx_identifier("has space"));
assert!(!is_valid_ptx_identifier("has)closeparen"));
assert!(!is_valid_ptx_identifier("has\nnewline"));
assert!(!is_valid_ptx_identifier("has;semicolon"));
let too_long: String = "a".repeat(MAX_PTX_IDENTIFIER_LEN + 1);
assert!(!is_valid_ptx_identifier(&too_long));
let at_cap: String = "a".repeat(MAX_PTX_IDENTIFIER_LEN);
assert!(is_valid_ptx_identifier(&at_cap));
}
#[test]
fn emit_rejects_injection_entry() {
let bp = TensorWasmKernelBlueprint::new(".entry attacker()\n")
.push(TensorWasmOp::StoreUnified {
elem: ElemType::F32,
lanes: 4,
})
.with_grid(GridHint {
total_threads: 1024,
preferred_block_size: 128,
});
let err = emit(&bp).expect_err("injection entry must be rejected");
assert!(matches!(err, EmitError::InvalidEntryName { .. }));
}
#[test]
fn emit_accepts_canonical_entry() {
let bp = TensorWasmKernelBlueprint::new("safe_kernel_42")
.push(TensorWasmOp::StoreUnified {
elem: ElemType::F32,
lanes: 4,
})
.with_grid(GridHint {
total_threads: 1024,
preferred_block_size: 128,
});
let out = emit(&bp).expect("canonical entry must succeed");
assert!(out.text.contains(".visible .entry safe_kernel_42("));
}