zshrs 0.11.41

The first compiled Unix shell — bytecode VM, worker pool, AOP intercept, Rkyv caching
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
//! `patchlevel.h` port — upstream zsh patch-level identifier.
//!
//! Port of `Src/patchlevel.h`. The C header defines a single
//! preprocessor constant `ZSH_PATCHLEVEL` that names the upstream
//! source revision the rest of the tree was built from. It's read
//! by `init.c` to populate the `$ZSH_PATCHLEVEL` shell parameter
//! and by the `zsh --version` startup-banner code.
//!
//! C source: 1 `#define`, 0 structs/enums/ported.

/// Port of `#define ZSH_PATCHLEVEL` from `Src/patchlevel.h:1`.
///
/// The upstream source-revision tag the C tree was generated from.
/// Format follows the convention `zsh-MAJOR.MINOR.PATCH-N-gHASH`
/// (where the trailing `-N-gHASH` is appended by `git describe`
/// during the upstream release process).
///
/// Track the same `zsh-5.9.1-0-g0e0d4ea` patchlevel that the user's
/// installed Homebrew zsh 5.9.1 reports so feature-detect / bug-report
/// scripts that compare `$ZSH_PATCHLEVEL` against the local install
/// match. Bug #444.
pub const ZSH_PATCHLEVEL: &str = "zsh-5.9.1-0-g0e0d4ea"; // matches Homebrew zsh 5.9.1 (bug #444)

/// Port of `#define ZSH_VERSION` (generated by `Src/Makemod:544`).
///
/// C body: `echo '#define ZSH_VERSION "'$(VERSION)'"' > $@`
/// — the build glue writes `VERSION` from `Config/version.mk` into
/// a generated header that init.c reads.
///
/// Upstream `Config/version.mk` ships `VERSION=5.9.0.3-test` (the
/// in-development snapshot tag), but every shipped zsh binary
/// (Homebrew, distro packages, etc.) reports the cleaned MAJOR.MINOR
/// or MAJOR.MINOR.PATCH form — the user's Homebrew install reports
/// `5.9.1`. Scripts in the wild gate on the release form
/// (`[[ $ZSH_VERSION = 5.9.* ]]`, `IFS=. read -r maj min pat <<<
/// $ZSH_VERSION` expecting three parts, `${ZSH_VERSION%%.*-*}` etc.)
/// — bug #442 in docs/BUGS.md.
///
/// Report the same `5.9.1` clean form as the installed Homebrew
/// binary so feature-detect scripts that compare against the local
/// zsh install match. zshrs-specific identity lives in `ZSHRS_VERSION`
/// below; the full upstream snapshot tag stays in `ZSH_PATCHLEVEL`
/// above.
///
/// Read by `params.rs::createparamtable` (c:966 — `setsparam("ZSH_VERSION", ZSH_VERSION)`)
/// and by the `--version` startup banner.
pub const ZSH_VERSION: &str = "5.9.1"; // matches Homebrew zsh (bug #442)

/// zshrs-specific identity. C zsh has no equivalent. Surfaced as the
/// `$ZSHRS_VERSION` parameter and the `--version` banner so scripts
/// that need to distinguish zshrs from upstream zsh have a clean
/// detection point (vs. clobbering `$ZSH_VERSION` with a `-test`
/// suffix).
pub const ZSHRS_VERSION: &str = "5.9.0.3-test"; // snapshot tag for zshrs identity

#[cfg(test)]
mod tests {
    use super::*;

    /// `$ZSH_PATCHLEVEL` is read at params.rs:1690 — pin both the
    /// snapshot value and its `zsh-MAJOR.MINOR-N-gHASH` shape. If
    /// upstream tags drop the `-g<hash>` suffix this fails — that's
    /// the git-describe contract zsh's version-reporting code relies
    /// on.
    #[test]
    fn patchlevel_value_and_git_describe_shape() {
        let _g = crate::test_util::global_state_lock();
        assert_eq!(ZSH_PATCHLEVEL, "zsh-5.9.1-0-g0e0d4ea");
        assert!(
            ZSH_PATCHLEVEL.contains("-g"),
            "git-describe `-g<hash>` suffix is load-bearing"
        );
    }

