...

Source file src/github.com/wojas/genericr/genericr_test.go

Documentation: github.com/wojas/genericr

     1  package genericr_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"path/filepath"
     7  	"runtime"
     8  	"testing"
     9  
    10  	"github.com/go-logr/logr"
    11  	"github.com/wojas/genericr"
    12  )
    13  
    14  func TestNewForTesting(t *testing.T) {
    15  	log := genericr.NewForTesting(t)
    16  	log.Info("hello world", "a", 1)
    17  	log.WithName("foo").WithValues("a", 42).WithName("bar").V(1).WithValues("b", 1).Info("hello world2", "x", 123, "y", 234)
    18  	t.Log("Normal test log")
    19  }
    20  
    21  func TestLogger_Table(t *testing.T) {
    22  	var last genericr.Entry
    23  	var lf genericr.LogFunc = func(e genericr.Entry) {
    24  		last = e
    25  		t.Log(e.String())
    26  	}
    27  	sink := genericr.New(lf)
    28  
    29  	tt := []struct {
    30  		f    func()
    31  		want string
    32  	}{
    33  		{
    34  			func() {
    35  				sink.Info(0, "hello world")
    36  			},
    37  			`[0]  "hello world"`,
    38  		},
    39  		{
    40  			func() {
    41  				sink.Info(0, "hello world", "a", 1)
    42  			},
    43  			`[0]  "hello world" a=1`,
    44  		},
    45  		{
    46  			func() {
    47  				sink.Info(4, "hello world", "a", 1)
    48  			},
    49  			`[4]  "hello world" a=1`,
    50  		},
    51  		{
    52  			func() {
    53  				sink.WithName("somename").Info(0, "hello world", "a", 1)
    54  			},
    55  			`[0] somename "hello world" a=1`,
    56  		},
    57  		{
    58  			func() {
    59  				sink.WithName("somename").WithName("sub").Info(0, "hello world", "a", 1)
    60  			},
    61  			`[0] somename.sub "hello world" a=1`,
    62  		},
    63  		{
    64  			func() {
    65  				sink.WithName("somename").WithName("sub").Info(1, "hello world", "a", 1, "b", 2)
    66  			},
    67  			`[1] somename.sub "hello world" a=1 b=2`,
    68  		},
    69  		{
    70  			func() {
    71  				sink.WithValues("x", "yz").WithName("somename").WithName("sub").Info(1, "hello world", "a", 1, "b", 2)
    72  			},
    73  			`[1] somename.sub "hello world" a=1 b=2 x="yz"`,
    74  		},
    75  		{
    76  			func() {
    77  				// Odd values by mistake, does not corrupt later calls
    78  				sink.WithValues("x", "yz", "z").Info(0, "hello world", "a", 1, "b", 2)
    79  			},
    80  			`[0]  "hello world" a=1 b=2 x="yz" z=null`,
    81  		},
    82  		{
    83  			func() {
    84  				sink.WithVerbosity(1).Info(0, "hello world", "a", 1)
    85  			},
    86  			`[0]  "hello world" a=1`,
    87  		},
    88  		{
    89  			func() {
    90  				sink.Info(01, "first")
    91  				sink.WithVerbosity(1).Info(1, "hello world", "a", 1)
    92  			},
    93  			`[1]  "hello world" a=1`,
    94  		},
    95  		{
    96  			func() {
    97  				sink.Info(0, "first")
    98  				sink.WithVerbosity(1).Info(0, "hello world", "a", 1)
    99  			},
   100  			`[0]  "hello world" a=1`,
   101  		},
   102  		{
   103  			func() {
   104  				sink.Info(0, "wrong params", "a")
   105  			},
   106  			`[0]  "wrong params" a=null`,
   107  		},
   108  		{
   109  			func() {
   110  				sink.Info(0, "wrong params", 42)
   111  			},
   112  			`[0]  "wrong params" "!(42)"=null`,
   113  		},
   114  		{
   115  			func() {
   116  				sink.Error(fmt.Errorf("some error"), "help")
   117  			},
   118  			`[0]  "help" error="some error"`,
   119  		},
   120  		{
   121  			f: func() {
   122  				sink.WithValues(
   123  					"int", 42,
   124  					"string", "foo",
   125  					"bytes", []byte("foo"),
   126  					"float", 3.14,
   127  					"struct", struct {
   128  						A string
   129  						B int
   130  					}{"foo", 12},
   131  					"map", map[string]int{
   132  						"foo": 12,
   133  					},
   134  					"nilval", nil,
   135  					"err", errors.New("oops"),
   136  					"stringslice", []string{"a", "b"},
   137  				).Info(0, "types")
   138  			},
   139  			want: `[0]  "types" bytes="66 6f 6f" err="oops" float=3.14 int=42 map={"foo":12} nilval=null string="foo" stringslice=["a","b"] struct={"A":"foo","B":12}`,
   140  		},
   141  	}
   142  
   143  	for i, row := range tt {
   144  		row.f()
   145  		s := last.String()
   146  		if s != row.want {
   147  			t.Errorf("row %d:\n  got:  `%s`\n  want: `%s`", i, s, row.want)
   148  		}
   149  	}
   150  }
   151  
   152  func TestLogger_Caller(t *testing.T) {
   153  	var last genericr.Entry
   154  	var lf genericr.LogFunc = func(e genericr.Entry) {
   155  		last = e
   156  		t.Log(e.String())
   157  		t.Log(runtime.Caller(e.CallerDepth)) // should log caller_test
   158  	}
   159  	sink := genericr.New(lf).WithCaller(true)
   160  	logSomethingFromOtherFile(logr.New(sink))
   161  
   162  	_, fname := filepath.Split(last.Caller.File)
   163  	if fname != "caller_test.go" {
   164  		t.Errorf("Caller: expected 'caller_test.go', got %q (full: %s:%d)",
   165  			fname, last.Caller.File, last.Caller.Line)
   166  	}
   167  	if last.CallerDepth != 4 {
   168  		t.Errorf("Caller depth: expected 4, got %d", last.CallerDepth)
   169  	}
   170  }
   171  
   172  type wrappedLogger struct {
   173  	log logr.Logger
   174  }
   175  
   176  func (wl wrappedLogger) Info(msg string, keysAndValues ...interface{}) {
   177  	wl.log.Info(msg, keysAndValues...)
   178  }
   179  
   180  func TestLogger_WithCallDepth(t *testing.T) {
   181  	var last genericr.Entry
   182  	var lf genericr.LogFunc = func(e genericr.Entry) {
   183  		last = e
   184  		t.Log(e.String())
   185  		t.Log(runtime.Caller(e.CallerDepth)) // should log caller_test
   186  	}
   187  	sink := genericr.New(lf).WithCaller(true).WithCallDepth(1)
   188  	logger := logr.New(sink)
   189  	wlogger := wrappedLogger{logger}
   190  
   191  	logSomethingFromOtherFile(wlogger)
   192  
   193  	_, fname := filepath.Split(last.Caller.File)
   194  	if fname != "caller_test.go" {
   195  		t.Errorf("Caller: expected 'caller_test.go', got %q (full: %s:%d)",
   196  			fname, last.Caller.File, last.Caller.Line)
   197  	}
   198  	if last.CallerDepth != 5 {
   199  		t.Errorf("Caller depth: expected 5, got %d", last.CallerDepth)
   200  	}
   201  }
   202  
   203  func BenchmarkLogger_basic(b *testing.B) {
   204  	foo := 0
   205  	var lf genericr.LogFunc = func(e genericr.Entry) {
   206  		foo += e.Level // just to prevent it from being optimized away
   207  	}
   208  	log := genericr.New(lf)
   209  
   210  	b.ReportAllocs()
   211  	b.ResetTimer()
   212  	for i := 0; i < b.N; i++ {
   213  		log.Info(0, "hello")
   214  	}
   215  }
   216  
   217  func BenchmarkLogger_basic_with_caller(b *testing.B) {
   218  	foo := 0
   219  	var lf genericr.LogFunc = func(e genericr.Entry) {
   220  		foo += e.Level // just to prevent it from being optimized away
   221  	}
   222  	log := genericr.New(lf).WithCaller(true)
   223  
   224  	b.ReportAllocs()
   225  	b.ResetTimer()
   226  	for i := 0; i < b.N; i++ {
   227  		log.Info(0, "hello")
   228  	}
   229  }
   230  
   231  func BenchmarkLogger_2vars(b *testing.B) {
   232  	foo := 0
   233  	var lf genericr.LogFunc = func(e genericr.Entry) {
   234  		foo += e.Level // just to prevent it from being optimized away
   235  	}
   236  	log := genericr.New(lf)
   237  
   238  	b.ReportAllocs()
   239  	b.ResetTimer()
   240  	for i := 0; i < b.N; i++ {
   241  		log.Info(0, "hello", "a", 1, "b", 2)
   242  	}
   243  }
   244  
   245  func BenchmarkLogger_clone(b *testing.B) {
   246  	foo := 0
   247  	var lf genericr.LogFunc = func(e genericr.Entry) {
   248  		foo += e.Level // just to prevent it from being optimized away
   249  	}
   250  	log := genericr.New(lf)
   251  
   252  	b.ReportAllocs()
   253  	b.ResetTimer()
   254  	for i := 0; i < b.N; i++ {
   255  		log.Info(0, "hello")
   256  	}
   257  }
   258  
   259  func BenchmarkLogger_complicated(b *testing.B) {
   260  	foo := 0
   261  	var lf genericr.LogFunc = func(e genericr.Entry) {
   262  		foo += e.Level // just to prevent it from being optimized away
   263  	}
   264  	log := genericr.New(lf)
   265  
   266  	b.ReportAllocs()
   267  	b.ResetTimer()
   268  	for i := 0; i < b.N; i++ {
   269  		log.WithName("bench").WithValues("x", 123).Info(0, "hello", "a", 1, "b", 2)
   270  	}
   271  }
   272  
   273  func BenchmarkLogger_complicated_precalculated(b *testing.B) {
   274  	foo := 0
   275  	var lf genericr.LogFunc = func(e genericr.Entry) {
   276  		foo += e.Level // just to prevent it from being optimized away
   277  	}
   278  	log := genericr.New(lf)
   279  	log2 := log.WithName("bench").WithValues("x", 123)
   280  
   281  	b.ReportAllocs()
   282  	b.ResetTimer()
   283  	for i := 0; i < b.N; i++ {
   284  		log2.Info(0, "hello", "a", 1, "b", 2)
   285  	}
   286  }
   287  
   288  func BenchmarkLogger_2vars_tostring(b *testing.B) {
   289  	foo := ""
   290  	var lf genericr.LogFunc = func(e genericr.Entry) {
   291  		foo = e.String()
   292  	}
   293  	log := genericr.New(lf)
   294  
   295  	b.ReportAllocs()
   296  	b.ResetTimer()
   297  	for i := 0; i < b.N; i++ {
   298  		log.Info(0, "hello", "a", 1, "b", 2)
   299  	}
   300  	_ = foo
   301  }
   302  

View as plain text