summaryrefslogtreecommitdiff
path: root/internal/log/rotate_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/log/rotate_test.go')
-rw-r--r--internal/log/rotate_test.go144
1 files changed, 144 insertions, 0 deletions
diff --git a/internal/log/rotate_test.go b/internal/log/rotate_test.go
new file mode 100644
index 0000000..5381a49
--- /dev/null
+++ b/internal/log/rotate_test.go
@@ -0,0 +1,144 @@
+package log
+
+import (
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+ "testing"
+)
+
+func createFileRotater(t *testing.T) (*FileRotater, func()) {
+ d, err := os.MkdirTemp("", "logtest")
+ if err != nil {
+ t.Fatalf("failed creating tmp dir: %v", err)
+ }
+ fn := filepath.Join(d, "test.log")
+ fr, err := NewFileRotater(fn)
+ if err != nil {
+ t.Fatalf("NewFileRotater error: %v", err)
+ }
+ if fr == nil {
+ t.Fatal("NewFileRotater returned nil")
+ }
+ return fr, func() {
+ err := os.RemoveAll(d)
+ if err != nil {
+ t.Errorf("failed removing file: %v", err)
+ }
+ }
+}
+
+func TestNewFileRotater(t *testing.T) {
+ _, cleanup := createFileRotater(t)
+ cleanup()
+
+ d, err := os.MkdirTemp("", "anotherlogtest")
+ if err != nil {
+ t.Fatalf("failed creating another tmp dir: %v", err)
+ }
+ nef := filepath.Join(d, "notexist", "test.log")
+ _, err = NewFileRotater(nef)
+ if err == nil {
+ t.Error("NewFileRotater returned no error with nonexistent dir")
+ }
+}
+
+func TestWriteConcurrent(t *testing.T) {
+ fr, cleanup := createFileRotater(t)
+ defer cleanup()
+ MaxSize = 5
+ var wg sync.WaitGroup
+ for range 5 {
+ wg.Add(1)
+ go func() {
+ _, err := fr.Write([]byte("test"))
+ defer wg.Done()
+ if err != nil {
+ t.Errorf("concurrent write returned an error: %v", err)
+ }
+ }()
+ }
+ wg.Wait()
+}
+
+func TestWriteTrim(t *testing.T) {
+ fr, cleanup := createFileRotater(t)
+ defer cleanup()
+ writeNCheckSize := func(n int, size int64) {
+ buf := make([]byte, n)
+
+ for i := 0; i < n; i++ {
+ buf[i] = 'x'
+ }
+ _, err := fr.Write(buf)
+ if err != nil {
+ t.Fatalf("failed writing: %v", err)
+ }
+
+ fs, err := fr.file.Stat()
+ if err != nil {
+ t.Fatalf("failed getting size: %v", err)
+ }
+
+ gsize := fs.Size()
+
+ if gsize != size {
+ t.Fatalf("got: %v, want: %v, max size: %v", gsize, size, MaxSize)
+ }
+ }
+
+ // we test by writing a start message and checking if it disappears after trimmign
+ // the max size we set to the length of the start message + 20 bytes
+ begS := "this is the start"
+ begB := []byte(begS)
+ startN := int64(len(begB))
+ MaxSize = startN + 20
+ TrimSize = MaxSize / 2
+
+ // no trim yet
+ _, err := fr.Write(begB)
+ if err != nil {
+ t.Fatalf("failed writing start message: %v", err)
+ }
+
+ // write until the trimming size
+ writeNCheckSize(5, startN+5)
+ writeNCheckSize(15, MaxSize)
+
+ // set the length we want to write
+ var n int64 = 11
+
+ // now the size should be the length of the trimmed message plus the remaining (non-trimmed part of the file) plus the length we want to write
+
+ size := int64(len(TrimMsg)) + (MaxSize - TrimSize) + n
+ writeNCheckSize(11, size)
+
+ // disable trimming by setting it to a high value
+ MaxSize = 9000
+ TrimSize = 9000
+
+ // now the size should be the old size plus the write size
+ newN := 12
+ writeNCheckSize(newN, size+int64(newN))
+
+ _, err = fr.file.Seek(0, io.SeekStart)
+ if err != nil {
+ t.Fatalf("failed going to beginning of file: %v", err)
+ }
+
+ b, err := io.ReadAll(fr.file)
+ if err != nil {
+ t.Fatalf("failed reading file: %v", err)
+ }
+
+ corpus := string(b)
+ if strings.Contains(corpus, begS) {
+ t.Fatalf("file still contains beginning message: %v", corpus)
+ }
+
+ if !strings.Contains(corpus, TrimMsg) {
+ t.Fatalf("file does not contain trim message: %v", corpus)
+ }
+}