summaryrefslogtreecommitdiffstats
path: root/tests/errors.rs
blob: 5f4a1a52effe7ef1f93f61cfe5062bbd4df54a6f (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#![cfg(feature = "toml")]

extern crate config;

#[macro_use]
extern crate serde_derive;

use config::*;

fn make() -> Config {
    let mut c = Config::default();
    c.merge(File::new("tests/Settings", FileFormat::Toml))
        .unwrap();

    c
}

#[test]
fn test_error_parse() {
    let mut c = Config::default();
    let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Toml));

    assert!(res.is_err());
    assert_eq!(
        res.unwrap_err().to_string(),
        "failed to parse datetime for key `error` at line 2 column 9 in tests/Settings-invalid.toml".to_string()
    );
}

#[test]
fn test_error_type() {
    let c = make();

    let res = c.get::<bool>("boolean_s_parse");

    assert!(res.is_err());
    assert_eq!(
        res.unwrap_err().to_string(),
        "invalid type: string \"fals\", expected a boolean for key \
         `boolean_s_parse` in tests/Settings.toml"
            .to_string()
    );
}

#[test]
fn test_error_type_detached() {
    let c = make();

    let value = c.get::<Value>("boolean_s_parse").unwrap();
    let res = value.try_into::<bool>();

    assert!(res.is_err());
    assert_eq!(
        res.unwrap_err().to_string(),
        "invalid type: string \"fals\", expected a boolean".to_string()
    );
}

#[test]
fn test_error_enum_de() {
    #[derive(Debug, Deserialize, PartialEq)]
    enum Diode {
        Off,
        Brightness(i32),
        Blinking(i32, i32),
        Pattern { name: String, inifinite: bool },
    }

    let on_v: Value = "on".into();
    let on_d = on_v.try_into::<Diode>();
    assert_eq!(
        on_d.unwrap_err().to_string(),
        "enum Diode does not have variant constructor on".to_string()
    );

    let array_v: Value = vec![100, 100].into();
    let array_d = array_v.try_into::<Diode>();
    assert_eq!(
        array_d.unwrap_err().to_string(),
        "value of enum Diode should be represented by either string or table with exactly one key"
    );


    let confused_v: Value =
    [("Brightness".to_string(), 100.into()),
     ("Blinking".to_string(), vec![300, 700].into())]
    .iter().cloned().collect::<std::collections::HashMap<String, Value>>().into();
    let confused_d = confused_v.try_into::<Diode>();
    assert_eq!(
        confused_d.unwrap_err().to_string(),
        "value of enum Diode should be represented by either string or table with exactly one key"
    );
}

#[test]
fn error_with_path() {
    #[derive(Debug, Deserialize)]
    struct Inner {
        test: i32,
    }

    #[derive(Debug, Deserialize)]
    struct Outer {
        inner: Inner,
    }
    const CFG: &str = r#"
inner:
    test: ABC
"#;

    let mut cfg = Config::new();
    cfg.merge(File::from_str(CFG, FileFormat::Yaml)).unwrap();
    let e = cfg.try_into::<Outer>().unwrap_err();
    if let ConfigError::Type { key: Some(path), .. } = e {
        assert_eq!(path, "inner.test");
    } else {
        panic!("Wrong error {:?}", e);
    }
}