wowlab_tidy/languages/rust/rules/tests/
gtest_required.rs1use ra_ap_syntax::{
2 AstNode,
3 ast::{self, HasAttrs},
4};
5
6use crate::{AstCtx, Example, Violation};
7
8#[rustfmt::skip]
9const EXAMPLES: &[Example] = &[
10 Example { label: "gtest", code: "#[gtest]\nfn works() {}", pass: true },
11 Example { label: "plain test", code: "#[test]\nfn works() {}", pass: false },
12 Example { label: "gtest before tokio", code: "#[gtest]\n#[tokio::test]\nasync fn works() {}", pass: true },
13 Example { label: "tokio without gtest", code: "#[tokio::test]\nasync fn works() {}", pass: false },
14 Example { label: "ordinary function", code: "fn works() {}", pass: true },
15];
16
17crate::ast_rule!(
18 gtest_required,
19 "Require every native Rust test to use the googletest test attribute.",
20 "A single test framework keeps matcher behavior and failure reporting consistent.",
21 Medium,
22);
23
24fn check_gtest_required(ctx: &AstCtx<'_>) -> Vec<Violation> {
25 ctx.nodes::<ast::Fn>()
26 .filter(|function| {
27 let attrs: Vec<String> = function
28 .attrs()
29 .map(|attr| attr.syntax().text().to_string())
30 .collect();
31 let native_test = attrs
32 .iter()
33 .any(|attr| attr == "#[test]" || attr == "#[tokio::test]");
34
35 native_test && !attrs.iter().any(|attr| attr == "#[gtest]")
36 })
37 .map(|function| ctx.violation(&function, "native test function must carry `#[gtest]`"))
38 .collect()
39}
40
41crate::tidy_ast_test!(check_gtest_required, {
42 crate::example_tests!(EXAMPLES, check_gtest_required);
43});