codeberg.org/gruf/go-log@v1.0.6-0.20231202001801-031c3d3d089b/log_test.go (about)

     1  package log_test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"net/http"
     7  	"strings"
     8  	"sync"
     9  	"testing"
    10  
    11  	"codeberg.org/gruf/go-kv"
    12  	"codeberg.org/gruf/go-log"
    13  )
    14  
    15  var (
    16  	testArgs = [][]interface{}{
    17  		{0, 1, 2, 3, 4},
    18  		{"hello", "world!"},
    19  		{"random", 0, 1, 2.2, 3.3, "arguments"},
    20  		{[]int{0, 1, 2, 3}, []string{"hello", "world"}, map[string]string{"hello": "world"}},
    21  		{http.Client{}, sync.Mutex{}},
    22  		{nil, nil, nil, nil},
    23  	}
    24  
    25  	testFmts = []struct {
    26  		fmt string
    27  		arg []interface{}
    28  	}{
    29  		{
    30  			fmt: "hello world: %q",
    31  			arg: []interface{}{"hello world"},
    32  		},
    33  		{
    34  			fmt: "no operators here",
    35  			arg: []interface{}{"oh no unexpected!"},
    36  		},
    37  		{
    38  			fmt: "0, 1, %d, %f, %s",
    39  			arg: []interface{}{2, 3.0, "4"},
    40  		},
    41  		{
    42  			fmt: "%d %d %d %d",
    43  			arg: []interface{}{"oh no bad and missing operators"},
    44  		},
    45  		{
    46  			fmt: "%#v",
    47  			arg: []interface{}{http.Client{}},
    48  		},
    49  		{
    50  			fmt: "%+v",
    51  			arg: []interface{}{map[string]interface{}{"key": "value", "hello": "world"}},
    52  		},
    53  	}
    54  
    55  	testFields = []kv.Fields{
    56  		{
    57  			kv.Field{K: "hello", V: "world!"},
    58  			kv.Field{K: "client", V: http.Client{}},
    59  		},
    60  		{
    61  			kv.Field{K: "map", V: map[string]string{"map": "of values"}},
    62  			kv.Field{K: "slice", V: []string{"slice", "of", "values"}},
    63  		},
    64  		{
    65  			kv.Field{K: "nil", V: nil},
    66  			kv.Field{K: "hmmm", V: "watcha sayyyy"},
    67  		},
    68  		{
    69  			kv.Field{K: "int", V: 420},
    70  			kv.Field{K: "float", V: 6.9},
    71  		},
    72  		{
    73  			kv.Field{K: "complex", V: complex(120, 120)},
    74  			kv.Field{K: "shrug", V: "\n\n\n\n\n\n\n\n\n\n\n\n"},
    75  		},
    76  	}
    77  )
    78  
    79  func TestLoggingLevels(t *testing.T) {
    80  	// Special case of no log flags
    81  	log.Default().Logger().SetFlags(0)
    82  
    83  	// Output to buffer
    84  	buf := bytes.Buffer{}
    85  	log.SetOutput(&buf)
    86  
    87  	testLog := func(do func(), expect bool) {
    88  		do()
    89  		if !expect && buf.Len() > 0 {
    90  			t.Error("log should not have produced output")
    91  		} else if expect && buf.Len() == 0 {
    92  			t.Error("log should have produced output")
    93  		}
    94  		buf.Reset()
    95  	}
    96  
    97  	for _, lvl := range []log.LEVEL{
    98  		log.ALL,
    99  		log.DEBUG,
   100  		log.INFO,
   101  		log.WARN,
   102  		log.ERROR,
   103  		log.PANIC,
   104  		log.NONE,
   105  	} {
   106  		// Update log level
   107  		log.SetLevel(lvl)
   108  
   109  		// DEBUG level
   110  		testLog(func() {
   111  			log.Debug("test log")
   112  		}, lvl >= log.DEBUG)
   113  		testLog(func() {
   114  			log.Debugf("test log")
   115  		}, lvl >= log.DEBUG)
   116  		testLog(func() {
   117  			log.DebugFields(kv.Field{K: "test", V: "log"})
   118  		}, lvl >= log.DEBUG)
   119  
   120  		// INFO level
   121  		testLog(func() {
   122  			log.Info("test log")
   123  		}, lvl >= log.INFO)
   124  		testLog(func() {
   125  			log.Infof("test log")
   126  		}, lvl >= log.INFO)
   127  		testLog(func() {
   128  			log.InfoFields(kv.Field{K: "test", V: "log"})
   129  		}, lvl >= log.INFO)
   130  
   131  		// WARN level
   132  		testLog(func() {
   133  			log.Warn("test log")
   134  		}, lvl >= log.WARN)
   135  		testLog(func() {
   136  			log.Warnf("test log")
   137  		}, lvl >= log.WARN)
   138  		testLog(func() {
   139  			log.WarnFields(kv.Field{K: "test", V: "log"})
   140  		}, lvl >= log.WARN)
   141  
   142  		// ERROR level
   143  		testLog(func() {
   144  			log.Error("test log")
   145  		}, lvl >= log.ERROR)
   146  		testLog(func() {
   147  			log.Errorf("test log")
   148  		}, lvl >= log.ERROR)
   149  		testLog(func() {
   150  			log.ErrorFields(kv.Field{K: "test", V: "log"})
   151  		}, lvl >= log.ERROR)
   152  
   153  		// PANIC level
   154  		testLog(func() {
   155  			defer func() { _ = recover() }()
   156  			log.Panic("test log")
   157  		}, lvl >= log.PANIC)
   158  		testLog(func() {
   159  			defer func() { _ = recover() }()
   160  			log.Panicf("test log")
   161  		}, lvl >= log.PANIC)
   162  		testLog(func() {
   163  			defer func() { _ = recover() }()
   164  			log.PanicFields(kv.Field{K: "test", V: "log"})
   165  		}, lvl >= log.PANIC)
   166  	}
   167  }
   168  
   169  func TestLoggerOutput(t *testing.T) {
   170  	// Special case of no log flags
   171  	log.Default().Logger().SetFlags(0)
   172  
   173  	// Output to buffer
   174  	buf := bytes.Buffer{}
   175  	log.SetOutput(&buf)
   176  
   177  	// Reset log level
   178  	log.SetLevel(log.ALL)
   179  
   180  	testLog := func(do func(), match func(string) bool) {
   181  		do()
   182  		if str := buf.String(); !match(strings.TrimSpace(str)) {
   183  			t.Errorf("unexpected log output: %s", str)
   184  		}
   185  		buf.Reset()
   186  	}
   187  
   188  	for _, arg := range testArgs {
   189  		expect := fmt.Sprint(arg...)
   190  
   191  		testLog(func() {
   192  			log.Debug(arg...)
   193  		}, func(out string) bool {
   194  			return strings.HasPrefix(out, "[DEBUG] ") &&
   195  				(strings.TrimPrefix(out, "[DEBUG] ") == expect)
   196  		})
   197  
   198  		testLog(func() {
   199  			log.Info(arg...)
   200  		}, func(out string) bool {
   201  			return strings.HasPrefix(out, "[INFO] ") &&
   202  				(strings.TrimPrefix(out, "[INFO] ") == expect)
   203  		})
   204  
   205  		testLog(func() {
   206  			log.Warn(arg...)
   207  		}, func(out string) bool {
   208  			return strings.HasPrefix(out, "[WARN] ") &&
   209  				(strings.TrimPrefix(out, "[WARN] ") == expect)
   210  		})
   211  
   212  		testLog(func() {
   213  			log.Error(arg...)
   214  		}, func(out string) bool {
   215  			return strings.HasPrefix(out, "[ERROR] ") &&
   216  				(strings.TrimPrefix(out, "[ERROR] ") == expect)
   217  		})
   218  
   219  		testLog(func() {
   220  			defer func() {
   221  				if recover() != expect {
   222  					t.Error("unexpected panic result")
   223  				}
   224  			}()
   225  			log.Panic(arg...)
   226  		}, func(out string) bool {
   227  			return strings.HasPrefix(out, "[PANIC] ") &&
   228  				(strings.TrimPrefix(out, "[PANIC] ") == expect)
   229  		})
   230  	}
   231  
   232  	for _, format := range testFmts {
   233  		expect := fmt.Sprintf(format.fmt, format.arg...)
   234  
   235  		testLog(func() {
   236  			log.Debugf(format.fmt, format.arg...)
   237  		}, func(out string) bool {
   238  			return strings.HasPrefix(out, "[DEBUG] ") &&
   239  				(strings.TrimPrefix(out, "[DEBUG] ") == expect)
   240  		})
   241  
   242  		testLog(func() {
   243  			log.Infof(format.fmt, format.arg...)
   244  		}, func(out string) bool {
   245  			return strings.HasPrefix(out, "[INFO] ") &&
   246  				(strings.TrimPrefix(out, "[INFO] ") == expect)
   247  		})
   248  
   249  		testLog(func() {
   250  			log.Warnf(format.fmt, format.arg...)
   251  		}, func(out string) bool {
   252  			return strings.HasPrefix(out, "[WARN] ") &&
   253  				(strings.TrimPrefix(out, "[WARN] ") == expect)
   254  		})
   255  
   256  		testLog(func() {
   257  			log.Errorf(format.fmt, format.arg...)
   258  		}, func(out string) bool {
   259  			return strings.HasPrefix(out, "[ERROR] ") &&
   260  				(strings.TrimPrefix(out, "[ERROR] ") == expect)
   261  		})
   262  
   263  		testLog(func() {
   264  			defer func() {
   265  				if recover() != expect {
   266  					t.Error("unexpected panic result")
   267  				}
   268  			}()
   269  			log.Panicf(format.fmt, format.arg...)
   270  		}, func(out string) bool {
   271  			return strings.HasPrefix(out, "[PANIC] ") &&
   272  				(strings.TrimPrefix(out, "[PANIC] ") == expect)
   273  		})
   274  	}
   275  
   276  	for _, fields := range testFields {
   277  		expect := fields.String()
   278  
   279  		testLog(func() {
   280  			log.DebugFields(fields...)
   281  		}, func(out string) bool {
   282  			return strings.HasPrefix(out, "[DEBUG] ") &&
   283  				(strings.TrimPrefix(out, "[DEBUG] ") == expect)
   284  		})
   285  
   286  		testLog(func() {
   287  			log.InfoFields(fields...)
   288  		}, func(out string) bool {
   289  			return strings.HasPrefix(out, "[INFO] ") &&
   290  				(strings.TrimPrefix(out, "[INFO] ") == expect)
   291  		})
   292  
   293  		testLog(func() {
   294  			log.WarnFields(fields...)
   295  		}, func(out string) bool {
   296  			return strings.HasPrefix(out, "[WARN] ") &&
   297  				(strings.TrimPrefix(out, "[WARN] ") == expect)
   298  		})
   299  
   300  		testLog(func() {
   301  			log.ErrorFields(fields...)
   302  		}, func(out string) bool {
   303  			return strings.HasPrefix(out, "[ERROR] ") &&
   304  				(strings.TrimPrefix(out, "[ERROR] ") == expect)
   305  		})
   306  
   307  		testLog(func() {
   308  			defer func() {
   309  				if recover() != expect {
   310  					t.Error("unexpected panic result")
   311  				}
   312  			}()
   313  			log.PanicFields(fields...)
   314  		}, func(out string) bool {
   315  			return strings.HasPrefix(out, "[PANIC] ") &&
   316  				(strings.TrimPrefix(out, "[PANIC] ") == expect)
   317  		})
   318  	}
   319  }