Skip to content

Commit 28cfde5

Browse files
wip
1 parent 91cb681 commit 28cfde5

File tree

2 files changed

+141
-10
lines changed

2 files changed

+141
-10
lines changed

tests/specification/reports.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::any::Any;
22

3-
use wasm::{RuntimeError, TrapError};
3+
use wasm::{RuntimeError, TrapError, ValidationError};
44

55
use super::test_errors::AssertEqError;
66

@@ -44,6 +44,8 @@ pub enum WastError {
4444
Wast(#[from] wast::Error),
4545
#[error("Runtime error not represented in WAST")]
4646
UnrepresentedRuntimeError,
47+
#[error("Validation error not represented in WAST: {0}")]
48+
UnrepresentedValidationError(ValidationError),
4749
#[error("{0}")]
4850
Io(#[from] std::io::Error),
4951
#[error("Some directive either referenced a non-existing Wasm module by its id or it did not specify an id at all and there was no other module defined prior to this directive.")]
@@ -54,6 +56,11 @@ pub enum WastError {
5456
UnknownGlobalReferenced,
5557
#[error("Module failed to link")]
5658
FailedToLink,
59+
#[error("Got unexpected validation error {actual}, expected {expected}")]
60+
UnexpectedValidationError {
61+
expected: String,
62+
actual: ValidationError,
63+
},
5764
}
5865

5966
impl From<wasm::ValidationError> for WastError {

tests/specification/run.rs

Lines changed: 133 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use wasm::RuntimeError;
2020
use wasm::TableType;
2121
use wasm::TrapError;
2222
use wasm::ValType;
23+
use wasm::ValidationError;
2324
use wast::core::WastArgCore;
2425
use wast::core::WastRetCore;
2526
use wast::{QuoteWat, WastArg, WastDirective, WastRet, Wat};
@@ -53,7 +54,108 @@ pub fn error_to_wasm_testsuite_string(runtime_error: &RuntimeError) -> Result<St
5354
RuntimeError::HostFunctionSignatureMismatch => Ok("host function signature mismatch"),
5455
_ => Err(WastError::UnrepresentedRuntimeError),
5556
}
56-
.map(ToOwned::to_owned)
57+
.map(str::to_owned)
58+
}
59+
60+
pub fn validation_error_to_wasm_testsuite_string(
61+
validation_error: &ValidationError,
62+
) -> Result<String, WastError> {
63+
std::panic::catch_unwind(|| {
64+
match validation_error {
65+
// _ => Err(WastError::UnrepresentedValidationError(
66+
// validation_error.clone(),
67+
// )),
68+
ValidationError::InvalidMagic => Ok("magic header not detected"),
69+
ValidationError::InvalidBinaryFormatVersion => Ok("unknown binary version"),
70+
ValidationError::Eof => todo!(),
71+
ValidationError::MalformedUtf8(_) => Ok("malformed UTF-8 encoding"),
72+
ValidationError::MalformedSectionTypeDiscriminator(_) => Ok("malformed section id"),
73+
ValidationError::MalformedNumTypeDiscriminator(_) => Ok("malformed number type"),
74+
ValidationError::MalformedVecTypeDiscriminator(_) => Ok("malformed vector type"),
75+
ValidationError::MalformedFuncTypeDiscriminator(_) => Ok("malformed function type"),
76+
ValidationError::MalformedRefTypeDiscriminator(_) => Ok("malformed reference type"),
77+
ValidationError::MalformedValType => todo!(),
78+
ValidationError::MalformedExportDescDiscriminator(_) => Ok("malformed export kind"),
79+
ValidationError::MalformedImportDescDiscriminator(_) => Ok("malformed import kind"),
80+
ValidationError::MalformedLimitsDiscriminator(_) => todo!(),
81+
ValidationError::MalformedLimitsMinLargerThanMax { .. } => todo!(),
82+
ValidationError::MalformedMutDiscriminator(_) => Ok("malformed mutability"),
83+
ValidationError::MalformedVariableLengthInteger => todo!(),
84+
ValidationError::MalformedElemKindDiscriminator(_) => Ok("malformed element kind"),
85+
ValidationError::InvalidTypeIdx(_) => Ok("unknown type"),
86+
ValidationError::InvalidFuncIdx(_) => Ok("unknown function"),
87+
ValidationError::InvalidTableIdx(_) => Ok("unknown table"),
88+
ValidationError::InvalidMemIdx(_) => Ok("unknown memory"),
89+
ValidationError::InvalidGlobalIdx(_) => Ok("unknown global"),
90+
ValidationError::InvalidElemIdx(_) => Ok("unknown elem segment"),
91+
ValidationError::InvalidDataIdx(_) => Ok("unknown data segment"),
92+
ValidationError::InvalidLocalIdx(_) => Ok("unknown local"),
93+
ValidationError::InvalidLabelIdx(_) => Ok("unknown label"),
94+
ValidationError::InvalidLaneIdx(_) => {
95+
todo!("this can be \"malformed lane index\" or \"invalid lane index\"")
96+
}
97+
ValidationError::UnexpectedContentAfterLastSection => {
98+
Ok("unexpected content after last section")
99+
}
100+
ValidationError::InvalidCustomSectionLength => todo!(),
101+
ValidationError::ExprMissingEnd => todo!(),
102+
ValidationError::InvalidInstr(byte) => return Ok(format!("illegal opcode {byte:02x}")),
103+
ValidationError::InvalidMultiByteInstr(byte, i) => {
104+
return Ok(format!("illegal opcode {byte:02x} {i:02x}"))
105+
}
106+
ValidationError::EndInvalidValueStack => todo!(),
107+
ValidationError::InvalidValidationStackValType(val_type) => todo!(),
108+
ValidationError::InvalidValidationStackType(validation_stack_entry) => todo!(),
109+
ValidationError::ExpectedAnOperand => todo!(),
110+
ValidationError::MemoryTooLarge => Ok("memory size must be at most 65536 pages (4GiB)"),
111+
ValidationError::MutationOfConstGlobal => Ok("global is immutable"),
112+
ValidationError::ErroneousAlignment { .. } => {
113+
Ok("alignment must not be larger than natural")
114+
}
115+
ValidationError::ValidationCtrlStackEmpty => todo!(),
116+
ValidationError::ElseWithoutMatchingIf => todo!(),
117+
ValidationError::IfWithoutMatchingElse => todo!(),
118+
ValidationError::MismatchedRefTypesDuringTableInit { table_ty, elem_ty } => todo!(),
119+
ValidationError::MismatchedRefTypesDuringTableCopy {
120+
source_table_ty,
121+
destination_table_ty,
122+
} => todo!(),
123+
ValidationError::MismatchedRefTypesOnValidationStack { expected, actual } => todo!(),
124+
ValidationError::IndirectCallToNonFuncRefTable(ref_type) => todo!(),
125+
ValidationError::ExpectedReferenceTypeOnStack(val_type) => todo!(),
126+
ValidationError::ReferencingAnUnreferencedFunction(func_idx) => todo!(),
127+
ValidationError::InvalidSelectTypeVectorLength(_) => todo!(),
128+
ValidationError::TooManyLocals(_) => Ok("too many locals"),
129+
ValidationError::DuplicateExportName => Ok("duplicate export name"),
130+
ValidationError::UnsupportedMultipleMemoriesProposal => {
131+
Ok("multiple memories are not allowed (yet)")
132+
}
133+
ValidationError::CodeExprHasTrailingInstructions => todo!(),
134+
ValidationError::FunctionAndCodeSectionsHaveDifferentLengths => {
135+
Ok("function and code section have inconsistent lengths")
136+
}
137+
ValidationError::DataCountAndDataSectionsLengthAreDifferent => {
138+
Ok("data count and data section have inconsistent lengths")
139+
}
140+
ValidationError::InvalidImportType => todo!(),
141+
ValidationError::InvalidStartFunctionSignature => todo!(),
142+
ValidationError::ActiveElementSegmentTypeMismatch => todo!(),
143+
ValidationError::I33IsNegative => todo!(),
144+
// TODO double check if our ValidationError::MissingDataCountSection
145+
// is really the same as "data count section required" in the
146+
// reference interpreter
147+
ValidationError::MissingDataCountSection => Ok("data count section required"),
148+
ValidationError::InvalidDataSegmentMode(_) => Ok("malformed data segement kind"),
149+
ValidationError::InvalidElementMode(_) => Ok("malformed elements segment kind"),
150+
ValidationError::TooManyFunctions => todo!(),
151+
ValidationError::TooManyTables => todo!(),
152+
ValidationError::TooManyMemories => todo!(),
153+
ValidationError::TooManyGlobals => todo!(),
154+
}
155+
.map(str::to_owned)
156+
})
157+
.map_err(WastError::Panic)
158+
.flatten()
57159
}
58160

59161
/// Clear the bytes and runtime instance before calling this function
@@ -280,22 +382,27 @@ fn run_directive<'a>(
280382
wast::WastDirective::AssertMalformed {
281383
span,
282384
module: mut modulee,
283-
message: _,
385+
message,
284386
}
285387
| wast::WastDirective::AssertInvalid {
286388
span,
287389
module: mut modulee,
288-
message: _,
390+
message,
289391
} => {
290392
let line_number = get_linenum(contents, span);
291393
let cmd = get_command(contents, span);
292-
let result = encode(&mut modulee).and_then(|bytes| {
293-
let bytes = arena.alloc_slice_clone(&bytes);
294-
validate_instantiate(store, bytes, linker, last_instantiated_module)
295-
});
394+
395+
// TODO: I think encoding should not produce errors
396+
let bytes = encode(&mut modulee).map_err(|err| {
397+
ScriptError::new(filepath, err, "Failed to encode module", line_number, cmd)
398+
})?;
399+
let bytes = arena.alloc_slice_clone(&bytes);
400+
let result = validate_instantiate(store, bytes, linker, last_instantiated_module);
296401

297402
let maybe_assert_error = match result {
298-
Ok(_module) => Some(WastError::AssertInvalidButValid),
403+
Ok(_) | Err(WastError::FailedToLink | WastError::WasmRuntimeError(_)) => {
404+
Some(WastError::AssertInvalidButValid)
405+
}
299406
Err(panic_err @ WastError::Panic(_)) => {
300407
return Err(ScriptError::new(
301408
filepath,
@@ -305,7 +412,24 @@ fn run_directive<'a>(
305412
cmd,
306413
))
307414
}
308-
Err(_other) => None,
415+
Err(WastError::WasmError(validation_error)) => {
416+
match validation_error_to_wasm_testsuite_string(&validation_error) {
417+
Ok(actual_message) => {
418+
if actual_message == message {
419+
None
420+
} else {
421+
Some(WastError::UnexpectedValidationError {
422+
expected: message.to_owned(),
423+
actual: validation_error,
424+
})
425+
}
426+
}
427+
Err(err) => Some(err),
428+
}
429+
}
430+
Err(other_err) => {
431+
unreachable!("no other errors should be possible here, got: {other_err}")
432+
}
309433
};
310434

311435
Ok(Some(AssertOutcome {

0 commit comments

Comments
 (0)