mirror of
https://github.com/rs/zerolog
synced 2026-06-08 17:13:30 +00:00
f6fbd330be
* Test coverage improvements Implements #397 and #591, might help with #473 Test coverage for core is 97.6% with only real fringe cases remaining. Improve `Fields` `isNilValue()` portability. Added a new global handler `FatalExitFunc` to allow intercepting `Fatal()` messages. Fixed CBOR float constants (removed the CBOR prefix) Added tests for: - global `FatalExitFunc` to allow intercepting Fatal messages (both for testing and public use). - `Logger` - `DisableSampling` - `.With()` copying existing context if present. - `.With().Fields()` all forms of `ErrorStackMarshaler` returns. - `.WithLevel()` for `FatalLevel`, `PanicLevel`, and `DisabledLevel`. - `.Err()` with `nil` and non-`nil` `error` and test the resulting log level. - `.should()` covering `nil` writer. - `.Output()` gets context values. - `.UpdateContext()` on a disabled logger doesn't panic and is a nop. - `.With()` all forms of `ErrorStackMarshaler` returns. - with a `nil`writer. - `.Hook()` passing no hooks. - `Array` - `.MarshalZerologArray` is a nop that won't panic. - `Context` - ` .Err()` and `.AnErr()` for `nil` errors and all forms of `ErrorStackMarshaler` returns. - `Event` - `.Caller()` to ensure we don't panic or add invalid information if `runtime.Caller()` fails -` .Err()` and `.AnErr()` for `nil` errors and all forms of `ErrorStackMarshaler` returns. - `Fields` - ` .appendFields()` all forms of `ErrorStackMarshaler` returns. - `HookLevel` - `.Run()` methods. - `LevelSampler` - `.Sample() methods. - `Syslog` - `.Write()`, `.WriteLevel()`, and `.Close()` methods. - `.WriteLevel()` with an `InvalidLevel`. - `Writer` - `.Write()` short write and error cases. - `MultiLevelWriter` `.WriteLevel()` and for `.Write()` error and `.Close()` cases. - test of unmarshalling a level byte returns correct error. - CBOR decodeStream - `.decodeFloat()`, `.binaryFmt()`, `.DecodeIfBinaryToString()`, `.DecodeObjectToStr()`, `.DecodeIfBinaryToBytes()`, `.decodeTagData()`, and `.decodeSimpleFloat()` - handling of invalid UTF-8 sequences - handling of UTC times. - handling of timestamps - handling of various map lengths Restructure `Event` `.caller()` so we test for ok and eliminate untestable coverage hole. Restructure `Context` `.Err()` when the `ErrorStackMarshaler` returns a `nil` so there's code to cover. Inverted logic for`Event` `.Caller()`'s call to `runtime.Caller()` for simpler testing. Inverted logic for `Array` `.putArray()` and `Event` `.putEvent()` so there isn't uncoverable code. Restructure `Field` `.appendFieldList()` to early return when `ErrorStackMarshaler` returns a `nil` Added comments for things we can't get coverage on. Did a go fmt ./... Coverage of core is now 100% on `Array`, `Context`, `Ctx`, `Event`, `Field`, `Hook`, and `Syslog`. Coverage of `Globals`, `Log`, `Sampler`, and `Writer` is almost all except some real edge-cases. JSON encoder coverage is 100% CBOR encoder coverage is 96.3% with base, cbor, string, time and types at 100% and decode_stream (which is lacks coverage on some panic states, and two incorrect coverage-tool lapses) * Fix CBOR tests for StackMarshaler Forgot to use the `decodeIfBinaryToString()`
144 lines
4.1 KiB
Go
144 lines
4.1 KiB
Go
package zerolog
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
type myError struct{}
|
|
|
|
func (e *myError) Error() string { return "test" }
|
|
|
|
func TestContext_ErrWithStackMarshaler(t *testing.T) {
|
|
// Save original
|
|
original := ErrorStackMarshaler
|
|
defer func() { ErrorStackMarshaler = original }()
|
|
|
|
// Set a mock marshaler
|
|
ErrorStackMarshaler = func(err error) interface{} {
|
|
return "stack-trace"
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
log := New(&buf).With().Stack().Err(errors.New("test error")).Logger()
|
|
|
|
log.Info().Msg("test message")
|
|
|
|
got := decodeIfBinaryToString(buf.Bytes())
|
|
want := `{"level":"info","stack":"stack-trace","error":"test error","message":"test message"}` + "\n"
|
|
if got != want {
|
|
t.Errorf("Context.Err() with stack marshaler = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestContext_AnErrWithNilErrorMarshal(t *testing.T) {
|
|
// Save original
|
|
original := ErrorMarshalFunc
|
|
defer func() { ErrorMarshalFunc = original }()
|
|
|
|
// Set marshaler to return a nil error pointer
|
|
ErrorMarshalFunc = func(err error) interface{} {
|
|
return (*myError)(nil) // nil pointer of error type
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
log := New(&buf).With().AnErr("test", errors.New("some error")).Logger()
|
|
|
|
log.Info().Msg("test message")
|
|
|
|
got := decodeIfBinaryToString(buf.Bytes())
|
|
want := `{"level":"info","message":"test message"}` + "\n" // No "test" field because isNilValue returned true
|
|
if got != want {
|
|
t.Errorf("Context.AnErr() with nil error marshal = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestContext_ErrWithNilStackMarshaler(t *testing.T) {
|
|
// Save original
|
|
original := ErrorStackMarshaler
|
|
defer func() { ErrorStackMarshaler = original }()
|
|
|
|
// Set marshaler to return nil
|
|
ErrorStackMarshaler = func(err error) interface{} {
|
|
return nil
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
log := New(&buf).With().Stack().Err(errors.New("test error")).Logger()
|
|
|
|
log.Info().Msg("test message")
|
|
|
|
got := decodeIfBinaryToString(buf.Bytes())
|
|
want := `{"level":"info","message":"test message"}` + "\n" // No stack or error field because stack marshaler returned nil
|
|
if got != want {
|
|
t.Errorf("Context.Err() with nil stack marshaler = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestContext_ErrWithStackMarshalerObject(t *testing.T) {
|
|
// Save original
|
|
original := ErrorStackMarshaler
|
|
defer func() { ErrorStackMarshaler = original }()
|
|
|
|
// Set a mock marshaler that returns LogObjectMarshaler
|
|
ErrorStackMarshaler = func(err error) interface{} {
|
|
return logObjectMarshalerImpl{name: "user", age: 30}
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
log := New(&buf).With().Stack().Err(errors.New("test error")).Logger()
|
|
|
|
log.Info().Msg("test message")
|
|
|
|
got := decodeIfBinaryToString(buf.Bytes())
|
|
want := `{"level":"info","stack":{"name":"user","age":-30},"error":"test error","message":"test message"}` + "\n"
|
|
if got != want {
|
|
t.Errorf("Context.Err() with stack marshaler object = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestContext_ErrWithStackMarshalerError(t *testing.T) {
|
|
// Save original
|
|
original := ErrorStackMarshaler
|
|
defer func() { ErrorStackMarshaler = original }()
|
|
|
|
// Set a mock marshaler that returns an error
|
|
ErrorStackMarshaler = func(err error) interface{} {
|
|
return errors.New("stack error")
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
log := New(&buf).With().Stack().Err(errors.New("test error")).Logger()
|
|
|
|
log.Info().Msg("test message")
|
|
|
|
got := decodeIfBinaryToString(buf.Bytes())
|
|
want := `{"level":"info","stack":"stack error","error":"test error","message":"test message"}` + "\n"
|
|
if got != want {
|
|
t.Errorf("Context.Err() with stack marshaler error = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestContext_ErrWithStackMarshalerInterface(t *testing.T) {
|
|
// Save original
|
|
original := ErrorStackMarshaler
|
|
defer func() { ErrorStackMarshaler = original }()
|
|
|
|
// Set a mock marshaler that returns an int
|
|
ErrorStackMarshaler = func(err error) interface{} {
|
|
return 42
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
log := New(&buf).With().Stack().Err(errors.New("test error")).Logger()
|
|
|
|
log.Info().Msg("test message")
|
|
|
|
got := decodeIfBinaryToString(buf.Bytes())
|
|
want := `{"level":"info","stack":42,"error":"test error","message":"test message"}` + "\n"
|
|
if got != want {
|
|
t.Errorf("Context.Err() with stack marshaler interface = %q, want %q", got, want)
|
|
}
|
|
}
|