[identity] Run account manager in a nested environment for integ tests.
This creates a nested environment to run account manager in for
integ tests, allowing the creation of multiple tests without
persistent data leaking between tests.
Testing: Existing tests.
Change-Id: I213fe17f10d975e4428858e286f42c0abf87fc2a
diff --git a/src/identity/tests/account_manager_integration/BUILD.gn b/src/identity/tests/account_manager_integration/BUILD.gn
index 557b8e4..def340a 100644
--- a/src/identity/tests/account_manager_integration/BUILD.gn
+++ b/src/identity/tests/account_manager_integration/BUILD.gn
@@ -35,6 +35,7 @@
"//src/identity/lib/account_common",
"//third_party/rust_crates:failure",
"//third_party/rust_crates:futures-preview",
+ "//third_party/rust_crates:lazy_static",
"//third_party/rust_crates:log",
"//third_party/rust_crates:parking_lot",
]
diff --git a/src/identity/tests/account_manager_integration/meta/account_manager_integration_lib_test.cmx b/src/identity/tests/account_manager_integration/meta/account_manager_integration_lib_test.cmx
index 7064183..66ef6c8 100644
--- a/src/identity/tests/account_manager_integration/meta/account_manager_integration_lib_test.cmx
+++ b/src/identity/tests/account_manager_integration/meta/account_manager_integration_lib_test.cmx
@@ -1,21 +1,12 @@
{
- "facets": {
- "fuchsia.test": {
- "injected-services": {
- "fuchsia.auth.account.AccountManager": [
- "fuchsia-pkg://fuchsia.com/account_manager#meta/account_manager.cmx",
- "--dev-auth-providers"
- ]
- }
- }
- },
"program": {
"binary": "test/account_manager_integration_lib_test"
},
"sandbox": {
"services": [
"fuchsia.logger.LogSink",
- "fuchsia.auth.account.AccountManager"
+ "fuchsia.sys.Environment",
+ "fuchsia.sys.Loader"
]
}
}
diff --git a/src/identity/tests/account_manager_integration/tests/account.rs b/src/identity/tests/account_manager_integration/tests/account.rs
index 73e657c..9a9aa9f 100644
--- a/src/identity/tests/account_manager_integration/tests/account.rs
+++ b/src/identity/tests/account_manager_integration/tests/account.rs
@@ -10,8 +10,23 @@
use fidl_fuchsia_auth_account::{
AccountManagerMarker, AccountManagerProxy, LocalAccountId, Status,
};
+use fuchsia_async as fasync;
+use fuchsia_component::client::{launch, App};
+use fuchsia_component::fuchsia_single_component_package_url;
+use fuchsia_component::server::{NestedEnvironment, ServiceFs};
use futures::future::join;
use futures::prelude::*;
+use lazy_static::lazy_static;
+use std::ops::Deref;
+
+lazy_static! {
+ /// URL for account manager.
+ static ref ACCOUNT_MANAGER_URL: String =
+ String::from(fuchsia_single_component_package_url!("account_manager"));
+
+ /// Arguments passed to account manager started in test environment.
+ static ref ACCOUNT_MANAGER_ARGS: Vec<String> = vec![String::from("--dev-auth-providers")];
+}
/// Calls provision_new_account on the supplied account_manager, returning an error on any
/// non-OK responses, or the account ID on success.
@@ -57,19 +72,98 @@
}
}
+/// A proxy to an account manager running in a nested environment.
+struct NestedAccountManagerProxy {
+ /// Proxy to account manager.
+ account_manager_proxy: AccountManagerProxy,
+
+ /// Application object for account manager. Needs to be kept in scope to
+ /// keep the nested environment alive.
+ _app: App,
+
+ /// The nested environment account manager is running in. Needs to be kept
+ /// in scope to keep the nested environment alive.
+ _nested_envronment: NestedEnvironment,
+}
+
+impl Deref for NestedAccountManagerProxy {
+ type Target = AccountManagerProxy;
+
+ fn deref(&self) -> &AccountManagerProxy {
+ &self.account_manager_proxy
+ }
+}
+
+/// Start account manager in an isolated environment and return a proxy to it.
+fn create_account_manager() -> Result<NestedAccountManagerProxy, Error> {
+ let mut service_fs = ServiceFs::new();
+
+ // Use a salted environment name to ensure the environment is unique across
+ // calls.
+ let nested_environment = service_fs.create_salted_nested_environment("account_test_env")?;
+
+ let app = launch(
+ nested_environment.launcher(),
+ ACCOUNT_MANAGER_URL.clone(),
+ Some(ACCOUNT_MANAGER_ARGS.clone()),
+ )?;
+ fasync::spawn(service_fs.collect());
+ let account_manager_proxy = app.connect_to_service::<AccountManagerMarker>()?;
+
+ Ok(NestedAccountManagerProxy {
+ account_manager_proxy,
+ _app: app,
+ _nested_envronment: nested_environment,
+ })
+}
+
// TODO(jsankey): Work with ComponentFramework and cramertj@ to develop a nice Rust equivalent of
-// the C++ TestWithEnvironment fixture to provide isolated environments for each test case. For now
-// we verify all functionality in a single test case.
+// the C++ TestWithEnvironment fixture to provide isolated environments for each test case. We
+// are currently creating a new environment for account manager to run in, but the tests
+// themselves run in a single environment.
#[fuchsia_async::run_singlethreaded(test)]
-async fn test_account_functionality() -> Result<(), Error> {
- let account_manager = fuchsia_component::client::connect_to_service::<AccountManagerMarker>()
- .expect("Failed to connect to account manager service");
+async fn test_provision_new_account() -> Result<(), Error> {
+ let account_manager =
+ create_account_manager().expect("Failed to launch account manager in nested environment.");
// Verify we initially have no accounts.
assert_eq!(await!(account_manager.get_account_ids())?, vec![]);
// Provision a new account.
- let mut account_1 = await!(provision_new_account(&account_manager))?;
+ let account_1 = await!(provision_new_account(&account_manager))?;
+ assert_eq!(
+ await!(account_manager.get_account_ids())?,
+ vec![LocalAccountId { id: account_1.id }]
+ );
+
+ // Provision a second new account and verify it has a different ID.
+ let account_2 = await!(provision_new_account(&account_manager))?;
+ assert_ne!(account_1.id, account_2.id);
+
+ let account_ids = await!(account_manager.get_account_ids())?;
+ assert_eq!(account_ids.len(), 2);
+ assert!(account_ids.contains(&account_1));
+ assert!(account_ids.contains(&account_2));
+
+ // Auth state should be unknown for the new accounts
+ let (_, auth_states) = await!(account_manager.get_account_auth_states())?;
+ assert_eq!(auth_states.len(), 2);
+ assert!(auth_states.iter().all(|state| state.auth_state.summary == AuthStateSummary::Unknown
+ && account_ids.contains(&state.account_id)));
+
+ Ok(())
+}
+
+#[fuchsia_async::run_singlethreaded(test)]
+async fn test_provision_new_account_from_auth_provider() -> Result<(), Error> {
+ let account_manager =
+ create_account_manager().expect("Failed to launch account manager in nested environment.");
+
+ // Verify we initially have no accounts.
+ assert_eq!(await!(account_manager.get_account_ids())?, vec![]);
+
+ // Provision a new account.
+ let account_1 = await!(provision_account_from_dev_auth_provider(&account_manager))?;
assert_eq!(
await!(account_manager.get_account_ids())?,
vec![LocalAccountId { id: account_1.id }]
@@ -79,11 +173,33 @@
let account_2 = await!(provision_account_from_dev_auth_provider(&account_manager))?;
assert_ne!(account_1.id, account_2.id);
- // Connect a channel to one of these accounts and verify it's usable.
+ let account_ids = await!(account_manager.get_account_ids())?;
+ assert_eq!(account_ids.len(), 2);
+ assert!(account_ids.contains(&account_1));
+ assert!(account_ids.contains(&account_2));
+
+ // Auth state should be unknown for the new accounts
+ let (_, auth_states) = await!(account_manager.get_account_auth_states())?;
+ assert_eq!(auth_states.len(), 2);
+ assert!(auth_states.iter().all(|state| state.auth_state.summary == AuthStateSummary::Unknown
+ && account_ids.contains(&state.account_id)));
+
+ Ok(())
+}
+
+#[fuchsia_async::run_singlethreaded(test)]
+async fn test_get_account_and_persona() -> Result<(), Error> {
+ let account_manager =
+ create_account_manager().expect("Failed to launch account manager in nested environment.");
+
+ assert_eq!(await!(account_manager.get_account_ids())?, vec![]);
+
+ let mut account = await!(provision_new_account(&account_manager))?;
+ // Connect a channel to the newly created account and verify it's usable.
let (acp_client_end, _) = create_endpoints()?;
let (account_client_end, account_server_end) = create_endpoints()?;
assert_eq!(
- await!(account_manager.get_account(&mut account_1, acp_client_end, account_server_end))?,
+ await!(account_manager.get_account(&mut account, acp_client_end, account_server_end))?,
Status::Ok
);
let account_proxy = account_client_end.into_proxy()?;
@@ -103,13 +219,36 @@
};
assert_eq!(persona_auth_state.summary, AuthStateSummary::Unknown);
+ Ok(())
+}
+
+#[fuchsia_async::run_singlethreaded(test)]
+async fn test_account_deletion() -> Result<(), Error> {
+ let account_manager =
+ create_account_manager().expect("Failed to launch account manager in nested environment.");
+
+ assert_eq!(await!(account_manager.get_account_ids())?, vec![]);
+
+ let mut account_1 = await!(provision_new_account(&account_manager))?;
+ let account_2 = await!(provision_new_account(&account_manager))?;
+ let existing_accounts = await!(account_manager.get_account_ids())?;
+ assert!(existing_accounts.contains(&LocalAccountId { id: account_1.id }));
+ assert!(existing_accounts.contains(&LocalAccountId { id: account_2.id }));
+ assert_eq!(existing_accounts.len(), 2);
+
// Delete an account and verify it is removed.
assert_eq!(await!(account_manager.remove_account(&mut account_1))?, Status::Ok);
assert_eq!(
await!(account_manager.get_account_ids())?,
vec![LocalAccountId { id: account_2.id }]
);
- // Deliberately leave an account as dirty state which will cause assert errors upon storage
- // isolation violations across invocations of this test. No state should be preserved.
+ // Connecting to the deleted account should fail.
+ let (acp_client_end, _acp_server_end) = create_endpoints()?;
+ let (_account_client_end, account_server_end) = create_endpoints()?;
+ assert_eq!(
+ await!(account_manager.get_account(&mut account_1, acp_client_end, account_server_end))?,
+ Status::NotFound
+ );
+
Ok(())
}