From 9968f74ae957382d2c4e967564b307dbcc8eeaa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 30 Oct 2026 10:35:54 +0100 Subject: [PATCH] Fix page count underflow for jobs with no completed runs The job status page computes the number of pages as (nRuns-1) / runsPerPage + 1 with nRuns unsigned. A job whose first run is still in progress has no completed builds, so nRuns is 0 and the subtraction wraps, displaying "Page 1 of 214748365". Report a single page in that case, and add a functional test for it. --- src/laminar.cpp | 2 +- test/laminar-functional.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/laminar.cpp b/src/laminar.cpp index e7ecf98..01c0c9c 100644 --- a/src/laminar.cpp +++ b/src/laminar.cpp @@ -307,7 +307,7 @@ std::string Laminar::getStatus(MonitorScope scope) { .bind(scope.job) .fetch([&](uint nRuns, uint averageRuntime){ j.set("averageRuntime", averageRuntime); - j.set("pages", (nRuns-1) / runsPerPage + 1); + j.set("pages", nRuns ? (nRuns-1) / runsPerPage + 1 : 1); j.startObject("sort"); j.set("page", scope.page) .set("field", scope.field) diff --git a/test/laminar-functional.cpp b/test/laminar-functional.cpp index e796d26..20da1ae 100644 --- a/test/laminar-functional.cpp +++ b/test/laminar-functional.cpp @@ -163,6 +163,18 @@ TEST_F(LaminarFixture, JobDescription) { EXPECT_STREQ("bar", data["description"].GetString()); } +TEST_F(LaminarFixture, JobPagesWithoutRuns) { + defineJob("foo", "true"); + auto es = eventSource("/jobs/foo"); + ioContext->waitScope.poll(); + ASSERT_EQ(1, es->messages().size()); + auto json = es->messages().front().GetObject(); + ASSERT_TRUE(json.HasMember("data")); + auto data = json["data"].GetObject(); + ASSERT_TRUE(data.HasMember("pages")); + EXPECT_EQ(1, data["pages"].GetInt()); +} + TEST_F(LaminarFixture, QueueFront) { setNumExecutors(0); defineJob("foo", "true");