func (l *TestLogger) Info(msg string, fields ...map[string]interface{}) {
	l.record(Info, msg, fields)
}
Info records an Info level event.
package logur
import (
	"context"
	"fmt"
	"sync"
)
type LogEvent struct {
	Line   string
	Level  Level
	Fields map[string]interface{}
}
func (e LogEvent) Equals(other LogEvent) bool {
	if e.Level != other.Level {
		return false
	}
	if e.Line != other.Line {
		return false
	}
	if len(e.Fields) != len(other.Fields) {
		return false
	}
	for key, value := range e.Fields {
		if other.Fields[key] != value {
			return false
		}
	}
	return true
}
func (e LogEvent) AssertEquals(other LogEvent) error {
	if !e.Equals(other) {
		return logEventAssertionError{
			actual:   e,
			expected: other,
		}
	}
	return nil
}
type logEventAssertionError struct {
	actual   LogEvent
	expected LogEvent
}
func (logEventAssertionError) Error() string {
	return "failed to assert that log events are equal"
}
func (e logEventAssertionError) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			_, _ = fmt.Fprintf(s, "%s\n", e.Error())
			_, _ = fmt.Fprint(s, "expected:\n")
			_, _ = fmt.Fprintf(s, "    line:   %s\n", e.expected.Line)
			_, _ = fmt.Fprintf(s, "    level:  %s\n", e.expected.Level)
			_, _ = fmt.Fprintf(s, "    fields: %+v\n", e.expected.Fields)
			_, _ = fmt.Fprint(s, "actual:\n")
			_, _ = fmt.Fprintf(s, "    line:   %s\n", e.actual.Line)
			_, _ = fmt.Fprintf(s, "    level:  %s\n", e.actual.Level)
			_, _ = fmt.Fprintf(s, "    fields: %+v\n", e.actual.Fields)
			return
		}
		_, _ = fmt.Fprintf(s, "%v", e.Error())
	case 's':
		_, _ = fmt.Fprintf(s, "%s", e.Error())
	case 'q':
		_, _ = fmt.Fprintf(s, "%q", e.Error())
	}
}
func LogEventsEqual(expected LogEvent, actual LogEvent) error {
	if expected.Level != actual.Level {
		return fmt.Errorf("expected log levels to be equal\ngot:  %s\nwant: %s", actual.Level, expected.Level)
	}
	if expected.Line != actual.Line {
		return fmt.Errorf("expected log lines to be equal\ngot:  %q\nwant: %q", actual.Line, expected.Line)
	}
	if len(expected.Fields) != len(actual.Fields) {
		return fmt.Errorf("expected log fields to be equal\ngot:  %v\nwant: %v", actual.Fields, expected.Fields)
	}
	for key, value := range expected.Fields {
		if actual.Fields[key] != value {
			return fmt.Errorf("expected log fields to be equal\ngot:  %v\nwant: %v", actual.Fields, expected.Fields)
		}
	}
	return nil
}
type TestLogger struct {
	events []LogEvent
	mu     sync.RWMutex
}
func NewTestLogger() *TestLogger {
	return &TestLogger{}
}
func (l *TestLogger) Count() int {
	l.mu.RLock()
	defer l.mu.RUnlock()
	return len(l.events)
}
func (l *TestLogger) LastEvent() *LogEvent {
	l.mu.RLock()
	defer l.mu.RUnlock()
	if l.events == nil || len(l.events) < 1 {
		return nil
	}
	event := l.events[len(l.events)-1]
	return &event
}
func (l *TestLogger) Events() []LogEvent {
	l.mu.RLock()
	defer l.mu.RUnlock()
	if l.events == nil {
		return []LogEvent{}
	}
	return l.events[:len(l.events)]
}
func (l *TestLogger) recordEvent(event LogEvent) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.events = append(l.events, event)
}
func (l *TestLogger) record(level Level, msg string, varfields []map[string]interface{}) {
	var fields map[string]interface{}
	if len(varfields) > 0 {
		fields = varfields[0]
	}
	l.recordEvent(LogEvent{
		Line:   msg,
		Level:  level,
		Fields: fields,
	})
}
func (l *TestLogger) Trace(msg string, fields ...map[string]interface{}) {
	l.record(Trace, msg, fields)
}
func (l *TestLogger) Debug(msg string, fields ...map[string]interface{}) {
	l.record(Debug, msg, fields)
}