master
go 155 lines 4.05 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package metrix
4
5 import (
6 "testing"
7
8 "github.com/stretchr/testify/require"
9 )
10
11 func TestCounterStoreScenarios(t *testing.T) {
12 tests := map[string]struct {
13 run func(t *testing.T)
14 }{
15 "snapshot counter delta and reset-aware semantics": {
16 run: func(t *testing.T) {
17 s := NewCollectorStore()
18 cc := cycleController(t, s)
19 c := s.Write().SnapshotMeter("http").Counter("requests_total")
20
21 cc.BeginCycle()
22 c.ObserveTotal(100)
23 cc.CommitCycleSuccess()
24 mustValue(t, s.Read(), "http.requests_total", nil, 100)
25 mustNoDelta(t, s.Read(), "http.requests_total", nil)
26
27 cc.BeginCycle()
28 c.ObserveTotal(150)
29 cc.CommitCycleSuccess()
30 mustValue(t, s.Read(), "http.requests_total", nil, 150)
31 mustDelta(t, s.Read(), "http.requests_total", nil, 50)
32
33 cc.BeginCycle()
34 c.ObserveTotal(20)
35 cc.CommitCycleSuccess()
36 mustDelta(t, s.Read(), "http.requests_total", nil, 20)
37 },
38 },
39 "snapshot counter delta unavailable on attempt gap": {
40 run: func(t *testing.T) {
41 s := NewCollectorStore()
42 cc := cycleController(t, s)
43 c := s.Write().SnapshotMeter("db").Counter("queries_total")
44
45 cc.BeginCycle()
46 c.ObserveTotal(10)
47 cc.CommitCycleSuccess()
48
49 cc.BeginCycle()
50 c.ObserveTotal(20)
51 cc.CommitCycleSuccess()
52 mustDelta(t, s.Read(), "db.queries_total", nil, 10)
53
54 cc.BeginCycle()
55 c.ObserveTotal(30)
56 cc.AbortCycle()
57
58 cc.BeginCycle()
59 c.ObserveTotal(40)
60 cc.CommitCycleSuccess()
61 mustNoDelta(t, s.Read(), "db.queries_total", nil)
62 },
63 },
64 "snapshot counter repeated writes are last-write-wins in cycle": {
65 run: func(t *testing.T) {
66 s := NewCollectorStore()
67 cc := cycleController(t, s)
68 c := s.Write().SnapshotMeter("app").Counter("events_total")
69
70 cc.BeginCycle()
71 c.ObserveTotal(10)
72 c.ObserveTotal(12)
73 cc.CommitCycleSuccess()
74 mustValue(t, s.Read(), "app.events_total", nil, 12)
75 },
76 },
77 "stateful counter add baselines from committed and accumulates": {
78 run: func(t *testing.T) {
79 s := NewCollectorStore()
80 cc := cycleController(t, s)
81 c := s.Write().StatefulMeter("runtime").Counter("jobs_total")
82
83 cc.BeginCycle()
84 c.Add(5)
85 cc.CommitCycleSuccess()
86 mustValue(t, s.Read(), "runtime.jobs_total", nil, 5)
87 mustNoDelta(t, s.Read(), "runtime.jobs_total", nil)
88
89 cc.BeginCycle()
90 c.Add(2)
91 c.Add(3)
92 cc.CommitCycleSuccess()
93 mustValue(t, s.Read(), "runtime.jobs_total", nil, 10)
94 mustDelta(t, s.Read(), "runtime.jobs_total", nil, 5)
95 },
96 },
97 "stateful counter negative add panics": {
98 run: func(t *testing.T) {
99 s := NewCollectorStore()
100 cc := cycleController(t, s)
101 c := s.Write().StatefulMeter("runtime").Counter("bad_total")
102
103 cc.BeginCycle()
104 expectPanic(t, func() {
105 c.Add(-1)
106 })
107 cc.AbortCycle()
108 },
109 },
110 "counter mode mixing snapshot and stateful panics": {
111 run: func(t *testing.T) {
112 s := NewCollectorStore()
113 s.Write().SnapshotMeter("mixed").Counter("metric")
114 expectPanic(t, func() {
115 _ = s.Write().StatefulMeter("mixed").Counter("metric")
116 })
117 },
118 },
119 "delta on non-counter returns unavailable": {
120 run: func(t *testing.T) {
121 s := NewCollectorStore()
122 cc := cycleController(t, s)
123 g := s.Write().SnapshotMeter("g").Gauge("value")
124 cc.BeginCycle()
125 g.Observe(3)
126 cc.CommitCycleSuccess()
127 mustNoDelta(t, s.Read(), "g.value", nil)
128 },
129 },
130 "snapshot counter hidden from Read on failed latest attempt": {
131 run: func(t *testing.T) {
132 s := NewCollectorStore()
133 cc := cycleController(t, s)
134 c := s.Write().SnapshotMeter("svc").Counter("requests_total")
135
136 cc.BeginCycle()
137 c.ObserveTotal(9)
138 cc.CommitCycleSuccess()
139 mustValue(t, s.Read(), "svc.requests_total", nil, 9)
140
141 cc.BeginCycle()
142 c.ObserveTotal(11)
143 cc.AbortCycle()
144
145 _, ok := s.Read().Value("svc.requests_total", nil)
146 require.False(t, ok, "expected snapshot counter hidden after failed attempt")
147 mustValue(t, s.Read(ReadRaw()), "svc.requests_total", nil, 9)
148 },
149 },
150 }
151
152 for name, tc := range tests {
153 t.Run(name, tc.run)
154 }
155 }