111 lines
2.5 KiB
Go
111 lines
2.5 KiB
Go
package log
|
|
|
|
import (
|
|
"fmt"
|
|
"log/syslog"
|
|
"regexp"
|
|
)
|
|
|
|
// UseMock sets a mock logger as the default logger, and returns it.
|
|
func UseMock() *Mock {
|
|
m := NewMock()
|
|
_ = Set(m)
|
|
return m
|
|
}
|
|
|
|
// NewMock creates a mock logger.
|
|
func NewMock() *Mock {
|
|
return &Mock{impl{newMockWriter()}}
|
|
}
|
|
|
|
// Mock is a logger that stores all log messages in memory to be examined by a
|
|
// test.
|
|
type Mock struct {
|
|
impl
|
|
}
|
|
|
|
// Mock implements the writer interface. It
|
|
// stores all logged messages in a buffer for inspection by test
|
|
// functions (via GetAll()) instead of sending them to syslog.
|
|
type mockWriter struct {
|
|
logged []string
|
|
msgChan chan<- string
|
|
getChan <-chan []string
|
|
clearChan chan<- struct{}
|
|
closeChan chan<- struct{}
|
|
}
|
|
|
|
var levelName = map[syslog.Priority]string{
|
|
syslog.LOG_ERR: "ERR",
|
|
syslog.LOG_WARNING: "WARNING",
|
|
syslog.LOG_INFO: "INFO",
|
|
syslog.LOG_DEBUG: "DEBUG",
|
|
}
|
|
|
|
func (w *mockWriter) logAtLevel(p syslog.Priority, msg string) {
|
|
w.msgChan <- fmt.Sprintf("%s: %s", levelName[p&7], msg)
|
|
}
|
|
|
|
// newMockWriter returns a new mockWriter
|
|
func newMockWriter() *mockWriter {
|
|
msgChan := make(chan string)
|
|
getChan := make(chan []string)
|
|
clearChan := make(chan struct{})
|
|
closeChan := make(chan struct{})
|
|
w := &mockWriter{
|
|
logged: []string{},
|
|
msgChan: msgChan,
|
|
getChan: getChan,
|
|
clearChan: clearChan,
|
|
closeChan: closeChan,
|
|
}
|
|
go func() {
|
|
for {
|
|
select {
|
|
case logMsg := <-msgChan:
|
|
w.logged = append(w.logged, logMsg)
|
|
case getChan <- w.logged:
|
|
case <-clearChan:
|
|
w.logged = []string{}
|
|
case <-closeChan:
|
|
close(getChan)
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
return w
|
|
}
|
|
|
|
// GetAll returns all messages logged since instantiation or the last call to
|
|
// Clear().
|
|
//
|
|
// The caller must not modify the returned slice or its elements.
|
|
func (m *Mock) GetAll() []string {
|
|
w := m.w.(*mockWriter)
|
|
return <-w.getChan
|
|
}
|
|
|
|
// GetAllMatching returns all messages logged since instantiation or the last
|
|
// Clear() whose text matches the given regexp. The regexp is
|
|
// accepted as a string and compiled on the fly, because convenience
|
|
// is more important than performance.
|
|
//
|
|
// The caller must not modify the elements of the returned slice.
|
|
func (m *Mock) GetAllMatching(reString string) []string {
|
|
var matches []string
|
|
w := m.w.(*mockWriter)
|
|
re := regexp.MustCompile(reString)
|
|
for _, logMsg := range <-w.getChan {
|
|
if re.MatchString(logMsg) {
|
|
matches = append(matches, logMsg)
|
|
}
|
|
}
|
|
return matches
|
|
}
|
|
|
|
// Clear resets the log buffer.
|
|
func (m *Mock) Clear() {
|
|
w := m.w.(*mockWriter)
|
|
w.clearChan <- struct{}{}
|
|
}
|