Skip to content

Commit 327500d

Browse files
Introduce node.js test runner
1 parent ce4e44e commit 327500d

File tree

7 files changed

+316
-8
lines changed

7 files changed

+316
-8
lines changed

.github/workflows/test.yml

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,43 +22,85 @@ jobs:
2222
toolchain: stable
2323
profile: minimal
2424
override: true
25+
- name: Set dynamic linker paths
26+
run: |
27+
export DYLD_LIBRARY_PATH=$(rustc --print sysroot)/lib
28+
export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib
29+
export PATH=$(rustc --print sysroot)/lib:$PATH
30+
export DYLD_LIBRARY_PATH_NIGHTLY=$(rustc +nightly --print sysroot)/lib
31+
export LD_LIBRARY_PATH_NIGHTLY=$(rustc +nightly --print sysroot)/lib
32+
export PATH_NIGHTLY=$(rustc +nightly --print sysroot)/lib:$PATH
33+
shell: bash
2534
- name: Tests pass (debug)
2635
run: |
2736
cargo run --manifest-path test-crates/samplebin/Cargo.toml
2837
continue-on-error: ${{ matrix.os == 'windows-latest' }}
38+
shell: bash
2939
- name: Tests pass (release)
3040
run: |
3141
cargo run --manifest-path test-crates/samplebin/Cargo.toml --release
3242
continue-on-error: ${{ matrix.os == 'windows-latest' }}
43+
shell: bash
3344
- name: Add nightly
3445
run: rustup toolchain add nightly
3546
- name: Bin stable, mod_a nightly (should fail)
3647
run: |
37-
! cargo +stable run --manifest-path test-crates/samplebin/Cargo.toml -- --channel:mod_a=nightly
48+
output=$(cargo +stable run --manifest-path test-crates/samplebin/Cargo.toml -- --channel:mod_a=nightly 2>&1)
49+
if [[ $output != *"feature mismatch for crate"* ]]; then
50+
echo "Expected feature mismatch error, but got:"
51+
echo "$output"
52+
exit 1
53+
fi
3854
shell: bash
3955
- name: Bin nightly, mod_a stable (should fail)
4056
run: |
41-
! cargo +nightly run --manifest-path test-crates/samplebin/Cargo.toml -- --channel:mod_a=stable
57+
output=$(cargo +nightly run --manifest-path test-crates/samplebin/Cargo.toml -- --channel:mod_a=stable 2>&1)
58+
if [[ $output != *"feature mismatch for crate"* ]]; then
59+
echo "Expected feature mismatch error, but got:"
60+
echo "$output"
61+
exit 1
62+
fi
4263
shell: bash
4364
- name: All nightly (should work)
4465
run: |
4566
cargo +nightly run --manifest-path test-crates/samplebin/Cargo.toml -- --channel:mod_a=nightly --channel:mod_b=nightly
4667
shell: bash
4768
- name: Bin has mokio-timer feature (should fail)
4869
run: |
49-
! cargo run --features=exports/mokio-timer --manifest-path test-crates/samplebin/Cargo.toml
70+
output=$(cargo run --features=exports/mokio-timer --manifest-path test-crates/samplebin/Cargo.toml 2>&1)
71+
if [[ $output != *"feature mismatch for crate"* ]]; then
72+
echo "Expected feature mismatch error, but got:"
73+
echo "$output"
74+
exit 1
75+
fi
5076
shell: bash
5177
- name: mod_a has mokio-timer feature (should fail)
5278
run: |
53-
! cargo run --manifest-path test-crates/mod_a/Cargo.toml -- --features:mod_a=mokio/timer
79+
output=$(cargo run --manifest-path test-crates/mod_a/Cargo.toml -- --features:mod_a=mokio/timer 2>&1)
80+
if [[ $output != *"feature mismatch for crate"* ]]; then
81+
echo "Expected feature mismatch error, but got:"
82+
echo "$output"
83+
exit 1
84+
fi
5485
shell: bash
5586
- name: mod_b has mokio-timer feature (should fail)
5687
run: |
57-
! cargo run --manifest-path test-crates/mod_b/Cargo.toml -- --features:mod_b=mokio/timer
88+
output=$(cargo run --manifest-path test-crates/mod_b/Cargo.toml -- --features:mod_b=mokio/timer 2>&1)
89+
if [[ $output != *"feature mismatch for crate"* ]]; then
90+
echo "Expected feature mismatch error, but got:"
91+
echo "$output"
92+
exit 1
93+
fi
5894
shell: bash
5995
- name: all mods have mokio-timer feature (should fail)
6096
run: |
61-
! cargo run --manifest-path test-crates/samplebin/Cargo.toml -- --features:mod_a=mokio/timer --features:mod_b=mokio/timer
97+
output=$(cargo run --manifest-path test-crates/samplebin/Cargo.toml -- --features:mod_a=mokio/timer --features:mod_b=mokio/timer 2>&1)
98+
if [[ $output != *"feature mismatch for crate"* ]]; then
99+
echo "Expected feature mismatch error, but got:"
100+
echo "$output"
101+
exit 1
102+
fi
103+
shell: bash
62104
- name: bin and mods have mokio-timer feature (should work)
63105
run: |
64106
cargo run --features=exports/mokio-timer --manifest-path test-crates/samplebin/Cargo.toml -- --features:mod_a=mokio/timer --features:mod_b=mokio/timer

