// Copyright 2014 ISRG. All rights reserved // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. package log import ( "errors" "fmt" "log/syslog" "net" "testing" "time" "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd" "github.com/letsencrypt/boulder/test" ) func TestConstruction(t *testing.T) { t.Parallel() writer, err := syslog.New(syslog.LOG_EMERG|syslog.LOG_KERN, "tag") test.AssertNotError(t, err, "Could not construct syslog object") stats, _ := statsd.NewNoopClient(nil) _, err = NewAuditLogger(writer, stats) test.AssertNotError(t, err, "Could not construct audit logger") } func TestSingleton(t *testing.T) { t.Parallel() log1 := GetAuditLogger() test.AssertNotNil(t, log1, "Logger shouldn't be nil") log2 := GetAuditLogger() test.AssertEquals(t, log1, log2) writer, err := syslog.New(syslog.LOG_EMERG|syslog.LOG_KERN, "tag") test.AssertNotError(t, err, "Could not construct syslog object") stats, _ := statsd.NewNoopClient(nil) log3, err := NewAuditLogger(writer, stats) test.AssertNotError(t, err, "Could not construct audit logger") // Should not work err = SetAuditLogger(log3) test.AssertError(t, err, "Can't re-set") // Verify no change log4 := GetAuditLogger() // Verify that log4 != log3 test.AssertNotEquals(t, log4, log3) // Verify that log4 == log2 == log1 test.AssertEquals(t, log4, log2) test.AssertEquals(t, log4, log1) } func TestDial(t *testing.T) { t.Parallel() stats, _ := statsd.NewNoopClient(nil) _, err := Dial("", "", "tag", stats) test.AssertNotError(t, err, "Could not construct audit logger") } func TestDialError(t *testing.T) { t.Parallel() stats, _ := statsd.NewNoopClient(nil) _, err := Dial("_fail", "_fail", "tag", stats) test.AssertError(t, err, "Audit Logger should have failed") } func TestConstructionNil(t *testing.T) { t.Parallel() stats, _ := statsd.NewNoopClient(nil) _, err := NewAuditLogger(nil, stats) test.AssertError(t, err, "Nil shouldn't be permitted.") } func TestEmit(t *testing.T) { t.Parallel() writer, err := syslog.New(syslog.LOG_EMERG|syslog.LOG_KERN, "tag") test.AssertNotError(t, err, "Could not construct syslog object") stats, _ := statsd.NewNoopClient(nil) audit, err := NewAuditLogger(writer, stats) test.AssertNotError(t, err, "Could not construct audit logger") audit.Audit("test message") } func TestEmitEmpty(t *testing.T) { t.Parallel() writer, err := syslog.New(syslog.LOG_EMERG|syslog.LOG_KERN, "tag") test.AssertNotError(t, err, "Could not construct syslog object") stats, _ := statsd.NewNoopClient(nil) audit, err := NewAuditLogger(writer, stats) test.AssertNotError(t, err, "Could not construct audit logger") audit.Audit("") } func TestEmitErrors(t *testing.T) { t.Parallel() stats, _ := statsd.NewNoopClient(nil) audit, _ := Dial("", "", "tag", stats) audit.AuditErr(errors.New("Error Audit")) audit.WarningErr(errors.New("Warning Audit")) } func TestSyslogMethods(t *testing.T) { t.Parallel() // Write all logs to UDP on a high port so as to not bother the system // which is running the test, particularly for Emerg() writer, err := syslog.Dial("udp", "127.0.0.1:65530", syslog.LOG_INFO|syslog.LOG_LOCAL0, "") test.AssertNotError(t, err, "Could not construct syslog object") stats, _ := statsd.NewNoopClient(nil) audit, err := NewAuditLogger(writer, stats) test.AssertNotError(t, err, "Could not construct audit logger") audit.Audit("audit-logger_test.go: audit-notice") audit.Crit("audit-logger_test.go: critical") audit.Debug("audit-logger_test.go: debug") audit.Emerg("audit-logger_test.go: emerg") audit.Err("audit-logger_test.go: err") audit.Info("audit-logger_test.go: info") audit.Notice("audit-logger_test.go: notice") audit.Warning("audit-logger_test.go: warning") audit.Alert("audit-logger_test.go: alert") } func TestPanic(t *testing.T) { t.Parallel() stats, _ := statsd.NewNoopClient(nil) audit, _ := Dial("", "", "tag", stats) defer audit.AuditPanic() panic("Test panic") // Can't assert anything here or golint gets angry } func TestAuditObject(t *testing.T) { t.Parallel() stats, _ := statsd.NewNoopClient(nil) audit, _ := Dial("", "", "tag", stats) // Test a simple object err := audit.AuditObject("Prefix", "String") test.AssertNotError(t, err, "Simple objects should be serializable") // Test a system object err = audit.AuditObject("Prefix", t) test.AssertNotError(t, err, "System objects should be serializable") // Test a complex object type validObj struct { A string B string } var valid = validObj{A: "B", B: "C"} err = audit.AuditObject("Prefix", valid) test.AssertNotError(t, err, "Complex objects should be serializable") type invalidObj struct { A chan string } var invalid = invalidObj{A: make(chan string)} err = audit.AuditObject("Prefix", invalid) test.AssertError(t, err, "Invalid objects should fail serialization") } func TestEmergencyExit(t *testing.T) { t.Parallel() // Write all logs to UDP on a high port so as to not bother the system // which is running the test, particularly for Emerg() writer, err := syslog.Dial("udp", "127.0.0.1:65530", syslog.LOG_INFO|syslog.LOG_LOCAL0, "") test.AssertNotError(t, err, "Could not construct syslog object") stats, _ := statsd.NewNoopClient(nil) audit, err := NewAuditLogger(writer, stats) test.AssertNotError(t, err, "Could not construct audit logger") called := false audit.SetEmergencyExitFunc(func() { called = true }) audit.EmergencyExit("Emergency!") test.AssertEquals(t, called, true) } func TestUnknownLoggingLevel(t *testing.T) { t.Parallel() stats, _ := statsd.NewNoopClient(nil) audit, _ := Dial("", "", "tag", stats) err := audit.logAtLevel("Logging.Unknown", "string") test.AssertError(t, err, "Should have been unknown.") } func TestTransmission(t *testing.T) { t.Parallel() l, err := newUDPListener("127.0.0.1:0") test.AssertNotError(t, err, "Failed to open log server") defer l.Close() stats, _ := statsd.NewNoopClient(nil) fmt.Printf("Going to %s\n", l.LocalAddr().String()) writer, err := syslog.Dial("udp", l.LocalAddr().String(), syslog.LOG_INFO|syslog.LOG_LOCAL0, "") test.AssertNotError(t, err, "Failed to find connect to log server") audit, err := NewAuditLogger(writer, stats) test.AssertNotError(t, err, "Failed to construct audit logger") data := make([]byte, 128) audit.Audit("audit-logger_test.go: audit-notice") _, _, err = l.ReadFrom(data) test.AssertNotError(t, err, "Failed to find packet") audit.Crit("audit-logger_test.go: critical") _, _, err = l.ReadFrom(data) test.AssertNotError(t, err, "Failed to find packet") audit.Debug("audit-logger_test.go: debug") _, _, err = l.ReadFrom(data) test.AssertNotError(t, err, "Failed to find packet") audit.Emerg("audit-logger_test.go: emerg") _, _, err = l.ReadFrom(data) test.AssertNotError(t, err, "Failed to find packet") audit.Err("audit-logger_test.go: err") _, _, err = l.ReadFrom(data) test.AssertNotError(t, err, "Failed to find packet") audit.Info("audit-logger_test.go: info") _, _, err = l.ReadFrom(data) test.AssertNotError(t, err, "Failed to find packet") audit.Notice("audit-logger_test.go: notice") _, _, err = l.ReadFrom(data) test.AssertNotError(t, err, "Failed to find packet") audit.Warning("audit-logger_test.go: warning") _, _, err = l.ReadFrom(data) test.AssertNotError(t, err, "Failed to find packet") audit.Alert("audit-logger_test.go: alert") _, _, err = l.ReadFrom(data) test.AssertNotError(t, err, "Failed to find packet") } func newUDPListener(addr string) (*net.UDPConn, error) { l, err := net.ListenPacket("udp", addr) if err != nil { return nil, err } l.SetDeadline(time.Now().Add(100 * time.Millisecond)) l.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) l.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) return l.(*net.UDPConn), nil }