summaryrefslogtreecommitdiffstats
path: root/tests/version.rs
blob: af244dba720326ae11ef0b1120a847e00299375a (plain) (blame)
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
use zagan_bet::version::{
    compatible, hello_line, is_newer, parse_hello, Version, VERSION,
};

#[test]
fn versions_parse_and_reject_nonsense() {
    assert_eq!(
        Version::parse("4.0.0"),
        Some(Version {
            major: 4,
            minor: 0,
            patch: 0
        })
    );
    assert_eq!(
        Version::parse("v4.1.2"),
        Some(Version {
            major: 4,
            minor: 1,
            patch: 2
        })
    );
    assert_eq!(
        Version::parse("4.0.0-rc1").map(|v| (v.major, v.minor, v.patch)),
        Some((4, 0, 0))
    );
    assert_eq!(
        Version::parse("4.0.0+build7").map(|v| v.patch),
        Some(0)
    );

    for bad in ["", "4", "4.0", "4.0.0.1", "x.0.0", "4.x.0", "4.0.0-"] {
        assert!(Version::parse(bad).is_none(), "{bad:?} should not parse");
    }

    assert!(Version::parse(VERSION).is_some(), "the build version must parse");
}

#[test]
fn compatibility_is_major_and_minor_only() {
    assert!(compatible("4.0.0", "4.0.9"));
    assert!(compatible("4.2.7", "4.2.1"));
    assert!(!compatible("4.0.0", "4.1.0"));
    assert!(!compatible("4.0.0", "5.0.0"));
    assert!(!compatible("nope", "4.0.0"));
}

#[test]
fn newer_versions_are_ordered_by_major_minor_patch() {
    assert!(is_newer("4.0.1", "4.0.0"));
    assert!(is_newer("4.1.0", "4.0.9"));
    assert!(is_newer("5.0.0", "4.9.9"));
    assert!(!is_newer("4.0.0", "4.0.0"));
    assert!(!is_newer("4.0.0", "4.0.1"));
    assert!(!is_newer("nonsense", "4.0.0"));
}

#[test]
fn the_hello_reply_round_trips() {
    let line = hello_line("4.0.0", "4.1.2", "https://zagan.example/");
    let reply = parse_hello(&line).expect("parse a generated reply");

    assert_eq!(reply.version, "4.0.0");
    assert_eq!(reply.latest, "4.1.2");
    assert_eq!(reply.url, "https://zagan.example/");

    assert!(parse_hello("HELLO 4.0.0 url=https://x/").is_none(), "latest is required");
    assert!(parse_hello("HELLO 4.0.0 latest=4.0.0").is_none(), "url is required");
    assert!(parse_hello("PONG").is_none());
    assert!(parse_hello("HELLO").is_none());
}

/// The GUI is a client, so it must ship in lockstep with the TUI and server.
/// Keep `gui/Cargo.toml` at the same version as the root package.
#[test]
fn the_gui_member_uses_the_same_version() {
    let gui_manifest = include_str!("../gui/Cargo.toml");
    let gui_version = gui_manifest
        .lines()
        .find_map(|line| line.trim().strip_prefix("version = "))
        .expect("gui/Cargo.toml declares a version")
        .trim_matches('"');
    assert_eq!(gui_version, VERSION);
}

/// egui's dependency tree must never enter the TUI or server build graph.
/// The GUI is a workspace member that depends on this package, never the
/// other way round.
#[test]
fn the_root_package_does_not_depend_on_the_gui() {
    let manifest = include_str!("../Cargo.toml");
    for forbidden in ["eframe", "egui"] {
        assert!(
            !manifest.contains(forbidden),
            "the root package must not depend on {forbidden}"
        );
    }
}