@@ -19,7 +19,10 @@ import {
1919 storagePath ,
2020} from "../../global.helper" ;
2121import { VariantAnalysisResultsManager } from "../../../../src/variant-analysis/variant-analysis-results-manager" ;
22- import { VariantAnalysisStatus } from "../../../../src/variant-analysis/shared/variant-analysis" ;
22+ import {
23+ VariantAnalysisStatus ,
24+ VariantAnalysisSubmission ,
25+ } from "../../../../src/variant-analysis/shared/variant-analysis" ;
2326import { VariantAnalysis as VariantAnalysisApiResponse } from "../../../../src/variant-analysis/gh-api/variant-analysis" ;
2427import { createMockApiResponse } from "../../../factories/variant-analysis/gh-api/variant-analysis-api-response" ;
2528import { UserCancellationException } from "../../../../src/commandRunner" ;
@@ -28,6 +31,9 @@ import { DbManager } from "../../../../src/databases/db-manager";
2831import { ExtensionApp } from "../../../../src/common/vscode/vscode-app" ;
2932import { DbConfigStore } from "../../../../src/databases/config/db-config-store" ;
3033import { mockedQuickPickItem } from "../../utils/mocking.helpers" ;
34+ import { QueryLanguage } from "../../../../src/common/query-language" ;
35+ import { readBundledPack } from "../../utils/bundled-pack-helpers" ;
36+ import { load } from "js-yaml" ;
3137
3238// up to 3 minutes per test
3339jest . setTimeout ( 3 * 60 * 1000 ) ;
@@ -81,10 +87,6 @@ describe("Variant Analysis Manager", () => {
8187 "data-remote-qlpack/qlpack.yml" ,
8288 ) . fsPath ;
8389
84- function getFile ( file : string ) : Uri {
85- return Uri . file ( join ( baseDir , file ) ) ;
86- }
87-
8890 beforeEach ( async ( ) => {
8991 jest
9092 . spyOn ( window , "showQuickPick" )
@@ -202,5 +204,136 @@ describe("Variant Analysis Manager", () => {
202204
203205 await expect ( promise ) . rejects . toThrow ( UserCancellationException ) ;
204206 } ) ;
207+
208+ describe ( "check variant analysis generated packs" , ( ) => {
209+ beforeEach ( ( ) => {
210+ mockSubmitVariantAnalysis = jest
211+ . spyOn ( ghApiClient , "submitVariantAnalysis" )
212+ . mockResolvedValue ( {
213+ id : 1 ,
214+ query_language : QueryLanguage . Javascript ,
215+ query_pack_url : "http://example.com" ,
216+ created_at : "2021-01-01T00:00:00Z" ,
217+ updated_at : "2021-01-01T00:00:00Z" ,
218+ status : "in_progress" ,
219+ controller_repo : {
220+ id : 1 ,
221+ name : "vscode-codeql" ,
222+ full_name : "github/vscode-codeql" ,
223+ private : false ,
224+ } ,
225+ actions_workflow_run_id : 20 ,
226+ scanned_repositories : [ ] as any [ ] ,
227+ } ) ;
228+
229+ executeCommandSpy = jest . spyOn ( commands , "executeCommand" ) ;
230+ } ) ;
231+
232+ it ( "should run a remote query that is part of a qlpack" , async ( ) => {
233+ await doVariantAnalysisTest ( {
234+ queryPath : "data-remote-qlpack/in-pack.ql" ,
235+ filesThatExist : [ "in-pack.ql" , "lib.qll" ] ,
236+ filesThatDoNotExist : [ ] ,
237+ qlxFilesThatExist : [ "in-pack.qlx" ] ,
238+ } ) ;
239+ } ) ;
240+
241+ it ( "should run a remote query that is not part of a qlpack" , async ( ) => {
242+ await doVariantAnalysisTest ( {
243+ queryPath : "data-remote-no-qlpack/in-pack.ql" ,
244+ filesThatExist : [ "in-pack.ql" ] ,
245+ filesThatDoNotExist : [ "lib.qll" , "not-in-pack.ql" ] ,
246+ qlxFilesThatExist : [ "in-pack.qlx" ] ,
247+ } ) ;
248+ } ) ;
249+
250+ it ( "should run a remote query that is nested inside a qlpack" , async ( ) => {
251+ await doVariantAnalysisTest ( {
252+ queryPath : "data-remote-qlpack-nested/subfolder/in-pack.ql" ,
253+ filesThatExist : [ "subfolder/in-pack.ql" , "otherfolder/lib.qll" ] ,
254+ filesThatDoNotExist : [ "subfolder/not-in-pack.ql" ] ,
255+ qlxFilesThatExist : [ "subfolder/in-pack.qlx" ] ,
256+ } ) ;
257+ } ) ;
258+ } ) ;
259+
260+ async function doVariantAnalysisTest ( {
261+ queryPath,
262+ filesThatExist,
263+ qlxFilesThatExist,
264+ filesThatDoNotExist,
265+ } : {
266+ queryPath : string ;
267+ filesThatExist : string [ ] ;
268+ qlxFilesThatExist : string [ ] ;
269+ filesThatDoNotExist : string [ ] ;
270+ } ) {
271+ const fileUri = getFile ( queryPath ) ;
272+
273+ await variantAnalysisManager . runVariantAnalysis (
274+ fileUri ,
275+ progress ,
276+ cancellationTokenSource . token ,
277+ ) ;
278+
279+ expect ( mockSubmitVariantAnalysis ) . toBeCalledTimes ( 1 ) ;
280+ expect ( executeCommandSpy ) . toBeCalledWith (
281+ "codeQL.monitorVariantAnalysis" ,
282+ expect . objectContaining ( {
283+ query : expect . objectContaining ( { filePath : fileUri . fsPath } ) ,
284+ } ) ,
285+ ) ;
286+
287+ const request : VariantAnalysisSubmission =
288+ mockSubmitVariantAnalysis . mock . calls [ 0 ] [ 1 ] ;
289+
290+ const packFS = await readBundledPack ( request . query . pack ) ;
291+ filesThatExist . forEach ( ( file ) => {
292+ expect ( packFS . fileExists ( file ) ) . toBe ( true ) ;
293+ } ) ;
294+ if ( await cli . cliConstraints . supportsQlxRemote ( ) ) {
295+ qlxFilesThatExist . forEach ( ( file ) => {
296+ expect ( packFS . fileExists ( file ) ) . toBe ( true ) ;
297+ } ) ;
298+ }
299+ filesThatDoNotExist . forEach ( ( file ) => {
300+ expect ( packFS . fileExists ( file ) ) . toBe ( false ) ;
301+ } ) ;
302+
303+ expect (
304+ packFS . fileExists ( "qlpack.yml" ) || packFS . fileExists ( "codeql-pack.yml" ) ,
305+ ) . toBe ( true ) ;
306+
307+ // depending on the cli version, we should have one of these files
308+ expect (
309+ packFS . fileExists ( "qlpack.lock.yml" ) ||
310+ packFS . fileExists ( "codeql-pack.lock.yml" ) ,
311+ ) . toBe ( true ) ;
312+
313+ const packFileName = packFS . fileExists ( "qlpack.yml" )
314+ ? "qlpack.yml"
315+ : "codeql-pack.yml" ;
316+ const qlpackContents : any = load (
317+ packFS . fileContents ( packFileName ) . toString ( "utf-8" ) ,
318+ ) ;
319+ expect ( qlpackContents . name ) . toEqual ( "codeql-remote/query" ) ;
320+ expect ( qlpackContents . version ) . toEqual ( "0.0.0" ) ;
321+ expect ( qlpackContents . dependencies ?. [ "codeql/javascript-all" ] ) . toEqual (
322+ "*" ,
323+ ) ;
324+
325+ const qlpackLockContents : any = load (
326+ packFS . fileContents ( "codeql-pack.lock.yml" ) . toString ( "utf-8" ) ,
327+ ) ;
328+
329+ const actualLockKeys = Object . keys ( qlpackLockContents . dependencies ) ;
330+
331+ // The lock file should contain at least codeql/javascript-all.
332+ expect ( actualLockKeys ) . toContain ( "codeql/javascript-all" ) ;
333+ }
334+
335+ function getFile ( file : string ) : Uri {
336+ return Uri . file ( join ( baseDir , file ) ) ;
337+ }
205338 } ) ;
206339} ) ;
0 commit comments