Add tests for distribution updates
This commit is contained in:
@@ -67,7 +67,7 @@ const NIGHTLY_DISTRIBUTION_REPOSITORY_NWO = "dsp-testing/codeql-cli-nightlies";
|
|||||||
*/
|
*/
|
||||||
export const DEFAULT_DISTRIBUTION_VERSION_RANGE: Range = new Range("2.x");
|
export const DEFAULT_DISTRIBUTION_VERSION_RANGE: Range = new Range("2.x");
|
||||||
|
|
||||||
interface DistributionState {
|
export interface DistributionState {
|
||||||
folderIndex: number;
|
folderIndex: number;
|
||||||
release: Release | null;
|
release: Release | null;
|
||||||
}
|
}
|
||||||
@@ -329,10 +329,11 @@ class ExtensionSpecificDistributionManager {
|
|||||||
// If the file doesn't exist, that just means we need to create it
|
// If the file doesn't exist, that just means we need to create it
|
||||||
|
|
||||||
this.distributionState = {
|
this.distributionState = {
|
||||||
folderIndex: this.extensionContext.globalState.get(
|
folderIndex:
|
||||||
"distributionFolderIndex",
|
this.extensionContext.globalState.get(
|
||||||
0,
|
"distributionFolderIndex",
|
||||||
),
|
0,
|
||||||
|
) ?? 0,
|
||||||
release: (this.extensionContext.globalState.get(
|
release: (this.extensionContext.globalState.get(
|
||||||
"distributionRelease",
|
"distributionRelease",
|
||||||
) ?? null) as Release | null,
|
) ?? null) as Release | null,
|
||||||
@@ -647,7 +648,7 @@ class ExtensionSpecificDistributionManager {
|
|||||||
await this.updateState((oldState) => {
|
await this.updateState((oldState) => {
|
||||||
return {
|
return {
|
||||||
...oldState,
|
...oldState,
|
||||||
folderIndex: oldState.folderIndex + 1,
|
folderIndex: (oldState.folderIndex ?? 0) + 1,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,21 @@
|
|||||||
import * as log from "../../../../src/common/logging/notifications";
|
import * as log from "../../../../src/common/logging/notifications";
|
||||||
import { extLogger } from "../../../../src/common/logging/vscode";
|
import { extLogger } from "../../../../src/common/logging/vscode";
|
||||||
import { writeFile } from "fs-extra";
|
import {
|
||||||
|
outputFile,
|
||||||
|
outputJson,
|
||||||
|
readFile,
|
||||||
|
readJson,
|
||||||
|
writeFile,
|
||||||
|
} from "fs-extra";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import * as os from "os";
|
import * as os from "os";
|
||||||
import type { DirectoryResult } from "tmp-promise";
|
import type { DirectoryResult } from "tmp-promise";
|
||||||
import { dir } from "tmp-promise";
|
import { dir } from "tmp-promise";
|
||||||
|
import type { DistributionState } from "../../../../src/codeql-cli/distribution";
|
||||||
import {
|
import {
|
||||||
|
DEFAULT_DISTRIBUTION_VERSION_RANGE,
|
||||||
DistributionManager,
|
DistributionManager,
|
||||||
|
DistributionUpdateCheckResultKind,
|
||||||
getExecutableFromDirectory,
|
getExecutableFromDirectory,
|
||||||
} from "../../../../src/codeql-cli/distribution";
|
} from "../../../../src/codeql-cli/distribution";
|
||||||
import type {
|
import type {
|
||||||
@@ -14,6 +23,19 @@ import type {
|
|||||||
showAndLogWarningMessage,
|
showAndLogWarningMessage,
|
||||||
} from "../../../../src/common/logging";
|
} from "../../../../src/common/logging";
|
||||||
import { createMockLogger } from "../../../__mocks__/loggerMock";
|
import { createMockLogger } from "../../../__mocks__/loggerMock";
|
||||||
|
import { mockedObject } from "../../../mocked-object";
|
||||||
|
import type { DistributionConfig } from "../../../../src/config";
|
||||||
|
import type { ExtensionContext } from "vscode";
|
||||||
|
import { Uri } from "vscode";
|
||||||
|
import { setupServer } from "msw/node";
|
||||||
|
import { http, HttpResponse } from "msw";
|
||||||
|
import {
|
||||||
|
codeQlLauncherName,
|
||||||
|
getRequiredAssetName,
|
||||||
|
} from "../../../../src/common/distribution";
|
||||||
|
import type { GithubRelease } from "../../../../src/codeql-cli/distribution/releases-api-consumer";
|
||||||
|
import type { Release } from "../../../../src/codeql-cli/distribution/release";
|
||||||
|
import { zip } from "zip-a-folder";
|
||||||
|
|
||||||
jest.mock("os", () => {
|
jest.mock("os", () => {
|
||||||
const original = jest.requireActual("os");
|
const original = jest.requireActual("os");
|
||||||
@@ -155,3 +177,344 @@ describe("Launcher path", () => {
|
|||||||
expect(errorSpy).toHaveBeenCalledTimes(1);
|
expect(errorSpy).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Distribution updates", () => {
|
||||||
|
const server = setupServer();
|
||||||
|
beforeAll(() =>
|
||||||
|
server.listen({
|
||||||
|
onUnhandledRequest: "error",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
afterEach(() => server.resetHandlers());
|
||||||
|
afterAll(() => server.close());
|
||||||
|
|
||||||
|
let manager: DistributionManager;
|
||||||
|
|
||||||
|
let globalStorageDirectory: DirectoryResult;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
globalStorageDirectory = await dir({
|
||||||
|
unsafeCleanup: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
manager = new DistributionManager(
|
||||||
|
mockedObject<DistributionConfig>({
|
||||||
|
customCodeQlPath: undefined,
|
||||||
|
channel: "stable",
|
||||||
|
includePrerelease: false,
|
||||||
|
personalAccessToken: undefined,
|
||||||
|
downloadTimeout: 100,
|
||||||
|
onDidChangeConfiguration: () => {},
|
||||||
|
}),
|
||||||
|
DEFAULT_DISTRIBUTION_VERSION_RANGE,
|
||||||
|
mockedObject<ExtensionContext>({
|
||||||
|
globalState: {
|
||||||
|
get: () => {},
|
||||||
|
update: () => {},
|
||||||
|
},
|
||||||
|
globalStorageUri: Uri.file(globalStorageDirectory.path),
|
||||||
|
}),
|
||||||
|
createMockLogger(),
|
||||||
|
);
|
||||||
|
|
||||||
|
await manager.initialize();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await globalStorageDirectory.cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have an empty distribution.json file after initialization", async () => {
|
||||||
|
expect(
|
||||||
|
await readJson(join(globalStorageDirectory.path, "distribution.json")),
|
||||||
|
).toEqual({
|
||||||
|
folderIndex: 0,
|
||||||
|
release: null,
|
||||||
|
} satisfies DistributionState);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("checkForUpdatesToDistribution", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
server.resetHandlers(
|
||||||
|
http.get(
|
||||||
|
"https://api.github.com/repos/github/codeql-cli-binaries/releases",
|
||||||
|
async () => {
|
||||||
|
return HttpResponse.json([
|
||||||
|
{
|
||||||
|
id: 1335,
|
||||||
|
name: "v2.2.0",
|
||||||
|
tag_name: "v2.2.0",
|
||||||
|
created_at: "2024-02-02T02:02:02Z",
|
||||||
|
prerelease: false,
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
id: 783,
|
||||||
|
name: getRequiredAssetName(),
|
||||||
|
size: 2378,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "v2.1.0",
|
||||||
|
tag_name: "v2.1.0",
|
||||||
|
created_at: "2022-02-02T02:02:02Z",
|
||||||
|
prerelease: false,
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: getRequiredAssetName(),
|
||||||
|
size: 100,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] satisfies GithubRelease[]);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have an update when no distribution is installed", async () => {
|
||||||
|
expect(
|
||||||
|
await manager.checkForUpdatesToExtensionManagedDistribution(0),
|
||||||
|
).toEqual({
|
||||||
|
kind: DistributionUpdateCheckResultKind.UpdateAvailable,
|
||||||
|
updatedRelease: {
|
||||||
|
id: 1335,
|
||||||
|
name: "v2.2.0",
|
||||||
|
createdAt: "2024-02-02T02:02:02Z",
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
id: 783,
|
||||||
|
name: getRequiredAssetName(),
|
||||||
|
size: 2378,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
} satisfies Awaited<
|
||||||
|
ReturnType<typeof manager.checkForUpdatesToExtensionManagedDistribution>
|
||||||
|
>);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not have an update when the latest distribution is installed", async () => {
|
||||||
|
await outputJson(join(globalStorageDirectory.path, "distribution.json"), {
|
||||||
|
folderIndex: 1,
|
||||||
|
release: {
|
||||||
|
id: 1335,
|
||||||
|
name: "v2.2.0",
|
||||||
|
createdAt: "2024-02-02T02:02:02Z",
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
id: 783,
|
||||||
|
name: getRequiredAssetName(),
|
||||||
|
size: 2378,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
} satisfies DistributionState);
|
||||||
|
await outputFile(
|
||||||
|
join(
|
||||||
|
globalStorageDirectory.path,
|
||||||
|
"distribution1",
|
||||||
|
"codeql",
|
||||||
|
codeQlLauncherName(),
|
||||||
|
),
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Re-initialize manager to read the state from the file
|
||||||
|
await manager.initialize();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await manager.checkForUpdatesToExtensionManagedDistribution(0),
|
||||||
|
).toEqual({
|
||||||
|
kind: DistributionUpdateCheckResultKind.AlreadyUpToDate,
|
||||||
|
} satisfies Awaited<
|
||||||
|
ReturnType<typeof manager.checkForUpdatesToExtensionManagedDistribution>
|
||||||
|
>);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have an update when an older distribution is installed", async () => {
|
||||||
|
await outputJson(join(globalStorageDirectory.path, "distribution.json"), {
|
||||||
|
folderIndex: 1,
|
||||||
|
release: {
|
||||||
|
id: 1,
|
||||||
|
name: "v2.1.0",
|
||||||
|
createdAt: "2022-02-02T02:02:02Z",
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: getRequiredAssetName(),
|
||||||
|
size: 100,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
} satisfies DistributionState);
|
||||||
|
await outputFile(
|
||||||
|
join(
|
||||||
|
globalStorageDirectory.path,
|
||||||
|
"distribution1",
|
||||||
|
"codeql",
|
||||||
|
codeQlLauncherName(),
|
||||||
|
),
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Re-initialize manager to read the state from the file
|
||||||
|
await manager.initialize();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await manager.checkForUpdatesToExtensionManagedDistribution(0),
|
||||||
|
).toEqual({
|
||||||
|
kind: DistributionUpdateCheckResultKind.UpdateAvailable,
|
||||||
|
updatedRelease: {
|
||||||
|
id: 1335,
|
||||||
|
name: "v2.2.0",
|
||||||
|
createdAt: "2024-02-02T02:02:02Z",
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
id: 783,
|
||||||
|
name: getRequiredAssetName(),
|
||||||
|
size: 2378,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
} satisfies Awaited<
|
||||||
|
ReturnType<typeof manager.checkForUpdatesToExtensionManagedDistribution>
|
||||||
|
>);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("installExtensionManagedDistributionRelease", () => {
|
||||||
|
const release: Release = {
|
||||||
|
id: 1335,
|
||||||
|
name: "v2.2.0",
|
||||||
|
createdAt: "2024-02-02T02:02:02Z",
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
id: 783,
|
||||||
|
name: getRequiredAssetName(),
|
||||||
|
size: 2378,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
let codeqlReleaseZipTempDir: DirectoryResult;
|
||||||
|
let codeqlReleaseZipPath: string;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
codeqlReleaseZipTempDir = await dir({
|
||||||
|
unsafeCleanup: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await outputFile(
|
||||||
|
join(
|
||||||
|
codeqlReleaseZipTempDir.path,
|
||||||
|
"distribution",
|
||||||
|
"codeql",
|
||||||
|
codeQlLauncherName(),
|
||||||
|
),
|
||||||
|
"launcher!",
|
||||||
|
);
|
||||||
|
codeqlReleaseZipPath = join(codeqlReleaseZipTempDir.path, "codeql.zip");
|
||||||
|
|
||||||
|
await zip(
|
||||||
|
join(codeqlReleaseZipTempDir.path, "distribution"),
|
||||||
|
codeqlReleaseZipPath,
|
||||||
|
);
|
||||||
|
|
||||||
|
server.resetHandlers(
|
||||||
|
http.get(
|
||||||
|
"https://api.github.com/repos/github/codeql-cli-binaries/releases/assets/783",
|
||||||
|
async () => {
|
||||||
|
const file = await readFile(codeqlReleaseZipPath);
|
||||||
|
|
||||||
|
return HttpResponse.arrayBuffer(file, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/octet-stream",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await codeqlReleaseZipTempDir?.cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs a distribution when no distribution exists", async () => {
|
||||||
|
await manager.installExtensionManagedDistributionRelease(release);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await readJson(join(globalStorageDirectory.path, "distribution.json")),
|
||||||
|
).toEqual({
|
||||||
|
folderIndex: 1,
|
||||||
|
release,
|
||||||
|
} satisfies DistributionState);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await readFile(
|
||||||
|
join(
|
||||||
|
globalStorageDirectory.path,
|
||||||
|
"distribution1",
|
||||||
|
"codeql",
|
||||||
|
codeQlLauncherName(),
|
||||||
|
),
|
||||||
|
"utf-8",
|
||||||
|
),
|
||||||
|
).toEqual("launcher!");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs a distribution when a distribution already exists", async () => {
|
||||||
|
await outputJson(join(globalStorageDirectory.path, "distribution.json"), {
|
||||||
|
folderIndex: 78,
|
||||||
|
release: {
|
||||||
|
id: 1,
|
||||||
|
name: "v2.1.0",
|
||||||
|
createdAt: "2022-02-02T02:02:02Z",
|
||||||
|
assets: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: getRequiredAssetName(),
|
||||||
|
size: 100,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
} satisfies DistributionState);
|
||||||
|
await outputFile(
|
||||||
|
join(
|
||||||
|
globalStorageDirectory.path,
|
||||||
|
"distribution78",
|
||||||
|
"codeql",
|
||||||
|
codeQlLauncherName(),
|
||||||
|
),
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Re-initialize manager to read the state from the file
|
||||||
|
await manager.initialize();
|
||||||
|
|
||||||
|
await manager.installExtensionManagedDistributionRelease(release);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await readJson(join(globalStorageDirectory.path, "distribution.json")),
|
||||||
|
).toEqual({
|
||||||
|
folderIndex: 79,
|
||||||
|
release,
|
||||||
|
} satisfies DistributionState);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await readFile(
|
||||||
|
join(
|
||||||
|
globalStorageDirectory.path,
|
||||||
|
"distribution79",
|
||||||
|
"codeql",
|
||||||
|
codeQlLauncherName(),
|
||||||
|
),
|
||||||
|
"utf-8",
|
||||||
|
),
|
||||||
|
).toEqual("launcher!");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user