Skip to content

Commit 468d868

Browse files
authored
Add function arguments test (#18)
* Build, load and test function arguments addon * Add building addons to CI workflow * Use cmake directly * Fix Windows specific issues * Configure using the default generator * Run tests on MacOS and Windows too * Ignore Windows debug symbols * Fix Windows issue importing ts-strip.js * Delete win_delay_load_hook.cc for now * Removed the MSVC conditional DELAYLOAD As per https://github.com/nodejs/node-gyp/blob/db5385c5467e5bfb914b9954f0313c46f1f4e10d/addon.gypi#L68-L89
1 parent 25a8cae commit 468d868

File tree

15 files changed

+1280
-13
lines changed

15 files changed

+1280
-13
lines changed

.github/workflows/test.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@ jobs:
88
strategy:
99
fail-fast: false
1010
matrix:
11+
runner:
12+
- macos-latest
13+
- ubuntu-latest
14+
- windows-latest
1115
node-version:
1216
- 20.x
1317
- 22.x
1418
- 24.x
1519
- 25.x
16-
runs-on: ubuntu-latest
20+
runs-on: ${{ matrix.runner }}
1721
steps:
1822
- name: Harden Runner
1923
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
@@ -32,11 +36,16 @@ jobs:
3236
npm --version
3337
- name: Install dependencies
3438
run: npm ci
39+
- name: Configure and build addons
40+
run: |
41+
npm run addons:configure
42+
npm run addons:build
3543
- name: npm test
3644
if: matrix.node-version != '20.x'
3745
run: npm run node:test
3846
- name: npm test with amaro
3947
if: matrix.node-version == '20.x'
4048
run: npm run node:test
4149
env:
42-
NODE_OPTIONS: --import=${{ github.workspace }}/implementors/node/ts-strip.js
50+
# Using file scheme prefix when to enable imports on Windows
51+
NODE_OPTIONS: --import=file://${{ github.workspace }}/implementors/node/ts-strip.js

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
11
node_modules/
2+
3+
# Shallow checkout for agents to reference
4+
/node/
5+
6+
# Artifacts from building addons
7+
/build/
8+
/tests/**/*.node
9+
/tests/**/*.pdb

CMakeLists.txt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
cmake_minimum_required(VERSION 3.15...3.31)
2+
project(node-api-cts)
3+
4+
set(NODE_API_HEADERS_DIR ${PROJECT_SOURCE_DIR}/node_modules/node-api-headers)
5+
6+
if(NOT EXISTS ${NODE_API_HEADERS_DIR})
7+
message(FATAL_ERROR "Expected ${NODE_API_HEADERS_DIR} to exist")
8+
endif()
9+
10+
if(MSVC)
11+
set(NODE_API_LIB ${PROJECT_BINARY_DIR}/node.lib)
12+
set(NODE_API_DEF ${NODE_API_HEADERS_DIR}/def/node_api.def)
13+
execute_process(COMMAND ${CMAKE_AR} /def:${NODE_API_DEF} /out:${NODE_API_LIB} ${CMAKE_STATIC_LINKER_FLAGS})
14+
endif()
15+
16+
function(add_node_api_cts_addon ADDON_NAME SRC)
17+
add_library(${ADDON_NAME} SHARED ${SRC})
18+
set_target_properties(${ADDON_NAME} PROPERTIES
19+
PREFIX ""
20+
SUFFIX ".node"
21+
# Co-locate the output binary with the source file
22+
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
23+
# (for MSVC)
24+
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}
25+
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}
26+
)
27+
if(APPLE)
28+
set_target_properties(${ADDON_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
29+
endif()
30+
target_include_directories(${ADDON_NAME} PRIVATE ${NODE_API_HEADERS_DIR}/include)
31+
target_link_libraries(${ADDON_NAME} PRIVATE ${NODE_API_LIB})
32+
target_compile_features(${ADDON_NAME} PRIVATE cxx_std_17)
33+
target_compile_definitions(${ADDON_NAME} PRIVATE ADDON_NAME=${ADDON_NAME})
34+
endfunction()
35+
36+
file(GLOB_RECURSE cmake_dirs RELATIVE ${CMAKE_SOURCE_DIR} tests/*/CMakeLists.txt)
37+
38+
foreach(cmake_file ${cmake_dirs})
39+
get_filename_component(subdir ${cmake_file} DIRECTORY)
40+
add_subdirectory(${subdir})
41+
endforeach()

implementors/node/load-addon.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import assert from "node:assert/strict";
2+
import { dlopen } from "node:process";
3+
import { constants } from "node:os";
4+
import path from "node:path";
5+
import fs from "node:fs";
6+
7+
const loadAddon = (addonFileName) => {
8+
assert(typeof addonFileName === "string", "Expected a string as addon filename");
9+
assert(!addonFileName.endsWith(".node"), "Expected addon filename without the .node extension");
10+
const addonPath = path.join(process.cwd(), addonFileName + ".node");
11+
assert(fs.existsSync(addonPath), `Expected ${addonPath} to exist - did you build the addons?`);
12+
const addon = { exports: {} };
13+
dlopen(addon, addonPath, constants.dlopen.RTLD_NOW);
14+
return addon.exports;
15+
};
16+
17+
Object.assign(globalThis, { loadAddon });

implementors/node/run-tests.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@ import { test, type TestContext } from "node:test";
55

66
const ROOT_PATH = path.resolve(import.meta.dirname, "..", "..");
77
const TESTS_ROOT_PATH = path.join(ROOT_PATH, "tests");
8+
89
const ASSERT_MODULE_PATH = path.join(
910
ROOT_PATH,
1011
"implementors",
1112
"node",
1213
"assert.js"
1314
);
15+
const LOAD_ADDON_MODULE_PATH = path.join(
16+
ROOT_PATH,
17+
"implementors",
18+
"node",
19+
"load-addon.js"
20+
);
1421

1522
async function listDirectoryEntries(dir: string) {
1623
const entries = await fs.readdir(dir, { withFileTypes: true });
@@ -31,13 +38,20 @@ async function listDirectoryEntries(dir: string) {
3138
return { directories, files };
3239
}
3340

34-
function runFileInSubprocess(filePath: string): Promise<void> {
41+
function runFileInSubprocess(cwd: string, filePath: string): Promise<void> {
3542
return new Promise((resolve, reject) => {
36-
const child = spawn(process.execPath, [
37-
"--import",
38-
ASSERT_MODULE_PATH,
39-
filePath,
40-
]);
43+
const child = spawn(
44+
process.execPath,
45+
[
46+
// Using file scheme prefix when to enable imports on Windows
47+
"--import",
48+
"file://" + ASSERT_MODULE_PATH,
49+
"--import",
50+
"file://" + LOAD_ADDON_MODULE_PATH,
51+
filePath,
52+
],
53+
{ cwd }
54+
);
4155

4256
let stderrOutput = "";
4357
child.stderr.setEncoding("utf8");
@@ -80,8 +94,7 @@ async function populateSuite(
8094
const { directories, files } = await listDirectoryEntries(dir);
8195

8296
for (const file of files) {
83-
const filePath = path.join(dir, file);
84-
await testContext.test(file, () => runFileInSubprocess(filePath));
97+
await testContext.test(file, () => runFileInSubprocess(dir, file));
8598
}
8699

87100
for (const directory of directories) {

0 commit comments

Comments
 (0)