    /// `$ZSH_VERSION` is read at params.rs `createparamtable` (c:966)
    /// and by the `--version` startup banner (Src/init.c:436). Pin
    /// the clean release form so script-side gates
    /// (`[[ $ZSH_VERSION = 5.9 ]]`, MAJOR.MINOR parsing) match shipped
    /// zsh — bug #73 in docs/BUGS.md. The full snapshot tag stays in
    /// `ZSHRS_VERSION` below + `ZSH_PATCHLEVEL` above.
    #[test]
    fn zsh_version_matches_upstream_config_version() {
        let _g = crate::test_util::global_state_lock();
        assert_eq!(ZSH_VERSION, "5.9.1");
        assert_eq!(ZSHRS_VERSION, "5.9.0.3-test");
        // Shape: MAJOR.MINOR[.PATCH[.SUB][-tag]]
        let major = ZSH_VERSION.split('.').next().unwrap_or("");
        assert!(
            major.chars().all(|c| c.is_ascii_digit()) && !major.is_empty(),
            "ZSH_VERSION must start with numeric MAJOR (got {ZSH_VERSION:?})"
        );
    }

    // ─── zsh-corpus pins for version constants ──────────────────────

    /// `ZSH_PATCHLEVEL` is non-empty.
    #[test]
    fn patchlevel_corpus_nonempty() {
        assert!(!ZSH_PATCHLEVEL.is_empty());
    }

    /// `ZSH_PATCHLEVEL` starts with "zsh-" prefix.
    #[test]
    fn patchlevel_corpus_zsh_prefix() {
        assert!(
            ZSH_PATCHLEVEL.starts_with("zsh-"),
            "patchlevel must start with `zsh-`, got {ZSH_PATCHLEVEL:?}"
        );
    }

    /// `ZSH_VERSION` follows MAJOR.MINOR format with at least one dot.
    #[test]
    fn patchlevel_corpus_version_has_dot() {
        assert!(
            ZSH_VERSION.contains('.'),
            "ZSH_VERSION must contain a dot (MAJOR.MINOR), got {ZSH_VERSION:?}"
        );
    }

    /// `ZSH_VERSION` MAJOR is "5" (current zsh series).
    #[test]
    fn patchlevel_corpus_version_major_is_five() {
        let major = ZSH_VERSION.split('.').next().unwrap();
        assert_eq!(major, "5", "current zsh is in the 5.x series");
    }

    /// `ZSH_VERSION` MINOR is parseable as integer.
    #[test]
    fn patchlevel_corpus_version_minor_parses() {
        let parts: Vec<&str> = ZSH_VERSION.split('.').collect();
        assert!(parts.len() >= 2, "must have MAJOR.MINOR");
        let minor: Result<i32, _> = parts[1].parse();
        assert!(minor.is_ok(), "MINOR must parse: {parts:?}");
    }

    /// Constants are distinct (patchlevel != version since patchlevel
    /// has the `-N-gHASH` tail).
    #[test]
    fn patchlevel_corpus_patchlevel_differs_from_version() {
        assert_ne!(ZSH_PATCHLEVEL, ZSH_VERSION);
    }

    // ═══════════════════════════════════════════════════════════════════
    // Additional C-parity tests for Src/patchlevel.h constants.
    // ═══════════════════════════════════════════════════════════════════

    /// ZSH_PATCHLEVEL has ≥ 4 dash-separated segments (zsh-VER-N-gHASH).
    #[test]
    fn patchlevel_has_four_dash_segments() {
        let parts: Vec<&str> = ZSH_PATCHLEVEL.split('-').collect();
        assert!(
            parts.len() >= 4,
            "patchlevel must have ≥ 4 dash segments, got {:?}",
            parts
        );
    }

    /// ZSH_PATCHLEVEL hash segment starts with 'g' (git-describe).
    #[test]
    fn patchlevel_hash_starts_with_g() {
        let last = ZSH_PATCHLEVEL.rsplit('-').next().unwrap_or("");
        assert!(
            last.starts_with('g'),
            "last segment {:?} must start with 'g'",
            last
        );
    }

