/* Copyright 2019 The Kubernetes Authors. Copyright 2020 Intel Coporation. SPDX-License-Identifier: Apache-2.0 */ package ktesting import ( "bytes" "errors" "fmt" "testing" ) func TestInfo(t *testing.T) { tests := map[string]struct { text string withValues []interface{} keysAndValues []interface{} names []string err error expectedOutput string }{ "should log with values passed to keysAndValues": { text: "test", keysAndValues: []interface{}{"akey", "avalue"}, expectedOutput: `INFO test akey="avalue" `, }, "should support single name": { names: []string{"hello"}, text: "test", keysAndValues: []interface{}{"akey", "avalue"}, expectedOutput: `INFO hello: test akey="avalue" `, }, "should support multiple names": { names: []string{"hello", "world"}, text: "test", keysAndValues: []interface{}{"akey", "avalue"}, expectedOutput: `INFO hello/world: test akey="avalue" `, }, "should not print duplicate keys with the same value": { text: "test", keysAndValues: []interface{}{"akey", "avalue", "akey", "avalue"}, expectedOutput: `INFO test akey="avalue" `, }, "should only print the last duplicate key when the values are passed to Info": { text: "test", keysAndValues: []interface{}{"akey", "avalue", "akey", "avalue2"}, expectedOutput: `INFO test akey="avalue2" `, }, "should only print the duplicate key that is passed to Info if one was passed to the logger": { withValues: []interface{}{"akey", "avalue"}, text: "test", keysAndValues: []interface{}{"akey", "avalue"}, expectedOutput: `INFO test akey="avalue" `, }, "should only print the key passed to Info when one is already set on the logger": { withValues: []interface{}{"akey", "avalue"}, text: "test", keysAndValues: []interface{}{"akey", "avalue2"}, expectedOutput: `INFO test akey="avalue2" `, }, "should correctly handle odd-numbers of KVs": { text: "test", keysAndValues: []interface{}{"akey", "avalue", "akey2"}, expectedOutput: `INFO test akey="avalue" akey2="(MISSING)" `, }, "should correctly html characters": { text: "test", keysAndValues: []interface{}{"akey", "<&>"}, expectedOutput: `INFO test akey="<&>" `, }, "should correctly handle odd-numbers of KVs in both log values and Info args": { withValues: []interface{}{"basekey1", "basevar1", "basekey2"}, text: "test", keysAndValues: []interface{}{"akey", "avalue", "akey2"}, expectedOutput: `INFO test basekey1="basevar1" basekey2="(MISSING)" akey="avalue" akey2="(MISSING)" `, }, "should correctly print regular error types": { text: "test", keysAndValues: []interface{}{"err", errors.New("whoops")}, expectedOutput: `INFO test err="whoops" `, }, "should correctly print regular error types when using logr.Error": { text: "test", err: errors.New("whoops"), expectedOutput: `ERROR test err="whoops" `, }, } for n, test := range tests { t.Run(n, func(t *testing.T) { var buffer logToBuf klogr := NewLogger(&buffer, NewConfig()) for _, name := range test.names { klogr = klogr.WithName(name) } klogr = klogr.WithValues(test.withValues...) if test.err != nil { klogr.Error(test.err, test.text, test.keysAndValues...) } else { klogr.Info(test.text, test.keysAndValues...) } actual := buffer.String() if actual != test.expectedOutput { t.Errorf("expected %q did not match actual %q", test.expectedOutput, actual) } }) } } func TestCallDepth(t *testing.T) { logger := NewLogger(t, NewConfig()) logger.Info("hello world") } type logToBuf struct { bytes.Buffer } func (l *logToBuf) Helper() { } func (l *logToBuf) Log(args ...interface{}) { for i, arg := range args { if i > 0 { l.Write([]byte(" ")) } l.Write([]byte(fmt.Sprintf("%s", arg))) } l.Write([]byte("\n")) }