github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/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  }