summaryrefslogtreecommitdiff
path: root/subprojects/clap/tests/builder/utf16.rs
blob: 5799039734b49cc5a3e73ba13d57ba73587ce221 (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
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
//! These Windows-only tests are ported from the Unix-only tests in
//! tests/utf16.rs. The tests that use StrictUtf8 mode are omitted here,
//! because that's a Unix-only feature.

#![cfg(windows)]

use clap::{arg, value_parser, Command};
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;

// Take a slice of ASCII bytes, convert them to UTF-16, and then append a
// dangling surrogate character to make the result invalid UTF-16.
fn bad_osstring(ascii: &[u8]) -> OsString {
    let mut wide_chars: Vec<u16> = ascii.iter().map(|&c| c as u16).collect();
    // UTF-16 surrogate characters are only valid in pairs.
    let surrogate_char: u16 = 0xDC00;
    wide_chars.push(surrogate_char);
    let os = OsString::from_wide(&wide_chars);
    assert!(os.to_str().is_none(), "invalid Unicode");
    os
}

#[test]
fn invalid_utf16_positional() {
    let r = Command::new("bad_utf16")
        .arg(arg!(<arg> "some arg").value_parser(value_parser!(OsString)))
        .try_get_matches_from(vec![OsString::from(""), bad_osstring(b"")]);
    assert!(r.is_ok(), "{}", r.unwrap_err());
    let m = r.unwrap();
    assert!(m.contains_id("arg"));
    assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b""));
}

#[test]
fn invalid_utf16_option_short_space() {
    let r = Command::new("bad_utf16")
        .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString)))
        .try_get_matches_from(vec![
            OsString::from(""),
            OsString::from("-a"),
            bad_osstring(b""),
        ]);
    assert!(r.is_ok(), "{}", r.unwrap_err());
    let m = r.unwrap();
    assert!(m.contains_id("arg"));
    assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b""));
}

#[test]
fn invalid_utf16_option_short_equals() {
    let r = Command::new("bad_utf16")
        .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString)))
        .try_get_matches_from(vec![OsString::from(""), bad_osstring(b"-a=")]);
    assert!(r.is_ok(), "{}", r.unwrap_err());
    let m = r.unwrap();
    assert!(m.contains_id("arg"));
    assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b""));
}

#[test]
fn invalid_utf16_option_short_no_space() {
    let r = Command::new("bad_utf16")
        .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString)))
        .try_get_matches_from(vec![OsString::from(""), bad_osstring(b"-a")]);
    assert!(r.is_ok(), "{}", r.unwrap_err());
    let m = r.unwrap();
    assert!(m.contains_id("arg"));
    assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b""));
}

#[test]
fn invalid_utf16_option_long_space() {
    let r = Command::new("bad_utf16")
        .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString)))
        .try_get_matches_from(vec![
            OsString::from(""),
            OsString::from("--arg"),
            bad_osstring(b""),
        ]);
    assert!(r.is_ok(), "{}", r.unwrap_err());
    let m = r.unwrap();
    assert!(m.contains_id("arg"));
    assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b""));
}

#[test]
fn invalid_utf16_option_long_equals() {
    let r = Command::new("bad_utf16")
        .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString)))
        .try_get_matches_from(vec![OsString::from(""), bad_osstring(b"--arg=")]);
    assert!(r.is_ok(), "{}", r.unwrap_err());
    let m = r.unwrap();
    assert!(m.contains_id("arg"));
    assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b""));
}