65 lines
2.3 KiB
C#
65 lines
2.3 KiB
C#
using System;
|
|
using Shouldly;
|
|
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Stability;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Tests;
|
|
|
|
[Trait("Category", "Unit")]
|
|
public sealed class MemoryWatchdogTests
|
|
{
|
|
private const long Mb = 1024 * 1024;
|
|
|
|
[Fact]
|
|
public void Baseline_sample_returns_None()
|
|
{
|
|
var w = new MemoryWatchdog(baselineBytes: 300 * Mb);
|
|
w.Sample(320 * Mb, DateTime.UtcNow).ShouldBe(WatchdogAction.None);
|
|
}
|
|
|
|
[Fact]
|
|
public void Warn_threshold_uses_larger_of_1_5x_or_plus_200MB()
|
|
{
|
|
// Baseline 300 → warn threshold = max(450, 500) = 500 MB
|
|
var w = new MemoryWatchdog(baselineBytes: 300 * Mb);
|
|
w.Sample(499 * Mb, DateTime.UtcNow).ShouldBe(WatchdogAction.None);
|
|
w.Sample(500 * Mb, DateTime.UtcNow).ShouldBe(WatchdogAction.Warn);
|
|
}
|
|
|
|
[Fact]
|
|
public void Soft_recycle_triggers_at_2x_or_plus_200MB_whichever_larger()
|
|
{
|
|
// Baseline 400 → soft = max(800, 600) = 800 MB
|
|
var w = new MemoryWatchdog(baselineBytes: 400 * Mb);
|
|
w.Sample(799 * Mb, DateTime.UtcNow).ShouldBe(WatchdogAction.Warn);
|
|
w.Sample(800 * Mb, DateTime.UtcNow).ShouldBe(WatchdogAction.SoftRecycle);
|
|
}
|
|
|
|
[Fact]
|
|
public void Hard_kill_triggers_at_absolute_ceiling()
|
|
{
|
|
var w = new MemoryWatchdog(baselineBytes: 1000 * Mb);
|
|
w.Sample(1501 * Mb, DateTime.UtcNow).ShouldBe(WatchdogAction.HardKill);
|
|
}
|
|
|
|
[Fact]
|
|
public void Sustained_slope_triggers_soft_recycle_before_absolute_threshold()
|
|
{
|
|
// Baseline 1000 MB → warn = 1200, soft = 2000 (absolute). Slope 6 MB/min over 30 min = 180 MB
|
|
// delta — still well below the absolute soft threshold; slope detector must fire on its own.
|
|
var w = new MemoryWatchdog(baselineBytes: 1000 * Mb) { SustainedSlopeBytesPerMinute = 5 * Mb };
|
|
var t0 = new DateTime(2026, 4, 17, 12, 0, 0, DateTimeKind.Utc);
|
|
|
|
long rss = 1050 * Mb;
|
|
var slopeFired = false;
|
|
for (var i = 0; i <= 35; i++)
|
|
{
|
|
var action = w.Sample(rss, t0.AddMinutes(i));
|
|
if (action == WatchdogAction.SoftRecycle) { slopeFired = true; break; }
|
|
rss += 6 * Mb;
|
|
}
|
|
|
|
slopeFired.ShouldBeTrue("slope detector should fire once the 30-min window fills");
|
|
}
|
|
}
|