1macro_rules! impl_event_properties {
21 ($type:ty) => {
22 impl EventProperties for $type {
23 fn sender(&self) -> UniqueName<'_> {
24 self.item.name.as_ref()
25 }
26 fn path(&self) -> ObjectPath<'_> {
27 self.item.path.as_ref()
28 }
29 }
30 };
31}
32
33macro_rules! impl_from_object_ref {
50 ($type:ty) => {
51 impl From<crate::ObjectRef> for $type {
52 fn from(obj_ref: crate::ObjectRef) -> Self {
53 Self { item: obj_ref }
54 }
55 }
56 };
57}
58
59macro_rules! impl_from_interface_event_enum_for_event {
75 ($outer_type:ty, $outer_variant:path) => {
76 #[cfg(feature = "wrappers")]
77 impl From<$outer_type> for Event {
78 fn from(event_variant: $outer_type) -> Event {
79 $outer_variant(event_variant.into())
80 }
81 }
82 };
83}
84
85macro_rules! impl_try_from_event_for_interface_enum {
106 ($outer_type:ty, $outer_variant:path) => {
107 impl TryFrom<Event> for $outer_type {
108 type Error = AtspiError;
109 fn try_from(generic_event: Event) -> Result<$outer_type, Self::Error> {
110 if let $outer_variant(event_type) = generic_event {
111 Ok(event_type)
112 } else {
113 Err(AtspiError::Conversion("Invalid type"))
114 }
115 }
116 }
117 };
118}
119
120macro_rules! impl_from_user_facing_event_for_interface_event_enum {
137 ($inner_type:ty, $outer_type:ty, $inner_variant:path) => {
138 impl From<$inner_type> for $outer_type {
139 fn from(specific_event: $inner_type) -> $outer_type {
140 $inner_variant(specific_event)
141 }
142 }
143 };
144}
145
146macro_rules! impl_from_user_facing_type_for_event_enum {
166 ($inner_type:ty, $outer_variant:path) => {
167 #[cfg(feature = "wrappers")]
168 impl From<$inner_type> for Event {
169 fn from(event_variant: $inner_type) -> Event {
170 $outer_variant(event_variant.into())
171 }
172 }
173 };
174}
175
176macro_rules! impl_try_from_event_for_user_facing_type {
199 ($inner_type:ty, $inner_variant:path, $outer_variant:path) => {
200 #[cfg(feature = "wrappers")]
201 impl TryFrom<Event> for $inner_type {
202 type Error = AtspiError;
203 fn try_from(generic_event: Event) -> Result<$inner_type, Self::Error> {
204 if let $outer_variant($inner_variant(specific_event)) = generic_event {
205 Ok(specific_event)
206 } else {
207 Err(AtspiError::Conversion("Invalid type"))
208 }
209 }
210 }
211 };
212}
213
214macro_rules! impl_to_dbus_message {
238 ($type:ty) => {
239 #[cfg(feature = "zbus")]
240 impl TryFrom<$type> for zbus::Message {
241 type Error = AtspiError;
242 fn try_from(event: $type) -> Result<Self, Self::Error> {
243 Ok(zbus::Message::signal(
244 event.path(),
245 <$type as BusProperties>::DBUS_INTERFACE,
246 <$type as BusProperties>::DBUS_MEMBER,
247 )?
248 .sender(event.sender().to_string())?
249 .build(&event.body())?)
250 }
251 }
252 };
253}
254
255macro_rules! impl_from_dbus_message {
278 ($type:ty) => {
279 impl_from_dbus_message!($type, Auto);
280 };
281 ($type:ty, Auto) => {
282 #[cfg(feature = "zbus")]
283 impl TryFrom<&zbus::Message> for $type {
284 type Error = AtspiError;
285 fn try_from(msg: &zbus::Message) -> Result<Self, Self::Error> {
286 use zvariant::Type;
287
288 Self::validate_interface(msg)?;
289 Self::validate_member(msg)?;
290
291 let body = msg.body();
292 let body_signature = body.signature();
293 let deser_body: <Self as MessageConversion>::Body = if body_signature == crate::events::EventBodyOwned::SIGNATURE {
294 body.deserialize_unchecked()?
295 } else if body_signature == crate::events::EventBodyQtOwned::SIGNATURE {
296 let qtbody: crate::events::EventBodyQtOwned = body.deserialize_unchecked()?;
297 qtbody.into()
298 } else {
299 return Err(AtspiError::SignatureMatch(format!(
300 "The message signature {} does not match the signal's body signature: {}",
301 body_signature,
302 <Self as MessageConversion>::Body::SIGNATURE,
303 )));
304 };
305 let item = msg.try_into()?;
306 Self::from_message_unchecked_parts(item, deser_body)
307 }
308 }
309 };
310 ($type:ty, Explicit) => {
311 #[cfg(feature = "zbus")]
312 impl TryFrom<&zbus::Message> for $type {
313 type Error = AtspiError;
314 fn try_from(msg: &zbus::Message) -> Result<Self, Self::Error> {
315 <$type as MessageConversionExt<<$type as MessageConversion>::Body>>::try_from_message(msg)
316 }
317 }
318 };
319}
320
321#[cfg(test)]
333macro_rules! generic_event_test_case {
334 ($type:ty) => {
335 #[test]
336 fn generic_event_uses() {
337 let struct_event = <$type>::default();
338 assert_eq!(struct_event.path().as_str(), "/org/a11y/atspi/accessible/null");
339 assert_eq!(struct_event.sender().as_str(), ":0.0");
340 let body = struct_event.body();
341 let body2 = Message::method_call(
342 struct_event.path().as_str(),
343 <$type as BusProperties>::DBUS_MEMBER,
344 )
345 .unwrap()
346 .sender(struct_event.sender().as_str())
347 .unwrap()
348 .build(&(body,))
349 .unwrap();
350 let build_struct = <$type>::from_message_unchecked(&body2)
351 .expect("<$type as Default>'s parts should build a valid ObjectRef");
352 assert_eq!(struct_event, build_struct);
353 }
354 };
355}
356
357#[cfg(test)]
368macro_rules! event_enum_test_case {
369 ($type:ty) => {
370 #[test]
371 fn event_enum_conversion() {
372 let struct_event = <$type>::default();
373 let event = Event::from(struct_event.clone());
374 let struct_event_back = <$type>::try_from(event)
375 .expect("Should convert event enum into specific event type because it was created from it. Check the `impl_from_interface_event_enum_for_event` macro");
376 assert_eq!(struct_event, struct_event_back);
377 }
378 };
379}
380
381#[cfg(test)]
397macro_rules! event_enum_transparency_test_case {
398 ($type:ty) => {
399 #[test]
400 fn event_enum_transparency_test_case() {
401 let specific_event = <$type>::default();
402 let generic_event = Event::from(specific_event.clone());
403 assert_eq!(
404 specific_event.member(),
405 generic_event.member(),
406 "DBus member strings do not match."
407 );
408 assert_eq!(
409 specific_event.interface(),
410 generic_event.interface(),
411 "Registry interfaces do not match."
412 );
413 assert_eq!(
414 specific_event.registry_string(),
415 generic_event.registry_string(),
416 "Registry strings do not match."
417 );
418 assert_eq!(
419 specific_event.match_rule(),
420 generic_event.match_rule(),
421 "Match rule strings do not match."
422 );
423 assert_eq!(specific_event.path(), generic_event.path(), "Pathsdo not match.");
424 assert_eq!(specific_event.sender(), generic_event.sender(), "Senders do not match.");
425 }
426 };
427}
428
429#[cfg(test)]
430macro_rules! zbus_message_qtspi_test_case {
431 ($type:ty, Auto) => {
432 #[cfg(feature = "zbus")]
433 #[test]
434 fn zbus_message_conversion_qtspi() {
435 let ev = <$type>::default();
438 let qt: crate::events::EventBodyQtOwned = ev.body().into();
439 let msg = zbus::Message::signal(
440 ev.path(),
441 ev.interface(),
442 ev.member(),
443 )
444 .unwrap()
445 .sender(":0.0")
446 .unwrap()
447 .build(&(qt,))
448 .unwrap();
449 <$type>::try_from(&msg).expect("Should be able to use an EventBodyQtOwned for any type whose BusProperties::Body = EventBodyOwned");
450 }
451 #[cfg(feature = "zbus")]
452 #[test]
453 fn zbus_message_conversion_qtspi_event_enum() {
454 let ev = <$type>::default();
457 let qt: crate::events::EventBodyQtOwned = ev.body().into();
458 let msg = zbus::Message::signal(
459 ev.path(),
460 ev.interface(),
461 ev.member(),
462 )
463 .unwrap()
464 .sender(":0.0")
465 .unwrap()
466 .build(&(qt,))
467 .unwrap();
468 assert_matches!(Event::try_from(&msg), Ok(_));
469 }
470 };
471 ($type:ty, Explicit) => {};
472}
473
474#[cfg(test)]
480macro_rules! zbus_message_test_case {
481 ($type:ty) => {
482 zbus_message_test_case!($type, Auto);
483 };
484 ($type:ty, $extra:tt) => {
485 zbus_message_qtspi_test_case!($type, $extra);
486 #[cfg(feature = "zbus")]
487 #[test]
488 fn zbus_msg_conversion_to_specific_event_type() {
489 let struct_event = <$type>::default();
490 let msg: zbus::Message = zbus::Message::try_from(struct_event.clone())
491 .expect("Should convert a `$type::default()` into a message. Check the `impl_to_dbus_message` macro .");
492 let struct_event_back =
493 <$type>::try_from(&msg).expect("Should convert from `$type::default()` originated `Message` back into a specific event type. Check the `impl_from_dbus_message` macro.");
494 assert_eq!(struct_event, struct_event_back, "Events converted into a message and back must be the same");
495 }
496
497 #[cfg(feature = "zbus")]
498 #[test]
499 fn zbus_msg_conversion_to_event_enum_type() {
500 let struct_event = <$type>::default();
501 let msg: zbus::Message = zbus::Message::try_from(struct_event.clone()).expect("Should convert a `$type::default()` into a message. Check the `impl_to_dbus_message` macro .");
502 let event_enum_back =
503 Event::try_from(&msg).expect("Should convert a from `$type::default()` built `Message` into an event enum. Check the `impl_from_dbus_message` macro .");
504 let event_enum: Event = struct_event.into();
505 assert_eq!(event_enum, event_enum_back);
506 }
507 #[cfg(feature = "zbus")]
510 #[test]
511 fn zbus_msg_conversion_failure_fake_msg() -> () {
512 let fake_msg = zbus::Message::signal(
513 "/org/a11y/sixtynine/fourtwenty",
514 "org.a11y.atspi.technically.valid",
515 "MadeUpMember",
516 )
517 .unwrap()
518 .sender(":0.0")
519 .unwrap()
520 .build(&())
521 .unwrap();
522 let event = <$type>::try_from(&fake_msg);
523 assert_matches!(event, Err(_), "This conversion should fail");
524 }
525
526 #[cfg(feature = "zbus")]
527 #[test]
528 fn zbus_msg_conversion_validated_message_with_body() -> () {
529 let fake_msg = zbus::Message::signal(
530 "/org/a11y/sixtynine/fourtwenty",
531 "org.a11y.atspi.technically.valid",
532 "MadeUpMember",
533 )
534 .unwrap()
535 .sender(":0.0")
536 .unwrap()
537 .build(&<$type>::default().body())
538 .unwrap();
539 let event = <$type>::from_message_unchecked(&fake_msg);
540 event.expect("The from_message_unchecked function should work, despite mismatching interface and member");
541 }
542
543 #[cfg(feature = "zbus")]
544 #[test]
545 fn zbus_msg_conversion_failure_correct_interface() -> () {
546 let fake_msg = zbus::Message::signal(
547 "/org/a11y/sixtynine/fourtwenty",
548 <$type as BusProperties>::DBUS_INTERFACE,
549 "MadeUpMember",
550 )
551 .unwrap()
552 .sender(":0.0")
553 .unwrap()
554 .build(&())
555 .unwrap();
556 let event = <$type>::try_from(&fake_msg);
557 assert_matches!(event, Err(AtspiError::MemberMatch(_)), "Wrong kind of error");
558 }
559
560 #[cfg(feature = "zbus")]
561 #[test]
562 fn zbus_msg_conversion_failure_correct_interface_and_member() -> () {
563 let fake_msg = zbus::Message::signal(
564 "/org/a11y/sixtynine/fourtwenty",
565 <$type as BusProperties>::DBUS_INTERFACE,
566 <$type as BusProperties>::DBUS_MEMBER,
567 )
568 .unwrap()
569 .sender(":0.0")
570 .unwrap()
571 .build(&())
572 .unwrap();
573 let event = <$type>::try_from(&fake_msg);
574 assert_matches!(event, Err(AtspiError::SignatureMatch(_)), "Wrong kind of error");
575 }
576
577 #[cfg(feature = "zbus")]
578 #[test]
579 fn zbus_msg_conversion_failure_correct_interface_and_member_invalid_body() -> () {
580 let invalid_body: (i32, u64, String, String) = (0, 0, String::new(), String::new());
582 let fake_msg = zbus::Message::signal(
583 "/org/a11y/sixtynine/fourtwenty",
584 <$type as BusProperties>::DBUS_INTERFACE,
585 <$type as BusProperties>::DBUS_MEMBER,
586 )
587 .unwrap()
588 .sender(":0.0")
589 .unwrap()
590 .build(&invalid_body)
591 .unwrap();
592 let event = <$type>::try_from(&fake_msg);
593 assert_matches!(event, Err(AtspiError::SignatureMatch(_)), "Wrong kind of error");
594 }
595
596 #[cfg(feature = "zbus")]
597 #[test]
598 fn zbus_msg_conversion_failure_correct_body() -> () {
599 let fake_msg = zbus::Message::signal(
600 "/org/a11y/sixtynine/fourtwenty",
601 "org.a11y.atspi.accessible.technically.valid",
602 "FakeMember",
603 )
604 .unwrap()
605 .sender(":0.0")
606 .unwrap()
607 .build(&<$type>::default().body())
608 .unwrap();
609 let event = <$type>::try_from(&fake_msg);
610 assert_matches!(event, Err(_));
611 }
612
613 #[cfg(feature = "zbus")]
614 #[test]
615 fn zbus_msg_conversion_failure_correct_body_and_member() -> () {
616 let fake_msg = zbus::Message::signal(
617 "/org/a11y/sixtynine/fourtwenty",
618 "org.a11y.atspi.accessible.technically.valid",
619 <$type as BusProperties>::DBUS_MEMBER,
620 )
621 .unwrap()
622 .sender(":0.0")
623 .unwrap()
624 .build(&<$type>::default().body())
625 .unwrap();
626 let event = <$type>::try_from(&fake_msg);
627 assert_matches!(event, Err(AtspiError::InterfaceMatch(_)), "Wrong kind of error");
628 }
629 #[cfg(feature = "zbus")]
630 #[test]
631 fn zbus_msg_conversion_failure_correct_body_and_interface() -> () {
632 let fake_msg = zbus::Message::signal(
633 "/org/a11y/sixtynine/fourtwenty",
634 <$type as BusProperties>::DBUS_INTERFACE,
635 "MadeUpMember",
636 )
637 .unwrap()
638 .sender(":0.0")
639 .unwrap()
640 .build(&<$type>::default().body())
641 .unwrap();
642 let event = <$type>::try_from(&fake_msg);
643 assert_matches!(event, Err(AtspiError::MemberMatch(_)), "Wrong kind of error");
644 }
645 };
646}
647
648macro_rules! event_wrapper_test_cases {
667 ($type:ty, $any_subtype:ty) => {
668 #[cfg(test)]
669 #[rename_item::rename(name($type), prefix = "events_tests_", case = "snake")]
670 mod foo {
671 use super::{$any_subtype, $type, AtspiError, Event, BusProperties, MessageConversion};
672 use assert_matches::assert_matches;
674 #[test]
675 fn into_and_try_from_event() {
676 let sub_type = <$any_subtype>::default();
678 let mod_type = <$type>::from(sub_type);
680 let event = Event::from(mod_type.clone());
682 let mod_type2 = <$type>::try_from(event.clone())
684 .expect("Should convert outer `Event` enum into interface enum because it was created from it. Check the `impl_try_from_event_for_user_facing_event_type` macro");
685 assert_eq!(
686 mod_type, mod_type2,
687 "Events were able to be parsed and encapsulated, but they have changed value"
688 );
689 }
690 #[cfg(feature = "zbus")]
691 #[test]
692 fn zbus_msg_invalid_interface() {
693 let fake_msg = zbus::Message::signal(
694 "/org/a11y/sixtynine/fourtwenty",
695 "org.a11y.atspi.technically.valid.lol",
696 <$any_subtype as BusProperties>::DBUS_MEMBER,
697 )
698 .unwrap()
699 .sender(":0.0")
700 .unwrap()
701 .build(&<$any_subtype>::default().body())
702 .unwrap();
703
704 let mod_type = <$type>::try_from(&fake_msg);
715 let event_type = Event::try_from(&fake_msg);
716 assert_matches!(mod_type, Err(AtspiError::InterfaceMatch(_)), "Wrong kind of error");
717 assert_matches!(event_type, Err(AtspiError::InterfaceMatch(_)), "Wrong kind of error");
718 }
719 #[cfg(feature = "zbus")]
720 #[test]
721 fn zbus_msg_invalid_member() {
722 let fake_msg = zbus::Message::signal(
723 "/org/a11y/sixtynine/fourtwenty",
724 <$any_subtype as BusProperties>::DBUS_INTERFACE,
725 "FakeFunctionLol",
726 )
727 .unwrap()
728 .sender(":0.0")
729 .unwrap()
730 .build(&<$any_subtype>::default().body())
731 .unwrap();
732 let mod_type = <$type>::try_from(&fake_msg);
734 assert_matches!(mod_type, Err(AtspiError::MemberMatch(_)), "Wrong kind of error");
735 }
736 #[cfg(feature = "zbus")]
737 #[test]
738 fn zbus_msg_invalid_member_and_interface() {
739 let fake_msg = zbus::Message::signal(
740 "/org/a11y/sixtynine/fourtwenty",
741 "org.a11y.atspi.technically.allowed",
742 "FakeFunctionLol",
743 )
744 .unwrap()
745 .sender(":0.0")
746 .unwrap()
747 .build(&<$any_subtype>::default().body())
748 .unwrap();
749 let mod_type = <$type>::try_from(&fake_msg);
751
752 assert_matches!(mod_type, Err(AtspiError::InterfaceMatch(_)), "Wrong kind of error");
754 }
755 #[cfg(feature = "zbus")]
756 #[test]
757 fn zbus_msg_conversion() {
758 let valid_msg = zbus::Message::signal(
759 "/org/a11y/sixtynine/fourtwenty",
760 <$any_subtype as BusProperties>::DBUS_INTERFACE,
761 <$any_subtype as BusProperties>::DBUS_MEMBER,
762 )
763 .unwrap()
764 .sender(":0.0")
765 .unwrap()
766 .build(&<$any_subtype>::default().body())
767 .unwrap();
768 let mod_type = <$type>::try_from(&valid_msg);
770 mod_type.expect("Should convert from `$any_subtype::default()` built `Message` back into a interface event enum variant wrapping an inner type. Check the `impl_from_dbus_message` macro.");
771 }
772 }
773 };
774}
775
776macro_rules! event_test_cases {
777 ($type:ty) => {
778 event_test_cases!($type, Auto);
779 };
780 ($type:ty, $qt:tt) => {
781 #[cfg(test)]
782 #[rename_item::rename(name($type), prefix = "event_tests_", case = "snake")]
783 mod foo {
784 use crate::{EventTypeProperties, Event};
785 use super::{$type, AtspiError, BusProperties, MessageConversion, EventProperties};
786 use zbus::Message;
787 use assert_matches::assert_matches;
789
790 generic_event_test_case!($type);
791 event_enum_test_case!($type);
792 zbus_message_test_case!($type, $qt);
793 event_enum_transparency_test_case!($type);
794 }
795 assert_impl_all!(
796 $type: Clone,
797 std::fmt::Debug,
798 serde::Serialize,
799 serde::Deserialize<'static>,
800 Default,
801 PartialEq,
802 Eq,
803 std::hash::Hash,
804 crate::EventProperties,
805 crate::EventTypeProperties,
806 crate::BusProperties,
807 );
808 #[cfg(feature = "zbus")]
809 assert_impl_all!(zbus::Message: TryFrom<$type>);
810 };
811}