Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a few tests for --compile --target #10523

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/compile_target.zig
Expand Up @@ -436,3 +436,45 @@ pub fn defineValues(this: *const CompileTarget) []const []const u8 {
},
}
}

const JSC = bun.JSC;
pub fn createCompileTargetBindings(globalObject: *JSC.JSGlobalObject) JSC.JSValue {
var object = JSC.JSValue.createEmptyObject(globalObject, 2);
const getDefaultTarget = struct {
pub fn getDefaultTarget(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
const target = CompileTarget{};
var str = bun.String.createFormat("{}", .{target}) catch |err| {
global.throwError(err, "Failed");
return .zero;
};
defer str.deref();
return str.toJS(global);
}
}.getDefaultTarget;
const from_fn = struct {
pub fn from(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
const name_value = callframe.arguments(1).ptr[0];
const input = name_value.toSlice(global, bun.default_allocator);
defer input.deinit();
const target = CompileTarget.from(input.slice());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol doesnt this function exit the program on failure.

would be cool if we could test the parser. its fine of course.


var str = bun.String.createFormat("{}", .{target}) catch |err| {
global.throwError(err, "Failed");
return .zero;
};
defer str.deref();
return str.toJS(global);
}
}.from;
object.put(
globalObject,
bun.String.init("getDefaultTarget"),
JSC.createCallback(globalObject, null, 0, &getDefaultTarget),
);
object.put(
globalObject,
bun.String.init("from"),
JSC.createCallback(globalObject, null, 1, &from_fn),
);
return object;
}
5 changes: 5 additions & 0 deletions src/js/internal-for-testing.ts
Expand Up @@ -34,3 +34,8 @@ export const upgrade_test_helpers = $zig("upgrade_command.zig", "upgrade_js_bind
openTempDirWithoutSharingDelete: () => void;
closeTempDirHandle: () => void;
};

export const CompileTarget = $zig("compile_target.zig", "createCompileTargetBindings") as {
getDefaultTarget: () => `bun-${string}`;
from: (input: string) => `bun-${string}`;
};
131 changes: 131 additions & 0 deletions test/bundler/bundler_compile_cross.test.ts
@@ -0,0 +1,131 @@
import { bunEnv } from "harness";
import { itBundled, testForFile } from "./expectBundled";
var { describe, test, expect } = testForFile(import.meta.path);
import { CompileTarget } from "bun:internal-for-testing";

