@zigc/lib 0.16.0-dev.3091 → 0.16.0-dev.3128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/c/math.zig +121 -30
- package/compiler/build_runner.zig +1 -0
- package/compiler/test_runner.zig +191 -59
- package/compiler_rt/cos.zig +141 -52
- package/compiler_rt/long_double.zig +37 -0
- package/compiler_rt/rem_pio2l.zig +173 -0
- package/compiler_rt/sin.zig +140 -55
- package/compiler_rt/sincos.zig +279 -72
- package/compiler_rt/tan.zig +118 -47
- package/compiler_rt/trig.zig +256 -6
- package/fuzzer.zig +855 -307
- package/package.json +1 -1
- package/std/Build/Fuzz.zig +6 -19
- package/std/Build/Step/Run.zig +530 -68
- package/std/Build/abi.zig +39 -7
- package/std/Build.zig +3 -0
- package/std/compress/flate/Compress.zig +3 -3
- package/std/debug/Info.zig +4 -0
- package/std/heap/ArenaAllocator.zig +145 -154
- package/std/mem/Allocator.zig +4 -5
- package/std/mem.zig +48 -0
- package/std/priority_dequeue.zig +13 -12
- package/std/priority_queue.zig +5 -4
- package/std/zig/Client.zig +8 -3
- package/std/zig/Server.zig +26 -0
- package/libc/mingw/complex/cabs.c +0 -48
- package/libc/mingw/complex/cabsf.c +0 -48
- package/libc/mingw/complex/cacos.c +0 -50
- package/libc/mingw/complex/cacosf.c +0 -50
- package/libc/mingw/complex/carg.c +0 -48
- package/libc/mingw/complex/cargf.c +0 -48
- package/libc/mingw/complex/casin.c +0 -50
- package/libc/mingw/complex/casinf.c +0 -50
- package/libc/mingw/complex/catan.c +0 -50
- package/libc/mingw/complex/catanf.c +0 -50
- package/libc/mingw/complex/ccos.c +0 -50
- package/libc/mingw/complex/ccosf.c +0 -50
- package/libc/mingw/complex/cexp.c +0 -48
- package/libc/mingw/complex/cexpf.c +0 -48
- package/libc/mingw/complex/cimag.c +0 -48
- package/libc/mingw/complex/cimagf.c +0 -48
- package/libc/mingw/complex/clog.c +0 -48
- package/libc/mingw/complex/clog10.c +0 -49
- package/libc/mingw/complex/clog10f.c +0 -49
- package/libc/mingw/complex/clogf.c +0 -48
- package/libc/mingw/complex/conj.c +0 -48
- package/libc/mingw/complex/conjf.c +0 -48
- package/libc/mingw/complex/cpow.c +0 -48
- package/libc/mingw/complex/cpowf.c +0 -48
- package/libc/mingw/complex/cproj.c +0 -48
- package/libc/mingw/complex/cprojf.c +0 -48
- package/libc/mingw/complex/creal.c +0 -48
- package/libc/mingw/complex/crealf.c +0 -48
- package/libc/mingw/complex/csin.c +0 -50
- package/libc/mingw/complex/csinf.c +0 -50
- package/libc/mingw/complex/csqrt.c +0 -48
- package/libc/mingw/complex/csqrtf.c +0 -48
- package/libc/mingw/complex/ctan.c +0 -50
- package/libc/mingw/complex/ctanf.c +0 -50
- package/libc/mingw/math/arm/s_rint.c +0 -86
- package/libc/mingw/math/arm/s_rintf.c +0 -51
- package/libc/mingw/math/arm/sincos.S +0 -30
- package/libc/mingw/math/arm-common/sincosl.c +0 -13
- package/libc/mingw/math/arm64/rint.c +0 -12
- package/libc/mingw/math/arm64/rintf.c +0 -12
- package/libc/mingw/math/arm64/sincos.S +0 -32
- package/libc/mingw/math/bsd_private_base.h +0 -148
- package/libc/mingw/math/frexpf.c +0 -13
- package/libc/mingw/math/frexpl.c +0 -71
- package/libc/mingw/math/x86/acosf.c +0 -29
- package/libc/mingw/math/x86/atanf.c +0 -23
- package/libc/mingw/math/x86/atanl.c +0 -18
- package/libc/mingw/math/x86/cos.def.h +0 -65
- package/libc/mingw/math/x86/cosl.c +0 -46
- package/libc/mingw/math/x86/cosl_internal.S +0 -55
- package/libc/mingw/math/x86/ldexp.c +0 -23
- package/libc/mingw/math/x86/scalbn.S +0 -41
- package/libc/mingw/math/x86/scalbnf.S +0 -40
- package/libc/mingw/math/x86/sin.def.h +0 -65
- package/libc/mingw/math/x86/sinl.c +0 -46
- package/libc/mingw/math/x86/sinl_internal.S +0 -58
- package/libc/mingw/math/x86/tanl.S +0 -62
- package/libc/mingw/misc/btowc.c +0 -28
- package/libc/mingw/misc/wcstof.c +0 -66
- package/libc/mingw/misc/wcstoimax.c +0 -132
- package/libc/mingw/misc/wcstoumax.c +0 -126
- package/libc/mingw/misc/wctob.c +0 -29
- package/libc/mingw/misc/winbs_uint64.c +0 -6
- package/libc/mingw/misc/winbs_ulong.c +0 -6
- package/libc/mingw/misc/winbs_ushort.c +0 -6
- package/libc/mingw/stdio/_Exit.c +0 -10
- package/libc/mingw/stdio/_findfirst64i32.c +0 -21
- package/libc/mingw/stdio/_findnext64i32.c +0 -21
- package/libc/mingw/stdio/_fstat64i32.c +0 -37
- package/libc/mingw/stdio/_stat64i32.c +0 -37
- package/libc/mingw/stdio/_wfindfirst64i32.c +0 -21
- package/libc/mingw/stdio/_wfindnext64i32.c +0 -21
- package/libc/mingw/stdio/_wstat64i32.c +0 -37
- package/libc/musl/src/legacy/valloc.c +0 -8
- package/libc/musl/src/math/__cosl.c +0 -96
- package/libc/musl/src/math/__sinl.c +0 -78
- package/libc/musl/src/math/__tanl.c +0 -143
- package/libc/musl/src/math/aarch64/lrint.c +0 -10
- package/libc/musl/src/math/aarch64/lrintf.c +0 -10
- package/libc/musl/src/math/aarch64/rintf.c +0 -7
- package/libc/musl/src/math/cosl.c +0 -39
- package/libc/musl/src/math/exp_data.c +0 -182
- package/libc/musl/src/math/exp_data.h +0 -26
- package/libc/musl/src/math/finite.c +0 -7
- package/libc/musl/src/math/finitef.c +0 -7
- package/libc/musl/src/math/frexp.c +0 -23
- package/libc/musl/src/math/frexpf.c +0 -23
- package/libc/musl/src/math/frexpl.c +0 -29
- package/libc/musl/src/math/i386/lrint.c +0 -8
- package/libc/musl/src/math/i386/lrintf.c +0 -8
- package/libc/musl/src/math/i386/rintf.c +0 -7
- package/libc/musl/src/math/lrint.c +0 -72
- package/libc/musl/src/math/lrintf.c +0 -8
- package/libc/musl/src/math/pow_data.c +0 -180
- package/libc/musl/src/math/pow_data.h +0 -22
- package/libc/musl/src/math/powerpc64/lrint.c +0 -16
- package/libc/musl/src/math/powerpc64/lrintf.c +0 -16
- package/libc/musl/src/math/rintf.c +0 -30
- package/libc/musl/src/math/s390x/rintf.c +0 -15
- package/libc/musl/src/math/sincosl.c +0 -60
- package/libc/musl/src/math/sinl.c +0 -41
- package/libc/musl/src/math/tanl.c +0 -29
- package/libc/musl/src/math/x32/lrint.s +0 -5
- package/libc/musl/src/math/x32/lrintf.s +0 -5
- package/libc/musl/src/math/x86_64/lrint.c +0 -8
- package/libc/musl/src/math/x86_64/lrintf.c +0 -8
- package/libc/wasi/libc-bottom-half/sources/reallocarray.c +0 -14
package/std/Build/Step/Run.zig
CHANGED
|
@@ -1068,7 +1068,6 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|
|
1068
1068
|
pub fn rerunInFuzzMode(
|
|
1069
1069
|
run: *Run,
|
|
1070
1070
|
fuzz: *std.Build.Fuzz,
|
|
1071
|
-
unit_test_name: []const u8,
|
|
1072
1071
|
prog_node: std.Progress.Node,
|
|
1073
1072
|
) !void {
|
|
1074
1073
|
const step = &run.step;
|
|
@@ -1139,7 +1138,6 @@ pub fn rerunInFuzzMode(
|
|
|
1139
1138
|
.unit_test_timeout_ns = null, // don't time out fuzz tests for now
|
|
1140
1139
|
.gpa = fuzz.gpa,
|
|
1141
1140
|
}, .{
|
|
1142
|
-
.unit_test_name = unit_test_name,
|
|
1143
1141
|
.fuzz = fuzz,
|
|
1144
1142
|
});
|
|
1145
1143
|
}
|
|
@@ -1211,7 +1209,6 @@ fn termMatches(expected: ?process.Child.Term, actual: process.Child.Term) bool {
|
|
|
1211
1209
|
|
|
1212
1210
|
const FuzzContext = struct {
|
|
1213
1211
|
fuzz: *std.Build.Fuzz,
|
|
1214
|
-
unit_test_name: []const u8,
|
|
1215
1212
|
};
|
|
1216
1213
|
|
|
1217
1214
|
fn runCommand(
|
|
@@ -1655,6 +1652,11 @@ fn evalZigTest(
|
|
|
1655
1652
|
options: Step.MakeOptions,
|
|
1656
1653
|
fuzz_context: ?FuzzContext,
|
|
1657
1654
|
) !void {
|
|
1655
|
+
if (fuzz_context != null) {
|
|
1656
|
+
try evalFuzzTest(run, spawn_options, options, fuzz_context.?);
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1658
1660
|
const step_owner = run.step.owner;
|
|
1659
1661
|
const gpa = step_owner.allocator;
|
|
1660
1662
|
const arena = step_owner.allocator;
|
|
@@ -1693,7 +1695,6 @@ fn evalZigTest(
|
|
|
1693
1695
|
run,
|
|
1694
1696
|
&child,
|
|
1695
1697
|
options,
|
|
1696
|
-
fuzz_context,
|
|
1697
1698
|
&multi_reader,
|
|
1698
1699
|
&test_metadata,
|
|
1699
1700
|
&test_results,
|
|
@@ -1815,7 +1816,6 @@ fn waitZigTest(
|
|
|
1815
1816
|
run: *Run,
|
|
1816
1817
|
child: *process.Child,
|
|
1817
1818
|
options: Step.MakeOptions,
|
|
1818
|
-
fuzz_context: ?FuzzContext,
|
|
1819
1819
|
multi_reader: *Io.File.MultiReader,
|
|
1820
1820
|
opt_metadata: *?TestMetadata,
|
|
1821
1821
|
results: *Step.TestResults,
|
|
@@ -1837,29 +1837,7 @@ fn waitZigTest(
|
|
|
1837
1837
|
var sub_prog_node: ?std.Progress.Node = null;
|
|
1838
1838
|
defer if (sub_prog_node) |n| n.end();
|
|
1839
1839
|
|
|
1840
|
-
if (
|
|
1841
|
-
assert(opt_metadata.* == null); // fuzz processes are never restarted
|
|
1842
|
-
switch (ctx.fuzz.mode) {
|
|
1843
|
-
.forever => {
|
|
1844
|
-
sendRunFuzzTestMessage(
|
|
1845
|
-
io,
|
|
1846
|
-
child.stdin.?,
|
|
1847
|
-
ctx.unit_test_name,
|
|
1848
|
-
.forever,
|
|
1849
|
-
0, // instance ID; will be used by multiprocess forever fuzzing in the future
|
|
1850
|
-
) catch |err| return .{ .write_failed = err };
|
|
1851
|
-
},
|
|
1852
|
-
.limit => |limit| {
|
|
1853
|
-
sendRunFuzzTestMessage(
|
|
1854
|
-
io,
|
|
1855
|
-
child.stdin.?,
|
|
1856
|
-
ctx.unit_test_name,
|
|
1857
|
-
.iterations,
|
|
1858
|
-
limit.amount,
|
|
1859
|
-
) catch |err| return .{ .write_failed = err };
|
|
1860
|
-
},
|
|
1861
|
-
}
|
|
1862
|
-
} else if (opt_metadata.*) |*md| {
|
|
1840
|
+
if (opt_metadata.*) |*md| {
|
|
1863
1841
|
// Previous unit test process died or was killed; we're continuing where it left off
|
|
1864
1842
|
requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err };
|
|
1865
1843
|
} else {
|
|
@@ -1872,14 +1850,11 @@ fn waitZigTest(
|
|
|
1872
1850
|
|
|
1873
1851
|
var last_update: Io.Clock.Timestamp = .now(io, .awake);
|
|
1874
1852
|
|
|
1875
|
-
var coverage_id: ?u64 = null;
|
|
1876
|
-
|
|
1877
1853
|
// This timeout is used when we're waiting on the test runner itself rather than a user-specified
|
|
1878
1854
|
// test. For instance, if the test runner leaves this much time between us requesting a test to
|
|
1879
1855
|
// start and it acknowledging the test starting, we terminate the child and raise an error. This
|
|
1880
1856
|
// *should* never happen, but could in theory be caused by some very unlucky IB in a test.
|
|
1881
|
-
const response_timeout:
|
|
1882
|
-
if (fuzz_context != null) break :t null; // don't timeout fuzz tests
|
|
1857
|
+
const response_timeout: Io.Clock.Duration = t: {
|
|
1883
1858
|
const ns = @max(options.unit_test_timeout_ns orelse 0, 60 * std.time.ns_per_s);
|
|
1884
1859
|
break :t .{ .clock = .awake, .raw = .fromNanoseconds(ns) };
|
|
1885
1860
|
};
|
|
@@ -1947,8 +1922,6 @@ fn waitZigTest(
|
|
|
1947
1922
|
);
|
|
1948
1923
|
},
|
|
1949
1924
|
.test_metadata => {
|
|
1950
|
-
assert(fuzz_context == null);
|
|
1951
|
-
|
|
1952
1925
|
// `metadata` would only be populated if we'd already seen a `test_metadata`, but we
|
|
1953
1926
|
// only request it once (and importantly, we don't re-request it if we kill and
|
|
1954
1927
|
// restart the test runner).
|
|
@@ -1986,7 +1959,6 @@ fn waitZigTest(
|
|
|
1986
1959
|
last_update = .now(io, .awake);
|
|
1987
1960
|
},
|
|
1988
1961
|
.test_results => {
|
|
1989
|
-
assert(fuzz_context == null);
|
|
1990
1962
|
const md = &opt_metadata.*.?;
|
|
1991
1963
|
|
|
1992
1964
|
const tr_hdr = body_r.takeStruct(std.zig.Server.Message.TestResults, .little) catch unreachable;
|
|
@@ -2033,44 +2005,523 @@ fn waitZigTest(
|
|
|
2033
2005
|
|
|
2034
2006
|
requestNextTest(io, child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err };
|
|
2035
2007
|
},
|
|
2008
|
+
else => {}, // ignore other messages
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
const FuzzTestRunner = struct {
|
|
2014
|
+
run: *Run,
|
|
2015
|
+
ctx: FuzzContext,
|
|
2016
|
+
coverage_id: ?u64,
|
|
2017
|
+
|
|
2018
|
+
instances: []Instance,
|
|
2019
|
+
/// The indexes of this are layed out such that it is effectively an array
|
|
2020
|
+
/// of `[instances.len][3]Io.Operation.Storage` of stdin, stdout, stderr.
|
|
2021
|
+
batch: Io.Batch,
|
|
2022
|
+
/// LIFO. Stream of message bodies trailed by PendingBroadcastFooter.
|
|
2023
|
+
pending_broadcasts: std.ArrayList(u8),
|
|
2024
|
+
broadcast: std.ArrayList(u8),
|
|
2025
|
+
broadcast_undelivered: u32,
|
|
2026
|
+
|
|
2027
|
+
const Instance = struct {
|
|
2028
|
+
child: process.Child,
|
|
2029
|
+
message: std.ArrayListAligned(u8, .@"4"),
|
|
2030
|
+
broadcast_written: usize,
|
|
2031
|
+
stderr: std.ArrayList(u8),
|
|
2032
|
+
stdin_vec: [1][]u8,
|
|
2033
|
+
stdout_vec: [1][]u8,
|
|
2034
|
+
stderr_vec: [1][]u8,
|
|
2035
|
+
progress_node: std.Progress.Node,
|
|
2036
|
+
|
|
2037
|
+
fn messageHeader(instance: *Instance) InHeader {
|
|
2038
|
+
assert(instance.message.items.len >= @sizeOf(InHeader));
|
|
2039
|
+
const header_ptr: *InHeader = @ptrCast(instance.message.items);
|
|
2040
|
+
var header = header_ptr.*;
|
|
2041
|
+
if (std.builtin.Endian.native != .little) {
|
|
2042
|
+
std.mem.byteSwapAllFields(InHeader, &header);
|
|
2043
|
+
}
|
|
2044
|
+
return header;
|
|
2045
|
+
}
|
|
2046
|
+
};
|
|
2047
|
+
|
|
2048
|
+
const PendingBroadcastFooter = struct {
|
|
2049
|
+
from_id: u32,
|
|
2050
|
+
body_len: u32,
|
|
2051
|
+
};
|
|
2052
|
+
|
|
2053
|
+
const InHeader = std.zig.Server.Message.Header;
|
|
2054
|
+
const OutHeader = std.zig.Client.Message.Header;
|
|
2055
|
+
|
|
2056
|
+
const stdin_i = 0;
|
|
2057
|
+
const stdout_i = 1;
|
|
2058
|
+
const stderr_i = 2;
|
|
2059
|
+
|
|
2060
|
+
fn init(
|
|
2061
|
+
run: *Run,
|
|
2062
|
+
ctx: FuzzContext,
|
|
2063
|
+
progress_node: std.Progress.Node,
|
|
2064
|
+
spawn_options: process.SpawnOptions,
|
|
2065
|
+
) !FuzzTestRunner {
|
|
2066
|
+
const step_owner = run.step.owner;
|
|
2067
|
+
const gpa = step_owner.allocator;
|
|
2068
|
+
const io = step_owner.graph.io;
|
|
2069
|
+
|
|
2070
|
+
const n_instances = switch (ctx.fuzz.mode) {
|
|
2071
|
+
.forever => step_owner.graph.max_jobs orelse @min(
|
|
2072
|
+
std.Thread.getCpuCount() catch 1,
|
|
2073
|
+
(std.math.maxInt(u32) - 2) / 3,
|
|
2074
|
+
),
|
|
2075
|
+
.limit => 1,
|
|
2076
|
+
};
|
|
2077
|
+
const instances = try gpa.alloc(Instance, n_instances);
|
|
2078
|
+
errdefer gpa.free(instances);
|
|
2079
|
+
const batch_storage = try gpa.alloc(Io.Operation.Storage, instances.len * 3);
|
|
2080
|
+
errdefer gpa.free(batch_storage);
|
|
2081
|
+
|
|
2082
|
+
@memset(instances, .{
|
|
2083
|
+
.child = undefined,
|
|
2084
|
+
.message = .empty,
|
|
2085
|
+
.broadcast_written = undefined,
|
|
2086
|
+
.stderr = .empty,
|
|
2087
|
+
.stdin_vec = undefined,
|
|
2088
|
+
.stdout_vec = undefined,
|
|
2089
|
+
.stderr_vec = undefined,
|
|
2090
|
+
.progress_node = undefined,
|
|
2091
|
+
});
|
|
2092
|
+
for (0.., instances) |id, *instance| {
|
|
2093
|
+
errdefer for (instances[0..id]) |*spawned| {
|
|
2094
|
+
spawned.child.kill(io);
|
|
2095
|
+
spawned.progress_node.end();
|
|
2096
|
+
};
|
|
2097
|
+
instance.child = try process.spawn(io, spawn_options);
|
|
2098
|
+
instance.progress_node = progress_node.start("starting fuzzer", 0);
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
return .{
|
|
2102
|
+
.run = run,
|
|
2103
|
+
.ctx = ctx,
|
|
2104
|
+
.coverage_id = null,
|
|
2105
|
+
|
|
2106
|
+
.instances = instances,
|
|
2107
|
+
.batch = .init(batch_storage),
|
|
2108
|
+
.pending_broadcasts = .empty,
|
|
2109
|
+
.broadcast = .empty,
|
|
2110
|
+
.broadcast_undelivered = 0,
|
|
2111
|
+
};
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
fn deinit(f: *FuzzTestRunner) void {
|
|
2115
|
+
const step_owner = f.run.step.owner;
|
|
2116
|
+
const gpa = step_owner.allocator;
|
|
2117
|
+
const io = step_owner.graph.io;
|
|
2118
|
+
|
|
2119
|
+
f.batch.cancel(io);
|
|
2120
|
+
gpa.free(f.batch.storage);
|
|
2121
|
+
var total_rss: usize = 0;
|
|
2122
|
+
for (f.instances) |*instance| {
|
|
2123
|
+
instance.child.kill(io);
|
|
2124
|
+
instance.message.deinit(gpa);
|
|
2125
|
+
instance.stderr.deinit(gpa);
|
|
2126
|
+
instance.progress_node.end();
|
|
2127
|
+
total_rss += instance.child.resource_usage_statistics.getMaxRss() orelse 0;
|
|
2128
|
+
}
|
|
2129
|
+
f.run.step.result_peak_rss = @max(f.run.step.result_peak_rss, total_rss);
|
|
2130
|
+
gpa.free(f.instances);
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
fn startInstances(f: *FuzzTestRunner) !void {
|
|
2134
|
+
const step_owner = f.run.step.owner;
|
|
2135
|
+
const io = step_owner.graph.io;
|
|
2136
|
+
|
|
2137
|
+
for (0.., f.instances) |id, *instance| {
|
|
2138
|
+
const id32: u32 = @intCast(id);
|
|
2139
|
+
(switch (f.ctx.fuzz.mode) {
|
|
2140
|
+
.forever => sendRunFuzzTestMessage(
|
|
2141
|
+
io,
|
|
2142
|
+
instance.child.stdin.?,
|
|
2143
|
+
f.run.fuzz_tests.items,
|
|
2144
|
+
.forever,
|
|
2145
|
+
id32,
|
|
2146
|
+
),
|
|
2147
|
+
.limit => |limit| sendRunFuzzTestMessage(
|
|
2148
|
+
io,
|
|
2149
|
+
instance.child.stdin.?,
|
|
2150
|
+
f.run.fuzz_tests.items,
|
|
2151
|
+
.iterations,
|
|
2152
|
+
limit.amount,
|
|
2153
|
+
),
|
|
2154
|
+
}) catch |write_err| {
|
|
2155
|
+
// The runner unexpectedly closed stdin, which means it crashed during initialization.
|
|
2156
|
+
// Clean up everything and wait for the child to exit.
|
|
2157
|
+
instance.child.stdin.?.close(io);
|
|
2158
|
+
instance.child.stdin = null;
|
|
2159
|
+
const term = try instance.child.wait(io);
|
|
2160
|
+
return f.run.step.fail(
|
|
2161
|
+
"unable to write stdin ({t}); test process unexpectedly {f}",
|
|
2162
|
+
.{ write_err, fmtTerm(term) },
|
|
2163
|
+
);
|
|
2164
|
+
};
|
|
2165
|
+
|
|
2166
|
+
try f.addStdoutRead(id32, @sizeOf(InHeader));
|
|
2167
|
+
try f.addStderrRead(id32);
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
fn listen(f: *FuzzTestRunner) !void {
|
|
2172
|
+
const step_owner = f.run.step.owner;
|
|
2173
|
+
const io = step_owner.graph.io;
|
|
2174
|
+
|
|
2175
|
+
while (true) {
|
|
2176
|
+
try f.batch.awaitConcurrent(io, .none);
|
|
2177
|
+
while (f.batch.next()) |completion| {
|
|
2178
|
+
const id = completion.index / 3;
|
|
2179
|
+
const result = completion.result;
|
|
2180
|
+
switch (completion.index % 3) {
|
|
2181
|
+
0 => try f.completeStdinWrite(id, result.file_write_streaming catch |e| switch (e) {
|
|
2182
|
+
error.BrokenPipe => return f.instanceEos(id),
|
|
2183
|
+
else => |write_e| return write_e,
|
|
2184
|
+
}),
|
|
2185
|
+
1 => try f.completeStdoutRead(id, result.file_read_streaming catch |e| switch (e) {
|
|
2186
|
+
error.EndOfStream => return f.instanceEos(id),
|
|
2187
|
+
else => |read_e| return read_e,
|
|
2188
|
+
}),
|
|
2189
|
+
2 => try f.completeStderrRead(id, result.file_read_streaming catch |e| switch (e) {
|
|
2190
|
+
error.EndOfStream => return f.instanceEos(id),
|
|
2191
|
+
else => |read_e| return read_e,
|
|
2192
|
+
}),
|
|
2193
|
+
else => unreachable,
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
fn completeStdoutRead(f: *FuzzTestRunner, id: u32, n: usize) !void {
|
|
2200
|
+
const step_owner = f.run.step.owner;
|
|
2201
|
+
const gpa = step_owner.allocator;
|
|
2202
|
+
const io = step_owner.graph.io;
|
|
2203
|
+
const instance = &f.instances[id];
|
|
2204
|
+
|
|
2205
|
+
instance.message.items.len += n;
|
|
2206
|
+
const total_read = instance.message.items.len;
|
|
2207
|
+
if (total_read < @sizeOf(InHeader)) {
|
|
2208
|
+
try f.addStdoutRead(id, @sizeOf(InHeader));
|
|
2209
|
+
return;
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
const header = instance.messageHeader();
|
|
2213
|
+
const body = instance.message.items[@sizeOf(InHeader)..];
|
|
2214
|
+
if (body.len != header.bytes_len) {
|
|
2215
|
+
try f.addStdoutRead(id, @sizeOf(InHeader) + header.bytes_len);
|
|
2216
|
+
return;
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
switch (header.tag) {
|
|
2220
|
+
.zig_version => {
|
|
2221
|
+
if (!std.mem.eql(u8, builtin.zig_version_string, body)) return f.run.step.fail(
|
|
2222
|
+
"zig version mismatch build runner vs compiler: '{s}' vs '{s}'",
|
|
2223
|
+
.{ builtin.zig_version_string, body },
|
|
2224
|
+
);
|
|
2225
|
+
},
|
|
2036
2226
|
.coverage_id => {
|
|
2037
|
-
|
|
2227
|
+
var body_r: Io.Reader = .fixed(body);
|
|
2228
|
+
f.coverage_id = body_r.takeInt(u64, .little) catch unreachable;
|
|
2038
2229
|
const cumulative_runs = body_r.takeInt(u64, .little) catch unreachable;
|
|
2039
2230
|
const cumulative_unique = body_r.takeInt(u64, .little) catch unreachable;
|
|
2040
2231
|
const cumulative_coverage = body_r.takeInt(u64, .little) catch unreachable;
|
|
2041
2232
|
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
.
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
fuzz.queue_cond.signal(io);
|
|
2056
|
-
}
|
|
2233
|
+
const fuzz = f.ctx.fuzz;
|
|
2234
|
+
fuzz.queue_mutex.lockUncancelable(io);
|
|
2235
|
+
defer fuzz.queue_mutex.unlock(io);
|
|
2236
|
+
try fuzz.msg_queue.append(fuzz.gpa, .{ .coverage = .{
|
|
2237
|
+
.id = f.coverage_id.?,
|
|
2238
|
+
.cumulative = .{
|
|
2239
|
+
.runs = cumulative_runs,
|
|
2240
|
+
.unique = cumulative_unique,
|
|
2241
|
+
.coverage = cumulative_coverage,
|
|
2242
|
+
},
|
|
2243
|
+
.run = f.run,
|
|
2244
|
+
} });
|
|
2245
|
+
fuzz.queue_cond.signal(io);
|
|
2057
2246
|
},
|
|
2058
2247
|
.fuzz_start_addr => {
|
|
2059
|
-
|
|
2248
|
+
var body_r: Io.Reader = .fixed(body);
|
|
2249
|
+
const fuzz = f.ctx.fuzz;
|
|
2060
2250
|
const addr = body_r.takeInt(u64, .little) catch unreachable;
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2251
|
+
|
|
2252
|
+
fuzz.queue_mutex.lockUncancelable(io);
|
|
2253
|
+
defer fuzz.queue_mutex.unlock(io);
|
|
2254
|
+
try fuzz.msg_queue.append(fuzz.gpa, .{ .entry_point = .{
|
|
2255
|
+
.addr = addr,
|
|
2256
|
+
.coverage_id = f.coverage_id.?,
|
|
2257
|
+
} });
|
|
2258
|
+
fuzz.queue_cond.signal(io);
|
|
2259
|
+
},
|
|
2260
|
+
.fuzz_test_change => {
|
|
2261
|
+
const test_i = std.mem.readInt(u32, body[0..4], .little);
|
|
2262
|
+
instance.progress_node.setName(f.run.fuzz_tests.items[test_i]);
|
|
2263
|
+
},
|
|
2264
|
+
.broadcast_fuzz_input => {
|
|
2265
|
+
if (f.instances.len == 1) {
|
|
2266
|
+
// No other processes to broadcast to.
|
|
2267
|
+
} else if (f.broadcast_undelivered == 0) {
|
|
2268
|
+
try f.instanceBroadcast(id, body);
|
|
2269
|
+
} else {
|
|
2270
|
+
const footer: PendingBroadcastFooter = .{
|
|
2271
|
+
.from_id = id,
|
|
2272
|
+
.body_len = @intCast(body.len),
|
|
2273
|
+
};
|
|
2274
|
+
// There is another broadcast in progress so add this one to the queue.
|
|
2275
|
+
const size = @sizeOf(PendingBroadcastFooter) + body.len;
|
|
2276
|
+
try f.pending_broadcasts.ensureUnusedCapacity(gpa, size);
|
|
2277
|
+
f.pending_broadcasts.appendSliceAssumeCapacity(body);
|
|
2278
|
+
f.pending_broadcasts.appendSliceAssumeCapacity(@ptrCast(&footer));
|
|
2069
2279
|
}
|
|
2070
2280
|
},
|
|
2071
2281
|
else => {}, // ignore other messages
|
|
2072
2282
|
}
|
|
2283
|
+
|
|
2284
|
+
instance.message.clearRetainingCapacity();
|
|
2285
|
+
try f.addStdoutRead(id, @sizeOf(InHeader));
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
fn completeStderrRead(f: *FuzzTestRunner, id: u32, n: usize) !void {
|
|
2289
|
+
const instance = &f.instances[id];
|
|
2290
|
+
instance.stderr.items.len += n;
|
|
2291
|
+
try f.addStderrRead(id);
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2294
|
+
fn completeStdinWrite(f: *FuzzTestRunner, id: u32, n: usize) !void {
|
|
2295
|
+
const instance = &f.instances[id];
|
|
2296
|
+
|
|
2297
|
+
instance.broadcast_written += n;
|
|
2298
|
+
if (instance.broadcast_written == f.broadcast.items.len) {
|
|
2299
|
+
f.broadcast_undelivered -= 1;
|
|
2300
|
+
if (f.broadcast_undelivered == 0) {
|
|
2301
|
+
try f.broadcastComplete();
|
|
2302
|
+
}
|
|
2303
|
+
} else {
|
|
2304
|
+
f.addStdinWrite(id);
|
|
2305
|
+
}
|
|
2073
2306
|
}
|
|
2307
|
+
|
|
2308
|
+
fn addStdoutRead(f: *FuzzTestRunner, id: u32, end: usize) !void {
|
|
2309
|
+
const step_owner = f.run.step.owner;
|
|
2310
|
+
const gpa = step_owner.allocator;
|
|
2311
|
+
const instance = &f.instances[id];
|
|
2312
|
+
|
|
2313
|
+
try instance.message.ensureTotalCapacity(gpa, end);
|
|
2314
|
+
const start = instance.message.items.len;
|
|
2315
|
+
instance.stdout_vec = .{instance.message.allocatedSlice()[start..end]};
|
|
2316
|
+
f.batch.addAt(id * 3 + stdout_i, .{ .file_read_streaming = .{
|
|
2317
|
+
.file = instance.child.stdout.?,
|
|
2318
|
+
.data = &instance.stdout_vec,
|
|
2319
|
+
} });
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
fn addStderrRead(f: *FuzzTestRunner, id: u32) !void {
|
|
2323
|
+
const step_owner = f.run.step.owner;
|
|
2324
|
+
const gpa = step_owner.allocator;
|
|
2325
|
+
const instance = &f.instances[id];
|
|
2326
|
+
|
|
2327
|
+
try instance.stderr.ensureUnusedCapacity(gpa, 1);
|
|
2328
|
+
instance.stderr_vec = .{instance.stderr.unusedCapacitySlice()};
|
|
2329
|
+
f.batch.addAt(id * 3 + stderr_i, .{ .file_read_streaming = .{
|
|
2330
|
+
.file = instance.child.stderr.?,
|
|
2331
|
+
.data = &instance.stderr_vec,
|
|
2332
|
+
} });
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
fn addStdinWrite(f: *FuzzTestRunner, id: u32) void {
|
|
2336
|
+
const instance = &f.instances[id];
|
|
2337
|
+
|
|
2338
|
+
assert(f.broadcast.items.len != instance.broadcast_written);
|
|
2339
|
+
instance.stdin_vec = .{f.broadcast.items[instance.broadcast_written..]};
|
|
2340
|
+
f.batch.addAt(id * 3 + stdin_i, .{ .file_write_streaming = .{
|
|
2341
|
+
.file = instance.child.stdin.?,
|
|
2342
|
+
.data = &instance.stdin_vec,
|
|
2343
|
+
} });
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
fn instanceEos(f: *FuzzTestRunner, id: u32) !void {
|
|
2347
|
+
const step_owner = f.run.step.owner;
|
|
2348
|
+
const io = step_owner.graph.io;
|
|
2349
|
+
const instance = &f.instances[id];
|
|
2350
|
+
|
|
2351
|
+
instance.child.stdin.?.close(io);
|
|
2352
|
+
instance.child.stdin = null;
|
|
2353
|
+
const term = try instance.child.wait(io);
|
|
2354
|
+
if (!termMatches(.{ .exited = 0 }, term)) {
|
|
2355
|
+
f.run.step.result_stderr = try f.mergedStderr();
|
|
2356
|
+
try f.saveCrash(id, term);
|
|
2357
|
+
return f.run.step.fail("test process unexpectedly {f}", .{fmtTerm(term)});
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
fn saveCrash(f: *FuzzTestRunner, id: u32, term: process.Child.Term) !void {
|
|
2362
|
+
const step = &f.run.step;
|
|
2363
|
+
const b = step.owner;
|
|
2364
|
+
const io = b.graph.io;
|
|
2365
|
+
|
|
2366
|
+
if (f.coverage_id == null) return;
|
|
2367
|
+
|
|
2368
|
+
// Search for the input file corresponding to the instance
|
|
2369
|
+
const InputHeader = Build.abi.fuzz.MmapInputHeader;
|
|
2370
|
+
var in_r_buf: [@sizeOf(InputHeader)]u8 = undefined;
|
|
2371
|
+
var in_r: Io.File.Reader = undefined;
|
|
2372
|
+
var in_f: Io.File = undefined;
|
|
2373
|
+
var in_name_buf: [12]u8 = undefined;
|
|
2374
|
+
var in_name: []const u8 = undefined;
|
|
2375
|
+
var i: u32 = 0;
|
|
2376
|
+
const header: InputHeader = while (true) {
|
|
2377
|
+
const name_prefix = "f" ++ Io.Dir.path.sep_str ++ "in";
|
|
2378
|
+
in_name = std.fmt.bufPrint(&in_name_buf, name_prefix ++ "{x}", .{i}) catch unreachable;
|
|
2379
|
+
in_f = b.cache_root.handle.openFile(io, in_name, .{
|
|
2380
|
+
.lock = .exclusive,
|
|
2381
|
+
.lock_nonblocking = true,
|
|
2382
|
+
}) catch |e| switch (e) {
|
|
2383
|
+
error.FileNotFound => return,
|
|
2384
|
+
error.WouldBlock => continue, // Can not be from
|
|
2385
|
+
// the crashed instance since it is still locked.
|
|
2386
|
+
else => return step.fail("failed to open file '{f}{s}': {t}", .{
|
|
2387
|
+
b.cache_root, in_name, e,
|
|
2388
|
+
}),
|
|
2389
|
+
};
|
|
2390
|
+
|
|
2391
|
+
in_r = in_f.readerStreaming(io, &in_r_buf);
|
|
2392
|
+
const header = in_r.interface.takeStruct(InputHeader, .little) catch |e| {
|
|
2393
|
+
in_f.close(io);
|
|
2394
|
+
switch (e) {
|
|
2395
|
+
error.ReadFailed => return step.fail("failed to read file '{f}{s}': {t}", .{
|
|
2396
|
+
b.cache_root, in_name, in_r.err.?,
|
|
2397
|
+
}),
|
|
2398
|
+
error.EndOfStream => continue,
|
|
2399
|
+
}
|
|
2400
|
+
};
|
|
2401
|
+
|
|
2402
|
+
if (header.pc_digest == f.coverage_id.? and
|
|
2403
|
+
header.instance_id == id and
|
|
2404
|
+
header.test_i < f.run.fuzz_tests.items.len)
|
|
2405
|
+
{
|
|
2406
|
+
break header;
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
in_f.close(io);
|
|
2410
|
+
if (i == std.math.maxInt(u32)) return;
|
|
2411
|
+
i += 1;
|
|
2412
|
+
};
|
|
2413
|
+
defer in_f.close(io);
|
|
2414
|
+
|
|
2415
|
+
// Save it to a seperate file
|
|
2416
|
+
const crash_name = "f" ++ Io.Dir.path.sep_str ++ "crash";
|
|
2417
|
+
const out = b.cache_root.handle.createFile(io, crash_name, .{
|
|
2418
|
+
.lock = .exclusive, // Multiple run steps could have found a crash at the same time
|
|
2419
|
+
}) catch |e| return step.fail("failed to create file '{f}{s}': {t}", .{
|
|
2420
|
+
b.cache_root, crash_name, e,
|
|
2421
|
+
});
|
|
2422
|
+
defer out.close(io);
|
|
2423
|
+
|
|
2424
|
+
var out_w_buf: [512]u8 = undefined;
|
|
2425
|
+
var out_w = out.writerStreaming(io, &out_w_buf);
|
|
2426
|
+
_ = out_w.interface.sendFileAll(&in_r, .limited(header.len)) catch |e| switch (e) {
|
|
2427
|
+
error.ReadFailed => return step.fail("failed to read file '{f}{s}': {t}", .{
|
|
2428
|
+
b.cache_root, in_name, in_r.err.?,
|
|
2429
|
+
}),
|
|
2430
|
+
error.WriteFailed => return step.fail("failed to write file '{f}{s}': {t}", .{
|
|
2431
|
+
b.cache_root, crash_name, out_w.err.?,
|
|
2432
|
+
}),
|
|
2433
|
+
};
|
|
2434
|
+
|
|
2435
|
+
return f.run.step.fail("test '{s}' {f}; input saved to '{f}{s}'", .{
|
|
2436
|
+
f.run.fuzz_tests.items[header.test_i],
|
|
2437
|
+
fmtTerm(term),
|
|
2438
|
+
b.cache_root,
|
|
2439
|
+
crash_name,
|
|
2440
|
+
});
|
|
2441
|
+
}
|
|
2442
|
+
|
|
2443
|
+
fn instanceBroadcast(f: *FuzzTestRunner, from_id: u32, bytes: []const u8) !void {
|
|
2444
|
+
assert(f.instances.len > 1);
|
|
2445
|
+
assert(f.broadcast_undelivered == 0); // no other broadcast is progress
|
|
2446
|
+
assert(f.broadcast.items.len == 0);
|
|
2447
|
+
assert(from_id < f.instances.len);
|
|
2448
|
+
|
|
2449
|
+
const step_owner = f.run.step.owner;
|
|
2450
|
+
const gpa = step_owner.allocator;
|
|
2451
|
+
|
|
2452
|
+
var out_header: OutHeader = .{
|
|
2453
|
+
.tag = .new_fuzz_input,
|
|
2454
|
+
.bytes_len = @intCast(bytes.len),
|
|
2455
|
+
};
|
|
2456
|
+
if (std.builtin.Endian.native != .little) {
|
|
2457
|
+
std.mem.byteSwapAllFields(OutHeader, &out_header);
|
|
2458
|
+
}
|
|
2459
|
+
try f.broadcast.ensureTotalCapacity(gpa, @sizeOf(OutHeader) + bytes.len);
|
|
2460
|
+
f.broadcast.appendSliceAssumeCapacity(@ptrCast(&out_header));
|
|
2461
|
+
f.broadcast.appendSliceAssumeCapacity(bytes);
|
|
2462
|
+
|
|
2463
|
+
f.broadcast_undelivered = @intCast(f.instances.len - 1);
|
|
2464
|
+
for (0.., f.instances) |to_id, *instance| {
|
|
2465
|
+
if (to_id == from_id) continue;
|
|
2466
|
+
instance.broadcast_written = 0;
|
|
2467
|
+
f.addStdinWrite(@intCast(to_id));
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
fn broadcastComplete(f: *FuzzTestRunner) !void {
|
|
2472
|
+
assert(f.instances.len > 1);
|
|
2473
|
+
assert(f.broadcast_undelivered == 0);
|
|
2474
|
+
f.broadcast.clearRetainingCapacity();
|
|
2475
|
+
|
|
2476
|
+
const pending = &f.pending_broadcasts;
|
|
2477
|
+
if (pending.items.len != 0) {
|
|
2478
|
+
// Another broadcast is pending; copy it over to `broadcast`
|
|
2479
|
+
|
|
2480
|
+
const footer_len = @sizeOf(PendingBroadcastFooter);
|
|
2481
|
+
const footer_bytes = pending.items[pending.items.len - footer_len ..];
|
|
2482
|
+
const footer: *align(1) PendingBroadcastFooter = @ptrCast(footer_bytes);
|
|
2483
|
+
pending.items.len -= footer_len;
|
|
2484
|
+
|
|
2485
|
+
const body = pending.items[pending.items.len - footer.body_len ..];
|
|
2486
|
+
try f.instanceBroadcast(footer.from_id, body);
|
|
2487
|
+
pending.items.len -= body.len;
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
fn mergedStderr(f: *FuzzTestRunner) std.mem.Allocator.Error![]const u8 {
|
|
2492
|
+
const step_owner = f.run.step.owner;
|
|
2493
|
+
const arena = step_owner.allocator;
|
|
2494
|
+
|
|
2495
|
+
// Collect any remaining stderr
|
|
2496
|
+
while (f.batch.next()) |completion| {
|
|
2497
|
+
if (completion.index % 3 != 2) continue;
|
|
2498
|
+
const len = completion.result.file_read_streaming catch continue;
|
|
2499
|
+
f.instances[completion.index / 3].stderr.items.len += len;
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
var stderr_len: usize = 0;
|
|
2503
|
+
for (f.instances) |*instance| stderr_len += instance.stderr.items.len;
|
|
2504
|
+
const stderr = try arena.alloc(u8, stderr_len);
|
|
2505
|
+
|
|
2506
|
+
stderr_len = 0;
|
|
2507
|
+
for (f.instances) |*instance| {
|
|
2508
|
+
@memcpy(stderr[stderr_len..][0..instance.stderr.items.len], instance.stderr.items);
|
|
2509
|
+
stderr_len += instance.stderr.items.len;
|
|
2510
|
+
}
|
|
2511
|
+
return stderr;
|
|
2512
|
+
}
|
|
2513
|
+
};
|
|
2514
|
+
|
|
2515
|
+
fn evalFuzzTest(
|
|
2516
|
+
run: *Run,
|
|
2517
|
+
spawn_options: process.SpawnOptions,
|
|
2518
|
+
options: Step.MakeOptions,
|
|
2519
|
+
fuzz_context: FuzzContext,
|
|
2520
|
+
) !void {
|
|
2521
|
+
var f: FuzzTestRunner = try .init(run, fuzz_context, options.progress_node, spawn_options);
|
|
2522
|
+
defer f.deinit();
|
|
2523
|
+
try f.startInstances();
|
|
2524
|
+
try f.listen();
|
|
2074
2525
|
}
|
|
2075
2526
|
|
|
2076
2527
|
const TestMetadata = struct {
|
|
@@ -2149,30 +2600,41 @@ fn sendRunTestMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag, in
|
|
|
2149
2600
|
fn sendRunFuzzTestMessage(
|
|
2150
2601
|
io: Io,
|
|
2151
2602
|
file: Io.File,
|
|
2152
|
-
|
|
2603
|
+
test_names: []const []const u8,
|
|
2153
2604
|
kind: std.Build.abi.fuzz.LimitKind,
|
|
2154
2605
|
amount_or_instance: u64,
|
|
2155
2606
|
) !void {
|
|
2156
2607
|
const header: std.zig.Client.Message.Header = .{
|
|
2157
2608
|
.tag = .start_fuzzing,
|
|
2158
|
-
.bytes_len =
|
|
2609
|
+
.bytes_len = 1 + 8 + 4 + count: {
|
|
2610
|
+
var c: u32 = @intCast(test_names.len * 4);
|
|
2611
|
+
for (test_names) |name| {
|
|
2612
|
+
c += @intCast(name.len);
|
|
2613
|
+
}
|
|
2614
|
+
break :count c;
|
|
2615
|
+
},
|
|
2159
2616
|
};
|
|
2160
2617
|
var w = file.writerStreaming(io, &.{});
|
|
2161
2618
|
w.interface.writeStruct(header, .little) catch |err| switch (err) {
|
|
2162
2619
|
error.WriteFailed => return w.err.?,
|
|
2163
2620
|
};
|
|
2164
|
-
w.interface.writeInt(u32, @intCast(test_name.len), .little) catch |err| switch (err) {
|
|
2165
|
-
error.WriteFailed => return w.err.?,
|
|
2166
|
-
};
|
|
2167
|
-
w.interface.writeAll(test_name) catch |err| switch (err) {
|
|
2168
|
-
error.WriteFailed => return w.err.?,
|
|
2169
|
-
};
|
|
2170
2621
|
w.interface.writeByte(@intFromEnum(kind)) catch |err| switch (err) {
|
|
2171
2622
|
error.WriteFailed => return w.err.?,
|
|
2172
2623
|
};
|
|
2173
2624
|
w.interface.writeInt(u64, amount_or_instance, .little) catch |err| switch (err) {
|
|
2174
2625
|
error.WriteFailed => return w.err.?,
|
|
2175
2626
|
};
|
|
2627
|
+
w.interface.writeInt(u32, @intCast(test_names.len), .little) catch |err| switch (err) {
|
|
2628
|
+
error.WriteFailed => return w.err.?,
|
|
2629
|
+
};
|
|
2630
|
+
for (test_names) |test_name| {
|
|
2631
|
+
w.interface.writeInt(u32, @intCast(test_name.len), .little) catch |err| switch (err) {
|
|
2632
|
+
error.WriteFailed => return w.err.?,
|
|
2633
|
+
};
|
|
2634
|
+
w.interface.writeAll(test_name) catch |err| switch (err) {
|
|
2635
|
+
error.WriteFailed => return w.err.?,
|
|
2636
|
+
};
|
|
2637
|
+
}
|
|
2176
2638
|
}
|
|
2177
2639
|
|
|
2178
2640
|
fn evalGeneric(run: *Run, spawn_options: process.SpawnOptions) !EvalGenericResult {
|