blob: 628181463657680f4a17e14307a8017050a1149f [file] [log] [blame]
// Copyright 2021 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.
//! This program launches `fuchsia.examples.services.BankAccount` service providers and consumes
//! their instances.
//!
//! This program is written as a test so that it can be easily launched with `fx test`.
use fuchsia_component::client as fclient;
use tracing::*;
use {
fidl_fuchsia_component as fcomponent, fidl_fuchsia_component_decl as fdecl,
fidl_fuchsia_examples_services as fexamples, fidl_fuchsia_io as fio,
};
const COLLECTION_NAME: &'static str = "account_providers";
#[fuchsia::test]
async fn read_and_write_to_multiple_service_instances() {
// Launch two BankAccount providers into the `account_providers` collection.
let realm = fuchsia_component::client::connect_to_protocol::<fcomponent::RealmMarker>()
.expect("connect to Realm service");
start_provider(&realm, "a", "provider-a#meta/default.cm").await;
start_provider(&realm, "b", "provider-b#meta/default.cm").await;
let service_dir = fclient::open_service::<fexamples::BankAccountMarker>()
.expect("failed to open service dir");
let instances = fuchsia_fs::directory::readdir(&service_dir)
.await
.expect("failed to read entries from service_dir")
.into_iter()
.map(|dirent| dirent.name);
// Debit both bank accounts by $5.
for instance in instances {
let proxy = fclient::connect_to_service_instance::<fexamples::BankAccountMarker>(&instance)
.expect("failed to connect to service instance");
let read_only_account = proxy.connect_to_read_only().expect("read_only protocol");
let owner = read_only_account.get_owner().await.expect("failed to get owner");
let initial_balance = read_only_account.get_balance().await.expect("failed to get_balance");
info!(%owner, balance = %initial_balance, "retrieved account");
let read_write_account = proxy.connect_to_read_write().expect("read_write protocol");
assert_eq!(read_write_account.get_owner().await.expect("failed to get_owner"), owner);
assert_eq!(
read_write_account.get_balance().await.expect("failed to get_balance"),
initial_balance
);
info!(%owner, "debiting account");
read_write_account.debit(5).await.expect("failed to debit");
assert_eq!(
read_write_account.get_balance().await.expect("failed to get_balance"),
initial_balance - 5
);
}
}
async fn start_provider(
realm: &fcomponent::RealmProxy,
name: &str,
url: &str,
) -> fio::DirectoryProxy {
info!(%name, %url, "creating BankAccount provider");
let child_args = fcomponent::CreateChildArgs { numbered_handles: None, ..Default::default() };
realm
.create_child(
&fdecl::CollectionRef { name: COLLECTION_NAME.to_string() },
&fdecl::Child {
name: Some(name.to_string()),
url: Some(url.to_string()),
startup: Some(fdecl::StartupMode::Lazy),
environment: None,
..Default::default()
},
child_args,
)
.await
.expect("failed to make create_child FIDL call")
.expect("failed to create_child");
let (exposed_dir, exposed_dir_server_end) =
fidl::endpoints::create_proxy::<fio::DirectoryMarker>()
.expect("failed to create endpoints");
info!(%name, %url, "open exposed dir of BankAccount provider");
realm
.open_exposed_dir(
&fdecl::ChildRef {
name: name.to_string(),
collection: Some(COLLECTION_NAME.to_string()),
},
exposed_dir_server_end,
)
.await
.expect("failed to make open_exposed_dir FIDL call")
.expect("failed to open_exposed_dir");
exposed_dir
}