tiny.profiling.host.coverage
Defined in host.
API (10)
Actions
Public operations.
Types and contracts
Public types and contracts.
Values and defaults
Public values and defaults.
Source
Source: src/profiling/host/coverage.zig
zig
const std = @import("std");const capture = @import("capture");const sys = @import("sys");const root = @import("root.zig");pub const tool = "kcov";pub const kind = "source_coverage";pub const directory_name = "coverage";pub const summary_name = "coverage.summary.json";pub const lines_name = "coverage.lines.jsonl";const include_dirs = [_][]const u8{ "src", "lib", "tools", "fun", "research", "verification", "build",};pub const Options = struct {};pub const Lane = struct { directory_path: []const u8, summary_path: []const u8, lines_path: []const u8,};pub fn plan(allocator: std.mem.Allocator, options: Options, workload_root: []const u8) !Lane { _ = options; return .{ .directory_path = try std.fs.path.join(allocator, &.{ workload_root, directory_name }), .summary_path = try std.fs.path.join(allocator, &.{ workload_root, summary_name }), .lines_path = try std.fs.path.join(allocator, &.{ workload_root, lines_name }), };}pub fn wrapArgv(allocator: std.mem.Allocator, options: Options, argv: []const []const u8, lane: Lane) ![]const []const u8 { _ = options; const include_arg = try includePathArg(allocator); const wrapped = try allocator.alloc([]const u8, argv.len + 4); wrapped[0] = tool; wrapped[1] = "--clean"; wrapped[2] = include_arg; wrapped[3] = lane.directory_path; for (argv, 0..) |arg, index| wrapped[index + 4] = arg; return wrapped;}pub fn summarize( allocator: std.mem.Allocator, lane: Lane, exit_code: i64, stderr_path: []const u8, tool_available: bool, workload_name: []const u8,) !root.Capture { if (!tool_available) return missingTool(lane); const cov_xml = findCovXml(allocator, lane.directory_path) catch |err| switch (err) { error.FileNotFound => return try failed(allocator, lane, exit_code, stderr_path), else => |actual| return actual, }; const summary = try capture.coverage.parseCoberturaFile(allocator, cov_xml); if (summary.instrumented_lines == 0) return try failed(allocator, lane, exit_code, stderr_path); try capture.coverage.writeLinesJsonlFile(lane.lines_path, summary, workload_name); try capture.coverage.writeSummaryFile(lane.summary_path, summary, lines_name); return .{ .kind = kind, .tool = tool, .capture_path = cov_xml, .summary_path = lane.summary_path, .state = "summary_written", };}fn includePathArg(allocator: std.mem.Allocator) ![]const u8 { const cwd = try sys.fs.cwdAlloc(allocator); var out: std.Io.Writer.Allocating = .init(allocator); errdefer out.deinit(); try out.writer.writeAll("--include-path="); for (include_dirs, 0..) |dir, index| { if (index != 0) try out.writer.writeByte(','); const path = try std.fs.path.join(allocator, &.{ cwd, dir }); try out.writer.writeAll(path); } return try out.toOwnedSlice();}fn findCovXml(allocator: std.mem.Allocator, directory: []const u8) anyerror![]const u8 { const entries = try sys.fs.listDirAlloc(allocator, directory); defer sys.fs.freeEntries(allocator, entries); for (entries) |entry| { if (entry.kind == .file and std.mem.eql(u8, entry.name, "cov.xml")) return try allocator.dupe(u8, entry.path); } for (entries) |entry| { if (entry.kind != .directory) continue; if (findCovXml(allocator, entry.path)) |path| return path else |err| switch (err) { error.FileNotFound => {}, else => |actual| return actual, } } return error.FileNotFound;}fn missingTool(lane: Lane) root.Capture { return .{ .kind = kind, .tool = tool, .capture_path = lane.directory_path, .summary_path = lane.summary_path, .state = "tool_missing", .caveat_kind = "tool_unavailable", .caveat_message = "kcov is not runnable on this host; source-line coverage was not captured", };}fn failed(allocator: std.mem.Allocator, lane: Lane, exit_code: i64, stderr_path: []const u8) !root.Capture { const row = try capture.caveat.classifyCommandCapture(allocator, .{ .phase = kind, .exit_code = if (exit_code == 0) 1 else exit_code, .timed_out = false, .capture_path = stderr_path, }) orelse capture.caveat.classifyCommandText(.{ .phase = kind, .exit_code = exit_code, .timed_out = false, .capture_path = stderr_path, }, ""); return .{ .kind = kind, .tool = tool, .capture_path = lane.directory_path, .summary_path = lane.summary_path, .state = "tool_failed", .caveat_kind = row.kind, .caveat_message = row.message, };}test "profiling coverage wraps workload argv in kcov" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); const lane = try plan(allocator, .{}, "zig-out/profiling/run/workloads/w"); const argv = [_][]const u8{ "zig-out/bin/w-bench", "--x" }; const wrapped = try wrapArgv(allocator, .{}, &argv, lane); try std.testing.expectEqualStrings("kcov", wrapped[0]); try std.testing.expectEqualStrings("--clean", wrapped[1]); try std.testing.expect(std.mem.startsWith(u8, wrapped[2], "--include-path=")); try std.testing.expectEqualStrings("zig-out/profiling/run/workloads/w/coverage", wrapped[3]); try std.testing.expectEqualStrings("zig-out/bin/w-bench", wrapped[4]);}test "profiling coverage summarizes a kcov directory" { var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const allocator = arena_state.allocator(); const dir = try std.fs.path.join(allocator, &.{ ".zig-cache", "tmp", tmp.sub_path[0..] }); const lane = try plan(allocator, .{}, dir); const nested = try std.fs.path.join(allocator, &.{ lane.directory_path, "bench.abc" }); try sys.fs.createDirPath(nested); const cov_xml = try std.fs.path.join(allocator, &.{ nested, "cov.xml" }); try sys.fs.writeFile(cov_xml, \\<coverage> \\ <sources><source>/repo/</source></sources> \\ <class name="a" filename="src/a.zig"><lines> \\ <line number="1" hits="1"/> \\ </lines></class> \\</coverage> ); const stderr_path = try std.fs.path.join(allocator, &.{ dir, "stderr.txt" }); try sys.fs.writeFile(stderr_path, ""); const row = try summarize(allocator, lane, 0, stderr_path, true, "w"); try std.testing.expectEqualStrings("summary_written", row.state); try std.testing.expectEqualStrings(cov_xml, row.capture_path); try std.testing.expect(sys.fs.exists(lane.summary_path)); try std.testing.expect(sys.fs.exists(lane.lines_path));}Source: src/profiling/host/root.zig:4
zig
pub const coverage = runtime.coverage;Audit
| Definitions | 11 |
|---|---|
| Public names | 11 |
| Members | 3 |
| Version | 26.7.0 |
| Revision | daab053ee433 |