Skip to content

Commit 6376d9e

Browse files
committed
ctest: add tests for aliases, structs, unions, as well as a test crate.
1 parent dc4c75d commit 6376d9e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3912
-182
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ extra_traits = []
142142
members = [
143143
"ctest",
144144
"ctest-next",
145+
"ctest-next-test",
145146
"ctest-test",
146147
"libc-test",
147148
]

ctest-next-test/Cargo.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[package]
2+
name = "ctest-next-test"
3+
version = "0.1.0"
4+
authors = ["Alex Crichton <[email protected]>"]
5+
publish = false
6+
edition = "2021"
7+
8+
[build-dependencies]
9+
ctest-next = { path = "../ctest-next" }
10+
cc = "1.0"
11+
12+
[dev-dependencies]
13+
ctest-next = { path = "../ctest-next" }
14+
15+
[dependencies]
16+
libc = { path = ".." }
17+
18+
[[bin]]
19+
name = "t1-next"
20+
test = false
21+
22+
[[bin]]
23+
name = "t2-next"
24+
test = false

ctest-next-test/build.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use std::env;
2+
3+
use ctest_next::{generate_test, TestGenerator};
4+
5+
fn main() {
6+
let opt_level = env::var("OPT_LEVEL")
7+
.ok()
8+
.and_then(|s| s.parse().ok())
9+
.unwrap_or(0);
10+
11+
let profile = env::var("PROFILE").unwrap_or_default();
12+
if profile == "release" || opt_level >= 2 {
13+
println!("cargo:rustc-cfg=optimized");
14+
}
15+
16+
// FIXME(ctest): The .c files are ignored right now, I'm not sure if they
17+
// were used or how they were used before.
18+
cc::Build::new()
19+
.include("src")
20+
.warnings(false)
21+
.file("src/t1.c")
22+
.compile("libt1.a");
23+
println!("cargo:rerun-if-changed=src/t1.c");
24+
println!("cargo:rerun-if-changed=src/t1.h");
25+
26+
cc::Build::new()
27+
.warnings(false)
28+
.file("src/t2.c")
29+
.compile("libt2.a");
30+
println!("cargo:rerun-if-changed=src/t2.c");
31+
println!("cargo:rerun-if-changed=src/t2.h");
32+
33+
let mut t1gen = TestGenerator::new();
34+
t1gen
35+
.header("t1.h")
36+
.include("src")
37+
.skip_private(true)
38+
.rename_fn(|f| f.link_name().unwrap_or(f.ident()).to_string().into())
39+
.rename_union_ty(|ty| (ty == "T1Union").then_some(ty.to_string()))
40+
.rename_struct_ty(|ty| (ty == "Transparent").then_some(ty.to_string()))
41+
.volatile_field(|s, f| s.ident() == "V" && f.ident() == "v")
42+
.volatile_static(|s| s.ident() == "vol_ptr")
43+
.volatile_static(|s| s.ident() == "T1_fn_ptr_vol")
44+
.volatile_fn_arg(|f, p| f.ident() == "T1_vol0" && p.ident() == "arg0")
45+
.volatile_fn_arg(|f, p| f.ident() == "T1_vol2" && p.ident() == "arg1")
46+
.volatile_fn_return_type(|f| f.ident() == "T1_vol1")
47+
.volatile_fn_return_type(|f| f.ident() == "T1_vol2")
48+
// The parameter `a` of the functions `T1r`, `T1s`, `T1t`, `T1v` is an array.
49+
.array_arg(|f, p| matches!(f.ident(), "T1r" | "T1s" | "T1t" | "T1v") && p.ident() == "a")
50+
.skip_roundtrip(|n| n == "Arr");
51+
generate_test(&mut t1gen, "src/t1.rs", "t1gen.rs").unwrap();
52+
53+
let mut t2gen = TestGenerator::new();
54+
t2gen
55+
.header("t2.h")
56+
.include("src")
57+
// public C typedefs have to manually be specified because they are identical to normal
58+
// structs on the Rust side.
59+
.rename_union_ty(|ty| (ty == "T2Union").then_some(ty.to_string()))
60+
.skip_roundtrip(|_| true);
61+
generate_test(&mut t2gen, "src/t2.rs", "t2gen.rs").unwrap();
62+
}

ctest-next-test/src/bin/t1-next.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![cfg(not(test))]
2+
#![deny(warnings)]
3+
4+
use ctest_next_test::t1::*;
5+
6+
include!(concat!(env!("OUT_DIR"), "/t1gen.rs"));

ctest-next-test/src/bin/t2-next.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![cfg(not(test))]
2+
#![deny(warnings)]
3+
4+
use ctest_next_test::t2::*;
5+
6+
include!(concat!(env!("OUT_DIR"), "/t2gen.rs"));

ctest-next-test/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//! `ctest-next-test` is a test crate for testing `ctest-next`. It consists
2+
//! of two test binaries, t1 and t2 that test various aspects of `ctest-next`,
3+
//! such as validation and generation of tests.
4+
5+
pub mod t1;
6+
pub mod t2;

