blob: a4ccacce43cb60f8b8838aeb3dfa830aba9dd0d4 [file] [log] [blame]
// 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.
use crate::agent::restore_agent;
use crate::agent::storage::storage_factory::testing::InMemoryStorageFactory;
use crate::base::SettingType;
use crate::factory_reset::types::FactoryResetInfo;
use crate::handler::base::Request;
use crate::handler::setting_handler::ControllerError;
use crate::ingress::fidl::Interface;
use crate::tests::fakes::base::create_setting_handler;
use crate::tests::fakes::recovery_policy_service::RecoveryPolicy;
use crate::tests::fakes::service_registry::ServiceRegistry;
use crate::EnvironmentBuilder;
use assert_matches::assert_matches;
use fidl_fuchsia_settings::{FactoryResetMarker, FactoryResetProxy, FactoryResetSettings};
use futures::lock::Mutex;
use std::sync::Arc;
const ENV_NAME: &str = "settings_service_factory_test_environment";
const STARTING_RESET: bool = true;
const CHANGED_RESET: bool = false;
async fn setup_env() -> (FactoryResetProxy, RecoveryPolicy) {
let service_registry = ServiceRegistry::create();
let recovery_policy_service_handler = RecoveryPolicy::create();
service_registry
.lock()
.await
.register_service(Arc::new(Mutex::new(recovery_policy_service_handler.clone())));
let env = EnvironmentBuilder::new(Arc::new(InMemoryStorageFactory::new()))
.service(Box::new(ServiceRegistry::serve(service_registry)))
.fidl_interfaces(&[Interface::FactoryReset])
.spawn_and_get_nested_environment(ENV_NAME)
.await
.unwrap();
let factory_reset_proxy =
env.connect_to_protocol::<FactoryResetMarker>().expect("FactoryReset should be available");
(factory_reset_proxy, recovery_policy_service_handler)
}
// Tests that the FIDL calls for the reset setting result in appropriate
// commands sent to the service.
#[fuchsia_async::run_until_stalled(test)]
async fn test_set() {
let (factory_reset_proxy, recovery_policy_service_handler) = setup_env().await;
// Validate the default value when the service starts.
let settings = factory_reset_proxy.watch().await.expect("watch completed");
assert_eq!(settings.is_local_reset_allowed, Some(STARTING_RESET));
// Validate no value has been sent to the recovery policy service.
{
let local_reset_allowed = recovery_policy_service_handler.is_local_reset_allowed();
let local_reset_allowed = local_reset_allowed.lock().await;
assert_eq!(*local_reset_allowed, None);
}
// Update the value.
let mut factory_reset_settings = FactoryResetSettings::EMPTY;
factory_reset_settings.is_local_reset_allowed = Some(CHANGED_RESET);
factory_reset_proxy
.set(factory_reset_settings)
.await
.expect("set completed")
.expect("set successful");
// Validate the value was sent to the recovery policy service.
{
let mutex = recovery_policy_service_handler.is_local_reset_allowed();
let local_reset_allowed = mutex.lock().await;
assert_eq!(*local_reset_allowed, Some(CHANGED_RESET));
}
// Validate the value is available on the next watch.
let settings = factory_reset_proxy.watch().await.expect("watch completed");
assert_eq!(settings.is_local_reset_allowed, Some(CHANGED_RESET));
}
// Makes sure that settings are restored from storage when service comes online.
#[fuchsia_async::run_until_stalled(test)]
async fn test_restore() {
// Ensure is_local_reset_allowed value is restored correctly.
validate_restore(true).await;
validate_restore(false).await;
}
async fn validate_restore(is_local_reset_allowed: bool) {
let service_registry = ServiceRegistry::create();
let recovery_policy_service_handler = RecoveryPolicy::create();
service_registry
.lock()
.await
.register_service(Arc::new(Mutex::new(recovery_policy_service_handler.clone())));
// Set stored value.
let storage_factory =
InMemoryStorageFactory::with_initial_data(&FactoryResetInfo { is_local_reset_allowed });
// Bring up environment with restore agent and factory reset.
let env = EnvironmentBuilder::new(Arc::new(storage_factory))
.service(Box::new(ServiceRegistry::serve(service_registry)))
.agents(&[restore_agent::blueprint::create()])
.fidl_interfaces(&[Interface::FactoryReset])
.spawn_and_get_nested_environment(ENV_NAME)
.await
.expect("env should be available");
// Connect to the proxy so we ensure the restore has occurred.
let factory_reset_proxy = env
.connect_to_protocol::<FactoryResetMarker>()
.expect("factory reset service should be available");
// Validate that the recovery policy service received the restored value.
{
let mutex = recovery_policy_service_handler.is_local_reset_allowed();
let local_reset_allowed = mutex.lock().await;
assert_eq!(*local_reset_allowed, Some(is_local_reset_allowed));
}
// Validate that the restored value is available on the next watch.
let settings = factory_reset_proxy.watch().await.expect("watch completed");
assert_eq!(settings.is_local_reset_allowed, Some(is_local_reset_allowed));
}
// Tests that the FIDL calls for the reset setting result in appropriate
// commands sent to the service.
#[fuchsia_async::run_until_stalled(test)]
async fn test_error_propagation() {
let service_registry = ServiceRegistry::create();
let recovery_policy_service_handler = RecoveryPolicy::create();
service_registry
.lock()
.await
.register_service(Arc::new(Mutex::new(recovery_policy_service_handler.clone())));
// Bring up environment with restore agent and factory reset.
let env = EnvironmentBuilder::new(Arc::new(InMemoryStorageFactory::new()))
.service(Box::new(ServiceRegistry::serve(service_registry)))
.handler(
SettingType::FactoryReset,
create_setting_handler(Box::new(move |request| {
if request == Request::Get {
return Box::pin(async {
Err(ControllerError::UnhandledType(SettingType::FactoryReset))
});
} else {
return Box::pin(async { Ok(None) });
}
})),
)
.fidl_interfaces(&[Interface::FactoryReset])
.spawn_and_get_nested_environment(ENV_NAME)
.await
.expect("env should be available");
// Connect to the proxy.
let factory_reset_proxy = env
.connect_to_protocol::<FactoryResetMarker>()
.expect("factory reset service should be available");
// Validate that an unavailable error is returned.
assert_matches!(
factory_reset_proxy.watch().await,
Err(fidl::Error::ClientChannelClosed {
status: fuchsia_zircon::Status::UNAVAILABLE,
protocol_name: "fuchsia.settings.FactoryReset"
})
);
}