@@ -12,6 +12,7 @@ import { tmpDir } from '../../helpers';
1212import { slurpQueryHistory , splatQueryHistory } from '../../query-serialization' ;
1313import { formatLegacyMessage , QueryInProgress } from '../../legacy-query-server/run-queries' ;
1414import { EvaluationResult , QueryResultType } from '../../pure/legacy-messages' ;
15+ import Sinon = require( 'sinon' ) ;
1516
1617describe ( 'query-results' , ( ) => {
1718 let disposeSpy : sinon . SinonSpy ;
@@ -156,149 +157,193 @@ describe('query-results', () => {
156157 } ) ;
157158 } ) ;
158159
159- it ( 'should interpretResultsSarif' , async function ( ) {
160- // up to 2 minutes per test
161- this . timeout ( 2 * 60 * 1000 ) ;
162-
163- const spy = sandbox . mock ( ) ;
164- spy . returns ( { a : '1234' } ) ;
165- const mockServer = {
166- interpretBqrsSarif : spy
167- } as unknown as CodeQLCliServer ;
168-
169- const interpretedResultsPath = path . join ( tmpDir . name , 'interpreted.json' ) ;
170- const resultsPath = '123' ;
171- const sourceInfo = { } ;
160+ describe ( 'interpretResultsSarif' , ( ) => {
161+ let mockServer : CodeQLCliServer ;
162+ let spy : Sinon . SinonExpectation ;
172163 const metadata = {
173164 kind : 'my-kind' ,
174165 id : 'my-id' as string | undefined ,
175166 scored : undefined
176167 } ;
177- const results1 = await interpretResultsSarif (
178- mockServer ,
179- metadata ,
180- {
181- resultsPath, interpretedResultsPath
182- } ,
183- sourceInfo as SourceInfo
184- ) ;
168+ const resultsPath = '123' ;
169+ const interpretedResultsPath = path . join ( tmpDir . name , 'interpreted.json' ) ;
170+ const sourceInfo = { } ;
185171
186- expect ( results1 ) . to . deep . eq ( { a : '1234' , t : 'SarifInterpretationData' } ) ;
187- expect ( spy ) . to . have . been . calledWith (
188- metadata ,
189- resultsPath , interpretedResultsPath , sourceInfo
190- ) ;
172+ beforeEach ( ( ) => {
173+ spy = sandbox . mock ( ) ;
174+ spy . returns ( { a : '1234' } ) ;
191175
192- // Try again, but with no id
193- spy . reset ( ) ;
194- spy . returns ( { a : '1234' } ) ;
195- delete metadata . id ;
196- const results2 = await interpretResultsSarif (
197- mockServer ,
198- metadata ,
199- {
200- resultsPath, interpretedResultsPath
201- } ,
202- sourceInfo as SourceInfo
203- ) ;
204- expect ( results2 ) . to . deep . eq ( { a : '1234' , t : 'SarifInterpretationData' } ) ;
205- expect ( spy ) . to . have . been . calledWith (
206- { kind : 'my-kind' , id : 'dummy-id' , scored : undefined } ,
207- resultsPath , interpretedResultsPath , sourceInfo
208- ) ;
176+ mockServer = {
177+ interpretBqrsSarif : spy
178+ } as unknown as CodeQLCliServer ;
179+ } ) ;
209180
210- // try a third time, but this time we get from a valid small SARIF file
211- spy . reset ( ) ;
212- fs . writeFileSync ( interpretedResultsPath , JSON . stringify ( {
213- runs : [ { results : [ ] } ] // A run needs results to succeed.
214- } ) , 'utf8' ) ;
215- const results3 = await interpretResultsSarif (
216- mockServer ,
217- metadata ,
218- {
219- resultsPath, interpretedResultsPath
220- } ,
221- sourceInfo as SourceInfo
222- ) ;
223- // We do not re-interpret if we are reading from a SARIF file.
224- expect ( spy ) . to . not . have . been . called ;
181+ afterEach ( async ( ) => {
182+ sandbox . restore ( ) ;
183+ await del ( interpretedResultsPath ) ;
184+ } ) ;
225185
226- expect ( results3 ) . to . have . property ( 't' , 'SarifInterpretationData' ) ;
227- expect ( results3 ) . to . have . nested . property ( 'runs[0].results' ) ;
186+ it ( 'should interpretResultsSarif' , async function ( ) {
187+ // up to 2 minutes per test
188+ this . timeout ( 2 * 60 * 1000 ) ;
189+
190+ const results = await interpretResultsSarif (
191+ mockServer ,
192+ metadata ,
193+ {
194+ resultsPath, interpretedResultsPath
195+ } ,
196+ sourceInfo as SourceInfo
197+ ) ;
198+
199+ expect ( results ) . to . deep . eq ( { a : '1234' , t : 'SarifInterpretationData' } ) ;
200+ expect ( spy ) . to . have . been . calledWith (
201+ metadata ,
202+ resultsPath , interpretedResultsPath , sourceInfo
203+ ) ;
204+ } ) ;
228205
229- // try a fourth time, but this time we use an invalid small SARIF file
230- spy . reset ( ) ;
231- fs . writeFileSync ( interpretedResultsPath , JSON . stringify ( {
232- a : '6' // Invalid: no runs or results
233- } ) , 'utf8' ) ;
206+ it ( 'should interpretBqrsSarif without ID' , async function ( ) {
207+ // up to 2 minutes per test
208+ this . timeout ( 2 * 60 * 1000 ) ;
234209
235- await expect (
236- interpretResultsSarif (
210+ delete metadata . id ;
211+ const results = await interpretResultsSarif (
237212 mockServer ,
238213 metadata ,
239214 {
240215 resultsPath, interpretedResultsPath
241216 } ,
242- sourceInfo as SourceInfo )
243- ) . to . be . rejectedWith ( 'Parsing output of interpretation failed: Invalid SARIF file: expecting at least one run with result.' ) ;
217+ sourceInfo as SourceInfo
218+ ) ;
219+ expect ( results ) . to . deep . eq ( { a : '1234' , t : 'SarifInterpretationData' } ) ;
220+ expect ( spy ) . to . have . been . calledWith (
221+ { kind : 'my-kind' , id : 'dummy-id' , scored : undefined } ,
222+ resultsPath , interpretedResultsPath , sourceInfo
223+ ) ;
224+ } ) ;
225+
226+ it ( 'should use sarifParser on a valid small SARIF file' , async function ( ) {
227+ // up to 2 minutes per test
228+ this . timeout ( 2 * 60 * 1000 ) ;
244229
245- // We do not attempt to re-interpret if we are reading from a SARIF file.
246- expect ( spy ) . to . not . have . been . called ;
230+ fs . writeFileSync ( interpretedResultsPath , JSON . stringify ( {
231+ runs : [ { results : [ ] } ] // A run needs results to succeed.
232+ } ) , 'utf8' ) ;
233+ const results = await interpretResultsSarif (
234+ mockServer ,
235+ metadata ,
236+ {
237+ resultsPath, interpretedResultsPath
238+ } ,
239+ sourceInfo as SourceInfo
240+ ) ;
241+ // We do not re-interpret if we are reading from a SARIF file.
242+ expect ( spy ) . to . not . have . been . called ;
247243
248- // Try a fifth time with a valid large SARIF file
249- spy . reset ( ) ;
250- const validSarifStream = fs . createWriteStream ( interpretedResultsPath , { flags : 'w' } ) ;
244+ expect ( results ) . to . have . property ( 't' , 'SarifInterpretationData' ) ;
245+ expect ( results ) . to . have . nested . property ( 'runs[0].results' ) ;
246+ } ) ;
251247
252- validSarifStream . write ( JSON . stringify ( {
253- runs : [ { results : [ ] } ] // A run needs results to succeed.
254- } ) , 'utf8' ) ;
248+ it ( 'should throw an error on an invalid small SARIF file' , async function ( ) {
249+ // up to 2 minutes per test
250+ this . timeout ( 2 * 60 * 1000 ) ;
255251
256- for ( let i = 0 ; i < 10000000 ; i ++ ) {
257- validSarifStream . write ( JSON . stringify ( {
258- a : '6'
252+ fs . writeFileSync ( interpretedResultsPath , JSON . stringify ( {
253+ a : '6' // Invalid: no runs or results
259254 } ) , 'utf8' ) ;
260- }
261- validSarifStream . end ( ) ;
262255
263- const results5 = await interpretResultsSarif (
264- mockServer ,
265- metadata ,
266- {
267- resultsPath, interpretedResultsPath
268- } ,
269- sourceInfo as SourceInfo
270- ) ;
271- // We do not re-interpret if we are reading from a SARIF file.
272- expect ( spy ) . to . not . have . been . called ;
256+ await expect (
257+ interpretResultsSarif (
258+ mockServer ,
259+ metadata ,
260+ {
261+ resultsPath, interpretedResultsPath
262+ } ,
263+ sourceInfo as SourceInfo )
264+ ) . to . be . rejectedWith ( 'Parsing output of interpretation failed: Invalid SARIF file: expecting at least one run with result.' ) ;
265+
266+ // We do not attempt to re-interpret if we are reading from a SARIF file.
267+ expect ( spy ) . to . not . have . been . called ;
268+ } ) ;
269+
270+ it ( 'should use sarifParser on a valid large SARIF file' , async function ( ) {
271+ // up to 2 minutes per test
272+ this . timeout ( 2 * 60 * 1000 ) ;
273273
274- expect ( results5 ) . to . have . property ( 't' , 'SarifInterpretationData' ) ;
275- expect ( results5 ) . to . have . nested . property ( 'runs[0].results' ) ;
274+ const validSarifStream = fs . createWriteStream ( interpretedResultsPath , { flags : 'w' } ) ;
276275
277- // Explicitly delete the large SARIF file — overwriting causes odd errors.
278- await del ( interpretedResultsPath ) ;
276+ const finished = new Promise ( ( res , rej ) => {
277+ validSarifStream . addListener ( 'finish' , res ) ;
278+ validSarifStream . addListener ( 'error' , rej ) ;
279+ } ) ;
279280
280- // Try a sixth time with an invalid large SARIF file
281- spy . reset ( ) ;
282- const invalidSarifStream = fs . createWriteStream ( interpretedResultsPath , { flags : 'w' } ) ;
283- for ( let i = 0 ; i < 10000000 ; i ++ ) {
284- invalidSarifStream . write ( JSON . stringify ( {
285- a : '6'
281+ validSarifStream . write ( JSON . stringify ( {
282+ runs : [ { results : [ ] } ] // A run needs results to succeed.
286283 } ) , 'utf8' ) ;
287- }
288- invalidSarifStream . end ( ) ;
289284
290- await expect (
291- interpretResultsSarif (
285+ const iterations = 10_000_000 ;
286+ for ( let i = 0 ; i < iterations ; i ++ ) {
287+ validSarifStream . write ( JSON . stringify ( {
288+ a : '6'
289+ } ) , 'utf8' ) ;
290+ }
291+ validSarifStream . end ( ) ;
292+ await finished ;
293+
294+ const results = await interpretResultsSarif (
292295 mockServer ,
293296 metadata ,
294297 {
295298 resultsPath, interpretedResultsPath
296299 } ,
297- sourceInfo as SourceInfo )
298- ) . to . be . rejectedWith ( 'Parsing output of interpretation failed: Invalid SARIF file: expecting at least one run with result.' ) ;
300+ sourceInfo as SourceInfo
301+ ) ;
302+ // We do not re-interpret if we are reading from a SARIF file.
303+ expect ( spy ) . to . not . have . been . called ;
299304
300- // We do not attempt to re-interpret if we are reading from a SARIF file.
301- expect ( spy ) . to . not . have . been . called ;
305+ expect ( results ) . to . have . property ( 't' , 'SarifInterpretationData' ) ;
306+ expect ( results ) . to . have . nested . property ( 'runs[0].results' ) ;
307+ } ) ;
308+
309+ it ( 'should throw an error on an invalid large SARIF file' , async function ( ) {
310+ // up to 2 minutes per test
311+ this . timeout ( 2 * 60 * 1000 ) ;
312+
313+ const invalidSarifStream = fs . createWriteStream ( interpretedResultsPath , { flags : 'w' } ) ;
314+
315+ const finished = new Promise ( ( res , rej ) => {
316+ invalidSarifStream . addListener ( 'finish' , res ) ;
317+ invalidSarifStream . addListener ( 'error' , rej ) ;
318+ } ) ;
319+
320+ invalidSarifStream . write ( '[' , 'utf8' ) ;
321+ const iterations = 10 ;
322+ for ( let i = 0 ; i < iterations ; i ++ ) {
323+ invalidSarifStream . write ( JSON . stringify ( {
324+ a : '6'
325+ } ) , 'utf8' ) ;
326+ if ( i < iterations - 1 ) {
327+ invalidSarifStream . write ( ',' ) ;
328+ }
329+ }
330+ invalidSarifStream . write ( ']' , 'utf8' ) ;
331+ invalidSarifStream . end ( ) ;
332+ await finished ;
333+
334+ await expect (
335+ interpretResultsSarif (
336+ mockServer ,
337+ metadata ,
338+ {
339+ resultsPath, interpretedResultsPath
340+ } ,
341+ sourceInfo as SourceInfo )
342+ ) . to . be . rejectedWith ( 'Parsing output of interpretation failed: Invalid SARIF file: expecting at least one run with result.' ) ;
343+
344+ // We do not attempt to re-interpret if we are reading from a SARIF file.
345+ expect ( spy ) . to . not . have . been . called ;
346+ } ) ;
302347 } ) ;
303348
304349 describe ( 'splat and slurp' , ( ) => {
0 commit comments