cbh_model 0.0.3

Implementation crate for cargo-bench-history - do not reference directly
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
//! Comparability: deciding which runs may be compared to each other, and how the
//! storage is partitioned so that only comparable runs share a series.
//!
//! The guiding rule (see the *Comparability & storage partitioning* section of
//! `DESIGN.md`) is to partition only by what makes results *fundamentally*
//! incomparable — project, engine, target triple, and (for hardware-dependent
//! engines) a machine key — and to record everything else as metadata so its
//! effect stays visible in the timeline.

use std::fmt;

use serde::Serialize;

use super::constants::{OBJECTS_SEGMENT, STORAGE_VERSION};

/// A benchmark engine, distinguished by whether its results depend on hardware.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Engine {
    /// Criterion wall-clock benchmarks: hardware-dependent and noisy.
    Criterion,
    /// Callgrind (via Gungraun) instruction counts: simulated, hardware-independent.
    Callgrind,
    /// `alloc_tracker` allocation counts and bytes: hardware-independent but not
    /// deterministic — warmup and buffer-resize allocations jitter the per-iteration
    /// figure, which is amortized over a Criterion-chosen iteration count.
    AllocTracker,
    /// `all_the_time` processor-time measurements: hardware-dependent and noisy.
    AllTheTime,
}

impl Engine {
    /// Every supported engine, in a stable order used to inject the combined
    /// benchmark environment and to harvest each engine's output tree after the
    /// single `cargo bench` invocation.
    pub const ALL: [Self; 4] = [
        Self::Callgrind,
        Self::Criterion,
        Self::AllocTracker,
        Self::AllTheTime,
    ];

    /// The stable lowercase identifier used in storage paths and config keys.
    #[must_use]
    pub fn as_str(self) -> &'static str {
        match self {
            Self::Criterion => "criterion",
            Self::Callgrind => "callgrind",
            Self::AllocTracker => "alloc_tracker",
            Self::AllTheTime => "all_the_time",
        }
    }

    /// Parses an [`Engine`] from its stable lowercase identifier.
    #[must_use]
    pub fn from_name(name: &str) -> Option<Self> {
        match name {
            "criterion" => Some(Self::Criterion),
            "callgrind" => Some(Self::Callgrind),
            "alloc_tracker" => Some(Self::AllocTracker),
            "all_the_time" => Some(Self::AllTheTime),
            _ => None,
        }
    }

    /// Whether results from this engine depend on the host hardware.
    ///
    /// Hardware-dependent engines require a machine key in their partition;
    /// hardware-independent ones use the literal `synthetic` instead. Allocation
    /// counts and bytes are a property of the code, not the machine, so
    /// `alloc_tracker` is hardware-independent; processor time obviously is not.
    #[must_use]
    pub fn is_hardware_dependent(self) -> bool {
        match self {
            Self::Criterion | Self::AllTheTime => true,
            Self::Callgrind | Self::AllocTracker => false,
        }
    }
}

impl fmt::Display for Engine {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

/// The set of factors that must match for two runs in a project to share a series.
///
/// A discriminant set is `engine / target_triple / machine`. Within a single
/// project all runs that share a discriminant set are comparable; runs in
/// different sets (a different engine, target triple, or machine key) never share
/// a series. It is both the value `run` writes under and the value `analyze` reads
/// back (parsed from a storage key), so the same type drives both sides.
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct DiscriminantSet {
    /// Engine identifier (for example, `callgrind`).
    pub engine: String,
    /// Resolved target triple the run was recorded under.
    pub target_triple: String,
    /// Machine key (`synthetic` for hardware-independent engines).
    pub machine_key: String,
}

impl DiscriminantSet {
    /// Creates a discriminant set, sanitizing the path-forming components.
    ///
    /// `target_triple` and `machine_key` are sanitized so that every segment is a
    /// single, well-formed path component: any character that is not ASCII
    /// alphanumeric, `-`, `_`, or `.` is replaced with `_`, and a segment that
    /// would otherwise be empty or consist only of dots becomes `_`. This keeps a
    /// stray `/` (or other surprising input) from silently splitting a storage key
    /// into the wrong number of segments. A `None` machine key becomes the literal
    /// `synthetic`, used for hardware-independent engines.
    #[must_use]
    pub fn new(engine: Engine, target_triple: &str, machine_key: Option<&str>) -> Self {
        Self {
            engine: engine.as_str().to_owned(),
            target_triple: sanitize_segment(target_triple),
            machine_key: machine_key.map_or_else(|| "synthetic".to_owned(), sanitize_segment),
        }
    }

