Merged revisions 196716,196830,198094,198116,198502,198877,199007,199262,199319,19946...
[official-gcc.git] / main / libgo / go / log / syslog / syslog_test.go
blobec4525190f4945b006f2c0106bf21116d5422fdc
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
7 package syslog
9 import (
10 "bufio"
11 "fmt"
12 "io"
13 "io/ioutil"
14 "log"
15 "net"
16 "os"
17 "sync"
18 "testing"
19 "time"
22 func runPktSyslog(c net.PacketConn, done chan<- string) {
23 var buf [4096]byte
24 var rcvd string
25 ct := 0
26 for {
27 var n int
28 var err error
30 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
31 n, _, err = c.ReadFrom(buf[:])
32 rcvd += string(buf[:n])
33 if err != nil {
34 if oe, ok := err.(*net.OpError); ok {
35 if ct < 3 && oe.Temporary() {
36 ct++
37 continue
40 break
43 c.Close()
44 done <- rcvd
47 var crashy = false
49 func runStreamSyslog(l net.Listener, done chan<- string, wg *sync.WaitGroup) {
50 for {
51 var c net.Conn
52 var err error
53 if c, err = l.Accept(); err != nil {
54 return
56 wg.Add(1)
57 go func(c net.Conn) {
58 defer wg.Done()
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')
63 if err != nil {
64 break
66 done <- s
68 c.Close()
69 }(c)
73 func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, wg *sync.WaitGroup) {
74 if n == "udp" || n == "tcp" {
75 la = "127.0.0.1:0"
76 } else {
77 // unix and unixgram: choose an address if none given
78 if la == "" {
79 // use ioutil.TempFile to get a name that is unique
80 f, err := ioutil.TempFile("", "syslogtest")
81 if err != nil {
82 log.Fatal("TempFile: ", err)
84 f.Close()
85 la = f.Name()
87 os.Remove(la)
90 wg = new(sync.WaitGroup)
91 if n == "udp" || n == "unixgram" {
92 l, e := net.ListenPacket(n, la)
93 if e != nil {
94 log.Fatalf("startServer failed: %v", e)
96 addr = l.LocalAddr().String()
97 sock = l
98 wg.Add(1)
99 go func() {
100 defer wg.Done()
101 runPktSyslog(l, done)
103 } else {
104 l, e := net.Listen(n, la)
105 if e != nil {
106 log.Fatalf("startServer failed: %v", e)
108 addr = l.Addr().String()
109 sock = l
110 wg.Add(1)
111 go func() {
112 defer wg.Done()
113 runStreamSyslog(l, done, wg)
116 return
119 func TestWithSimulated(t *testing.T) {
120 msg := "Test 123"
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")
130 if err != nil {
131 t.Fatalf("Dial() failed: %v", err)
133 err = s.Info(msg)
134 if err != nil {
135 t.Fatalf("log failed: %v", err)
137 check(t, msg, <-done)
138 s.Close()
142 func TestFlap(t *testing.T) {
143 net := "unix"
144 done := make(chan string)
145 addr, sock, _ := startServer(net, "", done)
146 defer os.Remove(addr)
147 defer sock.Close()
149 s, err := Dial(net, addr, LOG_INFO|LOG_USER, "syslog_test")
150 if err != nil {
151 t.Fatalf("Dial() failed: %v", err)
153 msg := "Moo 2"
154 err = s.Info(msg)
155 if err != nil {
156 t.Fatalf("log failed: %v", err)
158 check(t, msg, <-done)
160 // restart the server
161 _, sock2, _ := startServer(net, addr, done)
162 defer sock2.Close()
164 // and try retransmitting
165 msg = "Moo 3"
166 err = s.Info(msg)
167 if err != nil {
168 t.Fatalf("log failed: %v", err)
170 check(t, msg, <-done)
172 s.Close()
175 func TestNew(t *testing.T) {
176 if LOG_LOCAL7 != 23<<3 {
177 t.Fatalf("LOG_LOCAL7 has wrong value")
179 if testing.Short() {
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")
185 if err != nil {
186 t.Fatalf("New() failed: %s", err)
188 // Don't send any messages.
189 s.Close()
192 func TestNewLogger(t *testing.T) {
193 if testing.Short() {
194 t.Skip("skipping syslog test during -short")
196 f, err := NewLogger(LOG_USER|LOG_INFO, 0)
197 if f == nil {
198 t.Error(err)
202 func TestDial(t *testing.T) {
203 if testing.Short() {
204 t.Skip("skipping syslog test during -short")
206 f, err := Dial("", "", (LOG_LOCAL7|LOG_DEBUG)+1, "syslog_test")
207 if f != nil {
208 t.Fatalf("Should have trapped bad priority")
210 f, err = Dial("", "", -1, "syslog_test")
211 if f != nil {
212 t.Fatalf("Should have trapped bad priority")
214 l, err := Dial("", "", LOG_USER|LOG_ERR, "syslog_test")
215 if err != nil {
216 t.Fatalf("Dial() failed: %s", err)
218 l.Close()
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")
225 } else {
226 var parsedHostname, timestamp string
227 var pid int
228 if n, err := fmt.Sscanf(out, tmpl, &timestamp, &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) {
235 tests := []struct {
236 pri Priority
237 pre string
238 msg string
239 exp string
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")
249 } else {
250 for _, test := range tests {
251 done := make(chan string)
252 addr, sock, _ := startServer("udp", "", done)
253 defer sock.Close()
254 l, err := Dial("udp", addr, test.pri, test.pre)
255 if err != nil {
256 t.Fatalf("syslog.Dial() failed: %v", err)
258 _, err = io.WriteString(l, test.msg)
259 if err != nil {
260 t.Fatalf("WriteString() failed: %v", err)
262 rcvd := <-done
263 test.exp = fmt.Sprintf("<%d>", test.pri) + test.exp
264 var parsedHostname, timestamp string
265 var pid int
266 if n, err := fmt.Sscanf(rcvd, test.exp, &timestamp, &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))
275 defer sock.Close()
276 w, err := Dial("udp", addr, LOG_USER|LOG_ERR, "how's it going?")
277 if err != nil {
278 t.Fatalf("syslog.Dial() failed: %v", err)
280 var wg sync.WaitGroup
281 for i := 0; i < 10; i++ {
282 wg.Add(1)
283 go func() {
284 err := w.Info("test")
285 if err != nil {
286 t.Errorf("Info() failed: %v", err)
287 return
289 wg.Done()
292 wg.Wait()
295 func TestConcurrentReconnect(t *testing.T) {
296 crashy = true
297 defer func() { crashy = false }()
299 net := "unix"
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)
306 go func() {
307 ct := 0
308 for _ = range done {
309 ct++
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)
313 if ct > 500 {
314 break
317 count <- ct
320 var wg sync.WaitGroup
321 for i := 0; i < 10; i++ {
322 wg.Add(1)
323 go func() {
324 w, err := Dial(net, addr, LOG_USER|LOG_ERR, "tag")
325 if err != nil {
326 t.Fatalf("syslog.Dial() failed: %v", err)
328 for i := 0; i < 100; i++ {
329 err := w.Info("test")
330 if err != nil {
331 t.Errorf("Info() failed: %v", err)
332 return
335 wg.Done()
338 wg.Wait()
339 sock.Close()
340 srvWG.Wait()
341 close(done)
343 select {
344 case <-count:
345 case <-time.After(100 * time.Millisecond):
346 t.Error("timeout in concurrent reconnect")