package app import ( "bufio" "context" "flag" "io" "os" "regexp" "testing" "github.com/rs/zerolog" "gitea.libretechconsulting.com/rmcguire/go-app/pkg/config" ) func TestMustSetupConfigAndLogging(t *testing.T) { // Configure app and logger type inputs struct { envs map[string]string } type outputs struct { appName string logLevel zerolog.Level logRegexChecks []*regexp.Regexp } tests := []struct { name string inputs inputs want outputs }{ { name: "Test json logging with short timestamp", inputs: inputs{ envs: map[string]string{ "APP_NAME": "testapp", "APP_LOG_LEVEL": "warn", "APP_LOG_FORMAT": "json", "APP_LOG_TIME_FORMAT": "short", }, }, want: outputs{ appName: "testapp", logLevel: zerolog.WarnLevel, logRegexChecks: []*regexp.Regexp{ regexp.MustCompile(`^\{.*time":"\d{1,}:\d{2}`), }, }, }, { name: "Test json logging with unix timestamp", inputs: inputs{ envs: map[string]string{ "APP_NAME": "testapp", "APP_LOG_LEVEL": "info", "APP_LOG_FORMAT": "json", "APP_LOG_TIME_FORMAT": "unix", }, }, want: outputs{ appName: "testapp", logLevel: zerolog.InfoLevel, logRegexChecks: []*regexp.Regexp{ regexp.MustCompile(`time":\d+,`), }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Set environment variables for key, val := range tt.inputs.envs { os.Setenv(key, val) } // Prepare config in context ctx := MustSetupConfigAndLogging(context.Background()) // Retrieve config and logger from prepared context cfg := config.MustFromCtx(ctx) logger := zerolog.Ctx(ctx) // Check wants if cfg.Name != tt.want.appName { t.Errorf("Expected app name %s, got %s", tt.want.appName, cfg.Name) } if logger.GetLevel() != tt.want.logLevel { t.Errorf("Expected log level %#v, got %#v", tt.want.logLevel, logger.GetLevel()) } // Send and capture a log r, w := io.Pipe() testLogger := logger.Output(w) scanner := bufio.NewScanner(r) go func() { testLogger.Error().Msg("test message") w.Close() }() logOut := make([]byte, 0) if scanner.Scan() { logOut = scanner.Bytes() } // Check all expressions for _, expr := range tt.want.logRegexChecks { if !expr.Match(logOut) { t.Errorf("Regex %s did not match log %s", expr.String(), logOut) } } // Super annoying need to reset due to app framework package // using flag.Parse() and go test also using it testlog := flag.Lookup("test.testlogfile").Value.String() flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) flag.String("test.testlogfile", testlog, "") flag.String("test.paniconexit0", "", "") flag.String("test.v", "", "") flag.Parse() }) } }