use ito_config::types::{CoordinationStorage, ItoConfig};
use super::{
CapabilityPreflight, CompiledCapabilities, CompiledFeature, preflight_config,
preflight_config_with_capabilities,
};
use crate::errors::CoreError;
#[test]
fn reports_the_compiled_feature_set() {
let capabilities = CompiledCapabilities::current();
assert_eq!(capabilities.backend, cfg!(feature = "backend"));
assert_eq!(
capabilities.coordination_branch,
cfg!(feature = "coordination-branch")
);
assert_eq!(
capabilities.contains(CompiledFeature::Backend),
cfg!(feature = "backend")
);
}
#[test]
fn main_compatible_defaults_need_no_experimental_capability() {
let config = ItoConfig::default();
assert!(!config.backend.enabled);
assert!(!config.changes.coordination_branch.enabled.0);
assert_eq!(
config.changes.coordination_branch.storage,
CoordinationStorage::Embedded
);
preflight_config(&config, CapabilityPreflight::Stateful)
.expect("default configuration must work in the shipping binary");
}
#[test]
fn backend_config_is_rejected_or_accepted_by_compiled_capability() {
let mut config = ItoConfig::default();
config.backend.enabled = true;
let result = preflight_config(&config, CapabilityPreflight::Stateful);
if cfg!(feature = "backend") {
result.expect("backend-enabled builds should accept backend config");
} else {
assert_feature_error(
result.unwrap_err(),
CompiledFeature::Backend,
"backend.enabled",
);
}
}
#[test]
fn worktree_coordination_is_rejected_or_accepted_by_compiled_capability() {
let mut config = ItoConfig::default();
config.backend.enabled = false;
config.changes.coordination_branch.enabled.0 = true;
config.changes.coordination_branch.storage = CoordinationStorage::Worktree;
let result = preflight_config(&config, CapabilityPreflight::Stateful);
if cfg!(feature = "coordination-branch") {
result.expect("coordination-enabled builds should accept worktree storage");
} else {
assert_feature_error(
result.unwrap_err(),
CompiledFeature::CoordinationBranch,
"changes.coordination_branch.enabled",
);
}
}
#[test]
fn either_legacy_coordination_signal_requests_the_feature() {
for (enabled, storage, requested_by) in [
(
true,
CoordinationStorage::Embedded,
"changes.coordination_branch.enabled",
),
(
false,
CoordinationStorage::Worktree,
"changes.coordination_branch.storage=worktree",
),
] {
let mut config = ItoConfig::default();
config.backend.enabled = false;
config.changes.coordination_branch.enabled.0 = enabled;
config.changes.coordination_branch.storage = storage;
let result = preflight_config(&config, CapabilityPreflight::Stateful);
if cfg!(feature = "coordination-branch") {
result.expect("coordination-enabled builds should accept legacy config");
} else {
assert_feature_error(
result.unwrap_err(),
CompiledFeature::CoordinationBranch,
requested_by,
);
}
}
}
#[test]
fn recovery_preflight_remains_available_for_legacy_config() {
let mut config = ItoConfig::default();
config.backend.enabled = true;
config.changes.coordination_branch.enabled.0 = true;
config.changes.coordination_branch.storage = CoordinationStorage::Worktree;
preflight_config(&config, CapabilityPreflight::Recovery)
.expect("recovery commands must remain available");
}
#[test]
fn caller_capabilities_override_dependency_feature_unification() {
let mut config = ItoConfig::default();
config.backend.enabled = true;
let error = preflight_config_with_capabilities(
&config,
CapabilityPreflight::Stateful,
CompiledCapabilities {
backend: false,
coordination_branch: false,
},
)
.unwrap_err();
assert_feature_error(error, CompiledFeature::Backend, "backend.enabled");
config.backend.enabled = false;
config.changes.coordination_branch.storage = CoordinationStorage::Worktree;
let error = preflight_config_with_capabilities(
&config,
CapabilityPreflight::Stateful,
CompiledCapabilities {
backend: false,
coordination_branch: false,
},
)
.unwrap_err();
assert_feature_error(
error,
CompiledFeature::CoordinationBranch,
"changes.coordination_branch.storage=worktree",
);
}
fn assert_feature_error(error: CoreError, feature: CompiledFeature, requested_by: &str) {
let CoreError::FeatureUnavailable {
feature: actual,
requested_by: actual_request,
recovery,
} = error
else {
panic!("expected FeatureUnavailable, got {error:?}");
};
assert_eq!(actual, feature);
assert_eq!(actual_request, requested_by);
assert!(!recovery.is_empty());
}