| ... | ... | @@ -1539,10 +1539,6 @@ fn runCommand( |
| 1539 | 1539 | } |
| 1540 | 1540 | } |
| 1541 | 1541 | |
| 1542 | | const EvalZigTestResult = struct { |
| 1543 | | test_results: Step.TestResults, |
| 1544 | | test_metadata: ?TestMetadata, |
| 1545 | | }; |
| 1546 | 1542 | const EvalGenericResult = struct { |
| 1547 | 1543 | term: std.process.Child.Term, |
| 1548 | 1544 | stdout: ?[]const u8, |
| ... | ... | @@ -1605,21 +1601,8 @@ fn spawnChildAndCollect( |
| 1605 | 1601 | |
| 1606 | 1602 | if (run.stdio == .zig_test) { |
| 1607 | 1603 | var timer = try std.time.Timer.start(); |
| 1608 | | const res = try evalZigTest(run, &child, options, fuzz_context); |
| 1609 | | run.step.result_duration_ns = timer.read(); |
| 1610 | | run.step.test_results = res.test_results; |
| 1611 | | if (res.test_metadata) |tm| { |
| 1612 | | run.cached_test_metadata = tm.toCachedTestMetadata(); |
| 1613 | | if (options.web_server) |ws| { |
| 1614 | | if (b.graph.time_report) { |
| 1615 | | ws.updateTimeReportRunTest( |
| 1616 | | run, |
| 1617 | | &run.cached_test_metadata.?, |
| 1618 | | tm.ns_per_test, |
| 1619 | | ); |
| 1620 | | } |
| 1621 | | } |
| 1622 | | } |
| 1604 | defer run.step.result_duration_ns = timer.read(); |
| 1605 | try evalZigTest(run, &child, options, fuzz_context); |
| 1623 | 1606 | return null; |
| 1624 | 1607 | } else { |
| 1625 | 1608 | const inherit = child.stdout_behavior == .Inherit or child.stderr_behavior == .Inherit; |
| ... | ... | @@ -1675,7 +1658,7 @@ fn evalZigTest( |
| 1675 | 1658 | child: *std.process.Child, |
| 1676 | 1659 | options: Step.MakeOptions, |
| 1677 | 1660 | fuzz_context: ?FuzzContext, |
| 1678 | | ) !EvalZigTestResult { |
| 1661 | ) !void { |
| 1679 | 1662 | const step_owner = run.step.owner; |
| 1680 | 1663 | const gpa = step_owner.allocator; |
| 1681 | 1664 | const arena = step_owner.allocator; |
| ... | ... | @@ -1684,18 +1667,16 @@ fn evalZigTest( |
| 1684 | 1667 | // We will update this every time a child runs. |
| 1685 | 1668 | run.step.result_peak_rss = 0; |
| 1686 | 1669 | |
| 1687 | | var result: EvalZigTestResult = .{ |
| 1688 | | .test_results = .{ |
| 1689 | | .test_count = 0, |
| 1690 | | .skip_count = 0, |
| 1691 | | .fail_count = 0, |
| 1692 | | .crash_count = 0, |
| 1693 | | .timeout_count = 0, |
| 1694 | | .leak_count = 0, |
| 1695 | | .log_err_count = 0, |
| 1696 | | }, |
| 1697 | | .test_metadata = null, |
| 1670 | var test_results: Step.TestResults = .{ |
| 1671 | .test_count = 0, |
| 1672 | .skip_count = 0, |
| 1673 | .fail_count = 0, |
| 1674 | .crash_count = 0, |
| 1675 | .timeout_count = 0, |
| 1676 | .leak_count = 0, |
| 1677 | .log_err_count = 0, |
| 1698 | 1678 | }; |
| 1679 | var test_metadata: ?TestMetadata = null; |
| 1699 | 1680 | |
| 1700 | 1681 | while (true) { |
| 1701 | 1682 | try child.spawn(io); |
| ... | ... | @@ -1721,8 +1702,8 @@ fn evalZigTest( |
| 1721 | 1702 | options, |
| 1722 | 1703 | fuzz_context, |
| 1723 | 1704 | &poller, |
| 1724 | | &result.test_metadata, |
| 1725 | | &result.test_results, |
| 1705 | &test_metadata, |
| 1706 | &test_results, |
| 1726 | 1707 | )) { |
| 1727 | 1708 | .write_failed => |err| { |
| 1728 | 1709 | // The runner unexpectedly closed a stdio pipe, which means a crash. Make sure we've captured |
| ... | ... | @@ -1741,8 +1722,9 @@ fn evalZigTest( |
| 1741 | 1722 | child.resource_usage_statistics.getMaxRss() orelse 0, |
| 1742 | 1723 | ); |
| 1743 | 1724 | |
| 1744 | | try run.step.addError("unable to write stdin ({t}); test process unexpectedly {f}", .{ err, fmtTerm(term) }); |
| 1745 | | return result; |
| 1725 | // The individual unit test results are irrelevant: the test runner itself broke! |
| 1726 | // Fail immediately without populating `s.test_results`. |
| 1727 | return run.step.fail("unable to write stdin ({t}); test process unexpectedly {f}", .{ err, fmtTerm(term) }); |
| 1746 | 1728 | }, |
| 1747 | 1729 | .no_poll => |no_poll| { |
| 1748 | 1730 | // This might be a success (we requested exit and the child dutifully closed stdout) or |
| ... | ... | @@ -1764,10 +1746,10 @@ fn evalZigTest( |
| 1764 | 1746 | if (no_poll.active_test_index) |test_index| { |
| 1765 | 1747 | // A test was running, so this is definitely a crash. Report it against that |
| 1766 | 1748 | // test, and continue to the next test. |
| 1767 | | result.test_metadata.?.ns_per_test[test_index] = no_poll.ns_elapsed; |
| 1768 | | result.test_results.crash_count += 1; |
| 1749 | test_metadata.?.ns_per_test[test_index] = no_poll.ns_elapsed; |
| 1750 | test_results.crash_count += 1; |
| 1769 | 1751 | try run.step.addError("'{s}' {f}{s}{s}", .{ |
| 1770 | | result.test_metadata.?.testName(test_index), |
| 1752 | test_metadata.?.testName(test_index), |
| 1771 | 1753 | fmtTerm(term), |
| 1772 | 1754 | if (stderr_owned.len != 0) " with stderr:\n" else "", |
| 1773 | 1755 | std.mem.trim(u8, stderr_owned, "\n"), |
| ... | ... | @@ -1777,11 +1759,28 @@ fn evalZigTest( |
| 1777 | 1759 | |
| 1778 | 1760 | // Report an error if the child terminated uncleanly or if we were still trying to run more tests. |
| 1779 | 1761 | run.step.result_stderr = stderr_owned; |
| 1780 | | const tests_done = result.test_metadata != null and result.test_metadata.?.next_index == std.math.maxInt(u32); |
| 1762 | const tests_done = test_metadata != null and test_metadata.?.next_index == std.math.maxInt(u32); |
| 1781 | 1763 | if (!tests_done or !termMatches(.{ .Exited = 0 }, term)) { |
| 1782 | | try run.step.addError("test process unexpectedly {f}", .{fmtTerm(term)}); |
| 1764 | // The individual unit test results are irrelevant: the test runner itself broke! |
| 1765 | // Fail immediately without populating `s.test_results`. |
| 1766 | return run.step.fail("test process unexpectedly {f}", .{fmtTerm(term)}); |
| 1767 | } |
| 1768 | |
| 1769 | // We're done with all of the tests! Commit the test results and return. |
| 1770 | run.step.test_results = test_results; |
| 1771 | if (test_metadata) |tm| { |
| 1772 | run.cached_test_metadata = tm.toCachedTestMetadata(); |
| 1773 | if (options.web_server) |ws| { |
| 1774 | if (run.step.owner.graph.time_report) { |
| 1775 | ws.updateTimeReportRunTest( |
| 1776 | run, |
| 1777 | &run.cached_test_metadata.?, |
| 1778 | tm.ns_per_test, |
| 1779 | ); |
| 1780 | } |
| 1781 | } |
| 1783 | 1782 | } |
| 1784 | | return result; |
| 1783 | return; |
| 1785 | 1784 | }, |
| 1786 | 1785 | .timeout => |timeout| { |
| 1787 | 1786 | const stderr = poller.reader(.stderr).buffered(); |
| ... | ... | @@ -1789,10 +1788,10 @@ fn evalZigTest( |
| 1789 | 1788 | if (timeout.active_test_index) |test_index| { |
| 1790 | 1789 | // A test was running. Report the timeout against that test, and continue on to |
| 1791 | 1790 | // the next test. |
| 1792 | | result.test_metadata.?.ns_per_test[test_index] = timeout.ns_elapsed; |
| 1793 | | result.test_results.timeout_count += 1; |
| 1791 | test_metadata.?.ns_per_test[test_index] = timeout.ns_elapsed; |
| 1792 | test_results.timeout_count += 1; |
| 1794 | 1793 | try run.step.addError("'{s}' timed out after {D}{s}{s}", .{ |
| 1795 | | result.test_metadata.?.testName(test_index), |
| 1794 | test_metadata.?.testName(test_index), |
| 1796 | 1795 | timeout.ns_elapsed, |
| 1797 | 1796 | if (stderr.len != 0) " with stderr:\n" else "", |
| 1798 | 1797 | std.mem.trim(u8, stderr, "\n"), |
| ... | ... | @@ -1801,6 +1800,8 @@ fn evalZigTest( |
| 1801 | 1800 | } |
| 1802 | 1801 | // Just log an error and let the child be killed. |
| 1803 | 1802 | run.step.result_stderr = try arena.dupe(u8, stderr); |
| 1803 | // The individual unit test results in `results` are irrelevant: the test runner |
| 1804 | // is broken! Fail immediately without populating `s.test_results`. |
| 1804 | 1805 | return run.step.fail("test runner failed to respond for {D}", .{timeout.ns_elapsed}); |
| 1805 | 1806 | }, |
| 1806 | 1807 | } |