github.com/matrixorigin/matrixone@v0.7.0/pkg/logutil/internal_test.go (about)

     1  // Copyright 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package logutil
    16  
    17  import (
    18  	"context"
    19  	"github.com/lni/goutils/leaktest"
    20  	"regexp"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/require"
    24  	"go.uber.org/zap"
    25  	"go.uber.org/zap/zapcore"
    26  
    27  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    28  )
    29  
    30  func TestLogConfig_getter(t *testing.T) {
    31  	type fields struct {
    32  		Level      string
    33  		Format     string
    34  		Filename   string
    35  		MaxSize    int
    36  		MaxDays    int
    37  		MaxBackups int
    38  
    39  		Entry zapcore.Entry
    40  	}
    41  	tests := []struct {
    42  		name        string
    43  		fields      fields
    44  		wantLevel   zap.AtomicLevel
    45  		wantOpts    []zap.Option
    46  		wantSyncer  zapcore.WriteSyncer
    47  		wantEncoder zapcore.Encoder
    48  		wantSinks   []ZapSink
    49  	}{
    50  		{
    51  			name: "normal",
    52  			fields: fields{
    53  				Level:      "debug",
    54  				Format:     "console",
    55  				Filename:   "",
    56  				MaxSize:    0,
    57  				MaxDays:    0,
    58  				MaxBackups: 0,
    59  
    60  				Entry: zapcore.Entry{Level: zapcore.DebugLevel, Message: "console msg"},
    61  			},
    62  			wantLevel:   zap.NewAtomicLevelAt(zap.DebugLevel),
    63  			wantOpts:    []zap.Option{zap.AddStacktrace(zapcore.FatalLevel), zap.AddCaller()},
    64  			wantSyncer:  getConsoleSyncer(),
    65  			wantEncoder: getLoggerEncoder("console"),
    66  			wantSinks:   []ZapSink{{getLoggerEncoder("console"), getConsoleSyncer()}},
    67  		},
    68  	}
    69  	for _, tt := range tests {
    70  		t.Run(tt.name, func(t *testing.T) {
    71  			cfg := &LogConfig{
    72  				Level:      tt.fields.Level,
    73  				Format:     tt.fields.Format,
    74  				Filename:   tt.fields.Filename,
    75  				MaxSize:    tt.fields.MaxSize,
    76  				MaxDays:    tt.fields.MaxDays,
    77  				MaxBackups: tt.fields.MaxBackups,
    78  
    79  				DisableStore: true,
    80  			}
    81  			require.Equal(t, tt.wantLevel, cfg.getLevel())
    82  			require.Equal(t, len(tt.wantOpts), len(cfg.getOptions()))
    83  			require.Equal(t, tt.wantSyncer, cfg.getSyncer())
    84  			wantMsg, _ := tt.wantEncoder.EncodeEntry(tt.fields.Entry, nil)
    85  			gotMsg, _ := cfg.getEncoder().EncodeEntry(tt.fields.Entry, nil)
    86  			require.Equal(t, wantMsg.String(), gotMsg.String())
    87  			require.Equal(t, len(tt.wantSinks), len(cfg.getSinks()))
    88  		})
    89  	}
    90  }
    91  
    92  func TestSetupMOLogger(t *testing.T) {
    93  	defer leaktest.AfterTest(t)()
    94  	type args struct {
    95  		conf *LogConfig
    96  	}
    97  	tests := []struct {
    98  		name string
    99  		args args
   100  	}{
   101  		{
   102  			name: "console",
   103  			args: args{conf: &LogConfig{
   104  				Level:      zapcore.DebugLevel.String(),
   105  				Format:     "console",
   106  				Filename:   "",
   107  				MaxSize:    512,
   108  				MaxDays:    0,
   109  				MaxBackups: 0,
   110  
   111  				DisableStore: true,
   112  			}},
   113  		},
   114  		{
   115  			name: "json",
   116  			args: args{conf: &LogConfig{
   117  				Level:      zapcore.DebugLevel.String(),
   118  				Format:     "json",
   119  				Filename:   "",
   120  				MaxSize:    512,
   121  				MaxDays:    0,
   122  				MaxBackups: 0,
   123  
   124  				DisableStore: true,
   125  			}},
   126  		},
   127  		/*{
   128  		    // fix gopkg.in/natefinch/lumberjack.v2@v2.0.0/lumberjack.go:390 have a background goroutine for rotate-log
   129  			name: "json",
   130  			args: args{conf: &LogConfig{
   131  				Level:      zapcore.DebugLevel.String(),
   132  				Format:     "json",
   133  				Filename:   path.Join(t.TempDir(), "json.log"),
   134  				MaxSize:    0,
   135  				MaxDays:    0,
   136  				MaxBackups: 0,
   137  
   138  				DisableStore: true,
   139  			}},
   140  		},*/
   141  	}
   142  	for _, tt := range tests {
   143  		t.Run(tt.name, func(t *testing.T) {
   144  			SetupMOLogger(tt.args.conf)
   145  		})
   146  	}
   147  }
   148  
   149  func TestSetupMOLogger_panic(t *testing.T) {
   150  	defer leaktest.AfterTest(t)()
   151  	type args struct {
   152  		conf *LogConfig
   153  	}
   154  	tests := []struct {
   155  		name string
   156  		args args
   157  	}{
   158  		{
   159  			name: "panic",
   160  			args: args{conf: &LogConfig{
   161  				Level:      zapcore.DebugLevel.String(),
   162  				Format:     "panic",
   163  				Filename:   "",
   164  				MaxSize:    512,
   165  				MaxDays:    0,
   166  				MaxBackups: 0,
   167  			}},
   168  		},
   169  	}
   170  	for _, tt := range tests {
   171  		t.Run(tt.name, func(t *testing.T) {
   172  			defer func() {
   173  				if err := recover(); err != nil {
   174  					require.Equal(t, moerr.NewInternalError(context.TODO(), "unsupported log format: %s", tt.args.conf.Format), err)
   175  				} else {
   176  					t.Errorf("not receive panic")
   177  				}
   178  			}()
   179  			SetupMOLogger(tt.args.conf)
   180  		})
   181  	}
   182  }
   183  
   184  func Test_getLoggerEncoder(t *testing.T) {
   185  	defer leaktest.AfterTest(t)()
   186  	type args struct {
   187  		format string
   188  	}
   189  	type fields struct {
   190  		entry  zapcore.Entry
   191  		fields []zap.Field
   192  	}
   193  	tests := []struct {
   194  		name       string
   195  		args       args
   196  		fields     fields
   197  		wantOutput *regexp.Regexp
   198  		foundCnt   int
   199  	}{
   200  		{
   201  			name: "console",
   202  			args: args{
   203  				format: "console",
   204  			},
   205  			fields: fields{
   206  				entry:  zapcore.Entry{Level: zapcore.DebugLevel, Message: "console msg"},
   207  				fields: []zap.Field{},
   208  			},
   209  			// like: 0001/01/01 00:00:00.000000 +0000 DEBUG console msg
   210  			wantOutput: regexp.MustCompile(`\d{4}/\d{2}/\d{2} (\d{2}:{0,1}){3}\.\d{6} \+\d{4} DEBUG console msg`),
   211  			foundCnt:   1,
   212  		},
   213  		{
   214  			name: "json",
   215  			args: args{
   216  				format: "json",
   217  			},
   218  			fields: fields{
   219  				entry:  zapcore.Entry{Level: zapcore.DebugLevel, Message: "json msg"},
   220  				fields: []zap.Field{},
   221  			},
   222  			// like: 0001/01/01 00:00:00.000000 +0000 DEBUG console msg
   223  			wantOutput: regexp.MustCompile(`\{.*"level":"DEBUG".*"msg":"json msg".*\}`),
   224  			foundCnt:   1,
   225  		},
   226  	}
   227  	for _, tt := range tests {
   228  		t.Run(tt.name, func(t *testing.T) {
   229  			got := getLoggerEncoder(tt.args.format)
   230  			require.NotNil(t, got)
   231  			buf, err := got.EncodeEntry(tt.fields.entry, tt.fields.fields)
   232  			require.Nil(t, err)
   233  			t.Logf("encode result: %s", buf.String())
   234  			found := tt.wantOutput.FindAll(buf.Bytes(), -1)
   235  			t.Logf("found: %s", found)
   236  			require.Equal(t, tt.foundCnt, len(found))
   237  		})
   238  	}
   239  }
   240  
   241  func TestSetupMOLogger_panicDir(t *testing.T) {
   242  	type args struct {
   243  		conf *LogConfig
   244  	}
   245  	tests := []struct {
   246  		name string
   247  		args args
   248  	}{
   249  		{
   250  			name: "normal",
   251  			args: args{conf: &LogConfig{
   252  				Level:      zapcore.DebugLevel.String(),
   253  				Format:     "json",
   254  				Filename:   t.TempDir(),
   255  				MaxSize:    512,
   256  				MaxDays:    0,
   257  				MaxBackups: 0,
   258  
   259  				DisableStore: true,
   260  			}},
   261  		},
   262  	}
   263  	for _, tt := range tests {
   264  		t.Run(tt.name, func(t *testing.T) {
   265  			defer func() {
   266  				if err := recover(); err != nil {
   267  					require.Equal(t, "log file can't be a directory", err)
   268  				} else {
   269  					t.Errorf("not receive panic")
   270  				}
   271  			}()
   272  			SetupMOLogger(tt.args.conf)
   273  		})
   274  	}
   275  }