diff --git a/crates/cli/tests/cli_run.rs b/crates/cli/tests/cli_run.rs index f3e97456c0..cb54b40323 100644 --- a/crates/cli/tests/cli_run.rs +++ b/crates/cli/tests/cli_run.rs @@ -353,10 +353,10 @@ mod cli_run { if use_valgrind.and_is_supported() { let out = runner.run_with_valgrind(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -382,11 +382,11 @@ mod cli_run { if use_valgrind.and_is_supported() { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -394,7 +394,7 @@ mod cli_run { #[serial(zig_platform_parser_package_basic_cli_url)] #[cfg_attr(windows, ignore)] fn hello_world() { - let expected_ending = "Hello, World!\n"; + let expected_ending = "Hello, World!\nšŸ”Ø Building host ...\n"; let runner = Run::new_roc() .arg(CMD_RUN) .arg(BUILD_HOST_FLAG) @@ -404,11 +404,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -431,11 +431,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -456,11 +456,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -479,11 +479,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -499,102 +499,6 @@ mod cli_run { out.assert_clean_success(); } - #[ignore = "TODO move this to roc-lang/examples repository"] - #[test] - fn expects_dev_and_test() { - // these are in the same test function so we don't have to worry about race conditions - // on the building of the platform - - test_roc_app( - from_root("crates/cli/tests/expects", "expects.roc").as_path(), - vec![], - &[], - vec![], - indoc!( - r#" - ── EXPECT FAILED in tests/expects/expects.roc ────────────────────────────────── - - This expectation failed: - - 28│ expect words == [] - ^^^^^^^^^^^ - - When it failed, these variables had these values: - - words : List Str - words = ["this", "will", "for", "sure", "be", "a", "large", "string", "so", "when", "we", "split", "it", "it", "will", "use", "seamless", "slices", "which", "affect", "printing"] - - [:31] x = 42 - [:33] "Fjoer en ferdjer frieten oan dyn geve lea" = "Fjoer en ferdjer frieten oan dyn geve lea" - [:35] "this is line 24" = "this is line 24" - [:21] x = "abc" - [:21] x = 10 - [:21] x = (A (B C)) - Program finished! - "# - ), - UseValgrind::Yes, - TestCliCommands::Dev, - ); - - test_roc_app( - from_root("crates/cli/tests/expects", "expects.roc").as_path(), - vec![], - &[], - vec![], - indoc!( - r#" - ── EXPECT FAILED in tests/expects/expects.roc ────────────────────────────────── - - This expectation failed: - - 9│ expect a == 2 - ^^^^^^ - - When it failed, these variables had these values: - - a : Num * - a = 1 - - ── EXPECT FAILED in tests/expects/expects.roc ────────────────────────────────── - - This expectation failed: - - 10│ expect a == 3 - ^^^^^^ - - When it failed, these variables had these values: - - a : Num * - a = 1 - - ── EXPECT FAILED in tests/expects/expects.roc ────────────────────────────────── - - This expectation failed: - - 14│> expect - 15│> a = makeA - 16│> b = 2i64 - 17│> - 18│> a == b - - When it failed, these variables had these values: - - a : Int Signed64 - a = 1 - - b : I64 - b = 2 - - - 1 failed and 0 passed in ms. - "# - ), - UseValgrind::Yes, - TestCliCommands::Test, - ); - } - #[test] #[cfg_attr(windows, ignore)] fn test_module_imports_pkg_w_flag() { @@ -610,10 +514,10 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -643,10 +547,10 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -686,10 +590,10 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -706,7 +610,7 @@ mod cli_run { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } #[test] @@ -723,10 +627,10 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -751,10 +655,10 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -774,11 +678,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -796,11 +700,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1074,7 +978,7 @@ mod cli_run { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } #[test] @@ -1090,7 +994,7 @@ mod cli_run { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } #[test] @@ -1107,11 +1011,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1120,7 +1024,8 @@ mod cli_run { ALLOW_VALGRIND, BUILD_HOST_FLAG, OPTIMIZE_FLAG, SUPPRESS_BUILD_HOST_WARNING_FLAG, }; use cli_utils::helpers::{from_root, Run}; - use roc_cli::{CMD_BUILD, CMD_RUN}; + use indoc::indoc; + use roc_cli::{CMD_BUILD, CMD_DEV, CMD_RUN, CMD_TEST}; static BUILD_PLATFORM_HOST: std::sync::Once = std::sync::Once::new(); @@ -1136,7 +1041,6 @@ mod cli_run { from_root("crates/cli/tests/test-platform-simple-zig", "app.roc").as_path(), ) .run(); - dbg!(&out); out.assert_clean_success(); }); } @@ -1154,11 +1058,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1176,11 +1080,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1197,11 +1101,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1222,11 +1126,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1244,11 +1148,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1267,11 +1171,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1293,11 +1197,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1319,11 +1223,11 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1345,11 +1249,123 @@ mod cli_run { if ALLOW_VALGRIND { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); + } + } + + #[test] + fn expects_dev() { + build_platform_host(); + + let expected_ending = indoc!( + r#" + ── EXPECT FAILED in tests/expects/expects.roc ────────────────────────────────── + + This expectation failed: + + 25│ expect words == [] + ^^^^^^^^^^^ + + When it failed, these variables had these values: + + words : List Str + words = ["this", "will", "for", "sure", "be", "a", "large", "string", "so", "when", "we", "split", "it", "it", "will", "use", "seamless", "slices", "which", "affect", "printing"] + + Program finished! + + [:28] x = 42 + [:30] "Fjoer en ferdjer frieten oan dyn geve lea" = "Fjoer en ferdjer frieten oan dyn geve lea" + [:32] "this is line 24" = "this is line 24" + [:18] x = "abc" + [:18] x = 10 + [:18] x = (A (B C)) + "# + ); + let runner = cli_utils::helpers::Run::new_roc() + .arg(CMD_DEV) + .arg(from_root("crates/cli/tests/expects", "expects.roc").as_path()); + + dbg!(&runner); + + if ALLOW_VALGRIND { + 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] + fn expects_test() { + build_platform_host(); + + let expected_ending = indoc!( + r#" + ── EXPECT FAILED in tests/expects/expects.roc ────────────────────────────────── + + This expectation failed: + + 9│ expect a == 2 + ^^^^^^ + + When it failed, these variables had these values: + + a : Num * + a = 1 + + ── EXPECT FAILED in tests/expects/expects.roc ────────────────────────────────── + + This expectation failed: + + 10│ expect a == 3 + ^^^^^^ + + When it failed, these variables had these values: + + a : Num * + a = 1 + + ── EXPECT FAILED in tests/expects/expects.roc ────────────────────────────────── + + This expectation failed: + + 14│> expect + 15│> a = makeA + 16│> b = 2i64 + 17│> + 18│> a == b + + When it failed, these variables had these values: + + a : Int Signed64 + a = 1 + + b : I64 + b = 2 + + + 1 failed and 0 passed in ms. + "# + ); + let runner = cli_utils::helpers::Run::new_roc() + .arg(CMD_TEST) + .arg(from_root("crates/cli/tests/expects", "expects.roc").as_path()); + + if ALLOW_VALGRIND { + 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); } } } @@ -1391,11 +1407,11 @@ mod cli_run { if use_valgrind.and_is_supported() { let out = runner.run_with_valgrind(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } else { let out = runner.run(); out.assert_clean_success(); - out.assert_stdout_ends_with(expected_ending); + out.assert_stdout_and_stderr_ends_with(expected_ending); } } @@ -1633,9 +1649,9 @@ mod cli_run { Something is off with the body of the main definition: - 6│ main : Str -> Task {} [] - 7│ main = /_ -> - 8│ "this is a string, not a Task {} [] function like the platform expects." + 5│ main : Str -> Task {} [] + 6│ main = /_ -> + 7│ "this is a string, not a Task {} [] function like the platform expects." ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The body is a string of type: @@ -1667,8 +1683,8 @@ mod cli_run { Symbol is imported but not used. - 3│ imports [Symbol.{ Ident }] - ^^^^^^^^^^^^^^^^ + 3│ import Symbol exposing [Ident] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Since Symbol isn't used, you don't need to import it. @@ -1711,8 +1727,8 @@ mod cli_run { Symbol is imported but not used. - 3│ imports [Symbol.{ Ident }] - ^^^^^^^^^^^^^^^^ + 3│ import Symbol exposing [Ident] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Since Symbol isn't used, you don't need to import it. diff --git a/crates/cli/tests/expects/expects.roc b/crates/cli/tests/expects/expects.roc index e2125c0d99..439fcf250f 100644 --- a/crates/cli/tests/expects/expects.roc +++ b/crates/cli/tests/expects/expects.roc @@ -1,7 +1,4 @@ -app "expects-test" - packages { pf: "zig-platform/main.roc" } - imports [] - provides [main] to pf +app [main] { pf: platform "../test-platform-simple-zig/main.roc" } makeA = a = 1 diff --git a/crates/cli/tests/expects/zig-platform/host.zig b/crates/cli/tests/expects/zig-platform/host.zig deleted file mode 100644 index 1ac9ce6dbe..0000000000 --- a/crates/cli/tests/expects/zig-platform/host.zig +++ /dev/null @@ -1,129 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const str = @import("glue").str; -const RocStr = str.RocStr; -const testing = std.testing; -const expectEqual = testing.expectEqual; -const expect = testing.expect; - -const Align = 2 * @alignOf(usize); -extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque; -extern fn realloc(c_ptr: [*]align(Align) u8, size: usize) callconv(.C) ?*anyopaque; -extern fn free(c_ptr: [*]align(Align) u8) callconv(.C) void; -extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void; -extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void; - -const DEBUG: bool = false; - -export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { - if (DEBUG) { - var ptr = malloc(size); - const stdout = std.io.getStdOut().writer(); - stdout.print("alloc: {d} (alignment {d}, size {d})\n", .{ ptr, alignment, size }) catch unreachable; - return ptr; - } else { - return malloc(size); - } -} - -export fn roc_realloc(c_ptr: *anyopaque, new_size: usize, old_size: usize, alignment: u32) callconv(.C) ?*anyopaque { - if (DEBUG) { - const stdout = std.io.getStdOut().writer(); - stdout.print("realloc: {d} (alignment {d}, old_size {d})\n", .{ c_ptr, alignment, old_size }) catch unreachable; - } - - return realloc(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr))), new_size); -} - -export fn roc_dealloc(c_ptr: *anyopaque, alignment: u32) callconv(.C) void { - if (DEBUG) { - const stdout = std.io.getStdOut().writer(); - stdout.print("dealloc: {d} (alignment {d})\n", .{ c_ptr, alignment }) catch unreachable; - } - - free(@as([*]align(Align) u8, @alignCast(@ptrCast(c_ptr)))); -} - -export fn roc_panic(msg: *RocStr, tag_id: u32) callconv(.C) void { - _ = tag_id; - - const stderr = std.io.getStdErr().writer(); - stderr.print("Application crashed with message\n\n {s}\n\nShutting down\n", .{msg.asSlice()}) catch unreachable; - std.process.exit(1); -} - -export fn roc_dbg(loc: *RocStr, msg: *RocStr, src: *RocStr) callconv(.C) void { - // This platform uses stdout for testing purposes instead of the normal stderr. - const stdout = std.io.getStdOut().writer(); - stdout.print("[{s}] {s} = {s}\n", .{ loc.asSlice(), src.asSlice(), msg.asSlice() }) catch unreachable; -} - -export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void { - return memset(dst, value, size); -} - -extern fn kill(pid: c_int, sig: c_int) c_int; -extern fn shm_open(name: *const i8, oflag: c_int, mode: c_uint) c_int; -extern fn mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) *anyopaque; -extern fn getppid() c_int; - -fn roc_getppid() callconv(.C) c_int { - return getppid(); -} - -fn roc_getppid_windows_stub() callconv(.C) c_int { - return 0; -} - -fn roc_send_signal(pid: c_int, sig: c_int) callconv(.C) c_int { - return kill(pid, sig); -} -fn roc_shm_open(name: *const i8, oflag: c_int, mode: c_uint) callconv(.C) c_int { - return shm_open(name, oflag, mode); -} -fn roc_mmap(addr: ?*anyopaque, length: c_uint, prot: c_int, flags: c_int, fd: c_int, offset: c_uint) callconv(.C) *anyopaque { - return mmap(addr, length, prot, flags, fd, offset); -} - -comptime { - if (builtin.os.tag == .macos or builtin.os.tag == .linux) { - @export(roc_getppid, .{ .name = "roc_getppid", .linkage = .Strong }); - @export(roc_mmap, .{ .name = "roc_mmap", .linkage = .Strong }); - @export(roc_send_signal, .{ .name = "roc_send_signal", .linkage = .Strong }); - @export(roc_shm_open, .{ .name = "roc_shm_open", .linkage = .Strong }); - } - - if (builtin.os.tag == .windows) { - @export(roc_getppid_windows_stub, .{ .name = "roc_getppid", .linkage = .Strong }); - } -} - -const mem = std.mem; -const Allocator = mem.Allocator; - -extern fn roc__mainForHost_1_exposed_generic(*RocStr) void; - -const Unit = extern struct {}; - -pub fn main() u8 { - 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 - var callresult = RocStr.empty(); - 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.print("{s}", .{callresult.asSlice()}) catch unreachable; - - callresult.decref(); - - stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable; - - return 0; -} diff --git a/crates/cli/tests/expects/zig-platform/main.roc b/crates/cli/tests/expects/zig-platform/main.roc deleted file mode 100644 index a52fe9a480..0000000000 --- a/crates/cli/tests/expects/zig-platform/main.roc +++ /dev/null @@ -1,9 +0,0 @@ -platform "echo-in-zig" - requires {} { main : Str } - exposes [] - packages {} - imports [] - provides [mainForHost] - -mainForHost : Str -mainForHost = main diff --git a/crates/cli/tests/test-platform-simple-zig/host.zig b/crates/cli/tests/test-platform-simple-zig/host.zig index 029a3ea4ed..707bfeb4b2 100644 --- a/crates/cli/tests/test-platform-simple-zig/host.zig +++ b/crates/cli/tests/test-platform-simple-zig/host.zig @@ -93,27 +93,15 @@ const Unit = extern struct {}; pub export fn main() i32 { 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 var callresult = RocStr.empty(); 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.print("{s}\n", .{callresult.asSlice()}) catch unreachable; callresult.decref(); - stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable; - return 0; } - -fn to_seconds(tms: std.os.timespec) f64 { - return @as(f64, @floatFromInt(tms.tv_sec)) + (@as(f64, @floatFromInt(tms.tv_nsec)) / 1_000_000_000.0); -} diff --git a/crates/cli_utils/src/helpers.rs b/crates/cli_utils/src/helpers.rs index e21c5a2c8d..633011ec94 100644 --- a/crates/cli_utils/src/helpers.rs +++ b/crates/cli_utils/src/helpers.rs @@ -6,6 +6,7 @@ extern crate tempfile; use regex::Regex; use roc_command_utils::{cargo, pretty_command_string, root_dir}; +use roc_reporting::report::ANSI_STYLE_CODES; use serde::Deserialize; use serde_xml_rs::from_str; use std::env; @@ -56,10 +57,13 @@ impl std::fmt::Display for Out { } impl Out { + /// Assert that the command succeeded and that there are no unexpected errors in the stderr. pub fn assert_clean_success(&self) { self.assert_success_with_no_unexpected_errors(COMMON_STDERR.as_slice()); } + /// Assert that the command succeeded and that there are no unexpected errors in the stderr. + /// This DOES NOT normalise the output, use assert_stdout_ends_with for that. pub fn assert_success_with_no_unexpected_errors(&self, expected_errors: &[ExpectedString]) { assert!(self.status.success(), "Command failed\n\n{self}"); assert!( @@ -69,23 +73,47 @@ impl Out { ); } - /// Normalise the output for comparison in tests by stripping ANSI color codes - /// and replace test timings with a placeholder. - pub fn stdout_without_test_timings(&self) -> String { + /// Normalise the output for comparison in tests by replacing with a placeholder + fn normalize_for_tests(input: &String) -> String { + // remove ANSI color codes let ansi_regex = Regex::new(r"\x1b\[[0-9;]*[mGKH]").expect("Invalid ANSI regex pattern"); - let without_ansi = ansi_regex.replace_all(&self.stdout, ""); + let without_ansi = ansi_regex.replace_all(input, ""); + // replace timings with a placeholder let regex = Regex::new(r" in (\d+) ms\.").expect("Invalid regex pattern"); let replacement = " in ms."; - regex.replace_all(&without_ansi, replacement).to_string() + let without_timings = regex.replace_all(&without_ansi, replacement); + + // replace file paths with a placeholder + let filepath_regex = + Regex::new(r"\[([^:]+):(\d+)\]").expect("Invalid filepath regex pattern"); + let filepath_replacement = "[:$2]"; + filepath_regex + .replace_all(&without_timings, filepath_replacement) + .to_string() } - pub fn assert_stdout_ends_with(&self, expected: &str) { + /// Assert that the stdout ends with the expected string + /// This normalises the output for comparison in tests such as replacing timings + /// with a placeholder, or stripping ANSI colors + pub fn assert_stdout_and_stderr_ends_with(&self, expected: &str) { + let normalised_output = format!( + "{}{}", + Out::normalize_for_tests(&self.stdout), + Out::normalize_for_tests(&self.stderr) + ); + assert!( - dbg!(self.stdout_without_test_timings()).ends_with(expected), - "Expected stdout to end with:\n{}\n\nActual stdout:\n{}", + normalised_output.ends_with(expected), + "\n{}EXPECTED stdout and stderr after normalizing:\n----------------\n{}{}\n{}ACTUAL stdout and stderr after normalizing:\n----------------\n{}{}{}\n----------------\n{}", + ANSI_STYLE_CODES.cyan, + ANSI_STYLE_CODES.reset, expected, - self.stdout + ANSI_STYLE_CODES.cyan, + ANSI_STYLE_CODES.reset, + normalised_output, + ANSI_STYLE_CODES.cyan, + ANSI_STYLE_CODES.reset, ); } }