ctest-next-test/src/t1.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include "t1.h"
2+
#include <stdint.h>
3+
#include <stdlib.h>
4+
5+
void T1a(void) {}
6+
void *T1b(void) { return NULL; }
7+
void *T1c(void *a) { return NULL; }
8+
int32_t T1d(unsigned a) { return 0; }
9+
void T1e(unsigned a, const struct T1Bar *b) {}
10+
void T1f(void) {}
11+
void T1g(int32_t *a) {}
12+
void T1h(const int32_t *b) {}
13+
void T1i(int32_t a[4]) {}
14+
void T1j(const int32_t b[4]) {}
15+
void T1o(int32_t (*a)[4]) {}
16+
void T1p(int32_t (*const a)[4]) {}
17+
18+
void T1r(Arr a) {}
19+
void T1s(const Arr a) {}
20+
void T1t(Arr *a) {}
21+
void T1v(const Arr *a) {}
22+
23+
unsigned T1static = 3;
24+
25+
const uint8_t T1_static_u8 = 42;
26+
uint8_t T1_static_mut_u8 = 37;
27+
28+
uint8_t foo(uint8_t a, uint8_t b) { return a + b; }
29+
void bar(uint8_t a) { return; }
30+
void baz(void) { return; }
31+
32+
uint32_t (*nested(uint8_t arg))(uint16_t)
33+
{
34+
return NULL;
35+
}
36+
37+
uint32_t (*nested2(uint8_t (*arg0)(uint8_t), uint16_t (*arg1)(uint16_t)))(uint16_t)
38+
{
39+
return NULL;
40+
}
41+
42+
uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t) = foo;
43+
uint8_t (*const T1_static_const_fn_ptr_unsafe)(uint8_t, uint8_t) = foo;
44+
void (*const T1_static_const_fn_ptr_unsafe2)(uint8_t) = bar;
45+
void (*const T1_static_const_fn_ptr_unsafe3)(void) = baz;
46+
47+
const uint8_t T1_static_right = 7;
48+
uint8_t (*T1_static_right2)(uint8_t, uint8_t) = foo;
49+
50+
uint32_t (*(*T1_fn_ptr_s)(uint8_t))(uint16_t) = nested;
51+
uint32_t (*(*T1_fn_ptr_s2)(uint8_t (*arg0)(uint8_t), uint16_t (*arg1)(uint16_t)))(uint16_t) = nested2;
52+
53+
const int32_t T1_arr0[2] = {0, 0};
54+
const int32_t T1_arr1[2][3] = {{0, 0, 0}, {0, 0, 0}};
55+
const int32_t T1_arr2[1][2][3] = {{{0, 0, 0}, {0, 0, 0}}};
56+
57+
int32_t T1_arr3[2] = {0, 0};
58+
int32_t T1_arr4[2][3] = {{0, 0, 0}, {0, 0, 0}};
59+
int32_t T1_arr5[1][2][3] = {{{0, 0, 0}, {0, 0, 0}}};
60+
61+
int32_t T1_arr42[1][2][3] = {{{0, 0, 0}, {0, 0, 0}}};
62+
const int16_t *T1_sref = (void *)(1337);
63+
64+
volatile uint8_t *vol_ptr = NULL;
65+
void *T1_vol0(volatile void *x, void *a) { return a ? a : (void *)x; }
66+
volatile void *T1_vol1(void *x, void *b) { return b ? (volatile void *)x : (volatile void *)x; }
67+
volatile void *T1_vol2(void *c, volatile void *x) { return c ? x : x; }
68+
69+
// FIXME(#4365): duplicate symbol errors when enabled
70+
// uint8_t (*volatile T1_fn_ptr_vol)(uint8_t, uint8_t) = foo;

