blob: b2f46d0cb56ebc59fc74cfd58153fe010b84eecb [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::internal::event::{self as event, message::Receptor, restore, Event};
use crate::message::base::{MessageEvent, MessengerType};
use crate::registry::device_storage::testing::InMemoryStorageFactory;
use crate::switchboard::base::{
SettingRequest, SettingResponseResult, SettingType, SwitchboardError,
};
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 fuchsia_component::server::NestedEnvironment;
use futures::future::BoxFuture;
use futures::lock::Mutex;
use futures::StreamExt;
use std::sync::Arc;
const ENV_NAME: &str = "restore_agent_test_environment";
// Create an environment that includes Event handling.
async fn create_event_environment(
) -> (NestedEnvironment, Arc<Mutex<Option<event::message::Receptor>>>) {
let event_receptor: Arc<Mutex<Option<Receptor>>> = Arc::new(Mutex::new(None));
let receptor_capture = event_receptor.clone();
// Upon environment initialization, the subscriber will capture the event receptor.
let create_subscriber =
Arc::new(move |factory: event::message::Factory| -> BoxFuture<'static, ()> {
let event_receptor = receptor_capture.clone();
Box::pin(async move {
let (_, receptor) = factory
.create(MessengerType::Unbound)
.await
.expect("Should be able to retrieve messenger for publisher");
*event_receptor.lock().await = Some(receptor);
})
});
let env = EnvironmentBuilder::new(InMemoryStorageFactory::create())
.service(ServiceRegistry::serve(ServiceRegistry::create()))
.event_subscribers(&[Blueprint::create(create_subscriber)])
.settings(&[SettingType::Setup])
.agents(&[restore_agent::blueprint::create()])
.spawn_and_get_nested_environment(ENV_NAME)
.await
.unwrap();
(env, 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() -> SettingResponseResult + 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(InMemoryStorageFactory::create())
.handler(
SettingType::Unknown,
create_setting_handler(Box::new(move |request| {
let counter = counter_clone.clone();
if request == SettingRequest::Restore {
let result = (response_generate)();
return Box::pin(async move {
let mut counter_lock = counter.lock().await;
*counter_lock += 1;
return result;
});
} else {
return 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(SwitchboardError::UnimplementedRequest {
setting_type: SettingType::Unknown,
request: SettingRequest::Restore,
})
}),
true,
)
.await;
// Should succeed when the setting is not available.
verify_restore_handling(
Box::new(|| Err(SwitchboardError::UnhandledType { setting_type: SettingType::Unknown })),
true,
)
.await;
// Snould fail when any other error is introduced.
verify_restore_handling(
Box::new(|| Err(SwitchboardError::UnexpectedError { description: "foo".to_string() })),
false,
)
.await;
}
#[fuchsia_async::run_until_stalled(test)]
async fn test_unimplemented() {
let (_, receptor) = create_event_environment().await;
let mut event_receptor = receptor.lock().await.take().expect("Should have captured receptor");
if let Some(MessageEvent::Message(event::Payload::Event(received_event), ..)) =
event_receptor.next().await
{
assert_eq!(received_event, Event::Restore(restore::Event::NoOp(SettingType::Setup)));
}
}