blob: 7be1a581210393a67ed6ac6ed5e30bc8141d8e5b [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::event::{self as event, restore, Event};
use crate::handler::base::Request;
use crate::handler::setting_handler::{ControllerError, SettingHandlerResult};
use crate::ingress::fidl::Interface;
use crate::service;
use crate::service::message::Receptor;
use crate::tests::fakes::base::create_setting_handler;
use crate::tests::fakes::service_registry::ServiceRegistry;
use crate::tests::scaffold::event::subscriber::Blueprint;
use crate::EnvironmentBuilder;
use futures::future::BoxFuture;
use futures::lock::Mutex;
use std::sync::Arc;
const ENV_NAME: &str = "restore_agent_test_environment";
// Create an environment that includes Event handling.
async fn create_event_environment() -> Arc<Mutex<Option<Receptor>>> {
let event_receptor: Arc<Mutex<Option<Receptor>>> = Arc::new(Mutex::new(None));
// Upon environment initialization, the subscriber will capture the event receptor.
let create_subscriber = Arc::new({
let event_receptor = Arc::clone(&event_receptor);
move |delegate: service::message::Delegate| -> BoxFuture<'static, ()> {
let event_receptor = Arc::clone(&event_receptor);
Box::pin(async move {
let mut event_receptor = event_receptor.lock().await;
*event_receptor = Some(service::build_event_listener(&delegate).await);
})
}
});
let _env = EnvironmentBuilder::new(Arc::new(InMemoryStorageFactory::new()))
.service(ServiceRegistry::serve(ServiceRegistry::create()))
.event_subscribers(&[Blueprint::create(create_subscriber)])
.fidl_interfaces(&[Interface::Setup])
.agents(&[restore_agent::blueprint::create()])
.spawn_and_get_nested_environment(ENV_NAME)
.await
.unwrap();
event_receptor
}
// Helper function for bringing up an environment with a single handler for a
// single SettingType and validating the environment initialization result.
async fn verify_restore_handling(
response_generate: Box<dyn Fn() -> SettingHandlerResult + Send + Sync + 'static>,
success: bool,
) {
let counter: Arc<Mutex<u64>> = Arc::new(Mutex::new(0));
let counter_clone = counter.clone();
assert_eq!(
success,
EnvironmentBuilder::new(Arc::new(InMemoryStorageFactory::new()))
.handler(
SettingType::Unknown,
create_setting_handler(Box::new(move |request| {
let counter = counter_clone.clone();
if request == Request::Restore {
let result = (response_generate)();
Box::pin(async move {
let mut counter_lock = counter.lock().await;
*counter_lock += 1;
result
})
} else {
Box::pin(async { Ok(None) })
}
})),
)
.agents(&[restore_agent::blueprint::create()])
.settings(&[SettingType::Unknown])
.spawn_nested(ENV_NAME)
.await
.is_ok()
);
assert_eq!(*counter.lock().await, 1);
}
#[fuchsia_async::run_until_stalled(test)]
async fn test_restore() {
// Should succeed when the restore command is handled.
verify_restore_handling(Box::new(|| Ok(None)), true).await;
// Snould succeed when the restore command is explicitly not handled.
verify_restore_handling(
Box::new(|| {
Err(ControllerError::UnimplementedRequest(SettingType::Unknown, Request::Restore))
}),
true,
)
.await;
// Should succeed when the setting is not available.
verify_restore_handling(
Box::new(|| Err(ControllerError::UnhandledType(SettingType::Unknown))),
true,
)
.await;
// Snould fail when any other error is introduced.
verify_restore_handling(
Box::new(|| Err(ControllerError::UnexpectedError("foo".into()))),
false,
)
.await;
}
// Verifies the no-op event was properly passed through and matches.
#[fuchsia_async::run_until_stalled(test)]
async fn test_unimplemented() {
// The environment uses SettingType::Setup, whose controller, setup_controller, does not
// implement Restore.
let receptor = create_event_environment().await;
let mut event_receptor = receptor.lock().await.take().expect("Should have captured receptor");
loop {
let payload = event_receptor.next_of::<event::Payload>().await;
if let Ok((
event::Payload::Event(Event::Restore(restore::Event::NoOp(SettingType::Setup))),
_,
)) = payload
{
return;
}
// Else, test will stall and fail if the above event is never received.
}
}