ctest-next-test/src/t1.h

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#include <stdint.h>
2+
3+
typedef int32_t T1Foo;
4+
5+
#define T1N 5
6+
#define T1S "foo"
7+
8+
struct T1Bar
9+
{
10+
int32_t a;
11+
uint32_t b;
12+
T1Foo c;
13+
uint8_t d;
14+
int64_t e[T1N];
15+
int64_t f[T1N][2];
16+
};
17+
18+
struct T1Baz
19+
{
20+
uint64_t a;
21+
struct T1Bar b;
22+
};
23+
24+
typedef union
25+
{
26+
uint64_t a;
27+
uint32_t b;
28+
} T1Union;
29+
30+
union T1NoTypedefUnion
31+
{
32+
uint64_t a;
33+
uint32_t b;
34+
};
35+
36+
struct T1StructWithUnion
37+
{
38+
union T1NoTypedefUnion u;
39+
};
40+
41+
typedef double T1TypedefDouble;
42+
typedef int *T1TypedefPtr;
43+
typedef struct T1Bar T1TypedefStruct;
44+
45+
void T1a(void);
46+
void *T1b(void);
47+
void *T1c(void *);
48+
int32_t T1d(unsigned);
49+
void T1e(unsigned, const struct T1Bar *);
50+
void T1f(void);
51+
void T1g(int32_t *a);
52+
void T1h(const int32_t *b);
53+
void T1i(int32_t a[4]);
54+
void T1j(const int32_t b[4]);
55+
void T1o(int32_t (*a)[4]);
56+
void T1p(int32_t (*const a)[4]);
57+
58+
typedef int32_t(Arr)[4];
59+
typedef int32_t Transparent;
60+
61+
void T1r(Arr a);
62+
void T1s(const Arr a);
63+
void T1t(Arr *a);
64+
void T1v(const Arr *a);
65+
66+
#define T1C 4
67+
68+
extern uint32_t T1static;
69+
extern const uint8_t T1_static_u8;
70+
/* FIXME(#4365): duplicate symbol errors when enabled
71+
// uint8_t T1_static_mut_u8;
72+
// uint8_t (*T1_static_mut_fn_ptr)(uint8_t, uint8_t);
73+
extern uint8_t (*const T1_static_const_fn_ptr_unsafe)(uint8_t, uint8_t);
74+
*/
75+
extern void (*const T1_static_const_fn_ptr_unsafe2)(uint8_t);
76+
extern void (*const T1_static_const_fn_ptr_unsafe3)(void);
77+
78+
extern const uint8_t T1_static_right;
79+
/* FIXME(#4365): duplicate symbol errors when enabled
80+
// uint8_t (*T1_static_right2)(uint8_t, uint8_t);
81+
82+
// T1_fn_ptr_nested: function pointer to a function, taking a uint8_t, and
83+
// returning a function pointer to a function taking a uint16_t and returning a
84+
// uint32_t
85+
uint32_t (*(*T1_fn_ptr_s)(uint8_t))(uint16_t);
86+
87+
// T1_fn_ptr_nested: function pointer to a function, taking a function pointer
88+
// uint8_t -> uint8_t, and returning a function pointer to a function taking a
89+
// uint16_t and returning a uint32_t
90+
uint32_t (*(*T1_fn_ptr_s2)(uint8_t(*)(uint8_t), uint16_t(*)(uint16_t)))(uint16_t);
91+
*/
92+
93+
extern const int32_t T1_arr0[2];
94+
extern const int32_t T1_arr1[2][3];
95+
extern const int32_t T1_arr2[1][2][3];
96+
97+
extern int32_t T1_arr3[2];
98+
extern int32_t T1_arr4[2][3];
99+
extern int32_t T1_arr5[1][2][3];
100+
101+
extern int32_t T1_arr42[1][2][3];
102+
103+
extern const int16_t *T1_sref;
104+
105+
struct Q
106+
{
107+
uint8_t *q0;
108+
uint8_t **q1;
109+
uint8_t q2;
110+
};
111+
112+
struct T1_conflict_foo
113+
{
114+
int a;
115+
};
116+
117+
struct T1_conflict
118+
{
119+
int foo;
120+
};
121+
122+
// test packed structs
123+
//
124+
// on msvc there is only pragma pack
125+
// on clang and gcc there is a packed attribute
126+
127+
#pragma pack(push, 1)
128+
129+
struct Pack
130+
{
131+
uint8_t a;
132+
uint16_t b;
133+
};
134+
135+
#pragma pack(pop)
136+
137+
#pragma pack(push, 4)
138+
139+
struct Pack4
140+
{
141+
uint8_t a;
142+
uint32_t b;
143+
};
144+
145+
#pragma pack(pop)
146+
147+
// volatile pointers in struct fields:
148+
struct V
149+
{
150+
volatile uint8_t *v;
151+
};
152+
153+
// volatile pointers in externs:
154+
extern volatile uint8_t *vol_ptr;
155+
156+
// volatile pointers in function arguments:
157+
void *T1_vol0(volatile void *, void *);
158+
volatile void *T1_vol1(void *, void *);
159+
volatile void *T1_vol2(void *, volatile void *);
160+
161+
/* FIXME(#4365): duplicate symbol errors when enabled
162+
// volatile function pointers:
163+
uint8_t (*volatile T1_fn_ptr_vol)(uint8_t, uint8_t);
164+
*/
165+
166+
#define LOG_MAX_LINE_LENGTH (1400)
167+
168+
typedef struct
169+
{
170+
long tv_sec;
171+
int tv_usec;
172+
} timeval;
173+
174+
typedef struct
175+
{
176+
long level;
177+
char const *file;
178+
long line;
179+
char const *module;
180+
timeval tv;
181+
char message[LOG_MAX_LINE_LENGTH];
182+
} log_record_t;
183+
184+
typedef struct
185+
{
186+
long double inner;
187+
} LongDoubleWrap;

0 commit comments

Comments
 (0)