-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathformat_integration_test.go
More file actions
205 lines (170 loc) · 5.6 KB
/
format_integration_test.go
File metadata and controls
205 lines (170 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package mtlog
import (
"bytes"
"strings"
"testing"
"time"
"github.com/willibrandon/mtlog/core"
"github.com/willibrandon/mtlog/internal/parser"
"github.com/willibrandon/mtlog/sinks"
)
func TestFormatSpecifiersIntegration(t *testing.T) {
// Create a buffer to capture output
buf := &bytes.Buffer{}
// Create logger with console sink
logger := New(WithSink(sinks.NewConsoleSinkWithWriter(buf)))
// Test numeric formatting
t.Run("Numeric formatting", func(t *testing.T) {
buf.Reset()
logger.Information("Order {OrderId:000} has {ItemCount:00} items", 5, 3)
output := buf.String()
if !strings.Contains(output, "Order 005 has 03 items") {
t.Errorf("Expected zero-padded numbers in output, got: %s", output)
}
})
// Test hex formatting
t.Run("Hex formatting", func(t *testing.T) {
buf.Reset()
logger.Information("Color code: {Color:X}", 0xFF00AA)
output := buf.String()
if !strings.Contains(output, "Color code: FF00AA") {
t.Errorf("Expected hex format in output, got: %s", output)
}
})
// Test float formatting
t.Run("Float formatting", func(t *testing.T) {
buf.Reset()
logger.Information("Price: ${Price:F2} (discount: {Discount:P1})", 19.995, 0.125)
output := buf.String()
if !strings.Contains(output, "Price: $20.00") {
t.Errorf("Expected formatted price in output, got: %s", output)
}
if !strings.Contains(output, "discount: 12.5%") {
t.Errorf("Expected percentage format in output, got: %s", output)
}
})
// Test alignment
t.Run("Alignment", func(t *testing.T) {
buf.Reset()
logger.Information("Name: {Name,10} | Status: {Status,-8} | ID: {Id,5:000}", "Alice", "Active", 42)
output := buf.String()
if !strings.Contains(output, "Name: Alice | Status: Active | ID: 042") {
t.Errorf("Expected aligned output, got: %s", output)
}
})
// Test time formatting
t.Run("Time formatting", func(t *testing.T) {
buf.Reset()
testTime := time.Date(2025, 1, 22, 15, 30, 45, 0, time.UTC)
logger.Information("Event at {Timestamp:yyyy-MM-dd HH:mm:ss}", testTime)
output := buf.String()
if !strings.Contains(output, "Event at 2025-01-22 15:30:45") {
t.Errorf("Expected formatted time in output, got: %s", output)
}
})
// Test complex formatting
t.Run("Complex formatting", func(t *testing.T) {
buf.Reset()
testTime := time.Date(2025, 1, 22, 15, 30, 45, 0, time.UTC)
logger.Information(
"Transaction {TxId:00000} for ${Amount,10:F2} at {Time:HH:mm:ss} ({Status,-10})",
123, 1234.567, testTime, "COMPLETED",
)
output := buf.String()
if !strings.Contains(output, "Transaction 00123 for $ 1234.57 at 15:30:45 (COMPLETED )") {
t.Errorf("Expected complex formatted output, got: %s", output)
}
})
// Test that format specifiers work with ForContext
t.Run("Format with context", func(t *testing.T) {
buf.Reset()
contextLogger := logger.ForContext("RequestId", 42)
contextLogger.Information("Processing {Count:000} items", 7)
output := buf.String()
if !strings.Contains(output, "Processing 007 items") {
t.Errorf("Expected formatted output with context, got: %s", output)
}
})
}
func TestFormatSpecifiersInProperties(t *testing.T) {
// Create a logger with a custom test sink that captures both message and properties
type testEvent struct {
message string
properties map[string]any
}
var events []testEvent
testSink := &testCaptureSink{
capture: func(event *core.LogEvent) {
// Render the message
tmpl, _ := parser.Parse(event.MessageTemplate)
rendered := tmpl.Render(event.Properties)
events = append(events, testEvent{
message: rendered,
properties: event.Properties,
})
},
}
logger := New(WithSink(testSink))
// Log with various format specifiers
testTime := time.Date(2025, 1, 22, 15, 30, 45, 0, time.UTC)
logger.Information(
"Order {OrderId:0000} total ${Total:F2} at {OrderTime:yyyy-MM-dd}",
42, 123.456, testTime,
)
if len(events) != 1 {
t.Fatalf("Expected 1 event, got %d", len(events))
}
event := events[0]
// The formatted values should appear in the rendered message
if event.message != "Order 0042 total $123.46 at 2025-01-22" {
t.Errorf("Expected formatted message, got: %s", event.message)
}
// The properties should contain the original values
if event.properties["OrderId"] != 42 {
t.Errorf("Expected original OrderId value 42, got: %v", event.properties["OrderId"])
}
if event.properties["Total"] != 123.456 {
t.Errorf("Expected original Total value 123.456, got: %v", event.properties["Total"])
}
}
// testCaptureSink captures events for testing
type testCaptureSink struct {
capture func(*core.LogEvent)
}
func (t *testCaptureSink) Emit(event *core.LogEvent) {
if t.capture != nil {
t.capture(event)
}
}
func (t *testCaptureSink) Close() error { return nil }
func BenchmarkFormatSpecifiers(b *testing.B) {
logger := New(WithSink(&discardSink{}))
testTime := time.Now()
b.Run("NoFormat", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
logger.Information("Order {Id} total {Amount} at {Time}", 123, 456.78, testTime)
}
})
b.Run("WithFormat", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
logger.Information("Order {Id:00000} total {Amount:F2} at {Time:yyyy-MM-dd}", 123, 456.78, testTime)
}
})
b.Run("WithAlignment", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
logger.Information("Status: {Status,-10} Count: {Count,5}", "Active", 42)
}
})
b.Run("ComplexFormat", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
logger.Information(
"Transaction {Id:00000} for ${Amount,10:F2} at {Time:HH:mm:ss} ({Status,-8})",
123, 1234.56, testTime, "DONE",
)
}
})
}