/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------------------------------------------*/
import assert from "node:assert/strict";
import { createHash } from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
import {
createNativeClassifierTestFixture,
writeStoredZip,
} from "./create-native-classifier-test-fixture.mjs";
import {
validateNativeClassifierJar,
validatePlaceholderJar,
validateSha256Manifest,
} from "./validate-native-artifact.mjs";
import { validateLocalPublication } from "./validate-local-publication.mjs";
const classifier = "win32-x64";
const artifactName = "copilot-sdk-java-runtime-1.2.3-win32-x64.jar";
const moduleRoot = fileURLToPath(new URL("../", import.meta.url));
test("accepts a matching, complete Windows classifier", (t) => {
const fixture = createFixture(t);
createNativeClassifierTestFixture({
classifier,
outputPath: fixture.jarPath,
repoRoot: fixture.repoRoot,
});
assert.deepEqual(
validateNativeClassifierJar({
classifier,
jarPath: fixture.jarPath,
expectedFilename: artifactName,
repoRoot: fixture.repoRoot,
}),
{ classifier, nativeVersion: "9.8.7", sha256: undefined },
);
});
test("accepts a matching, complete Windows ARM64 classifier", (t) => {
const fixture = createFixture(t);
const windowsArm64Classifier = "win32-arm64";
const windowsArm64ArtifactName =
"copilot-sdk-java-runtime-1.2.3-win32-arm64.jar";
const windowsArm64JarPath = path.join(
fixture.root,
windowsArm64ArtifactName,
);
createNativeClassifierTestFixture({
classifier: windowsArm64Classifier,
outputPath: windowsArm64JarPath,
repoRoot: fixture.repoRoot,
});
assert.deepEqual(
validateNativeClassifierJar({
classifier: windowsArm64Classifier,
jarPath: windowsArm64JarPath,
expectedFilename: windowsArm64ArtifactName,
repoRoot: fixture.repoRoot,
}),
{
classifier: windowsArm64Classifier,
nativeVersion: "9.8.7",
sha256: undefined,
},
);
});
test("accepts a matching, complete Darwin classifier", (t) => {
const fixture = createFixture(t);
const darwinClassifier = "darwin-arm64";
const darwinArtifactName =
"copilot-sdk-java-runtime-1.2.3-darwin-arm64.jar";
const darwinJarPath = path.join(fixture.root, darwinArtifactName);
createNativeClassifierTestFixture({
classifier: darwinClassifier,
outputPath: darwinJarPath,
repoRoot: fixture.repoRoot,
});
assert.deepEqual(
validateNativeClassifierJar({
classifier: darwinClassifier,
jarPath: darwinJarPath,
expectedFilename: darwinArtifactName,
repoRoot: fixture.repoRoot,
}),
{
classifier: darwinClassifier,
nativeVersion: "9.8.7",
sha256: undefined,
},
);
});
test("accepts a matching, complete Linux ARM64 classifier", (t) => {
const fixture = createFixture(t);
const linuxArm64Classifier = "linux-arm64";
const linuxArm64ArtifactName =
"copilot-sdk-java-runtime-1.2.3-linux-arm64.jar";
const linuxArm64JarPath = path.join(fixture.root, linuxArm64ArtifactName);
createNativeClassifierTestFixture({
classifier: linuxArm64Classifier,
outputPath: linuxArm64JarPath,
repoRoot: fixture.repoRoot,
});
assert.deepEqual(
validateNativeClassifierJar({
classifier: linuxArm64Classifier,
jarPath: linuxArm64JarPath,
expectedFilename: linuxArm64ArtifactName,
repoRoot: fixture.repoRoot,
}),
{
classifier: linuxArm64Classifier,
nativeVersion: "9.8.7",
sha256: undefined,
},
);
});
test("rejects a wrong external filename before attachment", (t) => {
const fixture = createFixture(t);
const wrongName = path.join(fixture.root, "arbitrary.jar");
createNativeClassifierTestFixture({
classifier,
outputPath: wrongName,
repoRoot: fixture.repoRoot,
});
assert.throws(
() =>
validateNativeClassifierJar({
classifier,
jarPath: wrongName,
expectedFilename: artifactName,
repoRoot: fixture.repoRoot,
}),
/must be named/,
);
});
test("rejects a missing classifier JAR with the expected filename", (t) => {
const fixture = createFixture(t);
assert.throws(
() =>
validateNativeClassifierJar({
classifier,
jarPath: fixture.jarPath,
expectedFilename: artifactName,
repoRoot: fixture.repoRoot,
}),
/does not exist/,
);
});
test("rejects missing native resources", (t) => {
const fixture = createFixture(t);
writeStoredZip(fixture.jarPath, [
["native/win32-x64/runtime.node", "runtime"],
[
"native/win32-x64/platform.properties",
"classifier=win32-x64\nversion=9.8.7\n",
],
]);
assert.throws(
() =>
validateNativeClassifierJar({
classifier,
jarPath: fixture.jarPath,
expectedFilename: artifactName,
repoRoot: fixture.repoRoot,
}),
/copilot-runtime\.exe/,
);
});
test("rejects incorrect pinned package metadata", (t) => {
const fixture = createFixture(t);
writeStoredZip(fixture.jarPath, [
["native/win32-x64/runtime.node", "runtime"],
["native/win32-x64/copilot-runtime.exe", "runtime wrapper"],
[
"native/win32-x64/platform.properties",
"classifier=win32-x64\nversion=0.0.1\n",
],
]);
assert.throws(
() =>
validateNativeClassifierJar({
classifier,
jarPath: fixture.jarPath,
expectedFilename: artifactName,
repoRoot: fixture.repoRoot,
}),
/version=9\.8\.7/,
);
});
test("rejects Linux resources in a Windows classifier", (t) => {
const fixture = createFixture(t);
createNativeClassifierTestFixture({
classifier,
outputPath: fixture.jarPath,
repoRoot: fixture.repoRoot,
});
writeStoredZip(fixture.jarPath, [
["native/win32-x64/runtime.node", "runtime"],
["native/win32-x64/copilot-runtime.exe", "runtime wrapper"],
[
"native/win32-x64/platform.properties",
"classifier=win32-x64\nversion=9.8.7\n",
],
["native/linux-x64/runtime.node", "wrong platform"],
]);
assert.throws(
() =>
validateNativeClassifierJar({
classifier,
jarPath: fixture.jarPath,
expectedFilename: artifactName,
repoRoot: fixture.repoRoot,
}),
/must not contain/,
);
});
test("rejects Windows resources in a Linux classifier", (t) => {
const fixture = createFixture(t);
const linuxClassifier = "linux-x64";
const linuxArtifactName =
"copilot-sdk-java-runtime-1.2.3-linux-x64.jar";
const linuxJarPath = path.join(fixture.root, linuxArtifactName);
writeStoredZip(linuxJarPath, [
["native/linux-x64/runtime.node", "runtime"],
["native/linux-x64/copilot-runtime", "runtime wrapper"],
[
"native/linux-x64/platform.properties",
"classifier=linux-x64\nversion=9.8.7\n",
],
["native/win32-x64/runtime.node", "wrong platform"],
]);
assert.throws(
() =>
validateNativeClassifierJar({
classifier: linuxClassifier,
jarPath: linuxJarPath,
expectedFilename: linuxArtifactName,
repoRoot: fixture.repoRoot,
}),
/must not contain/,
);
});
test("rejects native resources in the placeholder JAR", (t) => {
const fixture = createFixture(t);
writeStoredZip(fixture.jarPath, [
["native/win32-x64/runtime.node", "runtime"],
]);
assert.throws(
() => validatePlaceholderJar(fixture.jarPath),
/must not contain/,
);
});
test("rejects Darwin native resources in the placeholder JAR", (t) => {
const fixture = createFixture(t);
writeStoredZip(fixture.jarPath, [
["native/darwin-arm64/runtime.node", "runtime"],
]);
assert.throws(
() => validatePlaceholderJar(fixture.jarPath),
/must not contain/,
);
});
test("accepts a native-free placeholder JAR", (t) => {
const fixture = createFixture(t);
writeStoredZip(fixture.jarPath, [
["META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"],
]);
assert.doesNotThrow(() => validatePlaceholderJar(fixture.jarPath));
});
test("rejects an invalid SHA-256 manifest", (t) => {
const fixture = createFixture(t);
createNativeClassifierTestFixture({
classifier,
outputPath: fixture.jarPath,
repoRoot: fixture.repoRoot,
});
const manifestPath = path.join(fixture.root, "classifier.sha256");
fs.writeFileSync(manifestPath, `${"0".repeat(64)} ${artifactName}\n`);
assert.throws(
() =>
validateSha256Manifest({
expectedFilename: artifactName,
jarPath: fixture.jarPath,
manifestPath,
}),
/SHA-256 mismatch/,
);
});
test("accepts a matching SHA-256 manifest", (t) => {
const fixture = createFixture(t);
createNativeClassifierTestFixture({
classifier,
outputPath: fixture.jarPath,
repoRoot: fixture.repoRoot,
});
const manifestPath = path.join(fixture.root, "classifier.sha256");
const digest = createHash("sha256")
.update(fs.readFileSync(fixture.jarPath))
.digest("hex");
fs.writeFileSync(manifestPath, `${digest} ${artifactName}\n`);
assert.doesNotThrow(() =>
validateSha256Manifest({
expectedFilename: artifactName,
jarPath: fixture.jarPath,
manifestPath,
}),
);
});
test("validates one complete signed local publication", (t) => {
const fixture = createFixture(t);
const artifactId = "copilot-sdk-java-runtime";
const version = "1.2.3";
const publicationDirectory = path.join(
fixture.root,
"repository",
"com",
"github",
artifactId,
version,
);
fs.mkdirSync(publicationDirectory, { recursive: true });
const primaryJar = `${artifactId}-${version}.jar`;
const linuxJar = `${artifactId}-${version}-linux-x64.jar`;
const linuxArm64Jar = `${artifactId}-${version}-linux-arm64.jar`;
const windowsJar = `${artifactId}-${version}-win32-x64.jar`;
const windowsArm64Jar = `${artifactId}-${version}-win32-arm64.jar`;
const darwinJar = `${artifactId}-${version}-darwin-arm64.jar`;
writeStoredZip(path.join(publicationDirectory, primaryJar), [
["META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"],
]);
writeStoredZip(
path.join(publicationDirectory, `${artifactId}-${version}-sources.jar`),
[],
);
writeStoredZip(
path.join(publicationDirectory, `${artifactId}-${version}-javadoc.jar`),
[],
);
createNativeClassifierTestFixture({
classifier: "linux-x64",
outputPath: path.join(publicationDirectory, linuxJar),
repoRoot: fixture.repoRoot,
});
createNativeClassifierTestFixture({
classifier: "linux-arm64",
outputPath: path.join(publicationDirectory, linuxArm64Jar),
repoRoot: fixture.repoRoot,
});
createNativeClassifierTestFixture({
classifier,
outputPath: path.join(publicationDirectory, windowsJar),
repoRoot: fixture.repoRoot,
});
createNativeClassifierTestFixture({
classifier: "win32-arm64",
outputPath: path.join(publicationDirectory, windowsArm64Jar),
repoRoot: fixture.repoRoot,
});
createNativeClassifierTestFixture({
classifier: "darwin-arm64",
outputPath: path.join(publicationDirectory, darwinJar),
repoRoot: fixture.repoRoot,
});
fs.writeFileSync(
path.join(publicationDirectory, `${artifactId}-${version}.pom`),
"",
);
for (const artifact of [
primaryJar,
`${artifactId}-${version}.pom`,
`${artifactId}-${version}-sources.jar`,
`${artifactId}-${version}-javadoc.jar`,
linuxJar,
linuxArm64Jar,
windowsJar,
windowsArm64Jar,
darwinJar,
]) {
fs.writeFileSync(
path.join(publicationDirectory, `${artifact}.asc`),
"signature",
);
}
assert.equal(
validateLocalPublication({
artifactId,
repositoryPath: path.join(fixture.root, "repository"),
repoRoot: fixture.repoRoot,
requireSignatures: true,
version,
}),
publicationDirectory,
);
});
test("local publication validation rejects cross-classifier contamination", (t) => {
const fixture = createFixture(t);
const artifactId = "copilot-sdk-java-runtime";
const version = "1.2.3";
const publicationDirectory = path.join(
fixture.root,
"repository",
"com",
"github",
artifactId,
version,
);
fs.mkdirSync(publicationDirectory, { recursive: true });
writeStoredZip(
path.join(publicationDirectory, `${artifactId}-${version}.jar`),
[["META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"]],
);
writeStoredZip(
path.join(publicationDirectory, `${artifactId}-${version}-sources.jar`),
[],
);
writeStoredZip(
path.join(publicationDirectory, `${artifactId}-${version}-javadoc.jar`),
[],
);
writeStoredZip(
path.join(publicationDirectory, `${artifactId}-${version}-linux-x64.jar`),
[
["native/linux-x64/runtime.node", "runtime"],
["native/linux-x64/copilot-runtime", "runtime wrapper"],
[
"native/linux-x64/platform.properties",
"classifier=linux-x64\nversion=9.8.7\n",
],
["native/win32-x64/runtime.node", "wrong platform"],
],
);
createNativeClassifierTestFixture({
classifier: "linux-arm64",
outputPath: path.join(
publicationDirectory,
`${artifactId}-${version}-linux-arm64.jar`,
),
repoRoot: fixture.repoRoot,
});
createNativeClassifierTestFixture({
classifier: "win32-x64",
outputPath: path.join(
publicationDirectory,
`${artifactId}-${version}-win32-x64.jar`,
),
repoRoot: fixture.repoRoot,
});
createNativeClassifierTestFixture({
classifier: "win32-arm64",
outputPath: path.join(
publicationDirectory,
`${artifactId}-${version}-win32-arm64.jar`,
),
repoRoot: fixture.repoRoot,
});
createNativeClassifierTestFixture({
classifier: "darwin-arm64",
outputPath: path.join(
publicationDirectory,
`${artifactId}-${version}-darwin-arm64.jar`,
),
repoRoot: fixture.repoRoot,
});
fs.writeFileSync(
path.join(publicationDirectory, `${artifactId}-${version}.pom`),
"",
);
assert.throws(
() =>
validateLocalPublication({
artifactId,
repositoryPath: path.join(fixture.root, "repository"),
repoRoot: fixture.repoRoot,
requireSignatures: false,
version,
}),
/must not contain/,
);
});
function createFixture(t) {
const fixtureParent = path.join(
moduleRoot,
"target",
"validate-native-artifact-test-",
);
fs.mkdirSync(fixtureParent, { recursive: true });
const root = fs.mkdtempSync(path.join(fixtureParent, `${process.pid}-`));
t.after(() =>
fs.rmSync(root, {
recursive: true,
force: true,
maxRetries: 3,
retryDelay: 100,
}),
);
const repoRoot = path.join(root, "repo");
fs.mkdirSync(path.join(repoRoot, "nodejs"), { recursive: true });
fs.writeFileSync(
path.join(repoRoot, "nodejs", "package.json"),
JSON.stringify({ copilotCliVersion: "9.8.7" }),
);
return {
root,
repoRoot,
jarPath: path.join(root, artifactName),
};
}