Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/integrations/v2/app_agent_receiver/sourcemaps_test.go
5340 views
1
package app_agent_receiver
2
3
import (
4
"bytes"
5
"errors"
6
"io"
7
"io/fs"
8
"net/http"
9
"path/filepath"
10
"testing"
11
12
"github.com/go-kit/log"
13
"github.com/prometheus/client_golang/prometheus"
14
"github.com/stretchr/testify/require"
15
)
16
17
type mockHTTPClient struct {
18
responses []struct {
19
*http.Response
20
error
21
}
22
requests []string
23
}
24
25
func (cl *mockHTTPClient) Get(url string) (resp *http.Response, err error) {
26
if len(cl.responses) > len(cl.requests) {
27
r := cl.responses[len(cl.requests)]
28
cl.requests = append(cl.requests, url)
29
return r.Response, r.error
30
}
31
return nil, errors.New("mockHTTPClient got more requests than expected")
32
}
33
34
type mockFileService struct {
35
files map[string][]byte
36
stats []string
37
reads []string
38
}
39
40
func (s *mockFileService) Stat(name string) (fs.FileInfo, error) {
41
s.stats = append(s.stats, name)
42
_, ok := s.files[name]
43
if !ok {
44
return nil, errors.New("file not found")
45
}
46
return nil, nil
47
}
48
49
func (s *mockFileService) ReadFile(name string) ([]byte, error) {
50
s.reads = append(s.reads, name)
51
content, ok := s.files[name]
52
if ok {
53
return content, nil
54
}
55
return nil, errors.New("file not found")
56
}
57
58
func newResponseFromTestData(t *testing.T, file string) *http.Response {
59
return &http.Response{
60
Body: io.NopCloser(bytes.NewReader(loadTestData(t, file))),
61
StatusCode: 200,
62
}
63
}
64
65
func mockException() *Exception {
66
return &Exception{
67
Stacktrace: &Stacktrace{
68
Frames: []Frame{
69
{
70
Colno: 6,
71
Filename: "http://localhost:1234/foo.js",
72
Function: "eval",
73
Lineno: 5,
74
},
75
{
76
Colno: 5,
77
Filename: "http://localhost:1234/foo.js",
78
Function: "callUndefined",
79
Lineno: 6,
80
},
81
},
82
},
83
}
84
}
85
86
func Test_RealSourceMapStore_DownloadSuccess(t *testing.T) {
87
conf := SourceMapConfig{
88
Download: true,
89
DownloadFromOrigins: []string{"*"},
90
}
91
92
httpClient := &mockHTTPClient{
93
responses: []struct {
94
*http.Response
95
error
96
}{
97
{newResponseFromTestData(t, "foo.js"), nil},
98
{newResponseFromTestData(t, "foo.js.map"), nil},
99
},
100
}
101
102
logger := log.NewNopLogger()
103
104
sourceMapStore := NewSourceMapStore(logger, conf, prometheus.NewRegistry(), httpClient, &mockFileService{})
105
106
exception := mockException()
107
108
transformed := TransformException(sourceMapStore, logger, exception, "123")
109
110
require.Equal(t, []string{"http://localhost:1234/foo.js", "http://localhost:1234/foo.js.map"}, httpClient.requests)
111
112
expected := &Exception{
113
Stacktrace: &Stacktrace{
114
Frames: []Frame{
115
{
116
Colno: 37,
117
Filename: "/__parcel_source_root/demo/src/actions.ts",
118
Function: "?",
119
Lineno: 6,
120
},
121
{
122
Colno: 2,
123
Filename: "/__parcel_source_root/demo/src/actions.ts",
124
Function: "?",
125
Lineno: 7,
126
},
127
},
128
},
129
}
130
131
require.Equal(t, *expected, *transformed)
132
}
133
134
func Test_RealSourceMapStore_DownloadError(t *testing.T) {
135
conf := SourceMapConfig{
136
Download: true,
137
DownloadFromOrigins: []string{"*"},
138
}
139
140
resp := &http.Response{
141
StatusCode: 500,
142
Body: io.NopCloser(bytes.NewReader([]byte{})),
143
}
144
145
httpClient := &mockHTTPClient{
146
responses: []struct {
147
*http.Response
148
error
149
}{
150
{resp, nil},
151
},
152
}
153
154
logger := log.NewNopLogger()
155
156
sourceMapStore := NewSourceMapStore(logger, conf, prometheus.NewRegistry(), httpClient, &mockFileService{})
157
158
exception := mockException()
159
160
transformed := TransformException(sourceMapStore, logger, exception, "123")
161
162
require.Equal(t, []string{"http://localhost:1234/foo.js"}, httpClient.requests)
163
require.Equal(t, exception, transformed)
164
}
165
166
func Test_RealSourceMapStore_DownloadHTTPOriginFiltering(t *testing.T) {
167
conf := SourceMapConfig{
168
Download: true,
169
DownloadFromOrigins: []string{"http://bar.com/"},
170
}
171
172
httpClient := &mockHTTPClient{
173
responses: []struct {
174
*http.Response
175
error
176
}{
177
{newResponseFromTestData(t, "foo.js"), nil},
178
{newResponseFromTestData(t, "foo.js.map"), nil},
179
},
180
}
181
182
logger := log.NewNopLogger()
183
184
sourceMapStore := NewSourceMapStore(logger, conf, prometheus.NewRegistry(), httpClient, &mockFileService{})
185
186
exception := &Exception{
187
Stacktrace: &Stacktrace{
188
Frames: []Frame{
189
{
190
Colno: 6,
191
Filename: "http://foo.com/foo.js",
192
Function: "eval",
193
Lineno: 5,
194
},
195
{
196
Colno: 5,
197
Filename: "http://bar.com/foo.js",
198
Function: "callUndefined",
199
Lineno: 6,
200
},
201
},
202
},
203
}
204
205
transformed := TransformException(sourceMapStore, logger, exception, "123")
206
207
require.Equal(t, []string{"http://bar.com/foo.js", "http://bar.com/foo.js.map"}, httpClient.requests)
208
209
expected := &Exception{
210
Stacktrace: &Stacktrace{
211
Frames: []Frame{
212
{
213
Colno: 6,
214
Filename: "http://foo.com/foo.js",
215
Function: "eval",
216
Lineno: 5,
217
},
218
{
219
Colno: 2,
220
Filename: "/__parcel_source_root/demo/src/actions.ts",
221
Function: "?",
222
Lineno: 7,
223
},
224
},
225
},
226
}
227
228
require.Equal(t, *expected, *transformed)
229
}
230
231
func Test_RealSourceMapStore_ReadFromFileSystem(t *testing.T) {
232
conf := SourceMapConfig{
233
Download: false,
234
FileSystem: []SourceMapFileLocation{
235
{
236
MinifiedPathPrefix: "http://foo.com/",
237
Path: filepath.FromSlash("/var/build/latest/"),
238
},
239
{
240
MinifiedPathPrefix: "http://bar.com/",
241
Path: filepath.FromSlash("/var/build/{{ .Release }}/"),
242
},
243
},
244
}
245
246
mapFile := loadTestData(t, "foo.js.map")
247
248
fileService := &mockFileService{
249
files: map[string][]byte{
250
filepath.FromSlash("/var/build/latest/foo.js.map"): mapFile,
251
filepath.FromSlash("/var/build/123/foo.js.map"): mapFile,
252
},
253
}
254
255
logger := log.NewNopLogger()
256
257
sourceMapStore := NewSourceMapStore(logger, conf, prometheus.NewRegistry(), &mockHTTPClient{}, fileService)
258
259
exception := &Exception{
260
Stacktrace: &Stacktrace{
261
Frames: []Frame{
262
{
263
Colno: 6,
264
Filename: "http://foo.com/foo.js",
265
Function: "eval",
266
Lineno: 5,
267
},
268
{
269
Colno: 6,
270
Filename: "http://foo.com/bar.js",
271
Function: "eval",
272
Lineno: 5,
273
},
274
{
275
Colno: 5,
276
Filename: "http://bar.com/foo.js",
277
Function: "callUndefined",
278
Lineno: 6,
279
},
280
{
281
Colno: 5,
282
Filename: "http://baz.com/foo.js",
283
Function: "callUndefined",
284
Lineno: 6,
285
},
286
},
287
},
288
}
289
290
transformed := TransformException(sourceMapStore, logger, exception, "123")
291
292
require.Equal(t, []string{
293
filepath.FromSlash("/var/build/latest/foo.js.map"),
294
filepath.FromSlash("/var/build/latest/bar.js.map"),
295
filepath.FromSlash("/var/build/123/foo.js.map"),
296
}, fileService.stats)
297
require.Equal(t, []string{
298
filepath.FromSlash("/var/build/latest/foo.js.map"),
299
filepath.FromSlash("/var/build/123/foo.js.map"),
300
}, fileService.reads)
301
302
expected := &Exception{
303
Stacktrace: &Stacktrace{
304
Frames: []Frame{
305
{
306
Colno: 37,
307
Filename: "/__parcel_source_root/demo/src/actions.ts",
308
Function: "?",
309
Lineno: 6,
310
},
311
{
312
Colno: 6,
313
Filename: "http://foo.com/bar.js",
314
Function: "eval",
315
Lineno: 5,
316
},
317
{
318
Colno: 2,
319
Filename: "/__parcel_source_root/demo/src/actions.ts",
320
Function: "?",
321
Lineno: 7,
322
},
323
{
324
Colno: 5,
325
Filename: "http://baz.com/foo.js",
326
Function: "callUndefined",
327
Lineno: 6,
328
},
329
},
330
},
331
}
332
333
require.Equal(t, *expected, *transformed)
334
}
335
336
func Test_RealSourceMapStore_ReadFromFileSystemAndDownload(t *testing.T) {
337
conf := SourceMapConfig{
338
Download: true,
339
DownloadFromOrigins: []string{"*"},
340
FileSystem: []SourceMapFileLocation{
341
{
342
MinifiedPathPrefix: "http://foo.com/",
343
Path: filepath.FromSlash("/var/build/latest/"),
344
},
345
},
346
}
347
348
mapFile := loadTestData(t, "foo.js.map")
349
350
fileService := &mockFileService{
351
files: map[string][]byte{
352
filepath.FromSlash("/var/build/latest/foo.js.map"): mapFile,
353
},
354
}
355
356
httpClient := &mockHTTPClient{
357
responses: []struct {
358
*http.Response
359
error
360
}{
361
{newResponseFromTestData(t, "foo.js"), nil},
362
{newResponseFromTestData(t, "foo.js.map"), nil},
363
},
364
}
365
366
logger := log.NewNopLogger()
367
368
sourceMapStore := NewSourceMapStore(logger, conf, prometheus.NewRegistry(), httpClient, fileService)
369
370
exception := &Exception{
371
Stacktrace: &Stacktrace{
372
Frames: []Frame{
373
{
374
Colno: 6,
375
Filename: "http://foo.com/foo.js",
376
Function: "eval",
377
Lineno: 5,
378
},
379
{
380
Colno: 5,
381
Filename: "http://bar.com/foo.js",
382
Function: "callUndefined",
383
Lineno: 6,
384
},
385
},
386
},
387
}
388
389
transformed := TransformException(sourceMapStore, logger, exception, "123")
390
391
require.Equal(t, []string{filepath.FromSlash("/var/build/latest/foo.js.map")}, fileService.stats)
392
require.Equal(t, []string{filepath.FromSlash("/var/build/latest/foo.js.map")}, fileService.reads)
393
require.Equal(t, []string{"http://bar.com/foo.js", "http://bar.com/foo.js.map"}, httpClient.requests)
394
395
expected := &Exception{
396
Stacktrace: &Stacktrace{
397
Frames: []Frame{
398
{
399
Colno: 37,
400
Filename: "/__parcel_source_root/demo/src/actions.ts",
401
Function: "?",
402
Lineno: 6,
403
},
404
{
405
Colno: 2,
406
Filename: "/__parcel_source_root/demo/src/actions.ts",
407
Function: "?",
408
Lineno: 7,
409
},
410
},
411
},
412
}
413
414
require.Equal(t, *expected, *transformed)
415
}
416
417
func Test_RealSourceMapStore_FilepathSanitized(t *testing.T) {
418
conf := SourceMapConfig{
419
Download: false,
420
FileSystem: []SourceMapFileLocation{
421
{
422
MinifiedPathPrefix: "http://foo.com/",
423
Path: filepath.FromSlash("/var/build/latest/"),
424
},
425
},
426
}
427
428
fileService := &mockFileService{}
429
430
logger := log.NewNopLogger()
431
432
sourceMapStore := NewSourceMapStore(logger, conf, prometheus.NewRegistry(), &mockHTTPClient{}, fileService)
433
434
exception := &Exception{
435
Stacktrace: &Stacktrace{
436
Frames: []Frame{
437
{
438
Colno: 6,
439
Filename: "http://foo.com/../../../etc/passwd",
440
Function: "eval",
441
Lineno: 5,
442
},
443
},
444
},
445
}
446
447
transformed := TransformException(sourceMapStore, logger, exception, "123")
448
449
require.Equal(t, []string{
450
filepath.FromSlash("/var/build/latest/etc/passwd.map"),
451
}, fileService.stats)
452
require.Len(t, fileService.reads, 0)
453
454
require.Equal(t, *exception, *transformed)
455
}
456
457
func Test_RealSourceMapStore_FilepathQueryParamsOmitted(t *testing.T) {
458
conf := SourceMapConfig{
459
Download: false,
460
FileSystem: []SourceMapFileLocation{
461
{
462
MinifiedPathPrefix: "http://foo.com/",
463
Path: filepath.FromSlash("/var/build/latest/"),
464
},
465
},
466
}
467
468
fileService := &mockFileService{}
469
470
logger := log.NewNopLogger()
471
472
sourceMapStore := NewSourceMapStore(logger, conf, prometheus.NewRegistry(), &mockHTTPClient{}, fileService)
473
474
exception := &Exception{
475
Stacktrace: &Stacktrace{
476
Frames: []Frame{
477
{
478
Colno: 6,
479
Filename: "http://foo.com/static/foo.js?v=1233",
480
Function: "eval",
481
Lineno: 5,
482
},
483
},
484
},
485
}
486
487
transformed := TransformException(sourceMapStore, logger, exception, "123")
488
489
require.Equal(t, []string{
490
filepath.FromSlash("/var/build/latest/static/foo.js.map"),
491
}, fileService.stats)
492
require.Len(t, fileService.reads, 0)
493
494
require.Equal(t, *exception, *transformed)
495
}
496
497