zbus_lockstep/
macros.rs

1#![allow(unused_macros)]
2#![allow(dead_code)]
3#![allow(unused_imports)]
4
5use std::{fs, path::PathBuf, str::FromStr};
6
7use crate::Result;
8
9/// Resolve XML path from either:
10///
11/// - provided argument,
12/// - default location (`xml/`, `XML/`, `../xml` or `../XML`) or
13/// - env_variable (`LOCKSTEP_XML_PATH`)
14///
15/// If no XML path is provided, it tries to find the default XML path.
16/// If the environment variable is set, it overrides the default, or
17/// argument path.
18///
19/// # Example
20///
21/// ```rust
22/// # use zbus_lockstep::resolve_xml_path;
23/// # use std::path::PathBuf;
24/// # fn main() {
25/// // path to XML files
26/// std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
27///
28/// let xml_path = resolve_xml_path(None).unwrap();
29/// assert_eq!(xml_path, PathBuf::from("../xml").canonicalize().unwrap());       
30/// # }
31/// ```
32/// # Panics
33///
34/// Panics if no XML path is provided and the default XML path is not found.
35pub fn resolve_xml_path(xml: Option<&str>) -> Result<PathBuf> {
36    let mut xml = xml;
37    let current_dir: PathBuf = std::env::current_dir()?;
38
39    // We want to know the name of the crate we are expanded in.
40    let crate_name = std::env::var("CARGO_PKG_NAME").unwrap_or_else(|_| String::from("unknown"));
41
42    let current_dir_lower_case = current_dir.join("xml");
43    let current_dir_upper_case = current_dir.join("XML");
44
45    let parent_dir_lower_case = current_dir.join("../xml");
46    let parent_dir_upper_case = current_dir.join("../XML");
47
48    let crate_dir_lower_case = current_dir.join(&crate_name).join("xml");
49    let crate_dir_upper_case = current_dir.join(&crate_name).join("XML");
50
51    // If no XML path is provided, try to find the default XML path.
52    if xml.is_none() {
53        if current_dir_lower_case.exists() {
54            xml = Some(
55                current_dir_lower_case
56                    .to_str()
57                    .expect("current_dir_lower_case is valid UTF-8"),
58            );
59        }
60
61        if current_dir_upper_case.exists() {
62            xml = Some(
63                current_dir_upper_case
64                    .to_str()
65                    .expect("current_dir_upper_case is valid UTF-8"),
66            );
67        }
68
69        if parent_dir_lower_case.exists() {
70            xml = Some(
71                parent_dir_lower_case
72                    .to_str()
73                    .expect("parent_dir_lower_case is valid UTF-8"),
74            );
75        }
76
77        if parent_dir_upper_case.exists() {
78            xml = Some(
79                parent_dir_upper_case
80                    .to_str()
81                    .expect("parent_dir_upper_case is valid UTF-8"),
82            );
83        }
84
85        if crate_dir_lower_case.exists() {
86            xml = Some(
87                crate_dir_lower_case
88                    .to_str()
89                    .expect("crate_dir_lower_case is valid UTF-8"),
90            );
91        }
92
93        if crate_dir_upper_case.exists() {
94            xml = Some(
95                crate_dir_upper_case
96                    .to_str()
97                    .expect("crate_dir_upper_case is valid UTF-8"),
98            );
99        }
100    }
101
102    let env_xml_path = std::env::var("LOCKSTEP_XML_PATH");
103    if env_xml_path.is_ok() {
104        // Override the default, or argument path if the environment variable is set.
105        xml = env_xml_path.as_ref().map(|s| s.as_str()).ok();
106    }
107
108    // If no XML path is provided and the default XML path is not found, panic.
109    if xml.is_none() {
110        panic!(
111            "No XML path provided and default XML path not found. Current dir: \"{}\" ",
112            current_dir.to_str().expect("current_dir is valid UTF-8")
113        );
114    }
115
116    // Convert, canonicalize and return the XML path.
117    let xml = PathBuf::from_str(xml.unwrap())?;
118    Ok(xml.canonicalize()?)
119}
120
121/// A generic helper to find the file path and interface name of a member.
122#[doc(hidden)]
123#[macro_export]
124macro_rules! find_definition_in_dbus_xml {
125    ($xml_path_buf:expr, $member:expr, $iface:expr, $msg_type:expr) => {{
126    use $crate::MsgType;
127
128    let xml_path_buf: std::path::PathBuf = $xml_path_buf;
129    let member: &str = $member;
130    let iface: Option<String> = $iface;
131    let msg_type: MsgType = $msg_type;
132
133    let mut xml_file_path = None;
134    let mut interface_name = None;
135
136    let read_dir = std::fs::read_dir(&xml_path_buf).expect("Failed to read XML directory");
137
138    // Walk the XML files in the directory.
139    for entry in read_dir {
140        let entry = entry.expect("Failed to read entry");
141
142        // Skip directories and non-XML files.
143        if entry.path().is_dir() || entry.path().extension().unwrap() != "xml" {
144            continue;
145        }
146
147        let entry_path = entry.path().clone();
148        let file = std::fs::File::open(entry.path()).expect("Failed to open file");
149        let node = $crate::zbus_xml::Node::from_reader(file).expect("Failed to parse XML file");
150
151        for interface in node.interfaces() {
152            // If called with an `iface` arg, skip he interfaces that do not match.
153            if iface.is_some() && interface.name().as_str() != iface.clone().unwrap()  {
154                continue;
155            }
156
157            match msg_type {
158                MsgType::Method => {
159                    for dbus_item in interface.methods() {
160                        if dbus_item.name() == member {
161                            if interface_name.is_some() {
162                                panic!(
163                                    "Multiple interfaces offer the same {:?} member: {}, please specify the interface name.",
164                                    msg_type, member
165                                );
166                            }
167                            interface_name = Some(interface.name().to_string());
168                            xml_file_path = Some(entry_path.clone());
169                            continue;
170                        }
171                    }
172                }
173                MsgType::Signal => {
174                    for dbus_item in interface.signals() {
175                        if dbus_item.name() == member {
176                            if interface_name.is_some() {
177                                panic!(
178                                    "Multiple interfaces offer the same {:?} member: {}, please specify the interface name.",
179                                    msg_type, member
180                                );
181                            }
182                            interface_name = Some(interface.name().to_string());
183                            xml_file_path = Some(entry_path.clone());
184                            continue;
185                        }
186                    }
187                }
188                MsgType::Property => {
189                    for dbus_item in interface.properties() {
190                        if dbus_item.name() == member {
191                            if interface_name.is_some() {
192                                panic!(
193                                    "Multiple interfaces offer the same {:?} member: {}, please specify the interface name.",
194                                    msg_type, member
195                                );
196                            }
197                            interface_name = Some(interface.name().to_string());
198                            xml_file_path = Some(entry_path.clone());
199                            continue;
200                        }
201                    }
202                }
203            };
204        }
205    }
206
207    // If the interface member was not found, return an error.
208    if xml_file_path.is_none() {
209        panic!("Member not found in XML files.");
210    }
211
212    (xml_file_path.unwrap(), interface_name.unwrap())
213    }};
214}
215
216/// Retrieve the signature of a method's return type.
217///
218/// This macro will take a method member name and return the signature of the
219/// return type.
220///
221/// Essentially a wrapper around [`zbus_lockstep::get_method_return_type`],
222/// but this macro tries to do its job with less arguments.
223///
224/// It will search in the XML specification of the method for the return type
225/// and return the signature of that type.
226///
227/// If multiple interfaces offer the same method, you will need to specify the
228/// interface name as well.
229///
230/// This macro can be called with or without the interface name.
231///
232/// # Examples
233///
234/// Basic usage:
235///
236/// ```rust
237/// use zbus_lockstep::method_return_signature;
238/// use zvariant::Signature;
239///
240/// std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
241///     
242/// let sig = method_return_signature!("RequestName");
243/// assert_eq!(&sig, &Signature::from_str_unchecked("u"));
244/// ```
245/// The macro supports colling arguments with identifiers as well as without.
246/// The macro may also be called with an interface name or interface and argument name:
247///
248/// ```rust
249/// # use zbus_lockstep::{method_return_signature};
250/// # std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
251/// let _sig = method_return_signature!("RequestName", "org.example.Node", "grape");
252///
253/// // or alternatively
254///
255/// let _sig = method_return_signature!(member: "RequestName", interface: "org.example.Node", argument: "grape");
256/// ```
257#[macro_export]
258macro_rules! method_return_signature {
259    ($member:expr) => {{
260        use $crate::MsgType;
261        let member = $member;
262
263        // Looking for default path or path specified by environment variable.
264        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
265        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
266            "Failed to resolve XML path, current dir: {}",
267            current_dir.to_str().unwrap()
268        ));
269
270        // Find the definition of the method in the XML specification.
271        let (file_path, interface_name) =
272            $crate::find_definition_in_dbus_xml!(xml_path, member, None, MsgType::Method);
273
274        let file = std::fs::File::open(file_path).expect("Failed to open file");
275        $crate::get_method_return_type(file, &interface_name, member, None)
276            .expect("Failed to get method arguments type signature")
277    }};
278
279    (member: $member:expr) => {
280        $crate::method_return_signature!($member)
281    };
282
283    ($member:expr, $interface:expr) => {{
284        let member = $member;
285        use $crate::MsgType;
286
287        let interface = Some($interface.to_string());
288
289        // Looking for default path or path specified by environment variable.
290        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
291        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
292            "Failed to resolve XML path, current dir: {}",
293            current_dir.to_str().unwrap()
294        ));
295
296        // Find the definition of the method in the XML specification.
297        let (file_path, interface_name) =
298            $crate::find_definition_in_dbus_xml!(xml_path, member, interface, MsgType::Method);
299
300        let file = std::fs::File::open(file_path).expect("Failed to open file");
301        $crate::get_method_return_type(file, &interface_name, member, None)
302            .expect("Failed to get method arguments type signature")
303    }};
304
305    (member: $member:expr, interface: $interface:expr) => {
306        $crate::method_return_signature!($member, $interface)
307    };
308
309    ($member:expr, $interface:expr, $argument:expr) => {{
310        let member = $member;
311        use $crate::MsgType;
312
313        let interface = Some($interface.to_string());
314        let argument = Some($argument);
315
316        // Looking for default path or path specified by environment variable.
317        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
318        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
319            "Failed to resolve XML path, current dir: {}",
320            current_dir.to_str().unwrap()
321        ));
322
323        // Find the definition of the method in the XML specification.
324        let (file_path, interface_name) =
325            $crate::find_definition_in_dbus_xml!(xml_path, member, interface, MsgType::Method);
326
327        let file = std::fs::File::open(file_path).expect("Failed to open file");
328        $crate::get_method_return_type(file, &interface_name, member, argument)
329            .expect("Failed to get method argument(s) type signature")
330    }};
331
332    (member: $member:expr, interface: $interface:expr, argument: $argument:expr) => {
333        $crate::method_return_signature!($member, $interface, $argument)
334    };
335}
336
337/// Retrieve the signature of a method's arguments.
338///
339/// Essentially a wrapper around [`zbus_lockstep::get_method_args_type`],
340/// but this macro tries to do its job with less arguments.
341///
342/// This macro will take a method member name and return the signature of the
343/// arguments type.
344///
345/// It will search in the XML specification of the method for the arguments type
346/// and return the signature of that type.
347///
348/// If multiple interfaces offer the same member, you will need to
349/// specify the interface name as well.
350///
351/// This macro can be called with or without the interface name.
352///
353/// # Examples
354///
355/// ```rust
356/// use zbus_lockstep::method_args_signature;
357/// use zvariant::Signature;
358///
359/// std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
360///     
361/// let sig = method_args_signature!("RequestName");
362/// assert_eq!(&sig, &Signature::from_str_unchecked("(su)"));
363/// ```
364/// The macro supports colling arguments with identifiers as well as without.
365/// The macro may also be called with an interface name or interface and argument name:
366///
367/// ```rust
368/// # use zbus_lockstep::{method_args_signature};
369/// # std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
370/// let _sig = method_args_signature!("RequestName", "org.example.Node", "apple");
371///
372/// // or alternatively
373///     
374/// let _sig = method_args_signature!(member: "RequestName", interface: "org.example.Node", argument: "apple");
375/// ```
376#[macro_export]
377macro_rules! method_args_signature {
378    ($member:expr) => {{
379        use $crate::MsgType;
380        let member = $member;
381
382        // Looking for default path or path specified by environment variable.
383        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
384        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
385            "Failed to resolve XML path, current dir: {}",
386            current_dir.to_str().unwrap()
387        ));
388
389        // Find the definition of the method in the XML specification.
390        let (file_path, interface_name) =
391            $crate::find_definition_in_dbus_xml!(xml_path, member, None, MsgType::Method);
392
393        let file = std::fs::File::open(file_path).expect("Failed to open file");
394        $crate::get_method_args_type(file, &interface_name, member, None)
395            .expect("Failed to get method arguments type signature")
396    }};
397
398    (member: $member:expr) => {
399        $crate::method_args_signature!($member)
400    };
401
402    ($member:expr, $interface:expr) => {{
403        use $crate::MsgType;
404        let member = $member;
405
406        let interface = Some($interface.to_string());
407
408        // Looking for default path or path specified by environment variable.
409        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
410        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
411            "Failed to resolve XML path, current dir: {}",
412            current_dir.to_str().unwrap()
413        ));
414
415        // Find the definition of the method in the XML specification.
416        let (file_path, interface_name) =
417            $crate::find_definition_in_dbus_xml!(xml_path, member, interface, MsgType::Method);
418
419        let file = std::fs::File::open(file_path).expect("Failed to open file");
420        $crate::get_method_args_type(file, &interface_name, member, None)
421            .expect("Failed to get method arguments type signature")
422    }};
423
424    (member: $member:expr, interface: $interface:expr) => {
425        $crate::method_args_signature!($member, $interface)
426    };
427
428    ($member:expr, $interface:expr, $argument:expr) => {{
429        use $crate::MsgType;
430        let member = $member;
431        let interface = Some($interface.to_string());
432
433        let argument = Some($argument);
434
435        // Looking for default path or path specified by environment variable.
436        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
437
438        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
439            "Failed to resolve XML path, current dir: {}",
440            current_dir.to_str().unwrap()
441        ));
442        // Find the definition of the method in the XML specification.
443        let (file_path, interface_name) =
444            $crate::find_definition_in_dbus_xml!(xml_path, member, interface, MsgType::Method);
445
446        let file = std::fs::File::open(file_path).expect("Failed to open file");
447        $crate::get_method_args_type(file, &interface_name, member, argument)
448            .expect("Failed to get method argument(s) type signature")
449    }};
450
451    (member: $member:expr, interface: $interface:expr, argument: $argument:expr) => {
452        $crate::method_args_signature!($member, $interface, $argument)
453    };
454}
455
456/// Retrieve the signature of a signal's body type.
457///
458/// Essentially a wrapper around [`zbus_lockstep::get_signal_body_type`],
459/// but this macro tries to find it with less arguments.
460///
461/// This macro will take a signal member name and return the signature of the
462/// signal body type.
463///
464/// If multiple interfaces offer the same member, you will need to
465/// specify the interface name as well.
466///
467/// This macro can be called with or without the interface name.
468///
469/// # Examples
470///
471/// ```rust
472/// use zbus_lockstep::signal_body_type_signature;
473/// use zvariant::Signature;
474///
475/// std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
476///     
477/// let sig = signal_body_type_signature!("AddNode");
478/// assert_eq!(&sig, &Signature::from_str_unchecked("(so)"));
479/// ```
480/// The macro supports colling arguments with identifiers as well as without.
481/// The macro may also be called with an interface name or interface and argument name:
482///
483/// ```rust
484/// # use zbus_lockstep::{signal_body_type_signature};
485/// # std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
486/// let _sig = signal_body_type_signature!("Alert", "org.example.Node", "color");
487///
488/// // or alternatively
489///
490/// let _sig = signal_body_type_signature!(member: "Alert", interface: "org.example.Node", argument: "color");
491/// ```
492#[macro_export]
493macro_rules! signal_body_type_signature {
494    ($member:expr) => {{
495        use $crate::MsgType;
496        let member = $member;
497
498        // Looking for default path or path specified by environment variable.
499        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
500        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
501            "Failed to resolve XML path, current dir: {}",
502            current_dir.to_str().unwrap()
503        ));
504
505        // Find the definition of the method in the XML specification.
506        let (file_path, interface_name) =
507            $crate::find_definition_in_dbus_xml!(xml_path, member, None, MsgType::Signal);
508
509        let file = std::fs::File::open(file_path).expect("Failed to open file");
510
511        $crate::get_signal_body_type(file, &interface_name, member, None)
512            .expect("Failed to get method arguments type signature")
513    }};
514
515    (member: $member:expr) => {
516        $crate::signal_body_type_signature!($member)
517    };
518
519    ($member:expr, $interface:expr) => {{
520        use $crate::MsgType;
521        let member = $member;
522        let interface = Some($interface.to_string());
523
524        // Looking for default path or path specified by environment variable.
525        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
526        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
527            "Failed to resolve XML path, current dir: {}",
528            current_dir.to_str().unwrap()
529        ));
530
531        // Find the definition of the method in the XML specification.
532        let (file_path, interface_name) =
533            $crate::find_definition_in_dbus_xml!(xml_path, member, interface, MsgType::Signal);
534
535        let file = std::fs::File::open(file_path).expect("Failed to open file");
536        $crate::get_signal_body_type(file, &interface_name, member, None)
537            .expect("Failed to get method arguments type signature")
538    }};
539
540    (member: $member:expr, interface: $interface:expr) => {
541        $crate::signal_body_type_signature!($member, $interface)
542    };
543
544    ($member:expr, $interface:expr, $argument:expr) => {{
545        use $crate::MsgType;
546        let member = $member;
547        let interface = Some($interface.to_string());
548
549        let argument = Some($argument);
550
551        // Looking for default path or path specified by environment variable.
552        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
553
554        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
555            "Failed to resolve XML path, current dir: {}",
556            current_dir.to_str().unwrap()
557        ));
558
559        // Find the definition of the method in the XML specification.
560        let (file_path, interface_name) =
561            $crate::find_definition_in_dbus_xml!(xml_path, member, interface, MsgType::Signal);
562
563        let file = std::fs::File::open(file_path).expect("Failed to open file");
564        $crate::get_signal_body_type(file, &interface_name, member, argument)
565            .expect("Failed to get method argument(s) type signature")
566    }};
567
568    (member: $member:expr, interface: $interface:expr, argument: $argument:expr) => {
569        $crate::signal_body_type_signature!($member, $interface, $argument)
570    };
571}
572
573/// Retrieve the signature of a property's type.
574///
575/// Essentially a wrapper around [`zbus_lockstep::get_property_type`],
576/// but this macro tries to do with less arguments.
577///
578/// This macro will take a property name and return the signature of the
579/// property's type.
580///
581/// If multiple interfaces offer the same member, you will need to
582/// specify the interface name as well.
583///
584/// This macro can be called with or without the interface name.
585///
586/// # Examples
587///
588/// ```rust
589/// use zbus_lockstep::property_type_signature;
590/// use zvariant::Signature;
591///
592/// std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
593///     
594/// let sig = property_type_signature!("Features");
595/// assert_eq!(&sig, &Signature::from_str_unchecked("as"));
596/// ```
597/// The member name and/or interface name can be used tp identify the arguments:
598///
599/// ```rust
600/// # use zbus_lockstep::{property_type_signature};
601/// # std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
602/// let _sig = property_type_signature!(member: "Features", interface: "org.example.Node");
603/// ```
604#[macro_export]
605macro_rules! property_type_signature {
606    ($member:expr) => {{
607        use $crate::MsgType;
608        let member = $member;
609
610        // Looking for default path or path specified by environment variable.
611        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
612        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
613            "Failed to resolve XML path, current dir: {}",
614            current_dir.to_str().unwrap()
615        ));
616
617        // Find the definition of the method in the XML specification.
618        let (file_path, interface_name) =
619            $crate::find_definition_in_dbus_xml!(xml_path, member, None, MsgType::Property);
620
621        let file = std::fs::File::open(file_path).expect("Failed to open file");
622
623        $crate::get_property_type(file, &interface_name, member)
624            .expect("Failed to get property type signature")
625    }};
626
627    (member: $member:expr) => {
628        $crate::property_type_signature!($member)
629    };
630
631    ($member:expr, $interface:expr) => {{
632        use $crate::MsgType;
633        let member = $member;
634        let interface = Some($interface.to_string());
635
636        // Looking for default path or path specified by environment variable.
637        let current_dir: std::path::PathBuf = std::env::current_dir().unwrap();
638        let xml_path = $crate::resolve_xml_path(None).expect(&format!(
639            "Failed to resolve XML path, current dir: {}",
640            current_dir.to_str().unwrap()
641        ));
642
643        // Find the definition of the method in the XML specification.
644        let (file_path, interface_name) =
645            $crate::find_definition_in_dbus_xml!(xml_path, member, interface, MsgType::Property);
646
647        let file = std::fs::File::open(file_path).expect("Failed to open file");
648        $crate::get_property_type(file, &interface_name, member)
649            .expect("Failed to get property type signature")
650    }};
651
652    (member: $member:expr, interface: $interface:expr) => {
653        $crate::property_type_signature!($member, $interface)
654    };
655}
656
657#[cfg(test)]
658mod test {
659    use zvariant::Signature;
660
661    use crate::signal_body_type_signature;
662
663    #[test]
664    fn test_signal_body_signature_macro() {
665        // path to XML files can be set by environment variable
666        // std::env::set_var("LOCKSTEP_XML_PATH", "../xml");
667        // But `resolve_xml_path` can find the `xml` in parent by itself.
668
669        let sig = crate::signal_body_type_signature!("AddNode");
670        assert_eq!(&sig, &zvariant::Signature::from_str_unchecked("(so)"));
671    }
672
673    #[test]
674    fn test_signal_body_signature_macro_with_identifier() {
675        let sig = crate::signal_body_type_signature!(member: "AddNode");
676        assert_eq!(sig, Signature::from_str_unchecked("(so)"));
677    }
678
679    #[test]
680    fn test_signal_body_signature_macro_with_interface() {
681        let sig = crate::signal_body_type_signature!("AddNode", "org.example.Node");
682        assert_eq!(sig, Signature::from_str_unchecked("(so)"));
683    }
684
685    #[test]
686    fn test_signal_body_signature_macro_with_interface_and_identifiers() {
687        let sig =
688            crate::signal_body_type_signature!(member: "AddNode", interface: "org.example.Node");
689        assert_eq!(sig, Signature::from_str_unchecked("(so)"));
690    }
691
692    #[test]
693    fn test_signal_body_signature_macro_with_argument_and_interface() {
694        let sig = crate::signal_body_type_signature!("Alert", "org.example.Node", "volume");
695        assert_eq!(sig, Signature::from_str_unchecked("d"));
696    }
697
698    #[test]
699    fn test_signal_body_signature_macro_with_argument_and_identifiers_and_interface() {
700        let sig = crate::signal_body_type_signature!(
701            member: "Alert",
702            interface: "org.example.Node",
703            argument: "urgent"
704        );
705        assert_eq!(sig, Signature::from_str_unchecked("b"));
706    }
707
708    #[test]
709    fn test_method_args_signature_macro() {
710        let sig = crate::method_args_signature!("RequestName");
711        assert_eq!(sig, Signature::from_str_unchecked("(su)"));
712    }
713
714    #[test]
715    fn test_method_args_signature_macro_with_identifier() {
716        let sig = crate::method_args_signature!(member: "RequestName");
717        assert_eq!(sig, Signature::from_str_unchecked("(su)"));
718    }
719
720    #[test]
721    fn test_method_args_signature_macro_with_interface() {
722        let sig = crate::method_args_signature!("RequestName", "org.example.Node");
723        assert_eq!(sig, Signature::from_str_unchecked("(su)"));
724    }
725
726    #[test]
727    fn test_method_args_signature_macro_with_interface_and_identifiers() {
728        let sig =
729            crate::method_args_signature!(member: "RequestName", interface: "org.example.Node");
730        assert_eq!(sig, Signature::from_str_unchecked("(su)"));
731    }
732
733    #[test]
734    fn test_method_args_signature_macro_with_argument_and_interface() {
735        let sig = crate::method_args_signature!("RequestName", "org.example.Node", "apple");
736        assert_eq!(sig, Signature::from_str_unchecked("s"));
737    }
738
739    #[test]
740    fn test_method_args_signature_macro_with_argument_and_identifiers_and_interface() {
741        let sig = crate::method_args_signature!(
742            member: "RequestName",
743            interface: "org.example.Node",
744            argument: "orange"
745        );
746        assert_eq!(sig, Signature::from_str_unchecked("u"));
747    }
748
749    #[test]
750    fn test_method_return_signature_macro() {
751        let sig = crate::method_return_signature!("RequestName");
752        assert_eq!(sig, Signature::from_str_unchecked("u"));
753    }
754
755    #[test]
756    fn test_method_return_signature_macro_with_identifier() {
757        let sig = crate::method_return_signature!(member: "RequestName");
758        assert_eq!(sig, Signature::from_str_unchecked("u"));
759    }
760
761    #[test]
762    fn test_method_return_signature_macro_with_interface() {
763        let sig = crate::method_return_signature!("RequestName", "org.example.Node");
764        assert_eq!(sig, Signature::from_str_unchecked("u"));
765    }
766
767    #[test]
768    fn test_method_return_signature_macro_with_interface_and_identifiers() {
769        let sig =
770            crate::method_return_signature!(member: "RequestName", interface: "org.example.Node");
771        assert_eq!(sig, Signature::from_str_unchecked("u"));
772    }
773
774    #[test]
775    fn test_method_return_signature_macro_with_argument_and_interface() {
776        let sig = crate::method_return_signature!("RequestName", "org.example.Node", "grape");
777        assert_eq!(sig, Signature::from_str_unchecked("u"));
778    }
779
780    #[test]
781    fn test_method_return_signature_macro_with_argument_and_identifiers_and_interface() {
782        let sig = crate::method_return_signature!(
783            member: "RequestName",
784            interface: "org.example.Node",
785            argument: "grape"
786        );
787        assert_eq!(sig, Signature::from_str_unchecked("u"));
788    }
789
790    #[test]
791    fn test_property_type_signature_macro() {
792        let sig = crate::property_type_signature!("Features");
793        assert_eq!(sig, Signature::from_str_unchecked("as"));
794    }
795
796    #[test]
797    fn test_property_type_signature_macro_with_identifier() {
798        let sig = crate::property_type_signature!(member: "Features");
799        assert_eq!(sig, Signature::from_str_unchecked("as"));
800    }
801
802    #[test]
803    fn test_property_type_signature_macro_with_interface() {
804        let sig = crate::property_type_signature!("Features", "org.example.Node");
805        assert_eq!(sig, Signature::from_str_unchecked("as"));
806    }
807
808    #[test]
809    fn test_property_type_signature_macro_with_interface_and_identifiers() {
810        let sig =
811            crate::property_type_signature!(member: "Features", interface: "org.example.Node");
812        assert_eq!(sig, Signature::from_str_unchecked("as"));
813    }
814}