eda033ff9b
Addresses errcheck, gosec, revive, staticcheck, and unused findings
across the codebase (unchecked error returns, unsafe file inclusion
warnings on operator/test-controlled paths, missing package comments,
unused parameters, deprecated API usage). Also fixes two suppression
comments that were silently no-ops due to wrong syntax (#nosec needs
a leading '#', nolint reasons need '//' not '--').
With the backlog clear, drop continue-on-error from the CI lint job
per the plan left in b4b4806.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
222 lines
6.4 KiB
Go
222 lines
6.4 KiB
Go
package logging
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestNew_TextFormat(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "text.log")
|
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error opening file: %v", err)
|
|
}
|
|
defer func() { _ = file.Close() }()
|
|
|
|
logger := New(InfoLevel, file)
|
|
logger.Info("hello world")
|
|
|
|
data, err := os.ReadFile(path) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("failed to read log file: %v", err)
|
|
}
|
|
out := string(data)
|
|
|
|
if !strings.Contains(out, "hello world") {
|
|
t.Fatalf("expected output to contain message, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "level=INFO") {
|
|
t.Fatalf("expected text output to contain level=INFO, got: %q", out)
|
|
}
|
|
if json.Valid(data) {
|
|
t.Fatalf("expected non-JSON text output, got JSON: %q", out)
|
|
}
|
|
}
|
|
|
|
func TestNewFromConfig_JSONOutput(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "json.log")
|
|
|
|
logger, err := NewFromConfig("info", path)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
logger.Info("structured message")
|
|
|
|
data, err := os.ReadFile(path) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("failed to read log file: %v", err)
|
|
}
|
|
|
|
var payload map[string]interface{}
|
|
if err := json.Unmarshal(data, &payload); err != nil {
|
|
t.Fatalf("expected valid JSON output, got error %v; output: %q", err, string(data))
|
|
}
|
|
|
|
if payload["msg"] != "structured message" {
|
|
t.Fatalf("expected msg field to equal message, got: %v", payload["msg"])
|
|
}
|
|
if payload["level"] != "INFO" {
|
|
t.Fatalf("expected level field INFO, got: %v", payload["level"])
|
|
}
|
|
timeVal, ok := payload["time"].(string)
|
|
if !ok {
|
|
t.Fatalf("expected time field to be a string, got: %v", payload["time"])
|
|
}
|
|
if _, err := time.Parse(time.RFC3339, timeVal); err != nil {
|
|
t.Fatalf("expected time field to be RFC3339, got %q: %v", timeVal, err)
|
|
}
|
|
}
|
|
|
|
func TestLevelFiltering_DebugSuppressedAtInfo(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "level.log")
|
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error opening file: %v", err)
|
|
}
|
|
defer func() { _ = file.Close() }()
|
|
|
|
logger := New(InfoLevel, file)
|
|
logger.Debug("should not appear")
|
|
logger.Info("should appear")
|
|
|
|
data, err := os.ReadFile(path) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("failed to read log file: %v", err)
|
|
}
|
|
out := string(data)
|
|
|
|
if strings.Contains(out, "should not appear") {
|
|
t.Fatalf("expected debug message to be suppressed, got: %q", out)
|
|
}
|
|
if !strings.Contains(out, "should appear") {
|
|
t.Fatalf("expected info message to be present, got: %q", out)
|
|
}
|
|
}
|
|
|
|
func TestNewFromOptions_FileOutput(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "out.log")
|
|
|
|
logger, err := NewFromOptions("info", "json", path)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
logger.Info("file message")
|
|
|
|
data, err := os.ReadFile(path) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("failed to read log file: %v", err)
|
|
}
|
|
|
|
var payload map[string]interface{}
|
|
if err := json.Unmarshal(data, &payload); err != nil {
|
|
t.Fatalf("expected valid JSON in file, got error %v; contents: %q", err, string(data))
|
|
}
|
|
if payload["msg"] != "file message" {
|
|
t.Fatalf("expected msg field, got: %v", payload["msg"])
|
|
}
|
|
}
|
|
|
|
func TestNewFromOptions_FormatSelection(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
jsonPath := filepath.Join(dir, "json.log")
|
|
jsonLogger, err := NewFromOptions("info", "json", jsonPath)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
jsonLogger.Info("json message")
|
|
|
|
jsonData, err := os.ReadFile(jsonPath) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("failed to read json log file: %v", err)
|
|
}
|
|
if !json.Valid(jsonData) {
|
|
t.Fatalf("expected valid JSON, got: %q", string(jsonData))
|
|
}
|
|
|
|
textPath := filepath.Join(dir, "text.log")
|
|
textLogger, err := NewFromOptions("info", "text", textPath)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
textLogger.Info("text message")
|
|
|
|
textData, err := os.ReadFile(textPath) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("failed to read text log file: %v", err)
|
|
}
|
|
if json.Valid(textData) {
|
|
t.Fatalf("expected non-JSON text output, got: %q", string(textData))
|
|
}
|
|
if !strings.Contains(string(textData), `msg="text message"`) {
|
|
t.Fatalf("expected text output to contain msg attribute, got: %q", string(textData))
|
|
}
|
|
|
|
// Default format ("" -> json) via NewFromOptions.
|
|
defaultPath := filepath.Join(dir, "default.log")
|
|
defaultLogger, err := NewFromOptions("info", "", defaultPath)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
defaultLogger.Info("default message")
|
|
|
|
defaultData, err := os.ReadFile(defaultPath) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("failed to read default log file: %v", err)
|
|
}
|
|
if !json.Valid(defaultData) {
|
|
t.Fatalf("expected empty format to default to JSON, got: %q", string(defaultData))
|
|
}
|
|
|
|
// NewFromConfig should also default to JSON.
|
|
configPath := filepath.Join(dir, "config.log")
|
|
configLogger, err := NewFromConfig("info", configPath)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
configLogger.Info("config message")
|
|
|
|
configData, err := os.ReadFile(configPath) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("failed to read config log file: %v", err)
|
|
}
|
|
if !json.Valid(configData) {
|
|
t.Fatalf("expected NewFromConfig to default to JSON format, got: %q", string(configData))
|
|
}
|
|
}
|
|
|
|
func TestSlogAccessor(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "slog.log")
|
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error opening file: %v", err)
|
|
}
|
|
defer func() { _ = file.Close() }()
|
|
|
|
logger := New(InfoLevel, file)
|
|
if logger.Slog() == nil {
|
|
t.Fatal("expected Slog() to return a non-nil *slog.Logger")
|
|
}
|
|
|
|
logger.Slog().Info("via slog accessor")
|
|
|
|
data, err := os.ReadFile(path) //nolint:gosec // path is from t.TempDir()
|
|
if err != nil {
|
|
t.Fatalf("failed to read log file: %v", err)
|
|
}
|
|
if !strings.Contains(string(data), "via slog accessor") {
|
|
t.Fatalf("expected message logged via Slog() accessor, got: %q", string(data))
|
|
}
|
|
}
|