constant_time_eq.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. //! Test that the [`libthreema_macros::ConstantTimeEq`] works as expected.
  2. #![expect(unused_crate_dependencies, reason = "False positive")]
  3. #![expect(
  4. clippy::single_char_lifetime_names,
  5. single_use_lifetimes,
  6. reason = "Test lifetimes"
  7. )]
  8. use libthreema_macros::ConstantTimeEq;
  9. #[derive(Clone, Copy, ConstantTimeEq, Debug)]
  10. struct NamedField {
  11. data: [u8; 3],
  12. }
  13. #[derive(ConstantTimeEq, Debug)]
  14. struct NamedFields {
  15. data1: [u8; 3],
  16. data2: u64,
  17. }
  18. #[derive(ConstantTimeEq, Debug)]
  19. struct NamedFieldsBorrowed<'a> {
  20. data1: &'a [u8],
  21. data2: u64,
  22. }
  23. #[derive(ConstantTimeEq, Debug)]
  24. struct NamedFieldsMultipleBorrowed<'a, 'b> {
  25. data1: &'a [u8],
  26. data2: &'b [u8],
  27. }
  28. #[derive(Clone, Copy, ConstantTimeEq, Debug)]
  29. struct UnnamedField(NamedField);
  30. #[derive(Clone, Copy, ConstantTimeEq, Debug)]
  31. struct UnnamedArrayField([u8; 3]);
  32. #[derive(Clone, Copy, ConstantTimeEq, Debug)]
  33. struct UnnamedFields(u32, u64, u32);
  34. #[derive(ConstantTimeEq, Debug)]
  35. struct NamedFieldWithInnerUnnamedField {
  36. data: UnnamedField,
  37. }
  38. #[derive(ConstantTimeEq, Debug)]
  39. struct NamedFieldWithInnerUnnamedFields {
  40. data: UnnamedFields,
  41. }
  42. #[derive(ConstantTimeEq, Debug)]
  43. struct NamedFieldWithInnerUnnamedArrayField {
  44. data: UnnamedArrayField,
  45. }
  46. #[derive(ConstantTimeEq, Debug)]
  47. struct NamedFieldsWithInnerUnnamedField {
  48. data1: UnnamedField,
  49. data2: u64,
  50. }
  51. #[derive(ConstantTimeEq, Debug)]
  52. struct NamedFieldsWithInnerUnnamedFields {
  53. data1: UnnamedFields,
  54. data2: u64,
  55. }
  56. #[derive(ConstantTimeEq, Debug)]
  57. struct NamedFieldsWithInnerUnnamedArrayField {
  58. data1: UnnamedArrayField,
  59. data2: u64,
  60. }
  61. #[cfg(test)]
  62. mod test {
  63. use rstest::rstest;
  64. use subtle::ConstantTimeEq as _;
  65. use crate::*;
  66. #[test]
  67. fn ct_eq_named_field() {
  68. let left = NamedField { data: [3; 3] };
  69. let right = NamedField { data: [3; 3] };
  70. assert!(bool::from(left.ct_eq(&right)));
  71. assert_eq!(left, right);
  72. }
  73. #[rstest]
  74. #[case([1, 0, 0])]
  75. #[case([0, 1, 1])]
  76. #[case([1, 1, 1])]
  77. fn ct_not_eq_named_field(#[case] right: [u8; 3]) {
  78. let left = NamedField { data: [0; 3] };
  79. let right = NamedField { data: right };
  80. assert!(bool::from(!left.ct_eq(&right)));
  81. assert_ne!(left, right);
  82. }
  83. #[test]
  84. fn ct_eq_named_fields() {
  85. let left = NamedFields {
  86. data1: [45; 3],
  87. data2: 3,
  88. };
  89. let right = NamedFields {
  90. data1: [45; 3],
  91. data2: 3,
  92. };
  93. assert!(bool::from(left.ct_eq(&right)));
  94. assert_eq!(left, right);
  95. }
  96. #[rstest]
  97. #[case(([87; 3], 3))]
  98. #[case(([45; 3], 2))]
  99. #[case(([34; 3], 5))]
  100. fn ct_not_eq_named_fields(#[case] right: ([u8; 3], u64)) {
  101. let left = NamedFields {
  102. data1: [45; 3],
  103. data2: 3,
  104. };
  105. let right = NamedFields {
  106. data1: right.0,
  107. data2: right.1,
  108. };
  109. assert!(bool::from(!left.ct_eq(&right)));
  110. assert_ne!(left, right);
  111. }
  112. #[test]
  113. fn ct_eq_unnamed_array_field() {
  114. let left = UnnamedArrayField([3; 3]);
  115. let right = UnnamedArrayField([3; 3]);
  116. assert!(bool::from(left.ct_eq(&right)));
  117. assert_eq!(left, right);
  118. }
  119. #[rstest]
  120. #[case([0, 0, 1])]
  121. #[case([1, 1, 0])]
  122. #[case([1, 1, 1])]
  123. fn ct_not_eq_unnamed_array_field(#[case] right: [u8; 3]) {
  124. let left = UnnamedArrayField([0, 0, 0]);
  125. let right = UnnamedArrayField(right);
  126. assert!(bool::from(!left.ct_eq(&right)));
  127. assert_ne!(left, right);
  128. }
  129. #[test]
  130. fn ct_eq_unnamed_field() {
  131. let left = UnnamedField(NamedField { data: [23; 3] });
  132. let right = UnnamedField(NamedField { data: [23; 3] });
  133. assert!(bool::from(left.ct_eq(&right)));
  134. assert_eq!(left, right);
  135. }
  136. #[rstest]
  137. #[case([0, 1, 0])]
  138. #[case([0, 1, 1])]
  139. #[case([1, 1, 1])]
  140. fn ct_not_eq_unnamed_field(#[case] right: [u8; 3]) {
  141. let left = UnnamedField(NamedField { data: [0; 3] });
  142. let right = UnnamedField(NamedField { data: right });
  143. assert!(bool::from(!left.ct_eq(&right)));
  144. assert_ne!(left, right);
  145. }
  146. #[test]
  147. fn ct_eq_unnamed_fields() {
  148. let left = UnnamedFields(109, 2, 35);
  149. let right = UnnamedFields(109, 2, 35);
  150. assert!(bool::from(left.ct_eq(&right)));
  151. assert_eq!(left, right);
  152. }
  153. #[rstest]
  154. #[case((0, 0, 1))]
  155. #[case((0, 1, 0))]
  156. #[case((0, 1, 1))]
  157. #[case((1, 0, 0))]
  158. #[case((1, 0, 1))]
  159. #[case((1, 1, 0))]
  160. #[case((1, 1, 1))]
  161. fn ct_not_eq_unnamed_fields(#[case] right: (u32, u64, u32)) {
  162. let left = UnnamedFields(0, 0, 0);
  163. let right = UnnamedFields(right.0, right.1, right.2);
  164. assert!(bool::from(!left.ct_eq(&right)));
  165. assert_ne!(left, right);
  166. }
  167. #[test]
  168. fn ct_eq_named_field_with_inner_unnamed_field() {
  169. let left = NamedFieldWithInnerUnnamedField {
  170. data: UnnamedField(NamedField { data: [23; 3] }),
  171. };
  172. let right = NamedFieldWithInnerUnnamedField {
  173. data: UnnamedField(NamedField { data: [23; 3] }),
  174. };
  175. assert!(bool::from(left.ct_eq(&right)));
  176. assert_eq!(left, right);
  177. }
  178. #[rstest]
  179. #[case([0, 0, 1])]
  180. #[case([0, 1, 1])]
  181. #[case([1, 1, 1])]
  182. fn ct_not_eq_named_field_with_inner_unnamed_field(#[case] right: [u8; 3]) {
  183. let left = NamedFieldWithInnerUnnamedField {
  184. data: UnnamedField(NamedField { data: [0; 3] }),
  185. };
  186. let right = NamedFieldWithInnerUnnamedField {
  187. data: UnnamedField(NamedField { data: right }),
  188. };
  189. assert!(bool::from(!left.ct_eq(&right)));
  190. assert_ne!(left, right);
  191. }
  192. #[test]
  193. fn ct_eq_named_field_with_inner_unnamed_fields() {
  194. let left = NamedFieldWithInnerUnnamedFields {
  195. data: UnnamedFields(109, 2, 35),
  196. };
  197. let right = NamedFieldWithInnerUnnamedFields {
  198. data: UnnamedFields(109, 2, 35),
  199. };
  200. assert!(bool::from(left.ct_eq(&right)));
  201. assert_eq!(left, right);
  202. }
  203. #[rstest]
  204. #[case((0, 0, 1))]
  205. #[case((0, 1, 0))]
  206. #[case((0, 1, 1))]
  207. #[case((1, 0, 0))]
  208. #[case((1, 0, 1))]
  209. #[case((1, 1, 0))]
  210. #[case((1, 1, 1))]
  211. fn ct_not_eq_named_field_with_inner_unnamed_fields(#[case] right: (u32, u64, u32)) {
  212. let left = NamedFieldWithInnerUnnamedFields {
  213. data: UnnamedFields(0, 0, 0),
  214. };
  215. let right = NamedFieldWithInnerUnnamedFields {
  216. data: UnnamedFields(right.0, right.1, right.2),
  217. };
  218. assert!(bool::from(!left.ct_eq(&right)));
  219. assert_ne!(left, right);
  220. }
  221. #[test]
  222. fn ct_eq_named_field_with_inner_unnamed_array_field() {
  223. let left = NamedFieldWithInnerUnnamedArrayField {
  224. data: UnnamedArrayField([75; 3]),
  225. };
  226. let right = NamedFieldWithInnerUnnamedArrayField {
  227. data: UnnamedArrayField([75; 3]),
  228. };
  229. assert!(bool::from(left.ct_eq(&right)));
  230. assert_eq!(left, right);
  231. }
  232. #[rstest]
  233. #[case([0, 0, 1])]
  234. #[case([1, 1, 0])]
  235. #[case([1, 1, 1])]
  236. fn ct_not_eq_named_field_with_inner_unnamed_array_field(#[case] right: [u8; 3]) {
  237. let left = NamedFieldWithInnerUnnamedArrayField {
  238. data: UnnamedArrayField([0; 3]),
  239. };
  240. let right = NamedFieldWithInnerUnnamedArrayField {
  241. data: UnnamedArrayField(right),
  242. };
  243. assert!(bool::from(!left.ct_eq(&right)));
  244. assert_ne!(left, right);
  245. }
  246. #[test]
  247. fn ct_eq_named_fields_with_inner_unnamed_field() {
  248. let left = NamedFieldsWithInnerUnnamedField {
  249. data1: UnnamedField(NamedField { data: [23; 3] }),
  250. data2: 3,
  251. };
  252. let right = NamedFieldsWithInnerUnnamedField {
  253. data1: UnnamedField(NamedField { data: [23; 3] }),
  254. data2: 3,
  255. };
  256. assert!(bool::from(left.ct_eq(&right)));
  257. assert_eq!(left, right);
  258. }
  259. #[rstest]
  260. #[case(([0, 0, 0], 1))]
  261. #[case(([1, 0, 1], 0))]
  262. #[case(([1, 1, 0], 1))]
  263. fn ct_not_eq_named_fields_with_inner_unnamed_field(#[case] right: ([u8; 3], u64)) {
  264. let left = NamedFieldsWithInnerUnnamedField {
  265. data1: UnnamedField(NamedField { data: [0; 3] }),
  266. data2: 0,
  267. };
  268. let right = NamedFieldsWithInnerUnnamedField {
  269. data1: UnnamedField(NamedField { data: right.0 }),
  270. data2: right.1,
  271. };
  272. assert!(bool::from(!left.ct_eq(&right)));
  273. assert_ne!(left, right);
  274. }
  275. #[test]
  276. fn ct_eq_named_fields_with_inner_unnamed_fields() {
  277. let left = NamedFieldsWithInnerUnnamedFields {
  278. data1: UnnamedFields(109, 2, 35),
  279. data2: 8,
  280. };
  281. let right = NamedFieldsWithInnerUnnamedFields {
  282. data1: UnnamedFields(109, 2, 35),
  283. data2: 8,
  284. };
  285. assert!(bool::from(left.ct_eq(&right)));
  286. assert_eq!(left, right);
  287. }
  288. #[rstest]
  289. #[case((0, 0, 0, 1))]
  290. #[case((0, 1, 0, 0))]
  291. #[case((1, 1, 1, 0))]
  292. #[case((1, 1, 0, 1))]
  293. fn ct_not_eq_named_fields_with_inner_unnamed_fields(#[case] right: (u32, u64, u32, u64)) {
  294. let left = NamedFieldsWithInnerUnnamedFields {
  295. data1: UnnamedFields(0, 0, 0),
  296. data2: 0,
  297. };
  298. let right = NamedFieldsWithInnerUnnamedFields {
  299. data1: UnnamedFields(right.0, right.1, right.2),
  300. data2: right.3,
  301. };
  302. assert!(bool::from(!left.ct_eq(&right)));
  303. assert_ne!(left, right);
  304. }
  305. #[test]
  306. fn ct_eq_named_fields_with_inner_unnamed_array_field() {
  307. let left = NamedFieldsWithInnerUnnamedArrayField {
  308. data1: UnnamedArrayField([75; 3]),
  309. data2: 5,
  310. };
  311. let right = NamedFieldsWithInnerUnnamedArrayField {
  312. data1: UnnamedArrayField([75; 3]),
  313. data2: 5,
  314. };
  315. assert!(bool::from(left.ct_eq(&right)));
  316. assert_eq!(left, right);
  317. }
  318. #[rstest]
  319. #[case(([0, 0, 1], 0))]
  320. #[case(([0, 0, 0], 1))]
  321. #[case(([0, 1, 1], 1))]
  322. fn ct_not_eq_named_fields_with_inner_unnamed_array_field(#[case] right: ([u8; 3], u64)) {
  323. let left = NamedFieldsWithInnerUnnamedArrayField {
  324. data1: UnnamedArrayField([0; 3]),
  325. data2: 0,
  326. };
  327. let right = NamedFieldsWithInnerUnnamedArrayField {
  328. data1: UnnamedArrayField(right.0),
  329. data2: right.1,
  330. };
  331. assert!(bool::from(!left.ct_eq(&right)));
  332. assert_ne!(left, right);
  333. }
  334. #[test]
  335. fn ct_eq_named_fields_borrowed() {
  336. let left = NamedFieldsBorrowed {
  337. data1: &[75; 3],
  338. data2: 5,
  339. };
  340. let right = NamedFieldsBorrowed {
  341. data1: &[75; 3],
  342. data2: 5,
  343. };
  344. assert!(bool::from(left.ct_eq(&right)));
  345. assert_eq!(left, right);
  346. }
  347. #[rstest]
  348. #[case(([0, 0, 0], 1))]
  349. #[case(([0, 0, 1], 0))]
  350. #[case(([1, 1, 1], 1))]
  351. fn ct_not_eq_named_fields_borrowed(#[case] right: ([u8; 3], u64)) {
  352. let left = NamedFieldsBorrowed {
  353. data1: &[0; 3],
  354. data2: 0,
  355. };
  356. let right = NamedFieldsBorrowed {
  357. data1: &right.0,
  358. data2: right.1,
  359. };
  360. assert!(bool::from(!left.ct_eq(&right)));
  361. assert_ne!(left, right);
  362. }
  363. #[test]
  364. fn ct_eq_named_fields_multiple_borrowed() {
  365. let left = NamedFieldsMultipleBorrowed {
  366. data1: &[75; 3],
  367. data2: &[38; 3],
  368. };
  369. let right = NamedFieldsMultipleBorrowed {
  370. data1: &[75; 3],
  371. data2: &[38; 3],
  372. };
  373. assert!(bool::from(left.ct_eq(&right)));
  374. assert_eq!(left, right);
  375. }
  376. #[rstest]
  377. #[case(([0, 0, 1], [0, 0, 0]))]
  378. #[case(([0, 0, 0], [0, 1, 1]))]
  379. #[case(([1, 1, 1], [1, 0, 0]))]
  380. fn ct_not_eq_named_fields_multiple_borrowed(#[case] right: ([u8; 3], [u8; 3])) {
  381. let left = NamedFieldsMultipleBorrowed {
  382. data1: &[0; 3],
  383. data2: &[0; 3],
  384. };
  385. let right = NamedFieldsMultipleBorrowed {
  386. data1: &right.0,
  387. data2: &right.1,
  388. };
  389. assert!(bool::from(!left.ct_eq(&right)));
  390. assert_ne!(left, right);
  391. }
  392. }