Skip to content

Commit 586ccc1

Browse files
mbyxtgross35
authored andcommitted
ctest: improve documentation and remove some unused items.
1 parent 192bccb commit 586ccc1

20 files changed

+90
-82
lines changed

ctest/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ publish = true
1010
[dependencies]
1111
askama = "0.14.0"
1212
cc = "1.2.29"
13-
proc-macro2 = { version = "1.0.95", features = ["span-locations"] }
13+
proc-macro2 = { version = "1.0.101", features = ["span-locations"] }
1414
quote = "1.0.40"
1515
syn = { version = "2.0.104", features = ["full", "visit", "extra-traits"] }
1616
thiserror = "2.0.12"

ctest/README.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ APIs in Rust match the APIs defined in C.
1010

1111
## MSRV (Minimum Supported Rust Version)
1212

13-
The MSRV is 1.63.0 because of the transitive dependencies.
13+
The MSRV is 1.88.0 because of the transitive dependencies.
1414
Note that MSRV may be changed anytime by dependencies.
1515

1616
## Example
@@ -34,7 +34,7 @@ mylib-sys = { path = "../mylib-sys" }
3434
libc = "0.2"
3535

3636
[build-dependencies]
37-
ctest = "0.4"
37+
ctest = "0.5.0-beta.0"
3838
```
3939

4040
Next, add a build script to `systest/build.rs`:
@@ -52,7 +52,7 @@ fn main() {
5252

5353
// Generate the tests, passing the path to the `*-sys` library as well as
5454
// the module to generate.
55-
cfg.generate("../mylib-sys/lib.rs", "all.rs");
55+
ctest::generate_test(&mut cfg, "../mylib-sys/lib.rs", "all.rs");
5656
}
5757
```
5858

@@ -72,10 +72,10 @@ directory, and everything should be kicked into action!
7272

7373
## How it works
7474

75-
This library will parse the `*-sys` crate to learn about all extern fn
76-
definitions within. It will then generate a test suite to ensure that all
77-
function function signatures, constant values, struct layout/alignment, type
78-
size/alignment, etc, all match their C equivalent.
75+
This library will parse the `*-sys` crate to learn about all definitions within.
76+
It will then generate a test suite to ensure that all function signatures,
77+
constant values, struct layout/alignment, type size/alignment, etc,
78+
all match their C equivalent.
7979

8080
The generated tests come in two forms. One is a Rust file which contains the
8181
`main` function (hence the `include!` above), and another is a C file which is
@@ -101,6 +101,14 @@ This project is licensed under either of
101101

102102
at your option.
103103

104+
## Modifying test templates
105+
If you modify the test templates for either Rust or C in any way, then before
106+
contributing you must run the following command to update the pre-generated test
107+
files we check against:
108+
```rust
109+
$ LIBC_BLESS=1 cargo test
110+
```
111+
104112
## Contribution
105113

106114
Unless you explicitly state otherwise, any contribution intentionally submitted

ctest/src/ast/constant.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ pub struct Const {
66
pub(crate) public: bool,
77
pub(crate) ident: BoxStr,
88
pub(crate) ty: syn::Type,
9-
#[expect(unused)]
10-
pub(crate) expr: syn::Expr,
119
}
1210

1311
impl Const {

ctest/src/ast/mod.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,3 @@ impl fmt::Display for Abi {
4848
}
4949
}
5050
}
51-
52-
/// Things that can appear directly inside of a module or scope.
53-
///
54-
/// This is not an exhaustive list and only contains variants directly useful
55-
/// for our purposes.
56-
#[derive(Debug, Clone)]
57-
#[expect(unused)]
58-
pub(crate) enum Item {
59-
/// Represents a constant defined in Rust.
60-
Const(Const),
61-
/// Represents a function defined in Rust.
62-
Fn(Box<Fn>),
63-
/// Represents a static variable defined in Rust.
64-
Static(Static),
65-
/// Represents a type alias defined in Rust.
66-
Type(Type),
67-
/// Represents a struct defined in Rust.
68-
Struct(Struct),
69-
/// Represents a union defined in Rust.
70-
Union(Union),
71-
}

ctest/src/cdecl.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
33
use std::fmt::Write;
44

