1
use std::num::NonZeroU32;
2

            
3
use ron::error::{Error, Position, Span, SpannedError};
4
use serde::{
5
    de::{Deserialize, Error as DeError, Unexpected},
6
    Deserializer,
7
};
8

            
9
#[cfg(feature = "internal-span-substring-test")]
10
use ron::util::span_substring::check_error_span_inclusive;
11

            
12
#[cfg(feature = "internal-span-substring-test")]
13
use ron::util::span_substring::check_error_span_exclusive;
14

            
15
#[derive(Debug, serde::Deserialize, PartialEq)]
16
#[serde(deny_unknown_fields)]
17
enum Test {
18
    TupleVariant(i32, String),
19
    StructVariant { a: bool, b: NonZeroU32, c: i32 },
20
}
21

            
22
#[derive(Debug, PartialEq)] // GRCOV_EXCL_LINE
23
struct TypeError;
24

            
25
impl<'de> Deserialize<'de> for TypeError {
26
7
    fn deserialize<D: Deserializer<'de>>(_deserializer: D) -> Result<Self, D::Error> {
27
7
        Err(D::Error::invalid_type(Unexpected::Unit, &"impossible"))
28
7
    }
29
}
30

            
31
#[test]
32
4
fn test_error_positions() {
33
4
    let bogus_struct = "  ()";
34
4
    let expected_err = Err(SpannedError {
35
4
        code: Error::InvalidValueForType {
36
4
            expected: String::from("impossible"),
37
4
            found: String::from("a unit value"),
38
4
        },
39
4
        span: Span {
40
4
            start: Position { line: 1, col: 1 },
41
4
            end: Position { line: 1, col: 3 },
42
4
        },
43
4
    });
44

            
45
4
    assert_eq!(ron::from_str::<TypeError>(bogus_struct), expected_err,);
46

            
47
    #[cfg(feature = "internal-span-substring-test")]
48
1
    check_error_span_inclusive::<TypeError>(bogus_struct, expected_err, "  (");
49

            
50
4
    let bogus_struct = "StructVariant(a: true, b: 0, c: -42)";
51
4
    let expected_err = Err(SpannedError {
52
4
        code: Error::InvalidValueForType {
53
4
            expected: String::from("a nonzero u32"),
54
4
            found: String::from("the unsigned integer `0`"),
55
4
        },
56
4
        span: Span {
57
4
            start: Position { line: 1, col: 27 },
58
4
            end: Position { line: 1, col: 28 },
59
4
        },
60
4
    });
61

            
62
4
    assert_eq!(ron::from_str::<Test>(bogus_struct), expected_err);
63

            
64
    #[cfg(feature = "internal-span-substring-test")]
65
1
    check_error_span_inclusive::<Test>(bogus_struct, expected_err, "0,");
66

            
67
4
    let bogus_struct = "TupleVariant(42)";
68
4
    let expected_err = Err(SpannedError {
69
4
        code: Error::ExpectedDifferentLength {
70
4
            expected: String::from("tuple variant Test::TupleVariant with 2 elements"),
71
4
            found: 1,
72
4
        },
73
4
        span: Span {
74
4
            start: Position { line: 1, col: 16 },
75
4
            end: Position { line: 1, col: 16 },
76
4
        },
77
4
    });
78

            
79
4
    assert_eq!(ron::from_str::<Test>(bogus_struct), expected_err);
80

            
81
    #[cfg(feature = "internal-span-substring-test")]
82
1
    check_error_span_inclusive::<Test>(bogus_struct, expected_err, ")");
83

            
84
4
    let bogus_struct = "NotAVariant";
85
4
    let expected_err = Err(SpannedError {
86
4
        code: Error::NoSuchEnumVariant {
87
4
            expected: &["TupleVariant", "StructVariant"],
88
4
            found: String::from("NotAVariant"),
89
4
            outer: Some(String::from("Test")),
90
4
        },
91
4
        span: Span {
92
4
            start: Position { line: 1, col: 1 },
93
4
            end: Position { line: 1, col: 12 },
94
4
        },
95
4
    });
96

            
97
4
    assert_eq!(ron::from_str::<Test>(bogus_struct), expected_err);
98

            
99
    #[cfg(feature = "internal-span-substring-test")]
100
1
    check_error_span_exclusive::<Test>(bogus_struct, expected_err, "NotAVariant");
101

            
102
4
    let bogus_struct = "StructVariant(a: true, b: 1, c: -42, d: \"gotcha\")";
103
4
    let expected_err = Err(SpannedError {
104
4
        code: Error::NoSuchStructField {
105
4
            expected: &["a", "b", "c"],
106
4
            found: String::from("d"),
107
4
            outer: Some(String::from("StructVariant")),
108
4
        },
109
4
        span: Span {
110
4
            start: Position { line: 1, col: 38 },
111
4
            end: Position { line: 1, col: 39 },
112
4
        },
113
4
    });
114

            
115
4
    assert_eq!(ron::from_str::<Test>(bogus_struct), expected_err);
116

            
117
    #[cfg(feature = "internal-span-substring-test")]
118
1
    check_error_span_inclusive::<Test>(bogus_struct, expected_err, "d:");
119

            
120
4
    let bogus_struct = "StructVariant(a: true, c: -42)";
121
4
    let expected_err = Err(SpannedError {
122
4
        code: Error::MissingStructField {
123
4
            field: "b",
124
4
            outer: Some(String::from("StructVariant")),
125
4
        },
126
4
        span: Span {
127
4
            start: Position { line: 1, col: 30 },
128
4
            end: Position { line: 1, col: 30 },
129
4
        },
130
4
    });
131

            
132
4
    assert_eq!(ron::from_str::<Test>(bogus_struct), expected_err);
133

            
134
    #[cfg(feature = "internal-span-substring-test")]
135
1
    check_error_span_inclusive::<Test>(bogus_struct, expected_err, ")");
136

            
137
4
    let bogus_struct = "StructVariant(a: true, b: 1, a: false, c: -42)";
138
4
    let expected_err = Err(SpannedError {
139
4
        code: Error::DuplicateStructField {
140
4
            field: "a",
141
4
            outer: Some(String::from("StructVariant")),
142
4
        },
143
4
        span: Span {
144
4
            start: Position { line: 1, col: 30 },
145
4
            end: Position { line: 1, col: 31 },
146
4
        },
147
4
    });
148

            
149
4
    assert_eq!(ron::from_str::<Test>(bogus_struct), expected_err);
150

            
151
    #[cfg(feature = "internal-span-substring-test")]
152
1
    check_error_span_inclusive::<Test>(bogus_struct, expected_err, "a:");
153
4
}