diff --git a/Makefile b/Makefile index b8f7b3b..a9103db 100644 --- a/Makefile +++ b/Makefile @@ -20,5 +20,5 @@ test: # Run test-coverage test-coverage: - @go test -cpu=4 -race -coverprofile=coverage.txt -covermode=atomic + @go test ./... -cpu=4 -race -coverprofile=coverage.txt -covermode=atomic .PHONY: test-coverage diff --git a/local/freecache_test.go b/local/freecache_test.go index efcf055..b4c45c3 100644 --- a/local/freecache_test.go +++ b/local/freecache_test.go @@ -11,26 +11,41 @@ import ( ) func TestFreeCache(t *testing.T) { - cache := NewFreeCache(10*MB, time.Second) - assert.Equal(t, time.Second/10, cache.offset) - cache.UseRandomizedTTL(time.Millisecond) - assert.Equal(t, time.Millisecond, cache.offset) - assert.Equal(t, "", cache.innerKeyPrefix) + t.Run("Test limited ttl", func(t *testing.T) { + cache := NewFreeCache(10*MB, time.Millisecond) + assert.Equal(t, time.Second, cache.ttl) + }) + + t.Run("Test limited offset", func(t *testing.T) { + cache := NewFreeCache(200*KB, time.Hour) + assert.Equal(t, 10*time.Second, cache.offset) + }) + + t.Run("Test default", func(t *testing.T) { + cache := NewFreeCache(10*MB, time.Second) + assert.Equal(t, time.Second/10, cache.offset) + cache.UseRandomizedTTL(time.Millisecond) + assert.Equal(t, time.Millisecond, cache.offset) + assert.Equal(t, "", cache.innerKeyPrefix) + }) - key1 := "key1" - val, exists := cache.Get(key1) - assert.False(t, exists) - assert.Equal(t, []byte(nil), val) + t.Run("Test GET/SET/DEL ", func(t *testing.T) { + cache := NewFreeCache(10*MB, time.Second) + key1 := "key1" + val, exists := cache.Get(key1) + assert.False(t, exists) + assert.Equal(t, []byte(nil), val) - cache.Set(key1, []byte("value1")) - val, exists = cache.Get(key1) - assert.True(t, exists) - assert.Equal(t, []byte("value1"), val) + cache.Set(key1, []byte("value1")) + val, exists = cache.Get(key1) + assert.True(t, exists) + assert.Equal(t, []byte("value1"), val) - cache.Del(key1) - val, exists = cache.Get(key1) - assert.False(t, exists) - assert.Equal(t, []byte(nil), val) + cache.Del(key1) + val, exists = cache.Get(key1) + assert.False(t, exists) + assert.Equal(t, []byte(nil), val) + }) } func TestNewFreeCacheWithInnerKeyPrefix(t *testing.T) { diff --git a/logger/default_test.go b/logger/default_test.go index 486d34c..d319aaa 100644 --- a/logger/default_test.go +++ b/logger/default_test.go @@ -1,21 +1,91 @@ package logger import ( + "bytes" + "fmt" + "log" + "strings" "testing" - - "github.com/stretchr/testify/assert" ) -type testLogger struct{} +func TestLocalLogger(t *testing.T) { + t.Run("TestDebug", func(t *testing.T) { + buffer := &bytes.Buffer{} + ll := &localLogger{ + logger: log.New(buffer, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds), + } + ll.Debug("debug message") + if got, want := buffer.String(), "[DEBUG] debug message\n"; !strings.Contains(got, want) { + t.Errorf("got %q, want %q", got, want) + } + }) -func TestSetDefaultLogger(t *testing.T) { - tl := &testLogger{} - SetDefaultLogger(tl) + t.Run("TestInfo", func(t *testing.T) { + buffer := &bytes.Buffer{} + ll := &localLogger{ + logger: log.New(buffer, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds), + } + ll.Info("info message") + if got, want := buffer.String(), "[INFO] info message\n"; !strings.Contains(got, want) { + t.Errorf("got %q, want %q", got, want) + } + }) - assert.Equal(t, tl, defaultLogger) -} + t.Run("TestWarn", func(t *testing.T) { + buffer := &bytes.Buffer{} + ll := &localLogger{ + logger: log.New(buffer, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds), + } + ll.Warn("warn message") + if got, want := buffer.String(), "[WARN] warn message\n"; !strings.Contains(got, want) { + t.Errorf("got %q, want %q", got, want) + } + }) + + t.Run("TestError", func(t *testing.T) { + buffer := &bytes.Buffer{} + ll := &localLogger{ + logger: log.New(buffer, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds), + } + ll.Error("error message") + if got, want := buffer.String(), "[ERROR] error message\n"; !strings.Contains(got, want) { + t.Errorf("got %q, want %q", got, want) + } + }) -func (l *testLogger) Debug(format string, v ...any) {} -func (l *testLogger) Info(format string, v ...any) {} -func (l *testLogger) Warn(format string, v ...any) {} -func (l *testLogger) Error(format string, v ...any) {} + t.Run("TestLogf", func(t *testing.T) { + buffer := &bytes.Buffer{} + ll := &localLogger{ + logger: log.New(buffer, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds), + } + // 定义测试用例 + testCases := []struct { + level Level + format string + expected string + shouldLog bool + }{ + {LevelDebug, "debug message %s", "[DEBUG] debug message test\n", true}, + {LevelInfo, "info message %s", "[INFO] info message test\n", true}, + {LevelWarn, "warn message %s", "[WARN] warn message test\n", true}, + {LevelError, "error message %s", "[ERROR] error message test\n", true}, + } + + // 循环执行测试用例 + for _, testCase := range testCases { + t.Run(fmt.Sprintf("Level%s", testCase.level), func(t *testing.T) { + buffer.Reset() // 清空缓冲区 + ll.logf(testCase.level, &testCase.format, "test") + if testCase.shouldLog { + if !strings.Contains(buffer.String(), testCase.expected) { + t.Errorf("Expected output: %s, but got: %s", testCase.expected, buffer.String()) + } + } else { + if buffer.String() != "" { + t.Errorf("Expected no output, but got: %s", buffer.String()) + } + } + }) + } + }) +} diff --git a/logger/logger_test.go b/logger/logger_test.go new file mode 100644 index 0000000..3601a9b --- /dev/null +++ b/logger/logger_test.go @@ -0,0 +1,162 @@ +package logger + +import ( + "bytes" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSetDefaultLogger(t *testing.T) { + t.Run("Test SetDefaultLogger", func(t *testing.T) { + tl := &testLogger{} + SetDefaultLogger(tl) + + assert.Equal(t, tl, defaultLogger) + }) + + t.Run("Test Set Invalid", func(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("expected panic, got nil") + } + }() + SetDefaultLogger(nil) + }) +} + +func TestLogger(t *testing.T) { + t.Run("TestDebug", func(t *testing.T) { + buffer := &bytes.Buffer{} + testLogger := &testLogger{buffer: buffer} + SetDefaultLogger(testLogger) + Debug("debug message") + if got, want := buffer.String(), "[DEBUG] debug message\n"; got != want { + t.Errorf("got %q, want %q", got, want) + } + }) + + t.Run("TestInfo", func(t *testing.T) { + buffer := &bytes.Buffer{} + testLogger := &testLogger{buffer: buffer} + SetDefaultLogger(testLogger) + Info("info message") + if got, want := buffer.String(), "[INFO] info message\n"; got != want { + t.Errorf("got %q, want %q", got, want) + } + }) + + t.Run("TestWarn", func(t *testing.T) { + buffer := &bytes.Buffer{} + testLogger := &testLogger{buffer: buffer} + SetDefaultLogger(testLogger) + Warn("warn message") + if got, want := buffer.String(), "[WARN] warn message\n"; got != want { + t.Errorf("got %q, want %q", got, want) + } + }) + + t.Run("TestError", func(t *testing.T) { + buffer := &bytes.Buffer{} + testLogger := &testLogger{buffer: buffer} + SetDefaultLogger(testLogger) + Error("error message") + if got, want := buffer.String(), "[ERROR] error message\n"; got != want { + t.Errorf("got %q, want %q", got, want) + } + }) + + t.Run("TestLevelError", func(t *testing.T) { + buffer := &bytes.Buffer{} + testLogger := &testLogger{buffer: buffer} + SetDefaultLogger(testLogger) + + SetLevel(LevelError) + Debug("debug message") + Info("info message") + Warn("warn message") + Error("error message") + if got, want := buffer.String(), "[ERROR] error message\n"; got != want { + t.Errorf("got %q, want %q", got, want) + } + }) + + t.Run("TestLevelWarn", func(t *testing.T) { + buffer := &bytes.Buffer{} + testLogger := &testLogger{buffer: buffer} + SetDefaultLogger(testLogger) + + SetLevel(LevelWarn) + Debug("debug message") + Info("info message") + Warn("warn message") + Error("error message") + if got, want := buffer.String(), "[WARN] warn message\n[ERROR] error message\n"; got != want { + t.Errorf("got %q, want %q", got, want) + } + }) + + t.Run("TestLevelInfo", func(t *testing.T) { + buffer := &bytes.Buffer{} + testLogger := &testLogger{buffer: buffer} + SetDefaultLogger(testLogger) + + SetLevel(LevelInfo) + Debug("debug message") + Info("info message") + Warn("warn message") + Error("error message") + if got, want := buffer.String(), "[INFO] info message\n[WARN] warn message\n[ERROR] error message\n"; got != want { + t.Errorf("got %q, want %q", got, want) + } + }) + + t.Run("TestInvalidLevel", func(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("expected panic, got nil") + } + }() + SetLevel(Level(-1)) + }) +} + +func TestLevelString(t *testing.T) { + tests := []struct { + level Level + want string + }{ + {LevelDebug, "[DEBUG] "}, + {LevelInfo, "[INFO] "}, + {LevelWarn, "[WARN] "}, + {LevelError, "[ERROR] "}, + } + for _, tt := range tests { + t.Run(tt.want, func(t *testing.T) { + if got := tt.level.String(); got != tt.want { + t.Errorf("Level.String() = %v, want %v", got, tt.want) + } + }) + } +} + +type testLogger struct { + buffer *bytes.Buffer +} + +func (tl *testLogger) Debug(format string, v ...any) { + fmt.Fprintf(tl.buffer, "[DEBUG] "+format+"\n", v...) +} + +func (tl *testLogger) Info(format string, v ...any) { + fmt.Fprintf(tl.buffer, "[INFO] "+format+"\n", v...) +} + +func (tl *testLogger) Warn(format string, v ...any) { + fmt.Fprintf(tl.buffer, "[WARN] "+format+"\n", v...) +} + +func (tl *testLogger) Error(format string, v ...any) { + fmt.Fprintf(tl.buffer, "[ERROR] "+format+"\n", v...) +} diff --git a/util/merge_test.go b/util/merge_test.go index fb697e7..8e48e31 100644 --- a/util/merge_test.go +++ b/util/merge_test.go @@ -7,6 +7,11 @@ import ( ) func TestMergeMap(t *testing.T) { + t.Run("merge nil", func(t *testing.T) { + actual := MergeMap[string, int]() + assert.Nil(t, actual) + }) + t.Run("merge one map", func(t *testing.T) { m1 := map[int]string{ 1: "a",