test: delete duplicate-coverage tests, fix TESTS.md drift, drop hand-rolled itoa
Items 1-3 of the 2026-08-04 test-suite review: TestCleanupLogsKeepsFilesWithinAgeLimit, TestRunDueEmptyOverlapInheritsGlobal, and TestSameWindowsPathHandlesSpaces had byte-identical coverage to an existing test and no assertion the survivor lacked. storage.defaultJobs, the one accidental 0% coverage gap the review found, is now covered and TESTS.md corrected to match. seed_test.go's itoa is replaced with strconv.FormatInt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+4
-45
@@ -255,6 +255,10 @@ func TestRunDueQueueRerunsAfterFinish(t *testing.T) {
|
||||
svc := newQueueService(t, domain.ExecutionModeParallel, domain.OverlapPolicyQueue, []domain.Job{
|
||||
{ID: 1, Name: "A", Schedule: "@every 1h", Command: "echo", Enabled: true},
|
||||
})
|
||||
// Empty per-job OverlapPolicy inherits the global queue policy.
|
||||
if svc.jobs[0].OverlapPolicy != "" {
|
||||
t.Fatalf("test setup: job OverlapPolicy = %q, want empty (inherit)", svc.jobs[0].OverlapPolicy)
|
||||
}
|
||||
|
||||
entered := make(chan int, 2)
|
||||
release := make(chan struct{})
|
||||
@@ -451,51 +455,6 @@ func TestRunDuePerJobSkipOverridesGlobalQueue(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestRunDueEmptyOverlapInheritsGlobal verifies that a job with no own policy
|
||||
// inherits the global default: with global "queue" and an empty Job.OverlapPolicy
|
||||
// the job queues a re-run.
|
||||
func TestRunDueEmptyOverlapInheritsGlobal(t *testing.T) {
|
||||
svc := newQueueService(t, domain.ExecutionModeParallel, domain.OverlapPolicyQueue, []domain.Job{
|
||||
{ID: 1, Name: "A", Schedule: "@every 1h", Command: "echo", Enabled: true},
|
||||
})
|
||||
if svc.jobs[0].OverlapPolicy != "" {
|
||||
t.Fatalf("test setup: job OverlapPolicy = %q, want empty (inherit)", svc.jobs[0].OverlapPolicy)
|
||||
}
|
||||
|
||||
entered := make(chan int, 2)
|
||||
release := make(chan struct{})
|
||||
svc.runJob = func(_ context.Context, job *domain.Job, _ string, _ string, _ time.Duration) (domain.RunRecord, error) {
|
||||
entered <- job.ID
|
||||
<-release
|
||||
return domain.RunRecord{Time: "t", JobID: job.ID, JobName: job.Name, State: "Success"}, nil
|
||||
}
|
||||
done := completions(svc)
|
||||
|
||||
primeDue(t, svc, 1)
|
||||
svc.RunDue(time.Now())
|
||||
if id := <-entered; id != 1 {
|
||||
t.Fatalf("started job = %d, want 1", id)
|
||||
}
|
||||
|
||||
primeDue(t, svc, 1)
|
||||
svc.RunDue(time.Now())
|
||||
expectNoEntry(t, entered)
|
||||
|
||||
svc.mu.Lock()
|
||||
pending := svc.runtimes[1].PendingRuns
|
||||
svc.mu.Unlock()
|
||||
if pending != 1 {
|
||||
t.Fatalf("empty per-job policy must inherit global queue, PendingRuns = %d", pending)
|
||||
}
|
||||
|
||||
close(release)
|
||||
waitRecord(t, done)
|
||||
if id := <-entered; id != 1 {
|
||||
t.Fatalf("inherited-queue re-run job = %d, want 1", id)
|
||||
}
|
||||
waitRecord(t, done)
|
||||
}
|
||||
|
||||
// TestRunNowSequentialGuard verifies the sequential-mode guard in RunNow: a manual
|
||||
// run is refused while another job is running, and allowed once nothing is.
|
||||
func TestRunNowSequentialGuard(t *testing.T) {
|
||||
|
||||
@@ -12,14 +12,8 @@ import (
|
||||
)
|
||||
|
||||
func TestSameWindowsPathIgnoresCaseAndQuotes(t *testing.T) {
|
||||
if !sameWindowsPath(`"D:\Apps\GoSentry\gosentry.exe"`, `d:\apps\gosentry\gosentry.exe`) {
|
||||
t.Fatal("expected paths to match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSameWindowsPathHandlesSpaces(t *testing.T) {
|
||||
if !sameWindowsPath(`"D:\Local Git\GoSentry\gosentry.exe"`, `d:\local git\gosentry\gosentry.exe`) {
|
||||
t.Fatal("expected paths with spaces to match")
|
||||
t.Fatal("expected paths to match")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,22 +50,6 @@ func TestCleanupLogsRemovesFilesPastMaxAge(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanupLogsKeepsFilesWithinAgeLimit(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
for i := 1; i <= 3; i++ {
|
||||
path := writeLogFile(t, dir, fmt.Sprintf("job_%d.log", i))
|
||||
setModTime(t, path, time.Duration(i)*24*time.Hour)
|
||||
}
|
||||
|
||||
if err := CleanupLogs(dir, 100, 30); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
entries, _ := os.ReadDir(dir)
|
||||
if len(entries) != 3 {
|
||||
t.Errorf("expected 3 files kept within age limit, got %d", len(entries))
|
||||
}
|
||||
}
|
||||
|
||||
// TestCleanupLogsByCountDeletesOldest verifies the count-based policy: when more
|
||||
// than maxFiles log files exist the oldest (by modification time) are removed.
|
||||
// maxAgeDays=0 disables age-based cleanup so the test exercises count only.
|
||||
|
||||
+1
-20
@@ -22,7 +22,7 @@ func writeTestLog(t *testing.T, dir, filename, state string, durationMS int64, j
|
||||
content.WriteString("\n")
|
||||
}
|
||||
if durationMS >= 0 {
|
||||
content.WriteString("state: " + state + "\nduration: " + itoa(durationMS) + "\n\n")
|
||||
content.WriteString("state: " + state + "\nduration: " + strconv.FormatInt(durationMS, 10) + "\n\n")
|
||||
} else {
|
||||
content.WriteString("state: " + state + "\n\n")
|
||||
}
|
||||
@@ -31,25 +31,6 @@ func writeTestLog(t *testing.T, dir, filename, state string, durationMS int64, j
|
||||
}
|
||||
}
|
||||
|
||||
func itoa(n int64) string {
|
||||
if n == 0 {
|
||||
return "0"
|
||||
}
|
||||
neg := n < 0
|
||||
if neg {
|
||||
n = -n
|
||||
}
|
||||
buf := make([]byte, 0, 20)
|
||||
for n > 0 {
|
||||
buf = append([]byte{byte('0' + n%10)}, buf...)
|
||||
n /= 10
|
||||
}
|
||||
if neg {
|
||||
buf = append([]byte{'-'}, buf...)
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
func TestSeedStatsBasic(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
job := domain.Job{ID: 1, Name: "Build"}
|
||||
|
||||
@@ -183,6 +183,41 @@ func TestLoadOrCreateConfigCreatesDefaultsOnFirstRun(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoadOrCreateJobsSeedsSampleJobsOnFirstRun verifies that a missing
|
||||
// jobs.json is created with the sample jobs from defaultJobs, so a new user
|
||||
// sees scheduled and manual execution without inventing a command.
|
||||
func TestLoadOrCreateJobsSeedsSampleJobsOnFirstRun(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "jobs.json")
|
||||
|
||||
got, err := loadOrCreateJobs(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := defaultJobs()
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("got %d jobs, want %d", len(got), len(want))
|
||||
}
|
||||
for i := range want {
|
||||
if got[i].Name != want[i].Name || got[i].Schedule != want[i].Schedule || got[i].Command != want[i].Command || got[i].Enabled != want[i].Enabled {
|
||||
t.Errorf("job %d = %+v, want %+v", i, got[i], want[i])
|
||||
}
|
||||
}
|
||||
|
||||
// The function must have written the seeded jobs to jobs.json.
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("jobs.json should have been created: %v", err)
|
||||
}
|
||||
var file domain.JobsFile
|
||||
if err := json.Unmarshal(data, &file); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(file.Jobs) != len(want) {
|
||||
t.Errorf("jobs.json has %d jobs, want %d", len(file.Jobs), len(want))
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoadOrCreateConfigMigratesLegacyThemeDefault covers a gosentry.json that
|
||||
// still stores the retired "default" theme value: load normalizes it to system.
|
||||
func TestLoadOrCreateConfigMigratesLegacyThemeDefault(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user