| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #![cfg(test)] |
| |
| use { |
| crate::utils::Position, |
| crate::{ |
| consumer_controls_binding, input_device, input_handler, keyboard_binding, mouse_binding, |
| touch_binding, |
| }, |
| assert_matches::assert_matches, |
| fidl_fuchsia_input_report as fidl_input_report, fidl_fuchsia_ui_input as fidl_ui_input, |
| fidl_fuchsia_ui_input3 as fidl_ui_input3, fidl_fuchsia_ui_pointerinjector as pointerinjector, |
| fuchsia_zircon as zx, |
| futures::FutureExt as _, |
| maplit::hashmap, |
| std::collections::HashMap, |
| std::collections::HashSet, |
| }; |
| |
| /// Returns the current time as an i64 for InputReports and zx::Time for InputEvents. |
| pub fn event_times() -> (i64, zx::Time) { |
| let event_time = zx::Time::get_monotonic(); |
| (event_time.into_nanos(), event_time) |
| } |
| |
| /// Creates a [`fidl_input_report::InputReport`] with a keyboard report. |
| /// |
| /// # Parameters |
| /// -`pressed_keys`: The input3 keys that will be added to the returned input report. |
| /// -`event_time`: The time in nanoseconds when the event was first recorded. |
| pub fn create_keyboard_input_report( |
| pressed_keys: Vec<fidl_fuchsia_input::Key>, |
| event_time: i64, |
| ) -> fidl_input_report::InputReport { |
| fidl_input_report::InputReport { |
| event_time: Some(event_time), |
| keyboard: Some(fidl_input_report::KeyboardInputReport { |
| pressed_keys3: Some(pressed_keys), |
| ..fidl_input_report::KeyboardInputReport::EMPTY |
| }), |
| mouse: None, |
| touch: None, |
| sensor: None, |
| consumer_control: None, |
| trace_id: None, |
| ..fidl_input_report::InputReport::EMPTY |
| } |
| } |
| |
| /// Creates a new [input_device::InputEvent] from the provided components. |
| pub fn create_input_event( |
| keyboard_event: keyboard_binding::KeyboardEvent, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| event_time: zx::Time, |
| handled: input_device::Handled, |
| ) -> input_device::InputEvent { |
| input_device::InputEvent { |
| device_event: input_device::InputDeviceEvent::Keyboard(keyboard_event), |
| device_descriptor: device_descriptor.clone(), |
| event_time, |
| handled, |
| trace_id: None, |
| } |
| } |
| |
| /// Creates a [`keyboard_binding::KeyboardEvent`] with the provided keys, meaning, and handled state. |
| /// |
| /// # Parameters |
| /// - `key`: The input3 key which changed state. |
| /// - `event_type`: The input3 key event type (e.g. pressed, released). |
| /// - `modifiers`: The input3 modifiers that are to be included as pressed. |
| /// - `event_time`: The timestamp in nanoseconds when the event was recorded. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| /// - `handled`: Whether the event has been consumed by an upstream handler. |
| pub fn create_keyboard_event_with_handled( |
| key: fidl_fuchsia_input::Key, |
| event_type: fidl_fuchsia_ui_input3::KeyEventType, |
| modifiers: Option<fidl_ui_input3::Modifiers>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| keymap: Option<String>, |
| key_meaning: Option<fidl_fuchsia_ui_input3::KeyMeaning>, |
| handled: input_device::Handled, |
| ) -> input_device::InputEvent { |
| let keyboard_event = keyboard_binding::KeyboardEvent::new(key, event_type) |
| .into_with_modifiers(modifiers) |
| .into_with_keymap(keymap) |
| .into_with_key_meaning(key_meaning); |
| create_input_event(keyboard_event, device_descriptor, event_time, handled) |
| } |
| |
| /// Creates a [`keyboard_binding::KeyboardEvent`] with the provided keys and meaning. |
| /// a repeat sequence. |
| /// |
| /// # Parameters |
| /// - `key`: The input3 key which changed state. |
| /// - `event_type`: The input3 key event type (e.g. pressed, released). |
| /// - `modifiers`: The input3 modifiers that are to be included as pressed. |
| /// - `event_time`: The timestamp in nanoseconds when the event was recorded. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| /// - `repeat_sequence`: The sequence of this key event in the autorepeat process. |
| pub fn create_keyboard_event_with_key_meaning_and_repeat_sequence( |
| key: fidl_fuchsia_input::Key, |
| event_type: fidl_fuchsia_ui_input3::KeyEventType, |
| modifiers: Option<fidl_ui_input3::Modifiers>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| keymap: Option<String>, |
| key_meaning: Option<fidl_fuchsia_ui_input3::KeyMeaning>, |
| repeat_sequence: u32, |
| ) -> input_device::InputEvent { |
| let device_event = keyboard_binding::KeyboardEvent::new(key, event_type) |
| .into_with_modifiers(modifiers) |
| .into_with_key_meaning(key_meaning) |
| .into_with_keymap(keymap) |
| .into_with_repeat_sequence(repeat_sequence); |
| create_input_event(device_event, device_descriptor, event_time, input_device::Handled::No) |
| } |
| |
| /// Creates a [`keyboard_binding::KeyboardEvent`] with the provided keys and meaning. |
| /// |
| /// # Parameters |
| /// - `key`: The input3 key which changed state. |
| /// - `event_type`: The input3 key event type (e.g. pressed, released). |
| /// - `modifiers`: The input3 modifiers that are to be included as pressed. |
| /// - `event_time`: The timestamp in nanoseconds when the event was recorded. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| pub fn create_keyboard_event_with_key_meaning( |
| key: fidl_fuchsia_input::Key, |
| event_type: fidl_fuchsia_ui_input3::KeyEventType, |
| modifiers: Option<fidl_ui_input3::Modifiers>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| keymap: Option<String>, |
| key_meaning: Option<fidl_fuchsia_ui_input3::KeyMeaning>, |
| ) -> input_device::InputEvent { |
| create_keyboard_event_with_key_meaning_and_repeat_sequence( |
| key, |
| event_type, |
| modifiers, |
| event_time, |
| device_descriptor, |
| keymap, |
| key_meaning, |
| 0, |
| ) |
| } |
| |
| /// Creates a [`keyboard_binding::KeyboardEvent`] with the provided keys. |
| /// |
| /// # Parameters |
| /// - `key`: The input3 key which changed state. |
| /// - `event_type`: The input3 key event type (e.g. pressed, released). |
| /// - `modifiers`: The input3 modifiers that are to be included as pressed. |
| /// - `event_time`: The timestamp in nanoseconds when the event was recorded. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| pub fn create_keyboard_event( |
| key: fidl_fuchsia_input::Key, |
| event_type: fidl_fuchsia_ui_input3::KeyEventType, |
| modifiers: Option<fidl_ui_input3::Modifiers>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| keymap: Option<String>, |
| ) -> input_device::InputEvent { |
| create_keyboard_event_with_key_meaning( |
| key, |
| event_type, |
| modifiers, |
| event_time, |
| device_descriptor, |
| keymap, |
| None, |
| ) |
| } |
| |
| /// Creates a fake input event with the given event time. Please do not |
| /// read into other event fields. |
| pub fn create_fake_input_event(event_time: zx::Time) -> input_device::InputEvent { |
| input_device::InputEvent { |
| event_time, |
| device_event: input_device::InputDeviceEvent::Fake, |
| device_descriptor: input_device::InputDeviceDescriptor::Fake, |
| handled: input_device::Handled::No, |
| trace_id: None, |
| } |
| } |
| |
| /// Creates a fake handled input event with the given event time. Please do not |
| /// read into other event fields. |
| pub fn create_fake_handled_input_event(event_time: zx::Time) -> input_device::InputEvent { |
| input_device::InputEvent { |
| event_time, |
| device_event: input_device::InputDeviceEvent::Fake, |
| device_descriptor: input_device::InputDeviceDescriptor::Fake, |
| handled: input_device::Handled::Yes, |
| trace_id: None, |
| } |
| } |
| |
| /// Creates an [`input_device::InputDeviceDescriptor`] for a consumer controls device. |
| pub fn consumer_controls_device_descriptor() -> input_device::InputDeviceDescriptor { |
| input_device::InputDeviceDescriptor::ConsumerControls( |
| consumer_controls_binding::ConsumerControlsDeviceDescriptor { |
| buttons: vec![ |
| fidl_input_report::ConsumerControlButton::CameraDisable, |
| fidl_input_report::ConsumerControlButton::FactoryReset, |
| fidl_input_report::ConsumerControlButton::MicMute, |
| fidl_input_report::ConsumerControlButton::Pause, |
| fidl_input_report::ConsumerControlButton::VolumeDown, |
| fidl_input_report::ConsumerControlButton::VolumeUp, |
| ], |
| }, |
| ) |
| } |
| |
| /// Creates a [`fidl_input_report::InputReport`] with a consumer control report. |
| /// |
| /// # Parameters |
| /// - `buttons`: The buttons in the consumer control report. |
| /// - `event_time`: The time of event. |
| pub fn create_consumer_control_input_report( |
| buttons: Vec<fidl_input_report::ConsumerControlButton>, |
| event_time: i64, |
| ) -> fidl_input_report::InputReport { |
| fidl_input_report::InputReport { |
| event_time: Some(event_time), |
| keyboard: None, |
| mouse: None, |
| touch: None, |
| sensor: None, |
| consumer_control: Some(fidl_input_report::ConsumerControlInputReport { |
| pressed_buttons: Some(buttons), |
| ..fidl_input_report::ConsumerControlInputReport::EMPTY |
| }), |
| trace_id: None, |
| ..fidl_input_report::InputReport::EMPTY |
| } |
| } |
| |
| /// Creates a [`consumer_controls_binding::ConsumerControlsEvent`] with the provided parameters. |
| /// |
| /// # Parameters |
| /// - `pressed_buttons`: The buttons to report in the event. |
| /// - `event_time`: The time of event. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| /// - `handled`: Whether the event has been consumed. |
| pub fn create_consumer_controls_event_with_handled( |
| pressed_buttons: Vec<fidl_input_report::ConsumerControlButton>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| handled: input_device::Handled, |
| ) -> input_device::InputEvent { |
| input_device::InputEvent { |
| device_event: input_device::InputDeviceEvent::ConsumerControls( |
| consumer_controls_binding::ConsumerControlsEvent::new(pressed_buttons), |
| ), |
| device_descriptor: device_descriptor.clone(), |
| event_time, |
| handled, |
| trace_id: None, |
| } |
| } |
| |
| /// Creates a [`consumer_controls_binding::ConsumerControlsEvent`] with the provided parameters. |
| /// |
| /// # Parameters |
| /// - `pressed_buttons`: The buttons to report in the event. |
| /// - `event_time`: The time of event. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| pub fn create_consumer_controls_event( |
| pressed_buttons: Vec<fidl_input_report::ConsumerControlButton>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| ) -> input_device::InputEvent { |
| create_consumer_controls_event_with_handled( |
| pressed_buttons, |
| event_time, |
| device_descriptor, |
| input_device::Handled::No, |
| ) |
| } |
| |
| /// Creates a [`fidl_input_report::InputReport`] with a mouse report. |
| /// |
| /// # Parameters |
| /// - `location`: The movement or position of the mouse report, in input device coordinates. |
| /// [`MouseLocation::Relative`] represents movement, and |
| /// [`MouseLocation::Absolute`] represents position. |
| /// - `wheel_delta_v`: The wheel delta in vertical. |
| /// - `wheel_delta_h`: The wheel delta in horizontal. |
| /// - `buttons`: The buttons to report as pressed in the mouse report. |
| /// - `event_time`: The time of event. |
| pub fn create_mouse_input_report( |
| location: mouse_binding::MouseLocation, |
| scroll_v: Option<i64>, |
| scroll_h: Option<i64>, |
| buttons: Vec<u8>, |
| event_time: i64, |
| ) -> fidl_input_report::InputReport { |
| fidl_input_report::InputReport { |
| event_time: Some(event_time), |
| keyboard: None, |
| mouse: Some(fidl_input_report::MouseInputReport { |
| movement_x: match location { |
| mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation { |
| counts: Position { x, .. }, |
| millimeters: Position { .. }, |
| }) => Some(x as i64), |
| _ => None, |
| }, |
| movement_y: match location { |
| mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation { |
| counts: Position { y, .. }, |
| millimeters: Position { .. }, |
| }) => Some(y as i64), |
| _ => None, |
| }, |
| position_x: match location { |
| mouse_binding::MouseLocation::Absolute(Position { x, .. }) => Some(x as i64), |
| _ => None, |
| }, |
| position_y: match location { |
| mouse_binding::MouseLocation::Absolute(Position { y, .. }) => Some(y as i64), |
| _ => None, |
| }, |
| scroll_v: scroll_v, |
| scroll_h: scroll_h, |
| pressed_buttons: Some(buttons), |
| ..fidl_input_report::MouseInputReport::EMPTY |
| }), |
| touch: None, |
| sensor: None, |
| consumer_control: None, |
| trace_id: None, |
| ..fidl_input_report::InputReport::EMPTY |
| } |
| } |
| |
| /// Creates a [`mouse_binding::MouseEvent`] with the provided parameters. |
| /// |
| /// # Parameters |
| /// - `location`: The mouse location to report in the event. |
| /// - `wheel_delta_v`: The wheel delta in vertical. |
| /// - `wheel_delta_h`: The wheel delta in horizontal. |
| /// - `phase`: The phase of the buttons in the event. |
| /// - `buttons`: The buttons to report in the event. |
| /// - `event_time`: The time of event. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| pub fn create_mouse_event_with_handled( |
| location: mouse_binding::MouseLocation, |
| wheel_delta_v: Option<i64>, |
| wheel_delta_h: Option<i64>, |
| phase: mouse_binding::MousePhase, |
| affected_buttons: HashSet<mouse_binding::MouseButton>, |
| pressed_buttons: HashSet<mouse_binding::MouseButton>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| handled: input_device::Handled, |
| ) -> input_device::InputEvent { |
| input_device::InputEvent { |
| device_event: input_device::InputDeviceEvent::Mouse(mouse_binding::MouseEvent::new( |
| location, |
| wheel_delta_v, |
| wheel_delta_h, |
| phase, |
| affected_buttons, |
| pressed_buttons, |
| )), |
| device_descriptor: device_descriptor.clone(), |
| event_time, |
| handled, |
| trace_id: None, |
| } |
| } |
| |
| /// Creates a [`mouse_binding::MouseEvent`] with the provided parameters. |
| /// |
| /// # Parameters |
| /// - `location`: The mouse location to report in the event. |
| /// - `phase`: The phase of the buttons in the event. |
| /// - `buttons`: The buttons to report in the event. |
| /// - `event_time`: The time of event. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| pub fn create_mouse_event( |
| location: mouse_binding::MouseLocation, |
| wheel_delta_v: Option<i64>, |
| wheel_delta_h: Option<i64>, |
| phase: mouse_binding::MousePhase, |
| affected_buttons: HashSet<mouse_binding::MouseButton>, |
| pressed_buttons: HashSet<mouse_binding::MouseButton>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| ) -> input_device::InputEvent { |
| create_mouse_event_with_handled( |
| location, |
| wheel_delta_v, |
| wheel_delta_h, |
| phase, |
| affected_buttons, |
| pressed_buttons, |
| event_time, |
| device_descriptor, |
| input_device::Handled::No, |
| ) |
| } |
| |
| /// Creates a [`pointerinjector::Event`] representing a mouse event. |
| /// |
| /// # Parameters |
| /// - `phase`: The phase of the touch contact. |
| /// - `contact`: The touch contact to create the event for. |
| /// - `position`: The position of the contact in the viewport space. |
| /// - `relative_motion`: The relative motion fopr the event. |
| /// - `wheel_delta_v`: The wheel delta in vertical. |
| /// - `wheel_delta_h`: The wheel delta in horizontal. |
| /// - `event_time`: The time in nanoseconds when the event was first recorded. |
| pub fn create_mouse_pointer_sample_event( |
| phase: pointerinjector::EventPhase, |
| buttons: Vec<mouse_binding::MouseButton>, |
| position: crate::utils::Position, |
| relative_motion: Option<[f32; 2]>, |
| wheel_delta_v: Option<i64>, |
| wheel_delta_h: Option<i64>, |
| event_time: zx::Time, |
| ) -> pointerinjector::Event { |
| let pointer_sample = pointerinjector::PointerSample { |
| pointer_id: Some(0), |
| phase: Some(phase), |
| position_in_viewport: Some([position.x, position.y]), |
| scroll_v: wheel_delta_v, |
| scroll_h: wheel_delta_h, |
| pressed_buttons: Some(buttons), |
| relative_motion, |
| ..pointerinjector::PointerSample::EMPTY |
| }; |
| let data = pointerinjector::Data::PointerSample(pointer_sample); |
| |
| pointerinjector::Event { |
| timestamp: Some(event_time.into_nanos()), |
| data: Some(data), |
| ..pointerinjector::Event::EMPTY |
| } |
| } |
| |
| /// Creates a [`fidl_input_report::InputReport`] with a touch report. |
| /// |
| /// # Parameters |
| /// - `contacts`: The contacts in the touch report. |
| /// - `event_time`: The time of event. |
| pub fn create_touch_input_report( |
| contacts: Vec<fidl_input_report::ContactInputReport>, |
| event_time: i64, |
| ) -> fidl_input_report::InputReport { |
| fidl_input_report::InputReport { |
| event_time: Some(event_time), |
| keyboard: None, |
| mouse: None, |
| touch: Some(fidl_input_report::TouchInputReport { |
| contacts: Some(contacts), |
| pressed_buttons: None, |
| ..fidl_input_report::TouchInputReport::EMPTY |
| }), |
| sensor: None, |
| consumer_control: None, |
| trace_id: None, |
| ..fidl_input_report::InputReport::EMPTY |
| } |
| } |
| |
| pub fn create_touch_contact(id: u32, position: Position) -> touch_binding::TouchContact { |
| touch_binding::TouchContact { id, position, pressure: None, contact_size: None } |
| } |
| |
| /// Creates a [`touch_binding::TouchEvent`] with the provided parameters. |
| /// |
| /// # Parameters |
| /// - `contacts`: The contacts in the touch report. |
| /// - `event_time`: The time of event. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| /// - `handled`: Whether the event has been consumed. |
| pub fn create_touch_event_with_handled( |
| mut contacts: HashMap<fidl_ui_input::PointerEventPhase, Vec<touch_binding::TouchContact>>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| handled: input_device::Handled, |
| ) -> input_device::InputEvent { |
| contacts.entry(fidl_ui_input::PointerEventPhase::Add).or_insert(vec![]); |
| contacts.entry(fidl_ui_input::PointerEventPhase::Down).or_insert(vec![]); |
| contacts.entry(fidl_ui_input::PointerEventPhase::Move).or_insert(vec![]); |
| contacts.entry(fidl_ui_input::PointerEventPhase::Up).or_insert(vec![]); |
| contacts.entry(fidl_ui_input::PointerEventPhase::Remove).or_insert(vec![]); |
| |
| let injector_contacts = hashmap! { |
| pointerinjector::EventPhase::Add => |
| contacts.get(&fidl_ui_input::PointerEventPhase::Add).unwrap().clone(), |
| pointerinjector::EventPhase::Change => |
| contacts.get(&fidl_ui_input::PointerEventPhase::Move).unwrap().clone(), |
| pointerinjector::EventPhase::Remove => |
| contacts.get(&fidl_ui_input::PointerEventPhase::Remove).unwrap().clone(), |
| }; |
| input_device::InputEvent { |
| device_event: input_device::InputDeviceEvent::Touch(touch_binding::TouchEvent { |
| contacts, |
| injector_contacts, |
| }), |
| device_descriptor: device_descriptor.clone(), |
| event_time, |
| handled: handled, |
| trace_id: None, |
| } |
| } |
| |
| /// Creates a [`touch_binding::TouchEvent`] with the provided parameters. |
| /// |
| /// # Parameters |
| /// - `contacts`: The contacts in the touch report. |
| /// - `event_time`: The time of event. |
| /// - `device_descriptor`: The device descriptor to add to the event. |
| pub fn create_touch_event( |
| contacts: HashMap<fidl_ui_input::PointerEventPhase, Vec<touch_binding::TouchContact>>, |
| event_time: zx::Time, |
| device_descriptor: &input_device::InputDeviceDescriptor, |
| ) -> input_device::InputEvent { |
| create_touch_event_with_handled( |
| contacts, |
| event_time, |
| device_descriptor, |
| input_device::Handled::No, |
| ) |
| } |
| |
| /// Creates a [`fidl_ui_scenic::Command`] representing the given touch contact. |
| /// |
| /// # Parameters |
| /// - `phase`: The phase of the touch contact. |
| /// - `contact`: The touch contact to create the event for. |
| /// - `position`: The position of the contact in the viewport space. |
| /// - `event_time`: The time in nanoseconds when the event was first recorded. |
| pub fn create_touch_pointer_sample_event( |
| phase: pointerinjector::EventPhase, |
| contact: &touch_binding::TouchContact, |
| position: crate::utils::Position, |
| event_time: zx::Time, |
| ) -> pointerinjector::Event { |
| let pointer_sample = pointerinjector::PointerSample { |
| pointer_id: Some(contact.id), |
| phase: Some(phase), |
| position_in_viewport: Some([position.x, position.y]), |
| scroll_v: None, |
| scroll_h: None, |
| pressed_buttons: None, |
| ..pointerinjector::PointerSample::EMPTY |
| }; |
| let data = pointerinjector::Data::PointerSample(pointer_sample); |
| |
| pointerinjector::Event { |
| timestamp: Some(event_time.into_nanos()), |
| data: Some(data), |
| trace_flow_id: Some(fuchsia_trace::generate_nonce()), |
| ..pointerinjector::Event::EMPTY |
| } |
| } |
| |
| /// Asserts that the given sequence of input reports generates the provided input events |
| /// when the reports are processed by the given device type. |
| #[macro_export] |
| macro_rules! assert_input_report_sequence_generates_events { |
| ( |
| // The input reports to process. |
| input_reports: $input_reports:expr, |
| // The events which are expected. |
| expected_events: $expected_events:expr, |
| // The descriptor for the device that is sent to the input processor. |
| device_descriptor: $device_descriptor:expr, |
| // The type of device generating the events. |
| device_type: $DeviceType:ty, |
| ) => { |
| let mut previous_report: Option<fidl_fuchsia_input_report::InputReport> = None; |
| let (event_sender, mut event_receiver) = futures::channel::mpsc::channel(std::cmp::max( |
| $input_reports.len(), |
| $expected_events.len(), |
| )); |
| |
| // Send all the reports prior to verifying the received events. |
| for report in $input_reports { |
| previous_report = <$DeviceType>::process_reports( |
| report, |
| previous_report, |
| &$device_descriptor, |
| &mut event_sender.clone(), |
| ); |
| } |
| |
| for expected_event in $expected_events { |
| let input_event = event_receiver.next().await; |
| match input_event { |
| Some(mut received_event) => { |
| // The trace_id field is set to a nonce value by process_reports(), so a naive |
| // comparison to an expected event will not match. Here, we set it to None to |
| // allow comparing against an expected event, but we ensure trace_id is set |
| // properly with another test. |
| received_event.trace_id = None; |
| pretty_assertions::assert_eq!(expected_event, received_event) |
| } |
| _ => assert!(false), |
| }; |
| } |
| }; |
| } |
| |
| /// Asserts that the given sequence of input events generates the provided Scenic commands when the |
| /// events are processed by the given input handler. |
| #[macro_export] |
| macro_rules! assert_input_event_sequence_generates_scenic_events { |
| ( |
| // The input handler that will handle input events. |
| input_handler: $input_handler:expr, |
| // The InputEvents to handle. |
| input_events: $input_events:expr, |
| // The commands the Scenic session should receive. |
| expected_commands: $expected_commands:expr, |
| // The Scenic session request stream. |
| scenic_session_request_stream: $scenic_session_request_stream:expr, |
| // A function to validate the Scenic commands. |
| assert_command: $assert_command:expr, |
| ) => { |
| for input_event in $input_events { |
| assert_matches!( |
| $input_handler.clone().handle_input_event(input_event).await.as_slice(), |
| [input_device::InputEvent { handled: input_device::Handled::Yes, .. }] |
| ); |
| } |
| |
| let mut expected_command_iter = $expected_commands.into_iter().peekable(); |
| while let Some(request) = $scenic_session_request_stream.next().await { |
| match request { |
| Ok(fidl_ui_scenic::SessionRequest::Enqueue { cmds, control_handle: _ }) => { |
| let mut command_iter = cmds.into_iter().peekable(); |
| while let Some(command) = command_iter.next() { |
| let expected_command = expected_command_iter.next().unwrap(); |
| $assert_command(command, expected_command); |
| |
| // All the expected events have been received, so make sure no more events |
| // are present before returning. |
| if expected_command_iter.peek().is_none() { |
| assert!(command_iter.peek().is_none()); |
| return; |
| } |
| } |
| } |
| _ => { |
| assert!(false); |
| } |
| } |
| } |
| }; |
| } |
| |
| /// Asserts that the given sequence of input events generates the provided media buttons events when |
| /// the input events are processed by the given input handler. |
| #[macro_export] |
| macro_rules! assert_input_event_sequence_generates_media_buttons_events { |
| ( |
| // The input handler that will handle input events. |
| input_handler: $input_handler:expr, |
| // The InputEvents to handle. |
| input_events: $input_events:expr, |
| // The events the listeners should receive. |
| expected_events: $expected_events:expr, |
| // The media buttons listener request stream(s). |
| media_buttons_listener_request_stream: $media_buttons_listener_request_stream:expr, |
| ) => { |
| fasync::Task::local(async move { |
| for input_event in $input_events { |
| assert_matches!( |
| $input_handler.clone().handle_input_event(input_event).await.as_slice(), |
| [input_device::InputEvent { handled: input_device::Handled::Yes, .. }] |
| ); |
| } |
| }) |
| .detach(); |
| |
| for mut stream in $media_buttons_listener_request_stream { |
| let mut expected_command_iter = $expected_events.clone().into_iter().peekable(); |
| while let Some(request) = stream.next().await { |
| match request { |
| Ok(fidl_ui_policy::MediaButtonsListenerRequest::OnEvent { |
| event, |
| responder, |
| }) => { |
| let expected_command = expected_command_iter.next().unwrap(); |
| pretty_assertions::assert_eq!(event, expected_command); |
| let _ = responder.send(); |
| |
| // All the expected events have been received, so make sure no more |
| // events are present before continuing to the next stream. |
| if expected_command_iter.peek().is_none() { |
| break; |
| } |
| } |
| _ => assert!(false), |
| } |
| } |
| } |
| }; |
| } |
| |
| /// Asserts that the given sequence of input events are ignored by the provided handler and request stream. |
| pub async fn assert_handler_ignores_input_event_sequence( |
| // The handler processing events. |
| input_handler: std::rc::Rc<dyn input_handler::InputHandler>, |
| // The InputEvents to handle. |
| input_events: Vec<input_device::InputEvent>, |
| // The listener request stream. |
| mut request_stream: impl futures::StreamExt + std::marker::Unpin, |
| ) { |
| for input_event in input_events { |
| assert_matches!( |
| input_handler.clone().handle_input_event(input_event).await.as_slice(), |
| [input_device::InputEvent { handled: input_device::Handled::Yes, .. }] |
| ); |
| } |
| |
| // The request stream should not receive any events. |
| assert!(request_stream.next().now_or_never().is_none()); |
| } |