    /// Whether this is a hardware-independent (`synthetic`) set.
    #[must_use]
    pub fn is_synthetic(&self) -> bool {
        self.machine_key == "synthetic"
    }

    /// The storage prefix that all runs in this series share, within `project`.
    ///
    /// Layout:
    /// `{STORAGE_VERSION}/{project}/{OBJECTS_SEGMENT}/{engine}/{target_triple}/{machine|synthetic}`.
    /// The fixed `objects` segment separates the data subtree from a project's
    /// metadata siblings (e.g. the cache-invalidation marker); below this prefix the
    /// history is organized by commit (see [`clean_key`] and [`dirty_key`]) so
    /// `analyze` can resolve a series from git topology.
    ///
    /// [`clean_key`]: Self::clean_key
    /// [`dirty_key`]: Self::dirty_key
    #[must_use]
    pub fn partition_prefix(&self, project: &str) -> String {
        let project = sanitize_segment(project);
        let engine = &self.engine;
        let triple = &self.target_triple;
        let machine_key = &self.machine_key;
        format!("{STORAGE_VERSION}/{project}/{OBJECTS_SEGMENT}/{engine}/{triple}/{machine_key}")
    }

    /// The object key for the canonical (clean working tree) result at `commit`.
    ///
    /// Layout: `{prefix}/{commit}/clean.json`. A clean run is keyed solely by its
    /// commit, so it is deterministic: a second clean run of the same commit maps
    /// to the same key and collides, which the write-once storage detects so `run`
    /// can refuse the duplicate unless an overwrite is explicitly requested.
    ///
    /// `commit` is sanitized so the directory name always forms a single segment.
    #[must_use]
    pub fn clean_key(&self, project: &str, commit: &str) -> String {
        let prefix = self.partition_prefix(project);
        let commit = sanitize_segment(commit);
        format!("{prefix}/{commit}/clean.json")
    }

    /// The object key for a dirty (uncommitted-changes) snapshot at `commit`,
    /// observed at `observation_unix`.
    ///
    /// Layout: `{prefix}/{commit}/dirty-{observation_unix}.json`. Because a dirty
    /// snapshot does not correspond to committed code, it is distinguished by its
    /// observation time rather than by the commit alone, so multiple dirty
    /// snapshots on the same base commit coexist; only two snapshots sharing an
    /// observation second collide.
    ///
    /// `commit` is sanitized so the directory name always forms a single segment.
    #[must_use]
    pub fn dirty_key(&self, project: &str, commit: &str, observation_unix: i64) -> String {
        let prefix = self.partition_prefix(project);
        let commit = sanitize_segment(commit);
        format!("{prefix}/{commit}/dirty-{observation_unix}.json")
    }

    /// The blessing sidecar key for this set's commit directory, issued at
    /// `issued_unix`.
    ///
    /// Layout: `{prefix}/{commit}/bless-{issued_unix}.json`. `commit` is sanitized
    /// so the directory name always forms a single segment.
    #[must_use]
    pub fn bless_key(&self, project: &str, commit: &str, issued_unix: i64) -> String {
        let prefix = self.partition_prefix(project);
        let commit = sanitize_segment(commit);
        format!("{prefix}/{commit}/bless-{issued_unix}.json")
    }

    /// The storage prefix shared by every object recorded at `commit` in this
    /// partition (`{prefix}/{commit}/`), used to enumerate a commit directory.
    ///
    /// `commit` is sanitized so the directory name always forms a single segment.
    #[must_use]
    pub fn commit_prefix(&self, project: &str, commit: &str) -> String {
        let prefix = self.partition_prefix(project);
        let commit = sanitize_segment(commit);
        format!("{prefix}/{commit}/")
    }
}

impl fmt::Display for DiscriminantSet {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}/{}/{}",
            self.engine, self.target_triple, self.machine_key
        )
    }
}

