Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions COVERAGE.md
Original file line number Diff line number Diff line change
@@ -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)
84 changes: 77 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
4 changes: 2 additions & 2 deletions scripts/check_deny.sh
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
88 changes: 87 additions & 1 deletion src/compiler/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)*])
Expand Down Expand Up @@ -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"));
}
}
2 changes: 1 addition & 1 deletion src/stdlib/parse_klog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}"#}),
}]
}
Expand Down
2 changes: 1 addition & 1 deletion src/stdlib/parse_linux_authorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}"#}),
}]
}
Expand Down
11 changes: 8 additions & 3 deletions src/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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}", &current_year)
}

fn compare_partial_diagnostic(got: &str, want: &str) -> bool {
got.lines()
.filter(|line| line.trim().starts_with("error[E"))
Expand Down
Loading
Loading