github.com/ethersphere/bee/v2@v2.2.0/pkg/log/registry_test.go (about)

     1  // Copyright 2022 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package log
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"sync"
    11  	"testing"
    12  
    13  	"github.com/google/go-cmp/cmp"
    14  )
    15  
    16  // allVerbosityLevels enumerates all possible verbosity levels.
    17  var allVerbosityLevels = []Level{
    18  	VerbosityNone,
    19  	VerbosityError,
    20  	VerbosityWarning,
    21  	VerbosityInfo,
    22  	VerbosityDebug,
    23  	VerbosityAll,
    24  }
    25  
    26  // opts specifies different set options for testing.
    27  var opts = []Option{
    28  	WithSink(new(bytes.Buffer)),
    29  	WithVerbosity(1),
    30  	WithCaller(CategoryError),
    31  	WithCallerFunc(),
    32  	WithTimestamp(),
    33  	WithTimestampLayout("0123456789"),
    34  	WithMaxDepth(2),
    35  	WithJSONOutput(),
    36  	WithCallerDepth(3),
    37  }
    38  
    39  func TestModifyDefaults(t *testing.T) {
    40  	o := defaults.options
    41  	t.Cleanup(func() {
    42  		defaults.pin = sync.Once{}
    43  		defaults.options = o
    44  	})
    45  
    46  	want := new(Options)
    47  	have := new(Options)
    48  	for _, o := range opts {
    49  		o(want)
    50  	}
    51  	defaults.options = have
    52  	ModifyDefaults(opts...)
    53  
    54  	diff := cmp.Diff(have, want, cmp.AllowUnexported(
    55  		Options{},
    56  		fmtOptions{},
    57  		bytes.Buffer{},
    58  	))
    59  	if diff != "" {
    60  		t.Errorf("ModifyDefaults(...) mismatch (-want +have):\n%s", diff)
    61  	}
    62  }
    63  
    64  func TestNewLogger(t *testing.T) {
    65  	l, o := loggers, defaults.options
    66  	t.Cleanup(func() {
    67  		loggers = l
    68  		defaults.pin = sync.Once{}
    69  		defaults.options = o
    70  	})
    71  
    72  	loggers = new(sync.Map)
    73  	defaults.options = new(Options)
    74  	ModifyDefaults(opts...)
    75  
    76  	var (
    77  		cnt int
    78  		val interface{}
    79  	)
    80  	NewLogger("root").Register()
    81  	loggers.Range(func(k, v interface{}) bool {
    82  		cnt++
    83  		val = v
    84  		return true
    85  	})
    86  	if cnt != 1 {
    87  		t.Fatalf("NewLogger(...) instance(s) count mismatch: want: 1; have: %d", cnt)
    88  	}
    89  	want := val.(*logger)
    90  	have := NewLogger("root").Register()
    91  
    92  	diff := cmp.Diff(have, want, cmp.AllowUnexported(
    93  		builder{},
    94  		logger{},
    95  		caller{},
    96  		formatter{},
    97  		fmtOptions{},
    98  		bytes.Buffer{},
    99  	))
   100  	if diff != "" {
   101  		t.Errorf("NewLogger(...) mismatch (-want +have):\n%s", diff)
   102  	}
   103  }
   104  
   105  func TestSetVerbosity(t *testing.T) {
   106  	l, o := loggers, defaults.options
   107  	t.Cleanup(func() {
   108  		loggers = l
   109  		defaults.pin = sync.Once{}
   110  		defaults.options = o
   111  	})
   112  
   113  	loggers = new(sync.Map)
   114  	defaults.options = new(Options)
   115  	ModifyDefaults(opts...)
   116  
   117  	NewLogger("root").Register()
   118  	NewLogger("root").WithName("child1").Register()
   119  	NewLogger("root").WithName("child1").WithValues("abc", 123).Register()
   120  
   121  	registered := make(map[string]*logger)
   122  	loggers.Range(func(k, v interface{}) bool {
   123  		registered[k.(string)] = v.(*logger)
   124  		return true
   125  	})
   126  
   127  	for _, verbosity := range allVerbosityLevels {
   128  		t.Run(fmt.Sprintf("to=%s/by logger", verbosity), func(t *testing.T) {
   129  			for _, logger := range registered {
   130  				if err := SetVerbosity(logger, verbosity); err != nil {
   131  					t.Errorf("SetVerbosity(...) unexpected error %v", err)
   132  				}
   133  
   134  				// On VerbosityAll, the maximum verbosity will
   135  				// be set instead (VerbosityDebug in our case).
   136  				if verbosity == VerbosityAll {
   137  					verbosity = VerbosityDebug
   138  				}
   139  
   140  				want, have := verbosity, registered[logger.id].verbosity.get()
   141  				if want != have {
   142  					t.Errorf("SetVerbosity(...) want verbosity: %q; have: %q", want, have)
   143  				}
   144  
   145  			}
   146  		})
   147  	}
   148  
   149  	for _, verbosity := range allVerbosityLevels {
   150  		t.Run(fmt.Sprintf("to=%s/by exp", verbosity), func(t *testing.T) {
   151  			if err := SetVerbosityByExp("^root", verbosity); err != nil {
   152  				t.Errorf("SetVerbosityByExp(...) unexpected error %v", err)
   153  			}
   154  
   155  			// On VerbosityAll, the maximum verbosity will
   156  			// be set instead (VerbosityDebug in our case).
   157  			if verbosity == VerbosityAll {
   158  				verbosity = VerbosityDebug
   159  			}
   160  
   161  			for _, logger := range registered {
   162  				want, have := verbosity, logger.verbosity.get()
   163  				if want != have {
   164  					t.Errorf("SetVerbosityByExp(...) want verbosity: %q; have: %q", want, have)
   165  				}
   166  			}
   167  		})
   168  	}
   169  }
   170  
   171  func TestRegistryRange(t *testing.T) {
   172  	l, o := loggers, defaults.options
   173  	t.Cleanup(func() {
   174  		loggers = l
   175  		defaults.pin = sync.Once{}
   176  		defaults.options = o
   177  	})
   178  
   179  	loggers = new(sync.Map)
   180  	defaults.options = new(Options)
   181  	ModifyDefaults(opts...)
   182  
   183  	NewLogger("root").Register()
   184  	NewLogger("root").WithName("child1").Register()
   185  	NewLogger("root").WithName("child1").WithValues("abc", 123).Register()
   186  
   187  	registered := make(map[string]*logger)
   188  	loggers.Range(func(k, v interface{}) bool {
   189  		registered[k.(string)] = v.(*logger)
   190  		return true
   191  	})
   192  
   193  	var cnt int
   194  	RegistryIterate(func(id, path string, verbosity Level, v uint) (next bool) {
   195  		cnt++
   196  
   197  		have := registered[id]
   198  		if have.id != id {
   199  			t.Errorf("RegistryIterate(...) want id: %q; have: %q", id, have.id)
   200  		}
   201  		if have.namesStr != path {
   202  			t.Errorf("RegistryIterate(...) want namesStr: %q; have: %q", path, have.namesStr)
   203  		}
   204  		if have.verbosity.get() != verbosity {
   205  			t.Errorf("RegistryIterate(...) want verbosity: %q; have: %q", verbosity, have.verbosity)
   206  		}
   207  		if have.v != v {
   208  			t.Errorf("RegistryIterate(...) want: v %d; have: %d", v, have.v)
   209  		}
   210  		return true
   211  	})
   212  
   213  	if have, want := cnt, len(registered); have != want {
   214  		t.Fatalf("RegistryIterate(...) instance(s) count mismatch: want: %d; have: %d", want, have)
   215  	}
   216  }