@@ -4,14 +4,16 @@ import * as sinon from 'sinon';
4
4
import { CancellationToken , extensions , QuickPickItem , Uri , window } from 'vscode' ;
5
5
import 'mocha' ;
6
6
import * as fs from 'fs-extra' ;
7
+ import * as os from 'os' ;
7
8
import * as yaml from 'js-yaml' ;
8
9
9
- import { runRemoteQuery } from '../../run-remote-query' ;
10
+ import { QlPack , runRemoteQuery } from '../../run-remote-query' ;
10
11
import { Credentials } from '../../authentication' ;
11
12
import { CliVersionConstraint , CodeQLCliServer } from '../../cli' ;
12
13
import { CodeQLExtensionInterface } from '../../extension' ;
13
14
import { setRemoteControllerRepo , setRemoteRepositoryLists } from '../../config' ;
14
15
import { UserCancellationException } from '../../commandRunner' ;
16
+ import { lte } from 'semver' ;
15
17
16
18
describe ( 'Remote queries' , function ( ) {
17
19
const baseDir = path . join ( __dirname , '../../../src/vscode-tests/cli-integration' ) ;
@@ -80,8 +82,7 @@ describe('Remote queries', function() {
80
82
const queryPackDir = path . join ( queryPackRootDir , 'query-pack' ) ;
81
83
printDirectoryContents ( queryPackDir ) ;
82
84
83
- // in-pack.ql renamed to query.ql
84
- expect ( fs . existsSync ( path . join ( queryPackDir , 'query.ql' ) ) ) . to . be . true ;
85
+ expect ( fs . existsSync ( path . join ( queryPackDir , 'in-pack.ql' ) ) ) . to . be . true ;
85
86
expect ( fs . existsSync ( path . join ( queryPackDir , 'lib.qll' ) ) ) . to . be . true ;
86
87
expect ( fs . existsSync ( path . join ( queryPackDir , 'qlpack.yml' ) ) ) . to . be . true ;
87
88
@@ -96,7 +97,7 @@ describe('Remote queries', function() {
96
97
const compiledPackDir = path . join ( queryPackDir , '.codeql/pack/github/remote-query-pack/0.0.0/' ) ;
97
98
printDirectoryContents ( compiledPackDir ) ;
98
99
99
- expect ( fs . existsSync ( path . join ( compiledPackDir , 'query .ql' ) ) ) . to . be . true ;
100
+ expect ( fs . existsSync ( path . join ( compiledPackDir , 'in-pack .ql' ) ) ) . to . be . true ;
100
101
expect ( fs . existsSync ( path . join ( compiledPackDir , 'lib.qll' ) ) ) . to . be . true ;
101
102
expect ( fs . existsSync ( path . join ( compiledPackDir , 'qlpack.yml' ) ) ) . to . be . true ;
102
103
// depending on the cli version, we should have one of these files
@@ -105,6 +106,7 @@ describe('Remote queries', function() {
105
106
fs . existsSync ( path . join ( compiledPackDir , 'codeql-pack.lock.yml' ) )
106
107
) . to . be . true ;
107
108
expect ( fs . existsSync ( path . join ( compiledPackDir , 'not-in-pack.ql' ) ) ) . to . be . false ;
109
+ verifyQlPack ( path . join ( compiledPackDir , 'qlpack.yml' ) , 'in-pack.ql' , '0.0.0' , await pathSerializationBroken ( ) ) ;
108
110
109
111
// dependencies
110
112
const libraryDir = path . join ( compiledPackDir , '.codeql/libraries/codeql' ) ;
@@ -129,8 +131,8 @@ describe('Remote queries', function() {
129
131
130
132
const queryPackDir = path . join ( queryPackRootDir , 'query-pack' ) ;
131
133
printDirectoryContents ( queryPackDir ) ;
132
- // in-pack.ql renamed to query.ql
133
- expect ( fs . existsSync ( path . join ( queryPackDir , 'query .ql' ) ) ) . to . be . true ;
134
+
135
+ expect ( fs . existsSync ( path . join ( queryPackDir , 'in-pack .ql' ) ) ) . to . be . true ;
134
136
expect ( fs . existsSync ( path . join ( queryPackDir , 'qlpack.yml' ) ) ) . to . be . true ;
135
137
// depending on the cli version, we should have one of these files
136
138
expect (
@@ -143,8 +145,10 @@ describe('Remote queries', function() {
143
145
// the compiled pack
144
146
const compiledPackDir = path . join ( queryPackDir , '.codeql/pack/codeql-remote/query/0.0.0/' ) ;
145
147
printDirectoryContents ( compiledPackDir ) ;
146
- expect ( fs . existsSync ( path . join ( compiledPackDir , 'query .ql' ) ) ) . to . be . true ;
148
+ expect ( fs . existsSync ( path . join ( compiledPackDir , 'in-pack .ql' ) ) ) . to . be . true ;
147
149
expect ( fs . existsSync ( path . join ( compiledPackDir , 'qlpack.yml' ) ) ) . to . be . true ;
150
+ verifyQlPack ( path . join ( compiledPackDir , 'qlpack.yml' ) , 'in-pack.ql' , '0.0.0' , await pathSerializationBroken ( ) ) ;
151
+
148
152
// depending on the cli version, we should have one of these files
149
153
expect (
150
154
fs . existsSync ( path . join ( compiledPackDir , 'qlpack.lock.yml' ) ) ||
@@ -165,6 +169,60 @@ describe('Remote queries', function() {
165
169
expect ( packNames ) . to . deep . equal ( [ 'javascript-all' , 'javascript-upgrades' ] ) ;
166
170
} ) ;
167
171
172
+ it ( 'should run a remote query that is nested inside a qlpack' , async ( ) => {
173
+ const fileUri = getFile ( 'data-remote-qlpack-nested/subfolder/in-pack.ql' ) ;
174
+
175
+ const queryPackRootDir = ( await runRemoteQuery ( cli , credentials , fileUri , true , progress , token ) ) ! ;
176
+
177
+ // to retrieve the list of repositories
178
+ expect ( showQuickPickSpy ) . to . have . been . calledOnce ;
179
+
180
+ // check a few files that we know should exist and others that we know should not
181
+
182
+ // the tarball to deliver to the server
183
+ printDirectoryContents ( queryPackRootDir ) ;
184
+ expect ( fs . readdirSync ( queryPackRootDir ) . find ( f => f . startsWith ( 'qlpack-' ) && f . endsWith ( '-generated.tgz' ) ) ) . not . to . be . undefined ;
185
+
186
+ const queryPackDir = path . join ( queryPackRootDir , 'query-pack' ) ;
187
+ printDirectoryContents ( queryPackDir ) ;
188
+
189
+ expect ( fs . existsSync ( path . join ( queryPackDir , 'subfolder/in-pack.ql' ) ) ) . to . be . true ;
190
+ expect ( fs . existsSync ( path . join ( queryPackDir , 'qlpack.yml' ) ) ) . to . be . true ;
191
+ // depending on the cli version, we should have one of these files
192
+ expect (
193
+ fs . existsSync ( path . join ( queryPackDir , 'qlpack.lock.yml' ) ) ||
194
+ fs . existsSync ( path . join ( queryPackDir , 'codeql-pack.lock.yml' ) )
195
+ ) . to . be . true ;
196
+ expect ( fs . existsSync ( path . join ( queryPackDir , 'otherfolder/lib.qll' ) ) ) . to . be . true ;
197
+ expect ( fs . existsSync ( path . join ( queryPackDir , 'not-in-pack.ql' ) ) ) . to . be . false ;
198
+
199
+ // the compiled pack
200
+ const compiledPackDir = path . join ( queryPackDir , '.codeql/pack/github/remote-query-pack/0.0.0/' ) ;
201
+ printDirectoryContents ( compiledPackDir ) ;
202
+ expect ( fs . existsSync ( path . join ( compiledPackDir , 'otherfolder/lib.qll' ) ) ) . to . be . true ;
203
+ expect ( fs . existsSync ( path . join ( compiledPackDir , 'subfolder/in-pack.ql' ) ) ) . to . be . true ;
204
+ expect ( fs . existsSync ( path . join ( compiledPackDir , 'qlpack.yml' ) ) ) . to . be . true ;
205
+ verifyQlPack ( path . join ( compiledPackDir , 'qlpack.yml' ) , 'subfolder/in-pack.ql' , '0.0.0' , await pathSerializationBroken ( ) ) ;
206
+
207
+ // depending on the cli version, we should have one of these files
208
+ expect (
209
+ fs . existsSync ( path . join ( compiledPackDir , 'qlpack.lock.yml' ) ) ||
210
+ fs . existsSync ( path . join ( compiledPackDir , 'codeql-pack.lock.yml' ) )
211
+ ) . to . be . true ;
212
+ expect ( fs . existsSync ( path . join ( compiledPackDir , 'not-in-pack.ql' ) ) ) . to . be . false ;
213
+ // should have generated a correct qlpack file
214
+ const qlpackContents : any = yaml . safeLoad ( fs . readFileSync ( path . join ( compiledPackDir , 'qlpack.yml' ) , 'utf8' ) ) ;
215
+ expect ( qlpackContents . name ) . to . equal ( 'codeql-remote/query' ) ;
216
+ expect ( qlpackContents . version ) . to . equal ( '0.0.0' ) ;
217
+ expect ( qlpackContents . dependencies ?. [ 'codeql/javascript-all' ] ) . to . equal ( '*' ) ;
218
+
219
+ // dependencies
220
+ const libraryDir = path . join ( compiledPackDir , '.codeql/libraries/codeql' ) ;
221
+ printDirectoryContents ( libraryDir ) ;
222
+ const packNames = fs . readdirSync ( libraryDir ) . sort ( ) ;
223
+ expect ( packNames ) . to . deep . equal ( [ 'javascript-all' , 'javascript-upgrades' ] ) ;
224
+ } ) ;
225
+
168
226
it ( 'should cancel a run before uploading' , async ( ) => {
169
227
const fileUri = getFile ( 'data-remote-no-qlpack/in-pack.ql' ) ;
170
228
@@ -180,6 +238,41 @@ describe('Remote queries', function() {
180
238
}
181
239
} ) ;
182
240
241
+ function verifyQlPack ( qlpackPath : string , queryPath : string , packVersion : string , pathSerializationBroken : boolean ) {
242
+ const qlPack = yaml . safeLoad ( fs . readFileSync ( qlpackPath , 'utf8' ) ) as QlPack ;
243
+
244
+ if ( pathSerializationBroken ) {
245
+ // the path serialization is broken, so we force it to be the path in the pack to be same as the query path
246
+ qlPack . defaultSuite ! [ 1 ] . query = queryPath ;
247
+ }
248
+
249
+ // don't check the build metadata since it is variable
250
+ delete ( qlPack as any ) . buildMetadata ;
251
+
252
+ expect ( qlPack ) . to . deep . equal ( {
253
+ name : 'codeql-remote/query' ,
254
+ version : packVersion ,
255
+ dependencies : {
256
+ 'codeql/javascript-all' : '*' ,
257
+ } ,
258
+ library : false ,
259
+ defaultSuite : [ {
260
+ description : 'Query suite for remote query'
261
+ } , {
262
+ query : queryPath
263
+ } ]
264
+ } ) ;
265
+ }
266
+
267
+ /**
268
+ * In version 2.7.2 and earlier, relative paths were not serialized correctly inside the qlpack.yml file.
269
+ * So, ignore part of the test for these versions.
270
+ *
271
+ * @returns true if path serialization is broken in this run
272
+ */
273
+ async function pathSerializationBroken ( ) {
274
+ return lte ( ( await cli . getVersion ( ) ) , '2.7.2' ) && os . platform ( ) === 'win32' ;
275
+ }
183
276
function getFile ( file : string ) : Uri {
184
277
return Uri . file ( path . join ( baseDir , file ) ) ;
185
278
}
0 commit comments