...

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

Documentation: github.com/sirupsen/logrus

     1  package logrus_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"runtime"
    11  	"sync"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  
    18  	. "github.com/sirupsen/logrus"
    19  	. "github.com/sirupsen/logrus/internal/testutils"
    20  )
    21  
    22  // TestReportCaller verifies that when ReportCaller is set, the 'func' field
    23  // is added, and when it is unset it is not set or modified
    24  // Verify that functions within the Logrus package aren't considered when
    25  // discovering the caller.
    26  func TestReportCallerWhenConfigured(t *testing.T) {
    27  	LogAndAssertJSON(t, func(log *Logger) {
    28  		log.ReportCaller = false
    29  		log.Print("testNoCaller")
    30  	}, func(fields Fields) {
    31  		assert.Equal(t, "testNoCaller", fields["msg"])
    32  		assert.Equal(t, "info", fields["level"])
    33  		assert.Equal(t, nil, fields["func"])
    34  	})
    35  
    36  	LogAndAssertJSON(t, func(log *Logger) {
    37  		log.ReportCaller = true
    38  		log.Print("testWithCaller")
    39  	}, func(fields Fields) {
    40  		assert.Equal(t, "testWithCaller", fields["msg"])
    41  		assert.Equal(t, "info", fields["level"])
    42  		assert.Equal(t,
    43  			"github.com/sirupsen/logrus_test.TestReportCallerWhenConfigured.func3", fields["func"])
    44  	})
    45  }
    46  
    47  func logSomething(t *testing.T, message string) Fields {
    48  	var buffer bytes.Buffer
    49  	var fields Fields
    50  
    51  	logger := New()
    52  	logger.Out = &buffer
    53  	logger.Formatter = new(JSONFormatter)
    54  	logger.ReportCaller = true
    55  
    56  	entry := logger.WithFields(Fields{
    57  		"foo": "bar",
    58  	})
    59  
    60  	entry.Info(message)
    61  
    62  	err := json.Unmarshal(buffer.Bytes(), &fields)
    63  	assert.Nil(t, err)
    64  
    65  	return fields
    66  }
    67  
    68  // TestReportCallerHelperDirect - verify reference when logging from a regular function
    69  func TestReportCallerHelperDirect(t *testing.T) {
    70  	fields := logSomething(t, "direct")
    71  
    72  	assert.Equal(t, "direct", fields["msg"])
    73  	assert.Equal(t, "info", fields["level"])
    74  	assert.Regexp(t, "github.com/.*/logrus_test.logSomething", fields["func"])
    75  }
    76  
    77  // TestReportCallerHelperDirect - verify reference when logging from a function called via pointer
    78  func TestReportCallerHelperViaPointer(t *testing.T) {
    79  	fptr := logSomething
    80  	fields := fptr(t, "via pointer")
    81  
    82  	assert.Equal(t, "via pointer", fields["msg"])
    83  	assert.Equal(t, "info", fields["level"])
    84  	assert.Regexp(t, "github.com/.*/logrus_test.logSomething", fields["func"])
    85  }
    86  
    87  func TestPrint(t *testing.T) {
    88  	LogAndAssertJSON(t, func(log *Logger) {
    89  		log.Print("test")
    90  	}, func(fields Fields) {
    91  		assert.Equal(t, "test", fields["msg"])
    92  		assert.Equal(t, "info", fields["level"])
    93  	})
    94  }
    95  
    96  func TestInfo(t *testing.T) {
    97  	LogAndAssertJSON(t, func(log *Logger) {
    98  		log.Info("test")
    99  	}, func(fields Fields) {
   100  		assert.Equal(t, "test", fields["msg"])
   101  		assert.Equal(t, "info", fields["level"])
   102  	})
   103  }
   104  
   105  func TestWarn(t *testing.T) {
   106  	LogAndAssertJSON(t, func(log *Logger) {
   107  		log.Warn("test")
   108  	}, func(fields Fields) {
   109  		assert.Equal(t, "test", fields["msg"])
   110  		assert.Equal(t, "warning", fields["level"])
   111  	})
   112  }
   113  
   114  func TestLog(t *testing.T) {
   115  	LogAndAssertJSON(t, func(log *Logger) {
   116  		log.Log(WarnLevel, "test")
   117  	}, func(fields Fields) {
   118  		assert.Equal(t, "test", fields["msg"])
   119  		assert.Equal(t, "warning", fields["level"])
   120  	})
   121  }
   122  
   123  func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
   124  	LogAndAssertJSON(t, func(log *Logger) {
   125  		log.Infoln("test", "test")
   126  	}, func(fields Fields) {
   127  		assert.Equal(t, "test test", fields["msg"])
   128  	})
   129  }
   130  
   131  func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
   132  	LogAndAssertJSON(t, func(log *Logger) {
   133  		log.Infoln("test", 10)
   134  	}, func(fields Fields) {
   135  		assert.Equal(t, "test 10", fields["msg"])
   136  	})
   137  }
   138  
   139  func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
   140  	LogAndAssertJSON(t, func(log *Logger) {
   141  		log.Infoln(10, 10)
   142  	}, func(fields Fields) {
   143  		assert.Equal(t, "10 10", fields["msg"])
   144  	})
   145  }
   146  
   147  func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
   148  	LogAndAssertJSON(t, func(log *Logger) {
   149  		log.Infoln(10, 10)
   150  	}, func(fields Fields) {
   151  		assert.Equal(t, "10 10", fields["msg"])
   152  	})
   153  }
   154  
   155  func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
   156  	LogAndAssertJSON(t, func(log *Logger) {
   157  		log.Info("test", 10)
   158  	}, func(fields Fields) {
   159  		assert.Equal(t, "test10", fields["msg"])
   160  	})
   161  }
   162  
   163  func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
   164  	LogAndAssertJSON(t, func(log *Logger) {
   165  		log.Info("test", "test")
   166  	}, func(fields Fields) {
   167  		assert.Equal(t, "testtest", fields["msg"])
   168  	})
   169  }
   170  
   171  func TestWithFieldsShouldAllowAssignments(t *testing.T) {
   172  	var buffer bytes.Buffer
   173  	var fields Fields
   174  
   175  	logger := New()
   176  	logger.Out = &buffer
   177  	logger.Formatter = new(JSONFormatter)
   178  
   179  	localLog := logger.WithFields(Fields{
   180  		"key1": "value1",
   181  	})
   182  
   183  	localLog.WithField("key2", "value2").Info("test")
   184  	err := json.Unmarshal(buffer.Bytes(), &fields)
   185  	assert.Nil(t, err)
   186  
   187  	assert.Equal(t, "value2", fields["key2"])
   188  	assert.Equal(t, "value1", fields["key1"])
   189  
   190  	buffer = bytes.Buffer{}
   191  	fields = Fields{}
   192  	localLog.Info("test")
   193  	err = json.Unmarshal(buffer.Bytes(), &fields)
   194  	assert.Nil(t, err)
   195  
   196  	_, ok := fields["key2"]
   197  	assert.Equal(t, false, ok)
   198  	assert.Equal(t, "value1", fields["key1"])
   199  }
   200  
   201  func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
   202  	LogAndAssertJSON(t, func(log *Logger) {
   203  		log.WithField("msg", "hello").Info("test")
   204  	}, func(fields Fields) {
   205  		assert.Equal(t, "test", fields["msg"])
   206  	})
   207  }
   208  
   209  func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
   210  	LogAndAssertJSON(t, func(log *Logger) {
   211  		log.WithField("msg", "hello").Info("test")
   212  	}, func(fields Fields) {
   213  		assert.Equal(t, "test", fields["msg"])
   214  		assert.Equal(t, "hello", fields["fields.msg"])
   215  	})
   216  }
   217  
   218  func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
   219  	LogAndAssertJSON(t, func(log *Logger) {
   220  		log.WithField("time", "hello").Info("test")
   221  	}, func(fields Fields) {
   222  		assert.Equal(t, "hello", fields["fields.time"])
   223  	})
   224  }
   225  
   226  func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
   227  	LogAndAssertJSON(t, func(log *Logger) {
   228  		log.WithField("level", 1).Info("test")
   229  	}, func(fields Fields) {
   230  		assert.Equal(t, "info", fields["level"])
   231  		assert.Equal(t, 1.0, fields["fields.level"]) // JSON has floats only
   232  	})
   233  }
   234  
   235  func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
   236  	LogAndAssertText(t, func(log *Logger) {
   237  		ll := log.WithField("herp", "derp")
   238  		ll.Info("hello")
   239  		ll.Info("bye")
   240  	}, func(fields map[string]string) {
   241  		for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
   242  			if _, ok := fields[fieldName]; ok {
   243  				t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
   244  			}
   245  		}
   246  	})
   247  }
   248  
   249  func TestWithTimeShouldOverrideTime(t *testing.T) {
   250  	now := time.Now().Add(24 * time.Hour)
   251  
   252  	LogAndAssertJSON(t, func(log *Logger) {
   253  		log.WithTime(now).Info("foobar")
   254  	}, func(fields Fields) {
   255  		assert.Equal(t, fields["time"], now.Format(time.RFC3339))
   256  	})
   257  }
   258  
   259  func TestWithTimeShouldNotOverrideFields(t *testing.T) {
   260  	now := time.Now().Add(24 * time.Hour)
   261  
   262  	LogAndAssertJSON(t, func(log *Logger) {
   263  		log.WithField("herp", "derp").WithTime(now).Info("blah")
   264  	}, func(fields Fields) {
   265  		assert.Equal(t, fields["time"], now.Format(time.RFC3339))
   266  		assert.Equal(t, fields["herp"], "derp")
   267  	})
   268  }
   269  
   270  func TestWithFieldShouldNotOverrideTime(t *testing.T) {
   271  	now := time.Now().Add(24 * time.Hour)
   272  
   273  	LogAndAssertJSON(t, func(log *Logger) {
   274  		log.WithTime(now).WithField("herp", "derp").Info("blah")
   275  	}, func(fields Fields) {
   276  		assert.Equal(t, fields["time"], now.Format(time.RFC3339))
   277  		assert.Equal(t, fields["herp"], "derp")
   278  	})
   279  }
   280  
   281  func TestTimeOverrideMultipleLogs(t *testing.T) {
   282  	var buffer bytes.Buffer
   283  	var firstFields, secondFields Fields
   284  
   285  	logger := New()
   286  	logger.Out = &buffer
   287  	formatter := new(JSONFormatter)
   288  	formatter.TimestampFormat = time.StampMilli
   289  	logger.Formatter = formatter
   290  
   291  	llog := logger.WithField("herp", "derp")
   292  	llog.Info("foo")
   293  
   294  	err := json.Unmarshal(buffer.Bytes(), &firstFields)
   295  	assert.NoError(t, err, "should have decoded first message")
   296  
   297  	buffer.Reset()
   298  
   299  	time.Sleep(10 * time.Millisecond)
   300  	llog.Info("bar")
   301  
   302  	err = json.Unmarshal(buffer.Bytes(), &secondFields)
   303  	assert.NoError(t, err, "should have decoded second message")
   304  
   305  	assert.NotEqual(t, firstFields["time"], secondFields["time"], "timestamps should not be equal")
   306  }
   307  
   308  func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
   309  
   310  	var buffer bytes.Buffer
   311  	var fields Fields
   312  
   313  	logger := New()
   314  	logger.Out = &buffer
   315  	logger.Formatter = new(JSONFormatter)
   316  
   317  	llog := logger.WithField("context", "eating raw fish")
   318  
   319  	llog.Info("looks delicious")
   320  
   321  	err := json.Unmarshal(buffer.Bytes(), &fields)
   322  	assert.NoError(t, err, "should have decoded first message")
   323  	assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
   324  	assert.Equal(t, fields["msg"], "looks delicious")
   325  	assert.Equal(t, fields["context"], "eating raw fish")
   326  
   327  	buffer.Reset()
   328  
   329  	llog.Warn("omg it is!")
   330  
   331  	err = json.Unmarshal(buffer.Bytes(), &fields)
   332  	assert.NoError(t, err, "should have decoded second message")
   333  	assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
   334  	assert.Equal(t, "omg it is!", fields["msg"])
   335  	assert.Equal(t, "eating raw fish", fields["context"])
   336  	assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
   337  
   338  }
   339  
   340  func TestNestedLoggingReportsCorrectCaller(t *testing.T) {
   341  	var buffer bytes.Buffer
   342  	var fields Fields
   343  
   344  	logger := New()
   345  	logger.Out = &buffer
   346  	logger.Formatter = new(JSONFormatter)
   347  	logger.ReportCaller = true
   348  
   349  	llog := logger.WithField("context", "eating raw fish")
   350  
   351  	llog.Info("looks delicious")
   352  	_, _, line, _ := runtime.Caller(0)
   353  
   354  	err := json.Unmarshal(buffer.Bytes(), &fields)
   355  	require.NoError(t, err, "should have decoded first message")
   356  	assert.Equal(t, 6, len(fields), "should have msg/time/level/func/context fields")
   357  	assert.Equal(t, "looks delicious", fields["msg"])
   358  	assert.Equal(t, "eating raw fish", fields["context"])
   359  	assert.Equal(t,
   360  		"github.com/sirupsen/logrus_test.TestNestedLoggingReportsCorrectCaller", fields["func"])
   361  	cwd, err := os.Getwd()
   362  	require.NoError(t, err)
   363  	assert.Equal(t, filepath.ToSlash(fmt.Sprintf("%s/logrus_test.go:%d", cwd, line-1)), filepath.ToSlash(fields["file"].(string)))
   364  
   365  	buffer.Reset()
   366  
   367  	logger.WithFields(Fields{
   368  		"Clyde": "Stubblefield",
   369  	}).WithFields(Fields{
   370  		"Jab'o": "Starks",
   371  	}).WithFields(Fields{
   372  		"uri": "https://www.youtube.com/watch?v=V5DTznu-9v0",
   373  	}).WithFields(Fields{
   374  		"func": "y drummer",
   375  	}).WithFields(Fields{
   376  		"James": "Brown",
   377  	}).Print("The hardest workin' man in show business")
   378  	_, _, line, _ = runtime.Caller(0)
   379  
   380  	err = json.Unmarshal(buffer.Bytes(), &fields)
   381  	assert.NoError(t, err, "should have decoded second message")
   382  	assert.Equal(t, 11, len(fields), "should have all builtin fields plus foo,bar,baz,...")
   383  	assert.Equal(t, "Stubblefield", fields["Clyde"])
   384  	assert.Equal(t, "Starks", fields["Jab'o"])
   385  	assert.Equal(t, "https://www.youtube.com/watch?v=V5DTznu-9v0", fields["uri"])
   386  	assert.Equal(t, "y drummer", fields["fields.func"])
   387  	assert.Equal(t, "Brown", fields["James"])
   388  	assert.Equal(t, "The hardest workin' man in show business", fields["msg"])
   389  	assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
   390  	assert.Equal(t,
   391  		"github.com/sirupsen/logrus_test.TestNestedLoggingReportsCorrectCaller", fields["func"])
   392  	require.NoError(t, err)
   393  	assert.Equal(t, filepath.ToSlash(fmt.Sprintf("%s/logrus_test.go:%d", cwd, line-1)), filepath.ToSlash(fields["file"].(string)))
   394  
   395  	logger.ReportCaller = false // return to default value
   396  }
   397  
   398  func logLoop(iterations int, reportCaller bool) {
   399  	var buffer bytes.Buffer
   400  
   401  	logger := New()
   402  	logger.Out = &buffer
   403  	logger.Formatter = new(JSONFormatter)
   404  	logger.ReportCaller = reportCaller
   405  
   406  	for i := 0; i < iterations; i++ {
   407  		logger.Infof("round %d of %d", i, iterations)
   408  	}
   409  }
   410  
   411  // Assertions for upper bounds to reporting overhead
   412  func TestCallerReportingOverhead(t *testing.T) {
   413  	iterations := 5000
   414  	before := time.Now()
   415  	logLoop(iterations, false)
   416  	during := time.Now()
   417  	logLoop(iterations, true)
   418  	after := time.Now()
   419  
   420  	elapsedNotReporting := during.Sub(before).Nanoseconds()
   421  	elapsedReporting := after.Sub(during).Nanoseconds()
   422  
   423  	maxDelta := 1 * time.Second
   424  	assert.WithinDuration(t, during, before, maxDelta,
   425  		"%d log calls without caller name lookup takes less than %d second(s) (was %d nanoseconds)",
   426  		iterations, maxDelta.Seconds(), elapsedNotReporting)
   427  	assert.WithinDuration(t, after, during, maxDelta,
   428  		"%d log calls without caller name lookup takes less than %d second(s) (was %d nanoseconds)",
   429  		iterations, maxDelta.Seconds(), elapsedReporting)
   430  }
   431  
   432  // benchmarks for both with and without caller-function reporting
   433  func BenchmarkWithoutCallerTracing(b *testing.B) {
   434  	for i := 0; i < b.N; i++ {
   435  		logLoop(1000, false)
   436  	}
   437  }
   438  
   439  func BenchmarkWithCallerTracing(b *testing.B) {
   440  	for i := 0; i < b.N; i++ {
   441  		logLoop(1000, true)
   442  	}
   443  }
   444  
   445  func TestConvertLevelToString(t *testing.T) {
   446  	assert.Equal(t, "trace", TraceLevel.String())
   447  	assert.Equal(t, "debug", DebugLevel.String())
   448  	assert.Equal(t, "info", InfoLevel.String())
   449  	assert.Equal(t, "warning", WarnLevel.String())
   450  	assert.Equal(t, "error", ErrorLevel.String())
   451  	assert.Equal(t, "fatal", FatalLevel.String())
   452  	assert.Equal(t, "panic", PanicLevel.String())
   453  }
   454  
   455  func TestParseLevel(t *testing.T) {
   456  	l, err := ParseLevel("panic")
   457  	assert.Nil(t, err)
   458  	assert.Equal(t, PanicLevel, l)
   459  
   460  	l, err = ParseLevel("PANIC")
   461  	assert.Nil(t, err)
   462  	assert.Equal(t, PanicLevel, l)
   463  
   464  	l, err = ParseLevel("fatal")
   465  	assert.Nil(t, err)
   466  	assert.Equal(t, FatalLevel, l)
   467  
   468  	l, err = ParseLevel("FATAL")
   469  	assert.Nil(t, err)
   470  	assert.Equal(t, FatalLevel, l)
   471  
   472  	l, err = ParseLevel("error")
   473  	assert.Nil(t, err)
   474  	assert.Equal(t, ErrorLevel, l)
   475  
   476  	l, err = ParseLevel("ERROR")
   477  	assert.Nil(t, err)
   478  	assert.Equal(t, ErrorLevel, l)
   479  
   480  	l, err = ParseLevel("warn")
   481  	assert.Nil(t, err)
   482  	assert.Equal(t, WarnLevel, l)
   483  
   484  	l, err = ParseLevel("WARN")
   485  	assert.Nil(t, err)
   486  	assert.Equal(t, WarnLevel, l)
   487  
   488  	l, err = ParseLevel("warning")
   489  	assert.Nil(t, err)
   490  	assert.Equal(t, WarnLevel, l)
   491  
   492  	l, err = ParseLevel("WARNING")
   493  	assert.Nil(t, err)
   494  	assert.Equal(t, WarnLevel, l)
   495  
   496  	l, err = ParseLevel("info")
   497  	assert.Nil(t, err)
   498  	assert.Equal(t, InfoLevel, l)
   499  
   500  	l, err = ParseLevel("INFO")
   501  	assert.Nil(t, err)
   502  	assert.Equal(t, InfoLevel, l)
   503  
   504  	l, err = ParseLevel("debug")
   505  	assert.Nil(t, err)
   506  	assert.Equal(t, DebugLevel, l)
   507  
   508  	l, err = ParseLevel("DEBUG")
   509  	assert.Nil(t, err)
   510  	assert.Equal(t, DebugLevel, l)
   511  
   512  	l, err = ParseLevel("trace")
   513  	assert.Nil(t, err)
   514  	assert.Equal(t, TraceLevel, l)
   515  
   516  	l, err = ParseLevel("TRACE")
   517  	assert.Nil(t, err)
   518  	assert.Equal(t, TraceLevel, l)
   519  
   520  	l, err = ParseLevel("invalid")
   521  	assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
   522  }
   523  
   524  func TestGetSetLevelRace(t *testing.T) {
   525  	wg := sync.WaitGroup{}
   526  	for i := 0; i < 100; i++ {
   527  		wg.Add(1)
   528  		go func(i int) {
   529  			defer wg.Done()
   530  			if i%2 == 0 {
   531  				SetLevel(InfoLevel)
   532  			} else {
   533  				GetLevel()
   534  			}
   535  		}(i)
   536  
   537  	}
   538  	wg.Wait()
   539  }
   540  
   541  func TestLoggingRace(t *testing.T) {
   542  	logger := New()
   543  
   544  	var wg sync.WaitGroup
   545  	wg.Add(100)
   546  
   547  	for i := 0; i < 100; i++ {
   548  		go func() {
   549  			logger.Info("info")
   550  			wg.Done()
   551  		}()
   552  	}
   553  	wg.Wait()
   554  }
   555  
   556  func TestLoggingRaceWithHooksOnEntry(t *testing.T) {
   557  	logger := New()
   558  	hook := new(ModifyHook)
   559  	logger.AddHook(hook)
   560  	entry := logger.WithField("context", "clue")
   561  
   562  	var wg sync.WaitGroup
   563  	wg.Add(100)
   564  
   565  	for i := 0; i < 100; i++ {
   566  		go func() {
   567  			entry.Info("info")
   568  			wg.Done()
   569  		}()
   570  	}
   571  	wg.Wait()
   572  }
   573  
   574  func TestReplaceHooks(t *testing.T) {
   575  	old, cur := &TestHook{}, &TestHook{}
   576  
   577  	logger := New()
   578  	logger.SetOutput(ioutil.Discard)
   579  	logger.AddHook(old)
   580  
   581  	hooks := make(LevelHooks)
   582  	hooks.Add(cur)
   583  	replaced := logger.ReplaceHooks(hooks)
   584  
   585  	logger.Info("test")
   586  
   587  	assert.Equal(t, old.Fired, false)
   588  	assert.Equal(t, cur.Fired, true)
   589  
   590  	logger.ReplaceHooks(replaced)
   591  	logger.Info("test")
   592  	assert.Equal(t, old.Fired, true)
   593  }
   594  
   595  // Compile test
   596  func TestLogrusInterfaces(t *testing.T) {
   597  	var buffer bytes.Buffer
   598  	// This verifies FieldLogger and Ext1FieldLogger work as designed.
   599  	// Please don't use them. Use Logger and Entry directly.
   600  	fn := func(xl Ext1FieldLogger) {
   601  		var l FieldLogger = xl
   602  		b := l.WithField("key", "value")
   603  		b.Debug("Test")
   604  	}
   605  	// test logger
   606  	logger := New()
   607  	logger.Out = &buffer
   608  	fn(logger)
   609  
   610  	// test Entry
   611  	e := logger.WithField("another", "value")
   612  	fn(e)
   613  }
   614  
   615  // Implements io.Writer using channels for synchronization, so we can wait on
   616  // the Entry.Writer goroutine to write in a non-racey way. This does assume that
   617  // there is a single call to Logger.Out for each message.
   618  type channelWriter chan []byte
   619  
   620  func (cw channelWriter) Write(p []byte) (int, error) {
   621  	cw <- p
   622  	return len(p), nil
   623  }
   624  
   625  func TestEntryWriter(t *testing.T) {
   626  	cw := channelWriter(make(chan []byte, 1))
   627  	log := New()
   628  	log.Out = cw
   629  	log.Formatter = new(JSONFormatter)
   630  	log.WithField("foo", "bar").WriterLevel(WarnLevel).Write([]byte("hello\n"))
   631  
   632  	bs := <-cw
   633  	var fields Fields
   634  	err := json.Unmarshal(bs, &fields)
   635  	assert.Nil(t, err)
   636  	assert.Equal(t, fields["foo"], "bar")
   637  	assert.Equal(t, fields["level"], "warning")
   638  }
   639  
   640  func TestLogLevelEnabled(t *testing.T) {
   641  	log := New()
   642  	log.SetLevel(PanicLevel)
   643  	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
   644  	assert.Equal(t, false, log.IsLevelEnabled(FatalLevel))
   645  	assert.Equal(t, false, log.IsLevelEnabled(ErrorLevel))
   646  	assert.Equal(t, false, log.IsLevelEnabled(WarnLevel))
   647  	assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
   648  	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
   649  	assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
   650  
   651  	log.SetLevel(FatalLevel)
   652  	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
   653  	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
   654  	assert.Equal(t, false, log.IsLevelEnabled(ErrorLevel))
   655  	assert.Equal(t, false, log.IsLevelEnabled(WarnLevel))
   656  	assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
   657  	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
   658  	assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
   659  
   660  	log.SetLevel(ErrorLevel)
   661  	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
   662  	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
   663  	assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel))
   664  	assert.Equal(t, false, log.IsLevelEnabled(WarnLevel))
   665  	assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
   666  	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
   667  	assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
   668  
   669  	log.SetLevel(WarnLevel)
   670  	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
   671  	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
   672  	assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel))
   673  	assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
   674  	assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
   675  	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
   676  	assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
   677  
   678  	log.SetLevel(InfoLevel)
   679  	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
   680  	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
   681  	assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel))
   682  	assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
   683  	assert.Equal(t, true, log.IsLevelEnabled(InfoLevel))
   684  	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
   685  	assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
   686  
   687  	log.SetLevel(DebugLevel)
   688  	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
   689  	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
   690  	assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel))
   691  	assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
   692  	assert.Equal(t, true, log.IsLevelEnabled(InfoLevel))
   693  	assert.Equal(t, true, log.IsLevelEnabled(DebugLevel))
   694  	assert.Equal(t, false, log.IsLevelEnabled(TraceLevel))
   695  
   696  	log.SetLevel(TraceLevel)
   697  	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
   698  	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
   699  	assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel))
   700  	assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
   701  	assert.Equal(t, true, log.IsLevelEnabled(InfoLevel))
   702  	assert.Equal(t, true, log.IsLevelEnabled(DebugLevel))
   703  	assert.Equal(t, true, log.IsLevelEnabled(TraceLevel))
   704  }
   705  
   706  func TestReportCallerOnTextFormatter(t *testing.T) {
   707  	l := New()
   708  
   709  	l.Formatter.(*TextFormatter).ForceColors = true
   710  	l.Formatter.(*TextFormatter).DisableColors = false
   711  	l.WithFields(Fields{"func": "func", "file": "file"}).Info("test")
   712  
   713  	l.Formatter.(*TextFormatter).ForceColors = false
   714  	l.Formatter.(*TextFormatter).DisableColors = true
   715  	l.WithFields(Fields{"func": "func", "file": "file"}).Info("test")
   716  }
   717  

View as plain text