Ctrl K
ComunidadGuías…

bldr/util/logfile/autodefault_test.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package logfile

import (
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/sirupsen/logrus"
)

// withEnvUnset clears key for the duration of the test, restoring it on
// cleanup if it was set originally.
func withEnvUnset(t *testing.T, key string) {
	t.Helper()
	prev, had := os.LookupEnv(key)
	if err := os.Unsetenv(key); err != nil {
		t.Fatalf("unsetenv %s: %v", key, err)
	}
	t.Cleanup(func() {
		if had {
			_ = os.Setenv(key, prev)
		} else {
			_ = os.Unsetenv(key)
		}
	})
}

func TestBuildAutoDefaultSpec_Unset(t *testing.T) {
	// Resolve a default log destination with explicit configuration absent.
	withEnvUnset(t, AutoDefaultEnvVar)
	now := time.Date(2026, 5, 4, 12, 30, 0, 0, time.UTC)
	spec, ok := BuildAutoDefaultSpec("/tmp/storage", now)
	if !ok {
		t.Fatalf("expected auto-default to fire when env unset")
	}

	// Verify the default log level, format, and expanded timestamp path.
	if spec.Level != logrus.DebugLevel {
		t.Errorf("level = %v, want DEBUG", spec.Level)
	}
	if spec.Format != "text" {
		t.Errorf("format = %q, want text", spec.Format)
	}
	want := filepath.Join("/tmp/storage", "logs", "20260504-123000.log")
	if spec.Path != want {
		t.Errorf("path = %q, want %q", spec.Path, want)
	}
}

func TestBuildAutoDefaultSpec_Set(t *testing.T) {
	t.Setenv(AutoDefaultEnvVar, "level=WARN;path=/tmp/foo.log")
	if _, ok := BuildAutoDefaultSpec("/tmp/storage", time.Now()); ok {
		t.Errorf("auto-default should not fire when BLDR_LOG_FILE is set")
	}
}

func TestBuildAutoDefaultSpec_None(t *testing.T) {
	t.Setenv(AutoDefaultEnvVar, "none")
	if _, ok := BuildAutoDefaultSpec("/tmp/storage", time.Now()); ok {
		t.Errorf("auto-default should not fire when BLDR_LOG_FILE=none")
	}
}

func TestBuildAutoDefaultSpec_EmptyString(t *testing.T) {
	t.Setenv(AutoDefaultEnvVar, "")
	if _, ok := BuildAutoDefaultSpec("/tmp/storage", time.Now()); !ok {
		t.Errorf("auto-default should fire when BLDR_LOG_FILE=''")
	}
}

func TestBuildAutoDefaultSpec_BlankString(t *testing.T) {
	t.Setenv(AutoDefaultEnvVar, "   ")
	if _, ok := BuildAutoDefaultSpec("/tmp/storage", time.Now()); !ok {
		t.Errorf("auto-default should fire when BLDR_LOG_FILE is blank")
	}
}

func TestBuildAutoDefaultSpec_EmptyRoot(t *testing.T) {
	withEnvUnset(t, AutoDefaultEnvVar)
	if _, ok := BuildAutoDefaultSpec("", time.Now()); ok {
		t.Errorf("auto-default should not fire when storage root is empty")
	}
}

func TestResolveLogLevel(t *testing.T) {
	// Define the project and builder log-level precedence.
	const (
		spacewave = "TEST_SPACEWAVE_LOG_LEVEL"
		bldr      = "TEST_BLDR_LOG_LEVEL"
	)
	chain := []string{spacewave, bldr}

	// Verify missing log-level settings use the fallback.
	t.Run("both unset returns fallback", func(t *testing.T) {
		// Clear both log-level settings for the fallback case.
		withEnvUnset(t, spacewave)
		withEnvUnset(t, bldr)

		// Resolve the configured log level.
		got := ResolveLogLevel(chain, logrus.InfoLevel)

		// Verify the resolved level matches the fallback.
		if got != logrus.InfoLevel {
			t.Errorf("got %v, want InfoLevel", got)
		}
	})

	// Verify the project log-level setting takes precedence.
	t.Run("project-prefixed wins over BLDR_", func(t *testing.T) {
		// Configure competing project and builder log levels.
		t.Setenv(spacewave, "warn")
		t.Setenv(bldr, "debug")

		// Resolve the configured log level.
		got := ResolveLogLevel(chain, logrus.InfoLevel)

		// Verify the resolved level matches the project or builder warning setting.
		if got != logrus.WarnLevel {
			t.Errorf("got %v, want WarnLevel", got)
		}
	})

	// Verify the builder setting applies when the project setting is absent.
	t.Run("falls through to BLDR_ when project unset", func(t *testing.T) {
		// Configure only the builder log level.
		withEnvUnset(t, spacewave)
		t.Setenv(bldr, "debug")

		// Resolve the configured log level.
		got := ResolveLogLevel(chain, logrus.InfoLevel)

		// Verify the resolved level matches the builder debug setting.
		if got != logrus.DebugLevel {
			t.Errorf("got %v, want DebugLevel", got)
		}
	})

	// Verify an invalid project setting permits the builder fallback.
	t.Run("invalid value falls through", func(t *testing.T) {
		// Configure an invalid project level and a valid builder level.
		t.Setenv(spacewave, "not-a-level")
		t.Setenv(bldr, "warn")

		// Resolve the configured log level.
		got := ResolveLogLevel(chain, logrus.InfoLevel)

		// Verify the resolved level matches the project or builder warning setting.
		if got != logrus.WarnLevel {
			t.Errorf("got %v, want WarnLevel", got)
		}
	})

	// Verify a blank project setting permits the builder fallback.
	t.Run("blank value skipped", func(t *testing.T) {
		// Configure a blank project level and a valid builder level.
		t.Setenv(spacewave, "   ")
		t.Setenv(bldr, "error")

		// Resolve the configured log level.
		got := ResolveLogLevel(chain, logrus.InfoLevel)

		// Verify the resolved level matches the builder error setting.
		if got != logrus.ErrorLevel {
			t.Errorf("got %v, want ErrorLevel", got)
		}
	})
}

func TestResolveRetention(t *testing.T) {
	tests := []struct {
		name     string
		raw      string
		wantDur  time.Duration
		wantWarn bool
	}{
		{"unset", "", DefaultRetention, false},
		{"blank", "   ", DefaultRetention, false},
		{"valid 1", "1", 24 * time.Hour, false},
		{"valid 14", "14", 14 * 24 * time.Hour, false},
		{"zero", "0", DefaultRetention, false},
		{"negative", "-3", DefaultRetention, false},
		{"non-numeric", "hello", DefaultRetention, true},
		{"trailing units", "7d", DefaultRetention, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			dur, warn := ResolveRetention("SPACEWAVE_LOG_RETENTION_DAYS", tt.raw)
			if dur != tt.wantDur {
				t.Errorf("dur = %v, want %v", dur, tt.wantDur)
			}
			if (warn != "") != tt.wantWarn {
				t.Errorf("warn = %q, want non-empty=%v", warn, tt.wantWarn)
			}
		})
	}
}