Skip to content

Commit da98158

Browse files
committed
[Tests] Replace the httpbin container with a local mock server in the nvm_download tests
The nvm_download tests used a local kennethreitz/httpbin container as the origin for the auth header checks; inside the development container (and in CI) no docker daemon is available, so those checks were skipped whenever the image could not be pulled or run. Add test/mocks/mock-server.js, a dependency-free Node.js server providing the endpoints the tests took from httpbin (/bearer and /get), and start it from the tests instead: - "Running 'nvm_download' with NVM_AUTH_HEADER" moves from the fast suite to the slow suite, since running the mock server requires a node binary, which the fast tests do not assume. - "Running 'nvm_download' with NVM_PROXY_AUTH_HEADER through a proxy" runs the mock server with the node binary of the installed LTS version. The header checks now always run, with no dependency on docker or a container image. Assisted-by: omp:llama.cpp:ggml-org/Qwen3.8-27B-GGUF
1 parent adb4e0e commit da98158

4 files changed

Lines changed: 145 additions & 68 deletions

File tree

‎test/fast/Unit tests/nvm_download‎

Lines changed: 0 additions & 42 deletions
This file was deleted.

‎test/mocks/mock-server.js‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// A minimal HTTP server for testing nvm's Authorization header support
2+
// (see the "nvm_download" slow tests). It requires no dependencies beyond
3+
// Node.js core modules.
4+
//
5+
// Usage: node mock-server.js <port-file>
6+
//
7+
// - Listens on 127.0.0.1 on an OS-assigned free port (port 0) and writes
8+
// the assigned port to <port-file> once the listener is bound, so the
9+
// test can discover it.
10+
// - Serves the endpoints the tests previously took from a local httpbin
11+
// container:
12+
// - /bearer: 200 when the request's Authorization header is exactly
13+
// "Bearer test-token", 401 otherwise.
14+
// - /get: 200 with a JSON body describing the request.
15+
// - any other path: 404.
16+
17+
'use strict';
18+
19+
const fs = require('fs');
20+
const http = require('http');
21+
22+
const [portFile] = process.argv.slice(2);
23+
if (!portFile) {
24+
console.error('usage: node mock-server.js <port-file>');
25+
process.exit(2);
26+
}
27+
28+
const server = http.createServer((req, res) => {
29+
if (req.url === '/bearer') {
30+
if (req.headers['authorization'] === 'Bearer test-token') {
31+
res.writeHead(200);
32+
res.end();
33+
} else {
34+
res.writeHead(401, { 'WWW-Authenticate': 'Bearer' });
35+
res.end();
36+
}
37+
} else if (req.url === '/get') {
38+
const body = JSON.stringify({ url: req.url, headers: req.headers });
39+
res.writeHead(200, { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) });
40+
res.end(body);
41+
} else {
42+
res.writeHead(404);
43+
res.end();
44+
}
45+
});
46+
47+
server.on('clientError', (err, socket) => {
48+
console.error(`mock server: client error: ${err.message}`);
49+
socket.end('HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Length: 0\r\n\r\n');
50+
});
51+
52+
server.on('error', (err) => {
53+
console.error(`mock server: ${err.message}`);
54+
process.exit(1);
55+
});
56+
57+
server.listen(0, '127.0.0.1', () => {
58+
const port = server.address().port;
59+
fs.writeFileSync(portFile, `${port}\n`);
60+
console.log(`mock server listening on port ${port}`);
61+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/bin/sh
2+
3+
# Tests nvm_download's NVM_AUTH_HEADER support against a local mock server
4+
# (test/mocks/mock-server.js) providing the endpoints a local httpbin
5+
# container used to provide. It is a slow test because running the mock
6+
# server requires a node binary, which the fast tests do not assume.
7+
cleanup () {
8+
unset -f die cleanup
9+
if [ -n "${mock_server_pid:-}" ]; then
10+
kill "${mock_server_pid}" >/dev/null 2>&1 || true
11+
fi
12+
rm -f "${mock_server_port_file:-}" 2>/dev/null || true
13+
}
14+
die () { echo "$@" ; cleanup ; exit 1; }
15+
16+
: nvm.sh
17+
\. ../../nvm.sh
18+
19+
set -ex
20+
21+
# nvm_download install.sh
22+
nvm_download "https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh" >/dev/null || die "nvm_download unable to download install.sh"
23+
24+
# nvm_download should fail to download wrong_install.sh
25+
! nvm_download "https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/wrong_install.sh" >/dev/null || die "nvm_download should fail to download no existing file"
26+
27+
# start the mock server (which provides the auth header endpoints) with
28+
# node, on an ephemeral port
29+
command -v node >/dev/null || die 'node is required to run the mock server'
30+
mock_server_port_file="$(mktemp)"
31+
node "../mocks/mock-server.js" "${mock_server_port_file}" >/dev/null 2>&1 &
32+
mock_server_pid="$!"
33+
mock_server_port=''
34+
i=0
35+
while [ "${i}" -lt 10 ]; do
36+
if [ -s "${mock_server_port_file}" ]; then
37+
mock_server_port="$(cat "${mock_server_port_file}")"
38+
break
39+
fi
40+
i=$((i + 1))
41+
sleep 1
42+
done
43+
[ -n "${mock_server_port}" ] || die 'the mock server did not report a port'
44+
45+
# nvm_download should pass when calling with auth header
46+
NVM_AUTH_HEADER="Bearer test-token" nvm_download "http://127.0.0.1:${mock_server_port}/bearer" > /dev/null || die 'nvm_download with auth header should send correctly'
47+
# nvm_download should fail when calling without auth header
48+
nvm_download "http://127.0.0.1:${mock_server_port}/bearer" > /dev/null && die 'nvm_download with no auth header should not send the header and should fail'
49+
50+
# ensure quoted extra args remain quoted
51+
nvm_download "https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh" -o "; die quoted-command-not-quoted" || die 'command failed'
52+
53+
cleanup

‎test/slow/Running 'nvm_download' with NVM_PROXY_AUTH_HEADER through a proxy‎

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@
44
# demands its own credentials. This is a slow test because it installs node:
55
# the latest LTS is installed, and the node binary of that installation is
66
# then used to run the dependency-free mock proxy. The proxy-header checks
7-
# themselves follow the nvm_download fast test, using a local httpbin
8-
# container as the origin.
7+
# use a local mock server (test/mocks/mock-server.js) as the origin, which
8+
# provides the endpoints a local httpbin container used to provide.
99

1010
cleanup () {
1111
unset -f die cleanup
1212
if [ -n "${mock_proxy_pid:-}" ]; then
1313
kill "${mock_proxy_pid}" >/dev/null 2>&1 || true
1414
fi
1515
rm -f "${mock_proxy_port_file:-}" 2>/dev/null || true
16-
docker rm -f httpbin >/dev/null 2>&1 || true
16+
if [ -n "${mock_server_pid:-}" ]; then
17+
kill "${mock_server_pid}" >/dev/null 2>&1 || true
18+
fi
19+
rm -f "${mock_server_port_file:-}" 2>/dev/null || true
1720
if [ -n "${nvm_alias_bak:-}" ]; then
1821
rm -rf "${nvm_alias_dir}" 2>/dev/null || true
1922
mv "${nvm_alias_bak}" "${nvm_alias_dir}" 2>/dev/null || true
@@ -63,31 +66,33 @@ done
6366
[ -n "${mock_proxy_port}" ] || die 'the mock proxy did not report a port'
6467
proxy_url="http://127.0.0.1:${mock_proxy_port}"
6568

69+
# start the mock server (which provides the origin endpoints) with the
70+
# installed node, on an ephemeral port
71+
mock_server_port_file="$(mktemp)"
72+
"${NODE_BIN}" "../mocks/mock-server.js" "${mock_server_port_file}" >/dev/null 2>&1 &
73+
mock_server_pid="$!"
74+
mock_server_port=''
75+
i=0
76+
while [ "${i}" -lt 10 ]; do
77+
if [ -s "${mock_server_port_file}" ]; then
78+
mock_server_port="$(cat "${mock_server_port_file}")"
79+
break
80+
fi
81+
i=$((i + 1))
82+
sleep 1
83+
done
84+
[ -n "${mock_server_port}" ] || die 'the mock server did not report a port'
85+
6686
# make sure no_proxy does not bypass the proxy for these tests
6787
unset no_proxy NO_PROXY
6888

69-
# the proxy header checks need a local httpbin container (as the nvm_download
70-
# fast test); retry the pull, and skip (rather than fail) if the image cannot
71-
# be pulled or run, so a transient Docker registry outage does not fail the
72-
# suite
73-
httpbin_pulled=0
74-
for i in 1 2 3 4 5; do
75-
if docker pull kennethreitz/httpbin; then httpbin_pulled=1; break; fi
76-
echo "docker pull httpbin failed, attempt $i/5"
77-
sleep $((i * 5))
78-
done
79-
if [ "${httpbin_pulled}" = 1 ] && SHELL=bash docker run -d --name httpbin -p 80:80 kennethreitz/httpbin; then
80-
sleep 1 # wait for httpbin to start
81-
# no Authorization and no Proxy-Authorization: expected fail
82-
http_proxy="${proxy_url}" nvm_download "http://127.0.0.1/get" > /dev/null && die 'nvm_download with no Authorization and no Proxy-Authorization header should fail'
83-
# Authorization but no Proxy-Authorization: expected fail
84-
NVM_AUTH_HEADER="Bearer test-token" http_proxy="${proxy_url}" nvm_download "http://127.0.0.1/bearer" > /dev/null && die 'nvm_download with Authorization but no Proxy-Authorization header should fail'
85-
# no Authorization but Proxy-Authorization: expected fail
86-
NVM_PROXY_AUTH_HEADER="Bearer proxy-token" http_proxy="${proxy_url}" nvm_download "http://127.0.0.1/bearer" > /dev/null && die 'nvm_download with Proxy-Authorization but no Authorization header should fail'
87-
# Authorization and Proxy-Authorization: expected success
88-
NVM_AUTH_HEADER="Bearer test-token" NVM_PROXY_AUTH_HEADER="Bearer proxy-token" http_proxy="${proxy_url}" nvm_download "http://127.0.0.1/bearer" > /dev/null || die 'nvm_download with Authorization and Proxy-Authorization headers should succeed'
89-
else
90-
echo 'skipping proxy header checks: unable to pull or run httpbin'
91-
fi
89+
# no Authorization and no Proxy-Authorization: expected fail
90+
http_proxy="${proxy_url}" nvm_download "http://127.0.0.1:${mock_server_port}/get" > /dev/null && die 'nvm_download with no Authorization and no Proxy-Authorization header should fail'
91+
# Authorization but no Proxy-Authorization: expected fail
92+
NVM_AUTH_HEADER="Bearer test-token" http_proxy="${proxy_url}" nvm_download "http://127.0.0.1:${mock_server_port}/bearer" > /dev/null && die 'nvm_download with Authorization but no Proxy-Authorization header should fail'
93+
# no Authorization but Proxy-Authorization: expected fail
94+
NVM_PROXY_AUTH_HEADER="Bearer proxy-token" http_proxy="${proxy_url}" nvm_download "http://127.0.0.1:${mock_server_port}/bearer" > /dev/null && die 'nvm_download with Proxy-Authorization but no Authorization header should fail'
95+
# Authorization and Proxy-Authorization: expected success
96+
NVM_AUTH_HEADER="Bearer test-token" NVM_PROXY_AUTH_HEADER="Bearer proxy-token" http_proxy="${proxy_url}" nvm_download "http://127.0.0.1:${mock_server_port}/bearer" > /dev/null || die 'nvm_download with Authorization and Proxy-Authorization headers should succeed'
9297

9398
cleanup

0 commit comments

Comments
 (0)