| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 12 |
|
| 13 |
|
| 14 |
|
| 15 |
|
| 16 |
|
| 17 |
|
| 18 |
|
| 19 |
|
| 20 |
|
| 21 |
|
| 22 |
use std::fs; |
| 23 |
use std::path::{Path, PathBuf}; |
| 24 |
|
| 25 |
|
| 26 |
|
| 27 |
fn reads_raw_samples(line: &str) -> bool { |
| 28 |
const NEEDLE: &str = "FROM samples"; |
| 29 |
let mut idx = 0; |
| 30 |
while let Some(pos) = line[idx..].find(NEEDLE) { |
| 31 |
let after = idx + pos + NEEDLE.len(); |
| 32 |
let boundary = line.as_bytes().get(after); |
| 33 |
let is_word = boundary.is_some_and(|&c| c.is_ascii_alphanumeric() || c == b'_'); |
| 34 |
if !is_word { |
| 35 |
return true; |
| 36 |
} |
| 37 |
idx = after; |
| 38 |
} |
| 39 |
false |
| 40 |
} |
| 41 |
|
| 42 |
#[test] |
| 43 |
fn tombstone_filter_seal() { |
| 44 |
let src = Path::new(env!("CARGO_MANIFEST_DIR")).join("src"); |
| 45 |
let mut stack = vec![src]; |
| 46 |
let mut violations: Vec<String> = Vec::new(); |
| 47 |
|
| 48 |
while let Some(dir) = stack.pop() { |
| 49 |
for entry in fs::read_dir(&dir).unwrap() { |
| 50 |
let path: PathBuf = entry.unwrap().path(); |
| 51 |
if path.is_dir() { |
| 52 |
stack.push(path); |
| 53 |
continue; |
| 54 |
} |
| 55 |
if path.extension().and_then(|e| e.to_str()) != Some("rs") { |
| 56 |
continue; |
| 57 |
} |
| 58 |
let text = fs::read_to_string(&path).unwrap(); |
| 59 |
let lines: Vec<&str> = text.lines().collect(); |
| 60 |
|
| 61 |
let end = lines |
| 62 |
.iter() |
| 63 |
.position(|l| l.contains("#[cfg(test)]")) |
| 64 |
.unwrap_or(lines.len()); |
| 65 |
|
| 66 |
for (i, line) in lines[..end].iter().enumerate() { |
| 67 |
if !reads_raw_samples(line) || line.contains("DELETE FROM samples") { |
| 68 |
continue; |
| 69 |
} |
| 70 |
let lo = i.saturating_sub(3); |
| 71 |
let window = lines[lo..=i].join("\n"); |
| 72 |
if window.contains("tombstone-ok") || window.contains("CREATE VIEW") { |
| 73 |
continue; |
| 74 |
} |
| 75 |
let rel = path |
| 76 |
.strip_prefix(env!("CARGO_MANIFEST_DIR")) |
| 77 |
.unwrap_or(&path); |
| 78 |
violations.push(format!("{}:{} {}", rel.display(), i + 1, line.trim())); |
| 79 |
} |
| 80 |
} |
| 81 |
} |
| 82 |
|
| 83 |
assert!( |
| 84 |
violations.is_empty(), |
| 85 |
"CHRONIC #2 seal: raw `FROM samples` read(s) without `live_samples` or a \ |
| 86 |
`tombstone-ok` justification:\n {}\n\nRoute visible-sample reads through \ |
| 87 |
`FROM live_samples`, or add a `tombstone-ok: <reason>` comment within 3 \ |
| 88 |
lines if the raw access is intentional (point-lookup, tombstone sweep).", |
| 89 |
violations.join("\n ") |
| 90 |
); |
| 91 |
} |
| 92 |
|