blob: b31d2d4d85abb5eb78023a7a0dcfeb80711d3522 [file] [edit]
// Copyright 2022 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::facet,
anyhow::Error,
diagnostics_log as flog,
fidl::endpoints::ProtocolMarker,
fidl_fuchsia_component_resolution as fresolution, fidl_fuchsia_logger as flogger,
fidl_fuchsia_sys as fv1sys, fuchsia_async as fasync,
fuchsia_component::server::ServiceFs,
fuchsia_component_test::LocalComponentHandles,
fuchsia_url::{AbsoluteComponentUrl, ComponentUrl, PackageUrl},
futures::{lock::Mutex, FutureExt, StreamExt, TryStreamExt},
itertools::Itertools,
std::{collections::HashSet, sync::Arc},
tracing::{error, warn},
};
type LogSubscriber = dyn tracing::Subscriber + std::marker::Send + std::marker::Sync + 'static;
// List of non hermetic packages accessed by a test which are logged to make it easy to transition.
#[derive(Debug)]
pub struct NonHermeticPkgList {
test_url: String,
list: Mutex<HashSet<String>>,
logger: Mutex<Option<Arc<LogSubscriber>>>,
}
impl NonHermeticPkgList {
fn new(test_url: String) -> Arc<Self> {
Arc::new(Self { test_url, list: HashSet::new().into(), logger: None.into() })
}
async fn add_pkg(&self, pkg_name: &str) {
let mut list = self.list.lock().await;
list.insert(format!("\"{}\"", pkg_name));
}
async fn set_logger(&self, subscriber: Arc<LogSubscriber>) {
let mut logger = self.logger.lock().await;
// only set logger once.
if logger.is_none() {
let _ = logger.insert(subscriber);
}
}
}
impl Drop for NonHermeticPkgList {
fn drop(&mut self) {
let list = self.list.get_mut();
if list.len() > 0 {
let s = format!("Test '{}' uses non-hermetic packages. \
Please add below line to facets of your test manifest:
\"{}\": [ {} ]\
\nSee https://fuchsia.dev/fuchsia-src/development/testing/components/test_runner_framework?hl=en#hermetic-resolver
for more information.",
self.test_url,
facet::TEST_DEPRECATED_ALLOWED_PACKAGES_FACET_KEY,
list.drain().join(", "));
// log in both test managers log sink and test's log sink so that it is easy to retrieve.
warn!("{}", s);
if let Some(subscriber) = self.logger.get_mut().take() {
tracing::subscriber::with_default(subscriber, || {
warn!("{}", s);
});
}
}
}
}
// Flag to enforce hermetic resolution. If false, default AllowedPackages value would be 'All'.
// This flag helps us easily revert the changes if there is a problem.
pub(crate) const ENFORCE_HERMETIC_RESOLUTION: bool = true;
// Enum donating the list of non-hermetic packages allowed to resolved by a test.
#[derive(Clone, Debug)]
pub enum AllowedPackages {
// Temporary enum for transition which will allow all packages.
All(Arc<NonHermeticPkgList>),
// Strict list of allowed packages.
List(Arc<HashSet<String>>),
}
impl AllowedPackages {
pub fn default(test_url: &str) -> Self {
match ENFORCE_HERMETIC_RESOLUTION {
false => Self::all(test_url.to_string()),
true => Self::zero_allowed_pkgs(),
}
}
pub fn all(test_url: String) -> Self {
Self::All(NonHermeticPkgList::new(test_url))
}
pub fn zero_allowed_pkgs() -> Self {
Self::List(Arc::new(HashSet::new()))
}
pub fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = String>,
{
Self::List(Arc::new(HashSet::from_iter(iter)))
}
}
impl PartialEq for AllowedPackages {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(AllowedPackages::All(_), AllowedPackages::All(_)) => true,
(AllowedPackages::List(l1), AllowedPackages::List(l2)) => l1.eq(l2),
_ => false,
}
}
fn ne(&self, other: &Self) -> bool {
!self.eq(other)
}
}
async fn validate_hermetic_package(
component_url_str: &str,
subscriber: Arc<LogSubscriber>,
hermetic_test_package_name: &String,
other_allowed_packages: &AllowedPackages,
) -> Result<(), fresolution::ResolverError> {
let component_url = ComponentUrl::parse(component_url_str).map_err(|err| {
warn!("cannot parse {}, {:?}", component_url_str, err);
fresolution::ResolverError::InvalidArgs
})?;
let allowed_packages = match other_allowed_packages {
AllowedPackages::All(list) => {
if let PackageUrl::Absolute(pkg_url) = &component_url.package_url() {
let package_name = pkg_url.name();
if package_name.as_ref() != hermetic_test_package_name {
list.add_pkg(package_name.as_ref()).await;
}
}
return Ok(());
}
AllowedPackages::List(l) => l,
};
match component_url.package_url() {
PackageUrl::Absolute(pkg_url) => {
let package_name = pkg_url.name();
if hermetic_test_package_name != package_name.as_ref()
&& !allowed_packages.contains(package_name.as_ref())
{
let s = format!("failed to resolve component {}: package {} is not in the test package allowlist: '{}, {}'
\nSee https://fuchsia.dev/fuchsia-src/development/testing/components/test_runner_framework?hl=en#hermetic-resolver
for more information.",
&component_url_str, package_name, hermetic_test_package_name, allowed_packages.iter().join(", "));
// log in both test managers log sink and test's log sink so that it is easy to retrieve.
tracing::subscriber::with_default(subscriber, || {
warn!("{}", s);
});
warn!("{}", s);
return Err(fresolution::ResolverError::PackageNotFound);
}
}
PackageUrl::Relative(_url) => {
// don't do anything as we don't restrict relative urls.
}
}
Ok(())
}
async fn serve_resolver(
mut stream: fresolution::ResolverRequestStream,
subscriber: Arc<LogSubscriber>,
hermetic_test_package_name: Arc<String>,
other_allowed_packages: AllowedPackages,
full_resolver: Arc<fresolution::ResolverProxy>,
) {
while let Some(request) = stream.try_next().await.expect("failed to serve component resolver") {
match request {
fresolution::ResolverRequest::Resolve { component_url, responder } => {
let mut result = if let Err(err) = validate_hermetic_package(
&component_url,
subscriber.clone(),
&hermetic_test_package_name,
&other_allowed_packages,
)
.await
{
Err(err)
} else {
let subscriber = subscriber.clone();
full_resolver.resolve(&component_url).await.unwrap_or_else(|err| {
tracing::subscriber::with_default(subscriber, || {
warn!("failed to resolve component {}: {:?}", component_url, err);
});
Err(fresolution::ResolverError::Internal)
})
};
if let Err(e) = responder.send(&mut result) {
warn!("Failed sending load response for {}: {}", component_url, e);
}
}
fresolution::ResolverRequest::ResolveWithContext {
component_url,
mut context,
responder,
} => {
// We don't need to worry about validating context because it should have
// been produced by Resolve call above.
let mut result = if let Err(err) = validate_hermetic_package(
&component_url,
subscriber.clone(),
&hermetic_test_package_name,
&other_allowed_packages,
)
.await
{
Err(err)
} else {
let subscriber = subscriber.clone();
full_resolver
.resolve_with_context(&component_url, &mut context)
.await
.unwrap_or_else(|err| {
tracing::subscriber::with_default(subscriber, || {
warn!(
"failed to resolve component {} with context {:?}: {:?}",
component_url, context, err
);
});
Err(fresolution::ResolverError::Internal)
})
};
if let Err(e) = responder.send(&mut result) {
warn!("Failed sending load response for {}: {}", component_url, e);
}
}
}
}
}
pub async fn serve_hermetic_resolver(
handles: LocalComponentHandles,
hermetic_test_package_name: Arc<String>,
other_allowed_packages: AllowedPackages,
full_resolver: Arc<fresolution::ResolverProxy>,
) -> Result<(), Error> {
let mut fs = ServiceFs::new();
let mut tasks = vec![];
let log_proxy = handles
.connect_to_named_protocol::<flogger::LogSinkMarker>(flogger::LogSinkMarker::DEBUG_NAME)?;
let tags = ["test_resolver"];
let (log_publisher, _interest_listener) = match flog::Publisher::new_with_proxy(
log_proxy,
flog::PublishOptions {
interest: flog::interest(tracing::Level::INFO),
tags: &tags,
..Default::default()
},
) {
Ok((publisher, listener)) => (Arc::new(publisher) as Arc<LogSubscriber>, listener.boxed()),
Err(e) => {
warn!("Error creating log publisher for resolver: {:?}", e);
(
Arc::new(tracing::subscriber::NoSubscriber::default()) as Arc<LogSubscriber>,
futures::future::ready(()).boxed(),
)
}
};
if let AllowedPackages::All(l) = &other_allowed_packages {
l.set_logger(log_publisher.clone()).await;
}
fs.dir("svc").add_fidl_service(move |stream: fresolution::ResolverRequestStream| {
let full_resolver = full_resolver.clone();
let hermetic_test_package_name = hermetic_test_package_name.clone();
let other_allowed_packages = other_allowed_packages.clone();
let log_publisher = log_publisher.clone();
tasks.push(fasync::Task::local(async move {
serve_resolver(
stream,
log_publisher,
hermetic_test_package_name,
other_allowed_packages,
full_resolver,
)
.await;
}));
});
fs.serve_connection(handles.outgoing_dir)?;
fs.collect::<()>().await;
Ok(())
}
async fn hermetic_loader(
component_url_str: &str,
hermetic_test_package_name: &String,
other_allowed_packages: &AllowedPackages,
loader_service: fv1sys::LoaderProxy,
) -> Option<Box<fv1sys::Package>> {
let component_url = match AbsoluteComponentUrl::parse(component_url_str) {
Ok(u) => u,
Err(e) => {
warn!("Invalid component url {}: {}", component_url_str, e);
return None;
}
};
let package_name = component_url.package_url().name();
match other_allowed_packages {
AllowedPackages::All(list) => {
if hermetic_test_package_name != package_name.as_ref() {
list.add_pkg(package_name.as_ref()).await;
}
}
AllowedPackages::List(allowed_packages) => {
if hermetic_test_package_name != package_name.as_ref()
&& !allowed_packages.contains(package_name.as_ref())
{
error!(
"failed to resolve component {}: package {} is not in the test package allowlist: '{}, {}'
\nSee https://fuchsia.dev/fuchsia-src/development/testing/components/test_runner_framework?hl=en#hermetic-resolver
for more information.",
&component_url_str, package_name, hermetic_test_package_name, allowed_packages.iter().join(", ")
);
return None;
}
}
}
match loader_service.load_url(component_url_str).await {
Ok(r) => r,
Err(e) => {
warn!("can't communicate with global loader: {}", e);
None
}
}
}
pub async fn serve_hermetic_loader(
mut stream: fv1sys::LoaderRequestStream,
hermetic_test_package_name: Arc<String>,
other_allowed_packages: AllowedPackages,
loader_service: fv1sys::LoaderProxy,
) {
while let Some(fv1sys::LoaderRequest::LoadUrl { url, responder }) =
stream.try_next().await.expect("failed to serve loader")
{
let mut result = hermetic_loader(
&url,
&hermetic_test_package_name,
&other_allowed_packages,
loader_service.clone(),
)
.await
.map(|p| *p);
if let Err(e) = responder.send(result.as_mut()) {
warn!("Failed sending load response for {}: {}", url, e);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use assert_matches::assert_matches;
use fidl::endpoints::create_proxy_and_stream;
use maplit::hashset;
async fn respond_to_resolve_requests(mut stream: fresolution::ResolverRequestStream) {
while let Some(request) =
stream.try_next().await.expect("failed to serve component mock resolver")
{
match request {
fresolution::ResolverRequest::Resolve { component_url, responder } => {
match component_url.as_str() {
"fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm"
| "fuchsia-pkg://fuchsia.com/package-three#meta/comp.cm"
| "fuchsia-pkg://fuchsia.com/package-four#meta/comp.cm" => {
responder.send(&mut Ok(fresolution::Component::EMPTY))
}
"fuchsia-pkg://fuchsia.com/package-two#meta/comp.cm" => responder
.send(&mut Err(fresolution::ResolverError::ResourceUnavailable)),
_ => responder.send(&mut Err(fresolution::ResolverError::Internal)),
}
.expect("failed sending response");
}
fresolution::ResolverRequest::ResolveWithContext {
component_url,
context: _,
responder,
} => {
match component_url.as_str() {
"fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm" | "name#resource" => {
responder.send(&mut Ok(fresolution::Component::EMPTY))
}
_ => responder.send(&mut Err(fresolution::ResolverError::PackageNotFound)),
}
.expect("failed sending response");
}
}
}
}
async fn respond_to_loader_requests(stream: &mut fv1sys::LoaderRequestStream) {
let request = stream
.next()
.await
.expect("did not get next request")
.expect("error getting next request");
match request {
fv1sys::LoaderRequest::LoadUrl { url, responder } => {
match url.as_str() {
"fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm"
| "fuchsia-pkg://fuchsia.com/package-three#meta/comp.cm"
| "fuchsia-pkg://fuchsia.com/package-four#meta/comp.cm"
| "fuchsia-pkg://fuchsia.com/package-five#meta/comp.cm" => {
responder.send(Some(&mut fv1sys::Package {
data: None,
directory: None,
resolved_url: url,
}))
}
"fuchsia-pkg://fuchsia.com/package-two#meta/comp.cm" => responder.send(None),
_ => responder.send(None),
}
.expect("failed sending response");
}
}
}
// Run hermetic resolver
fn run_resolver(
hermetic_test_package_name: Arc<String>,
other_allowed_packages: AllowedPackages,
mock_full_resolver: Arc<fresolution::ResolverProxy>,
) -> (fasync::Task<()>, fresolution::ResolverProxy) {
let (proxy, stream) =
fidl::endpoints::create_proxy_and_stream::<fresolution::ResolverMarker>().unwrap();
let subscriber = tracing::subscriber::NoSubscriber::default();
let task = fasync::Task::local(async move {
serve_resolver(
stream,
Arc::new(subscriber),
hermetic_test_package_name,
other_allowed_packages,
mock_full_resolver,
)
.await;
});
(task, proxy)
}
#[fuchsia::test]
async fn test_successful_resolve() {
let pkg_name = "package-one".to_string();
let (resolver_proxy, resolver_request_stream) =
create_proxy_and_stream::<fresolution::ResolverMarker>()
.expect("failed to create mock full resolver proxy");
let _full_resolver_task = fasync::Task::spawn(async move {
respond_to_resolve_requests(resolver_request_stream).await;
});
let (_task, hermetic_resolver_proxy) = run_resolver(
pkg_name.into(),
AllowedPackages::zero_allowed_pkgs(),
Arc::new(resolver_proxy),
);
assert_eq!(
hermetic_resolver_proxy
.resolve("fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm")
.await
.unwrap(),
Ok(fresolution::Component::EMPTY)
);
let mut mock_context = fresolution::Context { bytes: vec![0] };
assert_eq!(
hermetic_resolver_proxy
.resolve_with_context("name#resource", &mut mock_context)
.await
.unwrap(),
Ok(fresolution::Component::EMPTY)
);
assert_eq!(
hermetic_resolver_proxy
.resolve_with_context("name#not_found", &mut mock_context)
.await
.unwrap(),
Err(fresolution::ResolverError::PackageNotFound)
);
assert_eq!(
hermetic_resolver_proxy
.resolve_with_context(
"fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm",
&mut mock_context
)
.await
.unwrap(),
Ok(fresolution::Component::EMPTY)
);
}
#[fuchsia::test]
async fn drop_connection_on_resolve() {
let pkg_name = "package-one".to_string();
let (resolver_proxy, resolver_request_stream) =
create_proxy_and_stream::<fresolution::ResolverMarker>()
.expect("failed to create mock full resolver proxy");
let _full_resolver_task = fasync::Task::spawn(async move {
respond_to_resolve_requests(resolver_request_stream).await;
});
let (_task, hermetic_resolver_proxy) = run_resolver(
pkg_name.into(),
AllowedPackages::zero_allowed_pkgs(),
Arc::new(resolver_proxy),
);
let _ =
hermetic_resolver_proxy.resolve("fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm");
drop(hermetic_resolver_proxy); // code should not crash
}
#[fuchsia::test]
async fn test_package_not_allowed() {
let (resolver_proxy, _) = create_proxy_and_stream::<fresolution::ResolverMarker>()
.expect("failed to create mock full resolver proxy");
let (_task, hermetic_resolver_proxy) = run_resolver(
"package-two".to_string().into(),
AllowedPackages::zero_allowed_pkgs(),
Arc::new(resolver_proxy),
);
assert_eq!(
hermetic_resolver_proxy
.resolve("fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm")
.await
.unwrap(),
Err(fresolution::ResolverError::PackageNotFound)
);
let mut mock_context = fresolution::Context { bytes: vec![0] };
assert_eq!(
hermetic_resolver_proxy
.resolve_with_context(
"fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm",
&mut mock_context
)
.await
.unwrap(),
Err(fresolution::ResolverError::PackageNotFound)
);
}
#[fuchsia::test]
async fn other_packages_allowed() {
let (resolver_proxy, resolver_request_stream) =
create_proxy_and_stream::<fresolution::ResolverMarker>()
.expect("failed to create mock full resolver proxy");
let list = hashset!("package-three".to_string(), "package-four".to_string());
let _full_resolver_task = fasync::Task::spawn(async move {
respond_to_resolve_requests(resolver_request_stream).await;
});
let (_task, hermetic_resolver_proxy) = run_resolver(
"package-two".to_string().into(),
AllowedPackages::List(list.into()),
Arc::new(resolver_proxy),
);
assert_eq!(
hermetic_resolver_proxy
.resolve("fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm")
.await
.unwrap(),
Err(fresolution::ResolverError::PackageNotFound)
);
assert_eq!(
hermetic_resolver_proxy
.resolve("fuchsia-pkg://fuchsia.com/package-three#meta/comp.cm")
.await
.unwrap(),
Ok(fresolution::Component::EMPTY)
);
assert_eq!(
hermetic_resolver_proxy
.resolve("fuchsia-pkg://fuchsia.com/package-four#meta/comp.cm")
.await
.unwrap(),
Ok(fresolution::Component::EMPTY)
);
assert_eq!(
hermetic_resolver_proxy
.resolve("fuchsia-pkg://fuchsia.com/package-two#meta/comp.cm")
.await
.unwrap(),
// we return this error from our mock resolver for package-two.
Err(fresolution::ResolverError::ResourceUnavailable)
);
}
#[fuchsia::test]
async fn test_failed_resolve() {
let (resolver_proxy, resolver_request_stream) =
create_proxy_and_stream::<fresolution::ResolverMarker>()
.expect("failed to create mock full resolver proxy");
let _full_resolver_task = fasync::Task::spawn(async move {
respond_to_resolve_requests(resolver_request_stream).await;
});
let pkg_name = "package-two".to_string();
let (_task, hermetic_resolver_proxy) = run_resolver(
pkg_name.into(),
AllowedPackages::zero_allowed_pkgs(),
Arc::new(resolver_proxy),
);
assert_eq!(
hermetic_resolver_proxy
.resolve("fuchsia-pkg://fuchsia.com/package-two#meta/comp.cm")
.await
.unwrap(),
Err(fresolution::ResolverError::ResourceUnavailable)
);
}
#[fuchsia::test]
async fn test_invalid_url() {
let (resolver_proxy, _) = create_proxy_and_stream::<fresolution::ResolverMarker>()
.expect("failed to create mock full resolver proxy");
let pkg_name = "package-two".to_string();
let (_task, hermetic_resolver_proxy) = run_resolver(
pkg_name.into(),
AllowedPackages::zero_allowed_pkgs(),
Arc::new(resolver_proxy),
);
assert_eq!(
hermetic_resolver_proxy.resolve("invalid_url").await.unwrap(),
Err(fresolution::ResolverError::InvalidArgs)
);
}
mod loader {
use super::*;
#[fuchsia::test]
async fn test_successful_loader() {
let pkg_name = "package-one".to_string();
let (loader_proxy, mut loader_request_stream) =
create_proxy_and_stream::<fv1sys::LoaderMarker>()
.expect("failed to create mock loader proxy");
let (proxy, stream) = create_proxy_and_stream::<fv1sys::LoaderMarker>().unwrap();
let _loader_task = fasync::Task::spawn(async move {
respond_to_loader_requests(&mut loader_request_stream).await;
drop(loader_request_stream);
});
let _serve_task = fasync::Task::spawn(serve_hermetic_loader(
stream,
pkg_name.into(),
AllowedPackages::zero_allowed_pkgs(),
loader_proxy,
));
assert_matches!(
proxy.load_url("fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm").await.unwrap(),
Some(_)
);
}
#[fuchsia::test]
async fn drop_connection_on_load() {
let pkg_name = "package-one".to_string();
let (loader_proxy, mut loader_request_stream) =
create_proxy_and_stream::<fv1sys::LoaderMarker>()
.expect("failed to create mock loader proxy");
let (proxy, stream) = create_proxy_and_stream::<fv1sys::LoaderMarker>().unwrap();
let loader_task = fasync::Task::spawn(async move {
respond_to_loader_requests(&mut loader_request_stream).await;
drop(loader_request_stream);
});
let _serve_task = fasync::Task::spawn(serve_hermetic_loader(
stream,
pkg_name.into(),
AllowedPackages::zero_allowed_pkgs(),
loader_proxy,
));
let _ = proxy.load_url("fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm");
drop(proxy);
loader_task.await;
}
// Logging disabled as this outputs ERROR log, which will fail the test.
#[fuchsia::test(logging = false)]
async fn test_package_not_allowed() {
let (loader_proxy, _) = create_proxy_and_stream::<fv1sys::LoaderMarker>()
.expect("failed to create mock loader proxy");
let (proxy, stream) = create_proxy_and_stream::<fv1sys::LoaderMarker>().unwrap();
let _serve_task = fasync::Task::spawn(serve_hermetic_loader(
stream,
"package-two".to_string().into(),
AllowedPackages::zero_allowed_pkgs(),
loader_proxy,
));
assert_eq!(
proxy.load_url("fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm").await.unwrap(),
None
);
}
#[fuchsia::test]
async fn test_failed_loader() {
let (loader_proxy, mut loader_request_stream) =
create_proxy_and_stream::<fv1sys::LoaderMarker>()
.expect("failed to create mock loader proxy");
let _loader_task = fasync::Task::spawn(async move {
respond_to_loader_requests(&mut loader_request_stream).await;
drop(loader_request_stream);
});
let pkg_name = "package-two".to_string();
let (proxy, stream) = create_proxy_and_stream::<fv1sys::LoaderMarker>().unwrap();
let _serve_task = fasync::Task::spawn(serve_hermetic_loader(
stream,
pkg_name.into(),
AllowedPackages::zero_allowed_pkgs(),
loader_proxy,
));
assert_eq!(
proxy.load_url("fuchsia-pkg://fuchsia.com/package-two#meta/comp.cm").await.unwrap(),
None
);
}
// Logging disabled as this outputs ERROR log, which will fail the test.
#[fuchsia::test(logging = false)]
async fn other_packages_allowed() {
let list = hashset!("package-three".to_string(), "package-four".to_string());
let (loader_proxy, mut loader_request_stream) =
create_proxy_and_stream::<fv1sys::LoaderMarker>()
.expect("failed to create mock loader proxy");
let _loader_task = fasync::Task::spawn(async move {
for _ in 0..4 {
respond_to_loader_requests(&mut loader_request_stream).await;
}
drop(loader_request_stream);
});
let pkg_name = "package-five".to_string();
let (proxy, stream) = create_proxy_and_stream::<fv1sys::LoaderMarker>().unwrap();
let _serve_task = fasync::Task::spawn(serve_hermetic_loader(
stream,
pkg_name.into(),
AllowedPackages::List(list.into()),
loader_proxy,
));
assert_eq!(
proxy.load_url("fuchsia-pkg://fuchsia.com/package-one#meta/comp.cm").await.unwrap(),
None
);
assert_matches!(
proxy
.load_url("fuchsia-pkg://fuchsia.com/package-five#meta/comp.cm")
.await
.unwrap(),
Some(_)
);
assert_matches!(
proxy
.load_url("fuchsia-pkg://fuchsia.com/package-three#meta/comp.cm")
.await
.unwrap(),
Some(_)
);
assert_matches!(
proxy
.load_url("fuchsia-pkg://fuchsia.com/package-four#meta/comp.cm")
.await
.unwrap(),
Some(_)
);
}
#[fuchsia::test]
async fn test_invalid_url_loader() {
let (loader_proxy, _) = create_proxy_and_stream::<fv1sys::LoaderMarker>()
.expect("failed to create mock loader proxy");
let pkg_name = "package-two".to_string();
let (proxy, stream) = create_proxy_and_stream::<fv1sys::LoaderMarker>().unwrap();
let _serve_task = fasync::Task::spawn(serve_hermetic_loader(
stream,
pkg_name.into(),
AllowedPackages::zero_allowed_pkgs(),
loader_proxy,
));
assert_eq!(proxy.load_url("invalid_url").await.unwrap(), None);
}
}
}