describe("bundler", async () => {
itBundled("compile_cross/DetectDefaultTarget", {
compile: true,
target: CompileTarget.getDefaultTarget(),
env: {
...bunEnv,
BUN_COMPILE_TARGET_TARBALL_URL:
"https://localhost:999999/deliberately-invalid-url-to-check-that-it-detects-default-target-correctly",
},
files: {
"/entry.ts": /* js */ `
console.log("Hello, world!");
`,
},
run: { stdout: "Hello, world!" },
});
itBundled("compile_cross/DetectDefaultTarget2", {
compile: true,
target: "bun",
env: {
...bunEnv,
BUN_COMPILE_TARGET_TARBALL_URL:
"https://localhost:999999/deliberately-invalid-url-to-check-that-it-detects-default-target-correctly",
},
files: {
"/entry.ts": /* js */ `
console.log("Hello, world!");
`,
},
run: { stdout: "Hello, world!" },
});
itBundled("compile_cross/FailOnInvalidTarget", {
compile: true,
target: `bun-poop`,
env: {
...bunEnv,
BUN_COMPILE_TARGET_TARBALL_URL:
"https://localhost:999999/deliberately-invalid-url-to-check-that-it-detects-default-target-correctly",
},
files: {
"/entry.ts": /* js */ `
console.log("Hello, world!");
`,
},
bundleErrors: {
"<bun>": [`Unsupported target "poop" in "bun-poop"`],
},
});
itBundled("compile_cross/FailOnWildcardVersion", {
compile: true,
target: `bun-v1.*`,
env: {
...bunEnv,
BUN_COMPILE_TARGET_TARBALL_URL:
"https://localhost:999999/deliberately-invalid-url-to-check-that-it-detects-default-target-correctly",
},
files: {
"/entry.ts": /* js */ `
console.log("Hello, world!");
`,
},
bundleErrors: {
"<bun>": [
`Please pass a complete version number to --target. For example, --target=bun-v` +
Bun.version.replace("-debug", ""),
],
},
});
itBundled("compile_cross/FailsOnInvalidURL", {
compile: true,
target: `bun-linux-arm64-v1.0.9999`,
env: {
...bunEnv,
BUN_COMPILE_TARGET_TARBALL_URL: "https://localhost:999999/deliberately-invalid-url",
},
files: {
"/entry.ts": /* js */ `
console.log("Hello, world!");
`,
},
bundleErrors: {
"<bun>": [`failed to download cross-compiled bun executable`],
},
});

// we allow using a local file if it has the exact name we expect
// this is undocumented behavior, but it will make it easier to write tests in the future
itBundled("compile_cross/UsesFileFromSameLocation", {
compile: true,
target: `bun-linux-arm64-v1.999.9999`,
env: {
...bunEnv,
BUN_COMPILE_TARGET_TARBALL_URL: "https://localhost:999999/deliberately-invalid-url",
},
files: {
"/entry.ts": /* js */ `
console.log("Hello, world!");
`,
// expects "bun" to be trimmed
[CompileTarget.from("-linux-arm64-v1.999.9999")]: ``,
},
});

// expects "bun" to be trimmed
const sameLocationTarget = CompileTarget.from(`-${process.platform}-${process.arch}-v1.0.9999`);

// Test that it can load a file that didn't actually come from bun.selfExePath()
itBundled("compile_cross/RunsFileFromSameLocation", {
compile: true,
target: sameLocationTarget,
env: {
...bunEnv,
BUN_COMPILE_TARGET_TARBALL_URL: "https://localhost:999999/deliberately-invalid-url",
},
files: {
"/entry.ts": /* js */ `
console.log("Hello, world!");
`,

["/" + sameLocationTarget]: Buffer.from(await Bun.file(process.execPath).arrayBuffer()),
},
run: {
stdout: "Hello, world!",
},
});
});
22 changes: 19 additions & 3 deletions test/bundler/expectBundled.ts
Expand Up @@ -46,13 +46,29 @@ function dedent(str: string | TemplateStringsArray, ...args: any[]) {
let currentFile: string | undefined;

function errorOrWarnParser(isError = true) {
const prefix = isError ? "error: " : "warn: ";
return function (text: string) {
let defaultPrefix = isError ? "error: " : "warn: ";
return function parser(text: string) {
let prefix = defaultPrefix;
var i = 0;
var list = [];
while (i < text.length) {
let errorLineI = text.indexOf(prefix, i);
if (errorLineI === -1) {
// Sometimes, our errors start with the error name itself
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah i understand alot more now. thanks for the comment

// e.g. "ConnectionRefused: connect ECONNREFUSED 127.0.0.1:8080"
// In those cases, it IS an error, but it doesn't start with "error: ",
if (list.length === 0 && prefix === defaultPrefix && !text.includes(prefix)) {
const firstPrefix = text.indexOf(": ", 0);
if (firstPrefix !== -1) {
const possiblePrefix = text.slice(0, firstPrefix).trim();
if (/^([a-zA-Z0-9_]+)$/.test(possiblePrefix)) {
prefix = possiblePrefix.trim() + ": ";
i = 0;
continue;
}
}
}

return list;
}
const message = text.slice(errorLineI + prefix.length, text.indexOf("\n", errorLineI + 1));
Expand Down Expand Up @@ -175,7 +191,7 @@ export interface BundlerTestInput {
/** Defaults to `/out` */
outdir?: string;
/** Defaults to "browser". "bun" is set to "node" when using esbuild. */
target?: "bun" | "node" | "browser";
target?: "bun" | "node" | "browser" | `bun-${string}`;
publicPath?: string;
keepNames?: boolean;
legalComments?: "none" | "inline" | "eof" | "linked" | "external";
Expand Down