add tests and use RAII guard thingy

This commit is contained in:
Zack Radisic
2025-04-03 15:48:07 -07:00
parent 3b1c0de228
commit cd2cad6da0
3 changed files with 67 additions and 4 deletions

View File

@@ -365,6 +365,29 @@ extern "C" size_t Bun__process_dlopen_count;
extern "C" void CrashHandler__setDlOpenAction(const char* action);
/**
* RAII wrapper for CrashHandler__setDlOpenAction
* Sets the dlopen action on construction and clears it on destruction
*/
class DlOpenActionGuard {
public:
explicit DlOpenActionGuard(const char* action)
{
CrashHandler__setDlOpenAction(action);
}
~DlOpenActionGuard()
{
CrashHandler__setDlOpenAction(nullptr);
}
// Prevent copying and moving
DlOpenActionGuard(const DlOpenActionGuard&) = delete;
DlOpenActionGuard& operator=(const DlOpenActionGuard&) = delete;
DlOpenActionGuard(DlOpenActionGuard&&) = delete;
DlOpenActionGuard& operator=(DlOpenActionGuard&&) = delete;
};
JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalObject_, JSC::CallFrame* callFrame))
{
Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject_);
@@ -440,9 +463,8 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalOb
HMODULE handle = Bun__LoadLibraryBunString(&filename_str);
#else
CString utf8 = filename.utf8();
CrashHandler__setDlOpenAction(utf8.data());
DlOpenActionGuard guard(utf8.data());
void* handle = dlopen(utf8.data(), RTLD_LAZY);
CrashHandler__setDlOpenAction(nullptr);
#endif
globalObject->m_pendingNapiModuleDlopenHandle = handle;

View File

@@ -0,0 +1,19 @@
// GENERATED CODE ... NO TOUCHY!!
#include <node_api.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <uv.h>
napi_value Init(napi_env env, napi_value exports) {
// call some function which we do not support
int value = uv_cpumask_size();
printf("VALUE: %d\n", value);
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

View File

@@ -1,14 +1,20 @@
import { beforeAll, describe, expect, afterEach, test } from "bun:test";
import path from "node:path";
import { bunEnv, bunExe, makeTree, tempDirWithFiles, isWindows } from "harness";
import { bunEnv, bunExe, makeTree, tempDirWithFiles, isWindows, isDebug } from "harness";
import source from "./uv-stub-stuff/plugin.c";
import source_fail_on_init from "./uv-stub-stuff/plugin_fail_on_init.c";
import goodSource from "./uv-stub-stuff/good_plugin.c";
import { symbols, test_skipped } from "../../src/bun.js/bindings/libuv/generate_uv_posix_stubs_constants";
const symbols_to_test = symbols.filter(s => !test_skipped.includes(s));
const skip_on_debug = true;
// We use libuv on Windows
describe.if(!isWindows)("uv stubs", () => {
// These tests are super slow on debug builds
const run_test = !isWindows && (!isDebug || !skip_on_debug);
describe.if(run_test)("uv stubs", () => {
const cwd = process.cwd();
let tempdir: string = "";
let outdir: string = "";
@@ -16,6 +22,7 @@ describe.if(!isWindows)("uv stubs", () => {
beforeAll(async () => {
const files = {
"plugin.c": await Bun.file(source).text(),
"plugin_fail_on_init.c": await Bun.file(source_fail_on_init).text(),
"good_plugin.c": await Bun.file(goodSource).text(),
"package.json": JSON.stringify({
"name": "fake-plugin",
@@ -36,6 +43,7 @@ describe.if(!isWindows)("uv stubs", () => {
}),
"index.ts": `const symbol = process.argv[2]; const foo = require("./build/Release/xXx123_foo_counter_321xXx.node"); foo.callUVFunc(symbol)`,
"nocrash.ts": `const foo = require("./build/Release/good_plugin.node");console.log('HI!')`,
"fail_on_init.ts": `const foo = require("./build/Release/fail_on_init.node");console.log('HI!')`,
"binding.gyp": `{
"targets": [
{
@@ -51,6 +59,13 @@ describe.if(!isWindows)("uv stubs", () => {
"include_dirs": [ ".", "./libuv" ],
"cflags": ["-fPIC"],
"ldflags": ["-Wl,--export-dynamic"]
},
{
"target_name": "fail_on_init",
"sources": [ "plugin_fail_on_init.c" ],
"include_dirs": [ ".", "./libuv" ],
"cflags": ["-fPIC"],
"ldflags": ["-Wl,--export-dynamic"]
}
]
}
@@ -74,6 +89,13 @@ describe.if(!isWindows)("uv stubs", () => {
process.chdir(cwd);
});
test("should crash with path if possible", async () => {
const { stderr } = await Bun.$`${bunExe()} run fail_on_init.ts`.cwd(tempdir).throws(false).quiet();
const stderrStr = stderr.toString();
expect(stderrStr).toContain("while opening");
expect(stderrStr).toContain("fail_on_init.node");
});
for (const symbol of symbols_to_test) {
test(`should crash when calling unsupported uv functions: ${symbol}`, async () => {
console.log("GO:", symbol);