diff --git a/cli/tests/integration/cert_tests.rs b/cli/tests/integration/cert_tests.rs index f53ce9ceef..4ccc38809e 100644 --- a/cli/tests/integration/cert_tests.rs +++ b/cli/tests/integration/cert_tests.rs @@ -7,10 +7,8 @@ use lsp_types::Url; use std::io::BufReader; use std::io::Cursor; use std::io::Read; -use std::process::Command; use std::sync::Arc; use test_util as util; -use test_util::TempDir; use util::TestContext; itest_flaky!(cafile_url_imports { @@ -125,29 +123,29 @@ fn cafile_compile() { #[flaky_test::flaky_test] fn cafile_install_remote_module() { - let _g = util::http_server(); - let temp_dir = TempDir::new(); + let context = TestContext::with_http_server(); + let temp_dir = context.temp_dir(); let bin_dir = temp_dir.path().join("bin"); - std::fs::create_dir(&bin_dir).unwrap(); - let deno_dir = TempDir::new(); + bin_dir.create_dir_all(); 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 install_output = context + .new_command() + .args_vec([ + "install", + "--cert", + &cafile.to_string_lossy(), + "--root", + &temp_dir.path().to_string_lossy(), + "-n", + "echo_test", + "https://localhost:5545/echo.ts", + ]) + .split_output() + .run(); + println!("{}", install_output.stdout()); + eprintln!("{}", install_output.stderr()); + install_output.assert_exit_code(0); let mut echo_test_path = bin_dir.join("echo_test"); if cfg!(windows) { @@ -155,61 +153,52 @@ fn cafile_install_remote_module() { } assert!(echo_test_path.exists()); - let output = Command::new(echo_test_path) - .current_dir(temp_dir.path()) - .arg("foo") + let output = context + .new_command() + .name(echo_test_path) + .args("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")); + .run(); + output.assert_matches_text("[WILDCARD]foo"); } #[flaky_test::flaky_test] fn cafile_bundle_remote_exports() { - let _g = util::http_server(); + let context = TestContext::with_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 t = context.temp_dir(); 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()); + context + .new_command() + .args_vec([ + "bundle", + "--cert", + &cafile.to_string_lossy(), + mod1, + &bundle.to_string_lossy(), + ]) + .run() + .skip_output_check() + .assert_exit_code(0); + 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"); + test.write( + "import { printHello3 } from \"./mod1.bundle.js\"; +printHello3();", + ); - 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""); + context + .new_command() + .args_vec(["run", "--quiet", "--check", &test.to_string_lossy()]) + .run() + .assert_matches_text("[WILDCARD]Hello\n") + .assert_exit_code(0); } #[tokio::test] @@ -223,7 +212,7 @@ async fn listen_tls_alpn() { .arg("--allow-read") .arg("./cert/listen_tls_alpn.ts") .arg("4504") - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap(); let stdout = child.stdout.as_mut().unwrap(); @@ -272,7 +261,7 @@ async fn listen_tls_alpn_fail() { .arg("--allow-read") .arg("./cert/listen_tls_alpn_fail.ts") .arg("4505") - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap(); let stdout = child.stdout.as_mut().unwrap(); diff --git a/cli/tests/integration/compile_tests.rs b/cli/tests/integration/compile_tests.rs index 591d38d3d0..78249079db 100644 --- a/cli/tests/integration/compile_tests.rs +++ b/cli/tests/integration/compile_tests.rs @@ -1,6 +1,5 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use std::fs::File; use test_util as util; use util::assert_contains; use util::assert_not_contains; @@ -219,7 +218,7 @@ fn compile_with_file_exists_error() { dir.path().join("args/") }; let file_path = dir.path().join("args"); - File::create(&file_path).unwrap(); + file_path.write(""); context .new_command() .args_vec([ @@ -294,9 +293,7 @@ fn compile_with_conflict_file_exists_error() { exe )) .assert_exit_code(1); - assert!(std::fs::read(&exe) - .unwrap() - .eq(b"SHOULD NOT BE OVERWRITTEN")); + exe.assert_matches_text("SHOULD NOT BE OVERWRITTEN"); } #[test] diff --git a/cli/tests/integration/eval_tests.rs b/cli/tests/integration/eval_tests.rs index 99a0d674f4..daf1d8561b 100644 --- a/cli/tests/integration/eval_tests.rs +++ b/cli/tests/integration/eval_tests.rs @@ -8,7 +8,7 @@ fn eval_p() { .arg("eval") .arg("-p") .arg("1+2") - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap() .wait_with_output() @@ -28,7 +28,7 @@ fn eval_randomness() { .arg("eval") .arg("-p") .arg("Math.random()") - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap() .wait_with_output() diff --git a/cli/tests/integration/flags_tests.rs b/cli/tests/integration/flags_tests.rs index 695283aca2..89a8978dd3 100644 --- a/cli/tests/integration/flags_tests.rs +++ b/cli/tests/integration/flags_tests.rs @@ -1,7 +1,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use std::process::Stdio; use test_util as util; +use util::assert_contains; #[test] fn help_flag() { @@ -20,14 +20,9 @@ fn help_output() { let output = util::deno_cmd() .current_dir(util::testdata_path()) .arg("--help") - .stdout(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); + .run(); - assert!(output.status.success()); - let stdout = std::str::from_utf8(&output.stdout).unwrap(); + let stdout = output.combined_output(); let subcommand_descriptions = vec![ "Run a JavaScript or TypeScript program", "Run benchmarks", @@ -56,7 +51,7 @@ fn help_output() { ]; for description in subcommand_descriptions { - assert!(stdout.contains(description)); + assert_contains!(stdout, description); } } diff --git a/cli/tests/integration/fmt_tests.rs b/cli/tests/integration/fmt_tests.rs index dd9e503570..edebedc274 100644 --- a/cli/tests/integration/fmt_tests.rs +++ b/cli/tests/integration/fmt_tests.rs @@ -1,7 +1,6 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use test_util as util; -use test_util::TempDir; use util::assert_contains; use util::PathRef; use util::TestContext; @@ -91,25 +90,17 @@ fn fmt_test() { } #[test] -fn fmt_stdin_error() { - use std::io::Write; - let mut deno = util::deno_cmd() +fn fmt_stdin_syntax_error() { + let output = util::deno_cmd() .current_dir(util::testdata_path()) .arg("fmt") .arg("-") - .stdin(std::process::Stdio::piped()) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn() - .unwrap(); - let stdin = deno.stdin.as_mut().unwrap(); - let invalid_js = b"import { example }"; - stdin.write_all(invalid_js).unwrap(); - let output = deno.wait_with_output().unwrap(); - // Error message might change. Just check stdout empty, stderr not. - assert!(output.stdout.is_empty()); - assert!(!output.stderr.is_empty()); - assert!(!output.status.success()); + .set_stdin_text("import { example }") + .split_output() + .run(); + assert!(output.stdout().is_empty()); + assert!(!output.stderr().is_empty()); + output.assert_exit_code(1); } #[test] @@ -132,7 +123,8 @@ fn fmt_auto_ignore_git_and_node_modules() { bad_json_path.write("bad json\n"); } - let temp_dir = TempDir::new(); + let context = TestContext::default(); + let temp_dir = context.temp_dir(); let t = temp_dir.path().join("target"); let nest_git = t.join("nest").join(".git"); let git_dir = t.join(".git"); @@ -147,7 +139,6 @@ fn fmt_auto_ignore_git_and_node_modules() { create_bad_json(nest_node_modules); create_bad_json(node_modules_dir); - let context = TestContext::default(); let output = context .new_command() .cwd(t) diff --git a/cli/tests/integration/inspector_tests.rs b/cli/tests/integration/inspector_tests.rs index e593c3b29e..36d469196a 100644 --- a/cli/tests/integration/inspector_tests.rs +++ b/cli/tests/integration/inspector_tests.rs @@ -18,13 +18,12 @@ use hyper::Response; use std::io::BufRead; use std::time::Duration; use test_util as util; -use test_util::TempDir; use tokio::net::TcpStream; use tokio::time::timeout; use url::Url; use util::assert_starts_with; -use util::http_server; use util::DenoChild; +use util::TestContextBuilder; struct SpawnExecutor; @@ -292,7 +291,7 @@ async fn inspector_connect() { .arg("run") .arg(inspect_flag_with_unique_port("--inspect")) .arg(script) - .stderr(std::process::Stdio::piped()) + .stderr_piped() .spawn() .unwrap(); @@ -314,8 +313,7 @@ async fn inspector_break_on_first_line() { .arg("run") .arg(inspect_flag_with_unique_port("--inspect-brk")) .arg(script) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -398,8 +396,7 @@ async fn inspector_pause() { .arg("run") .arg(inspect_flag_with_unique_port("--inspect")) .arg(script) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -439,7 +436,7 @@ async fn inspector_port_collision() { .arg("run") .arg(&inspect_flag) .arg(script.clone()) - .stderr(std::process::Stdio::piped()) + .stderr_piped() .spawn() .unwrap(); @@ -453,7 +450,7 @@ async fn inspector_port_collision() { .arg("run") .arg(&inspect_flag) .arg(script) - .stderr(std::process::Stdio::piped()) + .stderr_piped() .spawn() .unwrap(); @@ -478,8 +475,7 @@ async fn inspector_does_not_hang() { .arg(inspect_flag_with_unique_port("--inspect-brk")) .env("NO_COLOR", "1") .arg(script) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -569,8 +565,7 @@ async fn inspector_without_brk_runs_code() { .arg("run") .arg(inspect_flag_with_unique_port("--inspect")) .arg(script) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -598,8 +593,7 @@ async fn inspector_runtime_evaluate_does_not_crash() { .arg("--allow-read") .arg(inspect_flag_with_unique_port("--inspect")) .stdin(std::process::Stdio::piped()) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -707,7 +701,7 @@ async fn inspector_json() { .arg("run") .arg(inspect_flag_with_unique_port("--inspect")) .arg(script) - .stderr(std::process::Stdio::piped()) + .stderr_piped() .spawn() .unwrap(); @@ -756,7 +750,7 @@ async fn inspector_json_list() { .arg("run") .arg(inspect_flag_with_unique_port("--inspect")) .arg(script) - .stderr(std::process::Stdio::piped()) + .stderr_piped() .spawn() .unwrap(); @@ -787,7 +781,7 @@ async fn inspector_connect_non_ws() { .arg("run") .arg(inspect_flag_with_unique_port("--inspect")) .arg(script) - .stderr(std::process::Stdio::piped()) + .stderr_piped() .spawn() .unwrap(); @@ -813,8 +807,7 @@ async fn inspector_break_on_first_line_in_test() { .arg(inspect_flag_with_unique_port("--inspect-brk")) .arg(script) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -890,8 +883,7 @@ async fn inspector_with_ts_files() { .arg("--check") .arg(inspect_flag_with_unique_port("--inspect-brk")) .arg(script) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -1009,8 +1001,7 @@ async fn inspector_memory() { .arg("run") .arg(inspect_flag_with_unique_port("--inspect-brk")) .arg(script) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -1110,8 +1101,7 @@ async fn inspector_profile() { .arg("run") .arg(inspect_flag_with_unique_port("--inspect-brk")) .arg(script) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -1188,22 +1178,20 @@ async fn inspector_profile() { #[ignore] #[tokio::test] async fn inspector_break_on_first_line_npm_esm() { - let _server = http_server(); - - let child = util::deno_cmd() - .arg("run") - .arg("--quiet") - .arg(inspect_flag_with_unique_port("--inspect-brk")) - .arg("npm:@denotest/bin/cli-esm") - .arg("this") - .arg("is") - .arg("a") - .arg("test") - .envs(util::env_vars_for_npm_tests()) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn() - .unwrap(); + let context = TestContextBuilder::for_npm().build(); + let child = context + .new_command() + .args_vec([ + "run", + "--quiet", + &inspect_flag_with_unique_port("--inspect-brk"), + "npm:@denotest/bin/cli-esm", + "this", + "is", + "a", + "test", + ]) + .spawn_with_piped_output(); let mut tester = InspectorTester::create(child, ignore_script_parsed).await; @@ -1258,21 +1246,20 @@ async fn inspector_break_on_first_line_npm_esm() { #[ignore] #[tokio::test] async fn inspector_break_on_first_line_npm_cjs() { - let _server = http_server(); - let child = util::deno_cmd() - .arg("run") - .arg("--quiet") - .arg(inspect_flag_with_unique_port("--inspect-brk")) - .arg("npm:@denotest/bin/cli-cjs") - .arg("this") - .arg("is") - .arg("a") - .arg("test") - .envs(util::env_vars_for_npm_tests()) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn() - .unwrap(); + let context = TestContextBuilder::for_npm().build(); + let child = context + .new_command() + .args_vec([ + "run", + "--quiet", + &inspect_flag_with_unique_port("--inspect-brk"), + "npm:@denotest/bin/cli-cjs", + "this", + "is", + "a", + "test", + ]) + .spawn_with_piped_output(); let mut tester = InspectorTester::create(child, ignore_script_parsed).await; @@ -1328,19 +1315,17 @@ async fn inspector_break_on_first_line_npm_cjs() { #[tokio::test] async fn inspector_error_with_npm_import() { let script = util::testdata_path().join("inspector/error_with_npm_import.js"); - let _server = http_server(); - - let child = util::deno_cmd() - .arg("run") - .arg("--quiet") - .arg("-A") - .arg(inspect_flag_with_unique_port("--inspect-brk")) - .arg(script) - .envs(util::env_vars_for_npm_tests()) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn() - .unwrap(); + let context = TestContextBuilder::for_npm().build(); + let child = context + .new_command() + .args_vec([ + "run", + "--quiet", + "-A", + &inspect_flag_with_unique_port("--inspect-brk"), + &script.to_string_lossy(), + ]) + .spawn_with_piped_output(); let mut tester = InspectorTester::create(child, ignore_script_parsed).await; @@ -1392,19 +1377,19 @@ async fn inspector_error_with_npm_import() { #[tokio::test] async fn inspector_wait() { let script = util::testdata_path().join("inspector/inspect_wait.js"); - let temp_dir = TempDir::new(); + let test_context = TestContextBuilder::new().use_temp_cwd().build(); + let temp_dir = test_context.temp_dir(); - let child = util::deno_cmd() - .current_dir(temp_dir.path()) - .arg("run") - .arg("--quiet") - .arg("-A") - .arg(inspect_flag_with_unique_port("--inspect-wait")) - .arg(script) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn() - .unwrap(); + let child = test_context + .new_command() + .args_vec([ + "run", + "--quiet", + "-A", + &inspect_flag_with_unique_port("--inspect-wait"), + &script.to_string_lossy(), + ]) + .spawn_with_piped_output(); tokio::time::sleep(tokio::time::Duration::from_millis(300)).await; assert!(!temp_dir.path().join("hello.txt").exists()); diff --git a/cli/tests/integration/js_unit_tests.rs b/cli/tests/integration/js_unit_tests.rs index 33d79236ca..d4a56b63e3 100644 --- a/cli/tests/integration/js_unit_tests.rs +++ b/cli/tests/integration/js_unit_tests.rs @@ -1,7 +1,6 @@ // 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; @@ -112,8 +111,7 @@ util::unit_test_factory!( fn js_unit_test(test: String) { let _g = util::http_server(); - let mut deno = util::deno_cmd(); - let deno = deno + let deno = util::deno_cmd() .current_dir(util::root_path()) .arg("test") .arg("--unstable") @@ -130,8 +128,7 @@ fn js_unit_test(test: String) { let mut deno = deno .arg("-A") .arg(util::tests_path().join("unit").join(format!("{test}.ts"))) - .stderr(Stdio::piped()) - .stdout(Stdio::piped()) + .piped_output() .spawn() .expect("failed to spawn script"); diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index 92b53b3b10..8ec1bdd41f 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -8,7 +8,6 @@ use deno_core::serde_json::Value; use deno_core::url::Url; use pretty_assertions::assert_eq; use std::fs; -use std::process::Stdio; use test_util::assert_starts_with; use test_util::deno_cmd_with_deno_dir; use test_util::env_vars_for_npm_tests; @@ -7130,8 +7129,7 @@ fn lsp_npm_specifier_unopened_file() { .arg("--quiet") .arg("other.ts") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); diff --git a/cli/tests/integration/node_unit_tests.rs b/cli/tests/integration/node_unit_tests.rs index 5489a7255f..9aad274e38 100644 --- a/cli/tests/integration/node_unit_tests.rs +++ b/cli/tests/integration/node_unit_tests.rs @@ -1,7 +1,6 @@ // 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; @@ -91,8 +90,7 @@ util::unit_test_factory!( fn node_unit_test(test: String) { let _g = util::http_server(); - let mut deno = util::deno_cmd(); - let mut deno = deno + let mut deno = util::deno_cmd() .current_dir(util::root_path()) .arg("test") .arg("--unstable") @@ -112,8 +110,7 @@ fn node_unit_test(test: String) { .join(format!("{test}.ts")), ) .envs(env_vars_for_npm_tests()) - .stderr(Stdio::piped()) - .stdout(Stdio::piped()) + .piped_output() .spawn() .expect("failed to spawn script"); diff --git a/cli/tests/integration/npm_tests.rs b/cli/tests/integration/npm_tests.rs index 95ffd71cd8..f49e3e9889 100644 --- a/cli/tests/integration/npm_tests.rs +++ b/cli/tests/integration/npm_tests.rs @@ -4,7 +4,6 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use pretty_assertions::assert_eq; -use std::process::Stdio; use test_util as util; use util::assert_contains; use util::env_vars_for_npm_tests; @@ -508,8 +507,7 @@ fn cached_only_after_first_run() { .arg("npm/cached_only_after_first_run/main1.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -528,8 +526,7 @@ fn cached_only_after_first_run() { .arg("npm/cached_only_after_first_run/main2.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -551,8 +548,7 @@ fn cached_only_after_first_run() { .arg("npm/cached_only_after_first_run/main1.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -578,8 +574,7 @@ fn reload_flag() { .arg("npm/reload/main.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -598,8 +593,7 @@ fn reload_flag() { .arg("npm/reload/main.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -618,8 +612,7 @@ fn reload_flag() { .arg("npm/reload/main.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -638,8 +631,7 @@ fn reload_flag() { .arg("npm/reload/main.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -658,8 +650,7 @@ fn reload_flag() { .arg("npm/reload/main.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -685,8 +676,7 @@ fn no_npm_after_first_run() { .arg("npm/no_npm_after_first_run/main1.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -707,8 +697,7 @@ fn no_npm_after_first_run() { .arg("npm/no_npm_after_first_run/main1.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -727,8 +716,7 @@ fn no_npm_after_first_run() { .arg("npm/no_npm_after_first_run/main1.ts") .env("NO_COLOR", "1") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -1273,8 +1261,7 @@ fn lock_file_missing_top_level_package() { .arg("-A") .arg("main.ts") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -1511,8 +1498,7 @@ fn lock_file_lock_write() { .arg("--quiet") .arg("npm:cowsay@1.5.0") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -1563,8 +1549,7 @@ fn auto_discover_lock_file() { .arg("npm:@denotest/bin/cli-esm") .arg("test") .envs(env_vars_for_npm_tests()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 306d4df67f..ac379d7fc5 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -331,8 +331,7 @@ itest!(webstorage_serialization { fn webstorage_location_shares_origin() { let deno_dir = util::new_deno_dir(); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd + let output = util::deno_cmd_with_deno_dir(&deno_dir) .current_dir(util::testdata_path()) .arg("run") .arg("--location") @@ -346,8 +345,7 @@ fn webstorage_location_shares_origin() { assert!(output.status.success()); assert_eq!(output.stdout, b"Storage { length: 0 }\n"); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd + let output = util::deno_cmd_with_deno_dir(&deno_dir) .current_dir(util::testdata_path()) .arg("run") .arg("--location") @@ -366,139 +364,69 @@ fn webstorage_location_shares_origin() { // storage persists against unique configuration files. #[test] fn webstorage_config_file() { - let deno_dir = util::new_deno_dir(); + let context = TestContext::default(); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("--config") - .arg("run/webstorage/config_a.jsonc") - .arg("run/webstorage/fixture.ts") - .stdout(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(output.status.success()); - assert_eq!(output.stdout, b"Storage { length: 0 }\n"); + context + .new_command() + .args( + "run --config run/webstorage/config_a.jsonc run/webstorage/fixture.ts", + ) + .run() + .assert_matches_text("Storage { length: 0 }\n"); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("--config") - .arg("run/webstorage/config_b.jsonc") - .arg("run/webstorage/logger.ts") - .stdout(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(output.status.success()); - assert_eq!(output.stdout, b"Storage { length: 0 }\n"); + context + .new_command() + .args("run --config run/webstorage/config_b.jsonc run/webstorage/logger.ts") + .run() + .assert_matches_text("Storage { length: 0 }\n"); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("--config") - .arg("run/webstorage/config_a.jsonc") - .arg("run/webstorage/logger.ts") - .stdout(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(output.status.success()); - assert_eq!(output.stdout, b"Storage { length: 1, hello: \"deno\" }\n"); + context + .new_command() + .args("run --config run/webstorage/config_a.jsonc run/webstorage/logger.ts") + .run() + .assert_matches_text("Storage { length: 1, hello: \"deno\" }\n"); } // tests to ensure `--config` does not effect persisted storage when a // `--location` is provided. #[test] fn webstorage_location_precedes_config() { - let deno_dir = util::new_deno_dir(); + let context = TestContext::default(); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("--location") - .arg("https://example.com/a.ts") - .arg("--config") - .arg("run/webstorage/config_a.jsonc") - .arg("run/webstorage/fixture.ts") - .stdout(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(output.status.success()); - assert_eq!(output.stdout, b"Storage { length: 0 }\n"); + context.new_command() + .args("run --location https://example.com/a.ts --config run/webstorage/config_a.jsonc run/webstorage/fixture.ts") + .run() + .assert_matches_text("Storage { length: 0 }\n"); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("--location") - .arg("https://example.com/b.ts") - .arg("--config") - .arg("run/webstorage/config_b.jsonc") - .arg("run/webstorage/logger.ts") - .stdout(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(output.status.success()); - assert_eq!(output.stdout, b"Storage { length: 1, hello: \"deno\" }\n"); + context.new_command() + .args("run --location https://example.com/b.ts --config run/webstorage/config_b.jsonc run/webstorage/logger.ts") + .run() + .assert_matches_text("Storage { length: 1, hello: \"deno\" }\n"); } // test to ensure that when there isn't a configuration or location, that the // main module is used to determine how to persist storage data. #[test] fn webstorage_main_module() { - let deno_dir = util::new_deno_dir(); + let context = TestContext::default(); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("run/webstorage/fixture.ts") - .stdout(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(output.status.success()); - assert_eq!(output.stdout, b"Storage { length: 0 }\n"); + context + .new_command() + .args("run run/webstorage/fixture.ts") + .run() + .assert_matches_text("Storage { length: 0 }\n"); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("run/webstorage/logger.ts") - .stdout(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(output.status.success()); - assert_eq!(output.stdout, b"Storage { length: 0 }\n"); + context + .new_command() + .args("run run/webstorage/logger.ts") + .run() + .assert_matches_text("Storage { length: 0 }\n"); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("run/webstorage/fixture.ts") - .stdout(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(output.status.success()); - assert_eq!(output.stdout, b"Storage { length: 1, hello: \"deno\" }\n"); + context + .new_command() + .args("run run/webstorage/fixture.ts") + .run() + .assert_matches_text("Storage { length: 1, hello: \"deno\" }\n"); } itest!(_075_import_local_query_hash { @@ -2102,8 +2030,7 @@ fn no_validate_asm() { .current_dir(util::testdata_path()) .arg("run") .arg("run/no_validate_asm.js") - .stderr(Stdio::piped()) - .stdout(Stdio::piped()) + .piped_output() .spawn() .unwrap() .wait_with_output() @@ -2146,7 +2073,7 @@ console.log("executing typescript"); .arg("--check") .arg("-") .stdin(std::process::Stdio::piped()) - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap(); let stdin = p.stdin.as_mut().unwrap(); @@ -2171,7 +2098,7 @@ console.log("executing javascript"); .arg("--check") .arg("-") .stdin(std::process::Stdio::piped()) - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap(); let stdin = p.stdin.as_mut().unwrap(); @@ -2290,7 +2217,7 @@ fn rust_log() { .current_dir(util::testdata_path()) .arg("run") .arg("run/001_hello.js") - .stderr(Stdio::piped()) + .stderr_piped() .spawn() .unwrap() .wait_with_output() @@ -2304,7 +2231,7 @@ fn rust_log() { .arg("run") .arg("run/001_hello.js") .env("RUST_LOG", "debug") - .stderr(Stdio::piped()) + .stderr_piped() .spawn() .unwrap() .wait_with_output() @@ -2315,36 +2242,24 @@ fn rust_log() { #[test] fn dont_cache_on_check_fail() { - let deno_dir = util::new_deno_dir(); + let context = TestContext::default(); + let output = context + .new_command() + .args("run --check=all --reload run/error_003_typescript.ts") + .split_output() + .run(); + assert!(!output.stderr().is_empty()); + output.skip_stdout_check(); + output.assert_exit_code(1); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("--check=all") - .arg("--reload") - .arg("run/error_003_typescript.ts") - .stderr(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(!output.status.success()); - assert!(!output.stderr.is_empty()); - - let mut deno_cmd = util::deno_cmd_with_deno_dir(&deno_dir); - let output = deno_cmd - .current_dir(util::testdata_path()) - .arg("run") - .arg("--check=all") - .arg("run/error_003_typescript.ts") - .stderr(Stdio::piped()) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(!output.status.success()); - assert!(!output.stderr.is_empty()); + let output = context + .new_command() + .args("run --check=all run/error_003_typescript.ts") + .split_output() + .run(); + assert!(!output.stderr().is_empty()); + output.skip_stdout_check(); + output.assert_exit_code(1); } mod permissions { @@ -2998,9 +2913,8 @@ fn issue12740() { let mod_dir = TempDir::new(); let mod1_path = mod_dir.path().join("mod1.ts"); let mod2_path = mod_dir.path().join("mod2.ts"); - let mut deno_cmd = util::deno_cmd(); - std::fs::write(&mod1_path, "").unwrap(); - let status = deno_cmd + mod1_path.write(""); + let status = util::deno_cmd() .current_dir(util::testdata_path()) .arg("run") .arg(&mod1_path) @@ -3011,9 +2925,9 @@ fn issue12740() { .wait() .unwrap(); assert!(status.success()); - std::fs::write(&mod1_path, "export { foo } from \"./mod2.ts\";").unwrap(); - std::fs::write(mod2_path, "(").unwrap(); - let status = deno_cmd + mod1_path.write("export { foo } from \"./mod2.ts\";"); + mod2_path.write("("); + let status = util::deno_cmd() .current_dir(util::testdata_path()) .arg("run") .arg(&mod1_path) @@ -3032,11 +2946,10 @@ fn issue12807() { let mod_dir = TempDir::new(); let mod1_path = mod_dir.path().join("mod1.ts"); let mod2_path = mod_dir.path().join("mod2.ts"); - let mut deno_cmd = util::deno_cmd(); // With a fresh `DENO_DIR`, run a module with a dependency and a type error. - std::fs::write(&mod1_path, "import './mod2.ts'; Deno.exit('0');").unwrap(); - std::fs::write(mod2_path, "console.log('Hello, world!');").unwrap(); - let status = deno_cmd + mod1_path.write("import './mod2.ts'; Deno.exit('0');"); + mod2_path.write("console.log('Hello, world!');"); + let status = util::deno_cmd() .current_dir(util::testdata_path()) .arg("run") .arg("--check") @@ -3050,7 +2963,7 @@ fn issue12807() { assert!(!status.success()); // Fix the type error and run again. std::fs::write(&mod1_path, "import './mod2.ts'; Deno.exit(0);").unwrap(); - let status = deno_cmd + let status = util::deno_cmd() .current_dir(util::testdata_path()) .arg("run") .arg("--check") @@ -3508,7 +3421,7 @@ fn check_local_then_remote() { .arg("--check=all") .arg("run/remote_type_error/main.ts") .env("NO_COLOR", "1") - .stderr(Stdio::piped()) + .stderr_piped() .spawn() .unwrap() .wait_with_output() @@ -3598,20 +3511,18 @@ itest!(config_json_import { #[test] fn running_declaration_files() { - let temp_dir = TempDir::new(); + let context = TestContextBuilder::new().use_temp_cwd().build(); + let temp_dir = context.temp_dir(); let files = vec!["file.d.ts", "file.d.cts", "file.d.mts"]; for file in files { temp_dir.write(file, ""); - let mut deno_cmd = util::deno_cmd_with_deno_dir(&temp_dir); - let output = deno_cmd - .current_dir(temp_dir.path()) - .args(["run", file]) - .spawn() - .unwrap() - .wait_with_output() - .unwrap(); - assert!(output.status.success()); + context + .new_command() + .args_vec(["run", file]) + .run() + .skip_output_check() + .assert_exit_code(0); } } @@ -3846,8 +3757,7 @@ fn basic_auth_tokens() { .current_dir(util::root_path()) .arg("run") .arg("http://127.0.0.1:4554/run/001_hello.js") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap() .wait_with_output() @@ -3869,8 +3779,7 @@ fn basic_auth_tokens() { .arg("run") .arg("http://127.0.0.1:4554/run/001_hello.js") .env("DENO_AUTH_TOKENS", "testuser123:testpassabc@127.0.0.1:4554") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap() .wait_with_output() @@ -3954,8 +3863,7 @@ async fn test_resolve_dns() { .arg("--check") .arg("--allow-net") .arg("run/resolve_dns.ts") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap() .wait_with_output() @@ -3982,8 +3890,7 @@ async fn test_resolve_dns() { .arg("--check") .arg("--allow-net=127.0.0.1:4553") .arg("run/resolve_dns.ts") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap() .wait_with_output() @@ -4012,8 +3919,7 @@ async fn test_resolve_dns() { .arg("--check") .arg("--allow-net=deno.land") .arg("run/resolve_dns.ts") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap() .wait_with_output() @@ -4034,8 +3940,7 @@ async fn test_resolve_dns() { .arg("run") .arg("--check") .arg("run/resolve_dns.ts") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap() .wait_with_output() @@ -4062,7 +3967,7 @@ async fn http2_request_url() { .arg("--allow-read") .arg("./run/http2_request_url.ts") .arg("4506") - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap(); let stdout = child.stdout.as_mut().unwrap(); @@ -4102,7 +4007,7 @@ fn set_raw_should_not_panic_on_no_tty() { // 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()) + .stderr_piped() .spawn() .unwrap() .wait_with_output() @@ -4156,7 +4061,7 @@ fn broken_stdout() { .arg("eval") .arg("console.log(3.14)") .stdout(writer) - .stderr(std::process::Stdio::piped()) + .stderr_piped() .spawn() .unwrap() .wait_with_output() @@ -4305,7 +4210,7 @@ async fn websocketstream_ping() { .arg("--cert") .arg(root_ca) .arg(script) - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap(); let server = tokio::net::TcpListener::bind("127.0.0.1:4513") @@ -4350,7 +4255,7 @@ async fn websocket_server_multi_field_connection_header() { .arg("--cert") .arg(root_ca) .arg(script) - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap(); @@ -4405,7 +4310,7 @@ async fn websocket_server_idletimeout() { .arg("--cert") .arg(root_ca) .arg(script) - .stdout(std::process::Stdio::piped()) + .stdout_piped() .spawn() .unwrap(); diff --git a/cli/tests/integration/vendor_tests.rs b/cli/tests/integration/vendor_tests.rs index 94ab2ad5ae..2bcf026106 100644 --- a/cli/tests/integration/vendor_tests.rs +++ b/cli/tests/integration/vendor_tests.rs @@ -5,7 +5,6 @@ use deno_core::serde_json::json; use pretty_assertions::assert_eq; use std::fmt::Write as _; use std::path::PathBuf; -use std::process::Stdio; use test_util as util; use test_util::TempDir; use util::http_server; @@ -24,7 +23,7 @@ fn output_dir_exists() { .env("NO_COLOR", "1") .arg("vendor") .arg("mod.ts") - .stderr(Stdio::piped()) + .stderr_piped() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -46,7 +45,7 @@ fn output_dir_exists() { .arg("--output") .arg("vendor") .arg("mod.ts") - .stderr(Stdio::piped()) + .stderr_piped() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -91,8 +90,7 @@ fn standard_test() { .arg("--output") .arg("vendor2") .env("NO_COLOR", "1") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -140,8 +138,7 @@ fn standard_test() { .arg("--import-map") .arg("vendor2/import_map.json") .arg("my_app.ts") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -178,8 +175,7 @@ fn import_map_output_dir() { .arg("--import-map") .arg("vendor/import_map.json") .arg("my_app.ts") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -210,8 +206,7 @@ fn remote_module_test() { .env("NO_COLOR", "1") .arg("vendor") .arg("http://localhost:4545/vendor/query_reexport.ts") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -272,7 +267,7 @@ fn existing_import_map_no_remote() { .arg("mod.ts") .arg("--import-map") .arg(import_map_filename) - .stderr(Stdio::piped()) + .stderr_piped() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -345,8 +340,7 @@ fn existing_import_map_mixed_with_remote() { .arg("vendor/import_map.json") .arg("--output") .arg("vendor2") - .stderr(Stdio::piped()) - .stdout(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -434,8 +428,7 @@ fn dynamic_import() { .arg("--import-map") .arg("vendor/import_map.json") .arg("mod.ts") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -459,8 +452,7 @@ fn dynamic_non_analyzable_import() { .arg("vendor") .arg("--reload") .arg("mod.ts") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -502,8 +494,7 @@ fn update_existing_config_test() { .arg("--output") .arg("vendor2") .env("NO_COLOR", "1") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); @@ -527,8 +518,7 @@ fn update_existing_config_test() { .arg("--check") .arg("--quiet") .arg("my_app.ts") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .piped_output() .spawn() .unwrap(); let output = deno.wait_with_output().unwrap(); diff --git a/cli/tests/integration/watcher_tests.rs b/cli/tests/integration/watcher_tests.rs index 0defaa69ea..a690db8467 100644 --- a/cli/tests/integration/watcher_tests.rs +++ b/cli/tests/integration/watcher_tests.rs @@ -217,8 +217,7 @@ async fn lint_watch_test() { .arg(&badly_linted) .arg("--watch") .arg("--unstable") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -275,8 +274,7 @@ async fn lint_watch_without_args_test() { .arg("lint") .arg("--watch") .arg("--unstable") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -330,8 +328,7 @@ async fn lint_all_files_on_each_change_test() { .arg(t.path()) .arg("--watch") .arg("--unstable") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -369,8 +366,7 @@ async fn fmt_watch_test() { .arg(&badly_formatted) .arg("--watch") .arg("--unstable") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -425,8 +421,7 @@ async fn fmt_watch_without_args_test() { .arg("fmt") .arg("--watch") .arg("--unstable") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -482,8 +477,7 @@ async fn fmt_check_all_files_on_each_change_test() { .arg("--watch") .arg("--check") .arg("--unstable") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -522,8 +516,7 @@ async fn bundle_js_watch() { .arg("--watch") .arg("--unstable") .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); @@ -595,8 +588,7 @@ async fn bundle_watch_not_exit() { .arg("--watch") .arg("--unstable") .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_stdout_lines, mut stderr_lines) = child_lines(&mut deno); @@ -660,8 +652,7 @@ async fn run_watch_no_dynamic() { .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -750,8 +741,7 @@ async fn run_watch_external_watch_files() { .arg("--unstable") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -798,8 +788,7 @@ async fn run_watch_load_unload_events() { .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -851,8 +840,7 @@ async fn run_watch_not_exit() { .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -909,8 +897,7 @@ async fn run_watch_with_import_map_and_relative_paths() { .arg(&import_map_path) .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -941,8 +928,7 @@ async fn run_watch_with_ext_flag() { .arg("ts") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -975,8 +961,7 @@ async fn run_watch_error_messages() { .arg("--watch") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_, mut stderr_lines) = child_lines(&mut child); @@ -1001,8 +986,7 @@ async fn test_watch_basic() { .arg("--no-check") .arg(t.path()) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1158,8 +1142,7 @@ async fn test_watch_doc() { .arg("--unstable") .arg(t.path()) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1207,8 +1190,7 @@ async fn test_watch_module_graph_error_referrer() { .arg("--unstable") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_, mut stderr_lines) = child_lines(&mut child); @@ -1245,8 +1227,7 @@ async fn test_watch_unload_handler_error_on_drop() { .arg("--watch") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (_, mut stderr_lines) = child_lines(&mut child); @@ -1283,8 +1264,7 @@ async fn run_watch_blob_urls_reset() { .arg("--watch") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1303,20 +1283,17 @@ async fn test_watch_sigint() { use nix::sys::signal; use nix::sys::signal::Signal; use nix::unistd::Pid; + use util::TestContext; - let t = TempDir::new(); + let context = TestContext::default(); + let t = context.temp_dir(); let file_to_watch = t.path().join("file_to_watch.js"); file_to_watch.write(r#"Deno.test("foo", () => {});"#); - let mut child = util::deno_cmd() - .current_dir(util::testdata_path()) - .arg("test") - .arg("--watch") - .arg(&file_to_watch) + let mut child = context + .new_command() + .args_vec(["test", "--watch", &file_to_watch.to_string_lossy()]) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn() - .unwrap(); + .spawn_with_piped_output(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); wait_contains("Test started", &mut stderr_lines).await; wait_contains("ok | 1 passed | 0 failed", &mut stdout_lines).await; @@ -1338,8 +1315,7 @@ async fn bench_watch_basic() { .arg("--no-check") .arg(t.path()) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1459,8 +1435,7 @@ async fn run_watch_reload_once() { .arg("--reload") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1499,8 +1474,7 @@ async fn test_watch_serve() { .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1551,8 +1525,7 @@ async fn run_watch_dynamic_imports() { .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1623,8 +1596,7 @@ async fn run_watch_inspect() { .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1678,8 +1650,7 @@ console.log("Listening...") .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1745,8 +1716,7 @@ export function foo() { .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1804,8 +1774,7 @@ export function foo() { .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); @@ -1870,8 +1839,7 @@ export function foo() { .arg("debug") .arg(&file_to_watch) .env("NO_COLOR", "1") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) + .piped_output() .spawn() .unwrap(); let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child); diff --git a/test_util/src/builders.rs b/test_util/src/builders.rs index b340a86746..414a0103f3 100644 --- a/test_util/src/builders.rs +++ b/test_util/src/builders.rs @@ -4,10 +4,14 @@ use std::cell::RefCell; use std::collections::HashMap; use std::collections::HashSet; use std::ffi::OsStr; +use std::ffi::OsString; use std::io::Read; use std::io::Write; +use std::ops::Deref; +use std::ops::DerefMut; use std::path::Path; use std::path::PathBuf; +use std::process::Child; use std::process::Command; use std::process::Stdio; use std::rc::Rc; @@ -375,6 +379,11 @@ impl TestCommandBuilder { for (key, value) in &self.envs { envs.insert(key.to_string(), value.to_string()); } + if !envs.contains_key("NPM_CONFIG_REGISTRY") + && !self.envs_remove.contains("NPM_CONFIG_REGISTRY") + { + envs.insert("NPM_CONFIG_REGISTRY".to_string(), npm_registry_unset_url()); + } envs } @@ -409,26 +418,33 @@ impl TestCommandBuilder { #[track_caller] pub fn run(&self) -> TestCommandOutput { - fn read_pipe_to_string(mut pipe: os_pipe::PipeReader) -> String { - let mut output = String::new(); - pipe.read_to_string(&mut output).unwrap(); - output - } - - fn sanitize_output(text: String, args: &[String]) -> String { - let mut text = strip_ansi_codes(&text).to_string(); - // deno test's output capturing flushes with a zero-width space in order to - // synchronize the output pipes. Occasionally this zero width space - // might end up in the output so strip it from the output comparison here. - if args.first().map(|s| s.as_str()) == Some("test") { - text = text.replace('\u{200B}', ""); - } - text - } - - let cwd = self.build_cwd(); let args = self.build_args(); + let mut command = self.start_build_command(&args); + + if self.split_output { + command = command.split_output(); + } + + if let Some(input) = &self.stdin { + command = command.set_stdin_text(input.clone()); + } + command = command.set_testdata_dir(&self.context.testdata_dir); + + command.run() + } + + pub fn spawn_with_piped_output(&self) -> DenoChild { + self + .start_build_command(&self.build_args()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap() + } + + fn start_build_command(&self, args: &[String]) -> DenoCmd { let mut command = Command::new(self.build_command_path()); + let cwd = self.build_cwd(); println!("command {} {}", self.command_name, args.join(" ")); println!("command cwd {}", cwd); @@ -436,14 +452,173 @@ impl TestCommandBuilder { if self.env_clear { command.env_clear(); } - let mut envs = self.build_envs(); - if !envs.contains_key("NPM_CONFIG_REGISTRY") { - envs.insert("NPM_CONFIG_REGISTRY".to_string(), npm_registry_unset_url()); - } + let envs = self.build_envs(); command.envs(envs); command.current_dir(cwd); command.stdin(Stdio::piped()); + DenoCmd::new_raw(self.context.temp_dir.clone(), command) + } +} +pub struct DenoCmd { + deno_dir: TempDir, + cmd: Command, + stdin_text: Option, + split_output: bool, + testdata_dir: Option, +} + +impl DenoCmd { + pub fn new_raw(deno_dir: TempDir, cmd: Command) -> Self { + Self { + deno_dir, + cmd, + stdin_text: None, + split_output: false, + testdata_dir: None, + } + } + + pub fn args(mut self, args: I) -> Self + where + I: IntoIterator, + S: AsRef, + { + self.cmd.args(args); + self + } + + pub fn arg(mut self, arg: S) -> Self + where + S: AsRef, + { + self.cmd.arg(arg); + self + } + + pub fn envs(mut self, vars: I) -> Self + where + I: IntoIterator, + K: AsRef, + V: AsRef, + { + self.cmd.envs(vars); + self + } + + pub fn env(mut self, key: K, val: V) -> Self + where + K: AsRef, + V: AsRef, + { + self.cmd.env(key, val); + self + } + + pub fn env_remove(mut self, key: K) -> Self + where + K: AsRef, + { + self.cmd.env_remove(key); + self + } + + pub fn stdin>(mut self, cfg: T) -> Self { + self.cmd.stdin(cfg); + self + } + + pub fn stdout>(mut self, cfg: T) -> Self { + self.cmd.stdout(cfg); + self + } + + pub fn stderr>(mut self, cfg: T) -> Self { + self.cmd.stderr(cfg); + self + } + + pub fn current_dir>(mut self, dir: P) -> Self { + self.cmd.current_dir(dir); + self + } + + pub fn output(mut self) -> Result { + self.cmd.output() + } + + pub fn status(mut self) -> Result { + self.cmd.status() + } + + pub fn stdin_piped(self) -> Self { + self.stdin(std::process::Stdio::piped()) + } + + pub fn stdout_piped(self) -> Self { + self.stdout(std::process::Stdio::piped()) + } + + pub fn stderr_piped(self) -> Self { + self.stderr(std::process::Stdio::piped()) + } + + pub fn piped_output(self) -> Self { + self.stdout_piped().stderr_piped() + } + + pub fn set_stdin_text(mut self, text: impl AsRef) -> Self { + self.stdin_text = Some(text.as_ref().to_string()); + self.stdin_piped() + } + + pub fn set_testdata_dir(mut self, dir: impl AsRef) -> Self { + self.testdata_dir = Some(PathRef::new(dir)); + self + } + + pub fn split_output(mut self) -> Self { + self.split_output = true; + self + } + + pub fn spawn(mut self) -> Result { + let mut child = DenoChild { + _deno_dir: self.deno_dir.clone(), + child: self.cmd.spawn()?, + }; + + if let Some(input) = &self.stdin_text { + let mut p_stdin = child.stdin.take().unwrap(); + write!(p_stdin, "{input}").unwrap(); + } + + Ok(child) + } + + pub fn run(self) -> TestCommandOutput { + fn read_pipe_to_string(mut pipe: os_pipe::PipeReader) -> String { + let mut output = String::new(); + pipe.read_to_string(&mut output).unwrap(); + output + } + + fn sanitize_output(text: String, args: &[OsString]) -> String { + let mut text = strip_ansi_codes(&text).to_string(); + // deno test's output capturing flushes with a zero-width space in order to + // synchronize the output pipes. Occasionally this zero width space + // might end up in the output so strip it from the output comparison here. + if args.first().and_then(|s| s.to_str()) == Some("test") { + text = text.replace('\u{200B}', ""); + } + text + } + + let mut command = self.cmd; + let args = command + .get_args() + .map(ToOwned::to_owned) + .collect::>(); let (combined_reader, std_out_err_handle) = if self.split_output { let (stdout_reader, stdout_writer) = pipe().unwrap(); let (stderr_reader, stderr_writer) = pipe().unwrap(); @@ -465,7 +640,7 @@ impl TestCommandBuilder { let mut process = command.spawn().expect("Failed spawning command"); - if let Some(input) = &self.stdin { + if let Some(input) = &self.stdin_text { let mut p_stdin = process.stdin.take().unwrap(); write!(p_stdin, "{input}").unwrap(); } @@ -500,16 +675,43 @@ impl TestCommandBuilder { signal, combined, std_out_err, - testdata_dir: self.context.testdata_dir.clone(), + testdata_dir: self.testdata_dir.unwrap_or_else(testdata_path), asserted_exit_code: RefCell::new(false), asserted_stdout: RefCell::new(false), asserted_stderr: RefCell::new(false), asserted_combined: RefCell::new(false), - _test_context: self.context.clone(), + _temp_dir: self.deno_dir.clone(), } } } +pub struct DenoChild { + // keep alive for the duration of the use of this struct + _deno_dir: TempDir, + child: Child, +} + +impl Deref for DenoChild { + type Target = Child; + fn deref(&self) -> &Child { + &self.child + } +} + +impl DerefMut for DenoChild { + fn deref_mut(&mut self) -> &mut Child { + &mut self.child + } +} + +impl DenoChild { + pub fn wait_with_output( + self, + ) -> Result { + self.child.wait_with_output() + } +} + pub struct TestCommandOutput { combined: Option, std_out_err: Option<(String, String)>, @@ -521,7 +723,7 @@ pub struct TestCommandOutput { asserted_combined: RefCell, asserted_exit_code: RefCell, // keep alive for the duration of the output reference - _test_context: TestContext, + _temp_dir: TempDir, } impl Drop for TestCommandOutput { @@ -572,7 +774,17 @@ impl TestCommandOutput { pub fn skip_output_check(&self) -> &Self { *self.asserted_combined.borrow_mut() = true; + self.skip_stdout_check(); + self.skip_stderr_check(); + self + } + + pub fn skip_stdout_check(&self) -> &Self { *self.asserted_stdout.borrow_mut() = true; + self + } + + pub fn skip_stderr_check(&self) -> &Self { *self.asserted_stderr.borrow_mut() = true; self } diff --git a/test_util/src/lib.rs b/test_util/src/lib.rs index e004f14743..24be651d12 100644 --- a/test_util/src/lib.rs +++ b/test_util/src/lib.rs @@ -55,9 +55,6 @@ use std::io::Write; use std::net::Ipv6Addr; use std::net::SocketAddr; use std::net::SocketAddrV6; -use std::ops::Deref; -use std::ops::DerefMut; -use std::path::Path; use std::path::PathBuf; use std::pin::Pin; use std::process::Child; @@ -85,6 +82,8 @@ pub mod lsp; mod npm; pub mod pty; +pub use builders::DenoChild; +pub use builders::DenoCmd; pub use builders::TestCommandBuilder; pub use builders::TestCommandOutput; pub use builders::TestContext; @@ -2099,15 +2098,13 @@ pub fn run_and_collect_output_with_args( envs: Option>, need_http_server: bool, ) -> (String, String) { - let mut deno_process_builder = deno_cmd(); - deno_process_builder + let mut deno_process_builder = deno_cmd() .args(args) - .current_dir(&testdata_path()) + .current_dir(testdata_path()) .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()); + .piped_output(); if let Some(envs) = envs { - deno_process_builder.envs(envs); + deno_process_builder = deno_process_builder.envs(envs); } let _http_guard = if need_http_server { Some(http_server()) @@ -2142,120 +2139,6 @@ pub fn new_deno_dir() -> TempDir { TempDir::new() } -/// Because we need to keep the [`TempDir`] alive for the entire run of this command, -/// we have to effectively reproduce the entire builder-pattern object for [`Command`]. -pub struct DenoCmd { - _deno_dir: TempDir, - cmd: Command, -} - -impl DenoCmd { - pub fn args(&mut self, args: I) -> &mut Self - where - I: IntoIterator, - S: AsRef, - { - self.cmd.args(args); - self - } - - pub fn arg(&mut self, arg: S) -> &mut Self - where - S: AsRef, - { - self.cmd.arg(arg); - self - } - - pub fn envs(&mut self, vars: I) -> &mut Self - where - I: IntoIterator, - K: AsRef, - V: AsRef, - { - self.cmd.envs(vars); - self - } - - pub fn env(&mut self, key: K, val: V) -> &mut Self - where - K: AsRef, - V: AsRef, - { - self.cmd.env(key, val); - self - } - - pub fn env_remove(&mut self, key: K) -> &mut Self - where - K: AsRef, - { - self.cmd.env_remove(key); - self - } - - pub fn stdin>(&mut self, cfg: T) -> &mut Self { - self.cmd.stdin(cfg); - self - } - - pub fn stdout>(&mut self, cfg: T) -> &mut Self { - self.cmd.stdout(cfg); - self - } - - pub fn stderr>(&mut self, cfg: T) -> &mut Self { - self.cmd.stderr(cfg); - self - } - - pub fn current_dir>(&mut self, dir: P) -> &mut Self { - self.cmd.current_dir(dir); - self - } - - pub fn output(&mut self) -> Result { - self.cmd.output() - } - - pub fn status(&mut self) -> Result { - self.cmd.status() - } - - pub fn spawn(&mut self) -> Result { - Ok(DenoChild { - _deno_dir: self._deno_dir.clone(), - child: self.cmd.spawn()?, - }) - } -} - -/// We need to keep the [`TempDir`] around until the child has finished executing, so -/// this acts as a RAII guard. -pub struct DenoChild { - _deno_dir: TempDir, - child: Child, -} - -impl Deref for DenoChild { - type Target = Child; - fn deref(&self) -> &Child { - &self.child - } -} - -impl DerefMut for DenoChild { - fn deref_mut(&mut self) -> &mut Child { - &mut self.child - } -} - -impl DenoChild { - pub fn wait_with_output(self) -> Result { - self.child.wait_with_output() - } -} - pub fn deno_cmd() -> DenoCmd { let deno_dir = new_deno_dir(); deno_cmd_with_deno_dir(&deno_dir) @@ -2267,10 +2150,7 @@ pub fn deno_cmd_with_deno_dir(deno_dir: &TempDir) -> DenoCmd { let mut cmd = Command::new(exe_path); cmd.env("DENO_DIR", deno_dir.path()); cmd.env("NPM_CONFIG_REGISTRY", npm_registry_unset_url()); - DenoCmd { - _deno_dir: deno_dir.clone(), - cmd, - } + DenoCmd::new_raw(deno_dir.clone(), cmd) } pub fn run_powershell_script_file(