1
use ron::error::{Position, Span, SpannedError};
2

            
3
#[cfg(feature = "internal-span-substring-test")]
4
use ron::util::span_substring::check_error_span_inclusive;
5

            
6
#[cfg(feature = "internal-span-substring-test")]
7
use ron::util::span_substring::check_error_span_exclusive;
8

            
9
#[derive(Debug, serde::Deserialize, PartialEq)]
10
#[serde(deny_unknown_fields)]
11
enum TestEnum {
12
    StructVariant { a: bool, b: char, c: i32 },
13
    NewtypeVariant(TestStruct),
14
}
15

            
16
#[derive(Debug, serde::Deserialize, PartialEq)]
17
#[serde(tag = "type")]
18
enum TestEnumInternal {
19
    StructVariant { a: bool },
20
}
21

            
22
#[derive(Debug, serde::Deserialize, PartialEq)]
23
#[serde(tag = "type", content = "content")]
24
enum TestEnumAdjacent {
25
    StructVariant { a: bool },
26
}
27

            
28
#[derive(Debug, serde::Deserialize, PartialEq)]
29
#[serde(untagged)]
30
enum TestEnumUntagged {
31
    StructVariant { a: bool },
32
}
33

            
34
#[derive(Debug, serde::Deserialize, PartialEq)]
35
#[serde(deny_unknown_fields)]
36
struct TestStruct {
37
    a: bool,
38
    b: char,
39
    c: i32,
40
}
41

            
42
#[test]
43
4
fn test_unknown_enum_variant() {
44
4
    assert_eq!(
45
4
        ron::from_str::<TestEnum>("NotAVariant"),
46
4
        Err(SpannedError {
47
4
            code: ron::Error::NoSuchEnumVariant {
48
4
                expected: &["StructVariant", "NewtypeVariant"],
49
4
                found: String::from("NotAVariant"),
50
4
                outer: Some(String::from("TestEnum")),
51
4
            },
52
4
            span: Span {
53
4
                start: Position { line: 1, col: 1 },
54
4
                end: Position { line: 1, col: 12 },
55
4
            }
56
4
        })
57
    );
58

            
59
    #[cfg(feature = "internal-span-substring-test")]
60
1
    check_error_span_exclusive::<TestEnum>(
61
1
        "NotAVariant",
62
1
        Err(SpannedError {
63
1
            code: ron::Error::NoSuchEnumVariant {
64
1
                expected: &["StructVariant", "NewtypeVariant"],
65
1
                found: String::from("NotAVariant"),
66
1
                outer: Some(String::from("TestEnum")),
67
1
            },
68
1
            span: Span {
69
1
                start: Position { line: 1, col: 1 },
70
1
                end: Position { line: 1, col: 12 },
71
1
            },
72
1
        }),
73
1
        "NotAVariant",
74
    );
75
4
}
76

            
77
#[test]
78
4
fn test_struct_enum_fields() {
79
4
    let bogus_struct = "StructVariant(a: true, b: 'b', c: -42, d: \"gotcha\")";
80
4
    let expected_err = Err(SpannedError {
81
4
        code: ron::Error::NoSuchStructField {
82
4
            expected: &["a", "b", "c"],
83
4
            found: String::from("d"),
84
4
            outer: Some(String::from("StructVariant")),
85
4
        },
86
4
        span: Span {
87
4
            start: Position { line: 1, col: 40 },
88
4
            end: Position { line: 1, col: 41 },
89
4
        },
90
4
    });
91

            
92
4
    assert_eq!(ron::from_str::<TestEnum>(bogus_struct), expected_err);
93

            
94
    #[cfg(feature = "internal-span-substring-test")]
95
1
    check_error_span_inclusive::<TestEnum>(bogus_struct, expected_err, "d:");
96

            
97
4
    let bogus_struct = "StructVariant(a: true, c: -42)";
98
4
    let expected_err = Err(SpannedError {
99
4
        code: ron::Error::MissingStructField {
100
4
            field: "b",
101
4
            outer: Some(String::from("StructVariant")),
102
4
        },
103
4
        span: Span {
104
4
            start: Position { line: 1, col: 30 },
105
4
            end: Position { line: 1, col: 30 },
106
4
        },
107
4
    });
108

            
109
4
    assert_eq!(ron::from_str::<TestEnum>(bogus_struct), expected_err);
110

            
111
    #[cfg(feature = "internal-span-substring-test")]
112
1
    check_error_span_inclusive::<TestEnum>(bogus_struct, expected_err, ")");
113

            
114
4
    let bogus_struct = "StructVariant(a: true, b: 'b', a: false, c: -42)";
115
4
    let expected_err = Err(SpannedError {
116
4
        code: ron::Error::DuplicateStructField {
117
4
            field: "a",
118
4
            outer: Some(String::from("StructVariant")),
119
4
        },
120
4
        span: Span {
121
4
            start: Position { line: 1, col: 32 },
122
4
            end: Position { line: 1, col: 33 },
123
4
        },
124
4
    });
125

            
126
4
    assert_eq!(ron::from_str::<TestEnum>(bogus_struct), expected_err);
127

            
128
    #[cfg(feature = "internal-span-substring-test")]
129
1
    check_error_span_inclusive::<TestEnum>(bogus_struct, expected_err, "a:");
130
4
}
131

            
132
#[test]
133
4
fn test_newtype_enum_fields() {
134
4
    let bogus_struct = "#![enable(unwrap_variant_newtypes)] NewtypeVariant(a: true, b: 'b', c: -42, d: \"gotcha\")";
135
4
    let expected_err = Err(SpannedError {
136
4
        code: ron::Error::NoSuchStructField {
137
4
            expected: &["a", "b", "c"],
138
4
            found: String::from("d"),
139
4
            outer: Some(String::from("NewtypeVariant")),
140
4
        },
141
4
        span: Span {
142
4
            start: Position { line: 1, col: 77 },
143
4
            end: Position { line: 1, col: 78 },
144
4
        },
145
4
    });
146

            
147
4
    assert_eq!(ron::from_str::<TestEnum>(bogus_struct), expected_err);
148

            
149
    #[cfg(feature = "internal-span-substring-test")]
150
1
    check_error_span_inclusive::<TestEnum>(bogus_struct, expected_err, "d:");
151

            
152
4
    let bogus_struct = "#![enable(unwrap_variant_newtypes)] NewtypeVariant(a: true, c: -42)";
153
4
    let expected_err = Err(SpannedError {
154
4
        code: ron::Error::MissingStructField {
155
4
            field: "b",
156
4
            outer: Some(String::from("NewtypeVariant")),
157
4
        },
158
4
        span: Span {
159
4
            start: Position { line: 1, col: 67 },
160
4
            end: Position { line: 1, col: 67 },
161
4
        },
162
4
    });
163

            
164
4
    assert_eq!(ron::from_str::<TestEnum>(bogus_struct), expected_err);
165

            
166
    #[cfg(feature = "internal-span-substring-test")]
167
1
    check_error_span_inclusive::<TestEnum>(bogus_struct, expected_err, ")");
168

            
169
4
    let bogus_struct =
170
4
        "#![enable(unwrap_variant_newtypes)] NewtypeVariant(a: true, b: 'b', a: false, c: -42)";
171
4
    let expected_err = Err(SpannedError {
172
4
        code: ron::Error::DuplicateStructField {
173
4
            field: "a",
174
4
            outer: Some(String::from("NewtypeVariant")),
175
4
        },
176
4
        span: Span {
177
4
            start: Position { line: 1, col: 69 },
178
4
            end: Position { line: 1, col: 70 },
179
4
        },
180
4
    });
181

            
182
4
    assert_eq!(ron::from_str::<TestEnum>(bogus_struct), expected_err);
183

            
184
    #[cfg(feature = "internal-span-substring-test")]
185
1
    check_error_span_inclusive::<TestEnum>(bogus_struct, expected_err, "a:");
186
4
}
187

            
188
#[test]
189
4
fn test_struct_fields() {
190
4
    let bogus_struct = "TestStruct(a: true, b: 'b', c: -42, d: \"gotcha\")";
191
4
    let expected_err = Err(SpannedError {
192
4
        code: ron::Error::NoSuchStructField {
193
4
            expected: &["a", "b", "c"],
194
4
            found: String::from("d"),
195
4
            outer: Some(String::from("TestStruct")),
196
4
        },
197
4
        span: Span {
198
4
            start: Position { line: 1, col: 37 },
199
4
            end: Position { line: 1, col: 38 },
200
4
        },
201
4
    });
202

            
203
4
    assert_eq!(ron::from_str::<TestStruct>(bogus_struct), expected_err);
204

            
205
    #[cfg(feature = "internal-span-substring-test")]
206
1
    check_error_span_inclusive::<TestStruct>(bogus_struct, expected_err, "d:");
207

            
208
4
    assert_eq!(
209
4
        ron::from_str::<TestStruct>("TestStruct(a: true, c: -42)"),
210
4
        Err(SpannedError {
211
4
            code: ron::Error::MissingStructField {
212
4
                field: "b",
213
4
                outer: Some(String::from("TestStruct")),
214
4
            },
215
4
            span: Span {
216
4
                start: Position { line: 1, col: 27 },
217
4
                end: Position { line: 1, col: 27 },
218
4
            }
219
4
        })
220
    );
221

            
222
4
    let bogus_struct = "TestStruct(a: true, b: 'b', a: false, c: -42)";
223
4
    let expected_err = Err(SpannedError {
224
4
        code: ron::Error::DuplicateStructField {
225
4
            field: "a",
226
4
            outer: Some(String::from("TestStruct")),
227
4
        },
228
4
        span: Span {
229
4
            start: Position { line: 1, col: 29 },
230
4
            end: Position { line: 1, col: 30 },
231
4
        },
232
4
    });
233

            
234
4
    assert_eq!(ron::from_str::<TestStruct>(bogus_struct), expected_err);
235

            
236
    #[cfg(feature = "internal-span-substring-test")]
237
1
    check_error_span_inclusive::<TestStruct>(bogus_struct, expected_err, "a:");
238
4
}
239

            
240
#[test]
241
4
fn test_internally_tagged_enum() {
242
    // Note: Not extracting the variant type is not great,
243
    //        but at least not wrong either
244
    //       Since the error occurs in serde-generated user code,
245
    //        after successfully deserialising, we cannot annotate
246

            
247
4
    let bogus_struct = "(type: \"StructVariant\")";
248
4
    let expected_err = Err(SpannedError {
249
4
        code: ron::Error::MissingStructField {
250
4
            field: "a",
251
4
            outer: None,
252
4
        },
253
4
        span: Span {
254
4
            start: Position { line: 1, col: 23 },
255
4
            end: Position { line: 1, col: 24 },
256
4
        },
257
4
    });
258

            
259
4
    assert_eq!(
260
4
        ron::from_str::<TestEnumInternal>(bogus_struct),
261
        expected_err
262
    );
263

            
264
    #[cfg(feature = "internal-span-substring-test")]
265
1
    check_error_span_exclusive::<TestEnumInternal>(bogus_struct, expected_err, ")");
266
4
}
267

            
268
#[test]
269
4
fn test_adjacently_tagged_enum() {
270
    // Note: TestEnumAdjacent makes sense here since we are now treating
271
    //        the enum as a struct
272

            
273
4
    assert_eq!(
274
4
        ron::from_str::<TestEnumAdjacent>("(type: StructVariant, content: (d: 4))"),
275
4
        Err(SpannedError {
276
4
            code: ron::Error::MissingStructField {
277
4
                field: "a",
278
4
                outer: Some(String::from("TestEnumAdjacent")),
279
4
            },
280
4
            span: Span {
281
4
                start: Position { line: 1, col: 37 },
282
4
                end: Position { line: 1, col: 37 },
283
4
            }
284
4
        })
285
    );
286
4
}
287

            
288
#[test]
289
4
fn test_untagged_enum() {
290
    // Note: Errors inside untagged enums are not bubbled up
291

            
292
4
    let bogus_struct = "(a: true, a: false)";
293
4
    let expected_err = Err(SpannedError {
294
4
        code: ron::Error::Message(String::from(
295
4
            "data did not match any variant of untagged enum TestEnumUntagged",
296
4
        )),
297
4
        span: Span {
298
4
            start: Position { line: 1, col: 19 },
299
4
            end: Position { line: 1, col: 20 },
300
4
        },
301
4
    });
302

            
303
4
    assert_eq!(
304
4
        ron::from_str::<TestEnumUntagged>(bogus_struct),
305
        expected_err
306
    );
307

            
308
    #[cfg(feature = "internal-span-substring-test")]
309
1
    check_error_span_exclusive::<TestEnumUntagged>(bogus_struct, expected_err, ")");
310
4
}