WIP improve cli tests

This commit is contained in:
Luke Boswell 2024-08-16 13:41:58 +10:00
parent d2fbf86fad
commit 7ce9ecd32d
No known key found for this signature in database
GPG key ID: F6DB3C9DB47377B0
6 changed files with 211 additions and 320 deletions

View file

@ -353,10 +353,10 @@ mod cli_run {
if use_valgrind.and_is_supported() { if use_valgrind.and_is_supported() {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_stdout_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_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() { if use_valgrind.and_is_supported() {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_clean_success(); out.assert_clean_success();
out.assert_stdout_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_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)] #[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"; let expected_ending = "Hello, World!\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)
@ -404,11 +404,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -431,11 +431,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -456,11 +456,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -479,11 +479,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -499,102 +499,6 @@ mod cli_run {
out.assert_clean_success(); 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"]
[<ignored for tests>:31] x = 42
[<ignored for tests>:33] "Fjoer en ferdjer frieten oan dyn geve lea" = "Fjoer en ferdjer frieten oan dyn geve lea"
[<ignored for tests>:35] "this is line 24" = "this is line 24"
[<ignored for tests>:21] x = "abc"
[<ignored for tests>:21] x = 10
[<ignored for tests>: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 <ignored for test> ms.
"#
),
UseValgrind::Yes,
TestCliCommands::Test,
);
}
#[test] #[test]
#[cfg_attr(windows, ignore)] #[cfg_attr(windows, ignore)]
fn test_module_imports_pkg_w_flag() { fn test_module_imports_pkg_w_flag() {
@ -610,10 +514,10 @@ mod cli_run {
if ALLOW_VALGRIND { if ALLOW_VALGRIND {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_stdout_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_stdout_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -643,10 +547,10 @@ mod cli_run {
if ALLOW_VALGRIND { if ALLOW_VALGRIND {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_stdout_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_stdout_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -686,10 +590,10 @@ mod cli_run {
if ALLOW_VALGRIND { if ALLOW_VALGRIND {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_stdout_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_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(); let out = runner.run();
out.assert_clean_success(); out.assert_clean_success();
out.assert_stdout_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
#[test] #[test]
@ -723,10 +627,10 @@ mod cli_run {
if ALLOW_VALGRIND { if ALLOW_VALGRIND {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_stdout_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_stdout_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -751,10 +655,10 @@ mod cli_run {
if ALLOW_VALGRIND { if ALLOW_VALGRIND {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_stdout_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_stdout_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -774,11 +678,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -796,11 +700,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1074,7 +978,7 @@ mod cli_run {
let out = runner.run(); let out = runner.run();
out.assert_clean_success(); out.assert_clean_success();
out.assert_stdout_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
#[test] #[test]
@ -1090,7 +994,7 @@ mod cli_run {
let out = runner.run(); let out = runner.run();
out.assert_clean_success(); out.assert_clean_success();
out.assert_stdout_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
#[test] #[test]
@ -1107,11 +1011,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_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_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, ALLOW_VALGRIND, BUILD_HOST_FLAG, OPTIMIZE_FLAG, SUPPRESS_BUILD_HOST_WARNING_FLAG,
}; };
use cli_utils::helpers::{from_root, Run}; 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(); 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(), from_root("crates/cli/tests/test-platform-simple-zig", "app.roc").as_path(),
) )
.run(); .run();
dbg!(&out);
out.assert_clean_success(); out.assert_clean_success();
}); });
} }
@ -1154,11 +1058,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1176,11 +1080,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1197,11 +1101,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1222,11 +1126,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1244,11 +1148,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1267,11 +1171,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1293,11 +1197,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1319,11 +1223,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_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_ends_with(expected_ending); out.assert_stdout_and_stderr_ends_with(expected_ending);
} }
} }
@ -1345,11 +1249,123 @@ 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_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_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!
[<ignored for tests>:28] x = 42
[<ignored for tests>:30] "Fjoer en ferdjer frieten oan dyn geve lea" = "Fjoer en ferdjer frieten oan dyn geve lea"
[<ignored for tests>:32] "this is line 24" = "this is line 24"
[<ignored for tests>:18] x = "abc"
[<ignored for tests>:18] x = 10
[<ignored for tests>: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 <ignored for test> 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() { if use_valgrind.and_is_supported() {
let out = runner.run_with_valgrind(); let out = runner.run_with_valgrind();
out.assert_clean_success(); out.assert_clean_success();
out.assert_stdout_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_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: Something is off with the body of the main definition:
6 main : Str -> Task {} [] 5 main : Str -> Task {} []
7 main = /_ -> 6 main = /_ ->
8 "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."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The body is a string of type: The body is a string of type:
@ -1667,8 +1683,8 @@ mod cli_run {
Symbol is imported but not used. 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. 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. 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. Since Symbol isn't used, you don't need to import it.

View file

@ -1,7 +1,4 @@
app "expects-test" app [main] { pf: platform "../test-platform-simple-zig/main.roc" }
packages { pf: "zig-platform/main.roc" }
imports []
provides [main] to pf
makeA = makeA =
a = 1 a = 1

View file

@ -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;
}

View file

@ -1,9 +0,0 @@
platform "echo-in-zig"
requires {} { main : Str }
exposes []
packages {}
imports []
provides [mainForHost]
mainForHost : Str
mainForHost = main

View file

@ -93,27 +93,15 @@ const Unit = extern struct {};
pub export fn main() i32 { pub export fn main() i32 {
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}\n", .{callresult.asSlice()}) catch unreachable; stdout.print("{s}\n", .{callresult.asSlice()}) catch unreachable;
callresult.decref(); callresult.decref();
stderr.print("runtime: {d:.3}ms\n", .{seconds * 1000}) catch unreachable;
return 0; 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);
}

View file

@ -6,6 +6,7 @@ extern crate tempfile;
use regex::Regex; use regex::Regex;
use roc_command_utils::{cargo, pretty_command_string, root_dir}; use roc_command_utils::{cargo, pretty_command_string, root_dir};
use roc_reporting::report::ANSI_STYLE_CODES;
use serde::Deserialize; use serde::Deserialize;
use serde_xml_rs::from_str; use serde_xml_rs::from_str;
use std::env; use std::env;
@ -56,10 +57,13 @@ impl std::fmt::Display for Out {
} }
impl Out { impl Out {
/// Assert that the command succeeded and that there are no unexpected errors in the stderr.
pub fn assert_clean_success(&self) { pub fn assert_clean_success(&self) {
self.assert_success_with_no_unexpected_errors(COMMON_STDERR.as_slice()); 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]) { pub fn assert_success_with_no_unexpected_errors(&self, expected_errors: &[ExpectedString]) {
assert!(self.status.success(), "Command failed\n\n{self}"); assert!(self.status.success(), "Command failed\n\n{self}");
assert!( assert!(
@ -69,23 +73,47 @@ impl Out {
); );
} }
/// Normalise the output for comparison in tests by stripping ANSI color codes /// Normalise the output for comparison in tests by replacing with a placeholder
/// and replace test timings with a placeholder. fn normalize_for_tests(input: &String) -> String {
pub fn stdout_without_test_timings(&self) -> String { // 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(&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 regex = Regex::new(r" in (\d+) ms\.").expect("Invalid regex pattern");
let replacement = " in <ignored for test> ms."; let replacement = " in <ignored for test> 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 = "[<ignored for tests>:$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!( assert!(
dbg!(self.stdout_without_test_timings()).ends_with(expected), normalised_output.ends_with(expected),
"Expected stdout to end with:\n{}\n\nActual stdout:\n{}", "\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, expected,
self.stdout ANSI_STYLE_CODES.cyan,
ANSI_STYLE_CODES.reset,
normalised_output,
ANSI_STYLE_CODES.cyan,
ANSI_STYLE_CODES.reset,
); );
} }
} }