Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ extra_traits = []
members = [
"ctest",
"ctest-next",
"ctest-next-test",
"ctest-test",
"libc-test",
]
Expand Down
33 changes: 33 additions & 0 deletions ctest-next-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "ctest-next-test"
version = "0.1.0"
authors = ["Alex Crichton <[email protected]>"]
publish = false
edition = "2021"

[build-dependencies]
ctest-next = { path = "../ctest-next" }
cc = "1.0"

[dev-dependencies]
ctest-next = { path = "../ctest-next" }

[dependencies]
libc = { path = ".." }

[[bin]]
name = "t1-next"
test = false

[[bin]]
name = "t2-next"
test = false

# FIXME(msrv): These should be moved to the root Cargo.toml as `[workspace.lints.*]`
# once MSRV is above 1.64 and replaced with `[lints] workspace=true`

[lints.rust]
# FIXME(cleanup): make ident usage consistent in each file
unused_qualifications = "allow"

[lints.clippy]
62 changes: 62 additions & 0 deletions ctest-next-test/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use std::env;

use ctest_next::{generate_test, TestGenerator};

fn main() {
let opt_level = env::var("OPT_LEVEL")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(0);

let profile = env::var("PROFILE").unwrap_or_default();
if profile == "release" || opt_level >= 2 {
println!("cargo:rustc-cfg=optimized");
}

// FIXME(ctest): The .c files are ignored right now, I'm not sure if they
// were used or how they were used before.
cc::Build::new()
.include("src")
.warnings(false)
.file("src/t1.c")
.compile("libt1.a");
println!("cargo:rerun-if-changed=src/t1.c");
println!("cargo:rerun-if-changed=src/t1.h");

cc::Build::new()
.warnings(false)
.file("src/t2.c")
.compile("libt2.a");
println!("cargo:rerun-if-changed=src/t2.c");
println!("cargo:rerun-if-changed=src/t2.h");

let mut t1gen = TestGenerator::new();
t1gen
.header("t1.h")
.include("src")
.skip_private(true)
.rename_fn(|f| f.link_name().unwrap_or(f.ident()).to_string().into())
.rename_union_ty(|ty| (ty == "T1Union").then_some(ty.to_string()))
.rename_struct_ty(|ty| (ty == "Transparent").then_some(ty.to_string()))
.volatile_field(|s, f| s.ident() == "V" && f.ident() == "v")
.volatile_static(|s| s.ident() == "vol_ptr")
.volatile_static(|s| s.ident() == "T1_fn_ptr_vol")
.volatile_fn_arg(|f, p| f.ident() == "T1_vol0" && p.ident() == "arg0")
.volatile_fn_arg(|f, p| f.ident() == "T1_vol2" && p.ident() == "arg1")
.volatile_fn_return_type(|f| f.ident() == "T1_vol1")
.volatile_fn_return_type(|f| f.ident() == "T1_vol2")
// The parameter `a` of the functions `T1r`, `T1s`, `T1t`, `T1v` is an array.
.array_arg(|f, p| matches!(f.ident(), "T1r" | "T1s" | "T1t" | "T1v") && p.ident() == "a")
.skip_roundtrip(|n| n == "Arr");
generate_test(&mut t1gen, "src/t1.rs", "t1gen.rs").unwrap();

let mut t2gen = TestGenerator::new();
t2gen
.header("t2.h")
.include("src")
// public C typedefs have to manually be specified because they are identical to normal
// structs on the Rust side.
.rename_union_ty(|ty| (ty == "T2Union").then_some(ty.to_string()))
.skip_roundtrip(|_| true);
generate_test(&mut t2gen, "src/t2.rs", "t2gen.rs").unwrap();
}
6 changes: 6 additions & 0 deletions ctest-next-test/src/bin/t1-next.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![cfg(not(test))]
#![deny(warnings)]

use ctest_next_test::t1::*;

include!(concat!(env!("OUT_DIR"), "/t1gen.rs"));
6 changes: 6 additions & 0 deletions ctest-next-test/src/bin/t2-next.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![cfg(not(test))]
#![deny(warnings)]

