diff --git a/COVERAGE.md b/COVERAGE.md new file mode 100644 index 0000000000..4c26787696 --- /dev/null +++ b/COVERAGE.md @@ -0,0 +1,35 @@ +# Code Coverage + +## Quick Start + +```bash +# Install cargo-llvm-cov (first time only) +cargo install cargo-llvm-cov + +# Run coverage and open HTML report +cargo llvm-cov --html --open + +# Run coverage for specific tests +cargo llvm-cov --html --open -- test_name +``` + +## Reports + +HTML report location: `target/llvm-cov/html/index.html` + +## Coverage Summary + +View text summary: +```bash +cargo llvm-cov report --summary-only +``` + +## Notes + +- Trybuild compile-time tests do not appear in coverage reports (they verify compile errors, not runtime behavior) +- Coverage measures runtime test execution only +- Current project coverage: ~74% lines, ~68% functions + +## Reference + +- [cargo-llvm-cov documentation](https://github.com/taiki-e/cargo-llvm-cov) diff --git a/Cargo.lock b/Cargo.lock index 9447fc2fec..4e904f9828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1336,12 +1336,6 @@ dependencies = [ "allocator-api2", ] -[[package]] -name = "hashbrown" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" - [[package]] name = "hashbrown" version = "0.16.1" @@ -1647,7 +1641,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.15.3", + "hashbrown 0.16.1", ] [[package]] @@ -3375,6 +3369,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_spanned" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3648,6 +3651,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" +[[package]] +name = "target-triple" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "591ef38edfb78ca4771ee32cf494cb8771944bee237a9b91fc9c1424ac4b777b" + [[package]] name = "tempfile" version = "3.21.0" @@ -3864,6 +3873,45 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.9.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" + [[package]] name = "tower" version = "0.5.2" @@ -3998,6 +4046,21 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "trybuild" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e17e807bff86d2a06b52bca4276746584a78375055b6e45843925ce2802b335" +dependencies = [ + "glob", + "serde", + "serde_derive", + "serde_json", + "target-triple", + "termcolor", + "toml", +] + [[package]] name = "twox-hash" version = "2.1.2" @@ -4256,6 +4319,7 @@ dependencies = [ "tokio", "tracing", "tracing-test", + "trybuild", "ua-parser", "unicode-segmentation", "url", @@ -4815,6 +4879,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" + [[package]] name = "winsafe" version = "0.0.19" diff --git a/Cargo.toml b/Cargo.toml index dc6f403fdb..c8f1e53338 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -263,6 +263,7 @@ regex = { version = "1", default-features = false, features = ["std", "perf", "u paste = { version = "1", default-features = false } proptest = { version = "1" } proptest-derive = { version = "0.6" } +trybuild = "1.0.114" [build-dependencies] lalrpop = { version = "0.22", default-features = false } diff --git a/scripts/check_deny.sh b/scripts/check_deny.sh index 0a5825c22f..842a1c8fbd 100755 --- a/scripts/check_deny.sh +++ b/scripts/check_deny.sh @@ -1,8 +1,8 @@ #!/bin/bash -if ! cargo install --list | grep -q "cargo-deny v0.18.3"; then +if ! cargo install --list | grep -q "cargo-deny v0.19.0"; then echo "Install cargo-deny" - cargo install cargo-deny --version 0.18.3 --force --locked + cargo install cargo-deny --version 0.19.0 --force --locked fi echo "Check deny" diff --git a/src/compiler/function.rs b/src/compiler/function.rs index 0b416fd740..035bcec2f2 100644 --- a/src/compiler/function.rs +++ b/src/compiler/function.rs @@ -87,7 +87,55 @@ pub struct Example { /// Macro to create an `Example` with automatic source location tracking /// Accepts fields in any order: title, source, result /// Optional fields added to `Example` shouldn't be required to be added for the macro to work, -/// mainting backwards compatibility +/// maintaining backwards compatibility +/// +/// # Examples +/// +/// Valid usage: +/// ``` +/// use vrl::example; +/// +/// let ex = example! { +/// title: "test", +/// source: "code", +/// result: Ok("output"), +/// }; +/// ``` +/// +/// Missing required field should fail: +/// ```compile_fail +/// use vrl::example; +/// +/// let ex = example! { +/// title: "test", +/// source: "code", +/// // missing result field +/// }; +/// ``` +/// +/// Duplicate field should fail: +/// ```compile_fail +/// use vrl::example; +/// +/// let ex = example! { +/// title: "test", +/// source: "code", +/// result: Ok("output"), +/// title: "duplicate", +/// }; +/// ``` +/// +/// Unknown field should fail: +/// ```compile_fail +/// use vrl::example; +/// +/// let ex = example! { +/// title: "test", +/// source: "code", +/// result: Ok("output"), +/// unknown_field: "value", +/// }; +/// ``` #[macro_export] macro_rules! example { // Entry point - delegate to internal parser with empty state @@ -97,6 +145,21 @@ macro_rules! example { $crate::example!(@internal [] [] [] [$($field: $value,)*]) }; + // Error: duplicate title field + (@internal [$title:expr] [$($source:tt)*] [$($result:tt)*] [title: $t:expr, $($rest:tt)*]) => { + compile_error!("duplicate 'title' field in example! macro") + }; + + // Error: duplicate source field + (@internal [$($title:tt)*] [$source:expr] [$($result:tt)*] [source: $s:expr, $($rest:tt)*]) => { + compile_error!("duplicate 'source' field in example! macro") + }; + + // Error: duplicate result field + (@internal [$($title:tt)*] [$($source:tt)*] [$result:expr] [result: $r:expr, $($rest:tt)*]) => { + compile_error!("duplicate 'result' field in example! macro") + }; + // Parse title field (@internal [$($title:tt)*] [$($source:tt)*] [$($result:tt)*] [title: $t:expr, $($rest:tt)*]) => { $crate::example!(@internal [$t] [$($source)*] [$($result)*] [$($rest)*]) @@ -714,4 +777,27 @@ mod tests { assert_eq!(ex3.source, "code3"); assert_eq!(ex3.result, Err("error3")); } + + #[test] + fn test_example_macro_trailing_commas() { + // Test with trailing comma + let ex_with_comma = example! { + title: "test", + source: "code", + result: Ok("ok"), + }; + assert_eq!(ex_with_comma.title, "test"); + assert_eq!(ex_with_comma.source, "code"); + assert_eq!(ex_with_comma.result, Ok("ok")); + + // Test without trailing comma + let ex_no_comma = example! { + title: "test", + source: "code", + result: Ok("ok") + }; + assert_eq!(ex_no_comma.title, "test"); + assert_eq!(ex_no_comma.source, "code"); + assert_eq!(ex_no_comma.result, Ok("ok")); + } } diff --git a/src/stdlib/parse_klog.rs b/src/stdlib/parse_klog.rs index c1c86768d1..841f0b3b5f 100644 --- a/src/stdlib/parse_klog.rs +++ b/src/stdlib/parse_klog.rs @@ -89,7 +89,7 @@ impl Function for ParseKlog { "level": "info", "line": 70, "message": "hello from klog", - "timestamp": "2025-05-05T17:59:40.692994Z" + "timestamp": "{CURRENT_YEAR}-05-05T17:59:40.692994Z" }"#}), }] } diff --git a/src/stdlib/parse_linux_authorization.rs b/src/stdlib/parse_linux_authorization.rs index 7caef05741..009d312b5c 100644 --- a/src/stdlib/parse_linux_authorization.rs +++ b/src/stdlib/parse_linux_authorization.rs @@ -27,7 +27,7 @@ impl Function for ParseLinuxAuthorization { "hostname": "localhost", "message": "Accepted publickey for eng from 10.1.1.1 port 8888 ssh2: RSA SHA256:foobar", "procid": 1111, - "timestamp": "2025-03-23T01:49:58Z" + "timestamp": "{CURRENT_YEAR}-03-23T01:49:58Z" }"#}), }] } diff --git a/src/test/mod.rs b/src/test/mod.rs index ceab7fdb8f..955bd5108a 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -208,7 +208,7 @@ fn process_result( let got_value = vrl_value_to_json_value(got); let mut failed = false; - let want = test.result.clone(); + let want = replace_current_year_placeholder(test.result.clone()); let want_value = if want.starts_with("r'") && want.ends_with('\'') { match regex::Regex::new(&want[2..want.len() - 1].replace("\\'", "'")) { Ok(regex) => regex.to_string().into(), @@ -257,7 +257,7 @@ fn process_result( Err(err) => { let mut failed = false; let got = err.to_string().trim().to_owned(); - let want = test.result.clone().trim().to_owned(); + let want = replace_current_year_placeholder(test.result.clone().trim().to_owned()); if (test.result_approx && compare_partial_diagnostic(&got, &want)) || got == want { println!("{}{}", Colour::Green.bold().paint("OK"), timings); @@ -319,7 +319,7 @@ fn process_compilation_diagnostics( let got = formatter.to_string(); let got = got.trim(); - let want = test.result.clone(); + let want = replace_current_year_placeholder(test.result.clone()); let want = want.trim(); if (test.result_approx && compare_partial_diagnostic(got, want)) || got == want { @@ -404,6 +404,11 @@ fn print_result( std::process::exit(code) } +fn replace_current_year_placeholder(input: String) -> String { + let current_year = Utc::now().format("%Y").to_string(); + input.replace("{CURRENT_YEAR}", ¤t_year) +} + fn compare_partial_diagnostic(got: &str, want: &str) -> bool { got.lines() .filter(|line| line.trim().starts_with("error[E")) diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000000..de766bbaaf --- /dev/null +++ b/tests/README.md @@ -0,0 +1,46 @@ +# VRL Tests + +Some tests are organized to mirror source code structure: +``` +src/compiler/function.rs → tests/compiler/function/*/ +src/parser/lex.rs → tests/parser/lex/*/ +``` + +## Trybuild Tests (Compile-Time) + +Trybuild tests verify code fails to compile with correct error messages. Defined in `tests/trybuild.rs`. + +### Quick Workflow + +1. **Create test file**: `tests/compiler/function/example/my_test.rs` +2. **Run tests**: `cargo test --test trybuild` (creates `wip/my_test.stderr`) +3. **Review error**: `cat wip/my_test.stderr` +4. **Accept (bless)**: `mv wip/my_test.stderr tests/compiler/function/example/` +5. **Add to suite**: Edit `tests/trybuild.rs`, add `t.compile_fail("tests/.../my_test.rs")` +6. **Commit both files**: `.rs` and `.stderr` files together + +### Important: Commit .stderr Files + +**Always commit `.stderr` files** - they define expected error messages and enable regression detection. + +### Update Error Messages + +```bash +TRYBUILD=overwrite cargo test --test trybuild +git diff tests/ # Review changes +``` + +## Commands + +```bash +cargo test # All tests +cargo test --test trybuild # Trybuild only +cargo test --test trybuild compiler_function_example # Specific test +``` + +Note: `trybuild` tests do not show up in code coverage reports. + +## Reference + +- [trybuild docs](https://docs.rs/trybuild/) +- [Rust testing guide](https://doc.rust-lang.org/book/ch11-00-testing.html) diff --git a/tests/compiler/function/example/duplicate_result.rs b/tests/compiler/function/example/duplicate_result.rs new file mode 100644 index 0000000000..ae3371651c --- /dev/null +++ b/tests/compiler/function/example/duplicate_result.rs @@ -0,0 +1,10 @@ +use vrl::example; + +fn main() { + let _ex = example! { + title: "test", + source: "code", + result: Ok("output"), + result: Err("duplicate"), + }; +} diff --git a/tests/compiler/function/example/duplicate_result.stderr b/tests/compiler/function/example/duplicate_result.stderr new file mode 100644 index 0000000000..92c8e7e535 --- /dev/null +++ b/tests/compiler/function/example/duplicate_result.stderr @@ -0,0 +1,13 @@ +error: duplicate 'result' field in example! macro + --> tests/compiler/function/example/duplicate_result.rs:4:15 + | +4 | let _ex = example! { + | _______________^ +5 | | title: "test", +6 | | source: "code", +7 | | result: Ok("output"), +8 | | result: Err("duplicate"), +9 | | }; + | |_____^ + | + = note: this error originates in the macro `$crate::example` which comes from the expansion of the macro `example` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/compiler/function/example/duplicate_source.rs b/tests/compiler/function/example/duplicate_source.rs new file mode 100644 index 0000000000..329503a1c2 --- /dev/null +++ b/tests/compiler/function/example/duplicate_source.rs @@ -0,0 +1,10 @@ +use vrl::example; + +fn main() { + let _ex = example! { + title: "test", + source: "code", + result: Ok("output"), + source: "duplicate", + }; +} diff --git a/tests/compiler/function/example/duplicate_source.stderr b/tests/compiler/function/example/duplicate_source.stderr new file mode 100644 index 0000000000..a62bcdabe0 --- /dev/null +++ b/tests/compiler/function/example/duplicate_source.stderr @@ -0,0 +1,13 @@ +error: duplicate 'source' field in example! macro + --> tests/compiler/function/example/duplicate_source.rs:4:15 + | +4 | let _ex = example! { + | _______________^ +5 | | title: "test", +6 | | source: "code", +7 | | result: Ok("output"), +8 | | source: "duplicate", +9 | | }; + | |_____^ + | + = note: this error originates in the macro `$crate::example` which comes from the expansion of the macro `example` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/compiler/function/example/duplicate_title.rs b/tests/compiler/function/example/duplicate_title.rs new file mode 100644 index 0000000000..910c8de49c --- /dev/null +++ b/tests/compiler/function/example/duplicate_title.rs @@ -0,0 +1,10 @@ +use vrl::example; + +fn main() { + let _ex = example! { + title: "test", + source: "code", + result: Ok("output"), + title: "duplicate", + }; +} diff --git a/tests/compiler/function/example/duplicate_title.stderr b/tests/compiler/function/example/duplicate_title.stderr new file mode 100644 index 0000000000..11fd7abab6 --- /dev/null +++ b/tests/compiler/function/example/duplicate_title.stderr @@ -0,0 +1,13 @@ +error: duplicate 'title' field in example! macro + --> tests/compiler/function/example/duplicate_title.rs:4:15 + | +4 | let _ex = example! { + | _______________^ +5 | | title: "test", +6 | | source: "code", +7 | | result: Ok("output"), +8 | | title: "duplicate", +9 | | }; + | |_____^ + | + = note: this error originates in the macro `$crate::example` which comes from the expansion of the macro `example` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/compiler/function/example/missing_result.rs b/tests/compiler/function/example/missing_result.rs new file mode 100644 index 0000000000..48935f1235 --- /dev/null +++ b/tests/compiler/function/example/missing_result.rs @@ -0,0 +1,8 @@ +use vrl::example; + +fn main() { + let _ex = example! { + title: "test", + source: "code", + }; +} diff --git a/tests/compiler/function/example/missing_result.stderr b/tests/compiler/function/example/missing_result.stderr new file mode 100644 index 0000000000..ec3c48c884 --- /dev/null +++ b/tests/compiler/function/example/missing_result.stderr @@ -0,0 +1,16 @@ +error: no rules expected `]` + --> tests/compiler/function/example/missing_result.rs:4:15 + | +4 | let _ex = example! { + | _______________^ +5 | | title: "test", +6 | | source: "code", +7 | | }; + | |_____^ no rules expected this token in macro call + | +note: while trying to match `title` + --> src/compiler/function.rs + | + | (@internal [$title:expr] [$($source:tt)*] [$($result:tt)*] [title: $t:expr, $($rest:tt)*]) => { + | ^^^^^ + = note: this error originates in the macro `$crate::example` which comes from the expansion of the macro `example` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/compiler/function/example/missing_source.rs b/tests/compiler/function/example/missing_source.rs new file mode 100644 index 0000000000..a555d79cbc --- /dev/null +++ b/tests/compiler/function/example/missing_source.rs @@ -0,0 +1,8 @@ +use vrl::example; + +fn main() { + let _ex = example! { + title: "test", + result: Ok("output"), + }; +} diff --git a/tests/compiler/function/example/missing_source.stderr b/tests/compiler/function/example/missing_source.stderr new file mode 100644 index 0000000000..cc6ee25286 --- /dev/null +++ b/tests/compiler/function/example/missing_source.stderr @@ -0,0 +1,16 @@ +error: no rules expected `]` + --> tests/compiler/function/example/missing_source.rs:4:15 + | +4 | let _ex = example! { + | _______________^ +5 | | title: "test", +6 | | result: Ok("output"), +7 | | }; + | |_____^ no rules expected this token in macro call + | +note: while trying to match `title` + --> src/compiler/function.rs + | + | (@internal [$title:expr] [$($source:tt)*] [$($result:tt)*] [title: $t:expr, $($rest:tt)*]) => { + | ^^^^^ + = note: this error originates in the macro `$crate::example` which comes from the expansion of the macro `example` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/compiler/function/example/missing_title.rs b/tests/compiler/function/example/missing_title.rs new file mode 100644 index 0000000000..eae56253dc --- /dev/null +++ b/tests/compiler/function/example/missing_title.rs @@ -0,0 +1,8 @@ +use vrl::example; + +fn main() { + let _ex = example! { + source: "code", + result: Ok("output"), + }; +} diff --git a/tests/compiler/function/example/missing_title.stderr b/tests/compiler/function/example/missing_title.stderr new file mode 100644 index 0000000000..0bb8b05d07 --- /dev/null +++ b/tests/compiler/function/example/missing_title.stderr @@ -0,0 +1,16 @@ +error: no rules expected `]` + --> tests/compiler/function/example/missing_title.rs:4:15 + | +4 | let _ex = example! { + | _______________^ +5 | | source: "code", +6 | | result: Ok("output"), +7 | | }; + | |_____^ no rules expected this token in macro call + | +note: while trying to match `source` + --> src/compiler/function.rs + | + | (@internal [$($title:tt)*] [$source:expr] [$($result:tt)*] [source: $s:expr, $($rest:tt)*]) => { + | ^^^^^^ + = note: this error originates in the macro `$crate::example` which comes from the expansion of the macro `example` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/compiler/function/example/pass.rs b/tests/compiler/function/example/pass.rs new file mode 100644 index 0000000000..4cc927de3a --- /dev/null +++ b/tests/compiler/function/example/pass.rs @@ -0,0 +1,9 @@ +use vrl::example; + +fn main() { + let _ex = example! { + title: "test", + source: "code", + result: Ok("output"), + }; +} diff --git a/tests/compiler/function/example/unknown_field.rs b/tests/compiler/function/example/unknown_field.rs new file mode 100644 index 0000000000..a4b7f33113 --- /dev/null +++ b/tests/compiler/function/example/unknown_field.rs @@ -0,0 +1,10 @@ +use vrl::example; + +fn main() { + let _ex = example! { + title: "test", + source: "code", + result: Ok("output"), + unknown_field: "value", + }; +} diff --git a/tests/compiler/function/example/unknown_field.stderr b/tests/compiler/function/example/unknown_field.stderr new file mode 100644 index 0000000000..8f33b2e358 --- /dev/null +++ b/tests/compiler/function/example/unknown_field.stderr @@ -0,0 +1,18 @@ +error: no rules expected identifier `unknown_field` + --> tests/compiler/function/example/unknown_field.rs:4:15 + | +4 | let _ex = example! { + | _______________^ +5 | | title: "test", +6 | | source: "code", +7 | | result: Ok("output"), +8 | | unknown_field: "value", +9 | | }; + | |_____^ no rules expected this token in macro call + | +note: while trying to match `title` + --> src/compiler/function.rs + | + | (@internal [$title:expr] [$($source:tt)*] [$($result:tt)*] [title: $t:expr, $($rest:tt)*]) => { + | ^^^^^ + = note: this error originates in the macro `example` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/trybuild.rs b/tests/trybuild.rs new file mode 100644 index 0000000000..5a32f5ab86 --- /dev/null +++ b/tests/trybuild.rs @@ -0,0 +1,53 @@ +//! Compile-time tests using trybuild. +//! +//! These tests verify that macros and other compile-time constructs correctly +//! reject invalid usage with appropriate error messages. +//! +//! # Organization +//! +//! Test files are organized to mirror the source code structure: +//! - `src/compiler/function.rs` → `tests/compiler/function/*/` +//! - `src/parser/foo.rs` → `tests/parser/foo/*/` +//! +//! # Adding New Tests +//! +//! 1. Create test files in the appropriate directory matching the source structure +//! 2. Add a new test function following the naming pattern: `{module}_{submodule}_{feature}` +//! 3. Use `t.pass()` for tests that should compile successfully +//! 4. Use `t.compile_fail()` for tests that should fail with specific error messages + +/// Tests for the example! macro defined in src/compiler/function.rs +/// +/// The example! macro accepts fields in any order and validates: +/// - All required fields are present (title, source, result) +/// - No duplicate fields +/// - No unknown fields +#[test] +fn compiler_function_example() { + let t = trybuild::TestCases::new(); + + // Valid usage + t.pass("tests/compiler/function/example/pass.rs"); + + // Duplicate field errors + t.compile_fail("tests/compiler/function/example/duplicate_title.rs"); + t.compile_fail("tests/compiler/function/example/duplicate_source.rs"); + t.compile_fail("tests/compiler/function/example/duplicate_result.rs"); + + // Missing field errors + t.compile_fail("tests/compiler/function/example/missing_title.rs"); + t.compile_fail("tests/compiler/function/example/missing_source.rs"); + t.compile_fail("tests/compiler/function/example/missing_result.rs"); + + // Unknown field errors + t.compile_fail("tests/compiler/function/example/unknown_field.rs"); +} + +// Add more test functions here as needed: +// +// #[test] +// fn parser_something() { +// let t = trybuild::TestCases::new(); +// t.pass("tests/parser/something/pass.rs"); +// t.compile_fail("tests/parser/something/fail.rs"); +// }