...

Source file src/github.com/go-kit/log/level/level_test.go

Documentation: github.com/go-kit/log/level

     1  package level_test
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/go-kit/log"
    11  	"github.com/go-kit/log/level"
    12  )
    13  
    14  func TestVariousLevels(t *testing.T) {
    15  	testCases := []struct {
    16  		name    string
    17  		allowed level.Option
    18  		want    string
    19  	}{
    20  		{
    21  			"Allow(DebugValue)",
    22  			level.Allow(level.DebugValue()),
    23  			strings.Join([]string{
    24  				`{"level":"debug","this is":"debug log"}`,
    25  				`{"level":"info","this is":"info log"}`,
    26  				`{"level":"warn","this is":"warn log"}`,
    27  				`{"level":"error","this is":"error log"}`,
    28  			}, "\n"),
    29  		},
    30  		{
    31  			"Allow(InfoValue)",
    32  			level.Allow(level.InfoValue()),
    33  			strings.Join([]string{
    34  				`{"level":"info","this is":"info log"}`,
    35  				`{"level":"warn","this is":"warn log"}`,
    36  				`{"level":"error","this is":"error log"}`,
    37  			}, "\n"),
    38  		},
    39  		{
    40  			"Allow(WarnValue)",
    41  			level.Allow(level.WarnValue()),
    42  			strings.Join([]string{
    43  				`{"level":"warn","this is":"warn log"}`,
    44  				`{"level":"error","this is":"error log"}`,
    45  			}, "\n"),
    46  		},
    47  		{
    48  			"Allow(ErrorValue)",
    49  			level.Allow(level.ErrorValue()),
    50  			strings.Join([]string{
    51  				`{"level":"error","this is":"error log"}`,
    52  			}, "\n"),
    53  		},
    54  		{
    55  			"Allow(nil)",
    56  			level.Allow(nil),
    57  			strings.Join([]string{}, "\n"),
    58  		},
    59  		{
    60  			"AllowAll",
    61  			level.AllowAll(),
    62  			strings.Join([]string{
    63  				`{"level":"debug","this is":"debug log"}`,
    64  				`{"level":"info","this is":"info log"}`,
    65  				`{"level":"warn","this is":"warn log"}`,
    66  				`{"level":"error","this is":"error log"}`,
    67  			}, "\n"),
    68  		},
    69  		{
    70  			"AllowDebug",
    71  			level.AllowDebug(),
    72  			strings.Join([]string{
    73  				`{"level":"debug","this is":"debug log"}`,
    74  				`{"level":"info","this is":"info log"}`,
    75  				`{"level":"warn","this is":"warn log"}`,
    76  				`{"level":"error","this is":"error log"}`,
    77  			}, "\n"),
    78  		},
    79  		{
    80  			"AllowInfo",
    81  			level.AllowInfo(),
    82  			strings.Join([]string{
    83  				`{"level":"info","this is":"info log"}`,
    84  				`{"level":"warn","this is":"warn log"}`,
    85  				`{"level":"error","this is":"error log"}`,
    86  			}, "\n"),
    87  		},
    88  		{
    89  			"AllowWarn",
    90  			level.AllowWarn(),
    91  			strings.Join([]string{
    92  				`{"level":"warn","this is":"warn log"}`,
    93  				`{"level":"error","this is":"error log"}`,
    94  			}, "\n"),
    95  		},
    96  		{
    97  			"AllowError",
    98  			level.AllowError(),
    99  			strings.Join([]string{
   100  				`{"level":"error","this is":"error log"}`,
   101  			}, "\n"),
   102  		},
   103  		{
   104  			"AllowNone",
   105  			level.AllowNone(),
   106  			``,
   107  		},
   108  	}
   109  
   110  	for _, tc := range testCases {
   111  		t.Run(tc.name, func(t *testing.T) {
   112  			var buf bytes.Buffer
   113  			logger := level.NewFilter(log.NewJSONLogger(&buf), tc.allowed)
   114  
   115  			level.Debug(logger).Log("this is", "debug log")
   116  			level.Info(logger).Log("this is", "info log")
   117  			level.Warn(logger).Log("this is", "warn log")
   118  			level.Error(logger).Log("this is", "error log")
   119  
   120  			if want, have := tc.want, strings.TrimSpace(buf.String()); want != have {
   121  				t.Errorf("\nwant:\n%s\nhave:\n%s", want, have)
   122  			}
   123  		})
   124  	}
   125  }
   126  
   127  func TestErrNotAllowed(t *testing.T) {
   128  	myError := errors.New("squelched!")
   129  	opts := []level.Option{
   130  		level.AllowWarn(),
   131  		level.ErrNotAllowed(myError),
   132  	}
   133  	logger := level.NewFilter(log.NewNopLogger(), opts...)
   134  
   135  	if want, have := myError, level.Info(logger).Log("foo", "bar"); want != have {
   136  		t.Errorf("want %#+v, have %#+v", want, have)
   137  	}
   138  
   139  	if want, have := error(nil), level.Warn(logger).Log("foo", "bar"); want != have {
   140  		t.Errorf("want %#+v, have %#+v", want, have)
   141  	}
   142  }
   143  
   144  func TestErrNoLevel(t *testing.T) {
   145  	myError := errors.New("no level specified")
   146  
   147  	var buf bytes.Buffer
   148  	opts := []level.Option{
   149  		level.SquelchNoLevel(true),
   150  		level.ErrNoLevel(myError),
   151  	}
   152  	logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)
   153  
   154  	if want, have := myError, logger.Log("foo", "bar"); want != have {
   155  		t.Errorf("want %v, have %v", want, have)
   156  	}
   157  	if want, have := ``, strings.TrimSpace(buf.String()); want != have {
   158  		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
   159  	}
   160  }
   161  
   162  func TestAllowNoLevel(t *testing.T) {
   163  	var buf bytes.Buffer
   164  	opts := []level.Option{
   165  		level.SquelchNoLevel(false),
   166  		level.ErrNoLevel(errors.New("I should never be returned!")),
   167  	}
   168  	logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)
   169  
   170  	if want, have := error(nil), logger.Log("foo", "bar"); want != have {
   171  		t.Errorf("want %v, have %v", want, have)
   172  	}
   173  	if want, have := `{"foo":"bar"}`, strings.TrimSpace(buf.String()); want != have {
   174  		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
   175  	}
   176  }
   177  
   178  func TestLevelContext(t *testing.T) {
   179  	var buf bytes.Buffer
   180  
   181  	// Wrapping the level logger with a context allows users to use
   182  	// log.DefaultCaller as per normal.
   183  	var logger log.Logger
   184  	logger = log.NewLogfmtLogger(&buf)
   185  	logger = level.NewFilter(logger, level.AllowAll())
   186  	logger = log.With(logger, "caller", log.DefaultCaller)
   187  
   188  	level.Info(logger).Log("foo", "bar")
   189  	if want, have := `level=info caller=level_test.go:188 foo=bar`, strings.TrimSpace(buf.String()); want != have {
   190  		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
   191  	}
   192  }
   193  
   194  func TestContextLevel(t *testing.T) {
   195  	var buf bytes.Buffer
   196  
   197  	// Wrapping a context with the level logger still works, but requires users
   198  	// to specify a higher callstack depth value.
   199  	var logger log.Logger
   200  	logger = log.NewLogfmtLogger(&buf)
   201  	logger = log.With(logger, "caller", log.Caller(5))
   202  	logger = level.NewFilter(logger, level.AllowAll())
   203  
   204  	level.Info(logger).Log("foo", "bar")
   205  	if want, have := `caller=level_test.go:204 level=info foo=bar`, strings.TrimSpace(buf.String()); want != have {
   206  		t.Errorf("\nwant '%s'\nhave '%s'", want, have)
   207  	}
   208  }
   209  
   210  func TestLevelFormatting(t *testing.T) {
   211  	testCases := []struct {
   212  		name   string
   213  		format func(io.Writer) log.Logger
   214  		output string
   215  	}{
   216  		{
   217  			name:   "logfmt",
   218  			format: log.NewLogfmtLogger,
   219  			output: `level=info foo=bar`,
   220  		},
   221  		{
   222  			name:   "JSON",
   223  			format: log.NewJSONLogger,
   224  			output: `{"foo":"bar","level":"info"}`,
   225  		},
   226  	}
   227  
   228  	for _, tc := range testCases {
   229  		t.Run(tc.name, func(t *testing.T) {
   230  			var buf bytes.Buffer
   231  
   232  			logger := tc.format(&buf)
   233  			level.Info(logger).Log("foo", "bar")
   234  			if want, have := tc.output, strings.TrimSpace(buf.String()); want != have {
   235  				t.Errorf("\nwant: '%s'\nhave '%s'", want, have)
   236  			}
   237  		})
   238  	}
   239  }
   240  
   241  func TestInjector(t *testing.T) {
   242  	var (
   243  		output []interface{}
   244  		logger log.Logger
   245  	)
   246  
   247  	logger = log.LoggerFunc(func(keyvals ...interface{}) error {
   248  		output = keyvals
   249  		return nil
   250  	})
   251  	logger = level.NewInjector(logger, level.InfoValue())
   252  
   253  	logger.Log("foo", "bar")
   254  	if got, want := len(output), 4; got != want {
   255  		t.Errorf("missing level not injected: got len==%d, want len==%d", got, want)
   256  	}
   257  	if got, want := output[0], level.Key(); got != want {
   258  		t.Errorf("wrong level key: got %#v, want %#v", got, want)
   259  	}
   260  	if got, want := output[1], level.InfoValue(); got != want {
   261  		t.Errorf("wrong level value: got %#v, want %#v", got, want)
   262  	}
   263  
   264  	level.Error(logger).Log("foo", "bar")
   265  	if got, want := len(output), 4; got != want {
   266  		t.Errorf("leveled record modified: got len==%d, want len==%d", got, want)
   267  	}
   268  	if got, want := output[0], level.Key(); got != want {
   269  		t.Errorf("wrong level key: got %#v, want %#v", got, want)
   270  	}
   271  	if got, want := output[1], level.ErrorValue(); got != want {
   272  		t.Errorf("wrong level value: got %#v, want %#v", got, want)
   273  	}
   274  }
   275  
   276  func TestParse(t *testing.T) {
   277  	testCases := []struct {
   278  		name    string
   279  		level   string
   280  		want    level.Value
   281  		wantErr error
   282  	}{
   283  		{
   284  			name:    "Debug",
   285  			level:   "debug",
   286  			want:    level.DebugValue(),
   287  			wantErr: nil,
   288  		},
   289  		{
   290  			name:    "Info",
   291  			level:   "info",
   292  			want:    level.InfoValue(),
   293  			wantErr: nil,
   294  		},
   295  		{
   296  			name:    "Warn",
   297  			level:   "warn",
   298  			want:    level.WarnValue(),
   299  			wantErr: nil,
   300  		},
   301  		{
   302  			name:    "Error",
   303  			level:   "error",
   304  			want:    level.ErrorValue(),
   305  			wantErr: nil,
   306  		},
   307  		{
   308  			name:    "Case Insensitive",
   309  			level:   "ErRoR",
   310  			want:    level.ErrorValue(),
   311  			wantErr: nil,
   312  		},
   313  		{
   314  			name:    "Trimmed",
   315  			level:   " Error ",
   316  			want:    level.ErrorValue(),
   317  			wantErr: nil,
   318  		},
   319  		{
   320  			name:    "Invalid",
   321  			level:   "invalid",
   322  			want:    nil,
   323  			wantErr: level.ErrInvalidLevelString,
   324  		},
   325  	}
   326  
   327  	for _, tc := range testCases {
   328  		t.Run(tc.name, func(t *testing.T) {
   329  			got, err := level.Parse(tc.level)
   330  			if err != tc.wantErr {
   331  				t.Errorf("got unexpected error %#v", err)
   332  			}
   333  
   334  			if got != tc.want {
   335  				t.Errorf("wrong value: got=%#v, want=%#v", got, tc.want)
   336  			}
   337  		})
   338  	}
   339  }
   340  
   341  func TestParseDefault(t *testing.T) {
   342  	testCases := []struct {
   343  		name  string
   344  		level string
   345  		want  level.Value
   346  	}{
   347  		{
   348  			name:  "Debug",
   349  			level: "debug",
   350  			want:  level.DebugValue(),
   351  		},
   352  		{
   353  			name:  "Info",
   354  			level: "info",
   355  			want:  level.InfoValue(),
   356  		},
   357  		{
   358  			name:  "Warn",
   359  			level: "warn",
   360  			want:  level.WarnValue(),
   361  		},
   362  		{
   363  			name:  "Error",
   364  			level: "error",
   365  			want:  level.ErrorValue(),
   366  		},
   367  		{
   368  			name:  "Case Insensitive",
   369  			level: "ErRoR",
   370  			want:  level.ErrorValue(),
   371  		},
   372  		{
   373  			name:  "Trimmed",
   374  			level: " Error ",
   375  			want:  level.ErrorValue(),
   376  		},
   377  		{
   378  			name:  "Invalid",
   379  			level: "invalid",
   380  			want:  level.InfoValue(),
   381  		},
   382  	}
   383  
   384  	for _, tc := range testCases {
   385  		t.Run(tc.name, func(t *testing.T) {
   386  			got := level.ParseDefault(tc.level, level.InfoValue())
   387  
   388  			if got != tc.want {
   389  				t.Errorf("wrong value: got=%#v, want=%#v", got, tc.want)
   390  			}
   391  		})
   392  	}
   393  }
   394  

View as plain text