abi_stable/library/
c_abi_testing.rs

1//! This module runs tests on the C abi as defined by Rust,
2//! to detect whether Rust changed how it deals with zero-sized types.
3
4use super::LibraryError;
5use crate::std_types::{RBoxError, Tuple2, Tuple3};
6
7// Types used in tests from this module
8mod types;
9
10mod functions;
11
12#[macro_use]
13mod c_abi_testing_macros;
14
15use self::types::MyUnit;
16
17pub use self::functions::{CAbiTestingFns, C_ABI_TESTING_FNS};
18
19/// Tests that the abi (as defined by the compiler) of the functions in
20/// CAbiTestingFns is the same as the caller's.
21pub fn run_tests(funcs: &CAbiTestingFns) -> Result<(), LibraryError> {
22    pair_tests(funcs)?;
23    triple_tests(funcs)?;
24    two_pair_tests(funcs)?;
25    mixed_units_test(funcs)?;
26    Ok(())
27}
28
29fn make_invalid_cabi_err<T>(expected: T, found: T) -> LibraryError
30where
31    T: std::fmt::Debug,
32{
33    LibraryError::InvalidCAbi {
34        expected: RBoxError::from_debug(&expected),
35        found: RBoxError::from_debug(&found),
36    }
37}
38
39fn pair_tests(funcs: &CAbiTestingFns) -> Result<(), LibraryError> {
40    check_roundtrip!(funcs, 0x1, (a = Tuple2(1, ())), ret_pair_a, take_pair_a);
41    check_roundtrip!(funcs, 0x5, (a = Tuple2(5, ())), ret_pair_a, take_pair_a);
42
43    check_roundtrip!(
44        funcs,
45        0x1_0000,
46        (a = Tuple2((), 1)),
47        ret_pair_b,
48        take_pair_b
49    );
50    check_roundtrip!(
51        funcs,
52        0x5_0000,
53        (a = Tuple2((), 5)),
54        ret_pair_b,
55        take_pair_b
56    );
57    Ok(())
58}
59
60fn triple_tests(funcs: &CAbiTestingFns) -> Result<(), LibraryError> {
61    check_roundtrip!(
62        funcs,
63        0x1_0001_0000,
64        (a = Tuple3((), 1, 1)),
65        ret_triple_a,
66        take_triple_a
67    );
68    check_roundtrip!(
69        funcs,
70        0x1_0005_0000,
71        (a = Tuple3((), 5, 1)),
72        ret_triple_a,
73        take_triple_a
74    );
75    check_roundtrip!(
76        funcs,
77        0x7_0001_0000,
78        (a = Tuple3((), 1, 7)),
79        ret_triple_a,
80        take_triple_a
81    );
82    check_roundtrip!(
83        funcs,
84        0x7_0003_0000,
85        (a = Tuple3((), 3, 7)),
86        ret_triple_a,
87        take_triple_a
88    );
89
90    check_roundtrip!(
91        funcs,
92        0x1_0000_0001,
93        (a = Tuple3(1, (), 1)),
94        ret_triple_b,
95        take_triple_b
96    );
97    check_roundtrip!(
98        funcs,
99        0x1_0000_0005,
100        (a = Tuple3(5, (), 1)),
101        ret_triple_b,
102        take_triple_b
103    );
104    check_roundtrip!(
105        funcs,
106        0x7_0000_0001,
107        (a = Tuple3(1, (), 7)),
108        ret_triple_b,
109        take_triple_b
110    );
111    check_roundtrip!(
112        funcs,
113        0x7_0000_0003,
114        (a = Tuple3(3, (), 7)),
115        ret_triple_b,
116        take_triple_b
117    );
118
119    check_roundtrip!(
120        funcs,
121        0x1_0001,
122        (a = Tuple3(1, 1, ())),
123        ret_triple_c,
124        take_triple_c
125    );
126    check_roundtrip!(
127        funcs,
128        0x1_0005,
129        (a = Tuple3(5, 1, ())),
130        ret_triple_c,
131        take_triple_c
132    );
133    check_roundtrip!(
134        funcs,
135        0x7_0001,
136        (a = Tuple3(1, 7, ())),
137        ret_triple_c,
138        take_triple_c
139    );
140    check_roundtrip!(
141        funcs,
142        0x7_0003,
143        (a = Tuple3(3, 7, ())),
144        ret_triple_c,
145        take_triple_c
146    );
147    Ok(())
148}
149
150fn two_pair_tests(funcs: &CAbiTestingFns) -> Result<(), LibraryError> {
151    let funcs = anon_struct! {
152        ret_2_pairs_a:|n|(funcs.ret_2_pairs_a)(n).into_tuple(),
153        ret_2_pairs_b:|n|(funcs.ret_2_pairs_b)(n).into_tuple(),
154        take_2_pairs_a:funcs.take_2_pairs_a,
155        take_2_pairs_b:funcs.take_2_pairs_b,
156    };
157
158    check_roundtrip!(
159        funcs,
160        0x1_0000_0005_0000,
161        (a = Tuple2((), 5), b = Tuple2((), 1)),
162        ret_2_pairs_a,
163        take_2_pairs_a,
164    );
165    check_roundtrip!(
166        funcs,
167        0xF_0000_000A_0000,
168        (a = Tuple2((), 10), b = Tuple2((), 15)),
169        ret_2_pairs_a,
170        take_2_pairs_a,
171    );
172
173    check_roundtrip!(
174        funcs,
175        0x0_0007_0000_0003,
176        (a = Tuple2(3, ()), b = Tuple2(7, ())),
177        ret_2_pairs_b,
178        take_2_pairs_b,
179    );
180    check_roundtrip!(
181        funcs,
182        0x0_0002_0000_000B,
183        (a = Tuple2(11, ()), b = Tuple2(2, ())),
184        ret_2_pairs_b,
185        take_2_pairs_b,
186    );
187    Ok(())
188}
189
190fn mixed_units_test(funcs: &CAbiTestingFns) -> Result<(), LibraryError> {
191    let single_test = |n: u64| {
192        let a = n as u16;
193        let b = (n >> 16) as u16;
194        let c = (n >> 32) as u16;
195        let d = (n >> 48) as u16;
196
197        let res = (funcs.mixed_units)(a, MyUnit, b, MyUnit, c, MyUnit, d);
198        if res != n {
199            Err(make_invalid_cabi_err(n, res))
200        } else {
201            Ok(())
202        }
203    };
204
205    single_test(0x0)?;
206    single_test(0x1)?;
207    single_test(0x2_0003)?;
208    single_test(0x4_0005_0006)?;
209    single_test(0x7_0008_0009_000A)?;
210    Ok(())
211}