Skip to content

Commit dcb2fb0

Browse files
committed
add tests for style checking script implementation
1 parent ecc0722 commit dcb2fb0

File tree

5 files changed

+244
-66
lines changed

5 files changed

+244
-66
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ target
22
Cargo.lock
33
*~
44
style
5+
!style/

libc-test/Cargo.toml

+6-1
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,10 @@ harness = true
9898

9999
[[test]]
100100
name = "style"
101-
path = "test/style.rs"
101+
path = "test/check_style.rs"
102+
harness = true
103+
104+
[[test]]
105+
name = "style_tests"
106+
path = "test/style_tests.rs"
102107
harness = true

libc-test/test/check_style.rs

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//! Simple script to verify the coding style of this library
2+
//!
3+
//! ## How to run
4+
//!
5+
//! The first argument to this script is the directory to run on, so running
6+
//! this script should be as simple as:
7+
//!
8+
//! ```notrust
9+
//! cargo test --test style
10+
//! ```
11+
//!
12+
//! ## Guidelines
13+
//!
14+
//! The current style is:
15+
//!
16+
//! * Specific module layout:
17+
//! 1. use directives
18+
//! 2. typedefs
19+
//! 3. structs
20+
//! 4. constants
21+
//! 5. f! { ... } functions
22+
//! 6. extern functions
23+
//! 7. modules + pub use
24+
25+
mod style;
26+
27+
use std::env;
28+
use std::path::Path;
29+
30+
use style::{Result, StyleChecker};
31+
32+
#[test]
33+
fn check_style() {
34+
let root_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../src");
35+
walk(&root_dir).unwrap();
36+
eprintln!("good style!");
37+
}
38+
39+
fn walk(root_dir: &Path) -> Result<()> {
40+
let mut style_checker = StyleChecker::new();
41+
42+
for entry in glob::glob(&format!(
43+
"{}/**/*.rs",
44+
root_dir.to_str().expect("dir should be valid UTF-8")
45+
))? {
46+
let entry = entry?;
47+
48+
let name = entry
49+
.file_name()
50+
.expect("file name should not end in ..")
51+
.to_str()
52+
.expect("file name should be valid UTF-8");
53+
if let "lib.rs" | "macros.rs" = &name[..] {
54+
continue;
55+
}
56+
57+
let path = entry.as_path();
58+
style_checker.check_file(path)?;
59+
style_checker.reset_state();
60+
}
61+
62+
style_checker.finalize()
63+
}

libc-test/test/style.rs renamed to libc-test/test/style/mod.rs

+17-65
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,24 @@
1-
//! Simple script to verify the coding style of this library
1+
//! Provides the [StyleChecker] visitor to verify the coding style of
2+
//! this library.
23
//!
3-
//! ## How to run
4-
//!
5-
//! The first argument to this script is the directory to run on, so running
6-
//! this script should be as simple as:
7-
//!
8-
//! ```notrust
9-
//! cargo test --test style
10-
//! ```
11-
//!
12-
//! ## Guidelines
13-
//!
14-
//! The current style is:
15-
//!
16-
//! * Specific module layout:
17-
//! 1. use directives
18-
//! 2. typedefs
19-
//! 3. structs
20-
//! 4. constants
21-
//! 5. f! { ... } functions
22-
//! 6. extern functions
23-
//! 7. modules + pub use
4+
//! This is split out so that the implementation itself can be tested
5+
//! separately, see test/check_style.rs for how it's used.
246
257
use std::fmt::Display;
8+
use std::fs;
269
use std::ops::Deref;
2710
use std::path::{Path, PathBuf};
28-
use std::{env, fs};
2911

3012
use syn::parse::{Parse, ParseStream};
3113
use syn::spanned::Spanned;
3214
use syn::visit::{self, Visit};
3315
use syn::Token;
3416

35-
type Error = Box<dyn std::error::Error>;
36-
type Result<T> = std::result::Result<T, Error>;
37-
38-
#[test]
39-
fn check_style() {
40-
let root_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../src");
41-
walk(&root_dir).unwrap();
42-
eprintln!("good style!");
43-
}
44-
45-
fn walk(root_dir: &Path) -> Result<()> {
46-
let mut style_checker = StyleChecker::new();
47-
48-
for entry in glob::glob(&format!(
49-
"{}/**/*.rs",
50-
root_dir.to_str().expect("dir should be valid UTF-8")
51-
))? {
52-
let entry = entry?;
53-
54-
let name = entry
55-
.file_name()
56-
.expect("file name should not end in ..")
57-
.to_str()
58-
.expect("file name should be valid UTF-8");
59-
if let "lib.rs" | "macros.rs" = &name[..] {
60-
continue;
61-
}
62-
63-
let path = entry.as_path();
64-
style_checker.check_file(path)?;
65-
style_checker.reset_state();
66-
}
67-
68-
style_checker.finalize()
69-
}
17+
pub type Error = Box<dyn std::error::Error>;
18+
pub type Result<T> = std::result::Result<T, Error>;
7019

