1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-21 23:04:45 -05:00

chore(cli): One Rust test per JS and Node unit test file (#19199)

This runs our `js_unit_tests` and `node_unit_tests` in parallel, one
rust test per JS unit test file. Some of our JS tests don't like running
in parallel due to port requirements, so this also makes those use a
specific port-per-file. This does not attempt to make the node-compat
tests work.
This commit is contained in:
Matt Mastracci 2023-05-22 13:35:59 -06:00 committed by GitHub
parent ffa020f43a
commit 612226de8e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 564 additions and 196 deletions

1
Cargo.lock generated
View file

@ -5087,6 +5087,7 @@ dependencies = [
"fastwebsockets",
"flate2",
"futures",
"glob",
"hyper 0.14.26",
"lazy-regex",
"lsp-types",

View file

@ -96,6 +96,7 @@ filetime = "0.2.16"
flate2 = "=1.0.24"
fs3 = "0.5.0"
futures = "0.3.21"
glob = "0.3.1"
hex = "0.4"
http = "0.2.9"
httparse = "1.8.0"

View file

@ -1,27 +1,113 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use std::io::BufRead;
use std::io::BufReader;
use std::process::Stdio;
use std::time::Duration;
use std::time::Instant;
use test_util as util;
#[test]
fn js_unit_tests_lint() {
let status = util::deno_cmd()
.arg("lint")
.arg("--unstable")
.arg(util::tests_path().join("unit"))
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
}
util::unit_test_factory!(
js_unit_test,
"tests/unit",
"*.ts",
[
abort_controller_test,
blob_test,
body_test,
broadcast_channel_test,
buffer_test,
build_test,
cache_api_test,
chmod_test,
chown_test,
command_test,
console_test,
copy_file_test,
custom_event_test,
dir_test,
dom_exception_test,
error_stack_test,
error_test,
esnext_test,
event_target_test,
event_test,
fetch_test,
ffi_test,
file_test,
filereader_test,
files_test,
flock_test,
fs_events_test,
get_random_values_test,
globals_test,
headers_test,
http_test,
internals_test,
intl_test,
io_test,
kv_test,
link_test,
make_temp_test,
message_channel_test,
metrics_test,
mkdir_test,
navigator_test,
net_test,
network_interfaces_test,
opcall_test,
os_test,
path_from_url_test,
performance_test,
permissions_test,
process_test,
progressevent_test,
promise_hooks_test,
read_dir_test,
read_file_test,
read_link_test,
read_text_file_test,
real_path_test,
ref_unref_test,
remove_test,
rename_test,
request_test,
resources_test,
response_test,
serve_test,
signal_test,
stat_test,
stdio_test,
structured_clone_test,
symlink_test,
sync_test,
test_util,
testing_test,
text_encoding_test,
timers_test,
tls_test,
truncate_test,
tty_color_test,
tty_test,
umask_test,
url_search_params_test,
url_test,
urlpattern_test,
utime_test,
version_test,
wasm_test,
webcrypto_test,
websocket_test,
webstorage_test,
worker_permissions_test,
worker_types,
write_file_test,
write_text_file_test,
]
);
#[test]
fn js_unit_tests() {
fn js_unit_test(test: String) {
let _g = util::http_server();
// Note that the unit tests are not safe for concurrency and must be run with a concurrency limit
// of one because there are some chdir tests in there.
// TODO(caspervonb) split these tests into two groups: parallel and serial.
let mut deno = util::deno_cmd()
.current_dir(util::root_path())
.arg("test")
@ -29,11 +115,58 @@ fn js_unit_tests() {
.arg("--location=http://js-unit-tests/foo/bar")
.arg("--no-prompt")
.arg("-A")
.arg(util::tests_path().join("unit"))
.arg(util::tests_path().join("unit").join(format!("{test}.ts")))
.stderr(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("failed to spawn script");
let status = deno.wait().expect("failed to wait for the child process");
let now = Instant::now();
let stdout = deno.stdout.take().unwrap();
let test_name = test.clone();
let stdout = std::thread::spawn(move || {
let reader = BufReader::new(stdout);
for line in reader.lines() {
if let Ok(line) = line {
println!("[{test_name} {:0>6.2}] {line}", now.elapsed().as_secs_f32());
} else {
break;
}
}
});
let now = Instant::now();
let stderr = deno.stderr.take().unwrap();
let test_name = test.clone();
let stderr = std::thread::spawn(move || {
let reader = BufReader::new(stderr);
for line in reader.lines() {
if let Ok(line) = line {
eprintln!("[{test_name} {:0>6.2}] {line}", now.elapsed().as_secs_f32());
} else {
break;
}
}
});
const PER_TEST_TIMEOUT: Duration = Duration::from_secs(2 * 60);
let now = Instant::now();
let status = loop {
if now.elapsed() > PER_TEST_TIMEOUT {
// Last-ditch kill
_ = deno.kill();
panic!("Test {test} failed to complete in time");
}
if let Some(status) = deno
.try_wait()
.expect("failed to wait for the child process")
{
break status;
}
std::thread::sleep(Duration::from_millis(100));
};
#[cfg(unix)]
assert_eq!(
std::os::unix::process::ExitStatusExt::signal(&status),
@ -41,5 +174,9 @@ fn js_unit_tests() {
"Deno should not have died with a signal"
);
assert_eq!(Some(0), status.code(), "Deno should have exited cleanly");
stdout.join().unwrap();
stderr.join().unwrap();
assert!(status.success());
}

View file

@ -1,12 +1,80 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use std::io::BufRead;
use std::io::BufReader;
use std::process::Stdio;
use std::time::Duration;
use std::time::Instant;
use test_util as util;
#[test]
fn node_unit_tests() {
util::unit_test_factory!(
node_unit_test,
"tests/unit_node",
"**/*_test.ts",
[
_fs_access_test = _fs / _fs_access_test,
_fs_appendFile_test = _fs / _fs_appendFile_test,
_fs_chmod_test = _fs / _fs_chmod_test,
_fs_chown_test = _fs / _fs_chown_test,
_fs_close_test = _fs / _fs_close_test,
_fs_copy_test = _fs / _fs_copy_test,
_fs_dir_test = _fs / _fs_dir_test,
_fs_exists_test = _fs / _fs_exists_test,
_fs_fdatasync_test = _fs / _fs_fdatasync_test,
_fs_fstat_test = _fs / _fs_fstat_test,
_fs_fsync_test = _fs / _fs_fsync_test,
_fs_ftruncate_test = _fs / _fs_ftruncate_test,
_fs_futimes_test = _fs / _fs_futimes_test,
_fs_link_test = _fs / _fs_link_test,
_fs_lstat_test = _fs / _fs_lstat_test,
_fs_mkdir_test = _fs / _fs_mkdir_test,
_fs_mkdtemp_test = _fs / _fs_mkdtemp_test,
_fs_opendir_test = _fs / _fs_opendir_test,
_fs_readFile_test = _fs / _fs_readFile_test,
_fs_readdir_test = _fs / _fs_readdir_test,
_fs_readlink_test = _fs / _fs_readlink_test,
_fs_realpath_test = _fs / _fs_realpath_test,
_fs_rename_test = _fs / _fs_rename_test,
_fs_rm_test = _fs / _fs_rm_test,
_fs_rmdir_test = _fs / _fs_rmdir_test,
_fs_stat_test = _fs / _fs_stat_test,
_fs_symlink_test = _fs / _fs_symlink_test,
_fs_truncate_test = _fs / _fs_truncate_test,
_fs_unlink_test = _fs / _fs_unlink_test,
_fs_utimes_test = _fs / _fs_utimes_test,
_fs_watch_test = _fs / _fs_watch_test,
_fs_write_test = _fs / _fs_write_test,
async_hooks_test,
child_process_test,
crypto_cipher_test = crypto / crypto_cipher_test,
crypto_hash_test = crypto / crypto_hash_test,
crypto_key_test = crypto / crypto_key_test,
crypto_sign_test = crypto / crypto_sign_test,
fs_test,
http_test,
_randomBytes_test = internal / _randomBytes_test,
_randomFill_test = internal / _randomFill_test,
_randomInt_test = internal / _randomInt_test,
pbkdf2_test = internal / pbkdf2_test,
scrypt_test = internal / scrypt_test,
module_test,
process_test,
querystring_test,
readline_test,
string_decoder_test,
timers_test,
tls_test,
tty_test,
util_test,
v8_test,
worker_threads_test
]
);
fn node_unit_test(test: String) {
let _g = util::http_server();
let mut deno = util::deno_cmd()
let mut deno = util::deno_cmd();
let mut deno = deno
.current_dir(util::root_path())
.arg("test")
.arg("--unstable")
@ -14,12 +82,78 @@ fn node_unit_tests() {
// but this shouldn't be necessary. tls.connect currently doesn't
// pass hostname option correctly and it causes cert errors.
.arg("--unsafely-ignore-certificate-errors")
.arg("-A")
.arg(util::tests_path().join("unit_node"))
.arg("-A");
// Parallel tests for crypto
if test.starts_with("crypto/") {
deno = deno.arg("--parallel");
}
let mut deno = deno
.arg(
util::tests_path()
.join("unit_node")
.join(format!("{test}.ts")),
)
.stderr(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("failed to spawn script");
let status = deno.wait().expect("failed to wait for the child process");
assert_eq!(Some(0), status.code());
let now = Instant::now();
let stdout = deno.stdout.take().unwrap();
let test_name = test.clone();
let stdout = std::thread::spawn(move || {
let reader = BufReader::new(stdout);
for line in reader.lines() {
if let Ok(line) = line {
println!("[{test_name} {:0>6.2}] {line}", now.elapsed().as_secs_f32());
} else {
break;
}
}
});
let now = Instant::now();
let stderr = deno.stderr.take().unwrap();
let test_name = test.clone();
let stderr = std::thread::spawn(move || {
let reader = BufReader::new(stderr);
for line in reader.lines() {
if let Ok(line) = line {
eprintln!("[{test_name} {:0>6.2}] {line}", now.elapsed().as_secs_f32());
} else {
break;
}
}
});
const PER_TEST_TIMEOUT: Duration = Duration::from_secs(5 * 60);
let now = Instant::now();
let status = loop {
if now.elapsed() > PER_TEST_TIMEOUT {
// Last-ditch kill
_ = deno.kill();
panic!("Test {test} failed to complete in time");
}
if let Some(status) = deno
.try_wait()
.expect("failed to wait for the child process")
{
break status;
}
std::thread::sleep(Duration::from_millis(100));
};
#[cfg(unix)]
assert_eq!(
std::os::unix::process::ExitStatusExt::signal(&status),
None,
"Deno should not have died with a signal"
);
assert_eq!(Some(0), status.code(), "Deno should have exited cleanly");
stdout.join().unwrap();
stderr.join().unwrap();
assert!(status.success());
}

View file

@ -10,6 +10,8 @@ import {
} from "./test_util.ts";
import { Buffer } from "../../../test_util/std/io/buffer.ts";
const listenPort = 4504;
Deno.test(
{ permissions: { net: true } },
async function fetchRequiresOneArgument() {
@ -639,7 +641,7 @@ Deno.test(
permissions: { net: true },
},
async function fetchRequest() {
const addr = "127.0.0.1:4501";
const addr = `127.0.0.1:${listenPort}`;
const bufPromise = bufferServer(addr);
const response = await fetch(`http://${addr}/blah`, {
method: "POST",
@ -673,7 +675,7 @@ Deno.test(
permissions: { net: true },
},
async function fetchRequestAcceptHeaders() {
const addr = "127.0.0.1:4501";
const addr = `127.0.0.1:${listenPort}`;
const bufPromise = bufferServer(addr);
const response = await fetch(`http://${addr}/blah`, {
method: "POST",
@ -705,7 +707,7 @@ Deno.test(
permissions: { net: true },
},
async function fetchPostBodyString() {
const addr = "127.0.0.1:4511";
const addr = `127.0.0.1:${listenPort}`;
const bufPromise = bufferServer(addr);
const body = "hello world";
const response = await fetch(`http://${addr}/blah`, {
@ -743,7 +745,7 @@ Deno.test(
permissions: { net: true },
},
async function fetchPostBodyTypedArray() {
const addr = "127.0.0.1:4503";
const addr = `127.0.0.1:${listenPort}`;
const bufPromise = bufferServer(addr);
const bodyStr = "hello world";
const body = new TextEncoder().encode(bodyStr);
@ -781,7 +783,7 @@ Deno.test(
permissions: { net: true },
},
async function fetchUserSetContentLength() {
const addr = "127.0.0.1:4501";
const addr = `127.0.0.1:${listenPort}`;
const bufPromise = bufferServer(addr);
const response = await fetch(`http://${addr}/blah`, {
method: "POST",
@ -812,7 +814,7 @@ Deno.test(
permissions: { net: true },
},
async function fetchUserSetTransferEncoding() {
const addr = "127.0.0.1:4501";
const addr = `127.0.0.1:${listenPort}`;
const bufPromise = bufferServer(addr);
const response = await fetch(`http://${addr}/blah`, {
method: "POST",
@ -1158,7 +1160,7 @@ Deno.test(
permissions: { net: true },
},
async function fetchPostBodyReadableStream() {
const addr = "127.0.0.1:4511";
const addr = `127.0.0.1:${listenPort}`;
const bufPromise = bufferServer(addr);
const stream = new TransformStream();
const writer = stream.writable.getWriter();
@ -1217,7 +1219,7 @@ Deno.test(
async function fetchFilterOutCustomHostHeader(): Promise<
void
> {
const addr = "127.0.0.1:4511";
const addr = `127.0.0.1:${listenPort}`;
const [hostname, port] = addr.split(":");
const listener = Deno.listen({
hostname,
@ -1717,7 +1719,7 @@ Deno.test(
async function fetchWithInvalidContentLengthAndTransferEncoding(): Promise<
void
> {
const addr = "127.0.0.1:4516";
const addr = `127.0.0.1:${listenPort}`;
const data = "a".repeat(10 << 10);
const body = new TextEncoder().encode(
@ -1749,7 +1751,7 @@ Deno.test(
async function fetchWithInvalidContentLength(): Promise<
void
> {
const addr = "127.0.0.1:4517";
const addr = `127.0.0.1:${listenPort}`;
const data = "a".repeat(10 << 10);
const body = new TextEncoder().encode(
@ -1777,7 +1779,7 @@ Deno.test(
async function fetchWithInvalidContentLength(): Promise<
void
> {
const addr = "127.0.0.1:4518";
const addr = `127.0.0.1:${listenPort}`;
const data = "a".repeat(10 << 10);
const contentLength = data.length / 2;
@ -1804,7 +1806,7 @@ Deno.test(
async function fetchWithInvalidContentLength(): Promise<
void
> {
const addr = "127.0.0.1:4519";
const addr = `127.0.0.1:${listenPort}`;
const data = "a".repeat(10 << 10);
const contentLength = data.length * 2;

View file

@ -12,6 +12,10 @@ import {
} from "./test_util.ts";
import { join } from "../../../test_util/std/path/mod.ts";
// Since these tests may run in parallel, ensure this port is unique to this file
const listenPort = 4503;
const listenPort2 = 4504;
let isCI: boolean;
try {
isCI = Deno.env.get("CI") !== undefined;
@ -20,10 +24,10 @@ try {
}
Deno.test({ permissions: { net: true } }, function netTcpListenClose() {
const listener = Deno.listen({ hostname: "127.0.0.1", port: 3500 });
const listener = Deno.listen({ hostname: "127.0.0.1", port: listenPort });
assert(listener.addr.transport === "tcp");
assertEquals(listener.addr.hostname, "127.0.0.1");
assertEquals(listener.addr.port, 3500);
assertEquals(listener.addr.port, listenPort);
assertNotEquals(listener.rid, 0);
listener.close();
});
@ -35,12 +39,12 @@ Deno.test(
function netUdpListenClose() {
const socket = Deno.listenDatagram({
hostname: "127.0.0.1",
port: 3500,
port: listenPort,
transport: "udp",
});
assert(socket.addr.transport === "udp");
assertEquals(socket.addr.hostname, "127.0.0.1");
assertEquals(socket.addr.port, 3500);
assertEquals(socket.addr.port, listenPort);
socket.close();
},
);
@ -127,7 +131,7 @@ Deno.test(
permissions: { net: true },
},
async function netTcpCloseWhileAccept() {
const listener = Deno.listen({ port: 4501 });
const listener = Deno.listen({ port: listenPort });
const p = listener.accept();
listener.close();
// TODO(piscisaureus): the error type should be `Interrupted` here, which
@ -212,22 +216,22 @@ Deno.test(
);
Deno.test({ permissions: { net: true } }, async function netTcpDialListen() {
const listener = Deno.listen({ port: 3500 });
const listener = Deno.listen({ port: listenPort });
listener.accept().then(
async (conn) => {
assert(conn.remoteAddr != null);
assert(conn.localAddr.transport === "tcp");
assertEquals(conn.localAddr.hostname, "127.0.0.1");
assertEquals(conn.localAddr.port, 3500);
assertEquals(conn.localAddr.port, listenPort);
await conn.write(new Uint8Array([1, 2, 3]));
conn.close();
},
);
const conn = await Deno.connect({ hostname: "127.0.0.1", port: 3500 });
const conn = await Deno.connect({ hostname: "127.0.0.1", port: listenPort });
assert(conn.remoteAddr.transport === "tcp");
assertEquals(conn.remoteAddr.hostname, "127.0.0.1");
assertEquals(conn.remoteAddr.port, 3500);
assertEquals(conn.remoteAddr.port, listenPort);
assert(conn.localAddr != null);
const buf = new Uint8Array(1024);
const readResult = await conn.read(buf);
@ -247,23 +251,23 @@ Deno.test({ permissions: { net: true } }, async function netTcpDialListen() {
});
Deno.test({ permissions: { net: true } }, async function netTcpSetNoDelay() {
const listener = Deno.listen({ port: 3500 });
const listener = Deno.listen({ port: listenPort });
listener.accept().then(
async (conn) => {
assert(conn.remoteAddr != null);
assert(conn.localAddr.transport === "tcp");
assertEquals(conn.localAddr.hostname, "127.0.0.1");
assertEquals(conn.localAddr.port, 3500);
assertEquals(conn.localAddr.port, listenPort);
await conn.write(new Uint8Array([1, 2, 3]));
conn.close();
},
);
const conn = await Deno.connect({ hostname: "127.0.0.1", port: 3500 });
const conn = await Deno.connect({ hostname: "127.0.0.1", port: listenPort });
conn.setNoDelay(true);
assert(conn.remoteAddr.transport === "tcp");
assertEquals(conn.remoteAddr.hostname, "127.0.0.1");
assertEquals(conn.remoteAddr.port, 3500);
assertEquals(conn.remoteAddr.port, listenPort);
assert(conn.localAddr != null);
const buf = new Uint8Array(1024);
const readResult = await conn.read(buf);
@ -283,23 +287,23 @@ Deno.test({ permissions: { net: true } }, async function netTcpSetNoDelay() {
});
Deno.test({ permissions: { net: true } }, async function netTcpSetKeepAlive() {
const listener = Deno.listen({ port: 3500 });
const listener = Deno.listen({ port: listenPort });
listener.accept().then(
async (conn) => {
assert(conn.remoteAddr != null);
assert(conn.localAddr.transport === "tcp");
assertEquals(conn.localAddr.hostname, "127.0.0.1");
assertEquals(conn.localAddr.port, 3500);
assertEquals(conn.localAddr.port, listenPort);
await conn.write(new Uint8Array([1, 2, 3]));
conn.close();
},
);
const conn = await Deno.connect({ hostname: "127.0.0.1", port: 3500 });
const conn = await Deno.connect({ hostname: "127.0.0.1", port: listenPort });
conn.setKeepAlive(true);
assert(conn.remoteAddr.transport === "tcp");
assertEquals(conn.remoteAddr.hostname, "127.0.0.1");
assertEquals(conn.remoteAddr.port, 3500);
assertEquals(conn.remoteAddr.port, listenPort);
assert(conn.localAddr != null);
const buf = new Uint8Array(1024);
const readResult = await conn.read(buf);
@ -360,14 +364,14 @@ Deno.test(
Deno.test(
{ permissions: { net: true } },
async function netUdpSendReceive() {
const alice = Deno.listenDatagram({ port: 3500, transport: "udp" });
const alice = Deno.listenDatagram({ port: listenPort, transport: "udp" });
assert(alice.addr.transport === "udp");
assertEquals(alice.addr.port, 3500);
assertEquals(alice.addr.port, listenPort);
assertEquals(alice.addr.hostname, "127.0.0.1");
const bob = Deno.listenDatagram({ port: 4501, transport: "udp" });
const bob = Deno.listenDatagram({ port: listenPort2, transport: "udp" });
assert(bob.addr.transport === "udp");
assertEquals(bob.addr.port, 4501);
assertEquals(bob.addr.port, listenPort2);
assertEquals(bob.addr.hostname, "127.0.0.1");
const sent = new Uint8Array([1, 2, 3]);
@ -377,7 +381,7 @@ Deno.test(
const [recvd, remote] = await bob.receive();
assert(remote.transport === "udp");
assertEquals(remote.port, 3500);
assertEquals(remote.port, listenPort);
assertEquals(recvd.length, 3);
assertEquals(1, recvd[0]);
assertEquals(2, recvd[1]);
@ -393,18 +397,18 @@ Deno.test(
// Must bind sender to an address that can send to the broadcast address on MacOS.
// Macos will give us error 49 when sending the broadcast packet if we omit hostname here.
const alice = Deno.listenDatagram({
port: 3500,
port: listenPort,
transport: "udp",
hostname: "0.0.0.0",
});
const bob = Deno.listenDatagram({
port: 4501,
port: listenPort,
transport: "udp",
hostname: "0.0.0.0",
});
assert(bob.addr.transport === "udp");
assertEquals(bob.addr.port, 4501);
assertEquals(bob.addr.port, listenPort);
assertEquals(bob.addr.hostname, "0.0.0.0");
const broadcastAddr = { ...bob.addr, hostname: "255.255.255.255" };
@ -415,7 +419,7 @@ Deno.test(
assertEquals(byteLength, 3);
const [recvd, remote] = await bob.receive();
assert(remote.transport === "udp");
assertEquals(remote.port, 3500);
assertEquals(remote.port, listenPort);
assertEquals(recvd.length, 3);
assertEquals(1, recvd[0]);
assertEquals(2, recvd[1]);
@ -563,9 +567,9 @@ Deno.test(
Deno.test(
{ permissions: { net: true } },
async function netUdpConcurrentSendReceive() {
const socket = Deno.listenDatagram({ port: 3500, transport: "udp" });
const socket = Deno.listenDatagram({ port: listenPort, transport: "udp" });
assert(socket.addr.transport === "udp");
assertEquals(socket.addr.port, 3500);
assertEquals(socket.addr.port, listenPort);
assertEquals(socket.addr.hostname, "127.0.0.1");
const recvPromise = socket.receive();
@ -588,7 +592,7 @@ Deno.test(
{ permissions: { net: true } },
async function netUdpBorrowMutError() {
const socket = Deno.listenDatagram({
port: 4501,
port: listenPort,
transport: "udp",
});
// Panic happened on second send: BorrowMutError
@ -761,7 +765,7 @@ Deno.test(
Deno.test(
{ permissions: { net: true } },
async function netListenAsyncIterator() {
const addr = { hostname: "127.0.0.1", port: 3500 };
const addr = { hostname: "127.0.0.1", port: listenPort };
const listener = Deno.listen(addr);
const runAsyncIterator = async () => {
for await (const conn of listener) {
@ -794,7 +798,7 @@ Deno.test(
permissions: { net: true },
},
async function netCloseWriteSuccess() {
const addr = { hostname: "127.0.0.1", port: 3500 };
const addr = { hostname: "127.0.0.1", port: listenPort };
const listener = Deno.listen(addr);
const closeDeferred = deferred();
listener.accept().then(async (conn) => {
@ -850,7 +854,7 @@ Deno.test(
}
}
const addr = { hostname: "127.0.0.1", port: 3500 };
const addr = { hostname: "127.0.0.1", port: listenPort };
const listener = Deno.listen(addr);
const listenerPromise = iteratorReq(listener);
const connectionPromise = (async () => {
@ -898,13 +902,13 @@ Deno.test(
Deno.test({ permissions: { net: true } }, async function whatwgStreams() {
(async () => {
const listener = Deno.listen({ hostname: "127.0.0.1", port: 3500 });
const listener = Deno.listen({ hostname: "127.0.0.1", port: listenPort });
const conn = await listener.accept();
await conn.readable.pipeTo(conn.writable);
listener.close();
})();
const conn = await Deno.connect({ hostname: "127.0.0.1", port: 3500 });
const conn = await Deno.connect({ hostname: "127.0.0.1", port: listenPort });
const reader = conn.readable.getReader();
const writer = conn.writable.getWriter();
const encoder = new TextEncoder();
@ -957,7 +961,7 @@ Deno.test(
async function netListenUnref() {
const [statusCode, _output] = await execCode(`
async function main() {
const listener = Deno.listen({ port: 3500 });
const listener = Deno.listen({ port: ${listenPort} });
listener.unref();
await listener.accept(); // This doesn't block the program from exiting
}
@ -972,14 +976,14 @@ Deno.test(
async function netListenUnref() {
const [statusCode, _output] = await execCode(`
async function main() {
const listener = Deno.listen({ port: 3500 });
const listener = Deno.listen({ port: ${listenPort} });
await listener.accept();
listener.unref();
await listener.accept(); // The program exits here
throw new Error(); // The program doesn't reach here
}
main();
const conn = await Deno.connect({ port: 3500 });
const conn = await Deno.connect({ port: ${listenPort} });
conn.close();
`);
assertEquals(statusCode, 0);
@ -991,7 +995,7 @@ Deno.test(
async function netListenUnrefAndRef() {
const p = execCode2(`
async function main() {
const listener = Deno.listen({ port: 3500 });
const listener = Deno.listen({ port: ${listenPort} });
listener.unref();
listener.ref(); // This restores 'ref' state of listener
console.log("started");
@ -1001,7 +1005,7 @@ Deno.test(
main();
`);
await p.waitStdoutText("started");
const conn = await Deno.connect({ port: 3500 });
const conn = await Deno.connect({ port: listenPort });
conn.close();
const [statusCode, output] = await p.finished();
assertEquals(statusCode, 0);
@ -1013,7 +1017,7 @@ Deno.test(
{ permissions: { net: true } },
async function netListenUnrefConcurrentAccept() {
const timer = setTimeout(() => {}, 1000);
const listener = Deno.listen({ port: 3500 });
const listener = Deno.listen({ port: listenPort });
listener.accept().catch(() => {});
listener.unref();
// Unref'd listener still causes Busy error
@ -1044,12 +1048,12 @@ Deno.test({
Deno.test(
{ permissions: { net: true, read: true, run: true } },
async function netConnUnref() {
const listener = Deno.listen({ port: 3500 });
const listener = Deno.listen({ port: listenPort });
const intervalId = setInterval(() => {}); // This keeps event loop alive.
const program = execCode(`
async function main() {
const conn = await Deno.connect({ port: 3500 });
const conn = await Deno.connect({ port: ${listenPort} });
conn.unref();
await conn.read(new Uint8Array(10)); // The program exits here
throw new Error(); // The program doesn't reach here
@ -1068,12 +1072,12 @@ Deno.test(
Deno.test(
{ permissions: { net: true, read: true, run: true } },
async function netConnUnrefReadable() {
const listener = Deno.listen({ port: 3500 });
const listener = Deno.listen({ port: listenPort });
const intervalId = setInterval(() => {}); // This keeps event loop alive.
const program = execCode(`
async function main() {
const conn = await Deno.connect({ port: 3500 });
const conn = await Deno.connect({ port: ${listenPort} });
conn.unref();
const reader = conn.readable.getReader();
await reader.read(); // The program exits here
@ -1093,7 +1097,7 @@ Deno.test(
Deno.test({ permissions: { net: true } }, async function netTcpReuseAddr() {
const listener1 = Deno.listen({
hostname: "127.0.0.1",
port: 3500,
port: listenPort,
});
listener1.accept().then(
(conn) => {
@ -1101,7 +1105,7 @@ Deno.test({ permissions: { net: true } }, async function netTcpReuseAddr() {
},
);
const conn1 = await Deno.connect({ hostname: "127.0.0.1", port: 3500 });
const conn1 = await Deno.connect({ hostname: "127.0.0.1", port: listenPort });
const buf1 = new Uint8Array(1024);
await conn1.read(buf1);
listener1.close();
@ -1109,7 +1113,7 @@ Deno.test({ permissions: { net: true } }, async function netTcpReuseAddr() {
const listener2 = Deno.listen({
hostname: "127.0.0.1",
port: 3500,
port: listenPort,
});
listener2.accept().then(
@ -1118,7 +1122,7 @@ Deno.test({ permissions: { net: true } }, async function netTcpReuseAddr() {
},
);
const conn2 = await Deno.connect({ hostname: "127.0.0.1", port: 3500 });
const conn2 = await Deno.connect({ hostname: "127.0.0.1", port: listenPort });
const buf2 = new Uint8Array(1024);
await conn2.read(buf2);

View file

@ -1,6 +1,8 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
import { assert, assertEquals, assertThrows } from "./test_util.ts";
const listenPort = 4505;
Deno.test(function resourcesCloseBadArgs() {
assertThrows(() => {
Deno.close((null as unknown) as number);
@ -16,8 +18,8 @@ Deno.test(function resourcesStdio() {
});
Deno.test({ permissions: { net: true } }, async function resourcesNet() {
const listener = Deno.listen({ port: 4501 });
const dialerConn = await Deno.connect({ port: 4501 });
const listener = Deno.listen({ port: listenPort });
const dialerConn = await Deno.connect({ port: listenPort });
const listenerConn = await listener.accept();
const res = Deno.resources();

View file

@ -14,6 +14,9 @@ import {
fail,
} from "./test_util.ts";
// Since these tests may run in parallel, ensure this port is unique to this file
const servePort = 4502;
const {
upgradeHttpRaw,
addTrailers,
@ -42,18 +45,18 @@ Deno.test(async function httpServerShutsDownPortBeforeResolving() {
const server = Deno.serve({
handler: (_req) => new Response("ok"),
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
});
await listeningPromise;
assertThrows(() => Deno.listen({ port: 4501 }));
assertThrows(() => Deno.listen({ port: servePort }));
ac.abort();
await server.finished;
const listener = Deno.listen({ port: 4501 });
const listener = Deno.listen({ port: servePort });
listener!.close();
});
@ -79,14 +82,14 @@ Deno.test(async function httpServerCanResolveHostnames() {
const server = Deno.serve({
handler: (_req) => new Response("ok"),
hostname: "localhost",
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const resp = await fetch("http://localhost:4501/", {
const resp = await fetch(`http://localhost:${servePort}/`, {
headers: { "connection": "close" },
});
const text = await resp.text();
@ -102,7 +105,7 @@ Deno.test(async function httpServerRejectsOnAddrInUse() {
const server = Deno.serve({
handler: (_req) => new Response("ok"),
hostname: "localhost",
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -114,7 +117,7 @@ Deno.test(async function httpServerRejectsOnAddrInUse() {
Deno.serve({
handler: (_req) => new Response("ok"),
hostname: "localhost",
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -135,20 +138,20 @@ Deno.test({ permissions: { net: true } }, async function httpServerBasic() {
// FIXME(bartlomieju):
// make sure that request can be inspected
console.log(request);
assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
assertEquals(new URL(request.url).href, `http://127.0.0.1:${servePort}/`);
assertEquals(await request.text(), "");
assertEquals(remoteAddr.hostname, "127.0.0.1");
promise.resolve();
return new Response("Hello World", { headers: { "foo": "bar" } });
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/", {
const resp = await fetch(`http://127.0.0.1:${servePort}/`, {
headers: { "connection": "close" },
});
await promise;
@ -173,7 +176,7 @@ Deno.test({ permissions: { net: true } }, async function httpServerOnError() {
await new Promise((r) => setTimeout(r, 100));
throw "fail";
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: () => {
@ -182,14 +185,14 @@ Deno.test({ permissions: { net: true } }, async function httpServerOnError() {
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/", {
const resp = await fetch(`http://127.0.0.1:${servePort}/`, {
headers: { "connection": "close" },
});
const text = await resp.text();
ac.abort();
await server;
assertEquals(text, "failed: http://127.0.0.1:4501/");
assertEquals(text, `failed: http://127.0.0.1:${servePort}/`);
});
Deno.test(
@ -208,7 +211,7 @@ Deno.test(
await new Promise((r) => setTimeout(r, 100));
throw "fail";
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: () => {
@ -217,7 +220,7 @@ Deno.test(
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/", {
const resp = await fetch(`http://127.0.0.1:${servePort}/`, {
headers: { "connection": "close" },
});
const text = await resp.text();
@ -234,7 +237,7 @@ Deno.test({ permissions: { net: true } }, async function httpServerOverload1() {
const listeningPromise = deferred();
const server = Deno.serve({
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -242,14 +245,14 @@ Deno.test({ permissions: { net: true } }, async function httpServerOverload1() {
// FIXME(bartlomieju):
// make sure that request can be inspected
console.log(request);
assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
assertEquals(new URL(request.url).href, `http://127.0.0.1:${servePort}/`);
assertEquals(await request.text(), "");
promise.resolve();
return new Response("Hello World", { headers: { "foo": "bar" } });
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/", {
const resp = await fetch(`http://127.0.0.1:${servePort}/`, {
headers: { "connection": "close" },
});
await promise;
@ -269,7 +272,7 @@ Deno.test({ permissions: { net: true } }, async function httpServerOverload2() {
const listeningPromise = deferred();
const server = Deno.serve({
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -277,14 +280,14 @@ Deno.test({ permissions: { net: true } }, async function httpServerOverload2() {
// FIXME(bartlomieju):
// make sure that request can be inspected
console.log(request);
assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
assertEquals(new URL(request.url).href, `http://127.0.0.1:${servePort}/`);
assertEquals(await request.text(), "");
promise.resolve();
return new Response("Hello World", { headers: { "foo": "bar" } });
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/", {
const resp = await fetch(`http://127.0.0.1:${servePort}/`, {
headers: { "connection": "close" },
});
await promise;
@ -387,14 +390,14 @@ Deno.test(
promise.resolve();
return new Response("");
},
port: 2333,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const conn = await Deno.connect({ port: 2333 });
const conn = await Deno.connect({ port: servePort });
// Send GET request with a body + content-length.
const encoder = new TextEncoder();
const body =
@ -525,18 +528,18 @@ Deno.test(
promise.resolve();
return new Response("", { headers: {} });
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const conn = await Deno.connect({ port: 4501 });
const conn = await Deno.connect({ port: servePort });
// Send GET request with a body + content-length.
const encoder = new TextEncoder();
const body =
`GET / HTTP/1.1\r\nHost: 127.0.0.1:4501\r\nContent-Length: 5\r\n\r\n12345`;
`GET / HTTP/1.1\r\nHost: 127.0.0.1:${servePort}\r\nContent-Length: 5\r\n\r\n12345`;
const writeResult = await conn.write(encoder.encode(body));
assertEquals(body.length, writeResult);
@ -590,14 +593,14 @@ function createStreamTest(count: number, delay: number, action: string) {
handler: (_request) => {
return new Response(makeStream(count, delay));
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/");
const resp = await fetch(`http://127.0.0.1:${servePort}/`);
const text = await resp.text();
ac.abort();
@ -643,14 +646,14 @@ Deno.test(
assertEquals("hello world", reqBody);
return new Response("yo");
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/", {
const resp = await fetch(`http://127.0.0.1:${servePort}/`, {
body: stream.readable,
method: "POST",
headers: { "connection": "close" },
@ -667,13 +670,13 @@ Deno.test({ permissions: { net: true } }, async function httpServerClose() {
const listeningPromise = deferred();
const server = Deno.serve({
handler: () => new Response("ok"),
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const client = await Deno.connect({ port: 4501 });
const client = await Deno.connect({ port: servePort });
client.close();
ac.abort();
await server;
@ -692,13 +695,13 @@ Deno.test({ permissions: { net: true } }, async function httpServerCloseGet() {
responsePromise.resolve();
return new Response("ok");
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const conn = await Deno.connect({ port: 4501 });
const conn = await Deno.connect({ port: servePort });
const encoder = new TextEncoder();
const body =
`GET / HTTP/1.1\r\nHost: example.domain\r\nConnection: close\r\n\r\n`;
@ -719,14 +722,14 @@ Deno.test(
const listeningPromise = deferred();
const server = Deno.serve({
handler: () => new Response(new Blob([])),
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/");
const resp = await fetch(`http://127.0.0.1:${servePort}/`);
const respBody = await resp.text();
assertEquals("", respBody);
@ -754,7 +757,7 @@ Deno.test(
});
return new Response(body);
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: (err) => {
@ -768,7 +771,7 @@ Deno.test(
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/");
const resp = await fetch(`http://127.0.0.1:${servePort}/`);
// Incorrectly implemented reader ReadableStream should reject.
assertStringIncludes(await resp.text(), "Failed to execute 'enqueue'");
await errorPromise;
@ -833,7 +836,7 @@ Deno.test({ permissions: { net: true } }, async function httpServerWebSocket() {
};
return response;
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -841,7 +844,7 @@ Deno.test({ permissions: { net: true } }, async function httpServerWebSocket() {
await listeningPromise;
const def = deferred();
const ws = new WebSocket("ws://localhost:4501");
const ws = new WebSocket(`ws://localhost:${servePort}`);
ws.onmessage = (m) => assertEquals(m.data, "foo");
ws.onerror = (e) => {
console.error(e);
@ -887,7 +890,7 @@ Deno.test(
conn.close();
return response;
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -895,7 +898,7 @@ Deno.test(
await listeningPromise;
const conn = await Deno.connect({ port: 4501 });
const conn = await Deno.connect({ port: servePort });
await conn.write(
new TextEncoder().encode(
"GET / HTTP/1.1\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\r\nUpgrade data",
@ -962,7 +965,7 @@ Deno.test(
};
return response;
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -970,7 +973,7 @@ Deno.test(
await listeningPromise;
const def = deferred();
const ws = new WebSocket("ws://localhost:4501");
const ws = new WebSocket(`ws://localhost:${servePort}`);
ws.onmessage = (m) => assertEquals(m.data, "foo");
ws.onerror = (e) => {
console.error(e);
@ -999,7 +1002,7 @@ Deno.test(
socket.onopen = () => socket.close();
return response;
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -1007,7 +1010,7 @@ Deno.test(
await listeningPromise;
const def = deferred();
const ws = new WebSocket("ws://localhost:4501");
const ws = new WebSocket(`ws://localhost:${servePort}`);
ws.onerror = (e) => {
console.error(e);
fail();
@ -1041,7 +1044,7 @@ Deno.test(
};
return response;
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -1049,8 +1052,9 @@ Deno.test(
await listeningPromise;
const def = deferred();
const ws = new WebSocket("ws://localhost:4501");
ws.onmessage = (m) => assertEquals(m.data, "http://localhost:4501/");
const ws = new WebSocket(`ws://localhost:${servePort}`);
ws.onmessage = (m) =>
assertEquals(m.data, `http://localhost:${servePort}/`);
ws.onerror = (e) => {
console.error(e);
fail();
@ -1078,14 +1082,14 @@ Deno.test(
promise.resolve();
return new Response("");
},
port: 2333,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const conn = await Deno.connect({ port: 2333 });
const conn = await Deno.connect({ port: servePort });
// Send GET request with a body + content-length.
const encoder = new TextEncoder();
const smthElse = "x".repeat(16 * 1024 + 256);
@ -1118,14 +1122,14 @@ Deno.test(
promise.resolve();
return new Response("");
},
port: 2333,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const conn = await Deno.connect({ port: 2333 });
const conn = await Deno.connect({ port: servePort });
// Send GET request with a body + content-length.
const encoder = new TextEncoder();
const smthElse = "x".repeat(16 * 1024 + 256);
@ -1161,14 +1165,14 @@ Deno.test(
promise.resolve();
return new Response("");
},
port: 2333,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const conn = await Deno.connect({ port: 2333 });
const conn = await Deno.connect({ port: servePort });
// Send GET request with a body + connection: close.
const encoder = new TextEncoder();
const body =
@ -1191,7 +1195,7 @@ Deno.test(
const ac = new AbortController();
const server = Deno.serve(
{ port: 2333, signal: ac.signal },
{ port: servePort, signal: ac.signal },
(request) => {
assert(request.body);
@ -1203,7 +1207,7 @@ Deno.test(
const ts = new TransformStream();
const writable = ts.writable.getWriter();
const resp = await fetch("http://127.0.0.1:2333/", {
const resp = await fetch(`http://127.0.0.1:${servePort}/`, {
method: "POST",
body: ts.readable,
});
@ -1255,7 +1259,7 @@ Deno.test(
const w = new BufWriter(conn);
const r = new BufReader(conn);
const body = `GET / HTTP/1.1\r\nHost: 127.0.0.1:4501\r\n\r\n`;
const body = `GET / HTTP/1.1\r\nHost: 127.0.0.1:${servePort}\r\n\r\n`;
const writeResult = await w.write(encoder.encode(body));
assertEquals(body.length, writeResult);
await w.flush();
@ -1313,7 +1317,7 @@ Deno.test(
promise.resolve();
return new Response(periodicStream());
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -1321,7 +1325,7 @@ Deno.test(
await listeningPromise;
// start a client
const clientConn = await Deno.connect({ port: 4501 });
const clientConn = await Deno.connect({ port: servePort });
const r1 = await writeRequest(clientConn);
assertEquals(r1, "0\n1\n2\n");
@ -1345,16 +1349,16 @@ Deno.test(
promise.resolve();
return new Response("hello", { headers: { "X-Header-Test": "Æ" } });
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const clientConn = await Deno.connect({ port: 4501 });
const clientConn = await Deno.connect({ port: servePort });
const requestText =
"GET / HTTP/1.1\r\nHost: 127.0.0.1:4501\r\nX-Header-Test: á\r\n\r\n";
`GET / HTTP/1.1\r\nHost: 127.0.0.1:${servePort}\r\nX-Header-Test: á\r\n\r\n`;
const requestBytes = new Uint8Array(requestText.length);
for (let i = 0; i < requestText.length; i++) {
requestBytes[i] = requestText.charCodeAt(i);
@ -1388,19 +1392,19 @@ Deno.test(
const server = Deno.serve({
handler: async (request) => {
// FIXME:
// assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
// assertEquals(new URL(request.url).href, `http://127.0.0.1:${servePort}/`);
assertEquals(await request.text(), "");
promise.resolve();
return new Response("11");
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const clientConn = await Deno.connect({ port: 4501 });
const clientConn = await Deno.connect({ port: servePort });
async function writeRequest(conn: Deno.Conn) {
const encoder = new TextEncoder();
@ -1408,7 +1412,7 @@ Deno.test(
const w = new BufWriter(conn);
const r = new BufReader(conn);
const body =
`CONNECT 127.0.0.1:4501 HTTP/1.1\r\nHost: 127.0.0.1:4501\r\n\r\n`;
`CONNECT 127.0.0.1:${servePort} HTTP/1.1\r\nHost: 127.0.0.1:${servePort}\r\n\r\n`;
const writeResult = await w.write(encoder.encode(body));
assertEquals(body.length, writeResult);
await w.flush();
@ -1446,7 +1450,7 @@ Deno.test(
promise.resolve();
return new Response("ok");
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -1454,7 +1458,7 @@ Deno.test(
});
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/", {
const resp = await fetch(`http://127.0.0.1:${servePort}/`, {
headers: [
["connection", "close"],
["cookie", "foo=bar"],
@ -1482,21 +1486,20 @@ Deno.test(
const ac = new AbortController();
const hostname = "localhost";
const port = 4501;
const server = Deno.serve({
handler: () => {
promise.resolve();
return new Response("ok");
},
port: port,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const url = `http://${hostname}:${port}/`;
const url = `http://${hostname}:${servePort}/`;
const args = ["-X", "DELETE", url];
const { success } = await new Deno.Command("curl", {
args,
@ -1525,13 +1528,13 @@ Deno.test(
promise.resolve();
return new Response(new Uint8Array([128]));
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
});
await listeningPromise;
const resp = await fetch("http://localhost:4501/");
const resp = await fetch(`http://localhost:${servePort}/`);
await promise;
@ -2211,12 +2214,11 @@ Deno.test(
const ac = new AbortController();
const listeningPromise = deferred();
const hostname = "127.0.0.1";
const port = 4501;
const server = Deno.serve({
handler: () => new Response("Hello World"),
hostname,
port,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -2227,7 +2229,7 @@ Deno.test(
await listeningPromise;
const caCert = Deno.readTextFileSync("cli/tests/testdata/tls/RootCA.pem");
const client = Deno.createHttpClient({ caCerts: [caCert] });
const resp = await fetch(`https://localhost:${port}/`, {
const resp = await fetch(`https://localhost:${servePort}/`, {
client,
headers: { "connection": "close" },
});
@ -2332,7 +2334,7 @@ Deno.test(
const ac = new AbortController();
const server = Deno.serve({
handler: (_request) => new Response(null, { status: 204 }),
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -2340,7 +2342,7 @@ Deno.test(
try {
await listeningPromise;
const resp = await fetch("http://127.0.0.1:4501/", {
const resp = await fetch(`http://127.0.0.1:${servePort}/`, {
method: "GET",
headers: { "connection": "close" },
});
@ -2641,7 +2643,7 @@ Deno.test(
const server = Deno.serve({
handler: (_req) => new Response("ok"),
hostname: "localhost",
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -2940,7 +2942,7 @@ Deno.test(
addTrailers(response, [["baz", "why"]]);
return response;
},
port: 4501,
port: servePort,
signal: ac.signal,
onListen: onListen(listeningPromise),
onError: createOnErrorCb(ac),
@ -2948,7 +2950,7 @@ Deno.test(
// We don't have a great way to access this right now, so just fetch the trailers with cURL
const [_, stderr] = await curlRequestWithStdErr([
"http://localhost:4501/path",
`http://localhost:${servePort}/path`,
"-v",
"--http2",
"--http2-prior-knowledge",

View file

@ -1,16 +0,0 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
import { assertEquals } from "./test_util.ts";
Deno.test(async function symlinkSyncPerm() {
const rs = new ReadableStream<string>({
start(controller) {
controller.enqueue("hello ");
controller.enqueue("deno");
controller.close();
},
});
for await (const chunk of rs.getIterator()) {
assertEquals(typeof chunk, "string");
}
});

View file

@ -6,13 +6,13 @@ import { buffer, text } from "node:stream/consumers";
import {
assertEquals,
assertThrows,
} from "../../../test_util/std/testing/asserts.ts";
} from "../../../../test_util/std/testing/asserts.ts";
const rsaPrivateKey = Deno.readTextFileSync(
new URL("./testdata/rsa_private.pem", import.meta.url),
new URL("../testdata/rsa_private.pem", import.meta.url),
);
const rsaPublicKey = Deno.readTextFileSync(
new URL("./testdata/rsa_public.pem", import.meta.url),
new URL("../testdata/rsa_public.pem", import.meta.url),
);
const input = new TextEncoder().encode("hello world");

View file

@ -1,6 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
import { createHash, createHmac } from "node:crypto";
import { assertEquals } from "../../../test_util/std/testing/asserts.ts";
import { assertEquals } from "../../../../test_util/std/testing/asserts.ts";
// https://github.com/denoland/deno/issues/18140
Deno.test({

View file

@ -13,7 +13,7 @@ import { Buffer } from "node:buffer";
import {
assertEquals,
assertThrows,
} from "../../../test_util/std/testing/asserts.ts";
} from "../../../../test_util/std/testing/asserts.ts";
import { createHmac } from "node:crypto";
const generateKeyPairAsync = promisify(

View file

@ -3,18 +3,18 @@
import {
assert,
assertEquals,
} from "../../../test_util/std/testing/asserts.ts";
} from "../../../../test_util/std/testing/asserts.ts";
import { createSign, createVerify, sign, verify } from "node:crypto";
import { Buffer } from "node:buffer";
const rsaPrivatePem = Buffer.from(
await Deno.readFile(
new URL("./testdata/rsa_private.pem", import.meta.url),
new URL("../testdata/rsa_private.pem", import.meta.url),
),
);
const rsaPublicPem = Buffer.from(
await Deno.readFile(
new URL("./testdata/rsa_public.pem", import.meta.url),
new URL("../testdata/rsa_public.pem", import.meta.url),
),
);

View file

@ -22,6 +22,7 @@ console_static_text.workspace = true
fastwebsockets = { workspace = true, features = ["upgrade"] }
flate2.workspace = true
futures.workspace = true
glob.workspace = true
hyper = { workspace = true, features = ["server", "http1", "http2", "runtime"] }
lazy-regex.workspace = true
lsp-types.workspace = true

99
test_util/src/factory.rs Normal file
View file

@ -0,0 +1,99 @@
use std::collections::HashSet;
use std::path::PathBuf;
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use glob::glob;
/// Generate a unit test factory verified and backed by a glob.
#[macro_export]
macro_rules! unit_test_factory {
($test_fn:ident, $base:literal, $glob:literal, [ $( $test:ident $(= $($path:ident)/+)? ),+ $(,)? ]) => {
#[test]
fn check_test_glob() {
$crate::factory::check_test_glob($base, $glob, [ $( ( stringify!($test), stringify!( $( $($path)/+ )? ) ) ),+ ].as_slice());
}
$(
#[allow(non_snake_case)]
#[test]
fn $test() {
$test_fn($crate::factory::get_path(stringify!($test), stringify!( $( $($path)/+ )?)))
}
)+
};
(__test__ $($prefix:ident)* $test:ident) => {
#[allow(non_snake_case)]
#[test]
fn $test() {
$test_fn(stringify!($($prefix)/+ $test))
}
};
}
pub fn get_path(test: &'static str, path: &'static str) -> String {
if path.is_empty() {
test.to_owned()
} else {
path.replace(' ', "")
}
}
/// Validate that the glob matches the list of tests specified.
pub fn check_test_glob(
base: &'static str,
glob_pattern: &'static str,
files: &[(&'static str, &'static str)],
) {
let base_dir = PathBuf::from(base)
.canonicalize()
.unwrap()
.to_string_lossy()
// Strip Windows slashes
.replace('\\', "/");
let mut found = HashSet::new();
let mut list = vec![];
for file in glob(&format!("{}/{}", base, glob_pattern))
.expect("Failed to read test path")
{
let mut file = file
.expect("Invalid file from glob")
.canonicalize()
.unwrap();
file.set_extension("");
let name = file.file_name().unwrap().to_string_lossy();
// Strip windows slashes
let file = file.to_string_lossy().replace('\\', "/");
let file = file
.strip_prefix(&base_dir)
.expect("File {file} did not start with {base_dir} prefix");
let file = file.strip_prefix('/').unwrap().to_owned();
if file.contains('/') {
list.push(format!("{}={}", name, file))
} else {
list.push(file.clone());
}
found.insert(file);
}
let mut error = false;
for (test, path) in files {
// Remove spaces from the macro
let path = if path.is_empty() {
(*test).to_owned()
} else {
path.replace(' ', "")
};
if found.contains(&path) {
found.remove(&path);
} else {
error = true;
}
}
if error || !found.is_empty() {
panic!(
"Glob did not match provided list of files. Expected: \n[\n {}\n]",
list.join(",\n ")
);
}
}

View file

@ -55,6 +55,7 @@ use url::Url;
pub mod assertions;
mod builders;
pub mod factory;
pub mod lsp;
mod npm;
pub mod pty;