github.com/tcncloud/wollemi@v0.8.1/adapters/logrus/logger_suite_test.go (about)

     1  package logrus_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"math"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/tcncloud/wollemi/adapters/logrus"
    16  	"github.com/tcncloud/wollemi/ports/logging"
    17  )
    18  
    19  func NewLoggerSuite(t *testing.T) *LoggerSuite {
    20  	return &LoggerSuite{T: t}
    21  }
    22  
    23  type LoggerSuite struct {
    24  	*testing.T
    25  	stdout *bytes.Buffer
    26  	log    *logrus.Logger
    27  }
    28  
    29  func (suite *LoggerSuite) It(name string, yield func(*LoggerSuite)) {
    30  	suite.Helper()
    31  	suite.Run(name, yield)
    32  }
    33  
    34  func (suite *LoggerSuite) Run(name string, yield func(*LoggerSuite)) {
    35  	suite.Helper()
    36  	suite.T.Run(name, func(t *testing.T) {
    37  		suite := NewLoggerSuite(t)
    38  		suite.Helper()
    39  
    40  		suite.stdout = bytes.NewBuffer(nil)
    41  
    42  		suite.log = logrus.NewLogger(suite.stdout)
    43  		suite.log.SetFormatter(&logging.JsonFormatter{})
    44  
    45  		yield(suite)
    46  	})
    47  }
    48  
    49  type Entry struct {
    50  	Level logging.Level
    51  	Msg   string
    52  	Time  time.Time
    53  }
    54  
    55  func (e *Entry) UnmarshalJSON(buf []byte) error {
    56  	var m map[string]string
    57  
    58  	err := json.Unmarshal(buf, &m)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	if s, ok := m["level"]; ok {
    64  		e.Level, err = logging.ParseLevel(s)
    65  		if err != nil {
    66  			return fmt.Errorf("could not parse level: %v", err)
    67  		}
    68  	}
    69  
    70  	if s, ok := m["msg"]; ok {
    71  		e.Msg = s
    72  	}
    73  
    74  	if s, ok := m["time"]; ok {
    75  		e.Time, err = time.Parse(time.RFC3339, s)
    76  		if err != nil {
    77  			return fmt.Errorf("could not parse time: %v", err)
    78  		}
    79  	}
    80  
    81  	return nil
    82  }
    83  
    84  func (t *LoggerSuite) Decode(r io.Reader, entries ...interface{}) {
    85  	decoder := json.NewDecoder(r)
    86  
    87  	for _, entry := range entries {
    88  		require.NoError(t, decoder.Decode(entry))
    89  	}
    90  }
    91  
    92  func (t *LoggerSuite) NowUnix() time.Time {
    93  	return time.Unix(time.Now().Unix(), 0)
    94  }
    95  
    96  func (t *LoggerSuite) BehavesLikeLogsMessage(run func(logging.Logger), lvl logging.Level, msg string) {
    97  	type T = LoggerSuite
    98  
    99  	t.Run(fmt.Sprintf("logs message with time at %s level", lvl), func(t *T) {
   100  		t.log.SetLevel(lvl)
   101  
   102  		min := t.NowUnix()
   103  		run(t.log)
   104  		max := t.NowUnix()
   105  
   106  		delta := time.Duration(math.Ceil(float64(max.Sub(min)) / 2.0))
   107  
   108  		entry := &Entry{}
   109  
   110  		t.Decode(t.stdout, entry)
   111  		assert.Equal(t, lvl, entry.Level)
   112  		assert.Equal(t, msg, entry.Msg)
   113  		assert.WithinDuration(t, min.Add(delta), entry.Time, delta)
   114  	})
   115  
   116  	t.Run(fmt.Sprintf("is not logged when log level less than %s", lvl), func(t *T) {
   117  		t.log.SetLevel(lvl - 1)
   118  		run(t.log)
   119  		assert.Empty(t, t.stdout.String())
   120  	})
   121  }