7120
#[derive(Default)]
72-
struct StyleChecker {
21+
pub struct StyleChecker {
7322
state: State,
7423
// FIXME: see StyleChecker::set_state
7524
_s_macros: usize,
@@ -106,32 +55,35 @@ enum ExprCfgElse {
10655
}
10756

10857
impl StyleChecker {
109-
fn new() -> Self {
58+
pub fn new() -> Self {
11059
Self::default()
11160
}
11261

11362
/// Reads and parses the file at the given path and checks
11463
/// for any style violations.
115-
fn check_file(&mut self, path: &Path) -> Result<()> {
64+
pub fn check_file(&mut self, path: &Path) -> Result<()> {
11665
let contents = fs::read_to_string(path)?;
117-
let file = syn::parse_file(&contents)?;
11866

11967
self.path = PathBuf::from(path);
120-
self.visit_file(&file);
68+
self.check_string(contents)
69+
}
12170

71+
pub fn check_string(&mut self, contents: String) -> Result<()> {
72+
let file = syn::parse_file(&contents)?;
73+
self.visit_file(&file);
12274
Ok(())
12375
}
12476

12577
/// Resets the state of the [StyleChecker].
126-
fn reset_state(&mut self) {
78+
pub fn reset_state(&mut self) {
12779
*self = Self {
12880
errors: std::mem::take(&mut self.errors),
12981
..Self::default()
13082
};
13183
}
13284

13385
/// Collect all errors into a single error, reporting them if any.
134-
fn finalize(self) -> Result<()> {
86+
pub fn finalize(self) -> Result<()> {
13587
if self.errors.is_empty() {
13688
return Ok(());
13789
}

libc-test/test/style_tests.rs

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
//! Verifies the implementation of the style checker in [style]
2+
3+
use style::StyleChecker;
4+
5+
mod style;
6+
7+
#[test]
8+
fn correct_module_layout() {
9+
let contents = r#"
10+
use core::mem::size_of;
11+
pub type foo_t = u32;
12+
struct Foo {}
13+
pub const FOO: u32 = 0x20000;
14+
f! {}
15+
extern "C" {}
16+
mod foolib;
17+
pub use self::foolib::*;
18+
"#
19+
.to_string();
20+
21+
let mut checker = StyleChecker::new();
22+
checker.check_string(contents).unwrap();
23+
checker.finalize().unwrap();
24+
}
25+
26+
#[test]
27+
fn incorrect_module_layout() {
28+
let contents = r#"
29+
use core::mem::size_of;
30+
pub type foo_t = u32;
31+
struct Foo {}
32+
pub const FOO: u32 = 0x20000;
33+
extern "C" {}
34+
f! {}
35+
mod foolib;
36+
pub use self::foolib::*;
37+
"#
38+
.to_string();
39+
40+
let mut checker = StyleChecker::new();
41+
checker.check_string(contents).unwrap();
42+
assert!(checker.finalize().is_err());
43+
}
44+
45+
#[test]
46+
fn incorrect_cfg_if_layout() {
47+
let contents = r#"
48+
cfg_if! {
49+
if #[cfg(foo)] {
50+
pub type foo_t = u32;
51+
use core::mem::size_of;
52+
}
53+
}
54+
"#
55+
.to_string();
56+
57+
let mut checker = StyleChecker::new();
58+
checker.check_string(contents).unwrap();
59+
assert!(checker.finalize().is_err());
60+
}
61+
62+
#[test]
63+
fn cfg_if_branch_resets_state() {
64+
let contents = r#"
65+
cfg_if! {
66+
if #[cfg(foo)] {
67+
use core::mem::size_of;
68+
pub type foo_t = u32;
69+
} else {
70+
use core::mem::align_of;
71+
}
72+
}
73+
"#
74+
.to_string();
75+
76+
let mut checker = StyleChecker::new();
77+
checker.check_string(contents).unwrap();
78+
checker.finalize().unwrap();
79+
}
80+
81+
#[test]
82+
fn multiple_f_macros() {
83+
let contents = r#"
84+
f! {}
85+
f! {}
86+
"#
87+
.to_string();
88+
89+
let mut checker = StyleChecker::new();
90+
checker.check_string(contents).unwrap();
91+
assert!(checker.finalize().is_err());
92+
}
93+
94+
#[test]
95+
fn cfg_if_over_cfg() {
96+
let contents = r#"
97+
#[cfg(foo)]
98+
pub struct Foo {}
99+
"#
100+
.to_string();
101+
102+
let mut checker = StyleChecker::new();
103+
checker.check_string(contents).unwrap();
104+
assert!(checker.finalize().is_err());
105+
}
106+
107+
#[test]
108+
fn cfg_if_ignore_target_arch() {
109+
let contents = r#"
110+
#[cfg(target_arch = "x86")]
111+
pub struct Foo {}
112+
"#
113+
.to_string();
114+
115+
let mut checker = StyleChecker::new();
116+
checker.check_string(contents).unwrap();
117+
checker.finalize().unwrap();
118+
}
119+
120+
#[test]
121+
fn cfg_if_ignore_target_endian_nested() {
122+
let contents = r#"
123+
#[cfg(all(target_endian = "little"))]
124+
pub struct Foo {}
125+
"#
126+
.to_string();
127+
128+
let mut checker = StyleChecker::new();
129+
checker.check_string(contents).unwrap();
130+
checker.finalize().unwrap();
131+
}
132+
133+
#[test]
134+
fn manual_copy() {
135+
let contents = r#"
136+
#[derive(Copy)]
137+
pub struct Foo {}
138+
"#
139+
.to_string();
140+
141+
let mut checker = StyleChecker::new();
142+
checker.check_string(contents).unwrap();
143+
assert!(checker.finalize().is_err());
144+
}
145+
146+
#[test]
147+
fn manual_clone() {
148+
let contents = r#"
149+
#[derive(Clone)]
150+
pub struct Foo {}
151+
"#
152+
.to_string();
153+
154+
let mut checker = StyleChecker::new();
155+
checker.check_string(contents).unwrap();
156+
assert!(checker.finalize().is_err());
157+
}

0 commit comments

Comments
 (0)