Skip to content

Commit 27d108a

Browse files
committed
test: simplify
1 parent f430121 commit 27d108a

3 files changed

Lines changed: 165 additions & 18 deletions

File tree

.github/workflows/lint-rs.yml

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -113,23 +113,8 @@ jobs:
113113
run: cargo clippy --all-targets --all-features -- -D warnings -D clippy::all
114114
working-directory: src-tauri
115115

116-
- name: Run Rust unit tests
117-
run: cargo test --lib && cargo test --test donut_proxy_integration && cargo test --test vpn_integration
118-
working-directory: src-tauri
119-
120-
- name: Run OpenVPN e2e test (Ubuntu only)
121-
if: matrix.os == 'ubuntu-22.04'
122-
shell: bash
123-
working-directory: src-tauri
124-
env:
125-
DONUTBROWSER_RUN_OPENVPN_E2E: "1"
126-
run: |
127-
CARGO_BIN="$(command -v cargo)"
128-
sudo --preserve-env=CARGO_HOME,RUSTUP_HOME,DONUTBROWSER_RUN_OPENVPN_E2E \
129-
"${CARGO_BIN}" test --test vpn_integration test_openvpn_traffic_flows_through_donut_proxy -- --nocapture
130-
131-
- name: Run Rust sync e2e tests
132-
run: node scripts/sync-test-harness.mjs
116+
- name: Run test suite
117+
run: pnpm test
133118

134119
- name: Run cargo audit security check
135120
run: cargo audit

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"dev": "next dev --turbopack -p 12341",
99
"build": "next build",
1010
"start": "next start",
11-
"test": "pnpm test:rust:unit && pnpm test:sync-e2e",
11+
"test": "pnpm test:rust:unit && pnpm test:openvpn-e2e && pnpm test:sync-e2e",
12+
"test:openvpn-e2e": "node scripts/openvpn-test-harness.mjs",
1213
"test:rust": "cd src-tauri && cargo test",
1314
"test:rust:unit": "cd src-tauri && cargo test --lib && cargo test --test donut_proxy_integration && cargo test --test vpn_integration",
1415
"test:sync-e2e": "node scripts/sync-test-harness.mjs",

scripts/openvpn-test-harness.mjs

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#!/usr/bin/env node
2+
/**
3+
* OpenVPN E2E Test Harness
4+
*
5+
* This script:
6+
* 1. Skips unless explicitly enabled via DONUTBROWSER_RUN_OPENVPN_E2E=1
7+
* 2. Builds the Rust vpn_integration test binary without running it
8+
* 3. Runs the OpenVPN e2e test binary under sudo
9+
*
10+
* Usage: DONUTBROWSER_RUN_OPENVPN_E2E=1 node scripts/openvpn-test-harness.mjs
11+
*/
12+
13+
import { spawn } from "child_process";
14+
import path from "path";
15+
import { fileURLToPath } from "url";
16+
17+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
18+
const ROOT_DIR = path.resolve(__dirname, "..");
19+
const SRC_TAURI_DIR = path.join(ROOT_DIR, "src-tauri");
20+
const TEST_NAME = "test_openvpn_traffic_flows_through_donut_proxy";
21+
22+
function log(message) {
23+
console.log(`[openvpn-harness] ${message}`);
24+
}
25+
26+
function error(message) {
27+
console.error(`[openvpn-harness] ERROR: ${message}`);
28+
}
29+
30+
function shouldRun() {
31+
if (process.env.DONUTBROWSER_RUN_OPENVPN_E2E !== "1") {
32+
log("Skipping OpenVPN e2e test because DONUTBROWSER_RUN_OPENVPN_E2E is not set");
33+
return false;
34+
}
35+
36+
if (process.platform !== "linux") {
37+
log(`Skipping OpenVPN e2e test on unsupported platform: ${process.platform}`);
38+
return false;
39+
}
40+
41+
return true;
42+
}
43+
44+
async function buildTestBinary() {
45+
log("Building OpenVPN e2e test binary...");
46+
47+
return new Promise((resolve, reject) => {
48+
let executablePath = "";
49+
let stdoutBuffer = "";
50+
51+
const proc = spawn(
52+
"cargo",
53+
[
54+
"test",
55+
"--test",
56+
"vpn_integration",
57+
TEST_NAME,
58+
"--no-run",
59+
"--message-format=json",
60+
],
61+
{
62+
cwd: SRC_TAURI_DIR,
63+
env: process.env,
64+
stdio: ["ignore", "pipe", "pipe"],
65+
}
66+
);
67+
68+
const parseBuffer = (flush = false) => {
69+
const lines = stdoutBuffer.split("\n");
70+
const completeLines = flush ? lines : lines.slice(0, -1);
71+
stdoutBuffer = flush ? "" : lines.at(-1) ?? "";
72+
73+
for (const line of completeLines.filter(Boolean)) {
74+
try {
75+
const message = JSON.parse(line);
76+
if (message.reason === "compiler-artifact" && message.executable) {
77+
executablePath = message.executable;
78+
}
79+
} catch {
80+
// Ignore non-JSON lines.
81+
}
82+
}
83+
};
84+
85+
proc.stdout.on("data", (data) => {
86+
stdoutBuffer += data.toString();
87+
parseBuffer();
88+
});
89+
90+
proc.stderr.on("data", (data) => {
91+
process.stderr.write(data);
92+
});
93+
94+
proc.on("error", (err) => {
95+
reject(err);
96+
});
97+
98+
proc.on("close", (code) => {
99+
parseBuffer(true);
100+
101+
if (code !== 0) {
102+
reject(new Error(`cargo test --no-run exited with code ${code}`));
103+
return;
104+
}
105+
106+
if (!executablePath) {
107+
reject(new Error("Could not determine the vpn_integration test binary path"));
108+
return;
109+
}
110+
111+
resolve(path.isAbsolute(executablePath) ? executablePath : path.resolve(SRC_TAURI_DIR, executablePath));
112+
});
113+
});
114+
}
115+
116+
async function runOpenVpnE2e(executablePath) {
117+
log("Running OpenVPN e2e test under sudo...");
118+
119+
return new Promise((resolve, reject) => {
120+
const proc = spawn(
121+
"sudo",
122+
[
123+
"--preserve-env=CI,GITHUB_ACTIONS,VPN_TEST_OVPN_HOST,VPN_TEST_OVPN_PORT,DONUTBROWSER_RUN_OPENVPN_E2E",
124+
executablePath,
125+
TEST_NAME,
126+
"--exact",
127+
"--nocapture",
128+
],
129+
{
130+
cwd: SRC_TAURI_DIR,
131+
env: process.env,
132+
stdio: "inherit",
133+
}
134+
);
135+
136+
proc.on("error", (err) => {
137+
reject(err);
138+
});
139+
140+
proc.on("close", (code) => {
141+
resolve(code ?? 1);
142+
});
143+
});
144+
}
145+
146+
async function main() {
147+
if (!shouldRun()) {
148+
process.exit(0);
149+
}
150+
151+
try {
152+
const executablePath = await buildTestBinary();
153+
const exitCode = await runOpenVpnE2e(executablePath);
154+
process.exit(exitCode);
155+
} catch (err) {
156+
error(err instanceof Error ? err.message : String(err));
157+
process.exit(1);
158+
}
159+
}
160+
161+
main();

0 commit comments

Comments
 (0)