Skip to content

Commit 66444e4

Browse files
committed
add test for --exclude-pattern precedence; warn if --exclude pattern overrides an --include
1 parent cfb22cd commit 66444e4

File tree

4 files changed

+169
-0
lines changed

4 files changed

+169
-0
lines changed

kani-driver/src/autoharness/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::list::collect_metadata::process_metadata;
1414
use crate::list::output::output_list_results;
1515
use crate::project::{Project, standalone_project, std_project};
1616
use crate::session::KaniSession;
17+
use crate::util::warning;
1718
use crate::{InvocationType, print_kani_version, project, verify_project};
1819
use anyhow::Result;
1920
use comfy_table::Table as PrettyTable;
@@ -162,6 +163,21 @@ impl KaniSession {
162163

163164
/// Add the compiler arguments specific to the `autoharness` subcommand.
164165
pub fn add_auto_harness_args(&mut self, included: &[String], excluded: &[String]) {
166+
for include_pattern in included {
167+
for exclude_pattern in excluded {
168+
// Check if include pattern contains exclude pattern
169+
// This catches cases like include="foo::bar" exclude="bar" or include="foo" exclude="foo"
170+
if include_pattern.contains(exclude_pattern) {
171+
warning(&format!(
172+
"Include pattern '{}' contains exclude pattern '{}'. \
173+
This combination will never match any functions since all functions matching \
174+
the include pattern will also match the exclude pattern, and the exclude pattern takes precedence.",
175+
include_pattern, exclude_pattern
176+
));
177+
}
178+
}
179+
}
180+
165181
let mut args = vec![];
166182
for pattern in included {
167183
args.push(format!("--autoharness-include-pattern {}", pattern));
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Copyright Kani Contributors
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
script: precedence.sh
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Copyright Kani Contributors
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
# Test that --include-pattern and --exclude-pattern work as expected when provided together.
5+
6+
set -e
7+
8+
# Define all function paths
9+
FUNCTIONS=(
10+
"foo::foo_function"
11+
"foo::bar::bar_function"
12+
"foo::bar::foo_bar_function"
13+
"foo::baz::foo_baz_function"
14+
"other::regular_function"
15+
"other::with_bar_name"
16+
"foo_top_level"
17+
"bar_top_level"
18+
)
19+
20+
# Check if a function appears in the "Selected Function" table
21+
check_selected() {
22+
local output="$1"
23+
local function_name="$2"
24+
if echo "$output" | grep -q "| $function_name *|"; then
25+
return 0
26+
else
27+
return 1
28+
fi
29+
}
30+
31+
# Check if a function appears in the "Skipped Function" table
32+
check_skipped() {
33+
local output="$1"
34+
local function_name="$2"
35+
if echo "$output" | grep -q "| $function_name *|.*Did not match provided filters"; then
36+
return 0
37+
else
38+
return 1
39+
fi
40+
}
41+
42+
# Check that the warning message gets printed for the patterns that are mutually exclusive (no functions get selected)
43+
check_warning() {
44+
local output="$1"
45+
local should_warn="$2"
46+
local warning_present=$(echo "$output" | grep -c "warning: Include pattern" || true)
47+
48+
if [ "$should_warn" = true ] && [ "$warning_present" -eq 0 ]; then
49+
echo "ERROR: expected printed warning about conflicting --include-pattern and --exclude-pattern flags"
50+
return 1
51+
elif [ "$should_warn" = false ] && [ "$warning_present" -gt 0 ]; then
52+
echo "ERROR: Got unexpected warning message"
53+
return 1
54+
fi
55+
return 0
56+
}
57+
58+
59+
# Helper function to verify functions against include/exclude patterns
60+
verify_functions() {
61+
local output="$1"
62+
local include_pattern="$2"
63+
local exclude_pattern="$3"
64+
65+
for func in "${FUNCTIONS[@]}"; do
66+
# If the function name matches the include pattern and not the exclude pattern, it should be selected
67+
if echo "$func" | grep -q "$include_pattern" && ! echo "$func" | grep -q "$exclude_pattern"; then
68+
if ! check_selected "$output" "$func"; then
69+
echo "ERROR: Expected $func to be selected"
70+
exit 1
71+
fi
72+
# Otherwise, it should be skipped
73+
else
74+
if ! check_skipped "$output" "$func"; then
75+
echo "ERROR: Expected $func to be skipped"
76+
exit 1
77+
fi
78+
fi
79+
done
80+
}
81+
82+
# Test cases
83+
test_cases=(
84+
"include 'foo' exclude 'foo::bar'"
85+
"include 'foo' exclude 'bar'"
86+
"include 'foo::bar' exclude 'bar'"
87+
"include 'foo' exclude 'foo'"
88+
)
89+
90+
include_patterns=(
91+
"foo"
92+
"foo"
93+
"foo::bar"
94+
"foo"
95+
)
96+
97+
exclude_patterns=(
98+
"foo::bar"
99+
"bar"
100+
"bar"
101+
"foo"
102+
)
103+
104+
# Whether each test case should produce a warning about no functions being selected
105+
should_warn=(
106+
false
107+
false
108+
true
109+
true
110+
)
111+
112+
for i in "${!test_cases[@]}"; do
113+
echo "Testing: ${test_cases[$i]}"
114+
output=$(kani autoharness -Z autoharness src/lib.rs --include-pattern "${include_patterns[$i]}" --exclude-pattern "${exclude_patterns[$i]}" --only-codegen)
115+
echo "$output"
116+
117+
if ! check_warning "$output" "${should_warn[$i]}"; then
118+
exit 1
119+
fi
120+
121+
verify_functions "$output" "${include_patterns[$i]}" "${exclude_patterns[$i]}"
122+
done
123+
124+
echo "All tests passed!"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
mod foo {
5+
fn foo_function() {}
6+
7+
mod bar {
8+
fn bar_function() {}
9+
10+
fn foo_bar_function() {}
11+
}
12+
13+
mod baz {
14+
fn foo_baz_function() {}
15+
}
16+
}
17+
18+
mod other {
19+
fn regular_function() {}
20+
21+
fn with_bar_name() {}
22+
}
23+
24+
fn foo_top_level() {}
25+
26+
fn bar_top_level() {}

0 commit comments

Comments
 (0)