1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build !windows,!plan9
22 func runPktSyslog(c net
.PacketConn
, done
chan<- string) {
30 c
.SetReadDeadline(time
.Now().Add(100 * time
.Millisecond
))
31 n
, _
, err
= c
.ReadFrom(buf
[:])
32 rcvd
+= string(buf
[:n
])
34 if oe
, ok
:= err
.(*net
.OpError
); ok
{
35 if ct
< 3 && oe
.Temporary() {
49 func runStreamSyslog(l net
.Listener
, done
chan<- string, wg
*sync
.WaitGroup
) {
53 if c
, err
= l
.Accept(); err
!= nil {
59 c
.SetReadDeadline(time
.Now().Add(5 * time
.Second
))
60 b
:= bufio
.NewReader(c
)
61 for ct
:= 1; !crashy || ct
&7 != 0; ct
++ {
62 s
, err
:= b
.ReadString('\n')
73 func startServer(n
, la
string, done
chan<- string) (addr
string, sock io
.Closer
, wg
*sync
.WaitGroup
) {
74 if n
== "udp" || n
== "tcp" {
77 // unix and unixgram: choose an address if none given
79 // use ioutil.TempFile to get a name that is unique
80 f
, err
:= ioutil
.TempFile("", "syslogtest")
82 log
.Fatal("TempFile: ", err
)
90 wg
= new(sync
.WaitGroup
)
91 if n
== "udp" || n
== "unixgram" {
92 l
, e
:= net
.ListenPacket(n
, la
)
94 log
.Fatalf("startServer failed: %v", e
)
96 addr
= l
.LocalAddr().String()
101 runPktSyslog(l
, done
)
104 l
, e
:= net
.Listen(n
, la
)
106 log
.Fatalf("startServer failed: %v", e
)
108 addr
= l
.Addr().String()
113 runStreamSyslog(l
, done
, wg
)
119 func TestWithSimulated(t
*testing
.T
) {
121 transport
:= []string{"unix", "unixgram", "udp", "tcp"}
123 for _
, tr
:= range transport
{
124 done
:= make(chan string)
125 addr
, _
, _
:= startServer(tr
, "", done
)
126 if tr
== "unix" || tr
== "unixgram" {
127 defer os
.Remove(addr
)
129 s
, err
:= Dial(tr
, addr
, LOG_INFO|LOG_USER
, "syslog_test")
131 t
.Fatalf("Dial() failed: %v", err
)
135 t
.Fatalf("log failed: %v", err
)
137 check(t
, msg
, <-done
)
142 func TestFlap(t
*testing
.T
) {
144 done
:= make(chan string)
145 addr
, sock
, _
:= startServer(net
, "", done
)
146 defer os
.Remove(addr
)
149 s
, err
:= Dial(net
, addr
, LOG_INFO|LOG_USER
, "syslog_test")
151 t
.Fatalf("Dial() failed: %v", err
)
156 t
.Fatalf("log failed: %v", err
)
158 check(t
, msg
, <-done
)
160 // restart the server
161 _
, sock2
, _
:= startServer(net
, addr
, done
)
164 // and try retransmitting
168 t
.Fatalf("log failed: %v", err
)
170 check(t
, msg
, <-done
)
175 func TestNew(t
*testing
.T
) {
176 if LOG_LOCAL7
!= 23<<3 {
177 t
.Fatalf("LOG_LOCAL7 has wrong value")
180 // Depends on syslog daemon running, and sometimes it's not.
181 t
.Skip("skipping syslog test during -short")
184 s
, err
:= New(LOG_INFO|LOG_USER
, "the_tag")
186 t
.Fatalf("New() failed: %s", err
)
188 // Don't send any messages.
192 func TestNewLogger(t
*testing
.T
) {
194 t
.Skip("skipping syslog test during -short")
196 f
, err
:= NewLogger(LOG_USER|LOG_INFO
, 0)
202 func TestDial(t
*testing
.T
) {
204 t
.Skip("skipping syslog test during -short")
206 f
, err
:= Dial("", "", (LOG_LOCAL7|LOG_DEBUG
)+1, "syslog_test")
208 t
.Fatalf("Should have trapped bad priority")
210 f
, err
= Dial("", "", -1, "syslog_test")
212 t
.Fatalf("Should have trapped bad priority")
214 l
, err
:= Dial("", "", LOG_USER|LOG_ERR
, "syslog_test")
216 t
.Fatalf("Dial() failed: %s", err
)
221 func check(t
*testing
.T
, in
, out
string) {
222 tmpl
:= fmt
.Sprintf("<%d>%%s %%s syslog_test[%%d]: %s\n", LOG_USER
+LOG_INFO
, in
)
223 if hostname
, err
:= os
.Hostname(); err
!= nil {
224 t
.Error("Error retrieving hostname")
226 var parsedHostname
, timestamp
string
228 if n
, err
:= fmt
.Sscanf(out
, tmpl
, ×tamp
, &parsedHostname
, &pid
); n
!= 3 || err
!= nil || hostname
!= parsedHostname
{
229 t
.Errorf("Got %q, does not match template %q (%d %s)", out
, tmpl
, n
, err
)
234 func TestWrite(t
*testing
.T
) {
241 {LOG_USER | LOG_ERR
, "syslog_test", "", "%s %s syslog_test[%d]: \n"},
242 {LOG_USER | LOG_ERR
, "syslog_test", "write test", "%s %s syslog_test[%d]: write test\n"},
243 // Write should not add \n if there already is one
244 {LOG_USER | LOG_ERR
, "syslog_test", "write test 2\n", "%s %s syslog_test[%d]: write test 2\n"},
247 if hostname
, err
:= os
.Hostname(); err
!= nil {
248 t
.Fatalf("Error retrieving hostname")
250 for _
, test
:= range tests
{
251 done
:= make(chan string)
252 addr
, sock
, _
:= startServer("udp", "", done
)
254 l
, err
:= Dial("udp", addr
, test
.pri
, test
.pre
)
256 t
.Fatalf("syslog.Dial() failed: %v", err
)
258 _
, err
= io
.WriteString(l
, test
.msg
)
260 t
.Fatalf("WriteString() failed: %v", err
)
263 test
.exp
= fmt
.Sprintf("<%d>", test
.pri
) + test
.exp
264 var parsedHostname
, timestamp
string
266 if n
, err
:= fmt
.Sscanf(rcvd
, test
.exp
, ×tamp
, &parsedHostname
, &pid
); n
!= 3 || err
!= nil || hostname
!= parsedHostname
{
267 t
.Errorf("s.Info() = '%q', didn't match '%q' (%d %s)", rcvd
, test
.exp
, n
, err
)
273 func TestConcurrentWrite(t
*testing
.T
) {
274 addr
, sock
, _
:= startServer("udp", "", make(chan string))
276 w
, err
:= Dial("udp", addr
, LOG_USER|LOG_ERR
, "how's it going?")
278 t
.Fatalf("syslog.Dial() failed: %v", err
)
280 var wg sync
.WaitGroup
281 for i
:= 0; i
< 10; i
++ {
284 err
:= w
.Info("test")
286 t
.Errorf("Info() failed: %v", err
)
295 func TestConcurrentReconnect(t
*testing
.T
) {
297 defer func() { crashy
= false }()
300 done
:= make(chan string)
301 addr
, sock
, srvWG
:= startServer(net
, "", done
)
302 defer os
.Remove(addr
)
304 // count all the messages arriving
305 count
:= make(chan int)
310 // we are looking for 500 out of 1000 events
311 // here because lots of log messages are lost
312 // in buffers (kernel and/or bufio)
320 var wg sync
.WaitGroup
321 for i
:= 0; i
< 10; i
++ {
324 w
, err
:= Dial(net
, addr
, LOG_USER|LOG_ERR
, "tag")
326 t
.Fatalf("syslog.Dial() failed: %v", err
)
328 for i
:= 0; i
< 100; i
++ {
329 err
:= w
.Info("test")
331 t
.Errorf("Info() failed: %v", err
)
345 case <-time
.After(100 * time
.Millisecond
):
346 t
.Error("timeout in concurrent reconnect")