supercov_engine/
rust_test_context.rs1use std::collections::{BTreeMap, BTreeSet};
4
5const DOMAIN: &[u8] = b"supercov-rust-test-v1\0";
6const OFFSET_BASIS: u64 = 0xcbf2_9ce4_8422_2325;
7const PRIME: u64 = 0x0000_0100_0000_01b3;
8const RESERVED_REMAP: u64 = 0xa5a5_a5a5_a5a5_a5a5;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum RustTestContextError {
12 InvalidTestName,
13 DuplicateTest(String),
14 Collision {
15 context_id: u64,
16 first: String,
17 second: String,
18 },
19}
20
21impl std::fmt::Display for RustTestContextError {
22 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 match self {
24 Self::InvalidTestName => write!(formatter, "Rust test name is empty or contains NUL"),
25 Self::DuplicateTest(test) => write!(formatter, "duplicate Rust test identity {test}"),
26 Self::Collision {
27 context_id,
28 first,
29 second,
30 } => write!(
31 formatter,
32 "Rust test context {context_id:016x} collides between {first} and {second}"
33 ),
34 }
35 }
36}
37
38impl std::error::Error for RustTestContextError {}
39
40pub fn rust_test_context_id(test: &str) -> Result<u64, RustTestContextError> {
41 if test.is_empty() || test.contains('\0') {
42 return Err(RustTestContextError::InvalidTestName);
43 }
44 let mut value = OFFSET_BASIS;
45 for byte in DOMAIN.iter().copied().chain(test.bytes()) {
46 value ^= u64::from(byte);
47 value = value.wrapping_mul(PRIME);
48 }
49 Ok(if matches!(value, 0 | u64::MAX) {
50 value ^ RESERVED_REMAP
51 } else {
52 value
53 })
54}
55
56fn preflight_with(
57 tests: impl IntoIterator<Item = String>,
58 derive: impl Fn(&str) -> Result<u64, RustTestContextError>,
59) -> Result<BTreeMap<String, u64>, RustTestContextError> {
60 let mut names = BTreeSet::new();
61 let mut owners = BTreeMap::<u64, String>::new();
62 let mut contexts = BTreeMap::new();
63 for test in tests {
64 if !names.insert(test.clone()) {
65 return Err(RustTestContextError::DuplicateTest(test));
66 }
67 let context_id = derive(&test)?;
68 if let Some(first) = owners.insert(context_id, test.clone()) {
69 return Err(RustTestContextError::Collision {
70 context_id,
71 first,
72 second: test,
73 });
74 }
75 contexts.insert(test, context_id);
76 }
77 Ok(contexts)
78}
79
80pub fn preflight_rust_test_contexts(
81 tests: impl IntoIterator<Item = String>,
82) -> Result<BTreeMap<String, u64>, RustTestContextError> {
83 preflight_with(tests, rust_test_context_id)
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn derivation_matches_the_compiler_contract_and_handles_unicode() {
92 assert_eq!(
93 rust_test_context_id("tests::child_context").unwrap(),
94 0x4a50_d37c_b3b7_f06f
95 );
96 assert_ne!(
97 rust_test_context_id("tests::δ").unwrap(),
98 rust_test_context_id("tests::d").unwrap()
99 );
100 assert!(matches!(
101 rust_test_context_id(""),
102 Err(RustTestContextError::InvalidTestName)
103 ));
104 }
105
106 #[test]
107 fn supervisor_rejects_duplicates_and_hash_collisions_before_launch() {
108 assert!(matches!(
109 preflight_rust_test_contexts(["same".into(), "same".into()]),
110 Err(RustTestContextError::DuplicateTest(_))
111 ));
112 assert!(matches!(
113 preflight_with(["first".into(), "second".into()], |_| Ok(7)),
114 Err(RustTestContextError::Collision { context_id: 7, .. })
115 ));
116 let contexts = preflight_rust_test_contexts(["second".into(), "first".into()]).unwrap();
117 assert_eq!(
118 contexts.keys().cloned().collect::<Vec<_>>(),
119 ["first", "second"]
120 );
121 }
122}