114 lines
4.5 KiB
C#
114 lines
4.5 KiB
C#
using Fleet.Core;
|
|
using Microsoft.Extensions.Time.Testing;
|
|
using MoShiro.Protocol;
|
|
|
|
namespace MoShiro.Measurement.Tests;
|
|
|
|
public sealed class RestartUpdaterTests
|
|
{
|
|
private readonly List<string> _restarts = [];
|
|
|
|
private RestartUpdater Create(string tag = "dev-aaa", string commit = "aaa", long builtAt = 1_000) =>
|
|
new("agent", _restarts.Add, TimeProvider.System, NullNodeLog.Instance, tag, commit, builtAt);
|
|
|
|
private static UpdateOfferParams Offer(string tag, long seq, string component = "agent", string commit = "bbb") =>
|
|
new() { Manifest = $"{{\"component\":\"{component}\",\"tag\":\"{tag}\",\"version\":\"0.4.0\",\"commit\":\"{commit}\",\"digest\":\"sha256:{new string('a', 64)}\",\"seq\":{seq}}}", Signature = "ignored" };
|
|
|
|
[Fact]
|
|
public void ANewerRelease_IsAvailable_AndOnlyARequestRestartsTheNode()
|
|
{
|
|
RestartUpdater updater = Create();
|
|
updater.Offer(Offer("dev-bbb", 2_000));
|
|
UpdateStatus status = updater.Status();
|
|
Assert.Equal("available", status.State);
|
|
Assert.Equal("dev-bbb", status.Available!.Tag);
|
|
Assert.Equal(2_000, status.Available.Seq);
|
|
Assert.Empty(_restarts);
|
|
|
|
Assert.True(updater.RequestApply());
|
|
Assert.Equal(["update"], _restarts);
|
|
Assert.Equal("applying", updater.Status().State);
|
|
}
|
|
|
|
[Fact]
|
|
public void TheReleaseThatIsAlreadyRunning_IsUpToDate_ByTagOrByCommit()
|
|
{
|
|
RestartUpdater updater = Create();
|
|
updater.Offer(Offer("dev-aaa", 2_000));
|
|
Assert.Equal("up_to_date", updater.Status().State);
|
|
updater.Offer(Offer("dev-other-tag", 2_000, commit: "aaa"));
|
|
Assert.Equal("up_to_date", updater.Status().State);
|
|
Assert.False(updater.RequestApply());
|
|
Assert.Empty(_restarts);
|
|
}
|
|
|
|
[Fact]
|
|
public void AnOfferOlderThanThisBuild_OrForAnotherComponent_IsNotAnUpdate()
|
|
{
|
|
RestartUpdater updater = Create(builtAt: 5_000);
|
|
updater.Offer(Offer("dev-bbb", 2_000));
|
|
Assert.Equal("up_to_date", updater.Status().State);
|
|
updater.Offer(Offer("dev-ccc", 9_000, component: "probe"));
|
|
Assert.Equal("up_to_date", updater.Status().State);
|
|
Assert.False(updater.RequestApply());
|
|
}
|
|
|
|
[Fact]
|
|
public void GarbageOffers_AreIgnored()
|
|
{
|
|
RestartUpdater updater = Create();
|
|
updater.Offer(new UpdateOfferParams { Manifest = "not json", Signature = "x" });
|
|
updater.Offer(new UpdateOfferParams { Manifest = new string('x', 5000), Signature = "x" });
|
|
updater.Offer(new UpdateOfferParams { Manifest = "{\"component\":\"agent\"}", Signature = "x" });
|
|
Assert.Equal("up_to_date", updater.Status().State);
|
|
Assert.False(updater.RequestApply());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task TheAutoPolicy_RestartsByItself_ButNotBeforeTheMinimumUptime()
|
|
{
|
|
var time = new FakeTimeProvider(DateTimeOffset.FromUnixTimeSeconds(2_000_000_000));
|
|
var updater = new RestartUpdater("agent", _restarts.Add, time, NullNodeLog.Instance, "dev-aaa", "aaa", 1_000, auto: true);
|
|
updater.Offer(Offer("dev-bbb", 2_000));
|
|
updater.Offer(Offer("dev-bbb", 2_000)); // 重连时面板会再发一次:不能排两个
|
|
Assert.Empty(_restarts);
|
|
time.Advance(TimeSpan.FromMinutes(9));
|
|
await Task.Delay(50);
|
|
Assert.Empty(_restarts);
|
|
time.Advance(TimeSpan.FromMinutes(2));
|
|
await WaitAsync(() => _restarts.Count == 1);
|
|
Assert.Equal("applying", updater.Status().State);
|
|
await Task.Delay(50);
|
|
Assert.Single(_restarts);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task TheManualPolicy_NeverRestartsByItself()
|
|
{
|
|
var time = new FakeTimeProvider(DateTimeOffset.FromUnixTimeSeconds(2_000_000_000));
|
|
var updater = new RestartUpdater("agent", _restarts.Add, time, NullNodeLog.Instance, "dev-aaa", "aaa", 1_000, auto: false);
|
|
updater.Offer(Offer("dev-bbb", 2_000));
|
|
time.Advance(TimeSpan.FromHours(1));
|
|
await Task.Delay(50);
|
|
Assert.Empty(_restarts);
|
|
Assert.Equal("available", updater.Status().State);
|
|
}
|
|
|
|
private static async Task WaitAsync(Func<bool> condition)
|
|
{
|
|
for (int i = 0; i < 100 && !condition(); i++)
|
|
{
|
|
await Task.Delay(20);
|
|
}
|
|
|
|
Assert.True(condition());
|
|
}
|
|
|
|
[Fact]
|
|
public void WithoutTheEnvironmentVariable_ThereIsNoUpdater()
|
|
{
|
|
Assert.Null(Environment.GetEnvironmentVariable(RestartUpdater.EnvironmentVariable));
|
|
Assert.Null(RestartUpdater.FromEnvironment("agent", _restarts.Add, TimeProvider.System, NullNodeLog.Instance));
|
|
}
|
|
}
|