1
+ /*
2
+ Copyright 2024 Splunk Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ import * as assert from 'assert' ;
18
+ import { beforeEach } from 'mocha' ;
19
+ import { generateFilePaths , generateRandomStackTrace } from './utils' ;
20
+
21
+ const chromeStackTraceEval = `Error: Something went wrong
22
+ at eval (eval at <anonymous> (http://example.com/scripts/main.js:10:20), <anonymous>:1:1)
23
+ at Object.functionName (http://example.com/scripts/utils.js:15:25)
24
+ at http://example.com/scripts/app.js:20:30
25
+ at new ConstructorName (http://example.com/scripts/controller.js:25:35)
26
+ at http://example.com/scripts/main.js:30:40` ;
27
+ const chromeStackTraceEvalExpected = [
28
+ 'http://example.com/scripts/main.js' ,
29
+ 'http://example.com/scripts/utils.js' ,
30
+ 'http://example.com/scripts/app.js' ,
31
+ 'http://example.com/scripts/controller.js' ,
32
+ ] ;
33
+
34
+ const chromeStackTraceAnonymous = `TypeError: undefined is not a function
35
+ at http://example.com/js/anonymous.js:10:5
36
+ at <anonymous>:15:10
37
+ at Object.functionName (http://example.com/js/utils.js:20:15)
38
+ at new ConstructorName (http://example.com/js/app.js:25:20)
39
+ at <anonymous>:30:25` ;
40
+ const chromeStackTraceAnonymousExpected = [
41
+ 'http://example.com/js/anonymous.js' ,
42
+ 'http://example.com/js/utils.js' ,
43
+ 'http://example.com/js/app.js' ,
44
+ ] ;
45
+
46
+ const geckoStackTraceEval = `Error: Something went wrong
47
+ @http://example.com/scripts/main.js:10:20
48
+ @eval (eval at <anonymous>:1:1)
49
+ functionName@http://example.com/scripts/utils.js:15:25
50
+ @http://example.com/scripts/app.js:20:30
51
+ ConstructorName@http://example.com/scripts/controller.js:25:35
52
+ @http://example.com/scripts/main.js:30:40` ;
53
+ const geckoStackTraceEvalExpected = [
54
+ 'http://example.com/scripts/main.js' ,
55
+ 'http://example.com/scripts/utils.js' ,
56
+ 'http://example.com/scripts/app.js' ,
57
+ 'http://example.com/scripts/controller.js' ,
58
+ ] ;
59
+
60
+ const geckoStackTraceAnonymous = `TypeError: undefined is not a function
61
+ @http://example.com/js/anonymous.js:10:5
62
+ @<anonymous>:15:10
63
+ functionName@http://example.com/js/utils.js:20:15
64
+ ConstructorName@http://example.com/js/app.js:25:20
65
+ @<anonymous>:30:25` ;
66
+ const geckoStackTraceAnonymousExpected = [
67
+ 'http://example.com/js/anonymous.js' ,
68
+ 'http://example.com/js/utils.js' ,
69
+ 'http://example.com/js/app.js'
70
+ ] ;
71
+
72
+ // Test 1: simple test w/ dupes
73
+ const stack1 = `Error
74
+ at http://localhost:8080/js/script1.js:10:15
75
+ at http://localhost:8080/js/script2.js:20:25
76
+ at http://localhost:8080/js/script1.js:30:35` ;
77
+ const expected1 = [ 'http://localhost:8080/js/script1.js' , 'http://localhost:8080/js/script2.js' ] ;
78
+
79
+ // Test 2: http and https
80
+ const stack2 = `Error
81
+ at https://example.com/js/app.js:50:10
82
+ at http://localhost/js/util.js:100:50` ;
83
+ const expected2 = [ 'https://example.com/js/app.js' , 'http://localhost/js/util.js' ] ;
84
+
85
+ // Test 3: No full path URLs
86
+ const stack3 = `Error
87
+ at someFunction (file.js:10:15)
88
+ at anotherFunction (file.js:20:25)` ;
89
+ const expected3 = [ ] ;
90
+
91
+ // Test 4: Only one URL, with port
92
+ const stack4 = `Error
93
+ at http://localhost:3000/js/main.js:10:15` ;
94
+ const expected4 = [ 'http://localhost:3000/js/main.js' ] ;
95
+
96
+ // Test 5: Duplicate URLs
97
+ const stack5 = `Error
98
+ at http://localhost:3000/js/main.js:10:15
99
+ at http://localhost:3000/js/main.js:20:25
100
+ at http://localhost:3000/js/utils.js:30:35` ;
101
+ const expected5 = [ 'http://localhost:3000/js/main.js' , 'http://localhost:3000/js/utils.js' ] ;
102
+
103
+ // Test 6: Urls with query strings and fragments
104
+ const stack6 = `Error
105
+ at http://example.com:8080/path/js/main.js?name=testname:10:15
106
+ at http://example.com:8080/path/js/main2.js#fragmentHere:20:15
107
+ at http://example.com:8080/path/js/main3.js?name=testname#fragmentHere:30:15` ;
108
+ const expected6 = [ 'http://example.com:8080/path/js/main.js' , 'http://example.com:8080/path/js/main2.js' , 'http://example.com:8080/path/js/main3.js' ] ;
109
+
110
+ // Test 7: Urls with different protocols and blobs
111
+ const stack7 = `Error
112
+ at file://testing.com:8000/js/testFile.js:1:2
113
+ at blob:https://example.com:1000/src/hello.js:2:3` ;
114
+ const expected7 = [ 'file://testing.com:8000/js/testFile.js' , 'https://example.com:1000/src/hello.js' ] ;
115
+
116
+ const regexFilter = / ( [ \w ] + : \/ \/ [ ^ \s / ] + \/ [ ^ \s ? : # ] + ) / g;
117
+ describe ( 'regexFilter' , ( ) => {
118
+ let urls = new Set ( ) ;
119
+ let match ;
120
+
121
+ beforeEach ( ( ) => {
122
+ urls = new Set ( ) ;
123
+ match = null ;
124
+ } ) ;
125
+ it ( 'should test chrome eval stack traces' , ( ) => {
126
+ while ( ( match = regexFilter . exec ( chromeStackTraceEval ) ) !== null ) {
127
+ urls . add ( match [ 0 ] ) ;
128
+ }
129
+ const urlArr = [ ...urls ] ;
130
+ assert . deepEqual ( urlArr , chromeStackTraceEvalExpected ) ;
131
+ } ) ;
132
+
133
+ it ( 'should test chrome anonymous stack traces' , ( ) => {
134
+ while ( ( match = regexFilter . exec ( chromeStackTraceAnonymous ) ) !== null ) {
135
+ urls . add ( match [ 0 ] ) ;
136
+ }
137
+ const urlArr = [ ...urls ] ;
138
+ assert . deepEqual ( urlArr , chromeStackTraceAnonymousExpected ) ;
139
+ } ) ;
140
+
141
+ it ( 'should test gecko eval stack traces' , ( ) => {
142
+ while ( ( match = regexFilter . exec ( geckoStackTraceEval ) ) !== null ) {
143
+ urls . add ( match [ 0 ] ) ;
144
+ }
145
+ const urlArr = [ ...urls ] ;
146
+ assert . deepEqual ( urlArr , geckoStackTraceEvalExpected ) ;
147
+ } ) ;
148
+
149
+ it ( 'should test gecko anonymous stack traces' , ( ) => {
150
+ while ( ( match = regexFilter . exec ( geckoStackTraceAnonymous ) ) !== null ) {
151
+ urls . add ( match [ 0 ] ) ;
152
+ }
153
+ const urlArr = [ ...urls ] ;
154
+ assert . deepEqual ( urlArr , geckoStackTraceAnonymousExpected ) ;
155
+ } ) ;
156
+
157
+ it ( 'should test simple stack trace with dupes' , ( ) => {
158
+ while ( ( match = regexFilter . exec ( stack1 ) ) !== null ) {
159
+ urls . add ( match [ 0 ] ) ;
160
+ }
161
+ const urlArr = [ ...urls ] ;
162
+ assert . deepEqual ( urlArr , expected1 ) ;
163
+ } ) ;
164
+
165
+ it ( 'should test http vs https stack traces' , ( ) => {
166
+ while ( ( match = regexFilter . exec ( stack2 ) ) !== null ) {
167
+ urls . add ( match [ 0 ] ) ;
168
+ }
169
+ const urlArr = [ ...urls ] ;
170
+ assert . deepEqual ( urlArr , expected2 ) ;
171
+ } ) ;
172
+
173
+ it ( 'should test no full url path stack traces' , ( ) => {
174
+ while ( ( match = regexFilter . exec ( stack3 ) ) !== null ) {
175
+ urls . add ( match [ 0 ] ) ;
176
+ }
177
+ const urlArr = [ ...urls ] ;
178
+ assert . deepEqual ( urlArr , expected3 ) ;
179
+ } ) ;
180
+
181
+ it ( 'should test url ports in stack traces' , ( ) => {
182
+ while ( ( match = regexFilter . exec ( stack4 ) ) !== null ) {
183
+ urls . add ( match [ 0 ] ) ;
184
+ }
185
+ const urlArr = [ ...urls ] ;
186
+ assert . deepEqual ( urlArr , expected4 ) ;
187
+ } ) ;
188
+
189
+ it ( 'should test duplicate urls in stack traces' , ( ) => {
190
+ while ( ( match = regexFilter . exec ( stack5 ) ) !== null ) {
191
+ urls . add ( match [ 0 ] ) ;
192
+ }
193
+ const urlArr = [ ...urls ] ;
194
+ assert . deepEqual ( urlArr , expected5 ) ;
195
+ } ) ;
196
+
197
+ it ( 'should test query strings/fragments in stack traces' , ( ) => {
198
+ while ( ( match = regexFilter . exec ( stack6 ) ) !== null ) {
199
+ urls . add ( match [ 0 ] ) ;
200
+ }
201
+ const urlArr = [ ...urls ] ;
202
+ assert . deepEqual ( urlArr , expected6 ) ;
203
+ } ) ;
204
+
205
+ it ( 'should test blobs and diff protocols in stack traces' , ( ) => {
206
+ while ( ( match = regexFilter . exec ( stack7 ) ) !== null ) {
207
+ urls . add ( match [ 0 ] ) ;
208
+ }
209
+ const urlArr = [ ...urls ] ;
210
+ assert . deepEqual ( urlArr , expected7 ) ;
211
+ } ) ;
212
+
213
+ it ( 'should test long stack traces' , ( ) => {
214
+ const randomPaths = generateFilePaths ( 20 , 20 ) ;
215
+ const randomStack = generateRandomStackTrace ( randomPaths , 10000 ) ;
216
+
217
+ while ( ( match = regexFilter . exec ( randomStack ) ) !== null ) {
218
+ urls . add ( match [ 0 ] ) ;
219
+ }
220
+ const urlArr = [ ...urls ] ;
221
+ assert . deepEqual ( urlArr . sort ( ) , randomPaths . sort ( ) ) ;
222
+ } ) ;
223
+ } ) ;
0 commit comments