use std::collections::BTreeMap;
use super::harness::{Journal, caller, one_tenant_state, other};
use crate::config::{Config, Namespace};
use crate::convergence::compile::RevisionProjection;
use crate::convergence::tenancy::TenancyProjection;
use crate::desired_state::{DesiredState, fixtures};
fn namespaces(config: &Config) -> BTreeMap<&str, &Namespace> {
config
.namespace
.iter()
.map(|namespace| (namespace.id.as_str(), namespace))
.collect()
}
fn project(state: &DesiredState) -> Config {
let config = TenancyProjection
.project(
&crate::convergence::compile::testing::bootstrap(),
state,
fixtures::revision_id(1),
)
.expect("two tenants project onto one deployment");
config
.validate_compiled()
.expect("a projected config passes the gate a boot passes");
config
}
#[tokio::test]
async fn each_tenants_project_is_its_own_namespace_and_borrows_nothing() {
let Some(journal) = Journal::open().await else {
return;
};
journal.publish_two_tenants().await;
let revision = journal.hydrated().await;
let config = project(revision.state());
let namespaces = namespaces(&config);
assert_eq!(
namespaces.keys().copied().collect::<Vec<_>>(),
vec!["acme/core", "globex/core", "platform"],
"two tenants' projects did not become two distinct namespaces"
);
for (id, tenant, project) in [
("acme/core", caller(), fixtures::project_id(2)),
("globex/core", other(), fixtures::project_id(12)),
] {
let namespace = namespaces[id];
let identity = namespace
.project
.as_ref()
.expect("a projected namespace carries the durable object it is");
assert_eq!(identity.tenant, tenant, "{id} is owned by the wrong tenant");
assert_eq!(identity.project, project, "{id} is the wrong project");
assert!(
!namespace.allow_platform_fallback,
"{id} may borrow the platform's credentials without being told to"
);
assert!(
!namespace.default,
"{id} was promoted to the deployment default"
);
}
assert!(namespaces["platform"].default);
assert!(namespaces["platform"].project.is_none());
}
#[tokio::test]
async fn a_neighbour_changes_nothing_about_a_tenants_own_namespace() {
let Some(journal) = Journal::open().await else {
return;
};
journal.publish_two_tenants().await;
let together = project(journal.hydrated().await.state());
let alone = project(&one_tenant_state());
assert_eq!(
namespaces(&alone).keys().copied().collect::<Vec<_>>(),
vec!["acme/core", "platform"],
"the single-tenant projection is not the comparison it is meant to be"
);
assert_eq!(
format!("{:?}", namespaces(&alone)["acme/core"]),
format!("{:?}", namespaces(&together)["acme/core"]),
"a second tenant changed what the first tenant's namespace is"
);
}