1
16
17 package benchmark
18
19 import (
20 "bytes"
21 "errors"
22 "strings"
23 "testing"
24
25 "github.com/stretchr/testify/assert"
26
27 logsapi "k8s.io/component-base/logs/api/v1"
28 _ "k8s.io/component-base/logs/json/register"
29 runtimev1 "k8s.io/cri-api/pkg/apis/runtime/v1"
30 "k8s.io/klog/v2"
31 )
32
33 func TestData(t *testing.T) {
34 versionResponse := &runtimev1.VersionResponse{
35 Version: "0.1.0",
36 RuntimeName: "containerd",
37 RuntimeVersion: "v1.6.18",
38 RuntimeApiVersion: "v1",
39 }
40
41 testcases := map[string]struct {
42 messages []logMessage
43
44
45 printf, structured, json string
46 stats logStats
47 }{
48 "data/simple.log": {
49 messages: []logMessage{
50 {
51 msg: "Pod status updated",
52 },
53 },
54 printf: `Pod status updated: []`,
55 structured: `"Pod status updated"`,
56 json: `"msg":"Pod status updated","v":0`,
57 stats: logStats{
58 TotalLines: 1,
59 JsonLines: 1,
60 ArgCounts: map[string]int{},
61 },
62 },
63 "data/split.log": {
64 messages: []logMessage{
65 {
66 msg: "Pod status updated",
67 },
68 {
69 msg: "Pod status updated again",
70 },
71 },
72 stats: logStats{
73 TotalLines: 3,
74 SplitLines: 1,
75 JsonLines: 2,
76 ArgCounts: map[string]int{},
77 },
78 },
79 "data/error.log": {
80 messages: []logMessage{
81 {
82 msg: "Pod status update",
83 err: errors.New("failed"),
84 isError: true,
85 },
86 },
87 printf: `Pod status update: failed []`,
88 structured: `"Pod status update" err="failed"`,
89 json: `"msg":"Pod status update","err":"failed"`,
90 stats: logStats{
91 TotalLines: 1,
92 JsonLines: 1,
93 ErrorMessages: 1,
94 ArgCounts: map[string]int{
95 stringArg: 1,
96 totalArg: 1,
97 },
98 },
99 },
100 "data/error-value.log": {
101 messages: []logMessage{
102 {
103 msg: "Pod status update",
104 kvs: []interface{}{"err", errors.New("failed")},
105 },
106 },
107 printf: `Pod status update: [err failed]`,
108 structured: `"Pod status update" err="failed"`,
109 json: `"msg":"Pod status update","v":0,"err":"failed"`,
110 stats: logStats{
111 TotalLines: 1,
112 JsonLines: 1,
113 ArgCounts: map[string]int{
114 stringArg: 1,
115 totalArg: 1,
116 },
117 },
118 },
119 "data/values.log": {
120 messages: []logMessage{
121 {
122 msg: "Example",
123 kvs: []interface{}{
124 "pod", klog.KRef("system", "kube-scheduler"),
125 "pv", klog.KRef("", "volume"),
126 "someString", "hello world",
127 "someValue", 1.0,
128 },
129 },
130 },
131 printf: `Example: [pod system/kube-scheduler pv volume someString hello world someValue 1]`,
132 structured: `"Example" pod="system/kube-scheduler" pv="volume" someString="hello world" someValue=1`,
133 json: `"msg":"Example","v":0,"pod":{"name":"kube-scheduler","namespace":"system"},"pv":{"name":"volume"},"someString":"hello world","someValue":1`,
134 stats: logStats{
135 TotalLines: 1,
136 JsonLines: 1,
137 ArgCounts: map[string]int{
138 stringArg: 1,
139 krefArg: 2,
140 numberArg: 1,
141 totalArg: 4,
142 },
143 },
144 },
145 "data/versionresponse.log": {
146 messages: []logMessage{
147 {
148 msg: "[RemoteRuntimeService] Version Response",
149 verbosity: 10,
150 kvs: []interface{}{
151 "apiVersion", versionResponse,
152 },
153 },
154 },
155 printf: `[RemoteRuntimeService] Version Response: [apiVersion &VersionResponse{Version:0.1.0,RuntimeName:containerd,RuntimeVersion:v1.6.18,RuntimeApiVersion:v1,}]`,
156 structured: `"[RemoteRuntimeService] Version Response" apiVersion="&VersionResponse{Version:0.1.0,RuntimeName:containerd,RuntimeVersion:v1.6.18,RuntimeApiVersion:v1,}"`,
157
158
159
160 json: `"msg":"[RemoteRuntimeService] Version Response","v":0,"apiVersion":"&VersionResponse{Version:0.1.0,RuntimeName:containerd,RuntimeVersion:v1.6.18,RuntimeApiVersion:v1,}"`,
161 stats: logStats{
162 TotalLines: 1,
163 JsonLines: 1,
164 ArgCounts: map[string]int{
165 totalArg: 1,
166 otherArg: 1,
167 },
168 OtherArgs: []interface{}{
169 versionResponse,
170 },
171 },
172 },
173 }
174
175 for filePath, expected := range testcases {
176 t.Run(filePath, func(t *testing.T) {
177 messages, stats, err := loadLog(filePath)
178 if err != nil {
179 t.Fatalf("unexpected load error: %v", err)
180 }
181 assert.Equal(t, expected.messages, messages)
182 assert.Equal(t, expected.stats, stats)
183 printAll := func(format func(item logMessage)) {
184 for _, item := range expected.messages {
185 format(item)
186 }
187 }
188 testBuffered := func(t *testing.T, expected string, format string, print func(item logMessage)) {
189 var buffer bytes.Buffer
190 c := logsapi.NewLoggingConfiguration()
191 c.Format = format
192 o := logsapi.LoggingOptions{
193 ErrorStream: &buffer,
194 InfoStream: &buffer,
195 }
196 klog.SetOutput(&buffer)
197 defer func() {
198 if err := logsapi.ResetForTest(nil); err != nil {
199 t.Errorf("Unexpected error resetting the logging configuration: %v", err)
200 }
201 }()
202 if err := logsapi.ValidateAndApplyWithOptions(c, &o, nil); err != nil {
203 t.Fatalf("Unexpected error configuring logging: %v", err)
204 }
205
206 printAll(print)
207 klog.Flush()
208
209 if !strings.Contains(buffer.String(), expected) {
210 t.Errorf("Expected log output to contain:\n%s\nActual log output:\n%s\n", expected, buffer.String())
211 }
212 }
213
214 t.Run("printf", func(t *testing.T) {
215 testBuffered(t, expected.printf, "text", printf)
216 })
217 t.Run("structured", func(t *testing.T) {
218 testBuffered(t, expected.structured, "text", printLogger)
219 })
220 t.Run("json", func(t *testing.T) {
221 testBuffered(t, expected.json, "json", printLogger)
222 })
223 })
224 }
225 }
226
View as plain text