...

Source file src/github.com/sirupsen/logrus/entry_test.go

Documentation: github.com/sirupsen/logrus

     1  package logrus
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func TestEntryWithError(t *testing.T) {
    14  
    15  	assert := assert.New(t)
    16  
    17  	defer func() {
    18  		ErrorKey = "error"
    19  	}()
    20  
    21  	err := fmt.Errorf("kaboom at layer %d", 4711)
    22  
    23  	assert.Equal(err, WithError(err).Data["error"])
    24  
    25  	logger := New()
    26  	logger.Out = &bytes.Buffer{}
    27  	entry := NewEntry(logger)
    28  
    29  	assert.Equal(err, entry.WithError(err).Data["error"])
    30  
    31  	ErrorKey = "err"
    32  
    33  	assert.Equal(err, entry.WithError(err).Data["err"])
    34  
    35  }
    36  
    37  func TestEntryWithContext(t *testing.T) {
    38  	assert := assert.New(t)
    39  	ctx := context.WithValue(context.Background(), "foo", "bar")
    40  
    41  	assert.Equal(ctx, WithContext(ctx).Context)
    42  
    43  	logger := New()
    44  	logger.Out = &bytes.Buffer{}
    45  	entry := NewEntry(logger)
    46  
    47  	assert.Equal(ctx, entry.WithContext(ctx).Context)
    48  }
    49  
    50  func TestEntryWithContextCopiesData(t *testing.T) {
    51  	assert := assert.New(t)
    52  
    53  	// Initialize a parent Entry object with a key/value set in its Data map
    54  	logger := New()
    55  	logger.Out = &bytes.Buffer{}
    56  	parentEntry := NewEntry(logger).WithField("parentKey", "parentValue")
    57  
    58  	// Create two children Entry objects from the parent in different contexts
    59  	ctx1 := context.WithValue(context.Background(), "foo", "bar")
    60  	childEntry1 := parentEntry.WithContext(ctx1)
    61  	assert.Equal(ctx1, childEntry1.Context)
    62  
    63  	ctx2 := context.WithValue(context.Background(), "bar", "baz")
    64  	childEntry2 := parentEntry.WithContext(ctx2)
    65  	assert.Equal(ctx2, childEntry2.Context)
    66  	assert.NotEqual(ctx1, ctx2)
    67  
    68  	// Ensure that data set in the parent Entry are preserved to both children
    69  	assert.Equal("parentValue", childEntry1.Data["parentKey"])
    70  	assert.Equal("parentValue", childEntry2.Data["parentKey"])
    71  
    72  	// Modify data stored in the child entry
    73  	childEntry1.Data["childKey"] = "childValue"
    74  
    75  	// Verify that data is successfully stored in the child it was set on
    76  	val, exists := childEntry1.Data["childKey"]
    77  	assert.True(exists)
    78  	assert.Equal("childValue", val)
    79  
    80  	// Verify that the data change to child 1 has not affected its sibling
    81  	val, exists = childEntry2.Data["childKey"]
    82  	assert.False(exists)
    83  	assert.Empty(val)
    84  
    85  	// Verify that the data change to child 1 has not affected its parent
    86  	val, exists = parentEntry.Data["childKey"]
    87  	assert.False(exists)
    88  	assert.Empty(val)
    89  }
    90  
    91  func TestEntryWithTimeCopiesData(t *testing.T) {
    92  	assert := assert.New(t)
    93  
    94  	// Initialize a parent Entry object with a key/value set in its Data map
    95  	logger := New()
    96  	logger.Out = &bytes.Buffer{}
    97  	parentEntry := NewEntry(logger).WithField("parentKey", "parentValue")
    98  
    99  	// Create two children Entry objects from the parent with two different times
   100  	childEntry1 := parentEntry.WithTime(time.Now().AddDate(0, 0, 1))
   101  	childEntry2 := parentEntry.WithTime(time.Now().AddDate(0, 0, 2))
   102  
   103  	// Ensure that data set in the parent Entry are preserved to both children
   104  	assert.Equal("parentValue", childEntry1.Data["parentKey"])
   105  	assert.Equal("parentValue", childEntry2.Data["parentKey"])
   106  
   107  	// Modify data stored in the child entry
   108  	childEntry1.Data["childKey"] = "childValue"
   109  
   110  	// Verify that data is successfully stored in the child it was set on
   111  	val, exists := childEntry1.Data["childKey"]
   112  	assert.True(exists)
   113  	assert.Equal("childValue", val)
   114  
   115  	// Verify that the data change to child 1 has not affected its sibling
   116  	val, exists = childEntry2.Data["childKey"]
   117  	assert.False(exists)
   118  	assert.Empty(val)
   119  
   120  	// Verify that the data change to child 1 has not affected its parent
   121  	val, exists = parentEntry.Data["childKey"]
   122  	assert.False(exists)
   123  	assert.Empty(val)
   124  }
   125  
   126  func TestEntryPanicln(t *testing.T) {
   127  	errBoom := fmt.Errorf("boom time")
   128  
   129  	defer func() {
   130  		p := recover()
   131  		assert.NotNil(t, p)
   132  
   133  		switch pVal := p.(type) {
   134  		case *Entry:
   135  			assert.Equal(t, "kaboom", pVal.Message)
   136  			assert.Equal(t, errBoom, pVal.Data["err"])
   137  		default:
   138  			t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
   139  		}
   140  	}()
   141  
   142  	logger := New()
   143  	logger.Out = &bytes.Buffer{}
   144  	entry := NewEntry(logger)
   145  	entry.WithField("err", errBoom).Panicln("kaboom")
   146  }
   147  
   148  func TestEntryPanicf(t *testing.T) {
   149  	errBoom := fmt.Errorf("boom again")
   150  
   151  	defer func() {
   152  		p := recover()
   153  		assert.NotNil(t, p)
   154  
   155  		switch pVal := p.(type) {
   156  		case *Entry:
   157  			assert.Equal(t, "kaboom true", pVal.Message)
   158  			assert.Equal(t, errBoom, pVal.Data["err"])
   159  		default:
   160  			t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
   161  		}
   162  	}()
   163  
   164  	logger := New()
   165  	logger.Out = &bytes.Buffer{}
   166  	entry := NewEntry(logger)
   167  	entry.WithField("err", errBoom).Panicf("kaboom %v", true)
   168  }
   169  
   170  func TestEntryPanic(t *testing.T) {
   171  	errBoom := fmt.Errorf("boom again")
   172  
   173  	defer func() {
   174  		p := recover()
   175  		assert.NotNil(t, p)
   176  
   177  		switch pVal := p.(type) {
   178  		case *Entry:
   179  			assert.Equal(t, "kaboom", pVal.Message)
   180  			assert.Equal(t, errBoom, pVal.Data["err"])
   181  		default:
   182  			t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
   183  		}
   184  	}()
   185  
   186  	logger := New()
   187  	logger.Out = &bytes.Buffer{}
   188  	entry := NewEntry(logger)
   189  	entry.WithField("err", errBoom).Panic("kaboom")
   190  }
   191  
   192  const (
   193  	badMessage   = "this is going to panic"
   194  	panicMessage = "this is broken"
   195  )
   196  
   197  type panickyHook struct{}
   198  
   199  func (p *panickyHook) Levels() []Level {
   200  	return []Level{InfoLevel}
   201  }
   202  
   203  func (p *panickyHook) Fire(entry *Entry) error {
   204  	if entry.Message == badMessage {
   205  		panic(panicMessage)
   206  	}
   207  
   208  	return nil
   209  }
   210  
   211  func TestEntryHooksPanic(t *testing.T) {
   212  	logger := New()
   213  	logger.Out = &bytes.Buffer{}
   214  	logger.Level = InfoLevel
   215  	logger.Hooks.Add(&panickyHook{})
   216  
   217  	defer func() {
   218  		p := recover()
   219  		assert.NotNil(t, p)
   220  		assert.Equal(t, panicMessage, p)
   221  
   222  		entry := NewEntry(logger)
   223  		entry.Info("another message")
   224  	}()
   225  
   226  	entry := NewEntry(logger)
   227  	entry.Info(badMessage)
   228  }
   229  
   230  func TestEntryWithIncorrectField(t *testing.T) {
   231  	assert := assert.New(t)
   232  
   233  	fn := func() {}
   234  
   235  	e := Entry{Logger: New()}
   236  	eWithFunc := e.WithFields(Fields{"func": fn})
   237  	eWithFuncPtr := e.WithFields(Fields{"funcPtr": &fn})
   238  
   239  	assert.Equal(eWithFunc.err, `can not add field "func"`)
   240  	assert.Equal(eWithFuncPtr.err, `can not add field "funcPtr"`)
   241  
   242  	eWithFunc = eWithFunc.WithField("not_a_func", "it is a string")
   243  	eWithFuncPtr = eWithFuncPtr.WithField("not_a_func", "it is a string")
   244  
   245  	assert.Equal(eWithFunc.err, `can not add field "func"`)
   246  	assert.Equal(eWithFuncPtr.err, `can not add field "funcPtr"`)
   247  
   248  	eWithFunc = eWithFunc.WithTime(time.Now())
   249  	eWithFuncPtr = eWithFuncPtr.WithTime(time.Now())
   250  
   251  	assert.Equal(eWithFunc.err, `can not add field "func"`)
   252  	assert.Equal(eWithFuncPtr.err, `can not add field "funcPtr"`)
   253  }
   254  
   255  func TestEntryLogfLevel(t *testing.T) {
   256  	logger := New()
   257  	buffer := &bytes.Buffer{}
   258  	logger.Out = buffer
   259  	logger.SetLevel(InfoLevel)
   260  	entry := NewEntry(logger)
   261  
   262  	entry.Logf(DebugLevel, "%s", "debug")
   263  	assert.NotContains(t, buffer.String(), "debug")
   264  
   265  	entry.Logf(WarnLevel, "%s", "warn")
   266  	assert.Contains(t, buffer.String(), "warn")
   267  }
   268  
   269  func TestEntryReportCallerRace(t *testing.T) {
   270  	logger := New()
   271  	entry := NewEntry(logger)
   272  
   273  	// logging before SetReportCaller has the highest chance of causing a race condition
   274  	// to be detected, but doing it twice just to increase the likelyhood of detecting the race
   275  	go func() {
   276  		entry.Info("should not race")
   277  	}()
   278  	go func() {
   279  		logger.SetReportCaller(true)
   280  	}()
   281  	go func() {
   282  		entry.Info("should not race")
   283  	}()
   284  }
   285  
   286  func TestEntryFormatterRace(t *testing.T) {
   287  	logger := New()
   288  	entry := NewEntry(logger)
   289  
   290  	// logging before SetReportCaller has the highest chance of causing a race condition
   291  	// to be detected, but doing it twice just to increase the likelyhood of detecting the race
   292  	go func() {
   293  		entry.Info("should not race")
   294  	}()
   295  	go func() {
   296  		logger.SetFormatter(&TextFormatter{})
   297  	}()
   298  	go func() {
   299  		entry.Info("should not race")
   300  	}()
   301  }
   302  

View as plain text