/// The components a storage key decomposes into.
///
/// A storage key references one of three kinds of object in a commit directory:
/// a clean run (`clean.json`), a dirty snapshot (`dirty-<unix>.json`), or a
/// blessing sidecar (`bless-<unix>.json`). The [`file`](Self::file) segment
/// distinguishes them; [`is_dirty`](Self::is_dirty) and
/// [`is_bless`](Self::is_bless) classify it.
///
/// This is the inverse of the key-construction methods above ([`clean_key`],
/// [`dirty_key`], [`bless_key`]): [`parse_key`] recovers this decomposition from a
/// stored object's key so `analyze` can group objects into comparable series.
///
/// [`clean_key`]: DiscriminantSet::clean_key
/// [`dirty_key`]: DiscriminantSet::dirty_key
/// [`bless_key`]: DiscriminantSet::bless_key
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StorageKey {
    /// The (sanitized) project segment.
    pub project: String,
    /// The discriminant set the key belongs to.
    pub set: DiscriminantSet,
    /// The commit directory segment (full commit ID, or `unknown`).
    pub commit: String,
    /// The file segment (`clean.json`, `dirty-<unix>.json`, or `bless-<unix>.json`).
    pub file: String,
}

impl StorageKey {
    /// Whether the key names a dirty (uncommitted-tree) snapshot.
    #[must_use]
    pub fn is_dirty(&self) -> bool {
        self.file.starts_with("dirty-")
    }

    /// Whether the key names a blessing sidecar rather than a stored run.
    #[must_use]
    pub fn is_bless(&self) -> bool {
        self.file.starts_with("bless-")
    }

    /// The blessing sidecar key for this set's commit directory, issued at
    /// `issued_unix`.
    #[must_use]
    pub fn bless_key(&self, issued_unix: i64) -> String {
        self.set.bless_key(&self.project, &self.commit, issued_unix)
    }
}

/// Parses a storage object key into its components.
///
/// Keys have the form
/// `{STORAGE_VERSION}/{project}/{OBJECTS_SEGMENT}/{engine}/{triple}/{machine_key}/{commit}/{file}`
/// — exactly eight non-empty segments, with the fixed `objects` segment directly
/// under the project. Any key that does not match that shape exactly (wrong
/// version, missing `objects` segment, too few or too many segments, or an empty
/// segment) is ignored (returns `None`) rather than misattributed — so a
/// per-project metadata sibling such as the cache-invalidation marker is skipped.
#[must_use]
pub fn parse_key(key: &str) -> Option<StorageKey> {
    let parts: Vec<&str> = key.split('/').collect();
    let [
        version,
        project,
        objects,
        engine,
        target_triple,
        machine_key,
        commit,
        file,
    ] = parts.as_slice()
    else {
        return None;
    };
    if *version != STORAGE_VERSION || *objects != OBJECTS_SEGMENT {
        return None;
    }
    if parts.iter().any(|segment| segment.is_empty()) {
        return None;
    }
    Some(StorageKey {
        project: (*project).to_owned(),
        set: DiscriminantSet {
            engine: (*engine).to_owned(),
            target_triple: (*target_triple).to_owned(),
            machine_key: (*machine_key).to_owned(),
        },
        commit: (*commit).to_owned(),
        file: (*file).to_owned(),
    })
}

/// Replaces every character that is not safe in a single path segment with `_`,
/// mapping an otherwise-empty or all-dots result to `_`.
///
/// "Safe" is the conservative set `[A-Za-z0-9._-]`, which is valid both as a
/// filesystem path component (for local storage) and as an Azure blob name part.
/// Mangling rather than rejecting means the tool never refuses a run merely
/// because its project, triple, or machine key contains an awkward character.
#[must_use]
pub fn sanitize_segment(raw: &str) -> String {
    let mangled: String = raw
        .chars()
        .map(|c| {
            if c.is_ascii_alphanumeric() || matches!(c, '-' | '_' | '.') {
                c
            } else {
                '_'
            }
        })
        .collect();
    if mangled.is_empty() || mangled.chars().all(|c| c == '.') {
        return "_".to_owned();
    }
    mangled
}

