| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| package logging |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "errors" |
| "os" |
| "testing" |
| |
| log "github.com/hashicorp/go-hclog" |
| "github.com/stretchr/testify/assert" |
| "github.com/stretchr/testify/require" |
| ) |
| |
| func TestLogger_SetupBasic(t *testing.T) { |
| cfg := &LogConfig{Name: "test-system", LogLevel: log.Info} |
| |
| logger, err := Setup(cfg, nil) |
| require.NoError(t, err) |
| require.NotNil(t, logger) |
| require.Equal(t, logger.Name(), "test-system") |
| require.True(t, logger.IsInfo()) |
| } |
| |
| func TestLogger_SetupInvalidLogLevel(t *testing.T) { |
| cfg := &LogConfig{} |
| |
| _, err := Setup(cfg, nil) |
| assert.Containsf(t, err.Error(), "invalid log level", "expected error %s", err) |
| } |
| |
| func TestLogger_SetupLoggerErrorLevel(t *testing.T) { |
| cfg := &LogConfig{ |
| LogLevel: log.Error, |
| } |
| |
| var buf bytes.Buffer |
| |
| logger, err := Setup(cfg, &buf) |
| require.NoError(t, err) |
| require.NotNil(t, logger) |
| |
| logger.Error("test error msg") |
| logger.Info("test info msg") |
| |
| output := buf.String() |
| |
| require.Contains(t, output, "[ERROR] test error msg") |
| require.NotContains(t, output, "[INFO] test info msg") |
| } |
| |
| func TestLogger_SetupLoggerDebugLevel(t *testing.T) { |
| cfg := LogConfig{LogLevel: log.Debug} |
| var buf bytes.Buffer |
| |
| logger, err := Setup(&cfg, &buf) |
| require.NoError(t, err) |
| require.NotNil(t, logger) |
| |
| logger.Info("test info msg") |
| logger.Debug("test debug msg") |
| |
| output := buf.String() |
| |
| require.Contains(t, output, "[INFO] test info msg") |
| require.Contains(t, output, "[DEBUG] test debug msg") |
| } |
| |
| func TestLogger_SetupLoggerWithName(t *testing.T) { |
| cfg := &LogConfig{ |
| LogLevel: log.Debug, |
| Name: "test-system", |
| } |
| var buf bytes.Buffer |
| |
| logger, err := Setup(cfg, &buf) |
| require.NoError(t, err) |
| require.NotNil(t, logger) |
| |
| logger.Warn("test warn msg") |
| |
| require.Contains(t, buf.String(), "[WARN] test-system: test warn msg") |
| } |
| |
| func TestLogger_SetupLoggerWithJSON(t *testing.T) { |
| cfg := &LogConfig{ |
| LogLevel: log.Debug, |
| LogFormat: JSONFormat, |
| Name: "test-system", |
| } |
| var buf bytes.Buffer |
| |
| logger, err := Setup(cfg, &buf) |
| require.NoError(t, err) |
| require.NotNil(t, logger) |
| |
| logger.Warn("test warn msg") |
| |
| var jsonOutput map[string]string |
| err = json.Unmarshal(buf.Bytes(), &jsonOutput) |
| require.NoError(t, err) |
| require.Contains(t, jsonOutput, "@level") |
| require.Equal(t, jsonOutput["@level"], "warn") |
| require.Contains(t, jsonOutput, "@message") |
| require.Equal(t, jsonOutput["@message"], "test warn msg") |
| } |
| |
| func TestLogger_SetupLoggerWithValidLogPath(t *testing.T) { |
| tmpDir := t.TempDir() |
| |
| cfg := &LogConfig{ |
| LogLevel: log.Info, |
| LogFilePath: tmpDir, //+ "/", |
| } |
| var buf bytes.Buffer |
| |
| logger, err := Setup(cfg, &buf) |
| require.NoError(t, err) |
| require.NotNil(t, logger) |
| } |
| |
| func TestLogger_SetupLoggerWithInValidLogPath(t *testing.T) { |
| cfg := &LogConfig{ |
| LogLevel: log.Info, |
| LogFilePath: "nonexistentdir/", |
| } |
| var buf bytes.Buffer |
| |
| logger, err := Setup(cfg, &buf) |
| require.Error(t, err) |
| require.True(t, errors.Is(err, os.ErrNotExist)) |
| require.Nil(t, logger) |
| } |
| |
| func TestLogger_SetupLoggerWithInValidLogPathPermission(t *testing.T) { |
| tmpDir := "/tmp/" + t.Name() |
| |
| err := os.Mkdir(tmpDir, 0o000) |
| assert.NoError(t, err, "unexpected error testing with invalid log path permission") |
| defer os.RemoveAll(tmpDir) |
| |
| cfg := &LogConfig{ |
| LogLevel: log.Info, |
| LogFilePath: tmpDir + "/", |
| } |
| var buf bytes.Buffer |
| |
| logger, err := Setup(cfg, &buf) |
| require.Error(t, err) |
| require.True(t, errors.Is(err, os.ErrPermission)) |
| require.Nil(t, logger) |
| } |
| |
| func TestLogger_SetupLoggerWithInvalidLogFilePath(t *testing.T) { |
| cases := map[string]struct { |
| path string |
| message string |
| }{ |
| "file name *": { |
| path: "/this/isnt/ok/juan*.log", |
| message: "file name contains globbing character", |
| }, |
| "file name ?": { |
| path: "/this/isnt/ok/juan?.log", |
| message: "file name contains globbing character", |
| }, |
| "file name [": { |
| path: "/this/isnt/ok/[juan].log", |
| message: "file name contains globbing character", |
| }, |
| "directory path *": { |
| path: "/this/isnt/ok/*/qwerty.log", |
| message: "directory contains glob character", |
| }, |
| "directory path ?": { |
| path: "/this/isnt/ok/?/qwerty.log", |
| message: "directory contains glob character", |
| }, |
| "directory path [": { |
| path: "/this/isnt/ok/[foo]/qwerty.log", |
| message: "directory contains glob character", |
| }, |
| } |
| |
| for name, tc := range cases { |
| name := name |
| tc := tc |
| cfg := &LogConfig{ |
| LogLevel: log.Info, |
| LogFilePath: tc.path, |
| } |
| _, err := Setup(cfg, &bytes.Buffer{}) |
| assert.Error(t, err, "%s: expected error due to *", name) |
| assert.Contains(t, err.Error(), tc.message, "%s: error message does not match: %s", name, err.Error()) |
| } |
| } |
| |
| func TestLogger_ChangeLogLevels(t *testing.T) { |
| cfg := &LogConfig{ |
| LogLevel: log.Debug, |
| Name: "test-system", |
| } |
| var buf bytes.Buffer |
| |
| logger, err := Setup(cfg, &buf) |
| require.NoError(t, err) |
| require.NotNil(t, logger) |
| |
| assert.Equal(t, log.Debug, logger.GetLevel()) |
| |
| // Create new named loggers from the base logger and change the levels |
| logger2 := logger.Named("test2") |
| logger3 := logger.Named("test3") |
| |
| logger2.SetLevel(log.Info) |
| logger3.SetLevel(log.Error) |
| |
| assert.Equal(t, log.Debug, logger.GetLevel()) |
| assert.Equal(t, log.Info, logger2.GetLevel()) |
| assert.Equal(t, log.Error, logger3.GetLevel()) |
| } |