github.com/jxskiss/gopkg@v0.17.3/easy/log_test.go (about)

     1  package easy
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"log"
     8  	"math/rand"
     9  	"regexp"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  
    15  	"github.com/jxskiss/gopkg/ptr"
    16  )
    17  
    18  type simple struct {
    19  	A string
    20  }
    21  
    22  type comptyp struct {
    23  	I32   int32
    24  	I32_p *int32
    25  
    26  	I64   int64
    27  	I64_p *int64
    28  
    29  	Str   string
    30  	Str_p *string
    31  
    32  	Simple   simple
    33  	Simple_p *simple
    34  }
    35  
    36  func TestCaller(t *testing.T) {
    37  	name, file, line := Caller(0)
    38  	assert.Equal(t, "easy.TestCaller", name)
    39  	assert.Equal(t, "easy/log_test.go", file)
    40  	assert.Equal(t, 37, line)
    41  }
    42  
    43  func TestJSON(t *testing.T) {
    44  	tests := []map[string]interface{}{
    45  		{
    46  			"value": 123,
    47  			"want":  "123",
    48  		},
    49  		{
    50  			"value": "456",
    51  			"want":  `"456"`,
    52  		},
    53  		{
    54  			"value": simple{"ABC"},
    55  			"want":  `{"A":"ABC"}`,
    56  		},
    57  		{
    58  			"value": "<html></html>",
    59  			"want":  `"<html></html>"`,
    60  		},
    61  	}
    62  	for _, test := range tests {
    63  		x := JSON(test["value"])
    64  		assert.Equal(t, test["want"], x)
    65  	}
    66  }
    67  
    68  func TestLogfmt(t *testing.T) {
    69  	tests := []map[string]interface{}{
    70  		{
    71  			"value": 123,
    72  			"want":  "123",
    73  		},
    74  		{
    75  			"value": (*string)(nil),
    76  			"want":  "null",
    77  		},
    78  		{
    79  			"value": comptyp{
    80  				I32:      32,
    81  				I32_p:    ptr.Int32(32),
    82  				I64:      64,
    83  				I64_p:    nil,
    84  				Str:      "str",
    85  				Str_p:    ptr.String("str with space"),
    86  				Simple:   simple{A: "simple.A"},
    87  				Simple_p: nil,
    88  			},
    89  			"want": `i32=32 i32_p=32 i64=64 str=str str_p="str with space"`,
    90  		},
    91  		{
    92  			"value": map[string]interface{}{
    93  				"a": 1234,
    94  				"b": "bcde",
    95  				"c": 123.456,
    96  				"d": simple{A: "simple.A"},
    97  				"e": nil,
    98  				"f": []byte("I'm bytes"),
    99  			},
   100  			"want": `a=1234 b=bcde c=123.456 f="I'm bytes"`,
   101  		},
   102  	}
   103  	for _, test := range tests {
   104  		got := Logfmt(test["value"])
   105  		assert.Equal(t, test["want"], got)
   106  	}
   107  }
   108  
   109  var prettyTestWant = strings.TrimSpace(`
   110  {
   111      "1": 123,
   112      "b": "<html>"
   113  }`)
   114  
   115  func TestPretty(t *testing.T) {
   116  	test := map[string]interface{}{
   117  		"1": 123,
   118  		"b": "<html>",
   119  	}
   120  	jsonString := JSON(test)
   121  	assert.Equal(t, `{"1":123,"b":"<html>"}`, jsonString)
   122  
   123  	got1 := Pretty(test)
   124  	assert.Equal(t, prettyTestWant, got1)
   125  
   126  	got2 := Pretty(jsonString)
   127  	assert.Equal(t, prettyTestWant, got2)
   128  
   129  	test3 := []byte("<fff> not a json object")
   130  	got3 := Pretty(test3)
   131  	assert.Equal(t, string(test3), got3)
   132  
   133  	test4 := make([]byte, 16)
   134  	rand.Read(test4)
   135  	got4 := Pretty(test4)
   136  	assert.Equal(t, "<pretty: non-printable bytes>", got4)
   137  }
   138  
   139  func TestCopyStdout(t *testing.T) {
   140  	msg := "test CopyStdout"
   141  	got, _ := CopyStdout(func() {
   142  		fmt.Println(msg)
   143  	})
   144  	assert.Contains(t, string(got), msg)
   145  }
   146  
   147  func TestCopyStdLog(t *testing.T) {
   148  	msg := "test CopyStdLog"
   149  	got := CopyStdLog(func() {
   150  		log.Println(msg)
   151  	})
   152  	assert.Contains(t, string(got), msg)
   153  }
   154  
   155  func TestDEBUG_bare_func(t *testing.T) {
   156  	// test func()
   157  	configTestLog(true, nil, nil)
   158  	msg := "test DEBUG_bare_func"
   159  	got := CopyStdLog(func() {
   160  		DEBUG(func() {
   161  			log.Println(msg, 1, 2, 3)
   162  		})
   163  	})
   164  	assert.Contains(t, string(got), msg)
   165  	assert.Contains(t, string(got), "1 2 3")
   166  }
   167  
   168  func TestDEBUG_logger_interface(t *testing.T) {
   169  	logbuf := bytes.NewBuffer(nil)
   170  	logger := &bufLogger{buf: logbuf}
   171  
   172  	// test logger interface
   173  	configTestLog(true, nil, nil)
   174  	msg := "test DEBUG_logger_interface"
   175  	DEBUG(logger, msg, 1, 2, 3)
   176  	got := logbuf.String()
   177  	assert.Contains(t, got, msg)
   178  	assert.Contains(t, got, "1 2 3")
   179  }
   180  
   181  func TestDEBUG_logger_func(t *testing.T) {
   182  	// test logger function
   183  	configTestLog(true, nil, nil)
   184  	logger := func() stdLogger {
   185  		return stdLogger{}
   186  	}
   187  	msg := "test DEBUG_logger_func"
   188  	got := CopyStdLog(func() {
   189  		DEBUG(logger, msg, 1, 2, 3)
   190  	})
   191  	assert.Contains(t, string(got), msg)
   192  	assert.Contains(t, string(got), "1 2 3")
   193  }
   194  
   195  func TestDEBUG_print_func(t *testing.T) {
   196  	// test print function
   197  	configTestLog(true, nil, nil)
   198  	msg := "test DEBUG_print_func"
   199  	prefix := "PREFIX: "
   200  	logger := func(format string, args ...interface{}) {
   201  		format = prefix + format
   202  		log.Printf(format, args...)
   203  	}
   204  	got := CopyStdLog(func() {
   205  		DEBUG(logger, msg, 1, 2, 3)
   206  	})
   207  	assert.Contains(t, string(got), prefix)
   208  	assert.Contains(t, string(got), msg)
   209  	assert.Contains(t, string(got), "1 2 3")
   210  }
   211  
   212  func TestDEBUG_ctx_logger(t *testing.T) {
   213  	logbuf := bytes.NewBuffer(nil)
   214  	ctx := context.WithValue(context.Background(), "TEST_LOGGER", &bufLogger{buf: logbuf})
   215  	getCtxLogger := func(ctx context.Context) ErrDebugLogger {
   216  		return ctx.Value("TEST_LOGGER").(*bufLogger)
   217  	}
   218  
   219  	// test ctx logger
   220  	configTestLog(true, nil, getCtxLogger)
   221  	msg := "test DEBUG_ctx_logger"
   222  	DEBUG(ctx, msg, 1, 2, 3)
   223  	got := logbuf.String()
   224  	assert.Contains(t, got, msg)
   225  	assert.Contains(t, got, "1 2 3")
   226  }
   227  
   228  func TestDEBUG_simple(t *testing.T) {
   229  	configTestLog(true, nil, nil)
   230  
   231  	// test format
   232  	got1 := CopyStdLog(func() {
   233  		DEBUG("test DEBUG_simple a=%v b=%v c=%v", 1, 2, 3)
   234  	})
   235  	want1 := "test DEBUG_simple a=1 b=2 c=3"
   236  	assert.Contains(t, string(got1), want1)
   237  
   238  	// raw params
   239  	got2 := CopyStdLog(func() {
   240  		DEBUG("test DEBUG_simple a=", 1, "b=", 2, "c=", 3)
   241  	})
   242  	want2 := "test DEBUG_simple a= 1 b= 2 c= 3"
   243  	assert.Contains(t, string(got2), want2)
   244  }
   245  
   246  func TestDEBUG_empty(t *testing.T) {
   247  	configTestLog(true, nil, nil)
   248  	got := CopyStdLog(func() { DEBUG() })
   249  	want := regexp.MustCompile(`easy/log_test.go#L\d+ - easy.TestDEBUG_empty`)
   250  	assert.Regexp(t, want, string(got))
   251  }
   252  
   253  func TestDEBUGSkip(t *testing.T) {
   254  	configTestLog(true, nil, nil)
   255  
   256  	got := CopyStdLog(func() { DEBUGWrap() })
   257  	want := regexp.MustCompile(`easy/log_test.go#L\d+ - easy.TestDEBUGSkip`)
   258  	assert.Regexp(t, want, string(got))
   259  
   260  	got = CopyStdLog(func() { DEBUGWrapSkip2() })
   261  	want = regexp.MustCompile(`easy/log_test.go#L\d+ - easy.TestDEBUGSkip`)
   262  	assert.Regexp(t, want, string(got))
   263  }
   264  
   265  func TestConfigLog(t *testing.T) {
   266  	defaultLogger := &bufLogger{}
   267  	getCtxLogger := func(ctx context.Context) ErrDebugLogger {
   268  		return ctx.Value("TEST_LOGGER").(*bufLogger)
   269  	}
   270  	configTestLog(true, defaultLogger, getCtxLogger)
   271  }
   272  
   273  type bufLogger struct {
   274  	buf *bytes.Buffer
   275  }
   276  
   277  func (p *bufLogger) Debugf(format string, args ...interface{}) {
   278  	if p.buf == nil {
   279  		p.buf = bytes.NewBuffer(nil)
   280  	}
   281  	fmt.Fprintf(p.buf, format, args...)
   282  }
   283  
   284  func (p *bufLogger) Errorf(format string, args ...interface{}) {
   285  	if p.buf == nil {
   286  		p.buf = bytes.NewBuffer(nil)
   287  	}
   288  	fmt.Fprintf(p.buf, format, args...)
   289  }
   290  
   291  func DEBUGWrap(args ...interface{}) {
   292  	DEBUGSkip(1, args...)
   293  }
   294  
   295  func DEBUGWrapSkip2(args ...interface{}) {
   296  	skip2 := func(args ...interface{}) {
   297  		DEBUGSkip(2, args...)
   298  	}
   299  	skip2(args...)
   300  }
   301  
   302  func configTestLog(
   303  	enableDebug bool,
   304  	defaultLogger ErrDebugLogger,
   305  	ctxFunc func(ctx context.Context) ErrDebugLogger,
   306  ) {
   307  	ConfigLog(LogCfg{
   308  		EnableDebug: func() bool { return enableDebug },
   309  		Logger:      func() ErrDebugLogger { return defaultLogger },
   310  		CtxLogger:   ctxFunc,
   311  	})
   312  }