/* Copyright 2020 The Knative Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package logging import ( "errors" "reflect" "testing" ) type abcf struct { A int b string C *de F func() } type de struct { D string e float64 } var someStruct abcf func init() { someStruct = abcf{ A: 42, b: "some string", C: &de{ D: "hello world", e: 72.3, }, F: InitializeLogger, } } func TestTLogger(legacy *testing.T) { verbosity = 5 InitializeLogger() t, cancel := NewTLogger(legacy) defer cancel() var blank interface{} = &someStruct t.V(6).Info("Should not be printed") t.V(4).Info("Should be printed!") t.Run("A-Nice-Subtest", func(ts *TLogger) { ts.V(0).Info("This is pretty important; everyone needs to see it!", "some pointer", blank, "some number", 42.0) t.Run("A-Nested-Subtest", func(ts *TLogger) { ts.Parallel() ts.V(1).Info("I am visible!") ts.V(6).Info("I am invisible!") t.Collect("collected_non_error", "I'm not an error!") }) t.Run("A-2nd-Nested-Subtest", func(ts *TLogger) { ts.Parallel() ts.V(1).Info("I am visible!") ts.V(6).Info("I am also invisible!") }) }) t.Run("Skipped", func(ts *TLogger) { ts.SkipNow() }) t.ErrorIfErr(nil, "I won't fail because no error!") t.FatalIfErr(nil, "I won't fail because no error!") t = t.WithName("LongerName") t = t.WithValues("persistentKey", "persistentValue") t.Logf("Sadly still have to support %s", "LogF") } func TestTLoggerFailing(legacy *testing.T) { t, cancel := NewTLogger(legacy) defer cancel() t.dontFail = true t.Run("Failing1", func(ts *TLogger) { t.V(0).Info("dontFail values", "t", t.dontFail, "ts", ts.dontFail) t.Collect("collected_error", errors.New("collected")) ts.Error("I am an error", "hello", "world") }) t.Run("Failing2", func(ts *TLogger) { ts.Fatal("I am a fatal error", "hello", "world") }) } type errorWithRuntimeCheckValues struct { testName string inputs []interface{} expectedError error expectedString string expectedInterfaces []interface{} } func TestTLoggerInternals(legacy *testing.T) { verbosity = 2 InitializeLogger() t, cancel := NewTLogger(legacy) defer cancel() tests := []errorWithRuntimeCheckValues{ {"empty", nil, nil, "", nil}, {"string with valid single key-value pair", []interface{}{"greetings!", "hello", "world"}, nil, "greetings!", []interface{}{"hello", "world"}}, {"junk inputs", []interface{}{42}, nil, "unstructured error", t.interfacesToFields(42)}, } for _, tt := range tests { t.Run("errorWithRuntimeCheck "+tt.testName, func(t *TLogger) { e, s, i := t.errorWithRuntimeCheck(tt.inputs...) if !errors.Is(e, tt.expectedError) { t.Error("error did not match", "got", e, "want", tt.expectedError) } if s != tt.expectedString { t.Error("string did not match", "got", s, "want", tt.expectedString) } if !reflect.DeepEqual(i, tt.expectedInterfaces) { t.Error("interfaces did not match", "got", i, "want", tt.expectedInterfaces) } }) } if validateKeysAndValues(42, "whoops not string key before") { t.Error("Should not have accepted non-string key") } if !validateKeysAndValues("we like string keys", "any value is fine") { t.Error("Should have accepted string key") } input := []interface{}{4, 5, 6} things := t.interfacesToFields(input...) expected := []interface{}{"arg 0", 4, "arg 1", 5, "arg 2", 6} if !reflect.DeepEqual(things, expected) { t.Error("interfacesToFields() didn't give expected output", "input", input, "want", expected, "got", things) } t.Helper() // Doesn't do anything } func TestStructuredError(legacy *testing.T) { verbosity = 5 InitializeLogger() t, cancel := NewTLogger(legacy) defer cancel() err := Error("Hello World", "key", "value", "current function", TestStructuredError, "deep struct", someStruct, "z", 4, "y", 3, "x", 2, "w", 1) t.Log(err.Error()) }