master
go 273 lines 8.07 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package tomcat
4
5 import (
6 "context"
7 "net/http"
8 "net/http/httptest"
9 "os"
10 "testing"
11
12 "github.com/netdata/netdata/go/plugins/pkg/web"
13 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/collecttest"
14
15 "github.com/stretchr/testify/assert"
16 "github.com/stretchr/testify/require"
17 )
18
19 var (
20 dataConfigJSON, _ = os.ReadFile("testdata/config.json")
21 dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
22
23 dataServerStatus, _ = os.ReadFile("testdata/server_status.xml")
24 )
25
26 func Test_testDataIsValid(t *testing.T) {
27 for name, data := range map[string][]byte{
28 "dataConfigJSON": dataConfigJSON,
29 "dataConfigYAML": dataConfigYAML,
30 "dataServerStatus": dataServerStatus,
31 } {
32 require.NotNil(t, data, name)
33 }
34 }
35
36 func TestCollector_ConfigurationSerialize(t *testing.T) {
37 collecttest.TestConfigurationSerialize(t, &Collector{}, dataConfigJSON, dataConfigYAML)
38 }
39
40 func TestCollector_Init(t *testing.T) {
41 tests := map[string]struct {
42 wantFail bool
43 config Config
44 }{
45 "success with default": {
46 wantFail: false,
47 config: New().Config,
48 },
49 "fail when URL not set": {
50 wantFail: true,
51 config: Config{
52 HTTPConfig: web.HTTPConfig{
53 RequestConfig: web.RequestConfig{URL: ""},
54 },
55 },
56 },
57 }
58
59 for name, test := range tests {
60 t.Run(name, func(t *testing.T) {
61 collr := New()
62 collr.Config = test.config
63
64 if test.wantFail {
65 assert.Error(t, collr.Init(context.Background()))
66 } else {
67 assert.NoError(t, collr.Init(context.Background()))
68 }
69 })
70 }
71 }
72
73 func TestCollector_Charts(t *testing.T) {
74 assert.NotNil(t, New().Charts())
75 }
76
77 func TestCollector_Check(t *testing.T) {
78 tests := map[string]struct {
79 wantFail bool
80 prepare func(t *testing.T) (*Collector, func())
81 }{
82 "success case": {
83 wantFail: false,
84 prepare: prepareCaseSuccess,
85 },
86 "fails on unexpected xml response": {
87 wantFail: true,
88 prepare: prepareCaseUnexpectedXMLResponse,
89 },
90 "fails on invalid format response": {
91 wantFail: true,
92 prepare: prepareCaseInvalidFormatResponse,
93 },
94 "fails on connection refused": {
95 wantFail: true,
96 prepare: prepareCaseConnectionRefused,
97 },
98 }
99
100 for name, test := range tests {
101 t.Run(name, func(t *testing.T) {
102 collr, cleanup := test.prepare(t)
103 defer cleanup()
104
105 if test.wantFail {
106 assert.Error(t, collr.Check(context.Background()))
107 } else {
108 assert.NoError(t, collr.Check(context.Background()))
109 }
110 })
111 }
112 }
113
114 func TestCollector_Collect(t *testing.T) {
115 tests := map[string]struct {
116 prepare func(t *testing.T) (collr *Collector, cleanup func())
117 wantMetrics map[string]int64
118 wantCharts int
119 }{
120 "success case": {
121 prepare: prepareCaseSuccess,
122 wantCharts: len(defaultCharts) + len(jvmMemoryPoolChartsTmpl)*8 + len(connectorChartsTmpl)*2,
123 wantMetrics: map[string]int64{
124 "connector_http-nio-8080_request_info_bytes_received": 0,
125 "connector_http-nio-8080_request_info_bytes_sent": 12174519,
126 "connector_http-nio-8080_request_info_error_count": 24,
127 "connector_http-nio-8080_request_info_processing_time": 28326,
128 "connector_http-nio-8080_request_info_request_count": 4838,
129 "connector_http-nio-8080_thread_info_busy": 1,
130 "connector_http-nio-8080_thread_info_count": 10,
131 "connector_http-nio-8080_thread_info_idle": 9,
132 "connector_http-nio-8081_request_info_bytes_received": 0,
133 "connector_http-nio-8081_request_info_bytes_sent": 12174519,
134 "connector_http-nio-8081_request_info_error_count": 24,
135 "connector_http-nio-8081_request_info_processing_time": 28326,
136 "connector_http-nio-8081_request_info_request_count": 4838,
137 "connector_http-nio-8081_thread_info_busy": 1,
138 "connector_http-nio-8081_thread_info_count": 10,
139 "connector_http-nio-8081_thread_info_idle": 9,
140 "jvm_memory_free": 144529816,
141 "jvm_memory_total": 179306496,
142 "jvm_memory_used": 34776680,
143 "jvm_memorypool_codeheap_non-nmethods_commited": 2555904,
144 "jvm_memorypool_codeheap_non-nmethods_max": 5840896,
145 "jvm_memorypool_codeheap_non-nmethods_used": 1477888,
146 "jvm_memorypool_codeheap_non-profiled_nmethods_commited": 4587520,
147 "jvm_memorypool_codeheap_non-profiled_nmethods_max": 122908672,
148 "jvm_memorypool_codeheap_non-profiled_nmethods_used": 4536704,
149 "jvm_memorypool_codeheap_profiled_nmethods_commited": 13172736,
150 "jvm_memorypool_codeheap_profiled_nmethods_max": 122908672,
151 "jvm_memorypool_codeheap_profiled_nmethods_used": 13132032,
152 "jvm_memorypool_compressed_class_space_commited": 1900544,
153 "jvm_memorypool_compressed_class_space_max": 1073741824,
154 "jvm_memorypool_compressed_class_space_used": 1712872,
155 "jvm_memorypool_g1_eden_space_commited": 108003328,
156 "jvm_memorypool_g1_eden_space_max": -1,
157 "jvm_memorypool_g1_eden_space_used": 23068672,
158 "jvm_memorypool_g1_old_gen_commited": 66060288,
159 "jvm_memorypool_g1_old_gen_max": 1914699776,
160 "jvm_memorypool_g1_old_gen_used": 6175120,
161 "jvm_memorypool_g1_survivor_space_commited": 5242880,
162 "jvm_memorypool_g1_survivor_space_max": -1,
163 "jvm_memorypool_g1_survivor_space_used": 5040192,
164 "jvm_memorypool_metaspace_commited": 18939904,
165 "jvm_memorypool_metaspace_max": -1,
166 "jvm_memorypool_metaspace_used": 18537336,
167 },
168 },
169 "fails on unexpected xml response": {
170 prepare: prepareCaseUnexpectedXMLResponse,
171 },
172 "fails on invalid format response": {
173 prepare: prepareCaseInvalidFormatResponse,
174 },
175 "fails on connection refused": {
176 prepare: prepareCaseConnectionRefused,
177 },
178 }
179
180 for name, test := range tests {
181 t.Run(name, func(t *testing.T) {
182 collr, cleanup := test.prepare(t)
183 defer cleanup()
184
185 mx := collr.Collect(context.Background())
186
187 require.Equal(t, test.wantMetrics, mx)
188
189 if len(test.wantMetrics) > 0 {
190 assert.Equal(t, test.wantCharts, len(*collr.Charts()))
191 collecttest.TestMetricsHasAllChartsDims(t, collr.Charts(), mx)
192 }
193 })
194 }
195 }
196
197 func prepareCaseSuccess(t *testing.T) (*Collector, func()) {
198 t.Helper()
199 srv := httptest.NewServer(http.HandlerFunc(
200 func(w http.ResponseWriter, r *http.Request) {
201 switch r.URL.Path {
202 case urlPathServerStatus:
203 if r.URL.RawQuery != urlQueryServerStatus {
204 w.WriteHeader(http.StatusNotFound)
205 } else {
206 _, _ = w.Write(dataServerStatus)
207 }
208 default:
209 w.WriteHeader(http.StatusNotFound)
210 }
211 }))
212 collr := New()
213 collr.URL = srv.URL
214 require.NoError(t, collr.Init(context.Background()))
215
216 return collr, srv.Close
217 }
218
219 func prepareCaseConnectionRefused(t *testing.T) (*Collector, func()) {
220 t.Helper()
221 collr := New()
222 collr.URL = "http://127.0.0.1:65001"
223 require.NoError(t, collr.Init(context.Background()))
224
225 return collr, func() {}
226 }
227
228 func prepareCaseUnexpectedXMLResponse(t *testing.T) (*Collector, func()) {
229 t.Helper()
230 resp := `
231 <?xml version="1.0" encoding="UTF-8" ?>
232 <root>
233 <elephant>
234 <burn>false</burn>
235 <mountain>true</mountain>
236 <fog>false</fog>
237 <skin>-1561907625</skin>
238 <burst>anyway</burst>
239 <shadow>1558616893</shadow>
240 </elephant>
241 <start>ever</start>
242 <base>2093056027</base>
243 <mission>-2007590351</mission>
244 <victory>999053756</victory>
245 <die>false</die>
246 </root>
247
248 `
249 srv := httptest.NewServer(http.HandlerFunc(
250 func(w http.ResponseWriter, r *http.Request) {
251 _, _ = w.Write([]byte(resp))
252 }))
253
254 collr := New()
255 collr.URL = srv.URL
256 require.NoError(t, collr.Init(context.Background()))
257
258 return collr, srv.Close
259 }
260
261 func prepareCaseInvalidFormatResponse(t *testing.T) (*Collector, func()) {
262 t.Helper()
263 srv := httptest.NewServer(http.HandlerFunc(
264 func(w http.ResponseWriter, r *http.Request) {
265 _, _ = w.Write([]byte("hello and\n goodbye"))
266 }))
267
268 collr := New()
269 collr.URL = srv.URL
270 require.NoError(t, collr.Init(context.Background()))
271
272 return collr, srv.Close
273 }