cli run tests passing on macos

This commit is contained in:
Luke Boswell 2024-08-16 17:59:53 +10:00
parent c3785a2def
commit 767ec7af84
No known key found for this signature in database
GPG key ID: F6DB3C9DB47377B0
9 changed files with 92 additions and 353 deletions

View file

@ -146,7 +146,7 @@ pub fn build_app() -> Command {
.action(ArgAction::SetTrue) .action(ArgAction::SetTrue)
.required(false); .required(false);
let flag_supress_build_host_warning = Arg::new(FLAG_SUPPRESS_BUILD_HOST_WARNING) let flag_suppress_build_host_warning = Arg::new(FLAG_SUPPRESS_BUILD_HOST_WARNING)
.long(FLAG_SUPPRESS_BUILD_HOST_WARNING) .long(FLAG_SUPPRESS_BUILD_HOST_WARNING)
.help("WARNING: platforms are responsible for building hosts, this flag will be removed when internal test platforms have a build script") .help("WARNING: platforms are responsible for building hosts, this flag will be removed when internal test platforms have a build script")
.action(ArgAction::SetTrue) .action(ArgAction::SetTrue)
@ -206,7 +206,7 @@ pub fn build_app() -> Command {
.arg(flag_time.clone()) .arg(flag_time.clone())
.arg(flag_linker.clone()) .arg(flag_linker.clone())
.arg(flag_build_host.clone()) .arg(flag_build_host.clone())
.arg(flag_supress_build_host_warning.clone()) .arg(flag_suppress_build_host_warning.clone())
.arg(flag_fuzz.clone()) .arg(flag_fuzz.clone())
.arg(flag_wasm_stack_size_kb) .arg(flag_wasm_stack_size_kb)
.arg( .arg(
@ -259,7 +259,7 @@ pub fn build_app() -> Command {
.arg(flag_time.clone()) .arg(flag_time.clone())
.arg(flag_linker.clone()) .arg(flag_linker.clone())
.arg(flag_build_host.clone()) .arg(flag_build_host.clone())
.arg(flag_supress_build_host_warning.clone()) .arg(flag_suppress_build_host_warning.clone())
.arg(flag_fuzz.clone()) .arg(flag_fuzz.clone())
.arg( .arg(
Arg::new(FLAG_VERBOSE) Arg::new(FLAG_VERBOSE)
@ -291,7 +291,7 @@ pub fn build_app() -> Command {
.arg(flag_time.clone()) .arg(flag_time.clone())
.arg(flag_linker.clone()) .arg(flag_linker.clone())
.arg(flag_build_host.clone()) .arg(flag_build_host.clone())
.arg(flag_supress_build_host_warning.clone()) .arg(flag_suppress_build_host_warning.clone())
.arg(flag_fuzz.clone()) .arg(flag_fuzz.clone())
.arg(roc_file_to_run.clone()) .arg(roc_file_to_run.clone())
.arg(args_for_app.clone().last(true)) .arg(args_for_app.clone().last(true))
@ -307,7 +307,7 @@ pub fn build_app() -> Command {
.arg(flag_time.clone()) .arg(flag_time.clone())
.arg(flag_linker.clone()) .arg(flag_linker.clone())
.arg(flag_build_host.clone()) .arg(flag_build_host.clone())
.arg(flag_supress_build_host_warning.clone()) .arg(flag_suppress_build_host_warning.clone())
.arg(flag_fuzz.clone()) .arg(flag_fuzz.clone())
.arg(roc_file_to_run.clone()) .arg(roc_file_to_run.clone())
.arg(args_for_app.clone().last(true)) .arg(args_for_app.clone().last(true))
@ -443,7 +443,7 @@ pub fn build_app() -> Command {
.arg(flag_time) .arg(flag_time)
.arg(flag_linker) .arg(flag_linker)
.arg(flag_build_host) .arg(flag_build_host)
.arg(flag_supress_build_host_warning) .arg(flag_suppress_build_host_warning)
.arg(flag_fuzz) .arg(flag_fuzz)
.arg(roc_file_to_run) .arg(roc_file_to_run)
.arg(args_for_app.trailing_var_arg(true)) .arg(args_for_app.trailing_var_arg(true))
@ -859,7 +859,7 @@ pub fn build(
// All hosts should be prebuilt, this flag keeps the rebuilding behvaiour // All hosts should be prebuilt, this flag keeps the rebuilding behvaiour
// as required for internal tests // as required for internal tests
let build_host = matches.get_flag(FLAG_BUILD_HOST); let build_host = matches.get_flag(FLAG_BUILD_HOST);
let supress_build_host_warning = matches.get_flag(FLAG_SUPPRESS_BUILD_HOST_WARNING); let suppress_build_host_warning = matches.get_flag(FLAG_SUPPRESS_BUILD_HOST_WARNING);
let fuzz = matches.get_flag(FLAG_FUZZ); let fuzz = matches.get_flag(FLAG_FUZZ);
if fuzz && !matches!(code_gen_backend, CodeGenBackend::Llvm(_)) { if fuzz && !matches!(code_gen_backend, CodeGenBackend::Llvm(_)) {
@ -896,7 +896,7 @@ pub fn build(
link_type, link_type,
linking_strategy, linking_strategy,
build_host, build_host,
supress_build_host_warning, suppress_build_host_warning,
wasm_dev_stack_bytes, wasm_dev_stack_bytes,
roc_cache_dir, roc_cache_dir,
load_config, load_config,

View file

@ -1,6 +1,6 @@
app [main] { app [main] {
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br", cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br",
parser: "https://github.com/lukewilliamboswell/roc-parser/releases/download/0.5.2/9VrPjwfQQ1QeSL3CfmWr2Pr9DESdDIXy97pwpuq84Ck.tar.br", parser: "https://github.com/lukewilliamboswell/roc-parser/releases/download/0.7.1/MvLlME9RxOBjl0QCxyn3LIaoG9pSlaNxCa-t3BfbPNc.tar.br",
} }
import cli.Stdout import cli.Stdout

View file

@ -15,7 +15,11 @@ mod cli_run {
use roc_cli::{CMD_BUILD, CMD_CHECK, CMD_FORMAT, CMD_RUN, CMD_TEST}; use roc_cli::{CMD_BUILD, CMD_CHECK, CMD_FORMAT, CMD_RUN, CMD_TEST};
use roc_reporting::report::strip_colors; use roc_reporting::report::strip_colors;
use roc_test_utils::assert_multiline_str_eq; use roc_test_utils::assert_multiline_str_eq;
use serial_test::serial;
// TODO -- we may need to keep this to prevent race conditions...
// but we shouldn't be building a host more than once now, so it should be all good
//
// use serial_test::serial;
use std::path::Path; use std::path::Path;
#[cfg(all(unix, not(target_os = "macos")))] #[cfg(all(unix, not(target_os = "macos")))]
@ -36,22 +40,7 @@ mod cli_run {
No, No,
} }
impl UseValgrind {
fn and_is_supported(&self) -> bool {
matches!(self, UseValgrind::Yes) && ALLOW_VALGRIND
}
}
#[derive(Debug, Clone, Copy)]
enum TestCliCommands {
// Many,
Run,
// Test,
// Dev,
}
const OPTIMIZE_FLAG: &str = concatcp!("--", roc_cli::FLAG_OPTIMIZE); const OPTIMIZE_FLAG: &str = concatcp!("--", roc_cli::FLAG_OPTIMIZE);
// const LINKER_FLAG: &str = concatcp!("--", roc_cli::FLAG_LINKER);
const BUILD_HOST_FLAG: &str = concatcp!("--", roc_cli::FLAG_BUILD_HOST); const BUILD_HOST_FLAG: &str = concatcp!("--", roc_cli::FLAG_BUILD_HOST);
const SUPPRESS_BUILD_HOST_WARNING_FLAG: &str = const SUPPRESS_BUILD_HOST_WARNING_FLAG: &str =
concatcp!("--", roc_cli::FLAG_SUPPRESS_BUILD_HOST_WARNING); concatcp!("--", roc_cli::FLAG_SUPPRESS_BUILD_HOST_WARNING);
@ -59,16 +48,10 @@ mod cli_run {
#[allow(dead_code)] #[allow(dead_code)]
const TARGET_FLAG: &str = concatcp!("--", roc_cli::FLAG_TARGET); const TARGET_FLAG: &str = concatcp!("--", roc_cli::FLAG_TARGET);
// #[derive(Debug, Clone, Copy)]
// enum CliMode {
// Roc, // buildAndRunIfNoErrors
// RocBuild, // buildOnly
// RocRun, // buildAndRun
// RocTest,
// RocDev,
// }
// TODO confirm we we need this // TODO confirm we we need this
// were we testing using Legacy linker anywhere? probably will get
// to this when I start fixing things on linux
//
// #[cfg(all(target_os = "linux", target_arch = "x86_64"))] // #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
// const TEST_LEGACY_LINKER: bool = true; // const TEST_LEGACY_LINKER: bool = true;
@ -110,84 +93,8 @@ mod cli_run {
assert_eq!(out.status.success(), expects_success_exit_code); assert_eq!(out.status.success(), expects_success_exit_code);
} }
// #[allow(clippy::too_many_arguments)] // TODO -- confirm we are using Valgrind correctly
// fn check_output_with_stdin( // leaving this here for now as a reminder
// file: &Path,
// stdin: &[&str],
// flags: &[&str],
// roc_app_args: &[String],
// extra_env: &[(&str, &str)],
// expected_ending: &str,
// use_valgrind: UseValgrind,
// test_cli_commands: TestCliCommands,
// ) {
// todo!()
// }
// #[allow(clippy::too_many_arguments)]
// fn get_output_with_stdin(
// file: &Path,
// stdin: Vec<&'static str>,
// flags: &[&str],
// roc_app_args: &[String],
// extra_env: &[(&str, &str)],
// use_valgrind: UseValgrind,
// test_cli_commands: TestCliCommands,
// ) -> Vec<(CliMode, Out)> {
// let mut output = Vec::new();
// // valgrind does not yet support avx512 instructions, see #1963.
// // we can't enable this only when testing with valgrind because of host re-use between tests
// #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
// if is_x86_feature_detected!("avx512f") {
// std::env::set_var("NO_AVX512", "1");
// }
// // TODO: expects don't currently work on windows
// let cli_commands = if cfg!(windows) {
// match test_cli_commands {
// TestCliCommands::Many => vec![CliMode::RocBuild, CliMode::RocRun],
// TestCliCommands::Run => vec![CliMode::RocRun],
// TestCliCommands::Test => vec![],
// TestCliCommands::Dev => vec![],
// }
// } else {
// match test_cli_commands {
// TestCliCommands::Many => vec![CliMode::RocBuild, CliMode::RocRun, CliMode::Roc],
// TestCliCommands::Run => vec![CliMode::Roc],
// TestCliCommands::Test => vec![CliMode::RocTest],
// TestCliCommands::Dev => vec![CliMode::RocDev],
// }
// };
// for cli_mode in cli_commands.into_iter() {
// let flags = {
// let mut vec = flags.to_vec();
// vec.push("--build-host");
// // max-threads segfaults on windows right now
// if !cfg!(windows) {
// vec.push("--max-threads=1");
// }
// vec.into_iter()
// };
// let cmd_output = match cli_mode {
// CliMode::RocBuild => {
// let runner = Run::new_roc()
// .arg(file.to_str().unwrap())
// .arg(CMD_BUILD)
// .add_args(flags.clone());
// let out = runner.clone().run();
// out.assert_clean_success();
// output.push((cli_mode, out));
// let file_ext = if cfg!(windows) { "exe " } else { "" };
// if matches!(use_valgrind, UseValgrind::Yes) && ALLOW_VALGRIND { // if matches!(use_valgrind, UseValgrind::Yes) && ALLOW_VALGRIND {
// let out = runner.run_with_valgrind(); // let out = runner.run_with_valgrind();
@ -234,155 +141,8 @@ mod cli_run {
// } // }
// output.push((cli_mode, out)); // output.push((cli_mode, out));
// } else {
// let mut runner = Run::new_roc()
// .arg(file.with_extension(file_ext).to_str().unwrap())
// .add_args(roc_app_args)
// .with_stdin_vals(stdin.clone());
// for env in extra_env {
// // this is funky, fix me
// runner.with_env([*env]);
// }
// let out = runner.run();
// out.assert_clean_success();
// output.push((cli_mode, out));
// }
// }
// CliMode::Roc => {
// let mut runner = Run::new_roc()
// .arg(file)
// .add_args(flags.clone())
// .add_args(roc_app_args)
// .with_stdin_vals(stdin.clone());
// for env in extra_env {
// // this is funky, fix me
// runner.with_env([*env]);
// }
// let out = runner.run();
// out.assert_clean_success();
// output.push((cli_mode, out));
// }
// CliMode::RocRun => {
// let mut runner = Run::new_roc()
// .arg(CMD_RUN)
// .add_args(flags.clone())
// .add_args(roc_app_args)
// .arg(file)
// .with_stdin_vals(stdin.clone());
// for env in extra_env {
// // this is funky, fix me
// runner.with_env([*env]);
// }
// let out = runner.run();
// out.assert_clean_success();
// output.push((cli_mode, out));
// }
// CliMode::RocTest => {
// // here failure is what we expect
// let mut runner = Run::new_roc()
// .arg(CMD_TEST)
// .add_args(flags.clone())
// .add_args(roc_app_args)
// .arg(file)
// .with_stdin_vals(stdin.clone());
// for env in extra_env {
// // this is funky, fix me
// runner.with_env([*env]);
// }
// let out = runner.run();
// out.assert_clean_success();
// output.push((cli_mode, out));
// }
// CliMode::RocDev => {
// // here failure is what we expect
// let mut runner = Run::new_roc()
// .arg(file)
// .add_args(iter::once(CMD_DEV).chain(flags.clone()))
// .add_args(roc_app_args)
// .with_stdin_vals(stdin.clone());
// for env in extra_env {
// // this is funky, fix me
// runner.with_env([*env]);
// }
// let out = runner.run();
// out.assert_clean_success();
// output.push((cli_mode, out));
// }
// };
// }
// output
// }
// /// Run `roc test` to execute `expect`s, perhaps on a library rather than an application
// /// will use valgrind if it's supported
// fn test_roc_expect(file_path: &Path, flags: &[&str], expected_ending: &str) {
// let runner = Run::new_roc().arg(CMD_TEST).arg(file_path).add_args(flags);
// let use_valgrind = UseValgrind::Yes;
// if use_valgrind.and_is_supported() {
// let out = runner.run_with_valgrind();
// out.assert_stdout_and_stderr_ends_with(expected_ending);
// } else {
// let out = runner.run();
// out.assert_stdout_and_stderr_ends_with(expected_ending);
// }
// }
#[allow(clippy::too_many_arguments)]
fn test_roc_app(
file_path: &Path,
stdin: Vec<&'static str>,
args: &[&str],
_extra_env: Vec<(&str, &str)>,
expected_ending: &str,
use_valgrind: UseValgrind,
_test_cli_commands: TestCliCommands,
) {
let runner = Run::new_roc()
.arg(CMD_RUN)
.arg(BUILD_HOST_FLAG)
.arg(file_path)
.add_args(args)
// TODO we should pipe this in here... just need to fix lifetimes
// .with_env(extra_env)
.with_stdin_vals(stdin);
if use_valgrind.and_is_supported() {
let out = runner.run_with_valgrind();
out.assert_clean_success();
out.assert_stdout_and_stderr_ends_with(expected_ending);
} else {
let out = runner.run();
out.assert_clean_success();
out.assert_stdout_and_stderr_ends_with(expected_ending);
}
}
#[test] #[test]
#[serial(zig_platform_parser_package_basic_cli_url)]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
fn hello_world() { fn hello_world() {
let expected_ending = "Hello, World!\n🔨 Building host ...\n"; let expected_ending = "Hello, World!\n🔨 Building host ...\n";
@ -403,16 +163,11 @@ mod cli_run {
} }
} }
#[cfg(windows)]
const LINE_ENDING: &str = "\r\n";
#[cfg(not(windows))]
const LINE_ENDING: &str = "\n";
#[test] #[test]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
// uses C platform // uses C platform
fn platform_switching_main() { fn platform_switching_main() {
let expected_ending = &("Which platform am I running on now?".to_string() + LINE_ENDING); let expected_ending = "Which platform am I running on now?\n🔨 Building host ...\n";
let runner = Run::new_roc() let runner = Run::new_roc()
.arg(CMD_RUN) .arg(CMD_RUN)
.arg(BUILD_HOST_FLAG) .arg(BUILD_HOST_FLAG)
@ -432,12 +187,13 @@ mod cli_run {
// We exclude the C platforming switching example // We exclude the C platforming switching example
// because the main platform switching example runs the c platform. // because the main platform switching example runs the c platform.
// If we don't, a race condition leads to test flakiness. // If we don't, a race condition leads to test flakiness if we attempt
// to build the host from two different tests running concurrently.
#[test] #[test]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
fn platform_switching_rust() { fn platform_switching_rust() {
let expected_ending = "Roc <3 Rust!\n"; let expected_ending = "Roc <3 Rust!\n🔨 Building host ...\n";
let runner = Run::new_roc() let runner = Run::new_roc()
.arg(CMD_RUN) .arg(CMD_RUN)
.arg(BUILD_HOST_FLAG) .arg(BUILD_HOST_FLAG)
@ -455,12 +211,10 @@ mod cli_run {
} }
} }
// zig_platform_parser_package_basic_cli_url use to be split up but then things could get stuck
#[test] #[test]
#[serial(zig_platform_parser_package_basic_cli_url)]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
fn platform_switching_zig() { fn platform_switching_zig() {
let expected_ending = "Roc <3 Zig!\n"; let expected_ending = "Roc <3 Zig!\n🔨 Building host ...\n";
let runner = Run::new_roc() let runner = Run::new_roc()
.arg(CMD_RUN) .arg(CMD_RUN)
.arg(BUILD_HOST_FLAG) .arg(BUILD_HOST_FLAG)
@ -592,7 +346,7 @@ mod cli_run {
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
/// this tests that a platform can correctly import a package /// this tests that a platform can correctly import a package
fn platform_requires_pkg() { fn platform_requires_pkg() {
let expected_ending = "from app from package"; let expected_ending = "from app from package🔨 Building host ...\n";
let runner = Run::new_roc() let runner = Run::new_roc()
.arg(CMD_RUN) .arg(CMD_RUN)
.arg(BUILD_HOST_FLAG) .arg(BUILD_HOST_FLAG)
@ -731,7 +485,6 @@ mod cli_run {
#[test] #[test]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
#[serial(cli_platform)]
fn cli_countdown_check() { fn cli_countdown_check() {
Run::new_roc() Run::new_roc()
.add_args([ .add_args([
@ -746,7 +499,6 @@ mod cli_run {
#[test] #[test]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
#[serial(cli_platform)]
fn cli_echo_check() { fn cli_echo_check() {
Run::new_roc() Run::new_roc()
.add_args([ .add_args([
@ -761,7 +513,6 @@ mod cli_run {
#[test] #[test]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
#[serial(cli_platform)]
fn cli_file_check() { fn cli_file_check() {
Run::new_roc() Run::new_roc()
.add_args([ .add_args([
@ -777,7 +528,6 @@ mod cli_run {
#[test] #[test]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
#[serial(cli_platform)]
fn cli_form_check() { fn cli_form_check() {
Run::new_roc() Run::new_roc()
.add_args([ .add_args([
@ -793,7 +543,6 @@ mod cli_run {
#[test] #[test]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
#[serial(cli_platform)]
fn cli_http_get_check() { fn cli_http_get_check() {
Run::new_roc() Run::new_roc()
.add_args([ .add_args([
@ -930,7 +679,6 @@ mod cli_run {
} }
#[test] #[test]
#[serial(cli_platform)]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
fn combine_tasks_with_record_builder() { fn combine_tasks_with_record_builder() {
let expected_ending = "For multiple tasks: {a: 123, b: \"abc\", c: [123]}\n"; let expected_ending = "For multiple tasks: {a: 123, b: \"abc\", c: [123]}\n";
@ -945,7 +693,6 @@ mod cli_run {
} }
#[test] #[test]
#[serial(cli_platform)]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
fn parse_args_with_record_builder() { fn parse_args_with_record_builder() {
let expected_ending = "Success: {count: 5, doubled: 14, file: \"file.txt\"}\n"; let expected_ending = "Success: {count: 5, doubled: 14, file: \"file.txt\"}\n";
@ -992,14 +739,11 @@ mod cli_run {
} }
#[test] #[test]
#[serial(zig_platform_parser_package_basic_cli_url)]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
fn parse_movies_csv() { fn parse_movies_csv() {
let expected_ending = "2 movies were found:\n\nThe movie 'Airplane!' was released in 1980 and stars Robert Hays and Julie Hagerty\nThe movie 'Caddyshack' was released in 1980 and stars Chevy Chase, Rodney Dangerfield, Ted Knight, Michael O'Keefe and Bill Murray\n\nParse success!\n\n"; let expected_ending = "2 movies were found:\n\nThe movie 'Airplane!' was released in 1980 and stars Robert Hays and Julie Hagerty\nThe movie 'Caddyshack' was released in 1980 and stars Chevy Chase, Rodney Dangerfield, Ted Knight, Michael O'Keefe and Bill Murray\n\nParse success!\n\n";
let runner = Run::new_roc() let runner = Run::new_roc()
.arg(CMD_RUN) .arg(CMD_RUN)
.arg(BUILD_HOST_FLAG)
.arg(SUPPRESS_BUILD_HOST_WARNING_FLAG)
.arg(file_from_root("crates/cli/tests/basic-cli", "parser-movies-csv.roc").as_path()); .arg(file_from_root("crates/cli/tests/basic-cli", "parser-movies-csv.roc").as_path());
let out = runner.run(); let out = runner.run();
@ -1008,15 +752,10 @@ mod cli_run {
} }
#[test] #[test]
#[serial(zig_platform_parser_package_basic_cli_url)]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
fn parse_letter_counts() { fn parse_letter_counts() {
let expected_ending = "I counted 7 letter A's!\n"; let expected_ending = "I counted 7 letter A's!\n";
let runner = Run::new_roc() let runner = Run::new_roc().arg(CMD_RUN).arg(
.arg(CMD_RUN)
.arg(BUILD_HOST_FLAG)
.arg(SUPPRESS_BUILD_HOST_WARNING_FLAG)
.arg(
file_from_root("crates/cli/tests/basic-cli", "parser-letter-counts.roc").as_path(), file_from_root("crates/cli/tests/basic-cli", "parser-letter-counts.roc").as_path(),
); );
@ -1032,8 +771,7 @@ mod cli_run {
"#; "#;
let runner = Run::new_roc() let runner = Run::new_roc()
.arg(CMD_RUN) .arg(CMD_RUN)
.arg(BUILD_HOST_FLAG) // uses basic-cli release
.arg(SUPPRESS_BUILD_HOST_WARNING_FLAG)
.arg(file_from_root("examples", "inspect-logging.roc").as_path()); .arg(file_from_root("examples", "inspect-logging.roc").as_path());
if ALLOW_VALGRIND { if ALLOW_VALGRIND {
@ -1348,7 +1086,7 @@ mod cli_run {
This expectation failed: This expectation failed:
9 expect a == 2 6 expect a == 2
^^^^^^ ^^^^^^
When it failed, these variables had these values: When it failed, these variables had these values:
@ -1360,7 +1098,7 @@ mod cli_run {
This expectation failed: This expectation failed:
10 expect a == 3 7 expect a == 3
^^^^^^ ^^^^^^
When it failed, these variables had these values: When it failed, these variables had these values:
@ -1372,11 +1110,11 @@ mod cli_run {
This expectation failed: This expectation failed:
14> expect 11> expect
15> a = makeA 12> a = makeA
16> b = 2i64 13> b = 2i64
17> 14>
18> a == b 15> a == b
When it failed, these variables had these values: When it failed, these variables had these values:
@ -1396,11 +1134,11 @@ mod cli_run {
if ALLOW_VALGRIND { if ALLOW_VALGRIND {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_clean_success(); // out.assert_clean_success();
out.assert_stdout_and_stderr_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} else { } else {
let out = runner.run(); let out = runner.run();
out.assert_clean_success(); // out.assert_clean_success();
out.assert_stdout_and_stderr_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1410,7 +1148,8 @@ mod cli_run {
// this is for testing the benchmarks, to perform proper benchmarks see crates/cli/benches/README.md // this is for testing the benchmarks, to perform proper benchmarks see crates/cli/benches/README.md
mod test_benchmarks { mod test_benchmarks {
use super::{ use super::{
UseValgrind, BUILD_HOST_FLAG, OPTIMIZE_FLAG, SUPPRESS_BUILD_HOST_WARNING_FLAG, UseValgrind, ALLOW_VALGRIND, BUILD_HOST_FLAG, OPTIMIZE_FLAG,
SUPPRESS_BUILD_HOST_WARNING_FLAG,
}; };
use cli_utils::helpers::{file_from_root, Run}; use cli_utils::helpers::{file_from_root, Run};
use roc_cli::CMD_BUILD; use roc_cli::CMD_BUILD;
@ -1453,7 +1192,7 @@ mod cli_run {
.arg(file_from_root(dir_name, roc_filename).as_path()) .arg(file_from_root(dir_name, roc_filename).as_path())
.with_stdin_vals(stdin); .with_stdin_vals(stdin);
if use_valgrind.and_is_supported() { if matches!(use_valgrind, UseValgrind::Yes) && ALLOW_VALGRIND {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_clean_success(); out.assert_clean_success();
out.assert_stdout_and_stderr_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
@ -1689,17 +1428,14 @@ mod cli_run {
#[test] #[test]
fn known_type_error() { fn known_type_error() {
check_compile_error( let expected_ending = indoc!(
&known_bad_file("TypeError.roc"),
&[],
indoc!(
r#" r#"
TYPE MISMATCH in tests/known_bad/TypeError.roc TYPE MISMATCH in tests/known_bad/TypeError.roc
Something is off with the body of the main definition: Something is off with the body of the main definition:
5 main : Str -> Task {} [] 5 main : Str -> Task {} []
6 main = /_ -> 6 main = \_ ->
7 "this is a string, not a Task {} [] function like the platform expects." 7 "this is a string, not a Task {} [] function like the platform expects."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -1716,9 +1452,18 @@ mod cli_run {
1 error and 0 warnings found in <ignored for test> ms."# 1 error and 0 warning found in <ignored for test> ms
), "#
); );
Run::new_roc()
.arg(CMD_CHECK)
.arg(file_from_root(
"crates/cli/tests/known_bad",
"TypeError.roc",
))
.run()
.assert_stdout_and_stderr_ends_with(expected_ending);
} }
#[test] #[test]

View file

@ -1,4 +1,4 @@
app [main] { pf: platform "../../../../examples/cli/false-interpreter/platform/main.roc" } app [main] { pf: platform "../false-interpreter/platform/main.roc" }
import pf.Task exposing [Task] import pf.Task exposing [Task]

View file

@ -107,23 +107,15 @@ const Unit = extern struct {};
pub fn main() u8 { pub fn main() u8 {
const stdout = std.io.getStdOut().writer(); const stdout = std.io.getStdOut().writer();
const stderr = std.io.getStdErr().writer();
var timer = std.time.Timer.start() catch unreachable;
// actually call roc to populate the callresult // actually call roc to populate the callresult
var callresult = RocStr.empty(); var callresult = RocStr.empty();
roc__mainForHost_1_exposed_generic(&callresult); roc__mainForHost_1_exposed_generic(&callresult);
const nanos = timer.read();
const seconds = (@as(f64, @floatFromInt(nanos)) / 1_000_000_000.0);
// stdout the result // stdout the result
stdout.print("{s}", .{callresult.asSlice()}) catch unreachable; stdout.print("{s}", .{callresult.asSlice()}) catch unreachable;
callresult.decref(); callresult.decref();
stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable;
return 0; return 0;
} }

View file

@ -75,9 +75,12 @@ impl Out {
/// Normalise the output for comparison in tests by replacing with a placeholder /// Normalise the output for comparison in tests by replacing with a placeholder
fn normalize_for_tests(input: &String) -> String { fn normalize_for_tests(input: &String) -> String {
// normalise from windows line endings to unix line endings
let without_clrf = input.replace("\r\n", "\n");
// remove ANSI color codes // remove ANSI color codes
let ansi_regex = Regex::new(r"\x1b\[[0-9;]*[mGKH]").expect("Invalid ANSI regex pattern"); let ansi_regex = Regex::new(r"\x1b\[[0-9;]*[mGKH]").expect("Invalid ANSI regex pattern");
let without_ansi = ansi_regex.replace_all(input, ""); let without_ansi = ansi_regex.replace_all(without_clrf.as_str(), "");
// replace timings with a placeholder // replace timings with a placeholder
let regex = Regex::new(r" in (\d+) ms\.").expect("Invalid regex pattern"); let regex = Regex::new(r" in (\d+) ms\.").expect("Invalid regex pattern");
@ -88,8 +91,15 @@ impl Out {
let filepath_regex = let filepath_regex =
Regex::new(r"\[([^:]+):(\d+)\]").expect("Invalid filepath regex pattern"); Regex::new(r"\[([^:]+):(\d+)\]").expect("Invalid filepath regex pattern");
let filepath_replacement = "[<ignored for tests>:$2]"; let filepath_replacement = "[<ignored for tests>:$2]";
filepath_regex let without_filepaths = filepath_regex.replace_all(&without_timings, filepath_replacement);
.replace_all(&without_timings, filepath_replacement)
// replace error summary timings
let error_summary_regex =
Regex::new(r"(\d+) error(?:s)? and (\d+) warning(?:s)? found in \d+ ms")
.expect("Invalid error summary regex pattern");
let error_summary_replacement = "$1 error and $2 warning found in <ignored for test> ms";
error_summary_regex
.replace_all(&without_filepaths, error_summary_replacement)
.to_string() .to_string()
} }

View file

@ -714,7 +714,7 @@ pub fn build_file<'a>(
link_type: LinkType, link_type: LinkType,
linking_strategy: LinkingStrategy, linking_strategy: LinkingStrategy,
build_host: bool, build_host: bool,
supress_build_host_warning: bool, suppress_build_host_warning: bool,
wasm_dev_stack_bytes: Option<u32>, wasm_dev_stack_bytes: Option<u32>,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
load_config: LoadConfig, load_config: LoadConfig,
@ -740,7 +740,7 @@ pub fn build_file<'a>(
link_type, link_type,
linking_strategy, linking_strategy,
build_host, build_host,
supress_build_host_warning, suppress_build_host_warning,
wasm_dev_stack_bytes, wasm_dev_stack_bytes,
loaded, loaded,
compilation_start, compilation_start,
@ -813,7 +813,7 @@ fn build_loaded_file<'a>(
link_type: LinkType, link_type: LinkType,
linking_strategy: LinkingStrategy, linking_strategy: LinkingStrategy,
build_host_requested: bool, build_host_requested: bool,
supress_build_host_warning: bool, suppress_build_host_warning: bool,
wasm_dev_stack_bytes: Option<u32>, wasm_dev_stack_bytes: Option<u32>,
loaded: roc_load::MonomorphizedModule<'a>, loaded: roc_load::MonomorphizedModule<'a>,
compilation_start: Instant, compilation_start: Instant,
@ -859,7 +859,7 @@ fn build_loaded_file<'a>(
// The following 3 cases we currently support for host rebuilding. Emit a deprecation // The following 3 cases we currently support for host rebuilding. Emit a deprecation
// warning and rebuild the host. // warning and rebuild the host.
(Ok(existing_legacy_host), _, true, LinkType::Executable) => { (Ok(existing_legacy_host), _, true, LinkType::Executable) => {
if !supress_build_host_warning { if !suppress_build_host_warning {
report_rebuilding_existing_host(&existing_legacy_host.to_string_lossy()); report_rebuilding_existing_host(&existing_legacy_host.to_string_lossy());
} }
build_and_preprocess_host( build_and_preprocess_host(
@ -880,7 +880,7 @@ fn build_loaded_file<'a>(
true, true,
LinkType::Executable, LinkType::Executable,
) => { ) => {
if !supress_build_host_warning { if !suppress_build_host_warning {
report_rebuilding_existing_host(&preprocessed_host.to_string_lossy()); report_rebuilding_existing_host(&preprocessed_host.to_string_lossy());
} }
build_and_preprocess_host( build_and_preprocess_host(
@ -894,7 +894,7 @@ fn build_loaded_file<'a>(
) )
} }
(Err(legacy_paths), Err(surgical_paths), true, LinkType::Executable) => { (Err(legacy_paths), Err(surgical_paths), true, LinkType::Executable) => {
if !supress_build_host_warning { if !suppress_build_host_warning {
report_rebuilding_missing_host(&format!("{legacy_paths}\n {surgical_paths}")); report_rebuilding_missing_host(&format!("{legacy_paths}\n {surgical_paths}"));
} }
build_and_preprocess_host( build_and_preprocess_host(
@ -1435,7 +1435,7 @@ pub fn build_str_test<'a>(
.map_err(|e| BuildFileError::from_mono_error(e, compilation_start))?; .map_err(|e| BuildFileError::from_mono_error(e, compilation_start))?;
// we are in a test, so we don't need to provide a warning about rebuilding the host // we are in a test, so we don't need to provide a warning about rebuilding the host
let supress_build_host_warning = true; let suppress_build_host_warning = true;
build_loaded_file( build_loaded_file(
arena, arena,
@ -1446,7 +1446,7 @@ pub fn build_str_test<'a>(
link_type, link_type,
linking_strategy, linking_strategy,
build_host_requested, build_host_requested,
supress_build_host_warning, suppress_build_host_warning,
wasm_dev_stack_bytes, wasm_dev_stack_bytes,
loaded, loaded,
compilation_start, compilation_start,

View file

@ -80,7 +80,7 @@ pub fn generate(
// TODO confirm these are the correct parameters to pass down. // TODO confirm these are the correct parameters to pass down.
// are we building a host here in glue generation? // are we building a host here in glue generation?
let build_host = true; let build_host = true;
let supress_build_host_warning = true; let suppress_build_host_warning = true;
let res_binary_path = match tempdir_res { let res_binary_path = match tempdir_res {
Ok(dylib_dir) => build_file( Ok(dylib_dir) => build_file(
@ -92,7 +92,7 @@ pub fn generate(
link_type, link_type,
linking_strategy, linking_strategy,
build_host, build_host,
supress_build_host_warning, suppress_build_host_warning,
None, None,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
load_config, load_config,

View file

@ -108,23 +108,15 @@ const Unit = extern struct {};
pub fn main() u8 { pub fn main() u8 {
const stdout = std.io.getStdOut().writer(); const stdout = std.io.getStdOut().writer();
const stderr = std.io.getStdErr().writer();
var timer = std.time.Timer.start() catch unreachable;
// actually call roc to populate the callresult // actually call roc to populate the callresult
var callresult = RocStr.empty(); var callresult = RocStr.empty();
roc__mainForHost_1_exposed_generic(&callresult); roc__mainForHost_1_exposed_generic(&callresult);
const nanos = timer.read();
const seconds = (@as(f64, @floatFromInt(nanos)) / 1_000_000_000.0);
// stdout the result // stdout the result
stdout.print("{s}", .{callresult.asSlice()}) catch unreachable; stdout.print("{s}", .{callresult.asSlice()}) catch unreachable;
callresult.decref(); callresult.decref();
stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable;
return 0; return 0;
} }