1 //! Integration tests for `zeroize_derive` proc macros
2 #![cfg(feature = "zeroize_derive")]
3
4 use zeroize::{Zeroize, ZeroizeOnDrop};
5
6 #[test]
derive_tuple_struct_test()7 fn derive_tuple_struct_test() {
8 #[derive(Zeroize, ZeroizeOnDrop)]
9 struct Z([u8; 3]);
10
11 let mut value = Z([1, 2, 3]);
12 value.zeroize();
13 assert_eq!(&value.0, &[0, 0, 0])
14 }
15
16 #[test]
17 #[cfg(feature = "alloc")]
derive_struct_test()18 fn derive_struct_test() {
19 #[derive(Zeroize, ZeroizeOnDrop)]
20 struct Z {
21 string: String,
22 vec: Vec<u8>,
23 bytearray: [u8; 3],
24 number: usize,
25 boolean: bool,
26 }
27
28 let mut value = Z {
29 string: String::from("Hello, world!"),
30 vec: vec![1, 2, 3],
31 bytearray: [4, 5, 6],
32 number: 42,
33 boolean: true,
34 };
35
36 value.zeroize();
37
38 assert!(value.string.is_empty());
39 assert!(value.vec.is_empty());
40 assert_eq!(&value.bytearray, &[0, 0, 0]);
41 assert_eq!(value.number, 0);
42 assert!(!value.boolean);
43 }
44
45 #[test]
derive_enum_test()46 fn derive_enum_test() {
47 #[derive(Zeroize, ZeroizeOnDrop)]
48 enum Z {
49 #[allow(dead_code)]
50 Variant1,
51 Variant2(usize),
52 }
53
54 let mut value = Z::Variant2(26);
55
56 value.zeroize();
57
58 assert!(matches!(value, Z::Variant2(0)));
59 }
60
61 /// Test that the custom macro actually derived `Drop` for `Z`
62 #[test]
derive_struct_drop()63 fn derive_struct_drop() {
64 #[derive(Zeroize, ZeroizeOnDrop)]
65 struct Z([u8; 3]);
66
67 assert!(std::mem::needs_drop::<Z>());
68 }
69
70 /// Test that the custom macro actually derived `Drop` for `Z`
71 #[test]
derive_enum_drop()72 fn derive_enum_drop() {
73 #[allow(dead_code)]
74 #[derive(Zeroize, ZeroizeOnDrop)]
75 enum Z {
76 Variant1,
77 Variant2(usize),
78 }
79
80 assert!(std::mem::needs_drop::<Z>());
81 }
82
83 /// Test that the custom macro actually derived `Drop` for `Z`
84 #[test]
derive_struct_only_drop()85 fn derive_struct_only_drop() {
86 #[derive(ZeroizeOnDrop)]
87 struct Z([u8; 3]);
88
89 assert!(std::mem::needs_drop::<Z>());
90 }
91
92 /// Test that the custom macro actually derived `Drop` for `Z`
93 #[test]
derive_enum_only_drop()94 fn derive_enum_only_drop() {
95 #[allow(dead_code)]
96 #[derive(ZeroizeOnDrop)]
97 enum Z {
98 Variant1,
99 Variant2(usize),
100 }
101
102 assert!(std::mem::needs_drop::<Z>());
103 }
104
105 /// Test that `Drop` is not derived in the following case by defining a
106 /// `Drop` impl which should conflict if the custom derive defined one too
107 #[allow(dead_code)]
108 #[derive(Zeroize)]
109 struct ZeroizeNoDropStruct([u8; 3]);
110
111 impl Drop for ZeroizeNoDropStruct {
drop(&mut self)112 fn drop(&mut self) {}
113 }
114
115 #[allow(dead_code)]
116 #[derive(Zeroize)]
117 enum ZeroizeNoDropEnum {
118 Variant([u8; 3]),
119 }
120
121 impl Drop for ZeroizeNoDropEnum {
drop(&mut self)122 fn drop(&mut self) {}
123 }
124
125 #[test]
126 #[cfg(feature = "alloc")]
derive_struct_skip()127 fn derive_struct_skip() {
128 #[derive(Zeroize, ZeroizeOnDrop)]
129 struct Z {
130 string: String,
131 vec: Vec<u8>,
132 #[zeroize(skip)]
133 bytearray: [u8; 3],
134 number: usize,
135 boolean: bool,
136 }
137
138 let mut value = Z {
139 string: String::from("Hello, world!"),
140 vec: vec![1, 2, 3],
141 bytearray: [4, 5, 6],
142 number: 42,
143 boolean: true,
144 };
145
146 value.zeroize();
147
148 assert!(value.string.is_empty());
149 assert!(value.vec.is_empty());
150 assert_eq!(&value.bytearray, &[4, 5, 6]);
151 assert_eq!(value.number, 0);
152 assert!(!value.boolean);
153 }
154
155 #[test]
156 #[cfg(feature = "alloc")]
derive_enum_skip()157 fn derive_enum_skip() {
158 #[derive(Zeroize, ZeroizeOnDrop)]
159 enum Z {
160 #[allow(dead_code)]
161 Variant1,
162 #[zeroize(skip)]
163 Variant2([u8; 3]),
164 #[zeroize(skip)]
165 Variant3 {
166 string: String,
167 vec: Vec<u8>,
168 bytearray: [u8; 3],
169 number: usize,
170 boolean: bool,
171 },
172 Variant4 {
173 string: String,
174 vec: Vec<u8>,
175 #[zeroize(skip)]
176 bytearray: [u8; 3],
177 number: usize,
178 boolean: bool,
179 },
180 }
181
182 let mut value = Z::Variant2([4, 5, 6]);
183
184 value.zeroize();
185
186 assert!(matches!(&value, Z::Variant2([4, 5, 6])));
187
188 let mut value = Z::Variant3 {
189 string: String::from("Hello, world!"),
190 vec: vec![1, 2, 3],
191 bytearray: [4, 5, 6],
192 number: 42,
193 boolean: true,
194 };
195
196 value.zeroize();
197
198 assert!(matches!(
199 &value,
200 Z::Variant3 { string, vec, bytearray, number, boolean }
201 if string == "Hello, world!" &&
202 vec == &[1, 2, 3] &&
203 bytearray == &[4, 5, 6] &&
204 *number == 42 &&
205 *boolean
206 ));
207
208 let mut value = Z::Variant4 {
209 string: String::from("Hello, world!"),
210 vec: vec![1, 2, 3],
211 bytearray: [4, 5, 6],
212 number: 42,
213 boolean: true,
214 };
215
216 value.zeroize();
217
218 assert!(matches!(
219 &value,
220 Z::Variant4 { string, vec, bytearray, number, boolean }
221 if string.is_empty() &&
222 vec.is_empty() &&
223 bytearray == &[4, 5, 6] &&
224 *number == 0 &&
225 !boolean
226 ));
227 }
228
229 #[test]
derive_bound()230 fn derive_bound() {
231 trait T: Zeroize {}
232
233 impl T for u8 {}
234
235 #[derive(Zeroize)]
236 #[zeroize(bound = "X: T")]
237 struct Z<X>(X);
238
239 let mut value = Z(5_u8);
240
241 value.zeroize();
242
243 assert_eq!(value.0, 0);
244 }
245
246 #[test]
derive_inherit_zeroize_on_drop()247 fn derive_inherit_zeroize_on_drop() {
248 #[derive(ZeroizeOnDrop)]
249 struct X([u8; 3]);
250
251 #[derive(ZeroizeOnDrop)]
252 struct Z(X);
253
254 let mut value = Z(X([1, 2, 3]));
255 unsafe {
256 std::ptr::drop_in_place(&mut value);
257 }
258 assert_eq!(&value.0 .0, &[0, 0, 0])
259 }
260
261 #[test]
derive_inherit_from_both()262 fn derive_inherit_from_both() {
263 #[derive(Zeroize, ZeroizeOnDrop)]
264 struct X([u8; 3]);
265
266 #[derive(ZeroizeOnDrop)]
267 struct Z(X);
268
269 let mut value = Z(X([1, 2, 3]));
270 unsafe {
271 std::ptr::drop_in_place(&mut value);
272 }
273 assert_eq!(&value.0 .0, &[0, 0, 0])
274 }
275
276 #[test]
derive_inherit_both()277 fn derive_inherit_both() {
278 #[derive(Zeroize, ZeroizeOnDrop)]
279 struct X([u8; 3]);
280
281 #[derive(Zeroize, ZeroizeOnDrop)]
282 struct Z(X);
283
284 let mut value = Z(X([1, 2, 3]));
285 unsafe {
286 std::ptr::drop_in_place(&mut value);
287 }
288 assert_eq!(&value.0 .0, &[0, 0, 0])
289 }
290
291 #[test]
derive_deref()292 fn derive_deref() {
293 struct X([u8; 3]);
294
295 impl std::ops::Deref for X {
296 type Target = [u8];
297
298 fn deref(&self) -> &Self::Target {
299 &self.0
300 }
301 }
302
303 impl std::ops::DerefMut for X {
304 fn deref_mut(&mut self) -> &mut Self::Target {
305 &mut self.0
306 }
307 }
308
309 #[derive(Zeroize, ZeroizeOnDrop)]
310 struct Z(X);
311
312 let mut value = Z(X([1, 2, 3]));
313 unsafe {
314 std::ptr::drop_in_place(&mut value);
315 }
316 assert_eq!(&value.0 .0, &[0, 0, 0])
317 }
318
319 #[test]
320 #[cfg(feature = "alloc")]
derive_zeroize_on_drop_generic()321 fn derive_zeroize_on_drop_generic() {
322 #[derive(ZeroizeOnDrop)]
323 struct Y<T: Zeroize>(Box<T>);
324
325 #[derive(ZeroizeOnDrop)]
326 struct Z<T: Zeroize>(Vec<T>);
327 }
328