| // Copyright 2019 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. |
| |
| use { |
| anyhow::{Context as _, Error}, |
| fidl_fuchsia_intl::{LocaleId, TemperatureUnit, TimeZoneId}, |
| fidl_fuchsia_media::AudioRenderUsage, |
| fidl_fuchsia_settings::*, |
| fidl_fuchsia_settings_policy::{ |
| PolicyParameters, Property, Target, Transform, Volume as PolicyVolume, |
| VolumePolicyControllerMarker, VolumePolicyControllerRequest, |
| VolumePolicyControllerRequestStream, |
| }, |
| fuchsia_async as fasync, |
| fuchsia_component::server::ServiceFs, |
| futures::prelude::*, |
| parking_lot::RwLock, |
| setui_client_lib::accessibility, |
| setui_client_lib::audio, |
| setui_client_lib::device, |
| setui_client_lib::display, |
| setui_client_lib::do_not_disturb, |
| setui_client_lib::factory_reset, |
| setui_client_lib::input, |
| setui_client_lib::intl, |
| setui_client_lib::light, |
| setui_client_lib::night_mode, |
| setui_client_lib::privacy, |
| setui_client_lib::setup, |
| setui_client_lib::utils, |
| setui_client_lib::volume_policy, |
| setui_client_lib::{ |
| AccessibilityOptions, CaptionCommands, CaptionFontStyle, CaptionOptions, |
| VolumePolicyCommands, VolumePolicyOptions, |
| }, |
| std::sync::Arc, |
| }; |
| |
| /// Validate that the results of the call are successful, and in the case of watch, |
| /// that the first item can be retrieved, but do not analyze the result. |
| macro_rules! assert_successful { |
| ($expr:expr) => { |
| // We only need an extra check on the watch so we can exercise it at least once. |
| // The sets already return a result. |
| if let ::setui_client_lib::utils::Either::Watch(mut stream) = $expr.await? { |
| stream.try_next().await?; |
| } |
| }; |
| } |
| |
| /// Validate that the results of the call are a successful set and return the result. |
| macro_rules! assert_set { |
| ($expr:expr) => { |
| match $expr.await? { |
| ::setui_client_lib::utils::Either::Set(output) => output, |
| ::setui_client_lib::utils::Either::Watch(_) => { |
| panic!("Did not expect a watch result for a set call") |
| } |
| ::setui_client_lib::utils::Either::Get(_) => { |
| panic!("Did not expect a get result for a set call") |
| } |
| } |
| }; |
| } |
| |
| /// Validate that the results of the call are a successful watch and return the |
| /// first result. |
| macro_rules! assert_watch { |
| ($expr:expr) => { |
| match $expr.await? { |
| ::setui_client_lib::utils::Either::Watch(mut stream) => { |
| stream.try_next().await?.expect("Watch should have a result") |
| } |
| ::setui_client_lib::utils::Either::Set(_) => { |
| panic!("Did not expect a set result for a watch call") |
| } |
| ::setui_client_lib::utils::Either::Get(_) => { |
| panic!("Did not expect a get result for a watch call") |
| } |
| } |
| }; |
| } |
| |
| /// Validate that the results of the call are a successful get and return the result. |
| macro_rules! assert_get { |
| ($expr:expr) => { |
| match $expr.await? { |
| ::setui_client_lib::utils::Either::Get(output) => output, |
| ::setui_client_lib::utils::Either::Watch(_) => { |
| panic!("Did not expect a watch result for a get call") |
| } |
| ::setui_client_lib::utils::Either::Set(_) => { |
| panic!("Did not expect a set result for a get call") |
| } |
| } |
| }; |
| } |
| |
| enum Services { |
| Accessibility(AccessibilityRequestStream), |
| Audio(AudioRequestStream), |
| Device(DeviceRequestStream), |
| Display(DisplayRequestStream), |
| DoNotDisturb(DoNotDisturbRequestStream), |
| FactoryReset(FactoryResetRequestStream), |
| Input(InputRequestStream), |
| Intl(IntlRequestStream), |
| Light(LightRequestStream), |
| NightMode(NightModeRequestStream), |
| Privacy(PrivacyRequestStream), |
| Setup(SetupRequestStream), |
| VolumePolicy(VolumePolicyControllerRequestStream), |
| } |
| |
| struct ExpectedStreamSettingsStruct { |
| stream: Option<AudioRenderUsage>, |
| source: Option<fidl_fuchsia_settings::AudioStreamSettingSource>, |
| level: Option<f32>, |
| volume_muted: Option<bool>, |
| input_muted: Option<bool>, |
| } |
| |
| const ENV_NAME: &str = "setui_client_test_environment"; |
| const TEST_BUILD_TAG: &str = "0.20190909.1.0"; |
| |
| #[fasync::run_singlethreaded] |
| async fn main() -> Result<(), Error> { |
| println!("accessibility service tests"); |
| println!(" client calls set"); |
| validate_accessibility_set().await?; |
| |
| println!(" client calls watch"); |
| validate_accessibility_watch().await?; |
| |
| println!("audio service tests"); |
| println!(" client calls audio watch"); |
| validate_audio(&ExpectedStreamSettingsStruct { |
| stream: None, |
| source: None, |
| level: None, |
| volume_muted: None, |
| input_muted: None, |
| }) |
| .await?; |
| |
| println!(" client calls set audio input - stream"); |
| validate_audio(&ExpectedStreamSettingsStruct { |
| stream: Some(AudioRenderUsage::Background), |
| source: None, |
| level: None, |
| volume_muted: None, |
| input_muted: None, |
| }) |
| .await?; |
| |
| println!(" client calls set audio input - source"); |
| validate_audio(&ExpectedStreamSettingsStruct { |
| stream: None, |
| source: Some(fidl_fuchsia_settings::AudioStreamSettingSource::System), |
| level: None, |
| volume_muted: None, |
| input_muted: None, |
| }) |
| .await?; |
| |
| println!(" client calls set audio input - level"); |
| validate_audio(&ExpectedStreamSettingsStruct { |
| stream: None, |
| source: None, |
| level: Some(0.3), |
| volume_muted: None, |
| input_muted: None, |
| }) |
| .await?; |
| |
| println!(" client calls set audio input - volume_muted"); |
| validate_audio(&ExpectedStreamSettingsStruct { |
| stream: None, |
| source: None, |
| level: None, |
| volume_muted: Some(true), |
| input_muted: None, |
| }) |
| .await?; |
| |
| println!(" client calls set audio input - input_muted"); |
| validate_audio(&ExpectedStreamSettingsStruct { |
| stream: None, |
| source: None, |
| level: None, |
| volume_muted: None, |
| input_muted: Some(false), |
| }) |
| .await?; |
| |
| println!(" client calls set audio input - multiple"); |
| validate_audio(&ExpectedStreamSettingsStruct { |
| stream: Some(AudioRenderUsage::Media), |
| source: Some(fidl_fuchsia_settings::AudioStreamSettingSource::User), |
| level: Some(0.6), |
| volume_muted: Some(false), |
| input_muted: Some(true), |
| }) |
| .await?; |
| |
| println!("device service tests"); |
| println!(" client calls device watch"); |
| validate_device().await?; |
| |
| println!("display service tests"); |
| println!(" client calls display watch"); |
| validate_display(None, None, None, None, None, None).await?; |
| |
| println!(" client calls set brightness"); |
| validate_display(Some(0.5), None, None, None, None, None).await?; |
| |
| println!(" client calls set auto brightness"); |
| validate_display(None, Some(true), None, None, None, None).await?; |
| |
| println!(" client calls set auto brightness value"); |
| validate_display(None, None, Some(0.5), None, None, None).await?; |
| |
| println!(" client calls set low light mode"); |
| validate_display(None, None, None, Some(LowLightMode::Enable), None, None).await?; |
| |
| println!(" client calls set theme"); |
| validate_display(None, None, None, None, Some(ThemeType::Dark), None).await?; |
| |
| println!(" client calls set screen enabled"); |
| validate_display(None, None, None, None, Some(ThemeType::Dark), Some(false)).await?; |
| |
| println!(" client can modify multiple settings"); |
| validate_display(Some(0.3), Some(false), Some(0.8), None, Some(ThemeType::Light), Some(true)) |
| .await?; |
| |
| println!("factory reset tests"); |
| println!(" client calls set local reset allowed"); |
| validate_factory_reset(true).await?; |
| |
| println!("light tests"); |
| println!(" client calls light set"); |
| validate_light_set().await?; |
| println!(" client calls watch light groups"); |
| validate_light_watch().await?; |
| println!(" client calls watch individual light group"); |
| validate_light_watch_individual().await?; |
| |
| println!(" client calls watch light sensor"); |
| validate_light_sensor().await?; |
| |
| println!("input service tests"); |
| println!(" client calls input watch"); |
| validate_input(None).await?; |
| |
| println!(" client calls set input"); |
| validate_input(Some(false)).await?; |
| |
| println!("input2 service tests"); |
| println!(" client calls input watch2"); |
| validate_input2_watch().await?; |
| |
| println!(" client calls set input with microphone"); |
| validate_input2_set(DeviceType::Microphone, "microphone", 3, "Available | Active").await?; |
| println!(" client calls set input with camera"); |
| validate_input2_set(DeviceType::Camera, "camera", 3, "Available | Active").await?; |
| |
| println!("do not disturb service tests"); |
| println!(" client calls dnd watch"); |
| validate_dnd(Some(false), Some(false)).await?; |
| |
| println!(" client calls set user initiated do not disturb"); |
| validate_dnd(Some(true), Some(false)).await?; |
| |
| println!(" client calls set night mode initiated do not disturb"); |
| validate_dnd(Some(false), Some(true)).await?; |
| |
| println!("intl service tests"); |
| println!(" client calls intl set"); |
| validate_intl_set().await?; |
| println!(" client calls intl watch"); |
| validate_intl_watch().await?; |
| |
| println!("night mode service tests"); |
| println!(" client calls night mode watch"); |
| validate_night_mode(None).await?; |
| |
| println!(" client calls set night_mode_enabled"); |
| validate_night_mode(Some(true)).await?; |
| |
| println!(" set() output"); |
| validate_night_mode_set_output(true).await?; |
| validate_night_mode_set_output(false).await?; |
| |
| println!(" watch() output"); |
| validate_night_mode_watch_output(None).await?; |
| validate_night_mode_watch_output(Some(true)).await?; |
| validate_night_mode_watch_output(Some(false)).await?; |
| |
| println!("privacy service tests"); |
| println!(" client calls privacy watch"); |
| validate_privacy(None).await?; |
| |
| println!(" client calls set user_data_sharing_consent"); |
| validate_privacy(Some(true)).await?; |
| |
| println!(" set() output"); |
| validate_privacy_set_output(true).await?; |
| validate_privacy_set_output(false).await?; |
| |
| println!(" watch() output"); |
| validate_privacy_watch_output(None).await?; |
| validate_privacy_watch_output(Some(true)).await?; |
| validate_privacy_watch_output(Some(false)).await?; |
| |
| println!("setup service tests"); |
| println!(" client calls set config interfaces"); |
| validate_setup().await?; |
| |
| println!("volume policy tests"); |
| println!(" client calls get"); |
| validate_volume_policy_get().await?; |
| println!(" client calls add"); |
| validate_volume_policy_add().await?; |
| println!(" client calls remove"); |
| validate_volume_policy_remove().await?; |
| |
| Ok(()) |
| } |
| |
| // Creates a service in an environment for a given setting type. |
| // Usage: create_service!(service_enum_name, |
| // request_name => {code block}, |
| // request2_name => {code_block} |
| // ... ); |
| macro_rules! create_service { |
| ($setting_type:path, $( $request:pat => $callback:block ),*) => {{ |
| |
| let mut fs = ServiceFs::new(); |
| fs.add_fidl_service($setting_type); |
| let env = fs.create_nested_environment(ENV_NAME)?; |
| |
| fasync::Task::spawn(fs.for_each_concurrent(None, move |connection| { |
| async move { |
| #![allow(unreachable_patterns)] |
| match connection { |
| $setting_type(stream) => { |
| stream |
| .err_into::<anyhow::Error>() |
| .try_for_each(|req| async move { |
| match req { |
| $($request => $callback)* |
| _ => panic!("Incorrect command to service"), |
| } |
| Ok(()) |
| }) |
| .unwrap_or_else(|e: anyhow::Error| panic!( |
| "error running setui server: {:?}", |
| e |
| )).await; |
| } |
| _ => { |
| panic!("Unexpected service"); |
| } |
| } |
| } |
| })).detach(); |
| env |
| }}; |
| } |
| |
| /// Creates a one-item list of input devices with the given properties. |
| fn create_input_devices( |
| device_type: DeviceType, |
| device_name: &str, |
| device_state: u64, |
| ) -> Vec<InputDevice> { |
| let mut devices = Vec::new(); |
| let mut source_states = Vec::new(); |
| source_states.push(SourceState { |
| source: Some(DeviceStateSource::Hardware), |
| state: Some(DeviceState { |
| toggle_flags: ToggleStateFlags::from_bits(1), |
| ..DeviceState::EMPTY |
| }), |
| ..SourceState::EMPTY |
| }); |
| source_states.push(SourceState { |
| source: Some(DeviceStateSource::Software), |
| state: Some(u64_to_state(device_state)), |
| ..SourceState::EMPTY |
| }); |
| let device = InputDevice { |
| device_name: Some(device_name.to_string()), |
| device_type: Some(device_type), |
| source_states: Some(source_states), |
| mutable_toggle_state: ToggleStateFlags::from_bits(12), |
| state: Some(u64_to_state(device_state)), |
| ..InputDevice::EMPTY |
| }; |
| devices.push(device); |
| devices |
| } |
| |
| async fn validate_intl_set() -> Result<(), Error> { |
| const TEST_TIME_ZONE: &str = "GMT"; |
| const TEST_TEMPERATURE_UNIT: TemperatureUnit = TemperatureUnit::Celsius; |
| const TEST_LOCALE: &str = "blah"; |
| const TEST_HOUR_CYCLE: fidl_fuchsia_settings::HourCycle = fidl_fuchsia_settings::HourCycle::H12; |
| |
| let env = create_service!(Services::Intl, |
| IntlRequest::Set { settings, responder } => { |
| assert_eq!(Some(TimeZoneId { id: TEST_TIME_ZONE.to_string() }), settings.time_zone_id); |
| assert_eq!(Some(TEST_TEMPERATURE_UNIT), settings.temperature_unit); |
| assert_eq!(Some(vec![LocaleId { id: TEST_LOCALE.into() }]), settings.locales); |
| assert_eq!(Some(TEST_HOUR_CYCLE), settings.hour_cycle); |
| responder.send(&mut Ok(()))?; |
| }); |
| |
| let intl_service = |
| env.connect_to_service::<IntlMarker>().context("Failed to connect to intl service")?; |
| |
| assert_set!(intl::command( |
| intl_service, |
| Some(TimeZoneId { id: TEST_TIME_ZONE.to_string() }), |
| Some(TEST_TEMPERATURE_UNIT), |
| vec![LocaleId { id: TEST_LOCALE.into() }], |
| Some(TEST_HOUR_CYCLE), |
| false, |
| )); |
| Ok(()) |
| } |
| |
| async fn validate_intl_watch() -> Result<(), Error> { |
| const TEST_TIME_ZONE: &str = "GMT"; |
| const TEST_TEMPERATURE_UNIT: TemperatureUnit = TemperatureUnit::Celsius; |
| const TEST_LOCALE: &str = "blah"; |
| const TEST_HOUR_CYCLE: fidl_fuchsia_settings::HourCycle = fidl_fuchsia_settings::HourCycle::H12; |
| |
| let env = create_service!(Services::Intl, |
| IntlRequest::Watch { responder } => { |
| responder.send(IntlSettings { |
| locales: Some(vec![LocaleId { id: TEST_LOCALE.into() }]), |
| temperature_unit: Some(TEST_TEMPERATURE_UNIT), |
| time_zone_id: Some(TimeZoneId { id: TEST_TIME_ZONE.to_string() }), |
| hour_cycle: Some(TEST_HOUR_CYCLE), |
| ..IntlSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let intl_service = |
| env.connect_to_service::<IntlMarker>().context("Failed to connect to intl service")?; |
| |
| let output = assert_watch!(intl::command(intl_service, None, None, vec![], None, false)); |
| assert_eq!( |
| output, |
| format!( |
| "{:#?}", |
| IntlSettings { |
| locales: Some(vec![LocaleId { id: TEST_LOCALE.into() }]), |
| temperature_unit: Some(TEST_TEMPERATURE_UNIT), |
| time_zone_id: Some(TimeZoneId { id: TEST_TIME_ZONE.to_string() }), |
| hour_cycle: Some(TEST_HOUR_CYCLE), |
| ..IntlSettings::EMPTY |
| } |
| ) |
| ); |
| Ok(()) |
| } |
| |
| async fn validate_device() -> Result<(), Error> { |
| let env = create_service!(Services::Device, |
| DeviceRequest::Watch { responder } => { |
| responder.send(DeviceSettings { |
| build_tag: Some(TEST_BUILD_TAG.to_string()), |
| ..DeviceSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let device_service = |
| env.connect_to_service::<DeviceMarker>().context("Failed to connect to device service")?; |
| |
| device::command(device_service).try_next().await?; |
| Ok(()) |
| } |
| |
| // Can only check one mutate option at once. |
| async fn validate_display( |
| expected_brightness: Option<f32>, |
| expected_auto_brightness: Option<bool>, |
| expected_auto_brightness_value: Option<f32>, |
| expected_low_light_mode: Option<LowLightMode>, |
| expected_theme_type: Option<ThemeType>, |
| expected_screen_enabled: Option<bool>, |
| ) -> Result<(), Error> { |
| let env = create_service!( |
| Services::Display, DisplayRequest::Set { settings, responder, } => { |
| if let (Some(brightness_value), Some(expected_brightness_value)) = |
| (settings.brightness_value, expected_brightness) { |
| assert_eq!(brightness_value, expected_brightness_value); |
| responder.send(&mut Ok(()))?; |
| } else if let (Some(auto_brightness), Some(expected_auto_brightness_value)) = |
| (settings.auto_brightness, expected_auto_brightness) { |
| assert_eq!(auto_brightness, expected_auto_brightness_value); |
| responder.send(&mut Ok(()))?; |
| } else if let (Some(auto_brightness_value), Some(expected_auto_brightness_value)) = |
| (settings.adjusted_auto_brightness, expected_auto_brightness_value) { |
| assert_eq!(auto_brightness_value, expected_auto_brightness_value); |
| responder.send(&mut Ok(()))?; |
| } else if let (Some(low_light_mode), Some(expected_low_light_mode_value)) = |
| (settings.low_light_mode, expected_low_light_mode) { |
| assert_eq!(low_light_mode, expected_low_light_mode_value); |
| responder.send(&mut Ok(()))?; |
| } else if let (Some(Theme{ theme_type: Some(theme_type), ..}), Some(expected_theme_type_value)) = |
| (settings.theme, expected_theme_type) { |
| assert_eq!(theme_type, expected_theme_type_value); |
| responder.send(&mut Ok(()))?; |
| } else if let (Some(screen_enabled), Some(expected_screen_enabled_value)) = |
| (settings.screen_enabled, expected_screen_enabled) { |
| assert_eq!(screen_enabled, expected_screen_enabled_value); |
| responder.send(&mut Ok(()))?; |
| } else { |
| panic!("Unexpected call to set"); |
| } |
| }, |
| DisplayRequest::Watch { responder } => { |
| responder.send(DisplaySettings { |
| auto_brightness: Some(false), |
| adjusted_auto_brightness: Some(0.5), |
| brightness_value: Some(0.5), |
| low_light_mode: Some(LowLightMode::Disable), |
| theme: Some(Theme{theme_type: Some(ThemeType::Default), ..Theme::EMPTY}), |
| screen_enabled: Some(true), |
| ..DisplaySettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let display_service = env |
| .connect_to_service::<DisplayMarker>() |
| .context("Failed to connect to display service")?; |
| |
| assert_successful!(display::command( |
| display_service, |
| expected_brightness, |
| expected_auto_brightness, |
| expected_auto_brightness_value, |
| false, |
| expected_low_light_mode, |
| Some(Theme { theme_type: expected_theme_type, ..Theme::EMPTY }), |
| expected_screen_enabled, |
| )); |
| |
| Ok(()) |
| } |
| |
| // Validates the set and watch for factory reset. |
| async fn validate_factory_reset(expected_local_reset_allowed: bool) -> Result<(), Error> { |
| let env = create_service!( |
| Services::FactoryReset, FactoryResetRequest::Set { settings, responder, } => { |
| if let (Some(local_reset_allowed), expected_local_reset_allowed) = |
| (settings.is_local_reset_allowed, expected_local_reset_allowed) |
| { |
| assert_eq!(local_reset_allowed, expected_local_reset_allowed); |
| responder.send(&mut Ok(()))?; |
| } else { |
| panic!("Unexpected call to set"); |
| } |
| }, |
| FactoryResetRequest::Watch { responder } => { |
| responder.send(FactoryResetSettings { |
| is_local_reset_allowed: Some(true), |
| ..FactoryResetSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let factory_reset_service = env |
| .connect_to_service::<FactoryResetMarker>() |
| .context("Failed to connect to factory reset service")?; |
| |
| assert_successful!(factory_reset::command( |
| factory_reset_service, |
| Some(expected_local_reset_allowed) |
| )); |
| |
| Ok(()) |
| } |
| |
| // Can only check one mutate option at once |
| async fn validate_light_sensor() -> Result<(), Error> { |
| let watch_called = Arc::new(RwLock::new(false)); |
| |
| let watch_called_clone = watch_called.clone(); |
| |
| let (display_service, mut stream) = |
| fidl::endpoints::create_proxy_and_stream::<DisplayMarker>().unwrap(); |
| |
| fasync::Task::spawn(async move { |
| while let Some(request) = stream.try_next().await.unwrap() { |
| match request { |
| DisplayRequest::WatchLightSensor2 { delta: _, responder } => { |
| *watch_called_clone.write() = true; |
| responder |
| .send(LightSensorData { |
| illuminance_lux: Some(100.0), |
| color: Some(fidl_fuchsia_ui_types::ColorRgb { |
| red: 25.0, |
| green: 16.0, |
| blue: 59.0, |
| }), |
| ..LightSensorData::EMPTY |
| }) |
| .unwrap(); |
| } |
| _ => {} |
| } |
| } |
| }) |
| .detach(); |
| |
| assert_watch!(display::command(display_service, None, None, None, true, None, None, None)); |
| assert_eq!(*watch_called.read(), true); |
| Ok(()) |
| } |
| |
| async fn validate_accessibility_set() -> Result<(), Error> { |
| const TEST_COLOR: fidl_fuchsia_ui_types::ColorRgba = |
| fidl_fuchsia_ui_types::ColorRgba { red: 238.0, green: 23.0, blue: 128.0, alpha: 255.0 }; |
| let expected_options: AccessibilityOptions = AccessibilityOptions { |
| audio_description: Some(true), |
| screen_reader: Some(true), |
| color_inversion: Some(false), |
| enable_magnification: Some(false), |
| color_correction: Some(ColorBlindnessType::Protanomaly), |
| caption_options: Some(CaptionCommands::CaptionOptions(CaptionOptions { |
| for_media: Some(true), |
| for_tts: Some(false), |
| window_color: Some(TEST_COLOR), |
| background_color: Some(TEST_COLOR), |
| style: CaptionFontStyle { |
| font_family: Some(CaptionFontFamily::Cursive), |
| font_color: Some(TEST_COLOR), |
| relative_size: Some(1.0), |
| char_edge_style: Some(EdgeStyle::Raised), |
| }, |
| })), |
| }; |
| |
| let env = create_service!( |
| Services::Accessibility, AccessibilityRequest::Set { settings, responder } => { |
| assert_eq!(expected_options.audio_description, settings.audio_description); |
| assert_eq!(expected_options.screen_reader, settings.screen_reader); |
| assert_eq!(expected_options.color_inversion, settings.color_inversion); |
| assert_eq!(expected_options.enable_magnification, settings.enable_magnification); |
| assert_eq!(expected_options.color_correction, settings.color_correction); |
| |
| // If no caption options are provided, then captions_settings field in service should |
| // also be None. The inverse of this should also be true. |
| assert_eq!(expected_options.caption_options.is_some(), settings.captions_settings.is_some()); |
| match (settings.captions_settings, expected_options.caption_options) { |
| (Some(captions_settings), Some(caption_settings_enum)) => { |
| let CaptionCommands::CaptionOptions(input) = caption_settings_enum; |
| |
| assert_eq!(input.for_media, captions_settings.for_media); |
| assert_eq!(input.for_tts, captions_settings.for_tts); |
| assert_eq!(input.window_color, captions_settings.window_color); |
| assert_eq!(input.background_color, captions_settings.background_color); |
| |
| if let Some(font_style) = captions_settings.font_style { |
| let input_style = input.style; |
| |
| assert_eq!(input_style.font_family, font_style.family); |
| assert_eq!(input_style.font_color, font_style.color); |
| assert_eq!(input_style.relative_size, font_style.relative_size); |
| assert_eq!(input_style.char_edge_style, font_style.char_edge_style); |
| } |
| } |
| _ => {} |
| } |
| |
| responder.send(&mut Ok(()))?; |
| } |
| ); |
| |
| let accessibility_service = env |
| .connect_to_service::<AccessibilityMarker>() |
| .context("Failed to connect to accessibility service")?; |
| |
| let output = assert_set!(accessibility::command(accessibility_service, expected_options)); |
| assert_eq!(output, "Successfully set AccessibilitySettings"); |
| Ok(()) |
| } |
| |
| async fn validate_accessibility_watch() -> Result<(), Error> { |
| let env = create_service!( |
| Services::Accessibility, |
| AccessibilityRequest::Watch { responder } => { |
| responder.send(AccessibilitySettings::EMPTY)?; |
| } |
| ); |
| |
| let accessibility_service = env |
| .connect_to_service::<AccessibilityMarker>() |
| .context("Failed to connect to accessibility service")?; |
| |
| let output = assert_watch!(accessibility::command( |
| accessibility_service, |
| AccessibilityOptions::default() |
| )); |
| assert_eq!(output, format!("{:#?}", AccessibilitySettings::EMPTY)); |
| Ok(()) |
| } |
| |
| async fn validate_audio(expected: &'static ExpectedStreamSettingsStruct) -> Result<(), Error> { |
| let env = create_service!(Services::Audio, |
| AudioRequest::Set { settings, responder } => { |
| if let Some(streams) = settings.streams { |
| verify_streams(streams, expected); |
| responder.send(&mut (Ok(())))?; |
| } else if let Some(input) = settings.input { |
| if let (Some(input_muted), Some(expected_input_muted)) = |
| (input.muted, expected.input_muted) { |
| assert_eq!(input_muted, expected_input_muted); |
| responder.send(&mut (Ok(())))?; |
| } |
| } |
| }, |
| AudioRequest::Watch { responder } => { |
| responder.send(AudioSettings { |
| streams: Some(vec![AudioStreamSettings { |
| stream: Some(AudioRenderUsage::Media), |
| source: Some(fidl_fuchsia_settings::AudioStreamSettingSource::User), |
| user_volume: Some(Volume { |
| level: Some(0.6), |
| muted: Some(false), |
| ..Volume::EMPTY |
| }), |
| ..AudioStreamSettings::EMPTY |
| }]), |
| input: Some(AudioInput { |
| muted: Some(true), |
| ..AudioInput::EMPTY |
| }), |
| ..AudioSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let audio_service = |
| env.connect_to_service::<AudioMarker>().context("Failed to connect to audio service")?; |
| |
| assert_successful!(audio::command( |
| audio_service, |
| expected.stream, |
| expected.source, |
| expected.level, |
| expected.volume_muted, |
| expected.input_muted, |
| )); |
| Ok(()) |
| } |
| |
| async fn validate_input(expected_mic_muted: Option<bool>) -> Result<(), Error> { |
| let env = create_service!(Services::Input, |
| InputRequest::Set { settings, responder } => { |
| if let Some(Microphone { muted, .. }) = settings.microphone { |
| assert_eq!(expected_mic_muted, muted); |
| responder.send(&mut (Ok(())))?; |
| } |
| }, |
| InputRequest::Watch { responder } => { |
| responder.send(InputDeviceSettings { |
| microphone: Some(Microphone { |
| muted: expected_mic_muted, |
| ..Microphone::EMPTY |
| }), |
| ..InputDeviceSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let input_service = |
| env.connect_to_service::<InputMarker>().context("Failed to connect to input service")?; |
| |
| let either = input::command(input_service, expected_mic_muted).await?; |
| if expected_mic_muted.is_none() { |
| if let utils::Either::Watch(mut stream) = either { |
| let output = stream.try_next().await?.expect("Watch should have a result"); |
| assert_eq!( |
| output, |
| format!( |
| "{:#?}", |
| InputDeviceSettings { |
| microphone: Some(Microphone { |
| muted: expected_mic_muted, |
| ..Microphone::EMPTY |
| }), |
| ..InputDeviceSettings::EMPTY |
| } |
| ) |
| ); |
| } else { |
| panic!("Did not expect set result for a watch command"); |
| } |
| } else if let utils::Either::Set(output) = either { |
| assert_eq!( |
| output, |
| format!("Successfully set mic mute to {}\n", expected_mic_muted.unwrap()) |
| ); |
| } else { |
| panic!("Did not expect watch result for a set command"); |
| } |
| |
| Ok(()) |
| } |
| |
| /// Transforms an u64 into an fuchsia_fidl_settings::DeviceState. |
| fn u64_to_state(num: u64) -> DeviceState { |
| DeviceState { toggle_flags: ToggleStateFlags::from_bits(num), ..DeviceState::EMPTY } |
| } |
| |
| async fn validate_input2_watch() -> Result<(), Error> { |
| let env = create_service!(Services::Input, |
| InputRequest::Watch2 { responder } => { |
| responder.send(InputSettings { |
| devices: Some( |
| create_input_devices( |
| DeviceType::Camera, |
| "camera", |
| 1, |
| ) |
| ), |
| ..InputSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let input_service = |
| env.connect_to_service::<InputMarker>().context("Failed to connect to input service")?; |
| |
| let output = assert_watch!(input::command2(input_service, None, None, None)); |
| // Just check that the output contains some key strings that confirms the watch returned. |
| // The string representation may not necessarily be in the same order. |
| assert!(output.contains("Software")); |
| assert!(output.contains("source_states: Some")); |
| assert!(output.contains("toggle_flags: Some")); |
| assert!(output.contains("camera")); |
| assert!(output.contains("Available")); |
| Ok(()) |
| } |
| |
| async fn validate_input2_set( |
| device_type: DeviceType, |
| device_name: &'static str, |
| device_state: u64, |
| expected_state_string: &str, |
| ) -> Result<(), Error> { |
| let env = create_service!(Services::Input, |
| InputRequest::SetStates { input_states, responder } => { |
| input_states.iter().for_each(move |state| { |
| assert_eq!(Some(device_type), state.device_type); |
| assert_eq!(Some(device_name.to_string()), state.name); |
| assert_eq!(Some(u64_to_state(device_state)), state.state); |
| }); |
| responder.send(&mut (Ok(())))?; |
| } |
| ); |
| |
| let input_service = |
| env.connect_to_service::<InputMarker>().context("Failed to connect to input service")?; |
| |
| let output = assert_set!(input::command2( |
| input_service, |
| Some(device_type), |
| Some(device_name.to_string()), |
| Some(u64_to_state(device_state)), |
| )); |
| // Just check that the output contains some key strings that confirms the set returned. |
| // The string representation may not necessarily be in the same order. |
| assert!(output.contains(&format!("{:?}", device_type))); |
| assert!(output.contains(&format!("{:?}", device_name))); |
| assert!(output.contains(expected_state_string)); |
| Ok(()) |
| } |
| |
| fn verify_streams( |
| streams: Vec<AudioStreamSettings>, |
| expected: &'static ExpectedStreamSettingsStruct, |
| ) { |
| let extracted_stream_settings = streams.get(0).unwrap(); |
| if let (Some(stream), Some(expected_stream)) = |
| (extracted_stream_settings.stream, expected.stream) |
| { |
| assert_eq!(stream, expected_stream); |
| } |
| if let (Some(source), Some(expected_source)) = |
| (extracted_stream_settings.source, expected.source) |
| { |
| assert_eq!(source, expected_source); |
| } |
| if let Some(user_volume) = extracted_stream_settings.user_volume.as_ref() { |
| if let (Some(level), Some(expected_level)) = (user_volume.level, expected.level) { |
| assert_eq!(level, expected_level); |
| } |
| if let (Some(volume_muted), Some(expected_volume_muted)) = |
| (user_volume.muted, expected.volume_muted) |
| { |
| assert_eq!(volume_muted, expected_volume_muted); |
| } |
| } |
| } |
| |
| async fn validate_dnd( |
| expected_user_dnd: Option<bool>, |
| expected_night_mode_dnd: Option<bool>, |
| ) -> Result<(), Error> { |
| let env = create_service!(Services::DoNotDisturb, |
| DoNotDisturbRequest::Set { settings, responder } => { |
| if let(Some(user_dnd), Some(expected_user_dnd)) = |
| (settings.user_initiated_do_not_disturb, expected_user_dnd) { |
| assert_eq!(user_dnd, expected_user_dnd); |
| responder.send(&mut Ok(()))?; |
| } else if let (Some(night_mode_dnd), Some(expected_night_mode_dnd)) = |
| (settings.night_mode_initiated_do_not_disturb, expected_night_mode_dnd) { |
| assert_eq!(night_mode_dnd, expected_night_mode_dnd); |
| responder.send(&mut (Ok(())))?; |
| } else { |
| panic!("Unexpected call to set"); |
| } |
| }, |
| DoNotDisturbRequest::Watch { responder } => { |
| responder.send(DoNotDisturbSettings { |
| user_initiated_do_not_disturb: Some(false), |
| night_mode_initiated_do_not_disturb: Some(false), |
| ..DoNotDisturbSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let do_not_disturb_service = env |
| .connect_to_service::<DoNotDisturbMarker>() |
| .context("Failed to connect to do not disturb service")?; |
| |
| assert_successful!(do_not_disturb::command( |
| do_not_disturb_service, |
| expected_user_dnd, |
| expected_night_mode_dnd |
| )); |
| Ok(()) |
| } |
| |
| async fn validate_light_set() -> Result<(), Error> { |
| const TEST_NAME: &str = "test_name"; |
| const LIGHT_VAL_1: f64 = 0.2; |
| const LIGHT_VAL_2: f64 = 0.42; |
| |
| let env = create_service!(Services::Light, |
| LightRequest::SetLightGroupValues { name, state, responder } => { |
| assert_eq!(name, TEST_NAME); |
| assert_eq!(state, vec![LightState { value: Some(LightValue::Brightness(LIGHT_VAL_1)), ..LightState::EMPTY }, |
| LightState { value: Some(LightValue::Brightness(LIGHT_VAL_2)), ..LightState::EMPTY }]); |
| responder.send(&mut Ok(()))?; |
| } |
| ); |
| |
| let light_service = |
| env.connect_to_service::<LightMarker>().context("Failed to connect to light service")?; |
| |
| assert_set!(light::command( |
| light_service, |
| setui_client_lib::LightGroup { |
| name: Some(TEST_NAME.to_string()), |
| simple: vec![], |
| brightness: vec![LIGHT_VAL_1, LIGHT_VAL_2], |
| rgb: vec![], |
| }, |
| )); |
| Ok(()) |
| } |
| |
| async fn validate_light_watch() -> Result<(), Error> { |
| const TEST_NAME: &str = "test_name"; |
| const ENABLED: bool = false; |
| const LIGHT_TYPE: LightType = LightType::Simple; |
| const LIGHT_VAL_1: f64 = 0.2; |
| const LIGHT_VAL_2: f64 = 0.42; |
| |
| let env = create_service!(Services::Light, |
| LightRequest::WatchLightGroups { responder } => { |
| responder.send(&mut vec![ |
| LightGroup { |
| name: Some(TEST_NAME.to_string()), |
| enabled: Some(ENABLED), |
| type_: Some(LIGHT_TYPE), |
| lights: Some(vec![ |
| LightState { value: Some(LightValue::Brightness(LIGHT_VAL_1)), ..LightState::EMPTY }, |
| LightState { value: Some(LightValue::Brightness(LIGHT_VAL_2)), ..LightState::EMPTY } |
| ]), |
| ..LightGroup::EMPTY |
| } |
| ].into_iter())?; |
| } |
| ); |
| |
| let light_service = |
| env.connect_to_service::<LightMarker>().context("Failed to connect to light service")?; |
| |
| let output = assert_watch!(light::command( |
| light_service, |
| setui_client_lib::LightGroup { |
| name: None, |
| simple: vec![], |
| brightness: vec![], |
| rgb: vec![], |
| }, |
| )); |
| assert_eq!( |
| output, |
| format!( |
| "{:#?}", |
| vec![LightGroup { |
| name: Some(TEST_NAME.to_string()), |
| enabled: Some(ENABLED), |
| type_: Some(LIGHT_TYPE), |
| lights: Some(vec![ |
| LightState { |
| value: Some(LightValue::Brightness(LIGHT_VAL_1)), |
| ..LightState::EMPTY |
| }, |
| LightState { |
| value: Some(LightValue::Brightness(LIGHT_VAL_2)), |
| ..LightState::EMPTY |
| } |
| ]), |
| ..LightGroup::EMPTY |
| }] |
| ) |
| ); |
| Ok(()) |
| } |
| |
| async fn validate_light_watch_individual() -> Result<(), Error> { |
| const TEST_NAME: &str = "test_name"; |
| const ENABLED: bool = false; |
| const LIGHT_TYPE: LightType = LightType::Simple; |
| const LIGHT_VAL_1: f64 = 0.2; |
| const LIGHT_VAL_2: f64 = 0.42; |
| |
| let env = create_service!(Services::Light, |
| LightRequest::WatchLightGroup { name, responder } => { |
| responder.send(LightGroup { |
| name: Some(name), |
| enabled: Some(ENABLED), |
| type_: Some(LIGHT_TYPE), |
| lights: Some(vec![ |
| LightState { value: Some(LightValue::Brightness(LIGHT_VAL_1)), ..LightState::EMPTY }, |
| LightState { value: Some(LightValue::Brightness(LIGHT_VAL_2)), ..LightState::EMPTY } |
| ]), |
| ..LightGroup::EMPTY |
| })?; |
| } |
| ); |
| |
| let light_service = |
| env.connect_to_service::<LightMarker>().context("Failed to connect to light service")?; |
| |
| let output = assert_watch!(light::command( |
| light_service, |
| setui_client_lib::LightGroup { |
| name: Some(TEST_NAME.to_string()), |
| simple: vec![], |
| brightness: vec![], |
| rgb: vec![], |
| }, |
| )); |
| assert_eq!( |
| output, |
| format!( |
| "{:#?}", |
| LightGroup { |
| name: Some(TEST_NAME.to_string()), |
| enabled: Some(ENABLED), |
| type_: Some(LIGHT_TYPE), |
| lights: Some(vec![ |
| LightState { |
| value: Some(LightValue::Brightness(LIGHT_VAL_1)), |
| ..LightState::EMPTY |
| }, |
| LightState { |
| value: Some(LightValue::Brightness(LIGHT_VAL_2)), |
| ..LightState::EMPTY |
| } |
| ]), |
| ..LightGroup::EMPTY |
| } |
| ) |
| ); |
| Ok(()) |
| } |
| |
| async fn validate_night_mode(expected_night_mode_enabled: Option<bool>) -> Result<(), Error> { |
| let env = create_service!( |
| Services::NightMode, NightModeRequest::Set { settings, responder, } => { |
| if let (Some(night_mode_enabled), Some(expected_night_mode_enabled_value)) = |
| (settings.night_mode_enabled, expected_night_mode_enabled) { |
| assert_eq!(night_mode_enabled, expected_night_mode_enabled_value); |
| responder.send(&mut Ok(()))?; |
| } else { |
| panic!("Unexpected call to set"); |
| } |
| }, |
| NightModeRequest::Watch { responder } => { |
| responder.send(NightModeSettings { |
| night_mode_enabled: Some(false), |
| ..NightModeSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let night_mode_service = env |
| .connect_to_service::<NightModeMarker>() |
| .context("Failed to connect to night mode service")?; |
| |
| assert_successful!(night_mode::command(night_mode_service, expected_night_mode_enabled)); |
| Ok(()) |
| } |
| |
| async fn validate_night_mode_set_output(expected_night_mode_enabled: bool) -> Result<(), Error> { |
| let env = create_service!( |
| Services::NightMode, NightModeRequest::Set { settings: _, responder, } => { |
| responder.send(&mut Ok(()))?; |
| }, |
| NightModeRequest::Watch { responder } => { |
| responder.send(NightModeSettings { |
| night_mode_enabled: Some(expected_night_mode_enabled), |
| ..NightModeSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let night_mode_service = env |
| .connect_to_service::<NightModeMarker>() |
| .context("Failed to connect to night mode service")?; |
| |
| let output = |
| assert_set!(night_mode::command(night_mode_service, Some(expected_night_mode_enabled))); |
| assert_eq!( |
| output, |
| format!("Successfully set night_mode_enabled to {}", expected_night_mode_enabled) |
| ); |
| Ok(()) |
| } |
| |
| async fn validate_night_mode_watch_output( |
| expected_night_mode_enabled: Option<bool>, |
| ) -> Result<(), Error> { |
| let env = create_service!( |
| Services::NightMode, NightModeRequest::Set { settings: _, responder, } => { |
| responder.send(&mut Ok(()))?; |
| }, |
| NightModeRequest::Watch { responder } => { |
| responder.send(NightModeSettings { |
| night_mode_enabled: expected_night_mode_enabled, |
| ..NightModeSettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let night_mode_service = env |
| .connect_to_service::<NightModeMarker>() |
| .context("Failed to connect to night_mode service")?; |
| |
| let output = assert_watch!(night_mode::command(night_mode_service, None)); |
| assert_eq!( |
| output, |
| format!( |
| "{:#?}", |
| NightModeSettings { |
| night_mode_enabled: expected_night_mode_enabled, |
| ..NightModeSettings::EMPTY |
| } |
| ) |
| ); |
| Ok(()) |
| } |
| |
| async fn validate_privacy(expected_user_data_sharing_consent: Option<bool>) -> Result<(), Error> { |
| let env = create_service!( |
| Services::Privacy, PrivacyRequest::Set { settings, responder, } => { |
| if let (Some(user_data_sharing_consent), Some(expected_user_data_sharing_consent_value)) = |
| (settings.user_data_sharing_consent, expected_user_data_sharing_consent) { |
| assert_eq!(user_data_sharing_consent, expected_user_data_sharing_consent_value); |
| responder.send(&mut Ok(()))?; |
| } else { |
| panic!("Unexpected call to set"); |
| } |
| }, |
| PrivacyRequest::Watch { responder } => { |
| responder.send(PrivacySettings { |
| user_data_sharing_consent: Some(false), |
| ..PrivacySettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let privacy_service = env |
| .connect_to_service::<PrivacyMarker>() |
| .context("Failed to connect to privacy service")?; |
| |
| assert_successful!(privacy::command(privacy_service, expected_user_data_sharing_consent)); |
| Ok(()) |
| } |
| |
| async fn validate_privacy_set_output( |
| expected_user_data_sharing_consent: bool, |
| ) -> Result<(), Error> { |
| let env = create_service!( |
| Services::Privacy, PrivacyRequest::Set { settings: _, responder, } => { |
| responder.send(&mut Ok(()))?; |
| }, |
| PrivacyRequest::Watch { responder } => { |
| responder.send(PrivacySettings { |
| user_data_sharing_consent: Some(expected_user_data_sharing_consent), |
| ..PrivacySettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let privacy_service = env |
| .connect_to_service::<PrivacyMarker>() |
| .context("Failed to connect to privacy service")?; |
| |
| let output = |
| assert_set!(privacy::command(privacy_service, Some(expected_user_data_sharing_consent))); |
| assert_eq!( |
| output, |
| format!( |
| "Successfully set user_data_sharing_consent to {}", |
| expected_user_data_sharing_consent |
| ) |
| ); |
| Ok(()) |
| } |
| |
| async fn validate_privacy_watch_output( |
| expected_user_data_sharing_consent: Option<bool>, |
| ) -> Result<(), Error> { |
| let env = create_service!( |
| Services::Privacy, PrivacyRequest::Set { settings: _, responder, } => { |
| responder.send(&mut Ok(()))?; |
| }, |
| PrivacyRequest::Watch { responder } => { |
| responder.send(PrivacySettings { |
| user_data_sharing_consent: expected_user_data_sharing_consent, |
| ..PrivacySettings::EMPTY |
| })?; |
| } |
| ); |
| |
| let privacy_service = env |
| .connect_to_service::<PrivacyMarker>() |
| .context("Failed to connect to privacy service")?; |
| |
| let output = assert_watch!(privacy::command(privacy_service, None)); |
| assert_eq!( |
| output, |
| format!( |
| "{:#?}", |
| PrivacySettings { |
| user_data_sharing_consent: expected_user_data_sharing_consent, |
| ..PrivacySettings::EMPTY |
| } |
| ) |
| ); |
| Ok(()) |
| } |
| |
| fn create_setup_setting(interfaces: ConfigurationInterfaces) -> SetupSettings { |
| let mut settings = SetupSettings::EMPTY; |
| settings.enabled_configuration_interfaces = Some(interfaces); |
| |
| settings |
| } |
| |
| async fn validate_setup() -> Result<(), Error> { |
| let expected_set_interfaces = ConfigurationInterfaces::Ethernet; |
| let expected_watch_interfaces = |
| ConfigurationInterfaces::Wifi | ConfigurationInterfaces::Ethernet; |
| let env = create_service!( |
| Services::Setup, SetupRequest::Set { settings, responder, } => { |
| if let Some(interfaces) = settings.enabled_configuration_interfaces { |
| assert_eq!(interfaces, expected_set_interfaces); |
| responder.send(&mut Ok(()))?; |
| } else { |
| panic!("Unexpected call to set"); |
| } |
| }, |
| SetupRequest::Watch { responder } => { |
| responder.send(create_setup_setting(expected_watch_interfaces))?; |
| } |
| ); |
| |
| let setup_service = |
| env.connect_to_service::<SetupMarker>().context("Failed to connect to setup service")?; |
| |
| assert_set!(setup::command(setup_service.clone(), Some(expected_set_interfaces))); |
| let output = assert_watch!(setup::command(setup_service.clone(), None)); |
| assert_eq!( |
| output, |
| setup::describe_setup_setting(&create_setup_setting(expected_watch_interfaces)) |
| ); |
| Ok(()) |
| } |
| |
| // Verifies that invoking a volume policy command with no arguments fetches the policy properties. |
| async fn validate_volume_policy_get() -> Result<(), Error> { |
| // Create a fake volume policy service that responds to GetProperties with a single property. |
| // Any other calls will cause the test to fail. |
| let env = create_service!( |
| Services::VolumePolicy, |
| VolumePolicyControllerRequest::GetProperties { responder } => { |
| let mut properties = Vec::new(); |
| properties.push(Property { |
| target: Some(Target::Stream(AudioRenderUsage::Background)), |
| active_policies: Some(vec![]), |
| available_transforms: Some(vec![Transform::Max]), |
| ..Property::EMPTY |
| }); |
| responder.send(&mut properties.into_iter())?; |
| } |
| ); |
| |
| let volume_policy_service = env |
| .connect_to_service::<VolumePolicyControllerMarker>() |
| .context("Failed to connect to volume policy service")?; |
| |
| let output = assert_get!(volume_policy::command(volume_policy_service, None, None)); |
| // Spot-check that the output contains the available transform in the data returned from the |
| // fake service. |
| assert!(output.contains("Max")); |
| Ok(()) |
| } |
| |
| // Verifies that adding a new policy works and prints out the resulting policy ID. |
| async fn validate_volume_policy_add() -> Result<(), Error> { |
| let expected_target = AudioRenderUsage::Background; |
| let expected_volume: f32 = 1.0; |
| let expected_policy_id = 42; |
| let add_options = VolumePolicyCommands::AddPolicy(VolumePolicyOptions { |
| target: expected_target, |
| min: None, |
| max: Some(expected_volume), |
| }); |
| |
| // Create a fake volume policy service that responds to AddPolicy and verifies that the inputs |
| // are the same as expected, then return the expected policy ID. Any other calls will cause the |
| // test to fail. |
| let env = create_service!( |
| Services::VolumePolicy, |
| VolumePolicyControllerRequest::AddPolicy { target, parameters, responder } => { |
| assert_eq!(target, Target::Stream(expected_target)); |
| assert_eq!( |
| parameters, |
| PolicyParameters::Max(PolicyVolume { |
| volume: Some(expected_volume), |
| ..PolicyVolume::EMPTY |
| }) |
| ); |
| responder.send(&mut Ok(expected_policy_id))?; |
| } |
| ); |
| |
| let volume_policy_service = env |
| .connect_to_service::<VolumePolicyControllerMarker>() |
| .context("Failed to connect to volume policy service")?; |
| |
| // Make the add call. |
| let output = |
| assert_set!(volume_policy::command(volume_policy_service, Some(add_options), None)); |
| // Verify that the output contains the policy ID returned from the fake service. |
| assert!(output.contains(expected_policy_id.to_string().as_str())); |
| Ok(()) |
| } |
| |
| // Verifies that removing a policy sends the proper call to the volume policy API. |
| async fn validate_volume_policy_remove() -> Result<(), Error> { |
| let expected_policy_id = 42; |
| // Create a fake volume policy service that verifies the removed policy ID matches the expected |
| // value. Any other calls will cause the |
| // test to fail. |
| let env = create_service!( |
| Services::VolumePolicy, VolumePolicyControllerRequest::RemovePolicy { policy_id, responder } => { |
| assert_eq!(policy_id, expected_policy_id); |
| responder.send(&mut Ok(()))?; |
| } |
| ); |
| |
| let volume_policy_service = env |
| .connect_to_service::<VolumePolicyControllerMarker>() |
| .context("Failed to connect to volume policy service")?; |
| |
| // Attempt to remove the given policy ID. |
| assert_set!(volume_policy::command(volume_policy_service, None, Some(expected_policy_id))); |
| Ok(()) |
| } |