github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/resource-recommend/log/logger_test.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package log
    18  
    19  import (
    20  	"context"
    21  	"flag"
    22  	"fmt"
    23  	"os"
    24  	"regexp"
    25  	"runtime"
    26  	"testing"
    27  
    28  	"k8s.io/klog/v2"
    29  )
    30  
    31  func TestInitContextAndGetCtxFields(t *testing.T) {
    32  	type args struct {
    33  		ctx context.Context
    34  	}
    35  	tests := []struct {
    36  		name string
    37  		args args
    38  	}{
    39  		{
    40  			name: "case1",
    41  			args: args{
    42  				ctx: context.Background(),
    43  			},
    44  		},
    45  	}
    46  	for _, tt := range tests {
    47  		t.Run(tt.name, func(t *testing.T) {
    48  			ctx := InitContext(tt.args.ctx)
    49  			fields := GetCtxFields(ctx)
    50  			if len(fields) != 2 {
    51  				t.Errorf("The fields length must be 2")
    52  			}
    53  			if fields[0] != LinkIDKey {
    54  				t.Errorf("fields must be included: %s", LinkIDKey)
    55  			}
    56  		})
    57  	}
    58  }
    59  
    60  func TestSetKeysAndValues(t *testing.T) {
    61  	type tempStruct struct {
    62  		a int
    63  		b string
    64  	}
    65  	tempStruct1 := &tempStruct{111, "aaa"}
    66  	type args struct {
    67  		ctx           context.Context
    68  		keysAndValues []interface{}
    69  	}
    70  	type want struct {
    71  		index     int
    72  		wantValue interface{}
    73  	}
    74  	tests := []struct {
    75  		name string
    76  		args args
    77  		want []want
    78  	}{
    79  		{
    80  			name: "case1",
    81  			args: args{
    82  				ctx:           InitContext(context.Background()),
    83  				keysAndValues: []interface{}{"k1", "v1", "k2", "v2"},
    84  			},
    85  			want: []want{
    86  				{
    87  					index: 2, wantValue: "k1",
    88  				},
    89  				{
    90  					index: 3, wantValue: "v1",
    91  				},
    92  				{
    93  					index: 4, wantValue: "k2",
    94  				},
    95  				{
    96  					index: 5, wantValue: "v2",
    97  				},
    98  			},
    99  		},
   100  		{
   101  			name: "case2",
   102  			args: args{
   103  				ctx:           InitContext(context.Background()),
   104  				keysAndValues: []interface{}{"k1", tempStruct{111, "aaa"}},
   105  			},
   106  			want: []want{
   107  				{
   108  					index: 2, wantValue: "k1",
   109  				},
   110  				{
   111  					index: 3, wantValue: tempStruct{111, "aaa"},
   112  				},
   113  			},
   114  		},
   115  		{
   116  			name: "case3",
   117  			args: args{
   118  				ctx:           InitContext(context.Background()),
   119  				keysAndValues: []interface{}{"k1", tempStruct1},
   120  			},
   121  			want: []want{
   122  				{
   123  					index: 2, wantValue: "k1",
   124  				},
   125  				{
   126  					index: 3, wantValue: tempStruct1,
   127  				},
   128  			},
   129  		},
   130  		{
   131  			name: "case4",
   132  			args: args{
   133  				ctx:           context.Background(),
   134  				keysAndValues: []interface{}{"k1", tempStruct1},
   135  			},
   136  			want: []want{
   137  				{
   138  					index: 0, wantValue: "k1",
   139  				},
   140  				{
   141  					index: 1, wantValue: tempStruct1,
   142  				},
   143  			},
   144  		},
   145  		{
   146  			name: "case4",
   147  			args: args{
   148  				ctx:           InitContext(context.Background()),
   149  				keysAndValues: []interface{}{},
   150  			},
   151  			want: []want{},
   152  		},
   153  	}
   154  	for _, tt := range tests {
   155  		t.Run(tt.name, func(t *testing.T) {
   156  			ctx := SetKeysAndValues(tt.args.ctx, tt.args.keysAndValues...)
   157  			fields := GetCtxFields(ctx)
   158  			for _, w := range tt.want {
   159  				if fields[w.index] != w.wantValue {
   160  					t.Errorf("set KeysAndValues error, index(%d) should be %v, got: %v", w.index, w.wantValue, fields[w.index])
   161  				} else {
   162  					t.Logf("set KeysAndValues successful, index(%d) should be %v, got: %v", w.index, w.wantValue, fields[w.index])
   163  				}
   164  			}
   165  		})
   166  	}
   167  }
   168  
   169  // 自定义的测试日志记录器,实现 io.Writer 接口
   170  type TestLogger struct {
   171  	RegularxEpression string
   172  	t                 *testing.T
   173  }
   174  
   175  func (tl *TestLogger) Write(p []byte) (n int, err error) {
   176  	str := string(p)
   177  
   178  	regex, err := regexp.Compile(tl.RegularxEpression)
   179  	if err != nil {
   180  		fmt.Println("Error compiling regex:", err)
   181  		return
   182  	}
   183  	isMatch := regex.MatchString(str)
   184  	if !isMatch {
   185  		tl.t.Errorf("match the log content error, regex is %s, got: %s", tl.RegularxEpression, str)
   186  	}
   187  
   188  	return len(p), nil
   189  }
   190  
   191  func TestErrorS(t *testing.T) {
   192  	type args struct {
   193  		ctx           context.Context
   194  		err           error
   195  		msg           string
   196  		keysAndValues []interface{}
   197  	}
   198  	tests := []struct {
   199  		name       string
   200  		args       args
   201  		wantLogStr string
   202  	}{
   203  		{
   204  			name: "case1",
   205  			args: args{
   206  				ctx:           SetKeysAndValues(context.Background(), "baseK1", "baseV1"),
   207  				err:           fmt.Errorf("err1"),
   208  				msg:           "errMsg1",
   209  				keysAndValues: []interface{}{"k1", "v1", "k2", "v2"},
   210  			},
   211  			wantLogStr: "E\\d{4} \\d{2}:\\d{2}:\\d{2}\\.\\d{6}   %d logger_test.go:%d] \"errMsg1\" err=\"err1\" baseK1=\"baseV1\" k1=\"v1\" k2=\"v2\"\n",
   212  		},
   213  		{
   214  			name: "case2",
   215  			args: args{
   216  				ctx:           context.Background(),
   217  				err:           fmt.Errorf("err1"),
   218  				msg:           "errMsg1",
   219  				keysAndValues: []interface{}{},
   220  			},
   221  			wantLogStr: "E\\d{4} \\d{2}:\\d{2}:\\d{2}\\.\\d{6}   %d logger_test.go:%d] \"errMsg1\" err=\"err1\"\n",
   222  		},
   223  	}
   224  	for _, tt := range tests {
   225  		t.Run(tt.name, func(t *testing.T) {
   226  			_, _, line, ok := runtime.Caller(0)
   227  			if !ok {
   228  				panic("Unable to retrieve caller information")
   229  			}
   230  			pid := os.Getpid()
   231  			klog.LogToStderr(false)
   232  			klog.SetOutput(&TestLogger{
   233  				RegularxEpression: fmt.Sprintf(tt.wantLogStr, pid, line+10),
   234  				t:                 t,
   235  			})
   236  			ErrorS(tt.args.ctx, tt.args.err, tt.args.msg, tt.args.keysAndValues...)
   237  		})
   238  	}
   239  }
   240  
   241  func TestInfoS(t *testing.T) {
   242  	type args struct {
   243  		ctx           context.Context
   244  		msg           string
   245  		keysAndValues []interface{}
   246  	}
   247  	tests := []struct {
   248  		name       string
   249  		args       args
   250  		wantLogStr string
   251  	}{
   252  		{
   253  			name: "case1",
   254  			args: args{
   255  				ctx:           SetKeysAndValues(context.Background(), "baseK1", "baseV1"),
   256  				msg:           "InfoMsg1",
   257  				keysAndValues: []interface{}{"k1", "v1", "k2", "v2"},
   258  			},
   259  			wantLogStr: "I\\d{4} \\d{2}:\\d{2}:\\d{2}\\.\\d{6}   %d logger_test.go:%d] \"InfoMsg1\" baseK1=\"baseV1\" k1=\"v1\" k2=\"v2\"\n",
   260  		},
   261  		{
   262  			name: "case2",
   263  			args: args{
   264  				ctx:           context.Background(),
   265  				msg:           "InfoMsg1",
   266  				keysAndValues: []interface{}{},
   267  			},
   268  			wantLogStr: "I\\d{4} \\d{2}:\\d{2}:\\d{2}\\.\\d{6}   %d logger_test.go:%d] \"InfoMsg1\"\n",
   269  		},
   270  	}
   271  	for _, tt := range tests {
   272  		t.Run(tt.name, func(t *testing.T) {
   273  			_, _, line, ok := runtime.Caller(0)
   274  			if !ok {
   275  				panic("Unable to retrieve caller information")
   276  			}
   277  			pid := os.Getpid()
   278  			klog.LogToStderr(false)
   279  			klog.SetOutput(&TestLogger{
   280  				RegularxEpression: fmt.Sprintf(tt.wantLogStr, pid, line+10),
   281  				t:                 t,
   282  			})
   283  			InfoS(tt.args.ctx, tt.args.msg, tt.args.keysAndValues...)
   284  		})
   285  	}
   286  }
   287  
   288  func TestVerbose_InfoS(t *testing.T) {
   289  	logLevel := klog.Level(1)
   290  	klog.InitFlags(nil)
   291  	flag.Set("v", logLevel.String())
   292  	flag.Parse()
   293  
   294  	type fields struct {
   295  		Verbose klog.Verbose
   296  	}
   297  	type args struct {
   298  		ctx           context.Context
   299  		msg           string
   300  		keysAndValues []interface{}
   301  	}
   302  	tests := []struct {
   303  		name       string
   304  		fields     fields
   305  		args       args
   306  		wantLogStr string
   307  	}{
   308  		{
   309  			name: "case1",
   310  			args: args{
   311  				ctx:           SetKeysAndValues(context.Background(), "baseK1", "baseV1"),
   312  				msg:           "InfoMsg1",
   313  				keysAndValues: []interface{}{"k1", "v1", "k2", "v2"},
   314  			},
   315  			wantLogStr: "I\\d{4} \\d{2}:\\d{2}:\\d{2}\\.\\d{6}   %d logger_test.go:%d] \"InfoMsg1\" baseK1=\"baseV1\" k1=\"v1\" k2=\"v2\"\n",
   316  		},
   317  		{
   318  			name: "case2",
   319  			args: args{
   320  				ctx:           context.Background(),
   321  				msg:           "InfoMsg1",
   322  				keysAndValues: []interface{}{},
   323  			},
   324  			wantLogStr: "I\\d{4} \\d{2}:\\d{2}:\\d{2}\\.\\d{6}   %d logger_test.go:%d] \"InfoMsg1\"\n",
   325  		},
   326  	}
   327  	for _, tt := range tests {
   328  		t.Run(tt.name, func(t *testing.T) {
   329  			_, _, line, ok := runtime.Caller(0)
   330  			if !ok {
   331  				panic("Unable to retrieve caller information")
   332  			}
   333  			pid := os.Getpid()
   334  			klog.LogToStderr(false)
   335  			klog.SetOutput(&TestLogger{
   336  				RegularxEpression: fmt.Sprintf(tt.wantLogStr, pid, line+10),
   337  				t:                 t,
   338  			})
   339  			V(logLevel).InfoS(tt.args.ctx, tt.args.msg, tt.args.keysAndValues...)
   340  			klog.Flush()
   341  		})
   342  	}
   343  }