mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-07 08:57:12 +00:00
138 lines
3.7 KiB
Go
138 lines
3.7 KiB
Go
package updates
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/rs/zerolog"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
func TestUpdateQueueEnqueueRejectLogsStructuredContext(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
restore := setUpdateQueueTestLogger(&buf)
|
|
defer restore()
|
|
|
|
queue := NewUpdateQueue()
|
|
job, accepted := queue.Enqueue("https://example.com/update1.tar.gz")
|
|
if !accepted || job == nil {
|
|
t.Fatal("expected first enqueue to succeed")
|
|
}
|
|
if !queue.MarkRunning(job.ID) {
|
|
t.Fatal("expected mark running to succeed")
|
|
}
|
|
|
|
buf.Reset()
|
|
|
|
if _, accepted := queue.Enqueue("https://example.com/update2.tar.gz"); accepted {
|
|
t.Fatal("expected second enqueue to be rejected")
|
|
}
|
|
|
|
entry := singleLogEntry(t, buf.String())
|
|
assertLogStringField(t, entry, "component", updatesQueueComponent)
|
|
assertLogStringField(t, entry, "action", "enqueue_rejected")
|
|
assertLogStringField(t, entry, "current_job_id", job.ID)
|
|
assertLogStringField(t, entry, "current_state", string(JobStateRunning))
|
|
assertLogStringField(t, entry, "requested_download_url", "https://example.com/update2.tar.gz")
|
|
}
|
|
|
|
func TestUpdateQueueMarkCompletedFailureLogsStructuredContext(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
restore := setUpdateQueueTestLogger(&buf)
|
|
defer restore()
|
|
|
|
queue := NewUpdateQueue()
|
|
job, accepted := queue.Enqueue("https://example.com/update.tar.gz")
|
|
if !accepted || job == nil {
|
|
t.Fatal("expected enqueue to succeed")
|
|
}
|
|
if !queue.MarkRunning(job.ID) {
|
|
t.Fatal("expected mark running to succeed")
|
|
}
|
|
|
|
buf.Reset()
|
|
|
|
queue.MarkCompleted(job.ID, errors.New("boom"))
|
|
|
|
entry := singleLogEntry(t, buf.String())
|
|
assertLogStringField(t, entry, "component", updatesQueueComponent)
|
|
assertLogStringField(t, entry, "action", "complete_failed")
|
|
assertLogStringField(t, entry, "job_id", job.ID)
|
|
assertLogStringField(t, entry, "job_state", string(JobStateFailed))
|
|
assertLogStringField(t, entry, "error", "boom")
|
|
if _, ok := entry["duration"]; !ok {
|
|
t.Fatal("expected duration field in failure log")
|
|
}
|
|
}
|
|
|
|
func TestUpdateQueueCancelLogsStructuredContext(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
restore := setUpdateQueueTestLogger(&buf)
|
|
defer restore()
|
|
|
|
queue := NewUpdateQueue()
|
|
job, accepted := queue.Enqueue("https://example.com/update.tar.gz")
|
|
if !accepted || job == nil {
|
|
t.Fatal("expected enqueue to succeed")
|
|
}
|
|
if !queue.MarkRunning(job.ID) {
|
|
t.Fatal("expected mark running to succeed")
|
|
}
|
|
|
|
buf.Reset()
|
|
|
|
if !queue.Cancel(job.ID) {
|
|
t.Fatal("expected cancel to succeed")
|
|
}
|
|
|
|
entry := singleLogEntry(t, buf.String())
|
|
assertLogStringField(t, entry, "component", updatesQueueComponent)
|
|
assertLogStringField(t, entry, "action", "cancel")
|
|
assertLogStringField(t, entry, "job_id", job.ID)
|
|
assertLogStringField(t, entry, "previous_state", string(JobStateRunning))
|
|
assertLogStringField(t, entry, "job_state", string(JobStateCancelled))
|
|
}
|
|
|
|
func setUpdateQueueTestLogger(buf *bytes.Buffer) func() {
|
|
original := log.Logger
|
|
log.Logger = zerolog.New(buf).Level(zerolog.DebugLevel)
|
|
return func() {
|
|
log.Logger = original
|
|
}
|
|
}
|
|
|
|
func singleLogEntry(t *testing.T, raw string) map[string]any {
|
|
t.Helper()
|
|
|
|
lines := strings.Split(strings.TrimSpace(raw), "\n")
|
|
if len(lines) != 1 {
|
|
t.Fatalf("expected exactly one log line, got %d: %q", len(lines), raw)
|
|
}
|
|
|
|
var parsed map[string]any
|
|
if err := json.Unmarshal([]byte(lines[0]), &parsed); err != nil {
|
|
t.Fatalf("failed to parse log entry: %v", err)
|
|
}
|
|
return parsed
|
|
}
|
|
|
|
func assertLogStringField(t *testing.T, entry map[string]any, field, want string) {
|
|
t.Helper()
|
|
|
|
raw, ok := entry[field]
|
|
if !ok {
|
|
t.Fatalf("missing field %q in log entry: %+v", field, entry)
|
|
}
|
|
|
|
got, ok := raw.(string)
|
|
if !ok {
|
|
t.Fatalf("field %q has non-string value %#v", field, raw)
|
|
}
|
|
|
|
if got != want {
|
|
t.Fatalf("field %q = %q, want %q", field, got, want)
|
|
}
|
|
}
|