test(dv-3): add 4-level roll-up + deep-leaf filter tests; return AsReadOnly; add caller-contract remark
Fix 1 (Important): RollUp_FourLevelDeepBadQuality_ReachesRoot — proves bad quality at a 4-segment-deep leaf propagates HasBadQuality up every ancestor to the root. Fix 2 (Important): Filter_DeepLeafMatch_RetainsAllAncestorBranches — proves filtering on a terminal segment of a 3-level path retains all ancestor branches. Fix 3 (Minor): BuildAttributeTree now returns roots.AsReadOnly() so the returned IReadOnlyList<DebugTreeNode> reference is not a mutable list. Fix 4 (Minor): Added <remarks> XML doc to BuildAttributeTree noting the caller-contract that at most one AttributeValueChanged per AttributeName should be passed. All 18 DebugTreeBuilder tests pass.
This commit is contained in:
@@ -21,6 +21,13 @@ public static class DebugTreeBuilder
|
||||
/// <see cref="AttributeValueChanged.AttributeName"/>). Null/empty/whitespace
|
||||
/// keeps everything; matching leaves carry along their ancestor branches.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// The caller is expected to pass at most one <see cref="AttributeValueChanged"/>
|
||||
/// per <see cref="AttributeValueChanged.AttributeName"/>. The DebugView page
|
||||
/// enforces this by keying a dictionary on the attribute name before calling this
|
||||
/// method. Passing duplicate names would produce sibling leaves with identical
|
||||
/// keys under the same parent branch.
|
||||
/// </remarks>
|
||||
public static IReadOnlyList<DebugTreeNode> BuildAttributeTree(
|
||||
IEnumerable<AttributeValueChanged> attributes, string? filter)
|
||||
{
|
||||
@@ -71,7 +78,7 @@ public static class DebugTreeBuilder
|
||||
}
|
||||
|
||||
SortAndRollUp(roots);
|
||||
return roots;
|
||||
return roots.AsReadOnly();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -203,4 +203,33 @@ public class DebugTreeBuilderTests
|
||||
var tree = DebugTreeBuilder.BuildAttributeTree(Array.Empty<AttributeValueChanged>(), null);
|
||||
Assert.Empty(tree);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RollUp_FourLevelDeepBadQuality_ReachesRoot()
|
||||
{
|
||||
var tree = DebugTreeBuilder.BuildAttributeTree(
|
||||
new[] { Attr("A.B.C.D", quality: "Bad") }, null);
|
||||
|
||||
var a = Assert.Single(tree);
|
||||
Assert.True(a.HasBadQuality);
|
||||
var b = Assert.Single(a.Children);
|
||||
Assert.True(b.HasBadQuality);
|
||||
var c = Assert.Single(b.Children);
|
||||
Assert.True(c.HasBadQuality);
|
||||
var d = Assert.Single(c.Children);
|
||||
Assert.True(d.HasBadQuality);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Filter_DeepLeafMatch_RetainsAllAncestorBranches()
|
||||
{
|
||||
var tree = DebugTreeBuilder.BuildAttributeTree(
|
||||
new[] { Attr("Motor1.Compressor.Pump"), Attr("Motor1.Speed") }, "Pump");
|
||||
|
||||
var motor = Assert.Single(tree);
|
||||
Assert.Equal("Motor1", motor.Key);
|
||||
var compressor = Assert.Single(motor.Children);
|
||||
Assert.Equal("Motor1.Compressor", compressor.Key);
|
||||
Assert.Equal("Motor1.Compressor.Pump", Assert.Single(compressor.Children).Key);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user