    /// ZSH_PATCHLEVEL commit-count segment is numeric.
    #[test]
    fn patchlevel_commit_count_is_numeric() {
        let parts: Vec<&str> = ZSH_PATCHLEVEL.split('-').collect();
        if parts.len() >= 4 {
            let count_part = parts[2];
            let parsed: Result<i32, _> = count_part.parse();
            assert!(parsed.is_ok(), "commit-count {:?} must parse", count_part);
        }
    }

    /// ZSH_VERSION has no spaces.
    #[test]
    fn zsh_version_no_spaces() {
        assert!(!ZSH_VERSION.contains(' '));
    }

    /// ZSH_PATCHLEVEL has no spaces.
    #[test]
    fn zsh_patchlevel_no_spaces() {
        assert!(!ZSH_PATCHLEVEL.contains(' '));
    }

    /// Both constants are ASCII (parse-safe across all locales).
    #[test]
    fn version_strings_are_ascii() {
        assert!(ZSH_VERSION.is_ascii());
        assert!(ZSH_PATCHLEVEL.is_ascii());
    }

    /// Both have no trailing whitespace.
    #[test]
    fn version_strings_no_trailing_ws() {
        assert_eq!(ZSH_VERSION.trim_end(), ZSH_VERSION);
        assert_eq!(ZSH_PATCHLEVEL.trim_end(), ZSH_PATCHLEVEL);
    }

    /// MAJOR.MINOR from ZSH_VERSION appears inside ZSH_PATCHLEVEL.
    #[test]
    fn patchlevel_contains_major_minor_from_version() {
        let mm: String = ZSH_VERSION.split('.').take(2).collect::<Vec<_>>().join(".");
        assert!(
            ZSH_PATCHLEVEL.contains(&mm),
            "patchlevel {:?} must contain {}",
            ZSH_PATCHLEVEL,
            mm
        );
    }

    // ═══════════════════════════════════════════════════════════════════
    // Additional C-parity tests for Src/patchlevel.h + Config/version.mk.
    // ═══════════════════════════════════════════════════════════════════

    /// ZSH_PATCHLEVEL hash after 'g' is a hex commit prefix.
    #[test]
    fn patchlevel_hash_after_g_is_hex() {
        let last = ZSH_PATCHLEVEL.rsplit('-').next().unwrap_or("");
        let hash = last.trim_start_matches('g');
        assert!(!hash.is_empty(), "hash must be non-empty after 'g'");
        assert!(
            hash.chars().all(|c| c.is_ascii_hexdigit()),
            "git-describe hash {:?} must be hex",
            hash
        );
    }

    /// ZSH_PATCHLEVEL hash prefix length is reasonable (≥7 for git short SHA).
    #[test]
    fn patchlevel_hash_short_sha_length() {
        let last = ZSH_PATCHLEVEL.rsplit('-').next().unwrap_or("");
        let hash = last.trim_start_matches('g');
        assert!(
            hash.len() >= 7 && hash.len() <= 40,
            "git short SHA must be 7-40 chars, got {} ({:?})",
            hash.len(),
            hash
        );
    }

    /// ZSH_PATCHLEVEL commit count is non-negative (no negative numbers).
    #[test]
    fn patchlevel_commit_count_non_negative() {
        let parts: Vec<&str> = ZSH_PATCHLEVEL.split('-').collect();
        if parts.len() >= 4 {
            let count: i32 = parts[2].parse().unwrap_or(-1);
            assert!(count >= 0, "commit count must be non-negative: {}", count);
        }
    }

    /// ZSH_VERSION components all parse as numeric (except possible `-tag` tail).
    #[test]
    fn zsh_version_components_numeric_until_tag() {
        let no_tag = ZSH_VERSION.split('-').next().unwrap_or("");
        for (i, comp) in no_tag.split('.').enumerate() {
            let parsed: Result<u32, _> = comp.parse();
            assert!(
                parsed.is_ok(),
                "ZSH_VERSION component[{}] = {:?} must parse as u32",
                i,
                comp
            );
        }
    }

