macro_tests.rs

  1// Copyright (c) 2024 Jonas Schäfer <jonas@zombofant.net>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7#![deny(
  8    non_camel_case_types,
  9    non_snake_case,
 10    unsafe_code,
 11    unused_variables,
 12    unused_mut,
 13    dead_code
 14)]
 15
 16mod helpers {
 17    // we isolate the helpers into a module, because we do not want to have
 18    // them in scope below.
 19    // this is to ensure that the macros do not have hidden dependencies on
 20    // any specific names being imported.
 21    use minidom::Element;
 22    use xso::{error::FromElementError, transform, try_from_element, AsXml, FromXml};
 23
 24    pub(super) fn roundtrip_full<T: AsXml + FromXml + PartialEq + std::fmt::Debug + Clone>(
 25        s: &str,
 26    ) {
 27        let initial: Element = s.parse().unwrap();
 28        let structural: T = match try_from_element(initial.clone()) {
 29            Ok(v) => v,
 30            Err(e) => panic!("failed to parse from {:?}: {}", s, e),
 31        };
 32        let recovered =
 33            transform(structural.clone()).expect("roundtrip did not produce an element");
 34        assert_eq!(initial, recovered);
 35        let structural2: T = match try_from_element(recovered) {
 36            Ok(v) => v,
 37            Err(e) => panic!("failed to parse from serialisation of {:?}: {}", s, e),
 38        };
 39        assert_eq!(structural, structural2);
 40    }
 41
 42    pub(super) fn parse_str<T: FromXml>(s: &str) -> Result<T, FromElementError> {
 43        let initial: Element = s.parse().unwrap();
 44        try_from_element(initial)
 45    }
 46}
 47
 48use self::helpers::{parse_str, roundtrip_full};
 49
 50use xso::{AsXml, FromXml};
 51
 52// these are adverserial local names in order to trigger any issues with
 53// unqualified names in the macro expansions.
 54#[allow(dead_code, non_snake_case)]
 55fn Err() {}
 56#[allow(dead_code, non_snake_case)]
 57fn Ok() {}
 58#[allow(dead_code, non_snake_case)]
 59fn Some() {}
 60#[allow(dead_code, non_snake_case)]
 61fn None() {}
 62#[allow(dead_code)]
 63type Option = ((),);
 64#[allow(dead_code)]
 65type Result = ((),);
 66
 67static NS1: &str = "urn:example:ns1";
 68static NS2: &str = "urn:example:ns2";
 69
 70static FOO_NAME: &::xso::exports::rxml::strings::NcNameStr = {
 71    #[allow(unsafe_code)]
 72    unsafe {
 73        ::xso::exports::rxml::strings::NcNameStr::from_str_unchecked("foo")
 74    }
 75};
 76
 77static BAR_NAME: &::xso::exports::rxml::strings::NcNameStr = {
 78    #[allow(unsafe_code)]
 79    unsafe {
 80        ::xso::exports::rxml::strings::NcNameStr::from_str_unchecked("bar")
 81    }
 82};
 83
 84#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
 85#[xml(namespace = NS1, name = "foo")]
 86struct Empty;
 87
 88#[test]
 89fn empty_roundtrip() {
 90    #[allow(unused_imports)]
 91    use std::{
 92        option::Option::{None, Some},
 93        result::Result::{Err, Ok},
 94    };
 95    roundtrip_full::<Empty>("<foo xmlns='urn:example:ns1'/>");
 96}
 97
 98#[test]
 99fn empty_name_mismatch() {
100    #[allow(unused_imports)]
101    use std::{
102        option::Option::{None, Some},
103        result::Result::{Err, Ok},
104    };
105    match parse_str::<Empty>("<bar xmlns='urn:example:ns1'/>") {
106        Err(xso::error::FromElementError::Mismatch(..)) => (),
107        other => panic!("unexpected result: {:?}", other),
108    }
109}
110
111#[test]
112fn empty_namespace_mismatch() {
113    #[allow(unused_imports)]
114    use std::{
115        option::Option::{None, Some},
116        result::Result::{Err, Ok},
117    };
118    match parse_str::<Empty>("<foo xmlns='urn:example:ns2'/>") {
119        Err(xso::error::FromElementError::Mismatch(..)) => (),
120        other => panic!("unexpected result: {:?}", other),
121    }
122}
123
124#[test]
125fn empty_unexpected_attribute() {
126    #[allow(unused_imports)]
127    use std::{
128        option::Option::{None, Some},
129        result::Result::{Err, Ok},
130    };
131    match parse_str::<Empty>("<foo xmlns='urn:example:ns1' fnord='bar'/>") {
132        Err(xso::error::FromElementError::Invalid(xso::error::Error::Other(e))) => {
133            assert_eq!(e, "Unknown attribute in Empty element.");
134        }
135        other => panic!("unexpected result: {:?}", other),
136    }
137}
138
139#[test]
140fn empty_unexpected_child() {
141    #[allow(unused_imports)]
142    use std::{
143        option::Option::{None, Some},
144        result::Result::{Err, Ok},
145    };
146    match parse_str::<Empty>("<foo xmlns='urn:example:ns1'><coucou/></foo>") {
147        Err(xso::error::FromElementError::Invalid(xso::error::Error::Other(e))) => {
148            assert_eq!(e, "Unknown child in Empty element.");
149        }
150        other => panic!("unexpected result: {:?}", other),
151    }
152}
153
154#[test]
155fn empty_qname_check_has_precedence_over_attr_check() {
156    #[allow(unused_imports)]
157    use std::{
158        option::Option::{None, Some},
159        result::Result::{Err, Ok},
160    };
161    match parse_str::<Empty>("<bar xmlns='urn:example:ns1' fnord='bar'/>") {
162        Err(xso::error::FromElementError::Mismatch(..)) => (),
163        other => panic!("unexpected result: {:?}", other),
164    }
165}
166
167#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
168#[xml(namespace = NS1, name = BAR_NAME)]
169struct NamePath;
170
171#[test]
172fn name_path_roundtrip() {
173    #[allow(unused_imports)]
174    use std::{
175        option::Option::{None, Some},
176        result::Result::{Err, Ok},
177    };
178    roundtrip_full::<NamePath>("<bar xmlns='urn:example:ns1'/>");
179}
180
181#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
182#[xml(namespace = "urn:example:ns2", name = "baz")]
183struct NamespaceLit;
184
185#[test]
186fn namespace_lit_roundtrip() {
187    #[allow(unused_imports)]
188    use std::{
189        option::Option::{None, Some},
190        result::Result::{Err, Ok},
191    };
192    roundtrip_full::<NamespaceLit>("<baz xmlns='urn:example:ns2'/>");
193}
194
195#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
196#[xml(namespace = NS1, name = "attr")]
197struct RequiredAttribute {
198    #[xml(attribute)]
199    foo: String,
200}
201
202#[test]
203fn required_attribute_roundtrip() {
204    #[allow(unused_imports)]
205    use std::{
206        option::Option::{None, Some},
207        result::Result::{Err, Ok},
208    };
209    roundtrip_full::<RequiredAttribute>("<attr xmlns='urn:example:ns1' foo='bar'/>");
210}
211
212#[test]
213fn required_attribute_positive() {
214    #[allow(unused_imports)]
215    use std::{
216        option::Option::{None, Some},
217        result::Result::{Err, Ok},
218    };
219    let data = parse_str::<RequiredAttribute>("<attr xmlns='urn:example:ns1' foo='bar'/>").unwrap();
220    assert_eq!(data.foo, "bar");
221}
222
223#[test]
224fn required_attribute_missing() {
225    #[allow(unused_imports)]
226    use std::{
227        option::Option::{None, Some},
228        result::Result::{Err, Ok},
229    };
230    match parse_str::<RequiredAttribute>("<attr xmlns='urn:example:ns1'/>") {
231        Err(::xso::error::FromElementError::Invalid(::xso::error::Error::Other(e)))
232            if e.contains("Required attribute field") && e.contains("missing") =>
233        {
234            ()
235        }
236        other => panic!("unexpected result: {:?}", other),
237    }
238}
239
240#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
241#[xml(namespace = NS1, name = "attr")]
242struct RenamedAttribute {
243    #[xml(attribute = "a1")]
244    foo: String,
245    #[xml(attribute = BAR_NAME)]
246    bar: String,
247}
248
249#[test]
250fn renamed_attribute_roundtrip() {
251    #[allow(unused_imports)]
252    use std::{
253        option::Option::{None, Some},
254        result::Result::{Err, Ok},
255    };
256    roundtrip_full::<RenamedAttribute>("<attr xmlns='urn:example:ns1' a1='bar' bar='baz'/>");
257}
258
259#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
260#[xml(namespace = NS1, name = "attr")]
261struct NamespacedAttribute {
262    #[xml(attribute(namespace = "urn:example:ns1", name = FOO_NAME))]
263    foo_1: String,
264    #[xml(attribute(namespace = NS2, name = "foo"))]
265    foo_2: String,
266    #[xml(attribute(namespace = NS1, name = BAR_NAME))]
267    bar_1: String,
268    #[xml(attribute(namespace = "urn:example:ns2", name = "bar"))]
269    bar_2: String,
270}
271
272#[test]
273fn namespaced_attribute_roundtrip_a() {
274    #[allow(unused_imports)]
275    use std::{
276        option::Option::{None, Some},
277        result::Result::{Err, Ok},
278    };
279    roundtrip_full::<NamespacedAttribute>(
280        "<attr xmlns='urn:example:ns1'
281          xmlns:tns0='urn:example:ns1' tns0:foo='a1' tns0:bar='a3'
282          xmlns:tns1='urn:example:ns2' tns1:foo='a2' tns1:bar='a4'/>",
283    );
284}
285
286#[test]
287fn namespaced_attribute_roundtrip_b() {
288    #[allow(unused_imports)]
289    use std::{
290        option::Option::{None, Some},
291        result::Result::{Err, Ok},
292    };
293    roundtrip_full::<NamespacedAttribute>(
294        "<tns0:attr
295          xmlns:tns0='urn:example:ns1' tns0:foo='a1' tns0:bar='a3'
296          xmlns:tns1='urn:example:ns2' tns1:foo='a2' tns1:bar='a4'/>",
297    );
298}
299
300#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
301#[xml(namespace = NS1, name = "attr")]
302struct PrefixedAttribute {
303    #[xml(attribute = "xml:lang")]
304    lang: String,
305}
306
307#[test]
308fn prefixed_attribute_roundtrip() {
309    #[allow(unused_imports)]
310    use std::{
311        option::Option::{None, Some},
312        result::Result::{Err, Ok},
313    };
314    roundtrip_full::<PrefixedAttribute>("<attr xmlns='urn:example:ns1' xml:lang='foo'/>");
315}
316
317#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
318#[xml(namespace = NS1, name = "attr")]
319struct RequiredNonStringAttribute {
320    #[xml(attribute)]
321    foo: i32,
322}
323
324#[test]
325fn required_non_string_attribute_roundtrip() {
326    #[allow(unused_imports)]
327    use std::{
328        option::Option::{None, Some},
329        result::Result::{Err, Ok},
330    };
331    roundtrip_full::<RequiredNonStringAttribute>("<attr xmlns='urn:example:ns1' foo='-16'/>");
332}
333
334#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
335#[xml(namespace = NS1, name = "attr")]
336struct DefaultAttribute {
337    #[xml(attribute(default))]
338    foo: std::option::Option<String>,
339
340    #[xml(attribute(default))]
341    bar: std::option::Option<u16>,
342}
343
344#[test]
345fn default_attribute_roundtrip_aa() {
346    #[allow(unused_imports)]
347    use std::{
348        option::Option::{None, Some},
349        result::Result::{Err, Ok},
350    };
351    roundtrip_full::<DefaultAttribute>("<attr xmlns='urn:example:ns1'/>");
352}
353
354#[test]
355fn default_attribute_roundtrip_pa() {
356    #[allow(unused_imports)]
357    use std::{
358        option::Option::{None, Some},
359        result::Result::{Err, Ok},
360    };
361    roundtrip_full::<DefaultAttribute>("<attr xmlns='urn:example:ns1' foo='xyz'/>");
362}
363
364#[test]
365fn default_attribute_roundtrip_ap() {
366    #[allow(unused_imports)]
367    use std::{
368        option::Option::{None, Some},
369        result::Result::{Err, Ok},
370    };
371    roundtrip_full::<DefaultAttribute>("<attr xmlns='urn:example:ns1' bar='16'/>");
372}
373
374#[test]
375fn default_attribute_roundtrip_pp() {
376    #[allow(unused_imports)]
377    use std::{
378        option::Option::{None, Some},
379        result::Result::{Err, Ok},
380    };
381    roundtrip_full::<DefaultAttribute>("<attr xmlns='urn:example:ns1' foo='xyz' bar='16'/>");
382}
383
384#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
385#[xml(namespace = NS1, name = "text")]
386struct TextString {
387    #[xml(text)]
388    text: String,
389}
390
391#[test]
392fn text_string_roundtrip() {
393    #[allow(unused_imports)]
394    use std::{
395        option::Option::{None, Some},
396        result::Result::{Err, Ok},
397    };
398    roundtrip_full::<TextString>("<text xmlns='urn:example:ns1'>hello world!</text>");
399}
400
401#[test]
402fn text_string_positive_preserves_whitespace() {
403    #[allow(unused_imports)]
404    use std::{
405        option::Option::{None, Some},
406        result::Result::{Err, Ok},
407    };
408    let el = parse_str::<TextString>("<text xmlns='urn:example:ns1'> \t\n</text>").unwrap();
409    assert_eq!(el.text, " \t\n");
410}
411
412#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
413#[xml(namespace = NS1, name = "text")]
414struct TextNonString {
415    #[xml(text)]
416    text: u32,
417}
418
419#[test]
420fn text_non_string_roundtrip() {
421    #[allow(unused_imports)]
422    use std::{
423        option::Option::{None, Some},
424        result::Result::{Err, Ok},
425    };
426    roundtrip_full::<TextNonString>("<text xmlns='urn:example:ns1'>123456</text>");
427}
428
429#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
430#[xml(namespace = NS1, name = "elem")]
431struct IgnoresWhitespaceWithoutTextConsumer;
432
433#[test]
434fn ignores_whitespace_without_text_consumer_positive() {
435    #[allow(unused_imports)]
436    use std::{
437        option::Option::{None, Some},
438        result::Result::{Err, Ok},
439    };
440    let _ = parse_str::<IgnoresWhitespaceWithoutTextConsumer>(
441        "<elem xmlns='urn:example:ns1'> \t\r\n</elem>",
442    )
443    .unwrap();
444}
445
446#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
447#[xml(namespace = NS1, name = "elem")]
448struct FailsTextWithoutTextConsumer;
449
450#[test]
451fn fails_text_without_text_consumer_positive() {
452    #[allow(unused_imports)]
453    use std::{
454        option::Option::{None, Some},
455        result::Result::{Err, Ok},
456    };
457    match parse_str::<FailsTextWithoutTextConsumer>("<elem xmlns='urn:example:ns1'>  quak  </elem>")
458    {
459        Err(::xso::error::FromElementError::Invalid(::xso::error::Error::Other(e)))
460            if e.contains("Unexpected text") =>
461        {
462            ()
463        }
464        other => panic!("unexpected result: {:?}", other),
465    }
466}
467
468#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
469#[xml(namespace = NS1, name = "text")]
470struct TextWithCodec {
471    #[xml(text(codec = xso::text::EmptyAsNone))]
472    text: std::option::Option<String>,
473}
474
475#[test]
476fn text_with_codec_roundtrip_empty() {
477    #[allow(unused_imports)]
478    use std::{
479        option::Option::{None, Some},
480        result::Result::{Err, Ok},
481    };
482    roundtrip_full::<TextWithCodec>("<text xmlns='urn:example:ns1'/>");
483}
484
485#[test]
486fn text_with_codec_roundtrip_non_empty() {
487    #[allow(unused_imports)]
488    use std::{
489        option::Option::{None, Some},
490        result::Result::{Err, Ok},
491    };
492    roundtrip_full::<TextWithCodec>("<text xmlns='urn:example:ns1'>hello</text>");
493}
494
495#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
496#[xml(namespace = NS1, name = "parent")]
497struct Parent {
498    #[xml(child)]
499    child: RequiredAttribute,
500}
501
502#[test]
503fn parent_roundtrip() {
504    #[allow(unused_imports)]
505    use std::{
506        option::Option::{None, Some},
507        result::Result::{Err, Ok},
508    };
509    roundtrip_full::<Parent>("<parent xmlns='urn:example:ns1'><attr foo='hello world!'/></parent>")
510}
511
512#[test]
513fn parent_positive() {
514    #[allow(unused_imports)]
515    use std::{
516        option::Option::{None, Some},
517        result::Result::{Err, Ok},
518    };
519    let v =
520        parse_str::<Parent>("<parent xmlns='urn:example:ns1'><attr foo='hello world!'/></parent>")
521            .unwrap();
522    assert_eq!(v.child.foo, "hello world!");
523}
524
525#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
526#[xml(namespace = NS1, name = "parent")]
527struct OptionalChild {
528    #[xml(child(default))]
529    child: std::option::Option<RequiredAttribute>,
530}
531
532#[test]
533fn optional_child_roundtrip_present() {
534    #[allow(unused_imports)]
535    use std::{
536        option::Option::{None, Some},
537        result::Result::{Err, Ok},
538    };
539    roundtrip_full::<OptionalChild>(
540        "<parent xmlns='urn:example:ns1'><attr foo='hello world!'/></parent>",
541    )
542}
543
544#[test]
545fn optional_child_roundtrip_absent() {
546    #[allow(unused_imports)]
547    use std::{
548        option::Option::{None, Some},
549        result::Result::{Err, Ok},
550    };
551    roundtrip_full::<OptionalChild>("<parent xmlns='urn:example:ns1'/>")
552}
553
554#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
555#[xml(namespace = NS1, name = "elem")]
556struct BoxedChild {
557    #[xml(child(default))]
558    child: std::option::Option<Box<BoxedChild>>,
559}
560
561#[test]
562fn boxed_child_roundtrip_absent() {
563    #[allow(unused_imports)]
564    use std::{
565        option::Option::{None, Some},
566        result::Result::{Err, Ok},
567    };
568    roundtrip_full::<BoxedChild>("<elem xmlns='urn:example:ns1'/>")
569}
570
571#[test]
572fn boxed_child_roundtrip_nested_1() {
573    #[allow(unused_imports)]
574    use std::{
575        option::Option::{None, Some},
576        result::Result::{Err, Ok},
577    };
578    roundtrip_full::<BoxedChild>("<elem xmlns='urn:example:ns1'><elem/></elem>")
579}
580
581#[test]
582fn boxed_child_roundtrip_nested_2() {
583    #[allow(unused_imports)]
584    use std::{
585        option::Option::{None, Some},
586        result::Result::{Err, Ok},
587    };
588    roundtrip_full::<BoxedChild>("<elem xmlns='urn:example:ns1'><elem><elem/></elem></elem>")
589}
590
591#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
592#[xml(namespace = NS1, name = "elem", builder = RenamedBuilder, iterator = RenamedIter)]
593struct RenamedTypes;
594
595#[test]
596fn renamed_types_roundtrip() {
597    #[allow(unused_imports)]
598    use std::{
599        option::Option::{None, Some},
600        result::Result::{Err, Ok},
601    };
602    roundtrip_full::<RenamedTypes>("<elem xmlns='urn:example:ns1'/>")
603}
604
605#[test]
606#[allow(unused_comparisons)]
607fn renamed_types_get_renamed() {
608    // these merely serve as a test that the types are declared with the names
609    // given in the attributes.
610    assert!(std::mem::size_of::<RenamedBuilder>() >= 0);
611    assert!(std::mem::size_of::<RenamedIter>() >= 0);
612}
613
614// What is this, you may wonder?
615// This is a test that any generated type names won't trigger
616// the `non_camel_case_types` lint.
617#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
618#[xml(namespace = NS1, name = "elem")]
619struct LintTest_;
620
621#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
622#[xml(namespace = NS1)]
623enum NameSwitchedEnum {
624    #[xml(name = "a")]
625    Variant1 {
626        #[xml(attribute)]
627        foo: String,
628    },
629    #[xml(name = "b")]
630    Variant2 {
631        #[xml(text)]
632        foo: String,
633    },
634}
635
636#[test]
637fn name_switched_enum_positive_variant_1() {
638    #[allow(unused_imports)]
639    use std::{
640        option::Option::{None, Some},
641        result::Result::{Err, Ok},
642    };
643    match parse_str::<NameSwitchedEnum>("<a xmlns='urn:example:ns1' foo='hello'/>") {
644        Ok(NameSwitchedEnum::Variant1 { foo }) => {
645            assert_eq!(foo, "hello");
646        }
647        other => panic!("unexpected result: {:?}", other),
648    }
649}
650
651#[test]
652fn name_switched_enum_positive_variant_2() {
653    #[allow(unused_imports)]
654    use std::{
655        option::Option::{None, Some},
656        result::Result::{Err, Ok},
657    };
658    match parse_str::<NameSwitchedEnum>("<b xmlns='urn:example:ns1'>hello</b>") {
659        Ok(NameSwitchedEnum::Variant2 { foo }) => {
660            assert_eq!(foo, "hello");
661        }
662        other => panic!("unexpected result: {:?}", other),
663    }
664}
665
666#[test]
667fn name_switched_enum_negative_name_mismatch() {
668    #[allow(unused_imports)]
669    use std::{
670        option::Option::{None, Some},
671        result::Result::{Err, Ok},
672    };
673    match parse_str::<NameSwitchedEnum>("<x xmlns='urn:example:ns1'>hello</x>") {
674        Err(xso::error::FromElementError::Mismatch { .. }) => (),
675        other => panic!("unexpected result: {:?}", other),
676    }
677}
678
679#[test]
680fn name_switched_enum_negative_namespace_mismatch() {
681    #[allow(unused_imports)]
682    use std::{
683        option::Option::{None, Some},
684        result::Result::{Err, Ok},
685    };
686    match parse_str::<NameSwitchedEnum>("<b xmlns='urn:example:ns2'>hello</b>") {
687        Err(xso::error::FromElementError::Mismatch { .. }) => (),
688        other => panic!("unexpected result: {:?}", other),
689    }
690}
691
692#[test]
693fn name_switched_enum_roundtrip_variant_1() {
694    #[allow(unused_imports)]
695    use std::{
696        option::Option::{None, Some},
697        result::Result::{Err, Ok},
698    };
699    roundtrip_full::<NameSwitchedEnum>("<a xmlns='urn:example:ns1' foo='hello'/>")
700}
701
702#[test]
703fn name_switched_enum_roundtrip_variant_2() {
704    #[allow(unused_imports)]
705    use std::{
706        option::Option::{None, Some},
707        result::Result::{Err, Ok},
708    };
709    roundtrip_full::<NameSwitchedEnum>("<b xmlns='urn:example:ns1'>hello</b>")
710}
711
712#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
713#[xml(namespace = NS1, builder = RenamedEnumBuilder, iterator = RenamedEnumIter)]
714enum RenamedEnumTypes {
715    #[xml(name = "elem")]
716    A,
717}
718
719#[test]
720fn renamed_enum_types_roundtrip() {
721    #[allow(unused_imports)]
722    use std::{
723        option::Option::{None, Some},
724        result::Result::{Err, Ok},
725    };
726    roundtrip_full::<RenamedEnumTypes>("<elem xmlns='urn:example:ns1'/>")
727}
728
729#[test]
730#[allow(unused_comparisons)]
731fn renamed_enum_types_get_renamed() {
732    // these merely serve as a test that the types are declared with the names
733    // given in the attributes.
734    assert!(std::mem::size_of::<RenamedEnumBuilder>() >= 0);
735    assert!(std::mem::size_of::<RenamedEnumIter>() >= 0);
736}