Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions crates/apollo_deployments/src/deployment_definitions_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::jsonnet_test::{
assert_build_deserializes,
assert_infra_matches_rust,
test_applicative_matches_app_configs,
test_generator_flat_input_matches_direct_build,
test_keys_to_be_replaced_are_covered_by_override_schema,
};
use crate::service::NodeType;
Expand Down Expand Up @@ -103,6 +104,15 @@ fn build_distributed_deserializes_into_node_config() {
assert_build_deserializes::<DistributedNodeServiceName>();
}

/// Verifies the generator's flat-input path reproduces building directly from the nested overrides.
#[test]
fn generator_flat_input_matches_direct_build() {
env::set_current_dir(resolve_project_relative_path("").unwrap())
.expect("Couldn't set working dir.");

test_generator_flat_input_matches_direct_build();
}

/// Test that the deployment file is up to date.
#[test]
fn deployment_files_are_up_to_date() {
Expand Down
38 changes: 38 additions & 0 deletions crates/apollo_deployments/src/jsonnet_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use strum::IntoEnumIterator;
use crate::deployment_definitions::BASE_APP_CONFIGS_DIR_PATH;
use crate::jsonnet_generation::{
eval_build_with_expr,
eval_build_with_overrides,
eval_overrides_file,
jsonnet_state,
overrides_from_sequencer_config,
};
Expand Down Expand Up @@ -88,6 +90,42 @@ fn eval_test_build(layout: &str) -> Value {
eval_build_with_expr(layout, "import 'testing/overrides.libsonnet'")
}

/// Flattens a nested JSON object into a map from dot-separated leaf path to value. Non-empty
/// objects recurse; scalars, arrays, nulls, and empty objects are leaves (the inverse of the
/// generator's nesting, so the round-trip below is well-defined).
fn flatten(value: &Value, prefix: &str, out: &mut BTreeMap<String, Value>) {
match value {
Value::Object(map) if !map.is_empty() => {
for (key, child) in map {
let path = if prefix.is_empty() { key.clone() } else { format!("{prefix}.{key}") };
flatten(child, &path, out);
}
}
leaf => {
out.insert(prefix.to_owned(), leaf.clone());
}
}
}

/// The generator's flat-input path — flatten the nested overrides, run them back through
/// `overrides_from_sequencer_config`, and `build` — reproduces building directly from the nested
/// fixture, over a complete (59-key) override set. (`testing/overrides.libsonnet` encodes `None` as
/// `null`, not the `#is_none` marker; that folding is covered by the mapping's own unit tests.)
pub fn test_generator_flat_input_matches_direct_build() {
let nested = eval_overrides_file("testing/overrides.libsonnet");
let mut flat = BTreeMap::new();
flatten(&nested, "", &mut flat);

// The mapping inverts the flattening.
assert_eq!(overrides_from_sequencer_config(&flat), nested);

// ...so the generator yields the same per-service config as building from the fixture directly.
assert_eq!(
eval_build_with_overrides("hybrid", &overrides_from_sequencer_config(&flat)),
eval_test_build("hybrid"),
);
}

/// Asserts the applicative config emitted by jsonnet reproduces the committed `app_configs/*.json`
/// — the deployment's non-overridable value layer (loaded on top of `config_schema.json` at deploy)
/// — for every key those files define. Excludes keys that are overridable, secret, or under
Expand Down