summaryrefslogtreecommitdiffstats
path: root/tests/version.rs
blob: 31bc2b6fec083863563dc70b537dd717c98fdf13 (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
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
use zagan_bet::version::{
    VERSION, Version, compatible, hello_line, is_newer, parse_hello, parse_pong, pong_line,
    unix_time_ms,
};

#[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/",
        1_700_000_000_123,
    );
    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_eq!(reply.time, 1_700_000_000_123);

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

#[test]
fn pong_carries_the_server_time() {
    let line = pong_line(1_700_000_000_456);
    assert_eq!(line, "PONG 1700000000456");
    assert_eq!(parse_pong(&line), Some(1_700_000_000_456));
    assert!(parse_pong("PONG").is_none());
    assert!(parse_pong("RES 1 PONG 1700000000456").is_none());
    assert!(unix_time_ms() > 1_600_000_000_000);
}

/// 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);
}

/// The gateway is a frontend too; keep it in lockstep with the core.
#[test]
fn the_webd_member_uses_the_same_version() {
    let manifest = include_str!("../webd/Cargo.toml");
    let version = manifest
        .lines()
        .find_map(|line| line.trim().strip_prefix("version = "))
        .expect("webd/Cargo.toml declares a version")
        .trim_matches('"');
    assert_eq!(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}"
        );
    }
}