Skip to content

Commit 1368d02

Browse files
committed
test(core): cover the unschedulable bookkeeping directly
Removing a job clears its recorded refusal, so a job deleted from the config stops holding /health degraded. That path had no test. Also covers that the returned map is a copy, which the health checker reads on every check. Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
1 parent f4fdc2a commit 1368d02

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) 2025-2026 Netresearch DTT GmbH
2+
// SPDX-License-Identifier: MIT
3+
4+
package core
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
// A refused job is remembered so /health can name it. That memory has to end
14+
// when the job does, or an operator who fixed the problem by deleting the job
15+
// would be left with a permanently degraded daemon and no job to blame it on.
16+
17+
func TestSchedulerRecordsRefusedJob(t *testing.T) {
18+
t.Parallel()
19+
20+
job := &TestJob{}
21+
job.Name = "broken"
22+
job.Schedule = "not-a-schedule"
23+
24+
sc := NewScheduler(newDiscardLogger())
25+
require.Error(t, sc.AddJob(job))
26+
27+
refused := sc.GetUnschedulableJobs()
28+
require.Contains(t, refused, "broken")
29+
assert.NotEmpty(t, refused["broken"], "the recorded reason is what makes the report actionable")
30+
}
31+
32+
// TestSchedulerRemoveJobClearsUnschedulable covers the removal half: dropping
33+
// the job from the config has to drop the complaint with it.
34+
func TestSchedulerRemoveJobClearsUnschedulable(t *testing.T) {
35+
t.Parallel()
36+
37+
job := &TestJob{}
38+
job.Name = "broken"
39+
job.Schedule = "not-a-schedule"
40+
41+
sc := NewScheduler(newDiscardLogger())
42+
require.Error(t, sc.AddJob(job))
43+
require.Contains(t, sc.GetUnschedulableJobs(), "broken")
44+
45+
require.NoError(t, sc.RemoveJob(job))
46+
47+
assert.NotContains(t, sc.GetUnschedulableJobs(), "broken",
48+
"a job removed from the config still held /health degraded")
49+
}
50+
51+
// TestSchedulerGetUnschedulableJobsIsACopy pins that callers cannot reach into
52+
// the scheduler's state through the returned map: the health checker reads it
53+
// on every check, and a shared map would be a data race as well as a way to
54+
// silently erase a refusal.
55+
func TestSchedulerGetUnschedulableJobsIsACopy(t *testing.T) {
56+
t.Parallel()
57+
58+
job := &TestJob{}
59+
job.Name = "broken"
60+
job.Schedule = "not-a-schedule"
61+
62+
sc := NewScheduler(newDiscardLogger())
63+
require.Error(t, sc.AddJob(job))
64+
65+
delete(sc.GetUnschedulableJobs(), "broken")
66+
67+
assert.Contains(t, sc.GetUnschedulableJobs(), "broken")
68+
}

0 commit comments

Comments
 (0)