use ctest_next_test::t2::*;

include!(concat!(env!("OUT_DIR"), "/t2gen.rs"));
6 changes: 6 additions & 0 deletions ctest-next-test/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//! `ctest-next-test` is a test crate for testing `ctest-next`. It consists
//! of two test binaries, t1 and t2 that test various aspects of `ctest-next`,
//! such as validation and generation of tests.

pub mod t1;
pub mod t2;
70 changes: 70 additions & 0 deletions ctest-next-test/src/t1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "t1.h"
#include <stdint.h>
#include <stdlib.h>

void T1a(void) {}
void *T1b(void) { return NULL; }
void *T1c(void *a) { return NULL; }
int32_t T1d(unsigned a) { return 0; }
void T1e(unsigned a, const struct T1Bar *b) {}
void T1f(void) {}
void T1g(int32_t *a) {}
void T1h(const int32_t *b) {}
void T1i(int32_t a[4]) {}
void T1j(const int32_t b[4]) {}
void T1o(int32_t (*a)[4]) {}
void T1p(int32_t (*const a)[4]) {}

void T1r(Arr a) {}
void T1s(const Arr a) {}
void T1t(Arr *a) {}
void T1v(const Arr *a) {}

unsigned T1static = 3;

const uint8_t T1_static_u8 = 42;
uint8_t T1_static_mut_u8 = 37;

uint8_t foo(uint8_t a, uint8_t b) { return a + b; }
void bar(uint8_t a) { return; }
void baz(void) { return; }

uint32_t (*nested(uint8_t arg))(uint16_t)
{
return NULL;
}

uint32_t (*nested2(uint8_t (*arg0)(uint8_t), uint16_t (*arg1)(uint16_t)))(uint16_t)
{
return NULL;
}

uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t) = foo;
uint8_t (*const T1_static_const_fn_ptr_unsafe)(uint8_t, uint8_t) = foo;
void (*const T1_static_const_fn_ptr_unsafe2)(uint8_t) = bar;
void (*const T1_static_const_fn_ptr_unsafe3)(void) = baz;

const uint8_t T1_static_right = 7;
uint8_t (*T1_static_right2)(uint8_t, uint8_t) = foo;

uint32_t (*(*T1_fn_ptr_s)(uint8_t))(uint16_t) = nested;
uint32_t (*(*T1_fn_ptr_s2)(uint8_t (*arg0)(uint8_t), uint16_t (*arg1)(uint16_t)))(uint16_t) = nested2;

const int32_t T1_arr0[2] = {0, 0};
const int32_t T1_arr1[2][3] = {{0, 0, 0}, {0, 0, 0}};
const int32_t T1_arr2[1][2][3] = {{{0, 0, 0}, {0, 0, 0}}};

int32_t T1_arr3[2] = {0, 0};
int32_t T1_arr4[2][3] = {{0, 0, 0}, {0, 0, 0}};
int32_t T1_arr5[1][2][3] = {{{0, 0, 0}, {0, 0, 0}}};

int32_t T1_arr42[1][2][3] = {{{0, 0, 0}, {0, 0, 0}}};
const int16_t *T1_sref = (void *)(1337);

volatile uint8_t *vol_ptr = NULL;
void *T1_vol0(volatile void *x, void *a) { return a ? a : (void *)x; }
volatile void *T1_vol1(void *x, void *b) { return b ? (volatile void *)x : (volatile void *)x; }
volatile void *T1_vol2(void *c, volatile void *x) { return c ? x : x; }

// FIXME(#4365): duplicate symbol errors when enabled
// uint8_t (*volatile T1_fn_ptr_vol)(uint8_t, uint8_t) = foo;
187 changes: 187 additions & 0 deletions ctest-next-test/src/t1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#include <stdint.h>

typedef int32_t T1Foo;

#define T1N 5
#define T1S "foo"

struct T1Bar
{
int32_t a;
uint32_t b;
T1Foo c;
uint8_t d;
int64_t e[T1N];
int64_t f[T1N][2];
};

struct T1Baz
{
uint64_t a;
struct T1Bar b;
};

