summaryrefslogtreecommitdiff
path: root/tests/rustls_version.rs
blob: 446cd58b7f1145f33a39fbd3805fe487ae5e6358 (plain)
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
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::{slice, str};

use toml::Table;

use rustls_ffi::rustls_version;

/// Test that the output of `rustls_version()` matches what we expect based on Cargo.toml state.
///
/// In particular this ensures that the Rustls version reported in the rustls-ffi version string
/// matches the version of the Rustls dependency that rustls-ffi was built with.
///
/// If this test starts to fail, you probably forgot to update `RUSTLS_CRATE_VERSION` in
/// `build.rs`.
#[cfg_attr(miri, ignore)] // Requires file I/O
#[test]
fn rustls_version_match() {
    // Parse Cargo.toml as a generic TOML Table.
    let mut metadata_file =
        File::open(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml"))
            .expect("failed to open Cargo.toml");
    let mut metadata_content = String::new();
    metadata_file
        .read_to_string(&mut metadata_content)
        .expect("failed to read Cargo.toml");
    let metadata = metadata_content.parse::<Table>().unwrap();

    // Find the crate version specified in Cargo.toml
    let package_metadata = metadata["package"]
        .as_table()
        .expect("missing package metadata");
    let crate_version = package_metadata["version"]
        .as_str()
        .expect("missing crate version");

    // Find the rustls dependency version specified in Cargo.toml
    let deps = metadata["dependencies"].as_table().unwrap();
    let rustls_dep = &deps["rustls"];
    let rustls_dep_version = match rustls_dep.as_table() {
        // Handle the `rustls = { version = "x.y.z", ... }` case
        Some(table) => table["version"].as_str(),
        // Handle the `rustls = "x.y.z"` case
        None => rustls_dep.as_str(),
    }
    .expect("missing rustls dependency version");

    // Assert that rustls_version() returns a string of the form:
    //   $CRATE_NAME/$CRATE_VERSION/rustls/$RUSTLS_VERSION
    // E.g.:
    //   rustls-ffi/0.13.0/rustls/0.23.4
    let rustls_ffi_version = rustls_version();
    let rustls_ffi_version = unsafe {
        str::from_utf8_unchecked(slice::from_raw_parts(
            rustls_ffi_version.data as *const u8,
            rustls_ffi_version.len,
        ))
    };
    let rustls_ffi_version_parts = rustls_ffi_version.split('/').collect::<Vec<_>>();
    assert_eq!(
        rustls_ffi_version_parts,
        vec![
            env!("CARGO_PKG_NAME"),
            crate_version,
            "rustls",
            rustls_dep_version,
        ]
    );
}