github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/internal/testlog/testlog.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package testlog provides a log handler for unit tests.
    18  package testlog
    19  
    20  import (
    21  	"sync"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/log"
    25  )
    26  
    27  // Handler returns a log handler which logs to the unit test log of t.
    28  func Handler(t *testing.T, level log.Lvl) log.Handler {
    29  	return log.LvlFilterHandler(level, &handler{t, log.TerminalFormat(false), level})
    30  }
    31  
    32  type handler struct {
    33  	t   *testing.T
    34  	fmt log.Format
    35  	lvl log.Lvl
    36  }
    37  
    38  func (h *handler) Log(r *log.Record) error {
    39  	h.t.Logf("%s", h.fmt.Format(r))
    40  	return nil
    41  }
    42  
    43  func (h *handler) Level() log.Lvl {
    44  	return h.lvl
    45  }
    46  
    47  // logger implements log.Logger such that all output goes to the unit test log via
    48  // t.Logf(). All methods in between logger.Trace, logger.Debug, etc. are marked as test
    49  // helpers, so the file and line number in unit test output correspond to the call site
    50  // which emitted the log message.
    51  type logger struct {
    52  	t  *testing.T
    53  	l  log.Logger
    54  	mu *sync.Mutex
    55  	h  *bufHandler
    56  }
    57  
    58  type bufHandler struct {
    59  	buf []*log.Record
    60  	fmt log.Format
    61  }
    62  
    63  func (h *bufHandler) Log(r *log.Record) error {
    64  	h.buf = append(h.buf, r)
    65  	return nil
    66  }
    67  func (h *bufHandler) Level() log.Lvl {
    68  	return log.LvlTrace
    69  }
    70  
    71  // Logger returns a logger which logs to the unit test log of t.
    72  func Logger(t *testing.T, level log.Lvl) log.Logger {
    73  	l := &logger{
    74  		t:  t,
    75  		l:  log.New(),
    76  		mu: new(sync.Mutex),
    77  		h:  &bufHandler{fmt: log.TerminalFormat(false)},
    78  	}
    79  	l.l.SetHandler(log.LvlFilterHandler(level, l.h))
    80  	return l
    81  }
    82  
    83  func (l *logger) Trace(msg string, ctx ...interface{}) {
    84  	l.t.Helper()
    85  	l.mu.Lock()
    86  	defer l.mu.Unlock()
    87  	l.l.Trace(msg, ctx...)
    88  	l.flush()
    89  }
    90  
    91  func (l *logger) Debug(msg string, ctx ...interface{}) {
    92  	l.t.Helper()
    93  	l.mu.Lock()
    94  	defer l.mu.Unlock()
    95  	l.l.Debug(msg, ctx...)
    96  	l.flush()
    97  }
    98  
    99  func (l *logger) Info(msg string, ctx ...interface{}) {
   100  	l.t.Helper()
   101  	l.mu.Lock()
   102  	defer l.mu.Unlock()
   103  	l.l.Info(msg, ctx...)
   104  	l.flush()
   105  }
   106  
   107  func (l *logger) Warn(msg string, ctx ...interface{}) {
   108  	l.t.Helper()
   109  	l.mu.Lock()
   110  	defer l.mu.Unlock()
   111  	l.l.Warn(msg, ctx...)
   112  	l.flush()
   113  }
   114  
   115  func (l *logger) Error(msg string, ctx ...interface{}) {
   116  	l.t.Helper()
   117  	l.mu.Lock()
   118  	defer l.mu.Unlock()
   119  	l.l.Error(msg, ctx...)
   120  	l.flush()
   121  }
   122  
   123  func (l *logger) Crit(msg string, ctx ...interface{}) {
   124  	l.t.Helper()
   125  	l.mu.Lock()
   126  	defer l.mu.Unlock()
   127  	l.l.Crit(msg, ctx...)
   128  	l.flush()
   129  }
   130  
   131  func (l *logger) New(ctx ...interface{}) log.Logger {
   132  	return &logger{l.t, l.l.New(ctx...), l.mu, l.h}
   133  }
   134  
   135  func (l *logger) GetHandler() log.Handler {
   136  	return l.l.GetHandler()
   137  }
   138  
   139  func (l *logger) SetHandler(h log.Handler) {
   140  	l.l.SetHandler(h)
   141  }
   142  
   143  // flush writes all buffered messages and clears the buffer.
   144  func (l *logger) flush() {
   145  	l.t.Helper()
   146  	for _, r := range l.h.buf {
   147  		l.t.Logf("%s", l.h.fmt.Format(r))
   148  	}
   149  	l.h.buf = nil
   150  }
   151  
   152  func (l *logger) OnTrace(fn func(l log.Logging)) {
   153  	if l.GetHandler().Level() >= log.LvlTrace {
   154  		fn(l.Trace)
   155  	}
   156  }
   157  
   158  func (l *logger) OnDebug(fn func(l log.Logging)) {
   159  	if l.GetHandler().Level() >= log.LvlDebug {
   160  		fn(l.Debug)
   161  	}
   162  }
   163  func (l *logger) OnInfo(fn func(l log.Logging)) {
   164  	if l.GetHandler().Level() >= log.LvlInfo {
   165  		fn(l.Info)
   166  	}
   167  }
   168  func (l *logger) OnWarn(fn func(l log.Logging)) {
   169  	if l.GetHandler().Level() >= log.LvlWarn {
   170  		fn(l.Warn)
   171  	}
   172  }
   173  func (l *logger) OnError(fn func(l log.Logging)) {
   174  	if l.GetHandler().Level() >= log.LvlError {
   175  		fn(l.Error)
   176  	}
   177  }
   178  func (l *logger) OnCrit(fn func(l log.Logging)) {
   179  	if l.GetHandler().Level() >= log.LvlCrit {
   180  		fn(l.Crit)
   181  	}
   182  }