mirror of
https://github.com/github/codeql-action.git
synced 2025-12-31 19:50:32 +08:00
387 lines
7.9 KiB
TypeScript
387 lines
7.9 KiB
TypeScript
import test, { ExecutionContext } from "ava";
|
|
import * as sinon from "sinon";
|
|
|
|
import * as actionsUtil from "./actions-util";
|
|
import type { PullRequestBranches } from "./actions-util";
|
|
import * as apiClient from "./api-client";
|
|
import {
|
|
shouldPerformDiffInformedAnalysis,
|
|
exportedForTesting,
|
|
} from "./diff-informed-analysis-utils";
|
|
import { Feature, Features } from "./feature-flags";
|
|
import { getRunnerLogger } from "./logging";
|
|
import { parseRepositoryNwo } from "./repository";
|
|
import {
|
|
setupTests,
|
|
mockCodeQLVersion,
|
|
mockFeatureFlagApiEndpoint,
|
|
setupActionsVars,
|
|
} from "./testing-utils";
|
|
import { GitHubVariant, withTmpDir } from "./util";
|
|
import type { GitHubVersion } from "./util";
|
|
|
|
setupTests(test);
|
|
|
|
interface DiffInformedAnalysisTestCase {
|
|
featureEnabled: boolean;
|
|
gitHubVersion: GitHubVersion;
|
|
pullRequestBranches: PullRequestBranches;
|
|
codeQLVersion: string;
|
|
diffInformedQueriesEnvVar?: boolean;
|
|
}
|
|
|
|
const defaultTestCase: DiffInformedAnalysisTestCase = {
|
|
featureEnabled: true,
|
|
gitHubVersion: {
|
|
type: GitHubVariant.DOTCOM,
|
|
},
|
|
pullRequestBranches: {
|
|
base: "main",
|
|
head: "feature-branch",
|
|
},
|
|
codeQLVersion: "2.21.0",
|
|
};
|
|
|
|
const testShouldPerformDiffInformedAnalysis = test.macro({
|
|
exec: async (
|
|
t: ExecutionContext,
|
|
_title: string,
|
|
partialTestCase: Partial<DiffInformedAnalysisTestCase>,
|
|
expectedResult: boolean,
|
|
) => {
|
|
return await withTmpDir(async (tmpDir) => {
|
|
setupActionsVars(tmpDir, tmpDir);
|
|
|
|
const testCase = { ...defaultTestCase, ...partialTestCase };
|
|
const logger = getRunnerLogger(true);
|
|
const codeql = mockCodeQLVersion(testCase.codeQLVersion);
|
|
|
|
if (testCase.diffInformedQueriesEnvVar !== undefined) {
|
|
process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES =
|
|
testCase.diffInformedQueriesEnvVar.toString();
|
|
} else {
|
|
delete process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES;
|
|
}
|
|
|
|
const features = new Features(
|
|
testCase.gitHubVersion,
|
|
parseRepositoryNwo("github/example"),
|
|
tmpDir,
|
|
logger,
|
|
);
|
|
mockFeatureFlagApiEndpoint(200, {
|
|
[Feature.DiffInformedQueries]: testCase.featureEnabled,
|
|
});
|
|
|
|
const getGitHubVersionStub = sinon
|
|
.stub(apiClient, "getGitHubVersion")
|
|
.resolves(testCase.gitHubVersion);
|
|
const getPullRequestBranchesStub = sinon
|
|
.stub(actionsUtil, "getPullRequestBranches")
|
|
.returns(testCase.pullRequestBranches);
|
|
|
|
const result = await shouldPerformDiffInformedAnalysis(
|
|
codeql,
|
|
features,
|
|
logger,
|
|
);
|
|
|
|
t.is(result, expectedResult);
|
|
|
|
delete process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES;
|
|
|
|
getGitHubVersionStub.restore();
|
|
getPullRequestBranchesStub.restore();
|
|
});
|
|
},
|
|
title: (_, title) => `shouldPerformDiffInformedAnalysis: ${title}`,
|
|
});
|
|
|
|
test(
|
|
testShouldPerformDiffInformedAnalysis,
|
|
"returns true in the default test case",
|
|
{},
|
|
true,
|
|
);
|
|
|
|
test(
|
|
testShouldPerformDiffInformedAnalysis,
|
|
"returns false when feature flag is disabled from the API",
|
|
{
|
|
featureEnabled: false,
|
|
},
|
|
false,
|
|
);
|
|
|
|
test(
|
|
testShouldPerformDiffInformedAnalysis,
|
|
"returns false when CODEQL_ACTION_DIFF_INFORMED_QUERIES is set to false",
|
|
{
|
|
featureEnabled: true,
|
|
diffInformedQueriesEnvVar: false,
|
|
},
|
|
false,
|
|
);
|
|
|
|
test(
|
|
testShouldPerformDiffInformedAnalysis,
|
|
"returns true when CODEQL_ACTION_DIFF_INFORMED_QUERIES is set to true",
|
|
{
|
|
featureEnabled: false,
|
|
diffInformedQueriesEnvVar: true,
|
|
},
|
|
true,
|
|
);
|
|
|
|
test(
|
|
testShouldPerformDiffInformedAnalysis,
|
|
"returns false for CodeQL version 2.20.0",
|
|
{
|
|
codeQLVersion: "2.20.0",
|
|
},
|
|
false,
|
|
);
|
|
|
|
test(
|
|
testShouldPerformDiffInformedAnalysis,
|
|
"returns false for invalid GHES version",
|
|
{
|
|
gitHubVersion: {
|
|
type: GitHubVariant.GHES,
|
|
version: "invalid-version",
|
|
},
|
|
},
|
|
false,
|
|
);
|
|
|
|
test(
|
|
testShouldPerformDiffInformedAnalysis,
|
|
"returns false for GHES version 3.18.5",
|
|
{
|
|
gitHubVersion: {
|
|
type: GitHubVariant.GHES,
|
|
version: "3.18.5",
|
|
},
|
|
},
|
|
false,
|
|
);
|
|
|
|
test(
|
|
testShouldPerformDiffInformedAnalysis,
|
|
"returns true for GHES version 3.19.0",
|
|
{
|
|
gitHubVersion: {
|
|
type: GitHubVariant.GHES,
|
|
version: "3.19.0",
|
|
},
|
|
},
|
|
true,
|
|
);
|
|
|
|
test(
|
|
testShouldPerformDiffInformedAnalysis,
|
|
"returns false when not a pull request",
|
|
{
|
|
pullRequestBranches: undefined,
|
|
},
|
|
false,
|
|
);
|
|
|
|
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);
|
|
});
|