package service import ( "testing" "github.com/mhsanaei/3x-ui/v3/internal/database" "github.com/mhsanaei/3x-ui/v3/internal/database/model" ) // P13: annotateAgentTelemetry overlays the agent-reported heartbeat // telemetry onto agent node views only — panel version becomes // "agent ", xray version/uptime/latency/CPU/mem/IPs take the // reported values. Traditional rows and never-reporting agents are // left untouched. func TestAnnotateAgentTelemetry(t *testing.T) { setupConflictDB(t) db := database.GetDB() agentNode := &model.Node{Id: 7401, Name: "agent-node", Address: ""} tradNode := &model.Node{Id: 7402, Name: "trad-node", Address: "198.51.100.2", PanelVersion: "3.4.2", XrayVersion: "26.6.27"} silentNode := &model.Node{Id: 7403, Name: "silent-agent-node", Address: ""} for _, n := range []*model.Node{agentNode, tradNode, silentNode} { if err := db.Create(n).Error; err != nil { t.Fatalf("create node %d: %v", n.Id, err) } } reporting := &model.AgentNode{ TokenHash: "hash-reporting", Name: "agent-node", NodeID: &agentNode.Id, AgentVersion: "3.7.0-agent.1", XrayVersion: "26.6.27", UptimeSecs: 90061, LatencyMs: 12, CpuPct: 3.5, MemPct: 41.2, IPv4: "203.0.113.7", IPv6: "2001:db8::7", TelemetryAt: 1700000000000, } silent := &model.AgentNode{TokenHash: "hash-silent", Name: "silent-agent-node", NodeID: &silentNode.Id} // The traditional node has no agent row at all — by the codebase's // definition (any binding makes a node agent-managed) it must pass // through the overlay untouched. for _, ag := range []*model.AgentNode{reporting, silent} { if err := db.Create(ag).Error; err != nil { t.Fatalf("create agent row: %v", err) } } views := toNodeViews([]*model.Node{agentNode, tradNode, silentNode}) annotateNodeTypes(views) annotateAgentTelemetry(views) byID := map[int]*NodeView{} for _, v := range views { byID[v.Id] = v } av := byID[7401] if av.NodeType != "agent" { t.Fatalf("node 7401 type = %q, want agent", av.NodeType) } if av.XrayVersion != "26.6.27" || av.PanelVersion != "agent 3.7.0-agent.1" || av.UptimeSecs != 90061 || av.LatencyMs != 12 || av.CpuPct != 3.5 || av.MemPct != 41.2 || av.Ipv4 != "203.0.113.7" || av.Ipv6 != "2001:db8::7" { t.Fatalf("agent view not overlaid: %+v", av) } tv := byID[7402] if tv.PanelVersion != "3.4.2" || tv.XrayVersion != "26.6.27" || tv.Ipv4 != "" || tv.Ipv6 != "" { t.Fatalf("traditional view mutated: %+v", tv) } sv := byID[7403] if sv.XrayVersion != "" || sv.PanelVersion != "" || sv.Ipv4 != "" || sv.UptimeSecs != 0 { t.Fatalf("silent agent view should stay empty: %+v", sv) } }