#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
    use super::*;

    #[test]
    fn hardware_dependence_matches_engine() {
        assert!(Engine::Criterion.is_hardware_dependent());
        assert!(Engine::AllTheTime.is_hardware_dependent());
        assert!(!Engine::Callgrind.is_hardware_dependent());
        assert!(!Engine::AllocTracker.is_hardware_dependent());
    }

    #[test]
    fn alloc_tracker_uses_a_synthetic_partition() {
        // Allocation counts are a property of the code, not the machine, so
        // `alloc_tracker` carries no machine key.
        let set = DiscriminantSet::new(Engine::AllocTracker, "x86_64-pc-windows-msvc", None);
        assert!(set.is_synthetic());
        assert_eq!(
            set.partition_prefix("folo"),
            "v1/folo/objects/alloc_tracker/x86_64-pc-windows-msvc/synthetic"
        );
    }

    #[test]
    fn all_the_time_partitions_by_machine_key() {
        // Processor time depends on the machine, so `all_the_time` carries a
        // machine fingerprint.
        let set =
            DiscriminantSet::new(Engine::AllTheTime, "x86_64-pc-windows-msvc", Some("abc123"));
        assert_eq!(
            set.partition_prefix("folo"),
            "v1/folo/objects/all_the_time/x86_64-pc-windows-msvc/abc123"
        );
    }

    #[test]
    fn machine_key_appears_in_partition() {
        let set = DiscriminantSet::new(Engine::Criterion, "x86_64-pc-windows-msvc", Some("abc123"));
        assert_eq!(
            set.partition_prefix("folo"),
            "v1/folo/objects/criterion/x86_64-pc-windows-msvc/abc123"
        );
    }

    #[test]
    fn is_synthetic_is_false_for_a_machine_keyed_set() {
        // A machine-dependent engine carries a real fingerprint, so the set is not
        // synthetic even though synthetic sets share the same type.
        let set =
            DiscriminantSet::new(Engine::AllTheTime, "x86_64-pc-windows-msvc", Some("abc123"));
        assert!(!set.is_synthetic());
    }

    #[test]
    fn display_formats_engine_triple_and_machine_key() {
        let set = DiscriminantSet::new(Engine::Criterion, "x86_64-pc-windows-msvc", Some("abc123"));
        assert_eq!(set.to_string(), "criterion/x86_64-pc-windows-msvc/abc123");

        // A synthetic set renders the literal `synthetic` machine segment.
        let synthetic = DiscriminantSet::new(Engine::AllocTracker, "x86_64-pc-windows-msvc", None);
        assert_eq!(
            synthetic.to_string(),
            "alloc_tracker/x86_64-pc-windows-msvc/synthetic"
        );
    }

    #[test]
    fn clean_key_is_named_by_commit() {
        let set = DiscriminantSet::new(Engine::Callgrind, "x86_64-unknown-linux-gnu", None);
        assert_eq!(
            set.clean_key("folo", "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/\
             deadbeefdeadbeefdeadbeefdeadbeefdeadbeef/clean.json"
        );
    }

    #[test]
    fn dirty_key_is_named_by_commit_and_observation_time() {
        let set = DiscriminantSet::new(Engine::Callgrind, "x86_64-unknown-linux-gnu", None);
        assert_eq!(
            set.dirty_key(
                "folo",
                "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
                1_700_000_000
            ),
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/\
             deadbeefdeadbeefdeadbeefdeadbeefdeadbeef/dirty-1700000000.json"
        );
    }

    #[test]
    fn bless_key_targets_the_commit_directory() {
        let set = DiscriminantSet::new(Engine::Callgrind, "x86_64-unknown-linux-gnu", None);
        assert_eq!(
            set.bless_key("folo", "abc123", 1_700_000_000),
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/abc123/bless-1700000000.json"
        );
    }

    #[test]
    fn commit_prefix_enumerates_one_commit_directory() {
        let set = DiscriminantSet::new(Engine::Callgrind, "x86_64-unknown-linux-gnu", None);
        assert_eq!(
            set.commit_prefix("folo", "dead/beef"),
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/dead_beef/"
        );
    }

    #[test]
    fn engine_display_matches_as_str() {
        assert_eq!(Engine::Criterion.to_string(), "criterion");
        assert_eq!(Engine::Callgrind.to_string(), "callgrind");
        assert_eq!(Engine::AllocTracker.to_string(), "alloc_tracker");
        assert_eq!(Engine::AllTheTime.to_string(), "all_the_time");
    }

    #[test]
    fn engine_from_name_roundtrips() {
        for engine in Engine::ALL {
            assert_eq!(Engine::from_name(engine.as_str()), Some(engine));
        }
        assert_eq!(Engine::from_name("dhat"), None);
    }

    #[test]
    fn sanitize_segment_keeps_safe_characters() {
        assert_eq!(
            sanitize_segment("x86_64-unknown-linux-gnu"),
            "x86_64-unknown-linux-gnu"
        );
        assert_eq!(sanitize_segment("my.project-1"), "my.project-1");
    }

    #[test]
    fn sanitize_segment_replaces_separators_and_specials() {
        assert_eq!(sanitize_segment("team/app"), "team_app");
        assert_eq!(sanitize_segment(r"team\app"), "team_app");
        assert_eq!(sanitize_segment("weird:name"), "weird_name");
        assert_eq!(sanitize_segment("with space"), "with_space");
        assert_eq!(sanitize_segment("café"), "caf_");
    }

    #[test]
    fn sanitize_segment_maps_empty_and_dot_only_to_underscore() {
        assert_eq!(sanitize_segment(""), "_");
        assert_eq!(sanitize_segment("."), "_");
        assert_eq!(sanitize_segment(".."), "_");
    }

    #[test]
    fn new_sanitizes_partition_components() {
        let set = DiscriminantSet::new(Engine::Criterion, "weird/triple", Some("machine/one"));
        assert_eq!(
            set.partition_prefix("team/app"),
            "v1/team_app/objects/criterion/weird_triple/machine_one"
        );
        // The partition prefix has exactly the six canonical segments.
        assert_eq!(set.partition_prefix("team/app").split('/').count(), 6);
    }

    #[test]
    fn clean_key_sanitizes_the_commit() {
        let set = DiscriminantSet::new(Engine::Callgrind, "x86_64-unknown-linux-gnu", None);
        let object = set.clean_key("folo", "dead/beef");
        assert_eq!(
            object,
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/dead_beef/clean.json"
        );
        // Exactly the eight canonical key segments survive sanitization.
        assert_eq!(object.split('/').count(), 8);
    }

    #[test]
    fn dirty_key_sanitizes_the_commit() {
        let set = DiscriminantSet::new(Engine::Callgrind, "x86_64-unknown-linux-gnu", None);
        let object = set.dirty_key("folo", "dead/beef", 1_700_000_000);
        assert_eq!(
            object,
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/dead_beef/dirty-1700000000.json"
        );
        // Exactly the eight canonical key segments survive sanitization.
        assert_eq!(object.split('/').count(), 8);
    }

    #[test]
    fn parse_key_decomposes_a_clean_key() {
        let parsed = parse_key(
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/abc123/clean.json",
        )
        .unwrap();
        assert_eq!(parsed.project, "folo");
        assert_eq!(parsed.set.engine, "callgrind");
        assert_eq!(parsed.set.target_triple, "x86_64-unknown-linux-gnu");
        assert_eq!(parsed.set.machine_key, "synthetic");
        assert_eq!(parsed.commit, "abc123");
        assert_eq!(parsed.file, "clean.json");
        assert!(!parsed.is_dirty());
        assert!(!parsed.is_bless());
    }

    #[test]
    fn parse_key_recognizes_a_dirty_snapshot() {
        let parsed = parse_key(
            "v1/folo/objects/criterion/x86_64-pc-windows-msvc/m1/abc123/dirty-1700000000.json",
        )
        .unwrap();
        assert!(parsed.is_dirty());
        assert_eq!(parsed.set.target_triple, "x86_64-pc-windows-msvc");
        assert_eq!(parsed.set.machine_key, "m1");
    }

    #[test]
    fn parse_key_recognizes_a_blessing_sidecar() {
        let parsed = parse_key(
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/abc123/bless-1700000000.json",
        )
        .unwrap();
        assert!(parsed.is_bless());
        assert!(!parsed.is_dirty());
        assert_eq!(parsed.commit, "abc123");
    }

    #[test]
    fn bless_key_targets_the_sets_commit_directory() {
        let parsed = parse_key(
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/abc123/clean.json",
        )
        .unwrap();
        assert_eq!(
            parsed.bless_key(1_700_000_000),
            "v1/folo/objects/callgrind/x86_64-unknown-linux-gnu/synthetic/abc123/bless-1700000000.json"
        );
    }

    #[test]
    fn parse_key_rejects_malformed_keys() {
        // Wrong (unrecognized) storage version, even with an otherwise valid shape.
        assert!(parse_key("v2/folo/objects/callgrind/t/m/c/f.json").is_none());
        // Missing the fixed `objects` segment (the pre-objects v1 shape).
        assert!(parse_key("v1/folo/callgrind/t/m/c/f.json").is_none());
        // A different literal in the objects position.
        assert!(parse_key("v1/folo/data/callgrind/t/m/c/f.json").is_none());
        // Structurally malformed keys at the recognized version.
        assert!(parse_key("v1/folo/objects/callgrind/t/m/f.json").is_none());
        assert!(parse_key("v1/folo/objects/callgrind/t/m/c/sub/f.json").is_none());
        assert!(parse_key("v1/folo/objects/callgrind/t//c/f.json").is_none());
        assert!(parse_key("v1/folo/objects/callgrind/t/m/c/").is_none());
    }
}