Files
mxaccessgw/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardGalaxySummaryProjectorTests.cs
T

149 lines
6.0 KiB
C#

using ZB.MOM.WW.GalaxyRepository;
using ZB.MOM.WW.GalaxyRepository.Grpc;
using ZB.MOM.WW.MxGateway.Server.Dashboard;
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
/// <summary>
/// Unit tests for <see cref="DashboardGalaxySummaryProjector"/>, the host-side
/// projection that turns a shared-library <see cref="GalaxyHierarchyCacheEntry"/>
/// into the dashboard's <see cref="DashboardGalaxySummary"/>.
/// </summary>
public sealed class DashboardGalaxySummaryProjectorTests
{
/// <summary>
/// Verifies that a healthy entry maps status, copies timestamps/counts, and
/// groups objects into template usage (ordered by instance count) and
/// category counts with resolved names.
/// </summary>
[Fact]
public void Project_HealthyEntry_MapsStatusCopiesCountsAndGroupsObjects()
{
DateTimeOffset queriedAt = new(2026, 6, 25, 10, 0, 0, TimeSpan.Zero);
DateTimeOffset successAt = new(2026, 6, 25, 10, 0, 1, TimeSpan.Zero);
DateTimeOffset deployAt = new(2026, 6, 24, 8, 30, 0, TimeSpan.Zero);
// Two templates (PumpTemplate x2, ValveTemplate x1) and two categories
// (10 = UserDefined x3, 13 = Area x1).
GalaxyObject area = new()
{
GobjectId = 1,
BrowseName = "AreaA",
IsArea = true,
CategoryId = 13,
};
GalaxyObject pumpA = new()
{
GobjectId = 2,
BrowseName = "Pump01",
CategoryId = 10,
};
pumpA.TemplateChain.Add("$PumpTemplate");
GalaxyObject pumpB = new()
{
GobjectId = 3,
BrowseName = "Pump02",
CategoryId = 10,
};
pumpB.TemplateChain.Add("$PumpTemplate");
GalaxyObject valve = new()
{
GobjectId = 4,
BrowseName = "Valve01",
CategoryId = 10,
};
valve.TemplateChain.Add("$ValveTemplate");
GalaxyObject[] objects = [area, pumpA, pumpB, valve];
GalaxyHierarchyCacheEntry entry = new(
Status: GalaxyCacheStatus.Healthy,
Sequence: 7,
LastQueriedAt: queriedAt,
LastSuccessAt: successAt,
LastDeployTime: deployAt,
LastError: null,
Objects: objects,
Index: GalaxyHierarchyIndex.Build(objects),
ObjectCount: 4,
AreaCount: 1,
AttributeCount: 12,
HistorizedAttributeCount: 5,
AlarmAttributeCount: 2);
DashboardGalaxySummary summary = DashboardGalaxySummaryProjector.Project(entry);
Assert.Equal(DashboardGalaxyStatus.Healthy, summary.Status);
Assert.Equal(queriedAt, summary.LastQueriedAt);
Assert.Equal(successAt, summary.LastSuccessAt);
Assert.Equal(deployAt, summary.LastDeployTime);
Assert.Null(summary.LastError);
Assert.Equal(4, summary.ObjectCount);
Assert.Equal(1, summary.AreaCount);
Assert.Equal(12, summary.AttributeCount);
Assert.Equal(5, summary.HistorizedAttributeCount);
Assert.Equal(2, summary.AlarmAttributeCount);
// Templates ordered by instance count descending: PumpTemplate (2) before ValveTemplate (1).
Assert.Equal(2, summary.TopTemplates.Count);
Assert.Equal("$PumpTemplate", summary.TopTemplates[0].TemplateName);
Assert.Equal(2, summary.TopTemplates[0].InstanceCount);
Assert.Equal("$ValveTemplate", summary.TopTemplates[1].TemplateName);
Assert.Equal(1, summary.TopTemplates[1].InstanceCount);
// Categories ordered by object count descending: UserDefined (3) before Area (1).
Assert.Equal(2, summary.ObjectCategories.Count);
Assert.Equal(10, summary.ObjectCategories[0].CategoryId);
Assert.Equal("UserDefined", summary.ObjectCategories[0].CategoryName);
Assert.Equal(3, summary.ObjectCategories[0].ObjectCount);
Assert.Equal(13, summary.ObjectCategories[1].CategoryId);
Assert.Equal("Area", summary.ObjectCategories[1].CategoryName);
Assert.Equal(1, summary.ObjectCategories[1].ObjectCount);
}
/// <summary>
/// Verifies that an unknown entry with no objects projects to the
/// <see cref="DashboardGalaxySummary.Unknown"/>-equivalent summary.
/// </summary>
[Fact]
public void Project_UnknownEmptyEntry_ProducesUnknownEquivalentSummary()
{
GalaxyHierarchyCacheEntry entry = GalaxyHierarchyCacheEntry.Empty;
DashboardGalaxySummary summary = DashboardGalaxySummaryProjector.Project(entry);
Assert.Equal(DashboardGalaxyStatus.Unknown, summary.Status);
Assert.Null(summary.LastQueriedAt);
Assert.Null(summary.LastSuccessAt);
Assert.Null(summary.LastDeployTime);
Assert.Null(summary.LastError);
Assert.Equal(0, summary.ObjectCount);
Assert.Equal(0, summary.AreaCount);
Assert.Equal(0, summary.AttributeCount);
Assert.Equal(0, summary.HistorizedAttributeCount);
Assert.Equal(0, summary.AlarmAttributeCount);
Assert.Empty(summary.TopTemplates);
Assert.Empty(summary.ObjectCategories);
}
/// <summary>
/// Verifies that the cache status enum is faithfully mapped to the dashboard
/// status enum across every defined value.
/// </summary>
[Theory]
[InlineData(GalaxyCacheStatus.Healthy, DashboardGalaxyStatus.Healthy)]
[InlineData(GalaxyCacheStatus.Stale, DashboardGalaxyStatus.Stale)]
[InlineData(GalaxyCacheStatus.Unavailable, DashboardGalaxyStatus.Unavailable)]
[InlineData(GalaxyCacheStatus.Unknown, DashboardGalaxyStatus.Unknown)]
public void Project_MapsCacheStatusToDashboardStatus(
GalaxyCacheStatus cacheStatus,
DashboardGalaxyStatus expected)
{
GalaxyHierarchyCacheEntry entry = GalaxyHierarchyCacheEntry.Empty with { Status = cacheStatus };
DashboardGalaxySummary summary = DashboardGalaxySummaryProjector.Project(entry);
Assert.Equal(expected, summary.Status);
}
}