Skip to content

Commit aa5bbcc

Browse files
authored
Merge pull request #4484 from mbyx/ctest_macro_expansion
Add macro expansion and ctest entrypoint.
2 parents 2d96246 + 7b1b6c3 commit aa5bbcc

File tree

11 files changed

+160
-15
lines changed

11 files changed

+160
-15
lines changed

ci/run.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ esac
9595

9696
# garando_errors only compiles on `cfg(any(unix, windows))`
9797
case "$target" in
98-
*wasm*) cmd="$cmd --exclude ctest --exclude ctest-test"
98+
*wasm*) cmd="$cmd --exclude ctest --exclude ctest-test --exclude ctest-next"
9999
esac
100100

101101
# # FIXME(ctest): duplicate symbol errors for statics, e.g. T1_static_mut_u8, on Unix-

ctest-next/src/generator.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::path::Path;
2+
3+
use crate::{expand, Result};
4+
5+
/// A builder used to generate a test suite.
6+
#[non_exhaustive]
7+
pub struct TestGenerator {}
8+
9+
impl Default for TestGenerator {
10+
fn default() -> Self {
11+
Self::new()
12+
}
13+
}
14+
15+
impl TestGenerator {
16+
/// Creates a new blank test generator.
17+
pub fn new() -> Self {
18+
Self {}
19+
}
20+
21+
/// Generate all tests for the given crate and output the Rust side to a file.
22+
pub fn generate<P: AsRef<Path>>(&self, crate_path: P, _output_file_path: P) -> Result<()> {
23+
let _expanded = expand(crate_path)?;
24+
Ok(())
25+
}
26+
}

ctest-next/src/lib.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
pub fn add(left: usize, right: usize) -> usize {
2-
left + right
3-
}
4-
5-
#[cfg(test)]
6-
mod tests {
7-
use super::*;
8-
9-
#[test]
10-
fn it_works() {
11-
let result = add(2, 2);
12-
assert_eq!(result, 4);
13-
}
14-
}
1+
#![warn(missing_docs)]
2+
#![warn(unreachable_pub)]
3+
4+
//! # ctest2 - an FFI binding validator
5+
//!
6+
//! This library is intended to be used as a build dependency in a separate
7+
//! project from the main repo to generate tests which can be used to validate
8+
//! FFI bindings in Rust against the headers from which they come from.
9+
10+
mod generator;
11+
mod macro_expansion;
12+
13+
pub use generator::TestGenerator;
14+
pub use macro_expansion::expand;
15+
16+
/// A possible error that can be encountered in our library.
17+
pub type Error = Box<dyn std::error::Error>;
18+
/// A type alias for `std::result::Result` that defaults to our error type.
19+
pub type Result<T, E = Error> = std::result::Result<T, E>;

ctest-next/src/macro_expansion.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use std::{env, fs::canonicalize, path::Path, process::Command};
2+
3+
use crate::Result;
4+
5+
/// Use rustc to expand all macros and pretty print the crate into a single file.
6+
pub fn expand<P: AsRef<Path>>(crate_path: P) -> Result<String> {
7+
let rustc = env::var("RUSTC").unwrap_or_else(|_| String::from("rustc"));
8+
9+
let output = Command::new(rustc)
10+
.env("RUSTC_BOOTSTRAP", "1")
11+
.arg("-Zunpretty=expanded")
12+
.arg(canonicalize(crate_path)?)
13+
.output()?;
14+
15+
if !output.status.success() {
16+
let error = std::str::from_utf8(&output.stderr)?;
17+
return Err(error.into());
18+
}
19+
20+
let expanded = std::str::from_utf8(&output.stdout)?.to_string();
21+
22+
Ok(expanded)
23+
}

ctest-next/tests/basic.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use ctest_next::TestGenerator;
2+
3+
#[test]
4+
fn test_entrypoint_hierarchy() {
5+
let generator = TestGenerator::new();
6+
7+
generator
8+
.generate("./tests/input/hierarchy/lib.rs", "hierarchy_out.rs")
9+
.unwrap();
10+
}
11+
12+
#[test]
13+
fn test_entrypoint_simple() {
14+
let generator = TestGenerator::new();
15+
16+
generator
17+
.generate("./tests/input/simple.rs", "simple_out.rs")
18+
.unwrap();
19+
}
20+
21+
#[test]
22+
fn test_entrypoint_macro() {
23+
let generator = TestGenerator::new();
24+
25+
generator
26+
.generate("./tests/input/macro.rs", "macro_out.rs")
27+
.unwrap();
28+
}
29+
30+
#[test]
31+
fn test_entrypoint_invalid_syntax() {
32+
let generator = TestGenerator::new();
33+
34+
let fails = generator
35+
.generate("./tests/input/invalid_syntax.rs", "invalid_syntax_out.rs")
36+
.is_err();
37+
38+
assert!(fails)
39+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#[allow(non_camel_case_types)]
2+
pub type in6_addr = u32;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use crate::bar::in6_addr;
2+
use std::os::raw::c_void;
3+
4+
pub const ON: bool = true;
5+
6+
unsafe extern "C" {
7+
fn malloc(size: usize) -> *mut c_void;
8+
9+
static in6addr_any: in6_addr;
10+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//! Ensure that our crate is able to handle definitions spread across many files
2+
3+
mod bar;
4+
mod foo;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
struct Foo {
2+
a: int,
3+
b: u8;
4+
}
5+
6+
unin Bar {
7+
x: u8,
8+
y: u8
9+
}

ctest-next/tests/input/macro.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
macro_rules! vector {
2+
($name:ident, $ty:ty) => {
3+
#[repr(C)]
4+
struct $name {
5+
x: $ty,
6+
y: $ty,
7+
}
8+
};
9+
}
10+
11+
vector!(VecU8, u8);
12+
vector!(VecU16, u16);

ctest-next/tests/input/simple.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use std::os::raw::c_char;
2+
3+
pub type Byte = u8;
4+
5+
#[repr(C)]
6+
pub struct Person {
7+
name: *const c_char,
8+
age: u8,
9+
}
10+
11+
#[repr(C)]
12+
pub union Word {
13+
word: u16,
14+
byte: [Byte; 2],
15+
}

0 commit comments

Comments
 (0)