Struct ctest2::TestGenerator
source · pub struct TestGenerator { /* private fields */ }
Expand description
A builder used to generate a test suite.
This builder has a number of configuration options which modify how the generated tests are emitted, and it is also the main entry point for parsing an FFI header crate for definitions.
Implementations§
source§impl TestGenerator
impl TestGenerator
sourcepub fn new() -> Self
pub fn new() -> Self
Creates a new blank test generator.
This won’t actually be that useful until functions like header
are
called, but the main “finalization method” is the generate
method.
sourcepub fn header(&mut self, header: &str) -> &mut Self
pub fn header(&mut self, header: &str) -> &mut Self
Add a header to be included as part of the generated C file.
The generate C test will be compiled by a C compiler, and this can be used to ensure that all the necessary header files are included to test all FFI definitions.
§Examples
use std::env;
use std::path::PathBuf;
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.header("foo.h")
.header("bar.h");
sourcepub fn rust_version(&mut self, major: u64, minor: u64, patch: u64) -> &mut Self
pub fn rust_version(&mut self, major: u64, minor: u64, patch: u64) -> &mut Self
Target Rust version: major
.minor
.patch
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.rust_version(1, 0, 1);
sourcepub fn include<P: AsRef<Path>>(&mut self, p: P) -> &mut Self
pub fn include<P: AsRef<Path>>(&mut self, p: P) -> &mut Self
Add a path to the C compiler header lookup path.
This is useful for if the C library is installed to a nonstandard location to ensure that compiling the C file succeeds.
§Examples
use std::env;
use std::path::PathBuf;
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
cfg.include(out_dir.join("include"));
sourcepub fn language(&mut self, lang: Lang) -> &mut Self
pub fn language(&mut self, lang: Lang) -> &mut Self
Sets the programming language.
§Examples
use std::env;
use std::path::PathBuf;
use ctest2::{TestGenerator, Lang};
let mut cfg = TestGenerator::new();
cfg.language(Lang::CXX);
sourcepub fn flag(&mut self, flag: &str) -> &mut Self
pub fn flag(&mut self, flag: &str) -> &mut Self
Add a flag to the C compiler invocation.
This can be useful for tweaking the warning settings of the underlying compiler.
§Examples
use std::env;
use std::path::PathBuf;
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
// if msvc
cfg.flag("/wd4820");
// if gnu
cfg.flag("-Wno-type-limits");
sourcepub fn out_dir<P: AsRef<Path>>(&mut self, p: P) -> &mut Self
pub fn out_dir<P: AsRef<Path>>(&mut self, p: P) -> &mut Self
Configures the output directory of the generated Rust and C code.
Note that for Cargo builds this defaults to $OUT_DIR
and it’s not
necessary to call.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.out_dir("path/to/output");
sourcepub fn target(&mut self, target: &str) -> &mut Self
pub fn target(&mut self, target: &str) -> &mut Self
Configures the target to compile C code for.
Note that for Cargo builds this defaults to $TARGET
and it’s not
necessary to call.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.target("x86_64-unknown-linux-gnu");
sourcepub fn define(&mut self, k: &str, v: Option<&str>) -> &mut Self
pub fn define(&mut self, k: &str, v: Option<&str>) -> &mut Self
Set a -D
flag for the C compiler being called.
This can be used to define various variables to configure how header files are included or what APIs are exposed from header files.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.define("_GNU_SOURCE", None)
.define("_WIN32_WINNT", Some("0x8000"));
sourcepub fn cfg(&mut self, k: &str, v: Option<&str>) -> &mut Self
pub fn cfg(&mut self, k: &str, v: Option<&str>) -> &mut Self
Set a --cfg
option with which to expand the Rust FFI crate.
By default the Rust code is run through expansion to determine what C APIs are exposed (to allow differences across platforms).
The k
argument is the #[cfg]
value to define, while v
is the
optional value of v
:
-
k == "foo"
andv == None
makes#[cfg(foo)]
expand. That is,cfg!(foo)
expands totrue
. -
k == "bar"
andv == Some("baz")
makes#[cfg(bar = "baz")]
expand. That is,cfg!(bar = "baz")
expands totrue
.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.cfg("foo", None) // cfg!(foo)
.cfg("bar", Some("baz")); // cfg!(bar = "baz")
sourcepub fn verbose_skip(&mut self, v: bool) -> &mut Self
pub fn verbose_skip(&mut self, v: bool) -> &mut Self
Skipped item names are printed to stderr
if v
is true
.
sourcepub fn type_name<F>(&mut self, f: F) -> &mut Self
pub fn type_name<F>(&mut self, f: F) -> &mut Self
Configures how a Rust type name is translated to a C type name.
The closure is given a Rust type name as well as a boolean indicating whether it’s a struct or not.
The default behavior is that struct foo
in Rust is translated to
struct foo
in C, and type foo
in Rust is translated to foo
in C.
Some header files, however, have the convention that struct foo_t
in
Rust should be foo_t
in C, for example.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.type_name(|ty, is_struct, is_union| {
if is_struct {
format!("{}_t", ty)
} else {
ty.to_string()
}
});
sourcepub fn field_name<F>(&mut self, f: F) -> &mut Self
pub fn field_name<F>(&mut self, f: F) -> &mut Self
Configures how a Rust struct field is translated to a C struct field.
The closure is given a Rust struct name as well as a field within that struct. The name of the corresponding field in C is then returned.
By default the field name in C just matches the field name in Rust, but
this is useful for fields which otherwise are named after keywords in
Rust (such as a field name of type
).
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.field_name(|_s, field| {
field.replace("foo", "bar")
});
sourcepub fn volatile_item<F>(&mut self, f: F) -> &mut Self
pub fn volatile_item<F>(&mut self, f: F) -> &mut Self
Is volatile?
The closure given takes a VolatileKind
denoting a particular item that
could be volatile, and returns whether this is the case.
§Examples
use ctest2::{TestGenerator, VolatileItemKind::StructField};
let mut cfg = TestGenerator::new();
cfg.volatile_item(|i| {
match i {
StructField(ref s, ref f)
if s == "foo_struct" && f == "foo_field"
=> true,
_ => false,
}});
sourcepub fn array_arg<F>(&mut self, f: F) -> &mut Self
pub fn array_arg<F>(&mut self, f: F) -> &mut Self
Is argument of function an array?
The closure denotes whether particular argument of a function is an array.
§Examples
use ctest2::{TestGenerator};
let mut cfg = TestGenerator::new();
cfg.array_arg(|i, n| {
match (i, n) {
("foo", 0) => true,
_ => false,
}});
sourcepub fn const_cname<F>(&mut self, f: F) -> &mut Self
pub fn const_cname<F>(&mut self, f: F) -> &mut Self
Configures how Rust const
s names are translated to C.
The closure is given a Rust const
name. The name of the corresponding
const
in C is then returned.
By default the const
name in C just matches the const
name in Rust.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.const_cname(|c| {
c.replace("FOO", "foo")
});
sourcepub fn skip_field<F>(&mut self, f: F) -> &mut Self
pub fn skip_field<F>(&mut self, f: F) -> &mut Self
Configures whether all tests for a field are skipped or not.
The closure is given a Rust struct name as well as a field within that struct. A flag indicating whether the field should be tested for type, size, offset, and alignment should be skipped or not.
By default all field properties are tested.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.skip_field(|s, field| {
s == "foo_t" || (s == "bar_t" && field == "bar")
});
sourcepub fn skip_field_type<F>(&mut self, f: F) -> &mut Self
pub fn skip_field_type<F>(&mut self, f: F) -> &mut Self
Configures whether tests for the type of a field is skipped or not.
The closure is given a Rust struct name as well as a field within that struct. A flag indicating whether the field’s type should be tested is returned.
By default all field properties are tested.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.skip_field_type(|s, field| {
s == "foo_t" || (s == "bar_t" && field == "bar")
});
sourcepub fn skip_signededness<F>(&mut self, f: F) -> &mut Self
pub fn skip_signededness<F>(&mut self, f: F) -> &mut Self
Configures whether a types signededness is tested or not.
The closure is given the name of a Rust type, and returns whether the type should be tested as having the right sign (positive or negative).
By default all signededness checks are performed.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.skip_signededness(|s| {
s.starts_with("foo_")
});
sourcepub fn skip_fn<F>(&mut self, f: F) -> &mut Self
pub fn skip_fn<F>(&mut self, f: F) -> &mut Self
Configures whether tests for a function definition are generated.
The closure is given the name of a Rust FFI function and returns whether test will be generated.
By default, a function’s signature is checked along with its address in memory.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.skip_fn(|s| {
s.starts_with("foo_")
});
sourcepub fn skip_static<F>(&mut self, f: F) -> &mut Self
pub fn skip_static<F>(&mut self, f: F) -> &mut Self
Configures whether tests for a static definition are generated.
The closure is given the name of a Rust extern static definition and returns whether test will be generated.
By default, a static’s type is checked along with its address in memory.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.skip_static(|s| {
s.starts_with("foo_")
});
sourcepub fn skip_fn_ptrcheck<F>(&mut self, f: F) -> &mut Self
pub fn skip_fn_ptrcheck<F>(&mut self, f: F) -> &mut Self
Configures whether tests for a function pointer’s value are generated.
The closure is given the name of a Rust FFI function and returns whether the test will be generated.
By default generated tests will ensure that the function pointer in C
corresponds to the same function pointer in Rust. This can often
uncover subtle symbol naming issues where a header file is referenced
through the C identifier foo
but the underlying symbol is mapped to
something like __foo_compat
.
sourcepub fn skip_const<F>(&mut self, f: F) -> &mut Self
pub fn skip_const<F>(&mut self, f: F) -> &mut Self
Configures whether the tests for a constant’s value are generated.
The closure is given the name of a Rust constant and returns whether the test will be generated.
By default all constant values are verified.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.skip_const(|s| {
s.starts_with("FOO_")
});
sourcepub fn skip_type<F>(&mut self, f: F) -> &mut Self
pub fn skip_type<F>(&mut self, f: F) -> &mut Self
Configures whether the tests for a typedef are emitted.
The closure is passed the name of a Rust typedef and returns whether the tests are generated.
By default existence of a typedef is checked.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.skip_type(|s| {
s.starts_with("foo_")
});
sourcepub fn skip_struct<F>(&mut self, f: F) -> &mut Self
pub fn skip_struct<F>(&mut self, f: F) -> &mut Self
Configures whether the tests for a struct are emitted.
The closure is passed the name of a Rust struct and returns whether the tests are generated.
By default structs undergo tests such as size, alignment, existence, field offset, etc.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.skip_struct(|s| {
s.starts_with("foo_")
});
sourcepub fn skip_roundtrip<F>(&mut self, f: F) -> &mut Self
pub fn skip_roundtrip<F>(&mut self, f: F) -> &mut Self
Configures whether the ABI roundtrip tests for a type are emitted.
The closure is passed the name of a Rust type and returns whether the tests are generated.
By default all types undergo ABI roundtrip tests. Arrays cannot undergo an ABI roundtrip because they cannot be returned by C functions, and have to be manually skipped here.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.skip_roundtrip(|s| {
s.starts_with("foo_")
});
sourcepub fn fn_cname<F>(&mut self, f: F) -> &mut Self
pub fn fn_cname<F>(&mut self, f: F) -> &mut Self
Configures the name of a function in the generate C code.
The closure is passed the Rust name of a function as well as any
optional #[link_name]
specified.
By default the name of the generated C reference is the same as the Rust function. This is useful, however, if different naming conventions are used in Rust than are present in C (which is discouraged, however).
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.fn_cname(|rust, link_name| link_name.unwrap_or(rust).to_string());
sourcepub fn generate<P: AsRef<Path>>(&mut self, krate: P, out_file: &str)
pub fn generate<P: AsRef<Path>>(&mut self, krate: P, out_file: &str)
Generate all tests.
This function is first given the path to the *-sys
crate which is
being tested along with an output file from where to generate the Rust
side of the tests.
This function does not consume the builder, but it is expected that all configuration has happened prior to calling this function.
This will also generate the corresponding C side of the tests and compile it.
§Examples
use ctest2::TestGenerator;
let mut cfg = TestGenerator::new();
cfg.generate("../path/to/libfoo-sys/lib.rs", "all.rs");