Skip to content
Open
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
63 changes: 63 additions & 0 deletions src/Cli.Tests/ValidateConfigTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,69 @@ public void TestChildWithEntitiesAndAutoentitiesResolvingZeroLogsNamedWarning()
VerifyAutoentityZeroDiscoveredWarning(loggerMock, expectedFileNameInMessage: "child-db.json");
}

/// <summary>
/// Child config with only autoentities that resolve to greater than 0 entities is valid.
/// Simulates the production code path where the metadata provider stores resolution
/// counts on the root (merged) config rather than on the child config directly.
/// </summary>
[TestMethod]
public void TestChildWithDataSourceAndAutoentitiesResolvingEntitiesIsValid()
{
// Child has no explicit entities; only autoentities.
RuntimeConfig childConfig = BuildTestConfig(
hasDataSource: true,
entities: new(),
autoentities: new() { { "ae1", BuildSimpleAutoentity() } });
childConfig.IsChildConfig = true;

RuntimeConfig rootConfig = BuildTestConfig(
hasDataSource: false, entities: new(),
dataSourceFiles: new DataSourceFiles(new[] { "child-db.json" }));
rootConfig.ChildConfigs.Add(("child-db.json", childConfig));

// Simulate production: metadata provider stores counts in the root config,
// NOT directly on the child config.
rootConfig.AutoentityResolutionCounts["ae1"] = 3;

RuntimeConfigValidator validator = BuildValidator(rootConfig);
validator.ValidateDataSourceAndEntityPresence(rootConfig);

Assert.AreEqual(0, validator.ConfigValidationExceptions.Count,
"Child config with autoentities that resolved entities should pass validation.");
}

/// <summary>
/// Both root and child configs have autoentities that resolve to >0 entities.
/// Resolution counts for both are stored only on the root config (as the metadata
/// provider does at runtime). Validation must pass for both configs.
/// </summary>
[TestMethod]
public void TestRootAndChildBothWithAutoentitiesResolvingEntitiesIsValid()
{
RuntimeConfig childConfig = BuildTestConfig(
hasDataSource: true,
entities: new(),
autoentities: new() { { "child-ae", BuildSimpleAutoentity() } });
childConfig.IsChildConfig = true;

RuntimeConfig rootConfig = BuildTestConfig(
hasDataSource: true,
entities: new(),
dataSourceFiles: new DataSourceFiles(new[] { "child-db.json" }),
autoentities: new() { { "root-ae", BuildSimpleAutoentity() } });
rootConfig.ChildConfigs.Add(("child-db.json", childConfig));

// Simulate production: metadata provider stores ALL counts in the root config.
rootConfig.AutoentityResolutionCounts["root-ae"] = 2;
rootConfig.AutoentityResolutionCounts["child-ae"] = 4;

RuntimeConfigValidator validator = BuildValidator(rootConfig);
validator.ValidateDataSourceAndEntityPresence(rootConfig);

Assert.AreEqual(0, validator.ConfigValidationExceptions.Count,
"Root and child configs both with autoentities that resolved entities should pass validation.");
}

/// <summary>
/// Helper: verifies that the autoentity-discovered-zero warning was logged at least once,
/// optionally also checking that the formatted message contains a child config file name.
Expand Down
11 changes: 11 additions & 0 deletions src/Core/Configurations/RuntimeConfigValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,17 @@ private void ValidateRootConfig(RuntimeConfig runtimeConfig)
// Validate each child config independently.
foreach ((string fileName, RuntimeConfig childConfig) in runtimeConfig.ChildConfigs)
{
// The metadata provider stores autoentity resolution counts on the root config.
// Copy those counts to the child config so per-child validation can find them
foreach (KeyValuePair<string, Autoentity> ae in childConfig.Autoentities)
{
if (!childConfig.AutoentityResolutionCounts.ContainsKey(ae.Key)
&& runtimeConfig.AutoentityResolutionCounts.TryGetValue(ae.Key, out int count))
{
childConfig.AutoentityResolutionCounts[ae.Key] = count;
}
}

ValidateNonRootConfig(childConfig, configName: fileName);
}
}
Expand Down
Loading