Skip to content

Commit 830e918

Browse files
Work on tests for new behavior
1 parent 82e78ed commit 830e918

6 files changed

Lines changed: 197 additions & 57 deletions

File tree

extensions/ql-vscode/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -969,8 +969,8 @@
969969
"react": "^16.8.6",
970970
"react-dom": "^16.8.6",
971971
"semver": "~7.3.2",
972-
"stream-chain": "^2.2.4",
973-
"stream-json": "^1.7.3",
972+
"stream-chain": "~2.2.4",
973+
"stream-json": "~1.7.3",
974974
"tmp": "^0.1.0",
975975
"tmp-promise": "~3.0.2",
976976
"tree-kill": "~1.2.2",
@@ -1005,8 +1005,8 @@
10051005
"@types/semver": "~7.2.0",
10061006
"@types/sinon": "~7.5.2",
10071007
"@types/sinon-chai": "~3.2.3",
1008-
"@types/stream-chain": "^2.0.1",
1009-
"@types/stream-json": "^1.7.1",
1008+
"@types/stream-chain": "~2.0.1",
1009+
"@types/stream-json": "~1.7.1",
10101010
"@types/through2": "^2.0.36",
10111011
"@types/tmp": "^0.1.0",
10121012
"@types/unzipper": "~0.10.1",

extensions/ql-vscode/src/cli.ts

Lines changed: 44 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const CSV_FORMAT = 'csv';
3838
*/
3939
const LOGGING_FLAGS = ['-v', '--log-to-stderr'];
4040

41+
const DUMMY_TOOL : sarif.Tool = {driver: {name: ''}};
42+
4143
/**
4244
* The expected output of `codeql resolve library-path`.
4345
*/
@@ -568,6 +570,47 @@ export class CodeQLCliServer implements Disposable {
568570
}
569571
}
570572