    /// ZSH_VERSION MAJOR.MINOR is at least 5.9 (current upstream minimum).
    #[test]
    fn zsh_version_meets_minimum_5_9() {
        let no_tag = ZSH_VERSION.split('-').next().unwrap_or("");
        let parts: Vec<u32> = no_tag.split('.').filter_map(|s| s.parse().ok()).collect();
        assert!(parts.len() >= 2, "MAJOR.MINOR required");
        let major = parts[0];
        let minor = parts[1];
        assert!(
            major > 5 || (major == 5 && minor >= 9),
            "ZSH_VERSION must be ≥ 5.9, got {}.{}",
            major,
            minor
        );
    }

    /// ZSH_PATCHLEVEL has no NUL bytes (C-string safety).
    #[test]
    fn zsh_patchlevel_has_no_nul_bytes() {
        assert!(!ZSH_PATCHLEVEL.contains('\0'));
    }

    /// ZSH_VERSION has no NUL bytes (C-string safety).
    #[test]
    fn zsh_version_has_no_nul_bytes() {
        assert!(!ZSH_VERSION.contains('\0'));
    }

    /// ZSH_PATCHLEVEL doesn't start with whitespace.
    #[test]
    fn zsh_patchlevel_no_leading_whitespace() {
        assert!(!ZSH_PATCHLEVEL.starts_with(char::is_whitespace));
    }

    /// ZSH_VERSION doesn't start with whitespace.
    #[test]
    fn zsh_version_no_leading_whitespace() {
        assert!(!ZSH_VERSION.starts_with(char::is_whitespace));
    }

    /// Both constants are stable across reads (compile-time const).
    #[test]
    fn version_constants_are_stable() {
        for _ in 0..100 {
            assert_eq!(ZSH_PATCHLEVEL, "zsh-5.9.1-0-g0e0d4ea");
            assert_eq!(ZSH_VERSION, "5.9.1");
        }
    }

    // ═══════════════════════════════════════════════════════════════════
    // Additional C-parity tests for Src/patchlevel.h + Config/version.mk
    // ═══════════════════════════════════════════════════════════════════

    /// Both constants are `&'static str` (compile-time pin).
    #[test]
    fn version_constants_static_str_type() {
        let _: &'static str = ZSH_PATCHLEVEL;
        let _: &'static str = ZSH_VERSION;
    }

    /// ZSH_PATCHLEVEL is reproducible byte-for-byte across address-of reads.
    #[test]
    fn zsh_patchlevel_address_is_stable() {
        let p1 = ZSH_PATCHLEVEL.as_ptr();
        let p2 = ZSH_PATCHLEVEL.as_ptr();
        assert_eq!(p1, p2, "PATCHLEVEL must have stable static address");
    }

    /// ZSH_VERSION reproducible byte-for-byte across address-of reads.
    #[test]
    fn zsh_version_address_is_stable() {
        let p1 = ZSH_VERSION.as_ptr();
        let p2 = ZSH_VERSION.as_ptr();
        assert_eq!(p1, p2, "VERSION must have stable static address");
    }

    /// ZSH_PATCHLEVEL length is reasonable (10..200 bytes — not empty,
    /// not absurdly long).
    #[test]
    fn zsh_patchlevel_length_in_sane_range() {
        let n = ZSH_PATCHLEVEL.len();
        assert!(
            n >= 10 && n <= 200,
            "PATCHLEVEL length {} must be in [10, 200]",
            n
        );
    }

    /// ZSH_VERSION length is reasonable (3..30 bytes).
    #[test]
    fn zsh_version_length_in_sane_range() {
        let n = ZSH_VERSION.len();
        assert!(n >= 3 && n <= 30, "VERSION length {} must be in [3, 30]", n);
    }

    /// ZSH_PATCHLEVEL doesn't contain any uppercase hex above 9
    /// (git-describe uses lowercase hex per `--abbrev` convention).
    #[test]
    fn zsh_patchlevel_hash_is_lowercase_hex() {
        let last = ZSH_PATCHLEVEL.rsplit('-').next().unwrap_or("");
        let hash = last.trim_start_matches('g');
        for c in hash.chars() {
            assert!(
                !c.is_ascii_uppercase(),
                "git-describe hash uses lowercase hex; found uppercase {:?}",
                c
            );
        }
    }

