gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/pkg/katautils/logger_test.go (about) 1 // Copyright (c) 2018 Intel Corporation 2 // Copyright (c) 2018 HyperHQ Inc. 3 // 4 // SPDX-License-Identifier: Apache-2.0 5 // 6 7 package katautils 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "regexp" 13 "strings" 14 "testing" 15 "time" 16 17 "github.com/sirupsen/logrus" 18 "github.com/stretchr/testify/assert" 19 ) 20 21 type testData struct { 22 network string 23 raddr string 24 expectError bool 25 } 26 27 func init() { 28 // Ensure all log levels are logged 29 kataUtilsLogger.Logger.Level = logrus.DebugLevel 30 31 // Discard log output 32 kataUtilsLogger.Logger.Out = ioutil.Discard 33 } 34 35 func TestHandleSystemLog(t *testing.T) { 36 assert := assert.New(t) 37 38 data := []testData{ 39 {"invalid-net-type", "999.999.999.999", true}, 40 {"invalid net-type", "a a ", true}, 41 {"invalid-net-type", ".", true}, 42 {"moo", "999.999.999.999", true}, 43 {"moo", "999.999.999.999:99999999999999999", true}, 44 {"qwerty", "uiop:ftw!", true}, 45 {"", "", false}, 46 } 47 48 for _, d := range data { 49 err := handleSystemLog(d.network, d.raddr) 50 if d.expectError { 51 assert.Error(err, fmt.Sprintf("%+v", d)) 52 } else { 53 assert.NoError(err, fmt.Sprintf("%+v", d)) 54 } 55 } 56 } 57 58 func TestNewSystemLogHook(t *testing.T) { 59 assert := assert.New(t) 60 61 hook, err := newSystemLogHook("", "") 62 assert.NoError(err) 63 64 msg := "wibble" 65 level := logrus.DebugLevel 66 67 logger := logrus.New() 68 69 // ensure all output is displayed 70 logger.Level = logrus.DebugLevel 71 72 // throw away all stdout so that the Format() call 73 // below returns the data in structured form. 74 logger.Out = ioutil.Discard 75 76 entry := &logrus.Entry{ 77 Logger: logger, 78 79 // UTC for time.Parse() 80 Time: time.Now().UTC(), 81 82 Message: msg, 83 Level: level, 84 } 85 86 // call the formatting function directly and see if the output 87 // matches what we expect. 88 bytes, err := hook.formatter.Format(entry) 89 assert.NoError(err) 90 91 output := string(bytes) 92 output = strings.TrimSpace(output) 93 output = strings.Replace(output, `"`, "", -1) 94 95 fields := strings.Fields(output) 96 97 msgFound := "" 98 timeFound := "" 99 levelFound := "" 100 101 // look for the expected fields 102 for _, field := range fields { 103 104 // split each structured field into name and value fields 105 f := strings.Split(field, "=") 106 assert.True(len(f) >= 2) 107 108 switch f[0] { 109 case "level": 110 levelFound = f[1] 111 case "msg": 112 msgFound = f[1] 113 case "time": 114 timeFound = f[1] 115 } 116 } 117 118 assert.Equal(levelFound, level.String()) 119 assert.Equal(msgFound, msg) 120 assert.NotEqual(timeFound, "") 121 122 // Tell time.Parse() how to handle the timestamps by putting it into 123 // the standard golang time format equivalent to: 124 // 125 // "Mon Jan 2 15:04:05 -0700 MST 2006". 126 // 127 expectedTimeFormat := "2006-01-02T15:04:05.999999999Z" 128 129 // Note that time.Parse() assumes a UTC time. 130 _, err = time.Parse(expectedTimeFormat, timeFound) 131 assert.NoError(err) 132 133 // time.Parse() is "clever" but also doesn't check anything more 134 // granular than a second, so let's be completely paranoid and check 135 // via regular expression too. 136 expectedPattern := 137 // YYYY-MM-DD 138 `\d{4}-\d{2}-\d{2}` + 139 // time separator 140 `T` + 141 // HH:MM:SS 142 `\d{2}:\d{2}:\d{2}` + 143 // high-precision separator 144 `.` + 145 // nano-seconds. Note that the quantifier range is 146 // required because the time.RFC3339Nano format 147 // trunctates trailing zeros. 148 `\d{1,9}` + 149 // UTC timezone specifier 150 `Z` 151 152 expectedRE := regexp.MustCompile(expectedPattern) 153 matched := expectedRE.FindAllStringSubmatch(timeFound, -1) 154 assert.NotNil(matched, "expected time in format %q, got %q", expectedPattern, timeFound) 155 }