573+
static async parseSarif(interpretedResultsPath: string) : Promise<sarif.Log> {
574+
try {
575+
// Parse the SARIF file into token streams, filtering out only the results array.
576+
const p = parser();
577+
const pipeline = chain([
578+
fs.createReadStream(interpretedResultsPath),
579+
p,
580+
pick({filter: 'runs.0.results'}),
581+
verifier()
582+
]);
583+
584+
// Creates JavaScript objects from the token stream
585+
const asm = Assembler.connectTo(pipeline);
586+
587+
// Returns a constructed Log object with the results or an empty array if no results were found.
588+
// If the parser fails for any reason, it will reject the promise.
589+
return await new Promise((resolve, reject) => {
590+
pipeline.on('error', (error) => {
591+
reject(error);
592+
});
593+
594+
asm.on('done', (asm) => {
595+
596+
const log : sarif.Log = {
597+
version: '2.1.0',
598+
runs: [
599+
{
600+
tool: DUMMY_TOOL,
601+
results: asm.current ?? []
602+
}
603+
]
604+
};
605+
606+
resolve(log);
607+
});
608+
});
609+
} catch (err) {
610+
throw new Error(`Parsing output of interpretation failed: ${err.stderr || err}`);
611+
}
612+
}
613+
571614
/**
572615
* Gets the metadata for a query.
573616
* @param queryPath The path to the query.
@@ -674,59 +717,7 @@ export class CodeQLCliServer implements Disposable {
674717

675718
async interpretBqrs(metadata: QueryMetadata, resultsPath: string, interpretedResultsPath: string, sourceInfo?: SourceInfo): Promise<sarif.Log> {
676719
await this.runInterpretCommand(SARIF_FORMAT, metadata, resultsPath, interpretedResultsPath, sourceInfo);
677-
try {
678-
// Parse the SARIF file into token streams, filtering out only the results array.
679-
const p = parser();
680-
const pipeline = chain([
681-
fs.createReadStream(interpretedResultsPath),
682-
p,
683-
pick({filter: 'runs.0.results'}),
684-
verifier()
685-
]);
686-
687-
// Creates JavaScript objects from the token stream
688-
const asm = Assembler.connectTo(pipeline);
689-
690-
// Returns a constructed Log object with the results or an empty array if no results were found.
691-
// If the parser fails for any reason, it will reject the promise.
692-
return await new Promise((resolve, reject) => {
693-
pipeline.on('error', (error) => {
694-
reject(error);
695-
});
696-
697-
asm.on('done', (asm) => {
698-
const dummyTool : sarif.Tool = {driver: {name: ''}};
699-
if (asm.current) {
700-
const log : sarif.Log = {
701-
version: '2.1.0',
702-
runs: [
703-
{
704-
tool: dummyTool,
705-
results: asm.current
706-
}
707-
]
708-
};
709-
710-
resolve(log);
711-
} else {
712-
const log : sarif.Log = {
713-
version: '2.1.0',
714-
runs: [
715-
{
716-
tool: dummyTool,
717-
results: []
718-
}
719-
]
720-
};
721-
722-
resolve(log);
723-
}
724-
725-
});
726-
});
727-
} catch (err) {
728-
throw new Error(`Parsing output of interpretation failed: ${err.stderr || err}`);
729-
}
720+
return await CodeQLCliServer.parseSarif(interpretedResultsPath);
730721
}
731722

732723
async generateResultsCsv(metadata: QueryMetadata, resultsPath: string, csvPath: string, sourceInfo?: SourceInfo): Promise<void> {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import * as chai from 'chai';
2+
import * as chaiAsPromised from 'chai-as-promised';
3+
4+
import { CodeQLCliServer } from '../../cli';
5+
6+
chai.use(chaiAsPromised);
7+
const expect = chai.expect;
8+
9+
describe.only('cliServerTests', () => {
10+
it('should parse a valid SARIF file', async () => {
11+
const result = await CodeQLCliServer.parseSarif(__dirname + '/data/sarif/validSarif.sarif');
12+
expect(result.runs.length).to.eq(1);
13+
});
14+
15+
it('should return an empty array if there are no results', async () => {
16+
const result = await CodeQLCliServer.parseSarif(__dirname + '/data/sarif/emptyResultsSarif.sarif');
17+
expect(result.runs[0].results?.length).to.eq(0);
18+
});
19+
20+
it('should throw an error if the file fails to parse', async () => {
21+
const result = await CodeQLCliServer.parseSarif(__dirname + '/data/sarif/invalidSarif.sarif');
22+
await expect(result).to.rejectedWith(/Error: Parsing output of interpretation failed: /);
23+
});
24+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"version": "2.1.0",
3+
"$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4",
4+
"runs": [
5+
{
6+
"tool": {
7+
"driver": {
8+
"name": "ESLint",
9+
"informationUri": "https://eslint.org",
10+
"rules": [
11+
{
12+
"id": "no-unused-vars",
13+
"shortDescription": {
14+
"text": "disallow unused variables"
15+
},
16+
"helpUri": "https://eslint.org/docs/rules/no-unused-vars",
17+
"properties": {
18+
"category": "Variables"
19+
}
20+
}
21+
]
22+
}
23+
},
24+
"artifacts": [
25+
{
26+
"location": {
27+
"uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js"
28+
}
29+
}
30+
],
31+
"results": [],
32+
]
33+
}
34+
]
35+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"version": "2.1.0",
3+
"$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4",
4+
"runs": [
5+
{
6+
"tool": {
7+
"driver": {
8+
"name": "ESLint",
9+
"informationUri": "https://eslint.org",
10+
"rules": [
11+
{
12+
"id": "no-unused-vars",
13+
"shortDescription": {
14+
"text": "disallow unused variables"
15+
},
16+
"helpUri": "https://eslint.org/docs/rules/no-unused-vars",
17+
"properties": {
18+
"category": "Variables"
19+
}
20+
}
21+
]
22+
}
23+
},
24+
"artifacts": [
25+
{
26+
"location": {
27+
"uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js"
28+
}
29+
}
30+
],
31+
}
32+
]
33+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"version": "2.1.0",
3+
"$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4",
4+
"runs": [
5+
{
6+
"tool": {
7+
"driver": {
8+
"name": "ESLint",
9+
"informationUri": "https://eslint.org",
10+
"rules": [
11+
{
12+
"id": "no-unused-vars",
13+
"shortDescription": {
14+
"text": "disallow unused variables"
15+
},
16+
"helpUri": "https://eslint.org/docs/rules/no-unused-vars",
17+
"properties": {
18+
"category": "Variables"
19+
}
20+
}
21+
]
22+
}
23+
},
24+
"artifacts": [
25+
{
26+
"location": {
27+
"uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js"
28+
}
29+
}
30+
],
31+
"results": [
32+
{
33+
"level": "error",
34+
"message": {
35+
"text": "'x' is assigned a value but never used."
36+
},
37+
"locations": [
38+
{
39+
"physicalLocation": {
40+
"artifactLocation": {
41+
"uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js",
42+
"index": 0
43+
},
44+
"region": {
45+
"startLine": 1,
46+
"startColumn": 5
47+
}
48+
}
49+
}
50+
],
51+
"ruleId": "no-unused-vars",
52+
"ruleIndex": 0
53+
}
54+
]
55+
}
56+
]
57+
}

0 commit comments

Comments
 (0)