v0.1.8 tests converted to standard library from testify
This commit is contained in:
+91
-47
@@ -1,108 +1,152 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestLevel tests the conversion of level strings to their corresponding integer constants
|
||||
// TestLevel verifies level string parsing, including case and whitespace handling.
|
||||
func TestLevel(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expected int64
|
||||
wantErr bool
|
||||
input string
|
||||
want int64
|
||||
wantErr bool
|
||||
}{
|
||||
{"debug", LevelDebug, false},
|
||||
{"DEBUG", LevelDebug, false},
|
||||
{" info ", LevelInfo, false},
|
||||
{"warn", LevelWarn, false},
|
||||
{"Warn", LevelWarn, false},
|
||||
{"error", LevelError, false},
|
||||
{"proc", LevelProc, false},
|
||||
{"disk", LevelDisk, false},
|
||||
{"sys", LevelSys, false},
|
||||
{"invalid", 0, true},
|
||||
{"", 0, true},
|
||||
{" ", 0, true},
|
||||
{"-4", 0, true}, // numeric forms are handled by applyConfigField, not Level
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
level, err := Level(tt.input)
|
||||
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expected, level)
|
||||
errContains(t, err, "invalid level string", "Level")
|
||||
return
|
||||
}
|
||||
mustNoErr(t, err, "Level")
|
||||
equal(t, level, tt.want, "level value")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestParseKeyValue verifies the parsing of "key=value" strings
|
||||
// TestParseKeyValue verifies key=value splitting and trimming.
|
||||
func TestParseKeyValue(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
wantKey string
|
||||
wantValue string
|
||||
wantErr bool
|
||||
wantErr string
|
||||
}{
|
||||
{"key=value", "key", "value", false},
|
||||
{" key = value ", "key", "value", false},
|
||||
{"key=value=with=equals", "key", "value=with=equals", false},
|
||||
{"noequals", "", "", true},
|
||||
{"=value", "", "", true},
|
||||
{"key=", "key", "", false},
|
||||
{"simple", "key=value", "key", "value", ""},
|
||||
{"trimmed", " key = value ", "key", "value", ""},
|
||||
{"value with separators", "key=value=with=equals", "key", "value=with=equals", ""},
|
||||
{"empty value", "key=", "key", "", ""},
|
||||
{"no separator", "noequals", "", "", "expected key=value"},
|
||||
{"empty key", "=value", "", "", "key cannot be empty"},
|
||||
{"whitespace key", " =value", "", "", "key cannot be empty"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
key, value, err := parseKeyValue(tt.input)
|
||||
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.wantKey, key)
|
||||
assert.Equal(t, tt.wantValue, value)
|
||||
if tt.wantErr != "" {
|
||||
errContains(t, err, tt.wantErr, "parseKeyValue")
|
||||
return
|
||||
}
|
||||
mustNoErr(t, err, "parseKeyValue")
|
||||
equal(t, key, tt.wantKey, "key")
|
||||
equal(t, value, tt.wantValue, "value")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestFmtErrorf ensures that internal errors are correctly prefixed
|
||||
// TestFmtErrorf verifies prefixing is applied once.
|
||||
func TestFmtErrorf(t *testing.T) {
|
||||
err := fmtErrorf("test error: %s", "details")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "log: test error: details", err.Error())
|
||||
mustErr(t, err, "fmtErrorf")
|
||||
equal(t, err.Error(), "log: test error: details", "message")
|
||||
|
||||
// Already prefixed
|
||||
err = fmtErrorf("log: already prefixed")
|
||||
assert.Equal(t, "log: already prefixed", err.Error())
|
||||
equal(t, err.Error(), "log: already prefixed", "message")
|
||||
equal(t, strings.Count(err.Error(), "log: "), 1, "prefix occurrences")
|
||||
}
|
||||
|
||||
// TestGetTrace checks the stack trace generation for various depths
|
||||
// TestGetTrace verifies depth bounds and caller-to-callee ordering.
|
||||
func TestGetTrace(t *testing.T) {
|
||||
// Test various depths
|
||||
tests := []struct {
|
||||
name string
|
||||
depth int64
|
||||
check func(string)
|
||||
check func(t *testing.T, trace string)
|
||||
}{
|
||||
{0, func(s string) { assert.Empty(t, s) }},
|
||||
{1, func(s string) { assert.NotEmpty(t, s) }},
|
||||
{3, func(s string) {
|
||||
assert.NotEmpty(t, s)
|
||||
assert.True(t, strings.Contains(s, "->") || s == "(unknown)")
|
||||
{"disabled", 0, func(t *testing.T, s string) {
|
||||
if s != "" {
|
||||
t.Errorf("depth 0 must produce no trace, got %q", s)
|
||||
}
|
||||
}},
|
||||
{"negative", -1, func(t *testing.T, s string) {
|
||||
if s != "" {
|
||||
t.Errorf("negative depth must produce no trace, got %q", s)
|
||||
}
|
||||
}},
|
||||
{"single frame", 1, func(t *testing.T, s string) {
|
||||
if s == "" {
|
||||
t.Error("depth 1 must produce a trace")
|
||||
}
|
||||
notContains(t, s, "->", "single frame must not contain a separator")
|
||||
}},
|
||||
{"multi frame", 3, func(t *testing.T, s string) {
|
||||
if s == "" {
|
||||
t.Fatal("depth 3 must produce a trace")
|
||||
}
|
||||
if s != "(unknown)" {
|
||||
contains(t, s, "->", "multi-frame separator")
|
||||
// Frames are reversed into caller -> callee order
|
||||
parts := strings.Split(s, " -> ")
|
||||
if len(parts) < 2 {
|
||||
t.Errorf("expected multiple frames, got %q", s)
|
||||
}
|
||||
}
|
||||
}},
|
||||
{"over limit", 11, func(t *testing.T, s string) {
|
||||
if s != "" {
|
||||
t.Errorf("depth above 10 must produce no trace, got %q", s)
|
||||
}
|
||||
}},
|
||||
{11, func(s string) { assert.Empty(t, s) }}, // Over limit
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(fmt.Sprintf("depth_%d", tt.depth), func(t *testing.T) {
|
||||
trace := getTrace(tt.depth, 0)
|
||||
tt.check(trace)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.check(t, getTrace(tt.depth, 0))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetTraceOrdering verifies the deepest caller appears first.
|
||||
func TestGetTraceOrdering(t *testing.T) {
|
||||
var trace string
|
||||
outer := func() { trace = getTrace(3, 0) }
|
||||
middle := func() { outer() }
|
||||
middle()
|
||||
|
||||
if trace == "" || trace == "(unknown)" {
|
||||
t.Skip("runtime frames unavailable under current inlining")
|
||||
}
|
||||
first := strings.Split(trace, " -> ")[0]
|
||||
last := strings.Split(trace, " -> ")
|
||||
// The innermost frame is getTrace itself; the caller chain precedes it
|
||||
if first == last[len(last)-1] {
|
||||
t.Errorf("frames not ordered: %q", trace)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user