|
3 | 3 | import std; |
4 | 4 | import mcpp.ui; |
5 | 5 | import mcpp.build.progress; |
| 6 | +import mcpp.build.action_progress; |
6 | 7 |
|
7 | 8 | // The build's report (.agents/docs/2026-09-29-build-progress-display-design.md, |
8 | 9 | // revised by .agents/docs/2026-09-30-build-output-refinement-design.md): its |
@@ -331,6 +332,43 @@ TEST(ProgressText, ThePhaseIsAlignedWithTheVerbs) { |
331 | 332 |
|
332 | 333 | // ─── When a package is named (revision 3, §5.3) ────────────────────────── |
333 | 334 |
|
| 335 | +TEST(ProgressModel, AnActionStartLoadsTheFastPathRecordBeforeNinjaWritesStdout) { |
| 336 | + namespace telemetry = mcpp::build::action_progress; |
| 337 | + Tmp tmp; |
| 338 | + Record rec; |
| 339 | + rec.packages = {{"progress-no-stdout", true, "progress-no-stdout", 0, 1, "v0.0.0 (.)", "project"}}; |
| 340 | + rec.owner = {{"gen/check.stamp", 0}}; |
| 341 | + rec.step = {{"gen/check.stamp", 0}}; |
| 342 | + rec.actions = {{"gen/check.stamp", "check-action"}}; |
| 343 | + rec.steps = 1; |
| 344 | + write_record(tmp.path, rec); |
| 345 | + Build build(tmp.path); // The cached path has a record on disk, not set_record(). |
| 346 | + build.pass_begin(); |
| 347 | + const auto env = build.environment(); |
| 348 | + const auto root = std::ranges::find(env, telemetry::kRootEnv, &decltype(env)::value_type::first); |
| 349 | + ASSERT_NE(root, env.end()); |
| 350 | + std::ofstream(telemetry::channel(root->second, "gen/check.stamp")) |
| 351 | + << R"({"v":1,"seq":1,"phase":"internal-check","done":1,"total":2})"; |
| 352 | + const auto unixMs = std::chrono::duration_cast<std::chrono::milliseconds>( |
| 353 | + std::chrono::system_clock::now().time_since_epoch()).count(); |
| 354 | + append(tmp.path / kStartsFile, std::format("gen/check.stamp\t{}\n", unixMs)); |
| 355 | + testing::internal::CaptureStderr(); |
| 356 | + open(false); |
| 357 | + const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2); |
| 358 | + std::string row; |
| 359 | + do { |
| 360 | + row = status_row(); |
| 361 | + if (row.contains("internal-check 1/2")) break; |
| 362 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
| 363 | + } while (std::chrono::steady_clock::now() < deadline); |
| 364 | + close(); |
| 365 | + (void)testing::internal::GetCapturedStderr(); |
| 366 | + EXPECT_TRUE(build.has_record()); |
| 367 | + EXPECT_NE(row.find("check-action"), std::string::npos) << row; |
| 368 | + EXPECT_NE(row.find("internal-check 1/2"), std::string::npos) << row; |
| 369 | + // No Build::status() or completed ninja-log entry was supplied. |
| 370 | +} |
| 371 | + |
334 | 372 | TEST(ProgressModel, APackageIsNamedOnceWhenItsFirstStepFinishes) { |
335 | 373 | mcpp::ui::disable_color(); |
336 | 374 | Tmp tmp; |
|
0 commit comments