    /// ZSH_PATCHLEVEL split on '-' all segments non-empty (no `--`).
    #[test]
    fn zsh_patchlevel_no_empty_segments() {
        for seg in ZSH_PATCHLEVEL.split('-') {
            assert!(
                !seg.is_empty(),
                "PATCHLEVEL must have no empty segments (no consecutive dashes)"
            );
        }
    }

    /// ZSH_VERSION split on '.' first 2 segments non-empty.
    #[test]
    fn zsh_version_major_minor_segments_non_empty() {
        let parts: Vec<&str> = ZSH_VERSION.split('.').collect();
        assert!(parts.len() >= 2);
        assert!(!parts[0].is_empty(), "MAJOR non-empty");
        assert!(!parts[1].is_empty(), "MINOR non-empty");
    }

    /// ZSH_PATCHLEVEL doesn't contain trailing newline.
    #[test]
    fn zsh_patchlevel_no_trailing_newline() {
        assert!(!ZSH_PATCHLEVEL.ends_with('\n'));
        assert!(!ZSH_PATCHLEVEL.ends_with('\r'));
    }

    /// ZSH_VERSION doesn't contain trailing newline.
    #[test]
    fn zsh_version_no_trailing_newline() {
        assert!(!ZSH_VERSION.ends_with('\n'));
        assert!(!ZSH_VERSION.ends_with('\r'));
    }

    /// Both constants are valid UTF-8 (trivially true for &str but
    /// pin the contract).
    #[test]
    fn version_constants_valid_utf8() {
        let _ = std::str::from_utf8(ZSH_PATCHLEVEL.as_bytes()).expect("PATCHLEVEL valid UTF-8");
        let _ = std::str::from_utf8(ZSH_VERSION.as_bytes()).expect("VERSION valid UTF-8");
    }

    // ═══════════════════════════════════════════════════════════════════
    // Additional pins for Src/patchlevel.h + Config/version.mk
    // ZSH_PATCHLEVEL shape / ZSH_VERSION semver-ish format
    // ═══════════════════════════════════════════════════════════════════

    /// Pin the upstream major version — ZSH_PATCHLEVEL must start `zsh-5.`
    /// (we're synced to upstream 5.x; any 6.x jump would be a deliberate
    /// rebase event flagged by this test).
    #[test]
    fn zsh_patchlevel_starts_with_zsh_5_dot() {
        assert!(
            ZSH_PATCHLEVEL.starts_with("zsh-5."),
            "ZSH_PATCHLEVEL must start `zsh-5.` (upstream major), got: {}",
            ZSH_PATCHLEVEL
        );
    }

    /// ZSH_VERSION must start with `5.` (matches the upstream major
    /// the patchlevel snapshot was taken from).
    #[test]
    fn zsh_version_starts_with_5_dot() {
        assert!(
            ZSH_VERSION.starts_with("5."),
            "ZSH_VERSION must start `5.` (upstream-major sync), got: {}",
            ZSH_VERSION
        );
    }

    /// ZSH_PATCHLEVEL has exactly 4 dash-separated segments: zsh, X.Y, N, gHASH.
    #[test]
    fn zsh_patchlevel_has_four_dash_segments() {
        let segs: Vec<&str> = ZSH_PATCHLEVEL.split('-').collect();
        assert_eq!(
            segs.len(),
            4,
            "ZSH_PATCHLEVEL must have 4 segments (zsh-X.Y-N-gHASH); got {} from {:?}",
            segs.len(),
            ZSH_PATCHLEVEL
        );
        assert_eq!(segs[0], "zsh");
        assert!(segs[3].starts_with('g'), "4th segment must start `g`");
    }

    /// ZSH_PATCHLEVEL's commit-count segment (3rd) is a non-negative integer.
    /// A value of `0` is legal — it means the current state IS the tagged
    /// release (no commits since the tag). The pinned `zsh-5.9.1-0-g0e0d4ea`
    /// snapshot matches Homebrew's shipped 5.9.1 build, which IS the tag.
    /// See bug #444 in docs/BUGS.md.
    #[test]
    fn zsh_patchlevel_commit_count_is_positive_integer() {
        let segs: Vec<&str> = ZSH_PATCHLEVEL.split('-').collect();
        let _n: u32 = segs[2].parse().expect("3rd segment must be u32");
    }

