Skip to content

Commit 81ae2f6

Browse files
committed
Only build tests on native targets
1 parent c1b7650 commit 81ae2f6

File tree

4 files changed

+139
-0
lines changed

4 files changed

+139
-0
lines changed

build.zig

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,25 @@ pub fn build(b: *std.Build) void {
598598
const is_native = target.query.isNativeCpu() and target.query.isNativeOs() and (target.query.isNativeAbi() or target.result.abi.isMusl());
599599
const is_windows = target.result.os.tag == .windows;
600600

601+
// fx platform effectful functions test - only run on native builds
602+
if (is_native) {
603+
const fx_platform_test = b.addTest(.{
604+
.name = "fx_platform_test",
605+
.root_module = b.createModule(.{
606+
.root_source_file = b.path("src/cli/test/fx_platform_test.zig"),
607+
.target = target,
608+
.optimize = optimize,
609+
}),
610+
.filters = test_filters,
611+
});
612+
613+
const run_fx_platform_test = b.addRunArtifact(fx_platform_test);
614+
if (run_args.len != 0) {
615+
run_fx_platform_test.addArgs(run_args);
616+
}
617+
tests_summary.addRun(&run_fx_platform_test.step);
618+
}
619+
601620
var build_afl = false;
602621
if (!is_native) {
603622
std.log.warn("Cross compilation does not support fuzzing (Only building repro executables)", .{});
@@ -809,6 +828,22 @@ fn addMainExe(
809828
copy_test_int_host.addCopyFileToSource(test_platform_int_host_lib.getEmittedBin(), b.pathJoin(&.{ "test/int/platform", test_int_host_filename }));
810829
b.getInstallStep().dependOn(&copy_test_int_host.step);
811830

831+
// Create fx test platform host static library - native target only
832+
const test_platform_fx_host_lib = createTestPlatformHostLib(
833+
b,
834+
"test_platform_fx_host",
835+
"test/fx/platform/host.zig",
836+
target,
837+
optimize,
838+
roc_modules,
839+
);
840+
841+
// Copy the fx test platform host library to the source directory
842+
const copy_test_fx_host = b.addUpdateSourceFiles();
843+
const test_fx_host_filename = if (target.result.os.tag == .windows) "host.lib" else "libhost.a";
844+
copy_test_fx_host.addCopyFileToSource(test_platform_fx_host_lib.getEmittedBin(), b.pathJoin(&.{ "test/fx/platform", test_fx_host_filename }));
845+
b.getInstallStep().dependOn(&copy_test_fx_host.step);
846+
812847
// Cross-compile int platform host libraries for musl and glibc targets
813848
const cross_compile_targets = [_]struct { name: []const u8, query: std.Target.Query }{
814849
.{ .name = "x64musl", .query = .{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .musl } },

src/cli/test/fx_platform_test.zig

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
const std = @import("std");
2+
const testing = std.testing;
3+
4+
test "fx platform effectful functions" {
5+
const allocator = testing.allocator;
6+
7+
// Build the fx app
8+
const build_result = try std.process.Child.run(.{
9+
.allocator = allocator,
10+
.argv = &[_][]const u8{
11+
"./zig-out/bin/roc",
12+
"build",
13+
"test/fx/app.roc",
14+
},
15+
});
16+
defer allocator.free(build_result.stdout);
17+
defer allocator.free(build_result.stderr);
18+
19+
switch (build_result.term) {
20+
.Exited => |code| {
21+
if (code != 0) {
22+
std.debug.print("Build failed with exit code {}\n", .{code});
23+
std.debug.print("STDOUT: {s}\n", .{build_result.stdout});
24+
std.debug.print("STDERR: {s}\n", .{build_result.stderr});
25+
return error.BuildFailed;
26+
}
27+
},
28+
else => {
29+
std.debug.print("Build terminated abnormally: {}\n", .{build_result.term});
30+
std.debug.print("STDOUT: {s}\n", .{build_result.stdout});
31+
std.debug.print("STDERR: {s}\n", .{build_result.stderr});
32+
return error.BuildFailed;
33+
},
34+
}
35+
36+
// Run the app and capture stdout/stderr separately
37+
const run_result = try std.process.Child.run(.{
38+
.allocator = allocator,
39+
.argv = &[_][]const u8{"./app"},
40+
});
41+
defer allocator.free(run_result.stdout);
42+
defer allocator.free(run_result.stderr);
43+
44+
// Clean up the app binary
45+
std.fs.cwd().deleteFile("./app") catch {};
46+
47+
switch (run_result.term) {
48+
.Exited => |code| {
49+
if (code != 0) {
50+
std.debug.print("Run failed with exit code {}\n", .{code});
51+
std.debug.print("STDOUT: {s}\n", .{run_result.stdout});
52+
std.debug.print("STDERR: {s}\n", .{run_result.stderr});
53+
return error.RunFailed;
54+
}
55+
},
56+
else => {
57+
std.debug.print("Run terminated abnormally: {}\n", .{run_result.term});
58+
std.debug.print("STDOUT: {s}\n", .{run_result.stdout});
59+
std.debug.print("STDERR: {s}\n", .{run_result.stderr});
60+
return error.RunFailed;
61+
},
62+
}
63+
64+
// Verify stdout contains expected messages
65+
try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Hello from stdout!") != null);
66+
try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Line 1 to stdout") != null);
67+
try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Line 3 to stdout") != null);
68+
try testing.expect(std.mem.indexOf(u8, run_result.stdout, "ALL TESTS COMPLETED") != null);
69+
70+
// Verify stderr contains expected messages
71+
try testing.expect(std.mem.indexOf(u8, run_result.stderr, "Error from stderr!") != null);
72+
try testing.expect(std.mem.indexOf(u8, run_result.stderr, "Line 2 to stderr") != null);
73+
74+
// Verify stderr messages are NOT in stdout
75+
try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Error from stderr!") == null);
76+
try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Line 2 to stderr") == null);
77+
78+
// Verify stdout messages are NOT in stderr (except the ones we intentionally put there for display)
79+
// Note: The host.zig writes "STDOUT: ..." to stdout and "STDERR: ..." to stderr
80+
// so we check that the actual content is separated correctly
81+
}

test/fx/app.roc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
app [writeToStdout, writeToStderr] { pf: platform "./platform/main.roc" }
2+
3+
writeToStdout : Str => {}
4+
writeToStdout = |_msg|
5+
# The host will actually handle the IO
6+
{}
7+
8+
writeToStderr : Str => {}
9+
writeToStderr = |_msg|
10+
# The host will actually handle the IO
11+
{}

test/fx/platform/main.roc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
platform ""
2+
requires {} {
3+
writeToStdout : Str => {},
4+
writeToStderr : Str => {}
5+
}
6+
exposes []
7+
packages {}
8+
provides { writeToStdout: "writeToStdout", writeToStderr: "writeToStderr" }
9+
10+
writeToStdout : Str => {}
11+
12+
writeToStderr : Str => {}

0 commit comments

Comments
 (0)