Files
MoShiro/backend/tests/MoShiro.Backend.Tests/ScheduleTests.cs
T
justme 238046d959
ci/woodpecker/push/verify Pipeline was successful
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/dev-image Pipeline was successful
test(backend): parallelize isolated fixtures [CI] [SKIP TESTS]
2026-10-10 04:54:18 +08:00

80 lines
3.6 KiB
C#

using System.Net;
using System.Text.Json.Nodes;
using MoShiro.Backend.Application;
using MoShiro.Protocol;
using MoShiro.TestSupport;
namespace MoShiro.Backend.Tests;
/// <summary>定时重启:默认开、北京时间 04:30;节点连上时补发,管理端改了设置马上群发,关掉就发空。</summary>
public sealed class ScheduleTests : IClassFixture<BackendFixture>
{
private readonly BackendFixture _backend;
public ScheduleTests(BackendFixture backend)
{
_backend = backend;
}
private async Task PatchAsync(JsonObject settings)
{
using HttpResponseMessage response = await _backend.Admin.PatchAsync("/api/admin/settings", BackendFixture.Json(settings, "application/merge-patch+json"));
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
private static Task<bool> LastIs(AgentSimulator agent, string? restartAt) =>
Task.FromResult(agent.Schedules.ToArray() is { Length: > 0 } all && all[^1].RestartAt == restartAt);
[Fact]
public void Format_WritesTheOffsetTheNodeParses()
{
Assert.Equal("04:30+08:00", ScheduleService.Format(4, 30, 480));
Assert.Equal("00:00+00:00", ScheduleService.Format(0, 0, 0));
Assert.Equal("23:05-05:30", ScheduleService.Format(23, 5, -330));
}
[Fact]
public async Task ANewNode_GetsTheDefaultSchedule_AndLaterChangesAreBroadcast()
{
await using AgentSimulator agent = await _backend.ConnectAgentAsync();
await BackendFixture.EventuallyAsync(() => LastIs(agent, "04:30+08:00"), because: "defaults: on, 04:30 Beijing time, sent right after hello");
try
{
await PatchAsync(new JsonObject { ["fleet.restart_hour"] = 3, ["fleet.restart_minute"] = 5, ["fleet.restart_utc_offset_minutes"] = 0 });
await BackendFixture.EventuallyAsync(() => LastIs(agent, "03:05+00:00"), because: "a changed time is pushed to online nodes");
await PatchAsync(new JsonObject { ["fleet.restart_enabled"] = false });
await BackendFixture.EventuallyAsync(() => LastIs(agent, null), because: "switching it off sends an empty schedule");
// 关着的时候新连上的节点也拿到「关」
await using AgentSimulator late = await _backend.ConnectAgentAsync();
await BackendFixture.EventuallyAsync(() => LastIs(late, null), because: "a node connecting while it is off is told so");
}
finally
{
await PatchAsync(new JsonObject { ["fleet.restart_enabled"] = true, ["fleet.restart_hour"] = 4, ["fleet.restart_minute"] = 30, ["fleet.restart_utc_offset_minutes"] = 480 });
}
}
[Fact]
public async Task BadValues_AreRefused()
{
using HttpResponseMessage response = await _backend.Admin.PatchAsync("/api/admin/settings",
BackendFixture.Json(new JsonObject { ["fleet.restart_hour"] = 24, ["fleet.restart_minute"] = 60, ["fleet.restart_utc_offset_minutes"] = 900 }, "application/merge-patch+json"));
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
[Fact]
public async Task DefaultLineTemplates_IncludeTheConnectTimings()
{
using HttpResponseMessage response = await _backend.Admin.GetAsync("/api/admin/tasks");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
JsonArray items = JsonNode.Parse(await response.Content.ReadAsStringAsync())!["items"]!.AsArray();
string[] kinds = [.. items.Select(i => i!["kind"]!.GetValue<string>())];
Assert.Contains("connect", kinds);
Assert.Contains("udp_echo", kinds);
Assert.Contains("tcp_echo", kinds);
}
}