diff --git a/uefi-macros/Cargo.toml b/uefi-macros/Cargo.toml index ea831ce03..fb9df1fe5 100644 --- a/uefi-macros/Cargo.toml +++ b/uefi-macros/Cargo.toml @@ -22,3 +22,7 @@ proc-macro = true proc-macro2 = "1.0.28" quote = "1.0.9" syn = { version = "1.0.75", features = ["full"] } + +[dev-dependencies] +trybuild = "1.0.45" +uefi = { version = "0.12.0", default-features = false } diff --git a/uefi-macros/tests/cargo_wrapper b/uefi-macros/tests/cargo_wrapper new file mode 100755 index 000000000..49db776c7 --- /dev/null +++ b/uefi-macros/tests/cargo_wrapper @@ -0,0 +1,2 @@ +#!/bin/sh +cargo -Zbuild-std=std "$@" diff --git a/uefi-macros/tests/compilation.rs b/uefi-macros/tests/compilation.rs new file mode 100644 index 000000000..1fec59ffd --- /dev/null +++ b/uefi-macros/tests/compilation.rs @@ -0,0 +1,20 @@ +use std::env; + +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + + // Due to the way trybuild compiles the input files, `no_std` + // doesn't work. So, since -Zbuild-std is enabled in the cargo + // config file in the root of the crate we need to also build the + // std crate for these tests. This wrapper script adds the necessary + // argument when trybuild invokes cargo. + let cargo_wrapper = env::current_exe() + .unwrap() + .parent() + .unwrap() + .join("../../../../uefi-macros/tests/cargo_wrapper"); + env::set_var("CARGO", cargo_wrapper); + + t.compile_fail("tests/ui/*.rs"); +} diff --git a/uefi-macros/tests/ui/entry.rs b/uefi-macros/tests/ui/entry.rs new file mode 100644 index 000000000..91dda4a52 --- /dev/null +++ b/uefi-macros/tests/ui/entry.rs @@ -0,0 +1,45 @@ +#![no_main] +#![feature(abi_efiapi)] + +use uefi::prelude::*; +use uefi_macros::entry; + +#[entry] +fn good_entry(_handle: Handle, _st: SystemTable) -> Status { + Status::SUCCESS +} + +#[entry(some_arg)] +fn bad_attr_arg(_handle: Handle, _st: SystemTable) -> Status { + Status::SUCCESS +} + +#[entry] +extern "C" fn bad_abi_modifier(_handle: Handle, _st: SystemTable) -> Status { + Status::SUCCESS +} + +#[entry] +async fn bad_async(_handle: Handle, _st: SystemTable) -> Status { + Status::SUCCESS +} + +#[entry] +fn bad_const(_handle: Handle, _st: SystemTable) -> Status { + Status::SUCCESS +} + +#[entry] +fn bad_generic(_handle: Handle, _st: SystemTable) -> Status { + Status::SUCCESS +} + +#[entry] +fn bad_args(_handle: Handle, _st: SystemTable, _x: usize) -> bool { + false +} + +#[entry] +fn bad_return_type(_handle: Handle, _st: SystemTable) -> bool { + false +} diff --git a/uefi-macros/tests/ui/entry.stderr b/uefi-macros/tests/ui/entry.stderr new file mode 100644 index 000000000..fb8dfc563 --- /dev/null +++ b/uefi-macros/tests/ui/entry.stderr @@ -0,0 +1,41 @@ +error: Entry attribute accepts no arguments + --> $DIR/entry.rs:12:9 + | +12 | #[entry(some_arg)] + | ^^^^^^^^ + +error: Entry method must have no ABI modifier + --> $DIR/entry.rs:18:1 + | +18 | extern "C" fn bad_abi_modifier(_handle: Handle, _st: SystemTable) -> Status { + | ^^^^^^^^^^ + +error: Entry method should not be async + --> $DIR/entry.rs:23:1 + | +23 | async fn bad_async(_handle: Handle, _st: SystemTable) -> Status { + | ^^^^^ + +error: Entry method should not be generic + --> $DIR/entry.rs:33:16 + | +33 | fn bad_generic(_handle: Handle, _st: SystemTable) -> Status { + | ^ + +error[E0308]: mismatched types + --> $DIR/entry.rs:38:4 + | +38 | fn bad_args(_handle: Handle, _st: SystemTable, _x: usize) -> bool { + | ^^^^^^^^ incorrect number of function parameters + | + = note: expected fn pointer `extern "efiapi" fn(uefi::Handle, uefi::table::SystemTable) -> uefi::Status` + found fn item `extern "efiapi" fn(uefi::Handle, uefi::table::SystemTable, usize) -> bool {bad_args}` + +error[E0308]: mismatched types + --> $DIR/entry.rs:43:4 + | +43 | fn bad_return_type(_handle: Handle, _st: SystemTable) -> bool { + | ^^^^^^^^^^^^^^^ expected struct `uefi::Status`, found `bool` + | + = note: expected fn pointer `extern "efiapi" fn(uefi::Handle, uefi::table::SystemTable<_>) -> uefi::Status` + found fn item `extern "efiapi" fn(uefi::Handle, uefi::table::SystemTable<_>) -> bool {bad_return_type}` diff --git a/uefi-macros/tests/ui/guid.rs b/uefi-macros/tests/ui/guid.rs new file mode 100644 index 000000000..4f18b21af --- /dev/null +++ b/uefi-macros/tests/ui/guid.rs @@ -0,0 +1,19 @@ +use uefi_macros::unsafe_guid; + +// The GUID here is OK. +#[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")] +struct Good; + +// Fail because the length is wrong. +#[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa")] +struct TooShort; + +// Error span should point to the second group. +#[unsafe_guid("aaaaaaaa-Gaaa-aaaa-aaaa-aaaaaaaaaaaa")] +struct BadHexGroup2; + +// Error span should point to the fifth group. +#[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaG")] +struct BadHexGroup5; + +fn main() {} diff --git a/uefi-macros/tests/ui/guid.stderr b/uefi-macros/tests/ui/guid.stderr new file mode 100644 index 000000000..8337be27e --- /dev/null +++ b/uefi-macros/tests/ui/guid.stderr @@ -0,0 +1,17 @@ +error: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa" is not a canonical GUID string (expected 36 bytes, found 35) + --> $DIR/guid.rs:8:15 + | +8 | #[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: GUID component "Gaaa" is not a hexadecimal number + --> $DIR/guid.rs:12:25 + | +12 | #[unsafe_guid("aaaaaaaa-Gaaa-aaaa-aaaa-aaaaaaaaaaaa")] + | ^^^^ + +error: GUID component "aaaaaaaaaaaG" is not a hexadecimal number + --> $DIR/guid.rs:16:40 + | +16 | #[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaG")] + | ^^^^^^^^^^^^