Skip to content

Commit 60ebde2

Browse files
wip
1 parent 91cb681 commit 60ebde2

File tree

2 files changed

+139
-10
lines changed

2 files changed

+139
-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: 131 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,106 @@ 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::ExpectedAnOperand => todo!(),
109+
ValidationError::MemoryTooLarge => Ok("memory size must be at most 65536 pages (4GiB)"),
110+
ValidationError::MutationOfConstGlobal => Ok("global is immutable"),
111+
ValidationError::ErroneousAlignment { .. } => {
112+
Ok("alignment must not be larger than natural")
113+
}
114+
ValidationError::ValidationCtrlStackEmpty => todo!(),
115+
ValidationError::ElseWithoutMatchingIf => todo!(),
116+
ValidationError::IfWithoutMatchingElse => todo!(),
117+
ValidationError::MismatchedRefTypesDuringTableInit { table_ty, elem_ty } => todo!(),
118+
ValidationError::MismatchedRefTypesDuringTableCopy {
119+
source_table_ty,
120+
destination_table_ty,
121+
} => todo!(),
122+
ValidationError::MismatchedRefTypesOnValidationStack { expected, actual } => todo!(),
123+
ValidationError::IndirectCallToNonFuncRefTable(ref_type) => todo!(),
124+
ValidationError::ExpectedReferenceTypeOnStack(val_type) => todo!(),
125+
ValidationError::ReferencingAnUnreferencedFunction(func_idx) => todo!(),
126+
ValidationError::InvalidSelectTypeVectorLength(_) => todo!(),
127+
ValidationError::TooManyLocals(_) => Ok("too many locals"),
128+
ValidationError::DuplicateExportName => Ok("duplicate export name"),
129+
ValidationError::UnsupportedMultipleMemoriesProposal => {
130+
Ok("multiple memories are not allowed (yet)")
131+
}
132+
ValidationError::CodeExprHasTrailingInstructions => todo!(),
133+
ValidationError::FunctionAndCodeSectionsHaveDifferentLengths => {
134+
Ok("function and code section have inconsistent lengths")
135+
}
136+
ValidationError::DataCountAndDataSectionsLengthAreDifferent => {
137+
Ok("data count and data section have inconsistent lengths")
138+
}
139+
ValidationError::InvalidStartFunctionSignature => todo!(),
140+
ValidationError::ActiveElementSegmentTypeMismatch => todo!(),
141+
ValidationError::I33IsNegative => todo!(),
142+
// TODO double check if our ValidationError::MissingDataCountSection
143+
// is really the same as "data count section required" in the
144+
// reference interpreter
145+
ValidationError::MissingDataCountSection => Ok("data count section required"),
146+
ValidationError::InvalidDataSegmentMode(_) => Ok("malformed data segement kind"),
147+
ValidationError::InvalidElementMode(_) => Ok("malformed elements segment kind"),
148+
ValidationError::TooManyFunctions => todo!(),
149+
ValidationError::TooManyTables => todo!(),
150+
ValidationError::TooManyMemories => todo!(),
151+
ValidationError::TooManyGlobals => todo!(),
152+
}
153+
.map(str::to_owned)
154+
})
155+
.map_err(WastError::Panic)
156+
.flatten()
57157
}
58158

59159
/// Clear the bytes and runtime instance before calling this function
@@ -280,22 +380,27 @@ fn run_directive<'a>(
280380
wast::WastDirective::AssertMalformed {
281381
span,
282382
module: mut modulee,
283-
message: _,
383+
message,
284384
}
285385
| wast::WastDirective::AssertInvalid {
286386
span,
287387
module: mut modulee,
288-
message: _,
388+
message,
289389
} => {
290390
let line_number = get_linenum(contents, span);
291391
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-
});
392+
393+
// TODO: I think encoding should not produce errors
394+
let bytes = encode(&mut modulee).map_err(|err| {
395+
ScriptError::new(filepath, err, "Failed to encode module", line_number, cmd)
396+
})?;
397+
let bytes = arena.alloc_slice_clone(&bytes);
398+
let result = validate_instantiate(store, bytes, linker, last_instantiated_module);
296399

297400
let maybe_assert_error = match result {
298-
Ok(_module) => Some(WastError::AssertInvalidButValid),
401+
Ok(_) | Err(WastError::FailedToLink | WastError::WasmRuntimeError(_)) => {
402+
Some(WastError::AssertInvalidButValid)
403+
}
299404
Err(panic_err @ WastError::Panic(_)) => {
300405
return Err(ScriptError::new(
301406
filepath,
@@ -305,7 +410,24 @@ fn run_directive<'a>(
305410
cmd,
306411
))
307412
}
308-
Err(_other) => None,
413+
Err(WastError::WasmError(validation_error)) => {
414+
match validation_error_to_wasm_testsuite_string(&validation_error) {
415+
Ok(actual_message) => {
416+
if actual_message == message {
417+
None
418+
} else {
419+
Some(WastError::UnexpectedValidationError {
420+
expected: message.to_owned(),
421+
actual: validation_error,
422+
})
423+
}
424+
}
425+
Err(err) => Some(err),
426+
}
427+
}
428+
Err(other_err) => {
429+
unreachable!("no other errors should be possible here, got: {other_err}")
430+
}
309431
};
310432

311433
Ok(Some(AssertOutcome {

0 commit comments

Comments
 (0)