| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- package xray
- import (
- "slices"
- "testing"
- )
- func newOnlineTestProcess() *Process {
- return &Process{newProcess(nil)}
- }
- func assertSameSet(t *testing.T, label string, got, want []string) {
- t.Helper()
- g := append([]string(nil), got...)
- w := append([]string(nil), want...)
- slices.Sort(g)
- slices.Sort(w)
- if !slices.Equal(g, w) {
- t.Errorf("%s = %v, want %v", label, got, want)
- }
- }
- // TestGetOnlineClientsByNodeScopesPerNode pins the fix for issue #4809: a
- // client online on one node must not be reported online on any other node.
- func TestGetOnlineClientsByNodeScopesPerNode(t *testing.T) {
- p := newOnlineTestProcess()
- p.RefreshLocalOnline([]string{"user1"}, 1000, 20000)
- p.SetNodeOnlineClients(3, []string{"user1", "user2"})
- p.SetNodeOnlineClients(5, []string{"user3"})
- byNode := p.GetOnlineClientsByNode()
- assertSameSet(t, "local (key 0)", byNode[localNodeKey], []string{"user1"})
- assertSameSet(t, "node 3", byNode[3], []string{"user1", "user2"})
- assertSameSet(t, "node 5", byNode[5], []string{"user3"})
- if slices.Contains(byNode[5], "user1") {
- t.Errorf("user1 leaked onto node 5: %v", byNode[5])
- }
- if slices.Contains(byNode[localNodeKey], "user3") || slices.Contains(byNode[3], "user3") {
- t.Errorf("user3 leaked off node 5: local=%v node3=%v", byNode[localNodeKey], byNode[3])
- }
- }
- // TestGetOnlineClientsByNodeOmitsEmptyGroups keeps the payload small: a node
- // with no online clients (e.g. just cleared) must not appear as an empty key.
- func TestGetOnlineClientsByNodeOmitsEmptyGroups(t *testing.T) {
- p := newOnlineTestProcess()
- p.SetNodeOnlineClients(3, []string{"user1"})
- p.SetNodeOnlineClients(7, []string{})
- byNode := p.GetOnlineClientsByNode()
- if _, ok := byNode[7]; ok {
- t.Errorf("node 7 has no online clients but is present: %v", byNode)
- }
- if _, ok := byNode[localNodeKey]; ok {
- t.Errorf("no local clients online but key 0 is present: %v", byNode)
- }
- }
- // TestGetOnlineClientsUnionDedupes confirms the flat union (used by the
- // client-centric / total-count views) still merges every node and dedupes.
- func TestGetOnlineClientsUnionDedupes(t *testing.T) {
- p := newOnlineTestProcess()
- p.RefreshLocalOnline([]string{"user1"}, 1000, 20000)
- p.SetNodeOnlineClients(3, []string{"user1", "user2"})
- assertSameSet(t, "union", p.GetOnlineClients(), []string{"user1", "user2"})
- }
- // TestRefreshLocalOnlineGraceWindow checks the in-memory local set honours the
- // grace window: idle-but-recent clients stay online, stale ones age out, and
- // the set is derived only from local activity (never the shared DB column).
- func TestRefreshLocalOnlineGraceWindow(t *testing.T) {
- p := newOnlineTestProcess()
- const grace = 20000
- p.RefreshLocalOnline([]string{"user1"}, 1000, grace)
- if got := p.GetOnlineClientsByNode()[localNodeKey]; !slices.Contains(got, "user1") {
- t.Fatalf("user1 should be online right after activity, got %v", got)
- }
- p.RefreshLocalOnline([]string{"user2"}, 11000, grace)
- got := p.GetOnlineClientsByNode()[localNodeKey]
- if !slices.Contains(got, "user1") || !slices.Contains(got, "user2") {
- t.Fatalf("both within grace window, got %v", got)
- }
- p.RefreshLocalOnline(nil, 22000, grace)
- got = p.GetOnlineClientsByNode()[localNodeKey]
- if slices.Contains(got, "user1") {
- t.Errorf("user1 (idle 21s, past grace) should have aged out, got %v", got)
- }
- if !slices.Contains(got, "user2") {
- t.Errorf("user2 (idle 11s, within grace) should still be online, got %v", got)
- }
- }
- // TestClearNodeOnlineClientsDropsNode mirrors a failed node probe: the node's
- // clients must disappear from the per-node map immediately.
- func TestClearNodeOnlineClientsDropsNode(t *testing.T) {
- p := newOnlineTestProcess()
- p.SetNodeOnlineClients(3, []string{"user1"})
- p.ClearNodeOnlineClients(3)
- if _, ok := p.GetOnlineClientsByNode()[3]; ok {
- t.Errorf("node 3 should be absent after ClearNodeOnlineClients")
- }
- }
|