rubicon/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,6 @@ macro_rules! compatibility_check {
429429

430430
let binary_label = format!("Binary {}", blue(&exe_name));
431431
let module_label = format!("Module {}", blue(so_name));
432-
println!("visible_len(binary_label) = {}", visible_len(&binary_label));
433-
println!("visible_len(module_label) = {}", visible_len(&module_label));
434432

435433
let binary_label_width = visible_len(&binary_label);
436434
let module_label_width = visible_len(&module_label);

test-crates/samplebin/src/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ fn main() {
132132
)
133133
}
134134

135+
soprintln!(
136+
"DYLD_LIBRARY_PATH = {}",
137+
std::env::var("DYLD_LIBRARY_PATH").unwrap_or_default()
138+
);
139+
soprintln!(
140+
"LD_LIBRARY_PATH = {}",
141+
std::env::var("LD_LIBRARY_PATH").unwrap_or_default()
142+
);
143+
soprintln!("PATH = {}", std::env::var("PATH").unwrap_or_default());
144+
135145
soprintln!("loading modules...");
136146
let lib_a = unsafe { libloading::Library::new(module_path("a")).unwrap() };
137147
let lib_a = Box::leak(Box::new(lib_a));

tests/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

tests/index.mjs

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import { spawn, execSync } from "child_process";
2+
import chalk from "chalk";
3+
import os from "os";
4+
import { existsSync } from "fs";
5+
import { dirname } from "path";
6+
7+
let ENV_VARS = {};
8+
9+
// Helper function to set environment variables
10+
function setEnvVariables() {
11+
const rustSysroot = execSync("rustc --print sysroot").toString().trim();
12+
const rustNightlySysroot = execSync("rustc +nightly --print sysroot")
13+
.toString()
14+
.trim();
15+
16+
const platform = os.platform();
17+
if (platform === "darwin") {
18+
console.log("🍎 Detected macOS");
19+
ENV_VARS.DYLD_LIBRARY_PATH = `${rustSysroot}/lib:${rustNightlySysroot}/lib`;
20+
} else if (platform === "win32") {
21+
console.log("🪟 Detected Windows");
22+
ENV_VARS.PATH += `;${process.env.PATH};${rustSysroot}/lib;${rustNightlySysroot}/lib`;
23+
} else if (platform === "linux") {
24+
console.log("🐧 Detected Linux");
25+
ENV_VARS.LD_LIBRARY_PATH = `${rustSysroot}/lib:${rustNightlySysroot}/lib`;
26+
} else {
27+
console.log(`❌ Unsupported platform: ${platform}`);
28+
process.exit(1);
29+
}
30+
31+
console.log("\nEnvironment Variables Summary:");
32+
for (const [key, value] of Object.entries(ENV_VARS)) {
33+
console.log(`${key}: ${value}`);
34+
}
35+
}
36+
37+
// Helper function to run a command and capture output
38+
function runCommand(command) {
39+
try {
40+
const child = spawn(command, [], {
41+
shell: true,
42+
stdio: ["inherit", "pipe", "pipe"],
43+
env: {
44+
SOPRINTLN: "1",
45+
PATH: process.env.PATH,
46+
...ENV_VARS,
47+
},
48+
});
49+
console.log("Set ENV_VARS to: ", ENV_VARS);
50+
51+
let output = "";
52+
53+
child.stdout.on("data", (data) => {
54+
process.stdout.write(data);
55+
output += data;
56+
});
57+
58+
child.stderr.on("data", (data) => {
59+
process.stderr.write(data);
60+
output += data;
61+
});
62+
63+
return new Promise((resolve) => {
64+
child.on("close", (code) => {
65+
resolve({
66+
success: code === 0,
67+
output: output,
68+
});
69+
});
70+
});
71+
} catch (error) {
72+
process.stderr.write(chalk.red(error.toString()));
73+
return Promise.resolve({
74+
success: false,
75+
output: error.toString(),
76+
});
77+
}
78+
}
79+
80+
// Helper function to check for feature mismatch
81+
function checkFeatureMismatch(output) {
82+
return output.includes("feature mismatch for crate");
83+
}
84+
85+
// Test cases
86+
const testCases = [
87+
{
88+
name: "Tests pass (debug)",
89+
command: "cargo run --manifest-path test-crates/samplebin/Cargo.toml",
90+
expectedResult: "success",
91+
},
92+
{
93+
name: "Tests pass (release)",
94+
command:
95+
"cargo run --manifest-path test-crates/samplebin/Cargo.toml --release",
96+
expectedResult: "success",
97+
},
98+
{
99+
name: "Bin stable, mod_a nightly (should fail)",
100+
command:
101+
"cargo +stable run --manifest-path test-crates/samplebin/Cargo.toml -- --channel:mod_a=nightly",
102+
expectedResult: "fail",
103+
checkFeatureMismatch: true,
104+
},
105+
{
106+
name: "Bin nightly, mod_a stable (should fail)",
107+
command:
108+
"cargo +nightly run --manifest-path test-crates/samplebin/Cargo.toml -- --channel:mod_a=stable",
109+
expectedResult: "fail",
110+
checkFeatureMismatch: true,
111+
},
112+
{
113+
name: "All nightly (should work)",
114+
command:
115+
"cargo +nightly run --manifest-path test-crates/samplebin/Cargo.toml -- --channel:mod_a=nightly --channel:mod_b=nightly",
116+
expectedResult: "success",
117+
},
118+
{
119+
name: "Bin has mokio-timer feature (should fail)",
120+
command:
121+
"cargo run --features=exports/mokio-timer --manifest-path test-crates/samplebin/Cargo.toml",
122+
expectedResult: "fail",
123+
checkFeatureMismatch: true,
124+
},
125+
{
126+
name: "mod_a has mokio-timer feature (should fail)",
127+
command:
128+
"cargo run --manifest-path test-crates/mod_a/Cargo.toml -- --features:mod_a=mokio/timer",
129+
expectedResult: "fail",
130+
checkFeatureMismatch: true,
131+
},
132+
{
133+
name: "mod_b has mokio-timer feature (should fail)",
134+
command:
135+
"cargo run --manifest-path test-crates/mod_b/Cargo.toml -- --features:mod_b=mokio/timer",
136+
expectedResult: "fail",
137+
checkFeatureMismatch: true,
138+
},
139+
{
140+
name: "all mods have mokio-timer feature (should fail)",
141+
command:
142+
"cargo run --manifest-path test-crates/samplebin/Cargo.toml -- --features:mod_a=mokio/timer --features:mod_b=mokio/timer",
143+
expectedResult: "fail",
144+
checkFeatureMismatch: true,
145+
},
146+
{
147+
name: "bin and mods have mokio-timer feature (should work)",
148+
command:
149+
"cargo run --features=exports/mokio-timer --manifest-path test-crates/samplebin/Cargo.toml -- --features:mod_a=mokio/timer --features:mod_b=mokio/timer",
150+
expectedResult: "success",
151+
},
152+
];
153+
154+
// Main function to run tests
155+
async function runTests() {
156+
console.log(chalk.blue("Changing working directory to Git root..."));
157+
let currentDir = process.cwd();
158+
159+
while (!existsSync(`${currentDir}/.git`)) {
160+
const parentDir = dirname(currentDir);
161+
if (parentDir === currentDir) {
162+
console.log(chalk.red("Git root not found. Exiting."));
163+
process.exit(1);
164+
}
165+
currentDir = parentDir;
166+
}
167+
process.chdir(currentDir);
168+
console.log(chalk.green(`Changed working directory to: ${currentDir}`));
169+
console.log(chalk.blue("Checking Rust version and toolchain..."));
170+
console.log(chalk.yellow("rustc --version:"));
171+
await runCommand("rustc --version");
172+
console.log(chalk.yellow("\nrustup which rustc:"));
173+
await runCommand("rustup which rustc");
174+
console.log("");
175+
176+
console.log(chalk.blue("Setting up environment variables..."));
177+
setEnvVariables();
178+
179+
console.log(chalk.blue("Installing nightly Rust..."));
180+
await runCommand("rustup toolchain add nightly");
181+
182+
console.log(chalk.blue("Running tests..."));
183+
for (const [index, test] of testCases.entries()) {
184+
console.log(chalk.yellow(`\nRunning test ${index + 1}: ${test.name}`));
185+
const { success, output } = await runCommand(test.command);
186+
187+
if (test.expectedResult === "success" && success) {
188+
console.log(chalk.green("Test passed as expected."));
189+
} else if (test.expectedResult === "fail" && !success) {
190+
if (test.checkFeatureMismatch && checkFeatureMismatch(output)) {
191+
console.log(
192+
chalk.green("Test failed with feature mismatch as expected."),
193+
);
194+
} else {
195+
console.log(
196+
chalk.red(
197+
"Test failed, but not with the expected feature mismatch error.",
198+
),
199+
);
200+
}
201+
} else {
202+
console.log(
203+
chalk.red(
204+
`Test result unexpected. Expected ${test.expectedResult}, but got ${success ? "success" : "failure"}.`,
205+
),
206+
);
207+
}
208+
}
209+
}
210+
211+
// Run the tests
212+
runTests().catch((error) => {
213+
console.error(chalk.red(`An error occurred: ${error.message}`));
214+
process.exit(1);
215+
});

tests/package-lock.json

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "tests",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"scripts": {
6+
"test": "echo \"Error: no test specified\" && exit 1"
7+
},
8+
"author": "",
9+
"license": "ISC",
10+
"description": "",
11+
"dependencies": {
12+
"chalk": "^5.3.0"
13+
}
14+
}

0 commit comments

Comments
 (0)