    /// ZSH_PATCHLEVEL's git hash (4th segment, after the `g`) is 7+ hex chars.
    #[test]
    fn zsh_patchlevel_hash_is_7_or_more_hex_chars() {
        let segs: Vec<&str> = ZSH_PATCHLEVEL.split('-').collect();
        let hash = &segs[3][1..]; // strip 'g'
        assert!(
            hash.len() >= 7,
            "git short hash must be ≥ 7 chars, got {} from {:?}",
            hash.len(),
            hash
        );
        assert!(
            hash.chars().all(|c| c.is_ascii_hexdigit()),
            "git hash must be all hex; got: {:?}",
            hash
        );
    }

    /// ZSH_VERSION's first dot-segment is parseable as u32 (the major).
    #[test]
    fn zsh_version_major_parseable_as_u32() {
        let major = ZSH_VERSION.split('.').next().unwrap();
        let _: u32 = major.parse().expect("major must parse as u32");
    }

    /// ZSH_VERSION's second dot-segment is parseable as u32 (the minor).
    #[test]
    fn zsh_version_minor_parseable_as_u32() {
        let mut iter = ZSH_VERSION.split('.');
        let _ = iter.next();
        let minor = iter.next().expect("VERSION must have minor segment");
        let _: u32 = minor.parse().expect("minor must parse as u32");
    }

    /// Both version constants are ASCII-only (no Unicode trickery).
    #[test]
    fn version_constants_are_ascii_only() {
        assert!(ZSH_PATCHLEVEL.is_ascii(), "ZSH_PATCHLEVEL must be ASCII");
        assert!(ZSH_VERSION.is_ascii(), "ZSH_VERSION must be ASCII");
    }

    /// Neither version constant contains a space.
    #[test]
    fn version_constants_have_no_spaces() {
        assert!(
            !ZSH_PATCHLEVEL.contains(' '),
            "ZSH_PATCHLEVEL must not contain spaces: {:?}",
            ZSH_PATCHLEVEL
        );
        assert!(
            !ZSH_VERSION.contains(' '),
            "ZSH_VERSION must not contain spaces: {:?}",
            ZSH_VERSION
        );
    }

    /// ZSH_VERSION major.minor matches the major.minor in ZSH_PATCHLEVEL.
    /// PATCHLEVEL segment 1 is `git describe`'s tag, which can be
    /// `5.9`, `5.9.1`, `5.9.0.2-test`, etc. — extract just the first two
    /// dot-segments and compare to VERSION's first two.
    #[test]
    fn zsh_version_major_minor_matches_patchlevel() {
        let segs: Vec<&str> = ZSH_PATCHLEVEL.split('-').collect();
        let pl_tag = segs[1];
        let pl_parts: Vec<&str> = pl_tag.split('.').collect();
        assert!(pl_parts.len() >= 2, "PATCHLEVEL tag must have MAJOR.MINOR");
        let pl_mm = format!("{}.{}", pl_parts[0], pl_parts[1]);
        let v_segs: Vec<&str> = ZSH_VERSION.split('.').collect();
        let v_mm = format!("{}.{}", v_segs[0], v_segs[1]);
        assert_eq!(
            pl_mm, v_mm,
            "PATCHLEVEL major.minor ({}) must match VERSION major.minor ({})",
            pl_mm, v_mm
        );
    }

    /// ZSH_PATCHLEVEL is not the bare upstream tag (must include git-describe suffix).
    #[test]
    fn zsh_patchlevel_is_not_bare_tag() {
        assert_ne!(
            ZSH_PATCHLEVEL, "zsh-5.9",
            "PATCHLEVEL must include git-describe suffix, not bare tag"
        );
        assert_ne!(
            ZSH_PATCHLEVEL, "5.9",
            "PATCHLEVEL must include `zsh-` prefix"
        );
    }

    /// Both constants are not empty / not whitespace-only.
    #[test]
    fn version_constants_non_empty() {
        assert!(!ZSH_PATCHLEVEL.is_empty());
        assert!(!ZSH_VERSION.is_empty());
        assert!(!ZSH_PATCHLEVEL.trim().is_empty());
        assert!(!ZSH_VERSION.trim().is_empty());
    }
}