// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package agent import ( "os" "path/filepath" "testing" "time" "github.com/hashicorp/logutils" "github.com/hashicorp/nomad/ci" "github.com/stretchr/testify/require" ) const ( testFileName = "Nomad.log" testDuration = 2 * time.Second testBytes = 10 ) func TestLogFile_timeRotation(t *testing.T) { ci.Parallel(t) tempDir := t.TempDir() filt := LevelFilter() logFile := logFile{ logFilter: filt, fileName: testFileName, logPath: tempDir, duration: testDuration, } logFile.Write([]byte("Hello World")) time.Sleep(2 * time.Second) logFile.Write([]byte("Second File")) want := 2 if got, _ := os.ReadDir(tempDir); len(got) != want { t.Errorf("Expected %d files, got %v file(s)", want, len(got)) } } func TestLogFile_openNew(t *testing.T) { ci.Parallel(t) require := require.New(t) tempDir := t.TempDir() filt := LevelFilter() filt.MinLevel = logutils.LogLevel("INFO") logFile := logFile{ logFilter: filt, fileName: testFileName, logPath: tempDir, MaxBytes: testBytes, duration: 24 * time.Hour, } require.NoError(logFile.openNew()) _, err := os.ReadFile(logFile.FileInfo.Name()) require.NoError(err) require.Equal(logFile.FileInfo.Name(), filepath.Join(tempDir, testFileName)) // Check if create time and bytes written are kept when opening the active // log file again. bytesWritten, err := logFile.Write([]byte("test")) require.NoError(err) time.Sleep(2 * time.Second) require.NoError(logFile.openNew()) timeDelta := time.Now().Sub(logFile.LastCreated) require.GreaterOrEqual(timeDelta, 2*time.Second) require.Equal(logFile.BytesWritten, int64(bytesWritten)) } func TestLogFile_byteRotation(t *testing.T) { ci.Parallel(t) require := require.New(t) tempDir := t.TempDir() filt := LevelFilter() filt.MinLevel = logutils.LogLevel("INFO") logFile := logFile{ logFilter: filt, fileName: testFileName, logPath: tempDir, MaxBytes: testBytes, duration: 24 * time.Hour, } logFile.Write([]byte("Hello World")) logFile.Write([]byte("Second File")) want := 2 tempFiles, _ := os.ReadDir(tempDir) require.Equal(want, len(tempFiles)) } func TestLogFile_logLevelFiltering(t *testing.T) { ci.Parallel(t) require := require.New(t) tempDir := t.TempDir() filt := LevelFilter() logFile := logFile{ logFilter: filt, fileName: testFileName, logPath: tempDir, MaxBytes: testBytes, duration: testDuration, } logFile.Write([]byte("[INFO] This is an info message")) logFile.Write([]byte("[DEBUG] This is a debug message")) logFile.Write([]byte("[ERR] This is an error message")) want := 2 tempFiles, _ := os.ReadDir(tempDir) require.Equal(want, len(tempFiles)) } func TestLogFile_deleteArchives(t *testing.T) { ci.Parallel(t) require := require.New(t) tempDir := t.TempDir() filt := LevelFilter() filt.MinLevel = logutils.LogLevel("INFO") logFile := logFile{ logFilter: filt, fileName: testFileName, logPath: tempDir, MaxBytes: testBytes, duration: 24 * time.Hour, MaxFiles: 1, } logFile.Write([]byte("[INFO] Hello World")) logFile.Write([]byte("[INFO] Second File")) logFile.Write([]byte("[INFO] Third File")) want := 2 tempFiles, _ := os.ReadDir(tempDir) require.Equal(want, len(tempFiles)) for _, tempFile := range tempFiles { var bytes []byte var err error path := filepath.Join(tempDir, tempFile.Name()) if bytes, err = os.ReadFile(path); err != nil { t.Errorf(err.Error()) return } contents := string(bytes) require.NotEqual("[INFO] Hello World", contents, "oldest log should have been deleted") } } func TestLogFile_deleteArchivesDisabled(t *testing.T) { ci.Parallel(t) require := require.New(t) tempDir := t.TempDir() filt := LevelFilter() filt.MinLevel = logutils.LogLevel("INFO") logFile := logFile{ logFilter: filt, fileName: testFileName, logPath: tempDir, MaxBytes: testBytes, duration: 24 * time.Hour, MaxFiles: 0, } logFile.Write([]byte("[INFO] Hello World")) logFile.Write([]byte("[INFO] Second File")) logFile.Write([]byte("[INFO] Third File")) want := 3 tempFiles, _ := os.ReadDir(tempDir) require.Equal(want, len(tempFiles)) }