...

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

View as plain text