mirror of
https://github.com/github/codeql-action.git
synced 2025-12-27 09:40:17 +08:00
When a user specifies "cleanup-level: overlay", it suggests that the user wishes to preserve the evaluation cache for future use. So in this case we should not set --expect-discarded-cache when running queries.
323 lines
7.2 KiB
TypeScript
323 lines
7.2 KiB
TypeScript
import * as fs from "fs";
|
|
import * as path from "path";
|
|
|
|
import test from "ava";
|
|
import * as sinon from "sinon";
|
|
|
|
import * as actionsUtil from "./actions-util";
|
|
import { exportedForTesting, runQueries } from "./analyze";
|
|
import { setCodeQL } from "./codeql";
|
|
import { Feature } from "./feature-flags";
|
|
import { Language } from "./languages";
|
|
import { getRunnerLogger } from "./logging";
|
|
import {
|
|
setupTests,
|
|
setupActionsVars,
|
|
createFeatures,
|
|
createTestConfig,
|
|
} from "./testing-utils";
|
|
import * as uploadLib from "./upload-lib";
|
|
import * as util from "./util";
|
|
|
|
setupTests(test);
|
|
|
|
/**
|
|
* Checks the status report produced by the analyze Action.
|
|
*
|
|
* - Checks that the duration fields are populated for the correct language.
|
|
* - Checks that the QA telemetry status report fields are populated when the QA feature flag is enabled.
|
|
*/
|
|
test("status report fields", async (t) => {
|
|
return await util.withTmpDir(async (tmpDir) => {
|
|
setupActionsVars(tmpDir, tmpDir);
|
|
|
|
const memoryFlag = "";
|
|
const addSnippetsFlag = "";
|
|
const threadsFlag = "";
|
|
sinon.stub(uploadLib, "validateSarifFileSchema");
|
|
|
|
for (const language of Object.values(Language)) {
|
|
setCodeQL({
|
|
databaseRunQueries: async () => {},
|
|
packDownload: async () => ({ packs: [] }),
|
|
databaseInterpretResults: async (
|
|
_db: string,
|
|
_queriesRun: string[],
|
|
sarifFile: string,
|
|
) => {
|
|
fs.writeFileSync(
|
|
sarifFile,
|
|
JSON.stringify({
|
|
runs: [
|
|
// references a rule with the lines-of-code tag, so baseline should be injected
|
|
{
|
|
tool: {
|
|
extensions: [
|
|
{
|
|
rules: [
|
|
{
|
|
properties: {
|
|
tags: ["lines-of-code"],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
properties: {
|
|
metricResults: [
|
|
{
|
|
rule: {
|
|
index: 0,
|
|
toolComponent: {
|
|
index: 0,
|
|
},
|
|
},
|
|
value: 123,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{},
|
|
],
|
|
}),
|
|
);
|
|
return "";
|
|
},
|
|
databasePrintBaseline: async () => "",
|
|
});
|
|
|
|
const config = createTestConfig({
|
|
languages: [language],
|
|
tempDir: tmpDir,
|
|
dbLocation: path.resolve(tmpDir, "codeql_databases"),
|
|
});
|
|
fs.mkdirSync(util.getCodeQLDatabasePath(config, language), {
|
|
recursive: true,
|
|
});
|
|
|
|
const statusReport = await runQueries(
|
|
tmpDir,
|
|
memoryFlag,
|
|
addSnippetsFlag,
|
|
threadsFlag,
|
|
"brutal",
|
|
undefined,
|
|
undefined,
|
|
config,
|
|
getRunnerLogger(true),
|
|
createFeatures([Feature.QaTelemetryEnabled]),
|
|
);
|
|
t.deepEqual(Object.keys(statusReport).sort(), [
|
|
"analysis_is_diff_informed",
|
|
`analyze_builtin_queries_${language}_duration_ms`,
|
|
"event_reports",
|
|
`interpret_results_${language}_duration_ms`,
|
|
]);
|
|
for (const eventReport of statusReport.event_reports!) {
|
|
t.deepEqual(eventReport.event, "codeql database interpret-results");
|
|
t.true("properties" in eventReport);
|
|
t.true("alertCounts" in eventReport.properties!);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
function runGetDiffRanges(changes: number, patch: string[] | undefined): any {
|
|
sinon
|
|
.stub(actionsUtil, "getRequiredInput")
|
|
.withArgs("checkout_path")
|
|
.returns("/checkout/path");
|
|
return exportedForTesting.getDiffRanges(
|
|
{
|
|
filename: "test.txt",
|
|
changes,
|
|
patch: patch?.join("\n"),
|
|
},
|
|
getRunnerLogger(true),
|
|
);
|
|
}
|
|
|
|
test("getDiffRanges: file unchanged", async (t) => {
|
|
const diffRanges = runGetDiffRanges(0, undefined);
|
|
t.deepEqual(diffRanges, []);
|
|
});
|
|
|
|
test("getDiffRanges: file diff too large", async (t) => {
|
|
const diffRanges = runGetDiffRanges(1000000, undefined);
|
|
t.deepEqual(diffRanges, [
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 0,
|
|
endLine: 0,
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("getDiffRanges: diff thunk with single addition range", async (t) => {
|
|
const diffRanges = runGetDiffRanges(2, [
|
|
"@@ -30,6 +50,8 @@",
|
|
" a",
|
|
" b",
|
|
" c",
|
|
"+1",
|
|
"+2",
|
|
" d",
|
|
" e",
|
|
" f",
|
|
]);
|
|
t.deepEqual(diffRanges, [
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 53,
|
|
endLine: 54,
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("getDiffRanges: diff thunk with single deletion range", async (t) => {
|
|
const diffRanges = runGetDiffRanges(2, [
|
|
"@@ -30,8 +50,6 @@",
|
|
" a",
|
|
" b",
|
|
" c",
|
|
"-1",
|
|
"-2",
|
|
" d",
|
|
" e",
|
|
" f",
|
|
]);
|
|
t.deepEqual(diffRanges, []);
|
|
});
|
|
|
|
test("getDiffRanges: diff thunk with single update range", async (t) => {
|
|
const diffRanges = runGetDiffRanges(2, [
|
|
"@@ -30,7 +50,7 @@",
|
|
" a",
|
|
" b",
|
|
" c",
|
|
"-1",
|
|
"+2",
|
|
" d",
|
|
" e",
|
|
" f",
|
|
]);
|
|
t.deepEqual(diffRanges, [
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 53,
|
|
endLine: 53,
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("getDiffRanges: diff thunk with addition ranges", async (t) => {
|
|
const diffRanges = runGetDiffRanges(2, [
|
|
"@@ -30,7 +50,9 @@",
|
|
" a",
|
|
" b",
|
|
" c",
|
|
"+1",
|
|
" c",
|
|
"+2",
|
|
" d",
|
|
" e",
|
|
" f",
|
|
]);
|
|
t.deepEqual(diffRanges, [
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 53,
|
|
endLine: 53,
|
|
},
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 55,
|
|
endLine: 55,
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("getDiffRanges: diff thunk with mixed ranges", async (t) => {
|
|
const diffRanges = runGetDiffRanges(2, [
|
|
"@@ -30,7 +50,7 @@",
|
|
" a",
|
|
" b",
|
|
" c",
|
|
"-1",
|
|
" d",
|
|
"-2",
|
|
"+3",
|
|
" e",
|
|
" f",
|
|
"+4",
|
|
"+5",
|
|
" g",
|
|
" h",
|
|
" i",
|
|
]);
|
|
t.deepEqual(diffRanges, [
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 54,
|
|
endLine: 54,
|
|
},
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 57,
|
|
endLine: 58,
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("getDiffRanges: multiple diff thunks", async (t) => {
|
|
const diffRanges = runGetDiffRanges(2, [
|
|
"@@ -30,6 +50,8 @@",
|
|
" a",
|
|
" b",
|
|
" c",
|
|
"+1",
|
|
"+2",
|
|
" d",
|
|
" e",
|
|
" f",
|
|
"@@ -130,6 +150,8 @@",
|
|
" a",
|
|
" b",
|
|
" c",
|
|
"+1",
|
|
"+2",
|
|
" d",
|
|
" e",
|
|
" f",
|
|
]);
|
|
t.deepEqual(diffRanges, [
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 53,
|
|
endLine: 54,
|
|
},
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 153,
|
|
endLine: 154,
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("getDiffRanges: no diff context lines", async (t) => {
|
|
const diffRanges = runGetDiffRanges(2, ["@@ -30 +50,2 @@", "+1", "+2"]);
|
|
t.deepEqual(diffRanges, [
|
|
{
|
|
path: "/checkout/path/test.txt",
|
|
startLine: 50,
|
|
endLine: 51,
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("getDiffRanges: malformed thunk header", async (t) => {
|
|
const diffRanges = runGetDiffRanges(2, ["@@ 30 +50,2 @@", "+1", "+2"]);
|
|
t.deepEqual(diffRanges, undefined);
|
|
});
|