2021-05-13 17:21:43 +00:00
|
|
|
//! Tests for the WGSL front end.
|
|
|
|
#![cfg(feature = "wgsl-in")]
|
|
|
|
|
2021-04-14 18:20:48 +00:00
|
|
|
fn check(input: &str, snapshot: &str) {
|
|
|
|
let output = naga::front::wgsl::parse_str(input)
|
|
|
|
.expect_err("expected parser error")
|
2021-05-02 04:49:02 +00:00
|
|
|
.emit_to_string(input);
|
2021-04-14 18:20:48 +00:00
|
|
|
if output != snapshot {
|
|
|
|
for diff in diff::lines(&output, snapshot) {
|
|
|
|
match diff {
|
|
|
|
diff::Result::Left(l) => println!("-{}", l),
|
|
|
|
diff::Result::Both(l, _) => println!(" {}", l),
|
|
|
|
diff::Result::Right(r) => println!("+{}", r),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic!("Error snapshot failed");
|
|
|
|
}
|
2021-02-13 20:54:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn function_without_identifier() {
|
2021-04-14 18:20:48 +00:00
|
|
|
check(
|
2021-02-13 20:54:31 +00:00
|
|
|
"fn () {}",
|
2021-04-14 23:22:40 +00:00
|
|
|
r###"error: expected identifier, found '('
|
2021-04-14 18:20:48 +00:00
|
|
|
┌─ wgsl:1:4
|
|
|
|
│
|
|
|
|
1 │ fn () {}
|
|
|
|
│ ^ expected identifier
|
2021-02-28 04:22:34 +00:00
|
|
|
|
2021-04-14 18:20:48 +00:00
|
|
|
"###,
|
2021-02-13 20:54:31 +00:00
|
|
|
);
|
|
|
|
}
|
2021-03-04 03:28:54 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn invalid_integer() {
|
2021-04-14 18:20:48 +00:00
|
|
|
check(
|
2021-03-07 05:03:05 +00:00
|
|
|
"fn foo([location(1.)] x: i32) {}",
|
2021-04-14 23:22:40 +00:00
|
|
|
r###"error: expected identifier, found '['
|
2021-04-14 18:20:48 +00:00
|
|
|
┌─ wgsl:1:8
|
|
|
|
│
|
|
|
|
1 │ fn foo([location(1.)] x: i32) {}
|
|
|
|
│ ^ expected identifier
|
2021-03-04 03:28:54 +00:00
|
|
|
|
2021-04-14 18:20:48 +00:00
|
|
|
"###,
|
2021-03-04 03:28:54 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn invalid_float() {
|
2021-04-14 18:20:48 +00:00
|
|
|
check(
|
2021-04-11 04:35:03 +00:00
|
|
|
"let scale: f32 = 1.1.;",
|
2021-04-14 23:22:40 +00:00
|
|
|
r###"error: expected floating-point literal, found `1.1.`
|
2021-04-14 18:20:48 +00:00
|
|
|
┌─ wgsl:1:18
|
|
|
|
│
|
|
|
|
1 │ let scale: f32 = 1.1.;
|
|
|
|
│ ^^^^ expected floating-point literal
|
2021-03-04 03:28:54 +00:00
|
|
|
|
2021-04-14 18:20:48 +00:00
|
|
|
"###,
|
2021-03-04 03:28:54 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn invalid_scalar_width() {
|
2021-04-14 18:20:48 +00:00
|
|
|
check(
|
2021-04-11 04:35:03 +00:00
|
|
|
"let scale: f32 = 1.1f1000;",
|
2021-04-14 23:22:40 +00:00
|
|
|
r###"error: invalid width of `1000` for literal
|
2021-04-14 18:20:48 +00:00
|
|
|
┌─ wgsl:1:18
|
|
|
|
│
|
|
|
|
1 │ let scale: f32 = 1.1f1000;
|
|
|
|
│ ^^^^^^^^ invalid width
|
|
|
|
│
|
|
|
|
= note: valid width is 32
|
2021-03-04 03:28:54 +00:00
|
|
|
|
2021-04-14 18:20:48 +00:00
|
|
|
"###,
|
2021-03-04 03:28:54 +00:00
|
|
|
);
|
|
|
|
}
|
2021-05-13 17:29:03 +00:00
|
|
|
|
|
|
|
macro_rules! check_validation_error {
|
|
|
|
( $( $source:literal ),* : $pattern:pat ) => {
|
|
|
|
$(
|
|
|
|
let error = validation_error($source);
|
|
|
|
if ! matches!(error, $pattern) {
|
|
|
|
eprintln!("validation error does not match pattern:\n\
|
|
|
|
{:?}\n\
|
|
|
|
\n\
|
|
|
|
expected match for pattern:\n\
|
|
|
|
{}",
|
|
|
|
error,
|
|
|
|
stringify!($pattern));
|
|
|
|
panic!("validation error does not match pattern");
|
|
|
|
}
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn validation_error(source: &str) -> Result<naga::valid::ModuleInfo, naga::valid::ValidationError> {
|
|
|
|
let module = naga::front::wgsl::parse_str(source).expect("expected WGSL parse to succeed");
|
|
|
|
naga::valid::Validator::new(
|
|
|
|
naga::valid::ValidationFlags::all(),
|
|
|
|
naga::valid::Capabilities::empty(),
|
|
|
|
)
|
|
|
|
.validate(&module)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn invalid_arrays() {
|
|
|
|
check_validation_error! {
|
|
|
|
"type Bad = array<array<f32>, 4>;",
|
|
|
|
"type Bad = array<sampler, 4>;",
|
|
|
|
"type Bad = array<texture_2d<f32>, 4>;":
|
|
|
|
Err(naga::valid::ValidationError::Type {
|
|
|
|
error: naga::valid::TypeError::InvalidArrayBaseType(_),
|
|
|
|
..
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
check_validation_error! {
|
|
|
|
r#"
|
|
|
|
[[block]] struct Block { value: f32; };
|
|
|
|
type Bad = array<Block, 4>;
|
|
|
|
"#:
|
|
|
|
Err(naga::valid::ValidationError::Type {
|
|
|
|
error: naga::valid::TypeError::NestedBlock,
|
|
|
|
..
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
check_validation_error! {
|
|
|
|
r#"
|
|
|
|
type Bad = [[stride(2)]] array<f32, 4>;
|
|
|
|
"#:
|
|
|
|
Err(naga::valid::ValidationError::Type {
|
|
|
|
error: naga::valid::TypeError::InsufficientArrayStride { stride: 2, base_size: 4 },
|
|
|
|
..
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
check_validation_error! {
|
|
|
|
"type Bad = array<f32, true>;",
|
|
|
|
r#"
|
|
|
|
let length: f32 = 2.718;
|
|
|
|
type Bad = array<f32, length>;
|
|
|
|
"#:
|
|
|
|
Err(naga::valid::ValidationError::Type {
|
|
|
|
error: naga::valid::TypeError::InvalidArraySizeConstant(_),
|
|
|
|
..
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn invalid_structs() {
|
|
|
|
check_validation_error! {
|
|
|
|
"struct Bad { data: sampler; };",
|
|
|
|
"struct Bad { data: texture_2d<f32>; };":
|
|
|
|
Err(naga::valid::ValidationError::Type {
|
|
|
|
error: naga::valid::TypeError::InvalidData(_),
|
|
|
|
..
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
check_validation_error! {
|
|
|
|
"[[block]] struct Bad { data: ptr<storage, f32>; };":
|
|
|
|
Err(naga::valid::ValidationError::Type {
|
|
|
|
error: naga::valid::TypeError::InvalidBlockType(_),
|
|
|
|
..
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
check_validation_error! {
|
|
|
|
"struct Bad { data: array<f32>; other: f32; };":
|
|
|
|
Err(naga::valid::ValidationError::Type {
|
|
|
|
error: naga::valid::TypeError::InvalidDynamicArray(_, _),
|
|
|
|
..
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|