mirror of
https://github.com/denoland/deno.git
synced 2024-11-01 09:24:20 -04:00
1255 lines
35 KiB
Rust
1255 lines
35 KiB
Rust
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
|
|
|
use crate::itest;
|
|
use deno_core::url;
|
|
use deno_runtime::deno_fetch::reqwest;
|
|
use deno_runtime::deno_net::ops_tls::TlsStream;
|
|
use deno_runtime::deno_tls::rustls;
|
|
use deno_runtime::deno_tls::rustls_pemfile;
|
|
use std::fs;
|
|
use std::io::BufReader;
|
|
use std::io::Cursor;
|
|
use std::io::{Read, Write};
|
|
use std::process::Command;
|
|
use std::sync::Arc;
|
|
use test_util as util;
|
|
use test_util::TempDir;
|
|
use tokio::task::LocalSet;
|
|
use trust_dns_client::serialize::txt::Lexer;
|
|
use trust_dns_client::serialize::txt::Parser;
|
|
|
|
#[macro_export]
|
|
macro_rules! itest(
|
|
($name:ident {$( $key:ident: $value:expr,)*}) => {
|
|
#[test]
|
|
fn $name() {
|
|
(test_util::CheckOutputIntegrationTest {
|
|
$(
|
|
$key: $value,
|
|
)*
|
|
.. Default::default()
|
|
}).run()
|
|
}
|
|
}
|
|
);
|
|
|
|
#[macro_export]
|
|
macro_rules! itest_flaky(
|
|
($name:ident {$( $key:ident: $value:expr,)*}) => {
|
|
#[flaky_test::flaky_test]
|
|
fn $name() {
|
|
(test_util::CheckOutputIntegrationTest {
|
|
$(
|
|
$key: $value,
|
|
)*
|
|
.. Default::default()
|
|
}).run()
|
|
}
|
|
}
|
|
);
|
|
|
|
// These files have `_tests.rs` suffix to make it easier to tell which file is
|
|
// the test (ex. `lint_tests.rs`) and which is the implementation (ex. `lint.rs`)
|
|
// when both are open, especially for two tabs in VS Code
|
|
|
|
#[path = "bench_tests.rs"]
|
|
mod bench;
|
|
#[path = "bundle_tests.rs"]
|
|
mod bundle;
|
|
#[path = "cache_tests.rs"]
|
|
mod cache;
|
|
#[path = "check_tests.rs"]
|
|
mod check;
|
|
#[path = "compat_tests.rs"]
|
|
mod compat;
|
|
#[path = "compile_tests.rs"]
|
|
mod compile;
|
|
#[path = "coverage_tests.rs"]
|
|
mod coverage;
|
|
#[path = "doc_tests.rs"]
|
|
mod doc;
|
|
#[path = "eval_tests.rs"]
|
|
mod eval;
|
|
#[path = "fmt_tests.rs"]
|
|
mod fmt;
|
|
#[path = "info_tests.rs"]
|
|
mod info;
|
|
#[path = "inspector_tests.rs"]
|
|
mod inspector;
|
|
#[path = "install_tests.rs"]
|
|
mod install;
|
|
#[path = "lint_tests.rs"]
|
|
mod lint;
|
|
#[path = "lsp_tests.rs"]
|
|
mod lsp;
|
|
#[path = "repl_tests.rs"]
|
|
mod repl;
|
|
#[path = "run_tests.rs"]
|
|
mod run;
|
|
#[path = "task_tests.rs"]
|
|
mod task;
|
|
#[path = "test_tests.rs"]
|
|
mod test;
|
|
#[path = "upgrade_tests.rs"]
|
|
mod upgrade;
|
|
#[path = "vendor_tests.rs"]
|
|
mod vendor;
|
|
#[path = "watcher_tests.rs"]
|
|
mod watcher;
|
|
#[path = "worker_tests.rs"]
|
|
mod worker;
|
|
|
|
#[test]
|
|
fn help_flag() {
|
|
let status = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("--help")
|
|
.spawn()
|
|
.unwrap()
|
|
.wait()
|
|
.unwrap();
|
|
assert!(status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn version_short_flag() {
|
|
let status = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("-V")
|
|
.spawn()
|
|
.unwrap()
|
|
.wait()
|
|
.unwrap();
|
|
assert!(status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn version_long_flag() {
|
|
let status = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("--version")
|
|
.spawn()
|
|
.unwrap()
|
|
.wait()
|
|
.unwrap();
|
|
assert!(status.success());
|
|
}
|
|
|
|
itest!(types {
|
|
args: "types",
|
|
output: "types.out",
|
|
});
|
|
|
|
#[test]
|
|
fn cache_test() {
|
|
let _g = util::http_server();
|
|
let deno_dir = TempDir::new();
|
|
let module_url =
|
|
url::Url::parse("http://localhost:4545/006_url_imports.ts").unwrap();
|
|
let output = Command::new(util::deno_exe_path())
|
|
.env("DENO_DIR", deno_dir.path())
|
|
.current_dir(util::testdata_path())
|
|
.arg("cache")
|
|
.arg("--check=all")
|
|
.arg("-L")
|
|
.arg("debug")
|
|
.arg(module_url.to_string())
|
|
.output()
|
|
.expect("Failed to spawn script");
|
|
assert!(output.status.success());
|
|
|
|
let prg = util::deno_exe_path();
|
|
let output = Command::new(&prg)
|
|
.env("DENO_DIR", deno_dir.path())
|
|
.env("HTTP_PROXY", "http://nil")
|
|
.env("NO_COLOR", "1")
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg(module_url.to_string())
|
|
.output()
|
|
.expect("Failed to spawn script");
|
|
|
|
let str_output = std::str::from_utf8(&output.stdout).unwrap();
|
|
|
|
let module_output_path = util::testdata_path().join("006_url_imports.ts.out");
|
|
let mut module_output = String::new();
|
|
let mut module_output_file = fs::File::open(module_output_path).unwrap();
|
|
module_output_file
|
|
.read_to_string(&mut module_output)
|
|
.unwrap();
|
|
|
|
assert_eq!(module_output, str_output);
|
|
}
|
|
|
|
#[test]
|
|
fn cache_invalidation_test() {
|
|
let deno_dir = TempDir::new();
|
|
let fixture_path = deno_dir.path().join("fixture.ts");
|
|
{
|
|
let mut file = std::fs::File::create(fixture_path.clone())
|
|
.expect("could not create fixture");
|
|
file
|
|
.write_all(b"console.log(\"42\");")
|
|
.expect("could not write fixture");
|
|
}
|
|
let output = Command::new(util::deno_exe_path())
|
|
.env("DENO_DIR", deno_dir.path())
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg(fixture_path.to_str().unwrap())
|
|
.output()
|
|
.expect("Failed to spawn script");
|
|
assert!(output.status.success());
|
|
let actual = std::str::from_utf8(&output.stdout).unwrap();
|
|
assert_eq!(actual, "42\n");
|
|
{
|
|
let mut file = std::fs::File::create(fixture_path.clone())
|
|
.expect("could not create fixture");
|
|
file
|
|
.write_all(b"console.log(\"43\");")
|
|
.expect("could not write fixture");
|
|
}
|
|
let output = Command::new(util::deno_exe_path())
|
|
.env("DENO_DIR", deno_dir.path())
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg(fixture_path.to_str().unwrap())
|
|
.output()
|
|
.expect("Failed to spawn script");
|
|
assert!(output.status.success());
|
|
let actual = std::str::from_utf8(&output.stdout).unwrap();
|
|
assert_eq!(actual, "43\n");
|
|
}
|
|
|
|
#[test]
|
|
fn cache_invalidation_test_no_check() {
|
|
let deno_dir = TempDir::new();
|
|
let fixture_path = deno_dir.path().join("fixture.ts");
|
|
{
|
|
let mut file = std::fs::File::create(fixture_path.clone())
|
|
.expect("could not create fixture");
|
|
file
|
|
.write_all(b"console.log(\"42\");")
|
|
.expect("could not write fixture");
|
|
}
|
|
let output = Command::new(util::deno_exe_path())
|
|
.env("DENO_DIR", deno_dir.path())
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--no-check")
|
|
.arg(fixture_path.to_str().unwrap())
|
|
.output()
|
|
.expect("Failed to spawn script");
|
|
assert!(output.status.success());
|
|
let actual = std::str::from_utf8(&output.stdout).unwrap();
|
|
assert_eq!(actual, "42\n");
|
|
{
|
|
let mut file = std::fs::File::create(fixture_path.clone())
|
|
.expect("could not create fixture");
|
|
file
|
|
.write_all(b"console.log(\"43\");")
|
|
.expect("could not write fixture");
|
|
}
|
|
let output = Command::new(util::deno_exe_path())
|
|
.env("DENO_DIR", deno_dir.path())
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--no-check")
|
|
.arg(fixture_path.to_str().unwrap())
|
|
.output()
|
|
.expect("Failed to spawn script");
|
|
assert!(output.status.success());
|
|
let actual = std::str::from_utf8(&output.stdout).unwrap();
|
|
assert_eq!(actual, "43\n");
|
|
}
|
|
|
|
#[test]
|
|
fn ts_dependency_recompilation() {
|
|
let t = TempDir::new();
|
|
let ats = t.path().join("a.ts");
|
|
|
|
std::fs::write(
|
|
&ats,
|
|
"
|
|
import { foo } from \"./b.ts\";
|
|
|
|
function print(str: string): void {
|
|
console.log(str);
|
|
}
|
|
|
|
print(foo);",
|
|
)
|
|
.unwrap();
|
|
|
|
let bts = t.path().join("b.ts");
|
|
std::fs::write(
|
|
&bts,
|
|
"
|
|
export const foo = \"foo\";",
|
|
)
|
|
.unwrap();
|
|
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.env("NO_COLOR", "1")
|
|
.arg("run")
|
|
.arg("--check")
|
|
.arg(&ats)
|
|
.output()
|
|
.expect("failed to spawn script");
|
|
|
|
let stdout_output = std::str::from_utf8(&output.stdout).unwrap().trim();
|
|
let stderr_output = std::str::from_utf8(&output.stderr).unwrap().trim();
|
|
|
|
assert!(stdout_output.ends_with("foo"));
|
|
assert!(stderr_output.starts_with("Check"));
|
|
|
|
// Overwrite contents of b.ts and run again
|
|
std::fs::write(
|
|
&bts,
|
|
"
|
|
export const foo = 5;",
|
|
)
|
|
.expect("error writing file");
|
|
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.env("NO_COLOR", "1")
|
|
.arg("run")
|
|
.arg("--check")
|
|
.arg(&ats)
|
|
.output()
|
|
.expect("failed to spawn script");
|
|
|
|
let stdout_output = std::str::from_utf8(&output.stdout).unwrap().trim();
|
|
let stderr_output = std::str::from_utf8(&output.stderr).unwrap().trim();
|
|
|
|
// error: TS2345 [ERROR]: Argument of type '5' is not assignable to parameter of type 'string'.
|
|
assert!(stderr_output.contains("TS2345"));
|
|
assert!(!output.status.success());
|
|
assert!(stdout_output.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn ts_no_recheck_on_redirect() {
|
|
let deno_dir = util::new_deno_dir();
|
|
let e = util::deno_exe_path();
|
|
|
|
let redirect_ts = util::testdata_path().join("017_import_redirect.ts");
|
|
assert!(redirect_ts.is_file());
|
|
let mut cmd = Command::new(e.clone());
|
|
cmd.env("DENO_DIR", deno_dir.path());
|
|
let mut initial = cmd
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--check")
|
|
.arg(redirect_ts.clone())
|
|
.spawn()
|
|
.expect("failed to span script");
|
|
let status_initial =
|
|
initial.wait().expect("failed to wait for child process");
|
|
assert!(status_initial.success());
|
|
|
|
let mut cmd = Command::new(e);
|
|
cmd.env("DENO_DIR", deno_dir.path());
|
|
let output = cmd
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--check")
|
|
.arg(redirect_ts)
|
|
.output()
|
|
.expect("failed to spawn script");
|
|
|
|
assert!(std::str::from_utf8(&output.stderr).unwrap().is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn timeout_clear() {
|
|
// https://github.com/denoland/deno/issues/7599
|
|
|
|
use std::time::Duration;
|
|
use std::time::Instant;
|
|
|
|
let source_code = r#"
|
|
const handle = setTimeout(() => {
|
|
console.log("timeout finish");
|
|
}, 10000);
|
|
clearTimeout(handle);
|
|
console.log("finish");
|
|
"#;
|
|
|
|
let mut p = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("-")
|
|
.stdin(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap();
|
|
let stdin = p.stdin.as_mut().unwrap();
|
|
stdin.write_all(source_code.as_bytes()).unwrap();
|
|
let start = Instant::now();
|
|
let status = p.wait().unwrap();
|
|
let end = Instant::now();
|
|
assert!(status.success());
|
|
// check that program did not run for 10 seconds
|
|
// for timeout to clear
|
|
assert!(end - start < Duration::new(10, 0));
|
|
}
|
|
|
|
#[test]
|
|
fn broken_stdout() {
|
|
let (reader, writer) = os_pipe::pipe().unwrap();
|
|
// drop the reader to create a broken pipe
|
|
drop(reader);
|
|
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("eval")
|
|
.arg("console.log(3.14)")
|
|
.stdout(writer)
|
|
.stderr(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap()
|
|
.wait_with_output()
|
|
.unwrap();
|
|
|
|
assert!(!output.status.success());
|
|
let stderr = std::str::from_utf8(output.stderr.as_ref()).unwrap().trim();
|
|
assert!(stderr.contains("Uncaught BrokenPipe"));
|
|
assert!(!stderr.contains("panic"));
|
|
}
|
|
|
|
itest!(error_cause {
|
|
args: "run error_cause.ts",
|
|
output: "error_cause.ts.out",
|
|
exit_code: 1,
|
|
});
|
|
|
|
itest!(error_cause_recursive {
|
|
args: "run error_cause_recursive.ts",
|
|
output: "error_cause_recursive.ts.out",
|
|
exit_code: 1,
|
|
});
|
|
|
|
itest_flaky!(cafile_url_imports {
|
|
args: "run --quiet --reload --cert tls/RootCA.pem cafile_url_imports.ts",
|
|
output: "cafile_url_imports.ts.out",
|
|
http_server: true,
|
|
});
|
|
|
|
itest_flaky!(cafile_ts_fetch {
|
|
args:
|
|
"run --quiet --reload --allow-net --cert tls/RootCA.pem cafile_ts_fetch.ts",
|
|
output: "cafile_ts_fetch.ts.out",
|
|
http_server: true,
|
|
});
|
|
|
|
itest_flaky!(cafile_eval {
|
|
args: "eval --cert tls/RootCA.pem fetch('https://localhost:5545/cafile_ts_fetch.ts.out').then(r=>r.text()).then(t=>console.log(t.trimEnd()))",
|
|
output: "cafile_ts_fetch.ts.out",
|
|
http_server: true,
|
|
});
|
|
|
|
itest_flaky!(cafile_info {
|
|
args:
|
|
"info --quiet --cert tls/RootCA.pem https://localhost:5545/cafile_info.ts",
|
|
output: "cafile_info.ts.out",
|
|
http_server: true,
|
|
});
|
|
|
|
itest_flaky!(cafile_url_imports_unsafe_ssl {
|
|
args: "run --quiet --reload --unsafely-ignore-certificate-errors=localhost cafile_url_imports.ts",
|
|
output: "cafile_url_imports_unsafe_ssl.ts.out",
|
|
http_server: true,
|
|
});
|
|
|
|
itest_flaky!(cafile_ts_fetch_unsafe_ssl {
|
|
args:
|
|
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors cafile_ts_fetch.ts",
|
|
output: "cafile_ts_fetch_unsafe_ssl.ts.out",
|
|
http_server: true,
|
|
});
|
|
|
|
itest!(deno_land_unsafe_ssl {
|
|
args:
|
|
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=deno.land deno_land_unsafe_ssl.ts",
|
|
output: "deno_land_unsafe_ssl.ts.out",
|
|
});
|
|
|
|
itest!(ip_address_unsafe_ssl {
|
|
args:
|
|
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=1.1.1.1 ip_address_unsafe_ssl.ts",
|
|
output: "ip_address_unsafe_ssl.ts.out",
|
|
});
|
|
|
|
itest!(localhost_unsafe_ssl {
|
|
args:
|
|
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=deno.land cafile_url_imports.ts",
|
|
output: "localhost_unsafe_ssl.ts.out",
|
|
http_server: true,
|
|
exit_code: 1,
|
|
});
|
|
|
|
#[flaky_test::flaky_test]
|
|
fn cafile_env_fetch() {
|
|
use deno_core::url::Url;
|
|
let _g = util::http_server();
|
|
let deno_dir = TempDir::new();
|
|
let module_url =
|
|
Url::parse("https://localhost:5545/cafile_url_imports.ts").unwrap();
|
|
let cafile = util::testdata_path().join("tls/RootCA.pem");
|
|
let output = Command::new(util::deno_exe_path())
|
|
.env("DENO_DIR", deno_dir.path())
|
|
.env("DENO_CERT", cafile)
|
|
.current_dir(util::testdata_path())
|
|
.arg("cache")
|
|
.arg(module_url.to_string())
|
|
.output()
|
|
.expect("Failed to spawn script");
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[flaky_test::flaky_test]
|
|
fn cafile_fetch() {
|
|
use deno_core::url::Url;
|
|
let _g = util::http_server();
|
|
let deno_dir = TempDir::new();
|
|
let module_url =
|
|
Url::parse("http://localhost:4545/cafile_url_imports.ts").unwrap();
|
|
let cafile = util::testdata_path().join("tls/RootCA.pem");
|
|
let output = Command::new(util::deno_exe_path())
|
|
.env("DENO_DIR", deno_dir.path())
|
|
.current_dir(util::testdata_path())
|
|
.arg("cache")
|
|
.arg("--cert")
|
|
.arg(cafile)
|
|
.arg(module_url.to_string())
|
|
.output()
|
|
.expect("Failed to spawn script");
|
|
assert!(output.status.success());
|
|
let out = std::str::from_utf8(&output.stdout).unwrap();
|
|
assert_eq!(out, "");
|
|
}
|
|
|
|
#[flaky_test::flaky_test]
|
|
fn cafile_install_remote_module() {
|
|
let _g = util::http_server();
|
|
let temp_dir = TempDir::new();
|
|
let bin_dir = temp_dir.path().join("bin");
|
|
std::fs::create_dir(&bin_dir).unwrap();
|
|
let deno_dir = TempDir::new();
|
|
let cafile = util::testdata_path().join("tls/RootCA.pem");
|
|
|
|
let install_output = Command::new(util::deno_exe_path())
|
|
.env("DENO_DIR", deno_dir.path())
|
|
.current_dir(util::testdata_path())
|
|
.arg("install")
|
|
.arg("--cert")
|
|
.arg(cafile)
|
|
.arg("--root")
|
|
.arg(temp_dir.path())
|
|
.arg("-n")
|
|
.arg("echo_test")
|
|
.arg("https://localhost:5545/echo.ts")
|
|
.output()
|
|
.expect("Failed to spawn script");
|
|
println!("{}", std::str::from_utf8(&install_output.stdout).unwrap());
|
|
eprintln!("{}", std::str::from_utf8(&install_output.stderr).unwrap());
|
|
assert!(install_output.status.success());
|
|
|
|
let mut echo_test_path = bin_dir.join("echo_test");
|
|
if cfg!(windows) {
|
|
echo_test_path = echo_test_path.with_extension("cmd");
|
|
}
|
|
assert!(echo_test_path.exists());
|
|
|
|
let output = Command::new(echo_test_path)
|
|
.current_dir(temp_dir.path())
|
|
.arg("foo")
|
|
.env("PATH", util::target_dir())
|
|
.output()
|
|
.expect("failed to spawn script");
|
|
let stdout = std::str::from_utf8(&output.stdout).unwrap().trim();
|
|
assert!(stdout.ends_with("foo"));
|
|
}
|
|
|
|
#[flaky_test::flaky_test]
|
|
fn cafile_bundle_remote_exports() {
|
|
let _g = util::http_server();
|
|
|
|
// First we have to generate a bundle of some remote module that has exports.
|
|
let mod1 = "https://localhost:5545/subdir/mod1.ts";
|
|
let cafile = util::testdata_path().join("tls/RootCA.pem");
|
|
let t = TempDir::new();
|
|
let bundle = t.path().join("mod1.bundle.js");
|
|
let mut deno = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("bundle")
|
|
.arg("--cert")
|
|
.arg(cafile)
|
|
.arg(mod1)
|
|
.arg(&bundle)
|
|
.spawn()
|
|
.expect("failed to spawn script");
|
|
let status = deno.wait().expect("failed to wait for the child process");
|
|
assert!(status.success());
|
|
assert!(bundle.is_file());
|
|
|
|
// Now we try to use that bundle from another module.
|
|
let test = t.path().join("test.js");
|
|
std::fs::write(
|
|
&test,
|
|
"
|
|
import { printHello3 } from \"./mod1.bundle.js\";
|
|
printHello3(); ",
|
|
)
|
|
.expect("error writing file");
|
|
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--check")
|
|
.arg(&test)
|
|
.output()
|
|
.expect("failed to spawn script");
|
|
// check the output of the test.ts program.
|
|
assert!(std::str::from_utf8(&output.stdout)
|
|
.unwrap()
|
|
.trim()
|
|
.ends_with("Hello"));
|
|
assert_eq!(output.stderr, b"");
|
|
}
|
|
|
|
#[test]
|
|
fn websocket() {
|
|
let _g = util::http_server();
|
|
|
|
let script = util::testdata_path().join("websocket_test.ts");
|
|
let root_ca = util::testdata_path().join("tls/RootCA.pem");
|
|
let status = util::deno_cmd()
|
|
.arg("test")
|
|
.arg("--unstable")
|
|
.arg("--allow-net")
|
|
.arg("--cert")
|
|
.arg(root_ca)
|
|
.arg(script)
|
|
.spawn()
|
|
.unwrap()
|
|
.wait()
|
|
.unwrap();
|
|
|
|
assert!(status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn websocketstream() {
|
|
let _g = util::http_server();
|
|
|
|
let script = util::testdata_path().join("websocketstream_test.ts");
|
|
let root_ca = util::testdata_path().join("tls/RootCA.pem");
|
|
let status = util::deno_cmd()
|
|
.arg("test")
|
|
.arg("--unstable")
|
|
.arg("--allow-net")
|
|
.arg("--cert")
|
|
.arg(root_ca)
|
|
.arg(script)
|
|
.spawn()
|
|
.unwrap()
|
|
.wait()
|
|
.unwrap();
|
|
|
|
assert!(status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn websocketstream_ping() {
|
|
use deno_runtime::deno_websocket::tokio_tungstenite::tungstenite;
|
|
let _g = util::http_server();
|
|
|
|
let script = util::testdata_path().join("websocketstream_ping_test.ts");
|
|
let root_ca = util::testdata_path().join("tls/RootCA.pem");
|
|
let mut child = util::deno_cmd()
|
|
.arg("test")
|
|
.arg("--unstable")
|
|
.arg("--allow-net")
|
|
.arg("--cert")
|
|
.arg(root_ca)
|
|
.arg(script)
|
|
.stdout(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap();
|
|
|
|
let server = std::net::TcpListener::bind("127.0.0.1:4513").unwrap();
|
|
let (stream, _) = server.accept().unwrap();
|
|
let mut socket = tungstenite::accept(stream).unwrap();
|
|
socket
|
|
.write_message(tungstenite::Message::Text(String::from("A")))
|
|
.unwrap();
|
|
socket
|
|
.write_message(tungstenite::Message::Ping(vec![]))
|
|
.unwrap();
|
|
socket
|
|
.write_message(tungstenite::Message::Text(String::from("B")))
|
|
.unwrap();
|
|
let message = socket.read_message().unwrap();
|
|
assert_eq!(message, tungstenite::Message::Pong(vec![]));
|
|
socket
|
|
.write_message(tungstenite::Message::Text(String::from("C")))
|
|
.unwrap();
|
|
socket.close(None).unwrap();
|
|
|
|
assert!(child.wait().unwrap().success());
|
|
}
|
|
|
|
#[test]
|
|
fn websocket_server_multi_field_connection_header() {
|
|
let script = util::testdata_path()
|
|
.join("websocket_server_multi_field_connection_header_test.ts");
|
|
let root_ca = util::testdata_path().join("tls/RootCA.pem");
|
|
let mut child = util::deno_cmd()
|
|
.arg("run")
|
|
.arg("--unstable")
|
|
.arg("--allow-net")
|
|
.arg("--cert")
|
|
.arg(root_ca)
|
|
.arg(script)
|
|
.stdout(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap();
|
|
|
|
let stdout = child.stdout.as_mut().unwrap();
|
|
let mut buffer = [0; 5];
|
|
let read = stdout.read(&mut buffer).unwrap();
|
|
assert_eq!(read, 5);
|
|
let msg = std::str::from_utf8(&buffer).unwrap();
|
|
assert_eq!(msg, "READY");
|
|
|
|
let req = http::request::Builder::new()
|
|
.header(http::header::CONNECTION, "keep-alive, Upgrade")
|
|
.uri("ws://localhost:4319")
|
|
.body(())
|
|
.unwrap();
|
|
let (mut socket, _) =
|
|
deno_runtime::deno_websocket::tokio_tungstenite::tungstenite::connect(req)
|
|
.unwrap();
|
|
let message = socket.read_message().unwrap();
|
|
assert_eq!(message, deno_runtime::deno_websocket::tokio_tungstenite::tungstenite::Message::Close(None));
|
|
socket.close(None).unwrap();
|
|
assert!(child.wait().unwrap().success());
|
|
}
|
|
|
|
// TODO(bartlomieju): this should use `deno run`, not `deno test`; but the
|
|
// test hangs then. https://github.com/denoland/deno/issues/14283
|
|
#[test]
|
|
#[ignore]
|
|
fn websocket_server_idletimeout() {
|
|
let script = util::testdata_path().join("websocket_server_idletimeout.ts");
|
|
let root_ca = util::testdata_path().join("tls/RootCA.pem");
|
|
let mut child = util::deno_cmd()
|
|
.arg("test")
|
|
.arg("--unstable")
|
|
.arg("--allow-net")
|
|
.arg("--cert")
|
|
.arg(root_ca)
|
|
.arg(script)
|
|
.stdout(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap();
|
|
|
|
let stdout = child.stdout.as_mut().unwrap();
|
|
let mut buffer = [0; 5];
|
|
let read = stdout.read(&mut buffer).unwrap();
|
|
assert_eq!(read, 5);
|
|
let msg = std::str::from_utf8(&buffer).unwrap();
|
|
assert_eq!(msg, "READY");
|
|
|
|
let req = http::request::Builder::new()
|
|
.uri("ws://localhost:4509")
|
|
.body(())
|
|
.unwrap();
|
|
let (_ws, _request) =
|
|
deno_runtime::deno_websocket::tokio_tungstenite::tungstenite::connect(req)
|
|
.unwrap();
|
|
|
|
assert!(child.wait().unwrap().success());
|
|
}
|
|
|
|
#[cfg(not(windows))]
|
|
#[test]
|
|
fn set_raw_should_not_panic_on_no_tty() {
|
|
let output = util::deno_cmd()
|
|
.arg("eval")
|
|
.arg("--unstable")
|
|
.arg("Deno.setRaw(Deno.stdin.rid, true)")
|
|
// stdin set to piped so it certainly does not refer to TTY
|
|
.stdin(std::process::Stdio::piped())
|
|
// stderr is piped so we can capture output.
|
|
.stderr(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap()
|
|
.wait_with_output()
|
|
.unwrap();
|
|
assert!(!output.status.success());
|
|
let stderr = std::str::from_utf8(&output.stderr).unwrap().trim();
|
|
assert!(stderr.contains("BadResource"));
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_resolve_dns() {
|
|
use std::net::SocketAddr;
|
|
use std::str::FromStr;
|
|
use std::sync::Arc;
|
|
use std::time::Duration;
|
|
use tokio::net::TcpListener;
|
|
use tokio::net::UdpSocket;
|
|
use tokio::sync::oneshot;
|
|
use trust_dns_server::authority::Catalog;
|
|
use trust_dns_server::authority::ZoneType;
|
|
use trust_dns_server::proto::rr::Name;
|
|
use trust_dns_server::store::in_memory::InMemoryAuthority;
|
|
use trust_dns_server::ServerFuture;
|
|
|
|
const DNS_PORT: u16 = 4553;
|
|
|
|
// Setup DNS server for testing
|
|
async fn run_dns_server(tx: oneshot::Sender<()>) {
|
|
let zone_file =
|
|
fs::read_to_string(util::testdata_path().join("resolve_dns.zone.in"))
|
|
.unwrap();
|
|
let lexer = Lexer::new(&zone_file);
|
|
let records = Parser::new().parse(
|
|
lexer,
|
|
Some(Name::from_str("example.com").unwrap()),
|
|
None,
|
|
);
|
|
if records.is_err() {
|
|
panic!("failed to parse: {:?}", records.err())
|
|
}
|
|
let (origin, records) = records.unwrap();
|
|
let authority = Box::new(Arc::new(
|
|
InMemoryAuthority::new(origin, records, ZoneType::Primary, false)
|
|
.unwrap(),
|
|
));
|
|
let mut catalog: Catalog = Catalog::new();
|
|
catalog.upsert(Name::root().into(), authority);
|
|
|
|
let mut server_fut = ServerFuture::new(catalog);
|
|
let socket_addr = SocketAddr::from(([127, 0, 0, 1], DNS_PORT));
|
|
let tcp_listener = TcpListener::bind(socket_addr).await.unwrap();
|
|
let udp_socket = UdpSocket::bind(socket_addr).await.unwrap();
|
|
server_fut.register_socket(udp_socket);
|
|
server_fut.register_listener(tcp_listener, Duration::from_secs(2));
|
|
|
|
// Notifies that the DNS server is ready
|
|
tx.send(()).unwrap();
|
|
|
|
server_fut.block_until_done().await.unwrap();
|
|
}
|
|
|
|
let (ready_tx, ready_rx) = oneshot::channel();
|
|
let dns_server_fut = run_dns_server(ready_tx);
|
|
let handle = tokio::spawn(dns_server_fut);
|
|
|
|
// Waits for the DNS server to be ready
|
|
ready_rx.await.unwrap();
|
|
|
|
// Pass: `--allow-net`
|
|
{
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.env("NO_COLOR", "1")
|
|
.arg("run")
|
|
.arg("--check")
|
|
.arg("--allow-net")
|
|
.arg("resolve_dns.ts")
|
|
.stdout(std::process::Stdio::piped())
|
|
.stderr(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap()
|
|
.wait_with_output()
|
|
.unwrap();
|
|
let err = String::from_utf8_lossy(&output.stderr);
|
|
let out = String::from_utf8_lossy(&output.stdout);
|
|
println!("{}", err);
|
|
assert!(output.status.success());
|
|
assert!(err.starts_with("Check file"));
|
|
|
|
let expected =
|
|
std::fs::read_to_string(util::testdata_path().join("resolve_dns.ts.out"))
|
|
.unwrap();
|
|
assert_eq!(expected, out);
|
|
}
|
|
|
|
// Pass: `--allow-net=127.0.0.1:4553`
|
|
{
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.env("NO_COLOR", "1")
|
|
.arg("run")
|
|
.arg("--check")
|
|
.arg("--allow-net=127.0.0.1:4553")
|
|
.arg("resolve_dns.ts")
|
|
.stdout(std::process::Stdio::piped())
|
|
.stderr(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap()
|
|
.wait_with_output()
|
|
.unwrap();
|
|
let err = String::from_utf8_lossy(&output.stderr);
|
|
let out = String::from_utf8_lossy(&output.stdout);
|
|
assert!(output.status.success());
|
|
assert!(err.starts_with("Check file"));
|
|
|
|
let expected =
|
|
std::fs::read_to_string(util::testdata_path().join("resolve_dns.ts.out"))
|
|
.unwrap();
|
|
assert_eq!(expected, out);
|
|
}
|
|
|
|
// Permission error: `--allow-net=deno.land`
|
|
{
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.env("NO_COLOR", "1")
|
|
.arg("run")
|
|
.arg("--check")
|
|
.arg("--allow-net=deno.land")
|
|
.arg("resolve_dns.ts")
|
|
.stdout(std::process::Stdio::piped())
|
|
.stderr(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap()
|
|
.wait_with_output()
|
|
.unwrap();
|
|
let err = String::from_utf8_lossy(&output.stderr);
|
|
let out = String::from_utf8_lossy(&output.stdout);
|
|
assert!(!output.status.success());
|
|
assert!(err.starts_with("Check file"));
|
|
assert!(err.contains(r#"error: Uncaught (in promise) PermissionDenied: Requires net access to "127.0.0.1:4553""#));
|
|
assert!(out.is_empty());
|
|
}
|
|
|
|
// Permission error: no permission specified
|
|
{
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.env("NO_COLOR", "1")
|
|
.arg("run")
|
|
.arg("--check")
|
|
.arg("resolve_dns.ts")
|
|
.stdout(std::process::Stdio::piped())
|
|
.stderr(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap()
|
|
.wait_with_output()
|
|
.unwrap();
|
|
let err = String::from_utf8_lossy(&output.stderr);
|
|
let out = String::from_utf8_lossy(&output.stdout);
|
|
assert!(!output.status.success());
|
|
assert!(err.starts_with("Check file"));
|
|
assert!(err.contains(r#"error: Uncaught (in promise) PermissionDenied: Requires net access to "127.0.0.1:4553""#));
|
|
assert!(out.is_empty());
|
|
}
|
|
|
|
handle.abort();
|
|
}
|
|
|
|
#[test]
|
|
fn typecheck_declarations_ns() {
|
|
let output = util::deno_cmd()
|
|
.arg("test")
|
|
.arg("--doc")
|
|
.arg(util::root_path().join("cli/dts/lib.deno.ns.d.ts"))
|
|
.output()
|
|
.unwrap();
|
|
println!("stdout: {}", String::from_utf8(output.stdout).unwrap());
|
|
println!("stderr: {}", String::from_utf8(output.stderr).unwrap());
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn typecheck_declarations_unstable() {
|
|
let output = util::deno_cmd()
|
|
.arg("test")
|
|
.arg("--doc")
|
|
.arg("--unstable")
|
|
.arg(util::root_path().join("cli/dts/lib.deno.unstable.d.ts"))
|
|
.output()
|
|
.unwrap();
|
|
println!("stdout: {}", String::from_utf8(output.stdout).unwrap());
|
|
println!("stderr: {}", String::from_utf8(output.stderr).unwrap());
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn typecheck_core() {
|
|
let deno_dir = TempDir::new();
|
|
let test_file = deno_dir.path().join("test_deno_core_types.ts");
|
|
std::fs::write(
|
|
&test_file,
|
|
format!(
|
|
"import \"{}\";",
|
|
deno_core::resolve_path(
|
|
util::root_path()
|
|
.join("core/lib.deno_core.d.ts")
|
|
.to_str()
|
|
.unwrap()
|
|
)
|
|
.unwrap()
|
|
),
|
|
)
|
|
.unwrap();
|
|
let output = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.arg("run")
|
|
.arg(test_file.to_str().unwrap())
|
|
.output()
|
|
.unwrap();
|
|
println!("stdout: {}", String::from_utf8(output.stdout).unwrap());
|
|
println!("stderr: {}", String::from_utf8(output.stderr).unwrap());
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[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());
|
|
}
|
|
|
|
#[test]
|
|
fn js_unit_tests() {
|
|
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")
|
|
.arg("--unstable")
|
|
.arg("--location=http://js-unit-tests/foo/bar")
|
|
.arg("--no-prompt")
|
|
.arg("-A")
|
|
.arg(util::tests_path().join("unit"))
|
|
.spawn()
|
|
.expect("failed to spawn script");
|
|
|
|
let status = deno.wait().expect("failed to wait for the child process");
|
|
assert_eq!(Some(0), status.code());
|
|
assert!(status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn basic_auth_tokens() {
|
|
let _g = util::http_server();
|
|
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::root_path())
|
|
.arg("run")
|
|
.arg("http://127.0.0.1:4554/001_hello.js")
|
|
.stdout(std::process::Stdio::piped())
|
|
.stderr(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap()
|
|
.wait_with_output()
|
|
.unwrap();
|
|
|
|
assert!(!output.status.success());
|
|
|
|
let stdout_str = std::str::from_utf8(&output.stdout).unwrap().trim();
|
|
assert!(stdout_str.is_empty());
|
|
|
|
let stderr_str = std::str::from_utf8(&output.stderr).unwrap().trim();
|
|
eprintln!("{}", stderr_str);
|
|
|
|
assert!(stderr_str
|
|
.contains("Module not found \"http://127.0.0.1:4554/001_hello.js\"."));
|
|
|
|
let output = util::deno_cmd()
|
|
.current_dir(util::root_path())
|
|
.arg("run")
|
|
.arg("http://127.0.0.1:4554/001_hello.js")
|
|
.env("DENO_AUTH_TOKENS", "testuser123:testpassabc@127.0.0.1:4554")
|
|
.stdout(std::process::Stdio::piped())
|
|
.stderr(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap()
|
|
.wait_with_output()
|
|
.unwrap();
|
|
|
|
let stderr_str = std::str::from_utf8(&output.stderr).unwrap().trim();
|
|
eprintln!("{}", stderr_str);
|
|
|
|
assert!(output.status.success());
|
|
|
|
let stdout_str = std::str::from_utf8(&output.stdout).unwrap().trim();
|
|
assert_eq!(util::strip_ansi_codes(stdout_str), "Hello World");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn listen_tls_alpn() {
|
|
// TLS streams require the presence of an ambient local task set to gracefully
|
|
// close dropped connections in the background.
|
|
LocalSet::new()
|
|
.run_until(async {
|
|
let mut child = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--unstable")
|
|
.arg("--quiet")
|
|
.arg("--allow-net")
|
|
.arg("--allow-read")
|
|
.arg("./listen_tls_alpn.ts")
|
|
.arg("4504")
|
|
.stdout(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap();
|
|
let stdout = child.stdout.as_mut().unwrap();
|
|
let mut msg = [0; 5];
|
|
let read = stdout.read(&mut msg).unwrap();
|
|
assert_eq!(read, 5);
|
|
assert_eq!(&msg, b"READY");
|
|
|
|
let mut reader = &mut BufReader::new(Cursor::new(include_bytes!(
|
|
"../testdata/tls/RootCA.crt"
|
|
)));
|
|
let certs = rustls_pemfile::certs(&mut reader).unwrap();
|
|
let mut root_store = rustls::RootCertStore::empty();
|
|
root_store.add_parsable_certificates(&certs);
|
|
let mut cfg = rustls::ClientConfig::builder()
|
|
.with_safe_defaults()
|
|
.with_root_certificates(root_store)
|
|
.with_no_client_auth();
|
|
cfg.alpn_protocols.push(b"foobar".to_vec());
|
|
let cfg = Arc::new(cfg);
|
|
|
|
let hostname = rustls::ServerName::try_from("localhost").unwrap();
|
|
|
|
let tcp_stream = tokio::net::TcpStream::connect("localhost:4504")
|
|
.await
|
|
.unwrap();
|
|
let mut tls_stream =
|
|
TlsStream::new_client_side(tcp_stream, cfg, hostname);
|
|
|
|
tls_stream.handshake().await.unwrap();
|
|
|
|
let (_, rustls_connection) = tls_stream.get_ref();
|
|
let alpn = rustls_connection.alpn_protocol().unwrap();
|
|
assert_eq!(alpn, b"foobar");
|
|
|
|
let status = child.wait().unwrap();
|
|
assert!(status.success());
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn listen_tls_alpn_fail() {
|
|
// TLS streams require the presence of an ambient local task set to gracefully
|
|
// close dropped connections in the background.
|
|
LocalSet::new()
|
|
.run_until(async {
|
|
let mut child = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--unstable")
|
|
.arg("--quiet")
|
|
.arg("--allow-net")
|
|
.arg("--allow-read")
|
|
.arg("./listen_tls_alpn_fail.ts")
|
|
.arg("4505")
|
|
.stdout(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap();
|
|
let stdout = child.stdout.as_mut().unwrap();
|
|
let mut msg = [0; 5];
|
|
let read = stdout.read(&mut msg).unwrap();
|
|
assert_eq!(read, 5);
|
|
assert_eq!(&msg, b"READY");
|
|
|
|
let mut reader = &mut BufReader::new(Cursor::new(include_bytes!(
|
|
"../testdata/tls/RootCA.crt"
|
|
)));
|
|
let certs = rustls_pemfile::certs(&mut reader).unwrap();
|
|
let mut root_store = rustls::RootCertStore::empty();
|
|
root_store.add_parsable_certificates(&certs);
|
|
let mut cfg = rustls::ClientConfig::builder()
|
|
.with_safe_defaults()
|
|
.with_root_certificates(root_store)
|
|
.with_no_client_auth();
|
|
cfg.alpn_protocols.push(b"boofar".to_vec());
|
|
let cfg = Arc::new(cfg);
|
|
|
|
let hostname = rustls::ServerName::try_from("localhost").unwrap();
|
|
|
|
let tcp_stream = tokio::net::TcpStream::connect("localhost:4505")
|
|
.await
|
|
.unwrap();
|
|
let mut tls_stream =
|
|
TlsStream::new_client_side(tcp_stream, cfg, hostname);
|
|
|
|
tls_stream.handshake().await.unwrap_err();
|
|
|
|
let (_, rustls_connection) = tls_stream.get_ref();
|
|
assert!(rustls_connection.alpn_protocol().is_none());
|
|
|
|
let status = child.wait().unwrap();
|
|
assert!(status.success());
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn http2_request_url() {
|
|
// TLS streams require the presence of an ambient local task set to gracefully
|
|
// close dropped connections in the background.
|
|
LocalSet::new()
|
|
.run_until(async {
|
|
let mut child = util::deno_cmd()
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--unstable")
|
|
.arg("--quiet")
|
|
.arg("--allow-net")
|
|
.arg("--allow-read")
|
|
.arg("./http2_request_url.ts")
|
|
.arg("4506")
|
|
.stdout(std::process::Stdio::piped())
|
|
.spawn()
|
|
.unwrap();
|
|
let stdout = child.stdout.as_mut().unwrap();
|
|
let mut buffer = [0; 5];
|
|
let read = stdout.read(&mut buffer).unwrap();
|
|
assert_eq!(read, 5);
|
|
let msg = std::str::from_utf8(&buffer).unwrap();
|
|
assert_eq!(msg, "READY");
|
|
|
|
let cert = reqwest::Certificate::from_pem(include_bytes!(
|
|
"../testdata/tls/RootCA.crt"
|
|
))
|
|
.unwrap();
|
|
|
|
let client = reqwest::Client::builder()
|
|
.add_root_certificate(cert)
|
|
.http2_prior_knowledge()
|
|
.build()
|
|
.unwrap();
|
|
|
|
let res = client.get("http://127.0.0.1:4506").send().await.unwrap();
|
|
assert_eq!(200, res.status());
|
|
|
|
let body = res.text().await.unwrap();
|
|
assert_eq!(body, "http://127.0.0.1:4506/");
|
|
|
|
child.kill().unwrap();
|
|
child.wait().unwrap();
|
|
})
|
|
.await;
|
|
}
|