In preparation for supporting log rotation, this patch makes the maillog package to use blitiri.com.ar/go/log instead of its own writer. Some of the tests are made more strict, to better test the log format. Amended-by: Alberto Bertogli <albertito@blitiri.com.ar> Fixed build, extended commit message, adjusted to the log options API, and added tests.
158 lines
4.2 KiB
Go
158 lines
4.2 KiB
Go
package maillog
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"blitiri.com.ar/go/log"
|
|
)
|
|
|
|
var netAddr = &net.TCPAddr{
|
|
IP: net.ParseIP("1.2.3.4"),
|
|
Port: 4321,
|
|
}
|
|
|
|
func expect(t *testing.T, buf *bytes.Buffer, s string) {
|
|
t.Helper()
|
|
re := regexp.MustCompile(`^....-..-.. ..:..:..\.\d{6} ` + s + "\n")
|
|
if !re.Match(buf.Bytes()) {
|
|
t.Errorf("mismatch:\n regexp: %q\n string: %q",
|
|
re, buf.String())
|
|
}
|
|
}
|
|
|
|
func TestLogger(t *testing.T) {
|
|
buf := &bytes.Buffer{}
|
|
l := New(nopCloser{buf})
|
|
|
|
l.Listening("1.2.3.4:4321")
|
|
expect(t, buf, "daemon listening on 1.2.3.4:4321")
|
|
buf.Reset()
|
|
|
|
l.Auth(netAddr, "user@domain", false)
|
|
expect(t, buf, "1.2.3.4:4321 auth failed for user@domain")
|
|
buf.Reset()
|
|
|
|
l.Auth(netAddr, "user@domain", true)
|
|
expect(t, buf, "1.2.3.4:4321 auth succeeded for user@domain")
|
|
buf.Reset()
|
|
|
|
l.Rejected(netAddr, "from", []string{"to1", "to2"}, "error")
|
|
expect(t, buf, `1.2.3.4:4321 rejected from=from to=\[to1 to2\] - error`)
|
|
buf.Reset()
|
|
|
|
l.Queued(netAddr, "from", []string{"to1", "to2"}, "qid")
|
|
expect(t, buf, `qid from=from queued ip=1.2.3.4:4321 to=\[to1 to2\]`)
|
|
buf.Reset()
|
|
|
|
l.SendAttempt("qid", "from", "to", nil, false)
|
|
expect(t, buf, "qid from=from to=to sent")
|
|
buf.Reset()
|
|
|
|
l.SendAttempt("qid", "from", "to", fmt.Errorf("error"), false)
|
|
expect(t, buf, `qid from=from to=to failed \(temporary\): error`)
|
|
buf.Reset()
|
|
|
|
l.SendAttempt("qid", "from", "to", fmt.Errorf("error"), true)
|
|
expect(t, buf, `qid from=from to=to failed \(permanent\): error`)
|
|
buf.Reset()
|
|
|
|
l.QueueLoop("qid", "from", 17*time.Second)
|
|
expect(t, buf, "qid from=from completed loop, next in 17s")
|
|
buf.Reset()
|
|
|
|
l.QueueLoop("qid", "from", 0)
|
|
expect(t, buf, "qid from=from all done")
|
|
buf.Reset()
|
|
}
|
|
|
|
// Test that the default actions go reasonably to the default logger.
|
|
// Unfortunately this is almost the same as TestLogger.
|
|
func TestDefault(t *testing.T) {
|
|
buf := &bytes.Buffer{}
|
|
Default = New(nopCloser{buf})
|
|
|
|
Listening("1.2.3.4:4321")
|
|
expect(t, buf, "daemon listening on 1.2.3.4:4321")
|
|
buf.Reset()
|
|
|
|
Auth(netAddr, "user@domain", false)
|
|
expect(t, buf, "1.2.3.4:4321 auth failed for user@domain")
|
|
buf.Reset()
|
|
|
|
Auth(netAddr, "user@domain", true)
|
|
expect(t, buf, "1.2.3.4:4321 auth succeeded for user@domain")
|
|
buf.Reset()
|
|
|
|
Rejected(netAddr, "from", []string{"to1", "to2"}, "error")
|
|
expect(t, buf, `1.2.3.4:4321 rejected from=from to=\[to1 to2\] - error`)
|
|
buf.Reset()
|
|
|
|
Queued(netAddr, "from", []string{"to1", "to2"}, "qid")
|
|
expect(t, buf, `qid from=from queued ip=1.2.3.4:4321 to=\[to1 to2\]`)
|
|
buf.Reset()
|
|
|
|
SendAttempt("qid", "from", "to", nil, false)
|
|
expect(t, buf, "qid from=from to=to sent")
|
|
buf.Reset()
|
|
|
|
SendAttempt("qid", "from", "to", fmt.Errorf("error"), false)
|
|
expect(t, buf, `qid from=from to=to failed \(temporary\): error`)
|
|
buf.Reset()
|
|
|
|
SendAttempt("qid", "from", "to", fmt.Errorf("error"), true)
|
|
expect(t, buf, `qid from=from to=to failed \(permanent\): error`)
|
|
buf.Reset()
|
|
|
|
QueueLoop("qid", "from", 17*time.Second)
|
|
expect(t, buf, "qid from=from completed loop, next in 17s")
|
|
buf.Reset()
|
|
|
|
QueueLoop("qid", "from", 0)
|
|
expect(t, buf, "qid from=from all done")
|
|
buf.Reset()
|
|
}
|
|
|
|
// io.Writer that fails all write operations, for testing.
|
|
type failedWriter struct{}
|
|
|
|
func (w *failedWriter) Write(p []byte) (int, error) {
|
|
return 0, fmt.Errorf("test error")
|
|
}
|
|
|
|
func (w *failedWriter) Close() error { return nil }
|
|
|
|
// Test that we complain (only once) when we can't log.
|
|
func TestFailedLogger(t *testing.T) {
|
|
// Set up a test logger, that will write to a buffer for us to check.
|
|
buf := &bytes.Buffer{}
|
|
log.Default = log.New(nopCloser{io.Writer(buf)})
|
|
|
|
// Set up a maillog that will use a writer which always fail, to trigger
|
|
// the condition.
|
|
failedw := &failedWriter{}
|
|
l := New(failedw)
|
|
|
|
// Log something, which should fail. Then verify that the error message
|
|
// appears in the log.
|
|
l.printf("123 testing")
|
|
s := buf.String()
|
|
if !strings.Contains(s, "failed to write to maillog: test error") {
|
|
t.Errorf("log did not contain expected message. Log: %#v", s)
|
|
}
|
|
|
|
// Further attempts should not generate any other errors.
|
|
buf.Reset()
|
|
l.printf("123 testing")
|
|
s = buf.String()
|
|
if s != "" {
|
|
t.Errorf("expected second attempt to not log, but log had: %#v", s)
|
|
}
|
|
}
|