节点在线、应用在线、配置在线使用令牌查询
大石头 authored at 2021-12-16 19:49:30
3.14 KiB
Stardust
using System;
using System.Threading;
using System.Threading.Tasks;
using NewLife.Security;
using Stardust.Data.Nodes;
using Stardust.Server;
using Stardust.Server.Services;
using Xunit;

namespace ServerTest.Services;

/// <summary>节点在线服务测试。覆盖定时器生命周期与离线告警门控(NODE-3)</summary>
public class NodeOnlineServiceTests
{
    private static Node CreateNode(Boolean alarmOnOffline) => new()
    {
        Code = "nd_" + Rand.NextString(8),
        Name = "node-" + Rand.NextString(4),
        Enable = true,
        AlarmOnOffline = alarmOnOffline,
    };

    [Fact(DisplayName = "超时判定为零时启动与停止服务不抛异常")]
    public async Task StartStop_NoThrow()
    {
        var svc = new NodeOnlineService(null, new StarServerSetting { SessionTimeout = 0 }, null);

        await svc.StartAsync(CancellationToken.None);
        await svc.StopAsync(CancellationToken.None);
    }

    [Fact(DisplayName = "未开启离线告警时上线检查直接跳过")]
    public void CheckOnline_NoAlarm_Skip()
    {
        var node = CreateNode(false);

        // 未开启告警时直接返回,不产生任何外部调用
        NodeOnlineService.CheckOnline(node);
    }

    [Fact(DisplayName = "未开启离线告警时下线检查直接跳过")]
    public void CheckOffline_NoAlarm_Skip()
    {
        var node = CreateNode(false);

        NodeOnlineService.CheckOffline(node, "test");
    }

    [Fact(DisplayName = "开启告警但未配置Webhook时下线检查安全跳过")]
    public void CheckOffline_AlarmWithoutWebhook_Skip()
    {
        var node = CreateNode(true);
        node.WebHook = null;

        // 没有 Webhook 时获取告警配置为空,直接返回,不发送告警
        NodeOnlineService.CheckOffline(node, "test");
    }

    [Fact(DisplayName = "空节点传入下线检查不抛异常")]
    public void CheckOffline_NullNode_NoThrow() => NodeOnlineService.CheckOffline(null, "test");

    [Fact(DisplayName = "超时清理只删除超过阈值未更新的在线记录")]
    public void ClearExpire_RemovesStaleOnly()
    {
        var node = CreateNode(false);
        node.Insert();

        var stale = new NodeOnline { SessionID = "sess_" + Rand.NextString(8), NodeID = node.ID };
        stale.Insert();
        var fresh = new NodeOnline { SessionID = "sess_" + Rand.NextString(8), NodeID = node.ID };
        fresh.Insert();

        try
        {
            // 绕过时间拦截器,把其中一条的更新时间改到很早
            var old = DateTime.Now.AddHours(-2);
            NodeOnline.Meta.Session.Execute($"Update {NodeOnline.Meta.TableName} Set UpdateTime='{old:yyyy-MM-dd HH:mm:ss}' Where ID={stale.ID}");

            var list = NodeOnline.ClearExpire(TimeSpan.FromMinutes(10));

            Assert.NotNull(list);
            Assert.Contains(list, e => e.ID == stale.ID);
            Assert.Null(NodeOnline.FindById(stale.ID));
            Assert.NotNull(NodeOnline.FindById(fresh.ID));
        }
        finally
        {
            NodeOnline.FindById(stale.ID)?.Delete();
            NodeOnline.FindById(fresh.ID)?.Delete();
            node.Delete();
        }
    }
}