Retro68/gcc/libgo/go/log/syslog/syslog_test.go

359 lines
7.7 KiB
Go
Raw Normal View History

2012-03-27 23:13:14 +00:00
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
2015-08-28 15:33:40 +00:00
// +build !windows,!nacl,!plan9
2012-03-27 23:13:14 +00:00
package syslog
import (
2014-09-21 17:33:12 +00:00
"bufio"
"fmt"
2012-03-27 23:13:14 +00:00
"io"
2014-09-21 17:33:12 +00:00
"io/ioutil"
2012-03-27 23:13:14 +00:00
"log"
"net"
2014-09-21 17:33:12 +00:00
"os"
"sync"
2012-03-27 23:13:14 +00:00
"testing"
"time"
)
2014-09-21 17:33:12 +00:00
func runPktSyslog(c net.PacketConn, done chan<- string) {
2012-03-27 23:13:14 +00:00
var buf [4096]byte
2014-09-21 17:33:12 +00:00
var rcvd string
ct := 0
2012-03-27 23:13:14 +00:00
for {
2014-09-21 17:33:12 +00:00
var n int
var err error
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
n, _, err = c.ReadFrom(buf[:])
rcvd += string(buf[:n])
if err != nil {
if oe, ok := err.(*net.OpError); ok {
if ct < 3 && oe.Temporary() {
ct++
continue
}
}
2012-03-27 23:13:14 +00:00
break
}
}
2014-09-21 17:33:12 +00:00
c.Close()
2012-03-27 23:13:14 +00:00
done <- rcvd
}
2014-09-21 17:33:12 +00:00
var crashy = false
func runStreamSyslog(l net.Listener, done chan<- string, wg *sync.WaitGroup) {
for {
var c net.Conn
var err error
if c, err = l.Accept(); err != nil {
return
}
wg.Add(1)
go func(c net.Conn) {
defer wg.Done()
c.SetReadDeadline(time.Now().Add(5 * time.Second))
b := bufio.NewReader(c)
for ct := 1; !crashy || ct&7 != 0; ct++ {
s, err := b.ReadString('\n')
if err != nil {
break
}
done <- s
}
c.Close()
}(c)
2012-03-27 23:13:14 +00:00
}
}
2014-09-21 17:33:12 +00:00
func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, wg *sync.WaitGroup) {
if n == "udp" || n == "tcp" {
la = "127.0.0.1:0"
} else {
// unix and unixgram: choose an address if none given
if la == "" {
// use ioutil.TempFile to get a name that is unique
f, err := ioutil.TempFile("", "syslogtest")
if err != nil {
log.Fatal("TempFile: ", err)
}
f.Close()
la = f.Name()
}
os.Remove(la)
2012-03-27 23:13:14 +00:00
}
2014-09-21 17:33:12 +00:00
wg = new(sync.WaitGroup)
if n == "udp" || n == "unixgram" {
l, e := net.ListenPacket(n, la)
if e != nil {
log.Fatalf("startServer failed: %v", e)
}
addr = l.LocalAddr().String()
sock = l
wg.Add(1)
go func() {
defer wg.Done()
runPktSyslog(l, done)
}()
} else {
l, e := net.Listen(n, la)
if e != nil {
log.Fatalf("startServer failed: %v", e)
}
addr = l.Addr().String()
sock = l
wg.Add(1)
go func() {
defer wg.Done()
runStreamSyslog(l, done, wg)
}()
}
return
}
func TestWithSimulated(t *testing.T) {
msg := "Test 123"
transport := []string{"unix", "unixgram", "udp", "tcp"}
for _, tr := range transport {
done := make(chan string)
addr, sock, srvWG := startServer(tr, "", done)
defer srvWG.Wait()
defer sock.Close()
if tr == "unix" || tr == "unixgram" {
defer os.Remove(addr)
}
s, err := Dial(tr, addr, LOG_INFO|LOG_USER, "syslog_test")
if err != nil {
t.Fatalf("Dial() failed: %v", err)
}
err = s.Info(msg)
if err != nil {
t.Fatalf("log failed: %v", err)
}
check(t, msg, <-done)
s.Close()
}
}
func TestFlap(t *testing.T) {
net := "unix"
done := make(chan string)
addr, sock, srvWG := startServer(net, "", done)
defer srvWG.Wait()
defer os.Remove(addr)
defer sock.Close()
s, err := Dial(net, addr, LOG_INFO|LOG_USER, "syslog_test")
if err != nil {
t.Fatalf("Dial() failed: %v", err)
}
msg := "Moo 2"
err = s.Info(msg)
if err != nil {
t.Fatalf("log failed: %v", err)
}
check(t, msg, <-done)
// restart the server
_, sock2, srvWG2 := startServer(net, addr, done)
defer srvWG2.Wait()
defer sock2.Close()
// and try retransmitting
msg = "Moo 3"
err = s.Info(msg)
if err != nil {
t.Fatalf("log failed: %v", err)
}
check(t, msg, <-done)
s.Close()
2012-03-27 23:13:14 +00:00
}
func TestNew(t *testing.T) {
2014-09-21 17:33:12 +00:00
if LOG_LOCAL7 != 23<<3 {
t.Fatalf("LOG_LOCAL7 has wrong value")
}
if testing.Short() {
// Depends on syslog daemon running, and sometimes it's not.
t.Skip("skipping syslog test during -short")
2012-03-27 23:13:14 +00:00
}
2014-09-21 17:33:12 +00:00
s, err := New(LOG_INFO|LOG_USER, "the_tag")
2012-03-27 23:13:14 +00:00
if err != nil {
t.Fatalf("New() failed: %s", err)
}
// Don't send any messages.
s.Close()
}
func TestNewLogger(t *testing.T) {
2014-09-21 17:33:12 +00:00
if testing.Short() {
t.Skip("skipping syslog test during -short")
2012-03-27 23:13:14 +00:00
}
2014-09-21 17:33:12 +00:00
f, err := NewLogger(LOG_USER|LOG_INFO, 0)
2012-03-27 23:13:14 +00:00
if f == nil {
t.Error(err)
}
}
func TestDial(t *testing.T) {
2014-09-21 17:33:12 +00:00
if testing.Short() {
t.Skip("skipping syslog test during -short")
2012-03-27 23:13:14 +00:00
}
2014-09-21 17:33:12 +00:00
f, err := Dial("", "", (LOG_LOCAL7|LOG_DEBUG)+1, "syslog_test")
if f != nil {
t.Fatalf("Should have trapped bad priority")
}
f, err = Dial("", "", -1, "syslog_test")
if f != nil {
t.Fatalf("Should have trapped bad priority")
}
l, err := Dial("", "", LOG_USER|LOG_ERR, "syslog_test")
2012-03-27 23:13:14 +00:00
if err != nil {
t.Fatalf("Dial() failed: %s", err)
}
l.Close()
}
2014-09-21 17:33:12 +00:00
func check(t *testing.T, in, out string) {
tmpl := fmt.Sprintf("<%d>%%s %%s syslog_test[%%d]: %s\n", LOG_USER+LOG_INFO, in)
if hostname, err := os.Hostname(); err != nil {
t.Error("Error retrieving hostname")
} else {
var parsedHostname, timestamp string
var pid int
if n, err := fmt.Sscanf(out, tmpl, &timestamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname {
t.Errorf("Got %q, does not match template %q (%d %s)", out, tmpl, n, err)
}
2012-03-27 23:13:14 +00:00
}
}
func TestWrite(t *testing.T) {
2014-09-21 17:33:12 +00:00
tests := []struct {
pri Priority
pre string
msg string
exp string
}{
{LOG_USER | LOG_ERR, "syslog_test", "", "%s %s syslog_test[%d]: \n"},
{LOG_USER | LOG_ERR, "syslog_test", "write test", "%s %s syslog_test[%d]: write test\n"},
// Write should not add \n if there already is one
{LOG_USER | LOG_ERR, "syslog_test", "write test 2\n", "%s %s syslog_test[%d]: write test 2\n"},
}
if hostname, err := os.Hostname(); err != nil {
t.Fatalf("Error retrieving hostname")
} else {
for _, test := range tests {
done := make(chan string)
addr, sock, srvWG := startServer("udp", "", done)
defer srvWG.Wait()
defer sock.Close()
l, err := Dial("udp", addr, test.pri, test.pre)
if err != nil {
t.Fatalf("syslog.Dial() failed: %v", err)
}
defer l.Close()
_, err = io.WriteString(l, test.msg)
if err != nil {
t.Fatalf("WriteString() failed: %v", err)
}
rcvd := <-done
test.exp = fmt.Sprintf("<%d>", test.pri) + test.exp
var parsedHostname, timestamp string
var pid int
if n, err := fmt.Sscanf(rcvd, test.exp, &timestamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname {
t.Errorf("s.Info() = '%q', didn't match '%q' (%d %s)", rcvd, test.exp, n, err)
}
}
2012-03-27 23:13:14 +00:00
}
2014-09-21 17:33:12 +00:00
}
func TestConcurrentWrite(t *testing.T) {
addr, sock, srvWG := startServer("udp", "", make(chan string, 1))
defer srvWG.Wait()
defer sock.Close()
w, err := Dial("udp", addr, LOG_USER|LOG_ERR, "how's it going?")
2012-03-27 23:13:14 +00:00
if err != nil {
2014-09-21 17:33:12 +00:00
t.Fatalf("syslog.Dial() failed: %v", err)
2012-03-27 23:13:14 +00:00
}
2014-09-21 17:33:12 +00:00
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
err := w.Info("test")
if err != nil {
t.Errorf("Info() failed: %v", err)
return
}
}()
}
wg.Wait()
}
func TestConcurrentReconnect(t *testing.T) {
crashy = true
defer func() { crashy = false }()
const N = 10
const M = 100
net := "unix"
done := make(chan string, N*M)
addr, sock, srvWG := startServer(net, "", done)
defer os.Remove(addr)
// count all the messages arriving
count := make(chan int)
go func() {
ct := 0
2015-08-28 15:33:40 +00:00
for range done {
2014-09-21 17:33:12 +00:00
ct++
// we are looking for 500 out of 1000 events
// here because lots of log messages are lost
// in buffers (kernel and/or bufio)
if ct > N*M/2 {
break
}
}
count <- ct
}()
var wg sync.WaitGroup
wg.Add(N)
for i := 0; i < N; i++ {
go func() {
defer wg.Done()
w, err := Dial(net, addr, LOG_USER|LOG_ERR, "tag")
if err != nil {
t.Fatalf("syslog.Dial() failed: %v", err)
}
defer w.Close()
for i := 0; i < M; i++ {
err := w.Info("test")
if err != nil {
t.Errorf("Info() failed: %v", err)
return
}
}
}()
}
wg.Wait()
sock.Close()
srvWG.Wait()
close(done)
select {
case <-count:
case <-time.After(100 * time.Millisecond):
t.Error("timeout in concurrent reconnect")
2012-03-27 23:13:14 +00:00
}
}