blob: dd68ae085cb71280e3518c8ac64053bd141a430e [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.
use {
crate::{
mod_manager::ModManager, module_output::ModuleOutputWriterService,
story_context_store::StoryContextStore, story_module::StoryModuleService,
},
failure::{Error, ResultExt},
fidl_fuchsia_app_discover::{DiscoverRegistryRequest, DiscoverRegistryRequestStream},
futures::prelude::*,
parking_lot::Mutex,
std::sync::Arc,
};
/// Handle DiscoveryRegistry requests.
pub async fn run_server(
story_context_store: Arc<Mutex<StoryContextStore>>,
mod_manager: Arc<Mutex<ModManager<StoryContextStore>>>,
mut stream: DiscoverRegistryRequestStream,
) -> Result<(), Error> {
while let Some(request) = stream.try_next().await.context("Error running discover registry")? {
match request {
DiscoverRegistryRequest::RegisterModuleOutputWriter { module, request, .. } => {
let module_output_stream = request.into_stream()?;
ModuleOutputWriterService::new(
story_context_store.clone(),
mod_manager.clone(),
module,
)?
.spawn(module_output_stream);
}
DiscoverRegistryRequest::RegisterStoryModule { module, request, .. } => {
let story_module_stream = request.into_stream()?;
StoryModuleService::new(story_context_store.clone(), mod_manager.clone(), module)?
.spawn(story_module_stream);
}
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use {
super::*,
crate::{
story_context_store::{ContextEntity, ContextReader, Contributor},
testing::{init_state, FakeEntityData, FakeEntityResolver},
},
fidl_fuchsia_app_discover::{
DiscoverRegistryMarker, ModuleIdentifier, ModuleOutputWriterMarker, StoryModuleMarker,
},
fidl_fuchsia_modular::{EntityResolverMarker, PuppetMasterMarker},
fuchsia_async as fasync,
maplit::hashset,
};
#[fasync::run_until_stalled(test)]
async fn test_register_module_output() -> Result<(), Error> {
// Initialize the fake entity resolver.
let (entity_resolver, request_stream) =
fidl::endpoints::create_proxy_and_stream::<EntityResolverMarker>().unwrap();
let mut fake_entity_resolver = FakeEntityResolver::new();
fake_entity_resolver
.register_entity("foo", FakeEntityData::new(vec!["some-type".into()], ""));
fake_entity_resolver.spawn(request_stream);
// Initialize service client and server.
let (client, request_stream) =
fidl::endpoints::create_proxy_and_stream::<DiscoverRegistryMarker>().unwrap();
let (puppet_master_client, _) =
fidl::endpoints::create_proxy_and_stream::<PuppetMasterMarker>().unwrap();
let (state, _, mod_manager) = init_state(puppet_master_client, entity_resolver);
let story_context = state.clone();
fasync::spawn_local(
async move { run_server(story_context, mod_manager, request_stream).await }
.unwrap_or_else(|e: Error| eprintln!("error running server {}", e)),
);
// Get the ModuleOutputWriter connection.
let (module_output_proxy, server_end) =
fidl::endpoints::create_proxy::<ModuleOutputWriterMarker>()?;
let module = ModuleIdentifier {
story_id: Some("story1".to_string()),
module_path: Some(vec!["mod-a".to_string()]),
};
assert!(client.register_module_output_writer(module, server_end).is_ok());
// Exercise the module output we got
assert!(module_output_proxy.write("param-foo", Some("foo")).await.is_ok());
// Verify state.
let expected_entity = ContextEntity::new_test(
"foo",
hashset!["some-type".to_string()],
hashset!(Contributor::module_new("story1", "mod-a", "param-foo")),
);
let context_store = state.lock();
let result = context_store.current().collect::<Vec<&ContextEntity>>();
assert_eq!(result.len(), 1);
assert_eq!(result[0], &expected_entity);
Ok(())
}
#[fasync::run_until_stalled(test)]
async fn test_register_story_module() -> Result<(), Error> {
// Initialize the fake entity resolver.
let (entity_resolver, request_stream) =
fidl::endpoints::create_proxy_and_stream::<EntityResolverMarker>().unwrap();
let mut fake_entity_resolver = FakeEntityResolver::new();
fake_entity_resolver
.register_entity("foo", FakeEntityData::new(vec!["some-type".into()], ""));
fake_entity_resolver.spawn(request_stream);
// Initialize service client and server.
let (client, request_stream) =
fidl::endpoints::create_proxy_and_stream::<DiscoverRegistryMarker>().unwrap();
let (puppet_master_client, _) =
fidl::endpoints::create_proxy_and_stream::<PuppetMasterMarker>().unwrap();
let (state, _, mod_manager) = init_state(puppet_master_client, entity_resolver);
let story_context = state.clone();
fasync::spawn_local(
async move { run_server(story_context, mod_manager, request_stream).await }
.unwrap_or_else(|e: Error| eprintln!("error running server {}", e)),
);
// Get the StoryModule connection.
let (story_module_proxy, server_end) =
fidl::endpoints::create_proxy::<StoryModuleMarker>()?;
let module = ModuleIdentifier {
story_id: Some("story1".to_string()),
module_path: Some(vec!["mod-a".to_string()]),
};
assert!(client.register_story_module(module, server_end).is_ok());
// Exercise the module output we got
assert!(story_module_proxy.write_output("param-foo", Some("foo")).await.is_ok());
// Verify state.
let expected_entity = ContextEntity::new_test(
"foo",
hashset!["some-type".to_string()],
hashset!(Contributor::module_new("story1", "mod-a", "param-foo")),
);
let context_store = state.lock();
let result = context_store.current().collect::<Vec<&ContextEntity>>();
assert_eq!(result.len(), 1);
assert_eq!(result[0], &expected_entity);
Ok(())
}
}