blob: 150f39f9ed9824ddf73dcfc7d598c6ac4b3b0ec3 [file] [log] [blame]
// 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.
#[cfg(test)]
use {
crate::agent::restore_agent,
crate::registry::device_storage::testing::*,
crate::switchboard::base::{DisplayInfo, LowLightMode, SettingType},
crate::tests::fakes::service_registry::ServiceRegistry,
crate::tests::test_failure_utils::create_test_env_with_failures,
crate::EnvironmentBuilder,
anyhow::format_err,
fidl::endpoints::{ServerEnd, ServiceMarker},
fidl::Error::ClientChannelClosed,
fidl_fuchsia_settings::{
DisplayMarker, DisplayProxy, DisplaySettings, IntlMarker, LowLightMode as FidlLowLightMode,
},
fuchsia_async as fasync,
fuchsia_zircon::{self as zx, Status},
futures::future::BoxFuture,
futures::lock::Mutex,
futures::prelude::*,
std::sync::Arc,
};
const ENV_NAME: &str = "settings_service_display_test_environment";
const STARTING_BRIGHTNESS: f32 = 0.5;
const CHANGED_BRIGHTNESS: f32 = 0.8;
const CONTEXT_ID: u64 = 0;
async fn setup_display_env() -> DisplayProxy {
let service_gen = |service_name: &str,
channel: zx::Channel|
-> BoxFuture<'static, Result<(), anyhow::Error>> {
if service_name != fidl_fuchsia_ui_brightness::ControlMarker::NAME {
return Box::pin(async { Err(format_err!("unsupported!")) });
}
let manager_stream_result =
ServerEnd::<fidl_fuchsia_ui_brightness::ControlMarker>::new(channel).into_stream();
if manager_stream_result.is_err() {
return Box::pin(async { Err(format_err!("could not move into stream")) });
}
let mut manager_stream = manager_stream_result.unwrap();
fasync::spawn(async move {
let mut stored_brightness_value: f32 = STARTING_BRIGHTNESS;
let mut auto_brightness_on = false;
while let Some(req) = manager_stream.try_next().await.unwrap() {
#[allow(unreachable_patterns)]
match req {
fidl_fuchsia_ui_brightness::ControlRequest::WatchCurrentBrightness {
responder,
} => {
responder.send(stored_brightness_value).unwrap();
}
fidl_fuchsia_ui_brightness::ControlRequest::SetManualBrightness {
value,
control_handle: _,
} => {
stored_brightness_value = value;
auto_brightness_on = false;
}
fidl_fuchsia_ui_brightness::ControlRequest::SetAutoBrightness {
control_handle: _,
} => {
auto_brightness_on = true;
}
fidl_fuchsia_ui_brightness::ControlRequest::WatchAutoBrightness {
responder,
} => {
responder.send(auto_brightness_on).unwrap();
}
_ => {}
}
}
});
Box::pin(async { Ok(()) })
};
let env = EnvironmentBuilder::new(InMemoryStorageFactory::create())
.service(Box::new(service_gen))
.settings(&[SettingType::Display])
.spawn_and_get_nested_environment(ENV_NAME)
.await
.unwrap();
env.connect_to_service::<DisplayMarker>().unwrap()
}
// Creates an environment that will fail on a get request.
async fn create_display_test_env_with_failures(
storage_factory: Arc<Mutex<InMemoryStorageFactory>>,
) -> DisplayProxy {
create_test_env_with_failures(storage_factory, ENV_NAME, SettingType::Display)
.await
.connect_to_service::<DisplayMarker>()
.unwrap()
}
/// Tests that the FIDL calls for manual brightness result in appropriate
/// commands sent to the switchboard.
#[fuchsia_async::run_until_stalled(test)]
async fn test_manual_brightness() {
let display_proxy = setup_display_env().await;
let settings = display_proxy.watch2().await.expect("watch completed");
assert_eq!(settings.brightness_value, Some(STARTING_BRIGHTNESS));
let mut display_settings = DisplaySettings::empty();
display_settings.brightness_value = Some(CHANGED_BRIGHTNESS);
display_proxy.set(display_settings).await.expect("set completed").expect("set successful");
let settings = display_proxy.watch2().await.expect("watch completed");
assert_eq!(settings.brightness_value, Some(CHANGED_BRIGHTNESS));
}
/// Tests that the FIDL calls for auto brightness result in appropriate
/// commands sent to the switchboard.
#[fuchsia_async::run_until_stalled(test)]
async fn test_auto_brightness() {
let display_proxy = setup_display_env().await;
let mut display_settings = DisplaySettings::empty();
display_settings.auto_brightness = Some(true);
display_proxy.set(display_settings).await.expect("set completed").expect("set successful");
let settings = display_proxy.watch2().await.expect("watch completed");
assert_eq!(settings.auto_brightness, Some(true));
}
/// Tests that the FIDL calls for light mode result in appropriate
/// commands sent to the switchboard.
#[fuchsia_async::run_until_stalled(test)]
async fn test_light_mode() {
let display_proxy = setup_display_env().await;
// Test that if display is enabled, it is reflected.
let mut display_settings = DisplaySettings::empty();
display_settings.low_light_mode = Some(FidlLowLightMode::Enable);
display_proxy.set(display_settings).await.expect("set completed").expect("set successful");
let settings = display_proxy.watch2().await.expect("watch completed");
assert_eq!(settings.low_light_mode, Some(FidlLowLightMode::Enable));
// Test that if display is disabled, it is reflected.
let mut display_settings = DisplaySettings::empty();
display_settings.low_light_mode = Some(FidlLowLightMode::Disable);
display_proxy.set(display_settings).await.expect("set completed").expect("set successful");
let settings = display_proxy.watch2().await.expect("watch completed");
assert_eq!(settings.low_light_mode, Some(FidlLowLightMode::Disable));
// Test that if display is disabled immediately, it is reflected.
let mut display_settings = DisplaySettings::empty();
display_settings.low_light_mode = Some(FidlLowLightMode::DisableImmediately);
display_proxy.set(display_settings).await.expect("set completed").expect("set successful");
let settings = display_proxy.watch2().await.expect("watch completed");
assert_eq!(settings.low_light_mode, Some(FidlLowLightMode::DisableImmediately));
}
/// Makes sure that a failing display stream doesn't cause a failure for a different interface.
#[fuchsia_async::run_until_stalled(test)]
async fn test_display_restore() {
// Ensure auto-brightness value is restored correctly.
validate_restore(0.7, true, LowLightMode::Enable).await;
// Ensure manual-brightness value is restored correctly.
validate_restore(0.9, false, LowLightMode::Disable).await;
}
async fn validate_restore(
manual_brightness: f32,
auto_brightness: bool,
low_light_mode: LowLightMode,
) {
let service_registry = ServiceRegistry::create();
let storage_factory = InMemoryStorageFactory::create();
{
let store = storage_factory
.lock()
.await
.get_device_storage::<DisplayInfo>(StorageAccessContext::Test, CONTEXT_ID);
let info = DisplayInfo {
manual_brightness_value: manual_brightness,
auto_brightness,
low_light_mode,
};
assert!(store.lock().await.write(&info, false).await.is_ok());
}
let env = EnvironmentBuilder::new(storage_factory)
.service(Box::new(ServiceRegistry::serve(service_registry)))
.agents(&[restore_agent::blueprint::create()])
.settings(&[SettingType::Display])
.spawn_and_get_nested_environment(ENV_NAME)
.await
.ok();
assert!(env.is_some());
let display_proxy = env.unwrap().connect_to_service::<DisplayMarker>().unwrap();
let settings = display_proxy.watch2().await.expect("watch completed");
if auto_brightness {
assert_eq!(settings.auto_brightness, Some(auto_brightness));
} else {
assert_eq!(settings.brightness_value, Some(manual_brightness));
}
}
/// Makes sure that a failing display stream doesn't cause a failure for a different interface.
#[fuchsia_async::run_until_stalled(test)]
async fn test_display_failure() {
let service_gen = |service_name: &str,
channel: zx::Channel|
-> BoxFuture<'static, Result<(), anyhow::Error>> {
match service_name {
fidl_fuchsia_ui_brightness::ControlMarker::NAME => {
// This stream is closed immediately
let manager_stream_result =
ServerEnd::<fidl_fuchsia_ui_brightness::ControlMarker>::new(channel)
.into_stream();
if manager_stream_result.is_err() {
return Box::pin(async {
Err(format_err!("could not move brightness channel into stream"))
});
}
return Box::pin(async { Ok(()) });
}
fidl_fuchsia_deprecatedtimezone::TimezoneMarker::NAME => {
let timezone_stream_result =
ServerEnd::<fidl_fuchsia_deprecatedtimezone::TimezoneMarker>::new(channel)
.into_stream();
if timezone_stream_result.is_err() {
return Box::pin(async {
Err(format_err!("could not move timezone channel into stream"))
});
}
let mut timezone_stream = timezone_stream_result.unwrap();
fasync::spawn(async move {
while let Some(req) = timezone_stream.try_next().await.unwrap() {
#[allow(unreachable_patterns)]
match req {
fidl_fuchsia_deprecatedtimezone::TimezoneRequest::GetTimezoneId {
responder,
} => {
responder.send("PDT").unwrap();
}
_ => {}
}
}
});
return Box::pin(async { Ok(()) });
}
_ => Box::pin(async { Err(format_err!("unsupported")) }),
}
};
let env = EnvironmentBuilder::new(InMemoryStorageFactory::create())
.service(Box::new(service_gen))
.settings(&[SettingType::Display, SettingType::Intl])
.spawn_and_get_nested_environment(ENV_NAME)
.await
.unwrap();
let display_proxy = env.connect_to_service::<DisplayMarker>().expect("connected to service");
let _settings_value = display_proxy.watch2().await.expect("watch completed");
let intl_service = env.connect_to_service::<IntlMarker>().unwrap();
let _settings = intl_service.watch2().await.expect("watch completed");
}
#[fuchsia_async::run_until_stalled(test)]
async fn test_channel_failure_watch2() {
let display_proxy =
create_display_test_env_with_failures(InMemoryStorageFactory::create()).await;
let result = display_proxy.watch2().await;
assert!(result.is_err());
assert_eq!(
ClientChannelClosed(Status::INTERNAL).to_string(),
result.err().unwrap().to_string()
);
}