5-
type BoxStr = Box<str>;
6-
5+
/// The constness of a C type.
76
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
87
pub(crate) enum Constness {
98
Const,
@@ -13,6 +12,8 @@ pub(crate) enum Constness {
1312
#[cfg_attr(not(test), expect(unused_imports))]
1413
use Constness::{Const, Mut};
1514

15+
use crate::BoxStr;
16+
1617
/// A basic representation of C's types.
1718
#[derive(Clone, Debug)]
1819
pub(crate) enum CTy {
@@ -175,6 +176,7 @@ fn space_if(yes: bool, s: &mut String) {
175176
}
176177
}
177178

179+
/// Create a named type with a certain constness.
178180
pub(crate) fn named(name: &str, constness: Constness) -> CTy {
179181
CTy::Named {
180182
name: name.into(),
@@ -186,6 +188,7 @@ pub(crate) fn named(name: &str, constness: Constness) -> CTy {
186188
}
187189
}
188190

191+
/// Create a named type with certain qualifiers.
189192
#[cfg_attr(not(test), expect(unused))]
190193
pub(crate) fn named_qual(name: &str, qual: Qual) -> CTy {
191194
CTy::Named {
@@ -194,6 +197,7 @@ pub(crate) fn named_qual(name: &str, qual: Qual) -> CTy {
194197
}
195198
}
196199

200+
/// Create a pointer to a type, specifying constness of the pointer.
197201
pub(crate) fn ptr(inner: CTy, constness: Constness) -> CTy {
198202
ptr_qual(
199203
inner,
@@ -205,21 +209,23 @@ pub(crate) fn ptr(inner: CTy, constness: Constness) -> CTy {
205209
)
206210
}
207211

212+
/// Create a pointer to a type, specifying the qualifiers of the pointer.
208213
pub(crate) fn ptr_qual(inner: CTy, qual: Qual) -> CTy {
209214
CTy::Ptr {
210215
ty: Box::new(inner),
211216
qual,
212217
}
213218
}
214219

220+
/// Create an array of some type and optional length.
215221
pub(crate) fn array(inner: CTy, len: Option<&str>) -> CTy {
216222
CTy::Array {
217223
ty: Box::new(inner),
218224
len: len.map(Into::into),
219225
}
220226
}
221227

222-
/// Function type (not a pointer)
228+
/// Create a function type (not a pointer) with the given arguments and return type.
223229
#[cfg_attr(not(test), expect(unused))]
224230
pub(crate) fn func(args: Vec<CTy>, ret: CTy) -> CTy {
225231
CTy::Fn {
@@ -228,7 +234,9 @@ pub(crate) fn func(args: Vec<CTy>, ret: CTy) -> CTy {
228234
}
229235
}
230236

231-
/// Function pointer
237+
/// Create a function pointer with the given arguments and return type.
238+
///
239+
/// By default the function pointer is mutable, with `volatile` and `restrict` keywords not applied.
232240
pub(crate) fn func_ptr(args: Vec<CTy>, ret: CTy) -> CTy {
233241
CTy::Ptr {
234242
ty: Box::new(CTy::Fn {

ctest/src/ffi_items.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Conversion of Rust code to a simplified abstract syntax tree.
2+
13
use std::ops::Deref;
24

35
use syn::punctuated::Punctuated;
@@ -208,14 +210,8 @@ impl<'ast> Visit<'ast> for FfiItems {
208210
let public = is_visible(&i.vis);
209211
let ident = i.ident.to_string().into_boxed_str();
210212
let ty = i.ty.deref().clone();
211-
let expr = i.expr.deref().clone();
212213

213-
self.constants.push(Const {
214-
public,
215-
ident,
216-
ty,
217-
expr,
218-
});
214+
self.constants.push(Const { public, ident, ty });
219215
}
220216

221217
fn visit_item_foreign_mod(&mut self, i: &'ast syn::ItemForeignMod) {

ctest/src/generator.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Configuration of the test generator.
2+
13
use std::env;
24
use std::fs::File;
35
use std::io::Write;
@@ -15,8 +17,8 @@ use crate::{
1517
VolatileItemKind, expand,
1618
};
1719

18-
/// A function that takes a mappable input and returns its mapping as Some, otherwise
19-
/// use the default name if None.
20+
/// A function that takes a mappable input and returns its mapping as `Some`, otherwise
21+
/// use the default name if `None`.
2022
type MappedName = Box<dyn Fn(&MapInput) -> Option<String>>;
2123
/// A function that determines whether to skip an item or not.
2224
type Skip = Box<dyn Fn(&MapInput) -> bool>;
@@ -52,16 +54,22 @@ pub struct TestGenerator {
5254
pub(crate) skip_fn_ptrcheck: Option<SkipTest>,
5355
}
5456

57+
/// An error that occurs when generating the test files.
5558
#[derive(Debug, Error)]
5659
pub enum GenerationError {
60+
/// An error that occurs when `rustc -Zunpretty=expand` fails to expand the crate.
5761
#[error("unable to expand crate {0}: {1}")]
5862
MacroExpansion(PathBuf, String),
63+
/// An error that occurs when `syn` is unable to parse the expanded crate due to invalid syntax.
5964
#[error("unable to parse expanded crate {0}: {1}")]
6065
RustSyntax(String, String),
66+
/// An error that occurs when the Rust to C translation fails.
6167
#[error("unable to prepare template input: {0}")]
6268
Translation(#[from] TranslationError),
69+
/// An error that occurs when there are errors in the Rust side of the test template.
6370
#[error("unable to render Rust template: {0}")]
6471
RustTemplateRender(askama::Error),
72+
/// An error that occurs when there are errors in the C side of the test template.
6573
#[error("unable to render C template: {0}")]
6674
CTemplateRender(askama::Error),
6775
#[error("unable to create or write template file: {0}")]
@@ -78,7 +86,7 @@ impl TestGenerator {
7886

7987
/// Add a header to be included as part of the generated C file.
8088
///
81-
/// The generate C test will be compiled by a C compiler, and this can be
89+
/// The generated C test will be compiled by a C compiler, and this can be
8290
/// used to ensure that all the necessary header files are included to test
8391
/// all FFI definitions.
8492
///

ctest/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![warn(unreachable_pub)]
33
#![warn(missing_debug_implementations)]
44

5-
//! # ctest2 - an FFI binding validator
5+
//! # ctest - an FFI binding validator
66
//!
77
//! This library is intended to be used as a build dependency in a separate
88
//! project from the main repo to generate tests which can be used to validate
@@ -33,6 +33,9 @@ pub type Result<T, E = Error> = std::result::Result<T, E>;
3333
/// A boxed string for representing identifiers.
3434
type BoxStr = Box<str>;
3535

36+
/// The edition used by rustc when expanding macros and compiling tests.
37+
pub(crate) const EDITION: &str = "2021";
38+
3639
/// A kind of item to which the C volatile qualifier could apply.
3740
///
3841
/// This is necessary because `ctest` does not parse the header file, so it

ctest/src/macro_expansion.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::fs::canonicalize;
33
use std::path::Path;
44
use std::process::Command;
55

6-
use crate::Result;
6+
use crate::{EDITION, Result};
77

88
/// Use rustc to expand all macros and pretty print the crate into a single file.
99
pub fn expand<P: AsRef<Path>>(crate_path: P, cfg: &[(String, Option<String>)]) -> Result<String> {
@@ -13,7 +13,7 @@ pub fn expand<P: AsRef<Path>>(crate_path: P, cfg: &[(String, Option<String>)]) -
1313
cmd.env("RUSTC_BOOTSTRAP", "1")
1414
.arg("-Zunpretty=expanded")
1515
.arg("--edition")
16-
.arg("2021") // By default, -Zunpretty=expanded uses 2015 edition.
16+
.arg(EDITION) // By default, -Zunpretty=expanded uses 2015 edition.
1717
.arg(canonicalize(crate_path)?);
1818

1919
// `libc` uses non standard cfg flags as well, which have to be manually expanded.

ctest/src/runner.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
//! Generation, compilation, and running of tests.
2+
13
use std::env;
24
use std::fs::{File, canonicalize};
35
use std::io::Write;
46
use std::path::{Path, PathBuf};
57
use std::process::Command;
68

79
use crate::generator::GenerationError;
8-
use crate::{Result, TestGenerator};
10+
use crate::{EDITION, Result, TestGenerator};
911

1012
/// Generate all tests for the given crate and output the Rust side to a file.
1113
#[doc(hidden)]
@@ -122,10 +124,9 @@ pub fn __compile_test(
122124
.arg(format!("-Lnative={}", output_dir.display()))
123125
.arg(format!("-lstatic={}", library_file.to_str().unwrap()))
124126
.arg("--edition")
125-
.arg("2021") // Defaults to 2015.
127+
.arg(EDITION) // Defaults to 2015.
126128
.arg("-o")
127-
.arg(&binary_path)
128-
.arg("-Aunused");
129+
.arg(&binary_path);
129130

130131
// Pass in a different target, linker or flags if set, useful for cross compilation.
131132

0 commit comments

Comments
 (0)