typedef union
{
uint64_t a;
uint32_t b;
} T1Union;

union T1NoTypedefUnion
{
uint64_t a;
uint32_t b;
};

struct T1StructWithUnion
{
union T1NoTypedefUnion u;
};

typedef double T1TypedefDouble;
typedef int *T1TypedefPtr;
typedef struct T1Bar T1TypedefStruct;

void T1a(void);
void *T1b(void);
void *T1c(void *);
int32_t T1d(unsigned);
void T1e(unsigned, const struct T1Bar *);
void T1f(void);
void T1g(int32_t *a);
void T1h(const int32_t *b);
void T1i(int32_t a[4]);
void T1j(const int32_t b[4]);
void T1o(int32_t (*a)[4]);
void T1p(int32_t (*const a)[4]);

typedef int32_t(Arr)[4];
typedef int32_t Transparent;

void T1r(Arr a);
void T1s(const Arr a);
void T1t(Arr *a);
void T1v(const Arr *a);

#define T1C 4

extern uint32_t T1static;
extern const uint8_t T1_static_u8;
/* FIXME(#4365): duplicate symbol errors when enabled
// uint8_t T1_static_mut_u8;
// uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t);
extern uint8_t (*const T1_static_const_fn_ptr_unsafe)(uint8_t, uint8_t);
*/
extern void (*const T1_static_const_fn_ptr_unsafe2)(uint8_t);
extern void (*const T1_static_const_fn_ptr_unsafe3)(void);

extern const uint8_t T1_static_right;
/* FIXME(#4365): duplicate symbol errors when enabled
// uint8_t (*T1_static_right2)(uint8_t, uint8_t);

// T1_fn_ptr_nested: function pointer to a function, taking a uint8_t, and
// returning a function pointer to a function taking a uint16_t and returning a
// uint32_t
uint32_t (*(*T1_fn_ptr_s)(uint8_t))(uint16_t);

// T1_fn_ptr_nested: function pointer to a function, taking a function pointer
// uint8_t -> uint8_t, and returning a function pointer to a function taking a
// uint16_t and returning a uint32_t
uint32_t (*(*T1_fn_ptr_s2)(uint8_t(*)(uint8_t), uint16_t(*)(uint16_t)))(uint16_t);
*/

extern const int32_t T1_arr0[2];
extern const int32_t T1_arr1[2][3];
extern const int32_t T1_arr2[1][2][3];

extern int32_t T1_arr3[2];
extern int32_t T1_arr4[2][3];
extern int32_t T1_arr5[1][2][3];

extern int32_t T1_arr42[1][2][3];

extern const int16_t *T1_sref;

struct Q
{
uint8_t *q0;
uint8_t **q1;
uint8_t q2;
};

struct T1_conflict_foo
{
int a;
};

struct T1_conflict
{
int foo;
};

// test packed structs
//
// on msvc there is only pragma pack
// on clang and gcc there is a packed attribute

#pragma pack(push, 1)

struct Pack
{
uint8_t a;
uint16_t b;
};

#pragma pack(pop)

#pragma pack(push, 4)

struct Pack4
{
uint8_t a;
uint32_t b;
};

#pragma pack(pop)

// volatile pointers in struct fields:
struct V
{
volatile uint8_t *v;
};

// volatile pointers in externs:
extern volatile uint8_t *vol_ptr;

// volatile pointers in function arguments:
void *T1_vol0(volatile void *, void *);
volatile void *T1_vol1(void *, void *);
volatile void *T1_vol2(void *, volatile void *);

/* FIXME(#4365): duplicate symbol errors when enabled
// volatile function pointers:
uint8_t (*volatile T1_fn_ptr_vol)(uint8_t, uint8_t);
*/

#define LOG_MAX_LINE_LENGTH (1400)

typedef struct
{
long tv_sec;
int tv_usec;
} timeval;

typedef struct
{
long level;
char const *file;
long line;
char const *module;
timeval tv;
char message[LOG_MAX_LINE_LENGTH];
} log_record_t;

typedef struct
{
long double inner;
} LongDoubleWrap;
Loading
Loading