master
go 212 lines 4.81 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package chartengine
4
5 import (
6 "testing"
7
8 "github.com/netdata/netdata/go/plugins/plugin/framework/chartengine/internal/program"
9 "github.com/stretchr/testify/assert"
10 "github.com/stretchr/testify/require"
11 )
12
13 func TestRenderChartInstanceIDScenarios(t *testing.T) {
14 tests := map[string]struct {
15 identity program.ChartIdentity
16 labels map[string]string
17 wantID string
18 wantOK bool
19 wantErr bool
20 }{
21 "static id without instances": {
22 identity: program.ChartIdentity{
23 IDTemplate: program.Template{
24 Raw: "mysql_queries",
25 },
26 },
27 labels: map[string]string{
28 "host": "db1",
29 },
30 wantID: "mysql_queries",
31 wantOK: true,
32 },
33 "literal id is independent of labels": {
34 identity: program.ChartIdentity{
35 IDTemplate: program.Template{
36 Raw: "win_nic_traffic",
37 },
38 },
39 labels: map[string]string{
40 "nic": "eth0",
41 },
42 wantID: "win_nic_traffic",
43 wantOK: true,
44 },
45 "instances explicit appends stable suffix": {
46 identity: program.ChartIdentity{
47 IDTemplate: program.Template{
48 Raw: "win_nic_traffic",
49 },
50 InstanceByLabels: []program.InstanceLabelSelector{
51 {Key: "nic"},
52 },
53 },
54 labels: map[string]string{
55 "nic": "eth0",
56 },
57 wantID: "win_nic_traffic_eth0",
58 wantOK: true,
59 },
60 "instances wildcard excludes key": {
61 identity: program.ChartIdentity{
62 IDTemplate: program.Template{
63 Raw: "latency_bucket",
64 },
65 InstanceByLabels: []program.InstanceLabelSelector{
66 {IncludeAll: true},
67 {Exclude: true, Key: "le"},
68 },
69 },
70 labels: map[string]string{
71 "service": "api",
72 "zone": "a",
73 "le": "1",
74 },
75 wantID: "latency_bucket_api_a",
76 wantOK: true,
77 },
78 "instances explicit missing key drops series": {
79 identity: program.ChartIdentity{
80 IDTemplate: program.Template{
81 Raw: "win_nic_traffic",
82 },
83 InstanceByLabels: []program.InstanceLabelSelector{
84 {Key: "nic"},
85 },
86 },
87 labels: map[string]string{
88 "device": "eth0",
89 },
90 wantOK: false,
91 },
92 }
93
94 for name, tc := range tests {
95 t.Run(name, func(t *testing.T) {
96 got, ok, err := renderChartInstanceID(tc.identity, tc.labels)
97 if tc.wantErr {
98 require.Error(t, err)
99 return
100 }
101 require.NoError(t, err)
102 assert.Equal(t, tc.wantOK, ok)
103 assert.Equal(t, tc.wantID, got)
104 })
105 }
106 }
107
108 func TestRenderChartInstanceIDSanitizesDotLabelValues(t *testing.T) {
109 identity := program.ChartIdentity{
110 IDTemplate: program.Template{Raw: "win_nic_traffic"},
111 InstanceByLabels: []program.InstanceLabelSelector{
112 {Key: "nic"},
113 },
114 }
115
116 got, ok, err := renderChartInstanceID(identity, map[string]string{"nic": "eth0.100"})
117 require.NoError(t, err)
118 assert.True(t, ok)
119 assert.Equal(t, "win_nic_traffic_eth0_100", got)
120 }
121
122 func TestSanitizeChartIDLabelValue(t *testing.T) {
123 tests := map[string]struct {
124 value string
125 want string
126 }{
127 "empty": {
128 value: "",
129 want: "",
130 },
131 "no dots unchanged": {
132 value: "eth0",
133 want: "eth0",
134 },
135 "single dot replaced": {
136 value: "db1.eu",
137 want: "db1_eu",
138 },
139 "multiple dots replaced": {
140 value: "a.b.c",
141 want: "a_b_c",
142 },
143 }
144
145 for name, tc := range tests {
146 t.Run(name, func(t *testing.T) {
147 assert.Equal(t, tc.want, sanitizeChartIDLabelValue(tc.value))
148 })
149 }
150 }
151
152 func TestRenderChartInstanceIDSanitizesLegacyLabelChars(t *testing.T) {
153 identity := program.ChartIdentity{
154 IDTemplate: program.Template{Raw: "win_nic_traffic"},
155 InstanceByLabels: []program.InstanceLabelSelector{
156 {Key: "nic"},
157 },
158 }
159
160 tests := []struct {
161 name string
162 value string
163 want string
164 }{
165 {name: "space", value: "a b", want: "a_b"},
166 {name: "backslash", value: "a\\b", want: "a_b"},
167 {name: "apostrophe", value: "a'b", want: "ab"},
168 }
169
170 for _, tc := range tests {
171 t.Run(tc.name, func(t *testing.T) {
172 got, ok, err := renderChartInstanceID(identity, map[string]string{"nic": tc.value})
173 require.NoError(t, err)
174 assert.True(t, ok)
175 assert.Equal(t, "win_nic_traffic_"+tc.want, got)
176 })
177 }
178 }
179
180 func TestRenderChartInstanceIDExcludeWinsRegardlessOfTokenOrder(t *testing.T) {
181 tests := map[string]struct {
182 selectors []program.InstanceLabelSelector
183 wantID string
184 }{
185 "exclude after explicit": {
186 selectors: []program.InstanceLabelSelector{
187 {Key: "host"},
188 {Exclude: true, Key: "host"},
189 },
190 wantID: "mysql_queries",
191 },
192 "exclude before explicit": {
193 selectors: []program.InstanceLabelSelector{
194 {Exclude: true, Key: "host"},
195 {Key: "host"},
196 },
197 wantID: "mysql_queries",
198 },
199 }
200
201 for name, tc := range tests {
202 t.Run(name, func(t *testing.T) {
203 got, ok, err := renderChartInstanceID(program.ChartIdentity{
204 IDTemplate: program.Template{Raw: "mysql_queries"},
205 InstanceByLabels: tc.selectors,
206 }, map[string]string{"host": "db1"})
207 require.NoError(t, err)
208 assert.True(t, ok)
209 assert.Equal(t, tc.wantID, got)
210 })
211 }
212 }