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,!js
23 func runPktSyslog(c net.PacketConn, done chan<- string) {
31 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
32 n, _, err = c.ReadFrom(buf[:])
33 rcvd += string(buf[:n])
35 if oe, ok := err.(*net.OpError); ok {
36 if ct < 3 && oe.Temporary() {
50 func testableNetwork(network string) bool {
52 case "unix", "unixgram":
55 switch runtime.GOARCH {
66 func runStreamSyslog(l net.Listener, done chan<- string, wg *sync.WaitGroup) {
70 if c, err = l.Accept(); err != nil {
76 c.SetReadDeadline(time.Now().Add(5 * time.Second))
77 b := bufio.NewReader(c)
78 for ct := 1; !crashy || ct&7 != 0; ct++ {
79 s, err := b.ReadString('\n')
90 func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, wg *sync.WaitGroup) {
91 if n == "udp" || n == "tcp" {
94 // unix and unixgram: choose an address if none given
96 // use ioutil.TempFile to get a name that is unique
97 f, err := ioutil.TempFile("", "syslogtest")
99 log.Fatal("TempFile: ", err)
107 wg = new(sync.WaitGroup)
108 if n == "udp" || n == "unixgram" {
109 l, e := net.ListenPacket(n, la)
111 log.Fatalf("startServer failed: %v", e)
113 addr = l.LocalAddr().String()
118 runPktSyslog(l, done)
121 l, e := net.Listen(n, la)
123 log.Fatalf("startServer failed: %v", e)
125 addr = l.Addr().String()
130 runStreamSyslog(l, done, wg)
136 func TestWithSimulated(t *testing.T) {
139 var transport []string
140 for _, n := range []string{"unix", "unixgram", "udp", "tcp"} {
141 if testableNetwork(n) {
142 transport = append(transport, n)
146 for _, tr := range transport {
147 done := make(chan string)
148 addr, sock, srvWG := startServer(tr, "", done)
151 if tr == "unix" || tr == "unixgram" {
152 defer os.Remove(addr)
154 s, err := Dial(tr, addr, LOG_INFO|LOG_USER, "syslog_test")
156 t.Fatalf("Dial() failed: %v", err)
160 t.Fatalf("log failed: %v", err)
162 check(t, msg, <-done)
167 func TestFlap(t *testing.T) {
169 if !testableNetwork(net) {
170 t.Skipf("skipping on %s/%s; 'unix' is not supported", runtime.GOOS, runtime.GOARCH)
173 done := make(chan string)
174 addr, sock, srvWG := startServer(net, "", done)
176 defer os.Remove(addr)
179 s, err := Dial(net, addr, LOG_INFO|LOG_USER, "syslog_test")
181 t.Fatalf("Dial() failed: %v", err)
186 t.Fatalf("log failed: %v", err)
188 check(t, msg, <-done)
190 // restart the server
191 _, sock2, srvWG2 := startServer(net, addr, done)
195 // and try retransmitting
199 t.Fatalf("log failed: %v", err)
201 check(t, msg, <-done)
206 func TestNew(t *testing.T) {
207 if LOG_LOCAL7 != 23<<3 {
208 t.Fatalf("LOG_LOCAL7 has wrong value")
211 // Depends on syslog daemon running, and sometimes it's not.
212 t.Skip("skipping syslog test during -short")
215 s, err := New(LOG_INFO|LOG_USER, "the_tag")
217 if err.Error() == "Unix syslog delivery error" {
218 t.Skip("skipping: syslogd not running")
220 t.Fatalf("New() failed: %s", err)
222 // Don't send any messages.
226 func TestNewLogger(t *testing.T) {
228 t.Skip("skipping syslog test during -short")
230 f, err := NewLogger(LOG_USER|LOG_INFO, 0)
232 if err.Error() == "Unix syslog delivery error" {
233 t.Skip("skipping: syslogd not running")
239 func TestDial(t *testing.T) {
241 t.Skip("skipping syslog test during -short")
243 f, err := Dial("", "", (LOG_LOCAL7|LOG_DEBUG)+1, "syslog_test")
245 t.Fatalf("Should have trapped bad priority")
247 f, err = Dial("", "", -1, "syslog_test")
249 t.Fatalf("Should have trapped bad priority")
251 l, err := Dial("", "", LOG_USER|LOG_ERR, "syslog_test")
253 if err.Error() == "Unix syslog delivery error" {
254 t.Skip("skipping: syslogd not running")
256 t.Fatalf("Dial() failed: %s", err)
261 func check(t *testing.T, in, out string) {
262 tmpl := fmt.Sprintf("<%d>%%s %%s syslog_test[%%d]: %s\n", LOG_USER+LOG_INFO, in)
263 if hostname, err := os.Hostname(); err != nil {
264 t.Error("Error retrieving hostname")
266 var parsedHostname, timestamp string
268 if n, err := fmt.Sscanf(out, tmpl, ×tamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname {
269 t.Errorf("Got %q, does not match template %q (%d %s)", out, tmpl, n, err)
274 func TestWrite(t *testing.T) {
282 {LOG_USER | LOG_ERR, "syslog_test", "", "%s %s syslog_test[%d]: \n"},
283 {LOG_USER | LOG_ERR, "syslog_test", "write test", "%s %s syslog_test[%d]: write test\n"},
284 // Write should not add \n if there already is one
285 {LOG_USER | LOG_ERR, "syslog_test", "write test 2\n", "%s %s syslog_test[%d]: write test 2\n"},
288 if hostname, err := os.Hostname(); err != nil {
289 t.Fatalf("Error retrieving hostname")
291 for _, test := range tests {
292 done := make(chan string)
293 addr, sock, srvWG := startServer("udp", "", done)
296 l, err := Dial("udp", addr, test.pri, test.pre)
298 t.Fatalf("syslog.Dial() failed: %v", err)
301 _, err = io.WriteString(l, test.msg)
303 t.Fatalf("WriteString() failed: %v", err)
306 test.exp = fmt.Sprintf("<%d>", test.pri) + test.exp
307 var parsedHostname, timestamp string
309 if n, err := fmt.Sscanf(rcvd, test.exp, ×tamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname {
310 t.Errorf("s.Info() = '%q', didn't match '%q' (%d %s)", rcvd, test.exp, n, err)
316 func TestConcurrentWrite(t *testing.T) {
317 addr, sock, srvWG := startServer("udp", "", make(chan string, 1))
320 w, err := Dial("udp", addr, LOG_USER|LOG_ERR, "how's it going?")
322 t.Fatalf("syslog.Dial() failed: %v", err)
324 var wg sync.WaitGroup
325 for i := 0; i < 10; i++ {
329 err := w.Info("test")
331 t.Errorf("Info() failed: %v", err)
339 func TestConcurrentReconnect(t *testing.T) {
341 defer func() { crashy = false }()
346 if !testableNetwork(net) {
348 if !testableNetwork(net) {
349 t.Skipf("skipping on %s/%s; neither 'unix' or 'tcp' is supported", runtime.GOOS, runtime.GOARCH)
352 done := make(chan string, N*M)
353 addr, sock, srvWG := startServer(net, "", done)
355 defer os.Remove(addr)
358 // count all the messages arriving
359 count := make(chan int)
364 // we are looking for 500 out of 1000 events
365 // here because lots of log messages are lost
366 // in buffers (kernel and/or bufio)
374 var wg sync.WaitGroup
376 for i := 0; i < N; i++ {
379 w, err := Dial(net, addr, LOG_USER|LOG_ERR, "tag")
381 t.Errorf("syslog.Dial() failed: %v", err)
385 for i := 0; i < M; i++ {
386 err := w.Info("test")
388 t.Errorf("Info() failed: %v", err)
401 case <-time.After(100 * time.Millisecond):
402 t.Error("timeout in concurrent reconnect")