github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/log/syslog/syslog_test.go (about) 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. 4 5 // +build !windows,!nacl,!plan9 6 7 package syslog 8 9 import ( 10 "bufio" 11 "fmt" 12 "io" 13 "io/ioutil" 14 "log" 15 "net" 16 "os" 17 "runtime" 18 "sync" 19 "testing" 20 "time" 21 ) 22 23 func runPktSyslog(c net.PacketConn, done chan<- string) { 24 var buf [4096]byte 25 var rcvd string 26 ct := 0 27 for { 28 var n int 29 var err error 30 31 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) 32 n, _, err = c.ReadFrom(buf[:]) 33 rcvd += string(buf[:n]) 34 if err != nil { 35 if oe, ok := err.(*net.OpError); ok { 36 if ct < 3 && oe.Temporary() { 37 ct++ 38 continue 39 } 40 } 41 break 42 } 43 } 44 c.Close() 45 done <- rcvd 46 } 47 48 var crashy = false 49 50 func testableNetwork(network string) bool { 51 switch network { 52 case "unix", "unixgram": 53 switch runtime.GOOS { 54 case "darwin": 55 switch runtime.GOARCH { 56 case "arm", "arm64": 57 return false 58 } 59 case "android": 60 return false 61 } 62 } 63 return true 64 } 65 66 func runStreamSyslog(l net.Listener, done chan<- string, wg *sync.WaitGroup) { 67 for { 68 var c net.Conn 69 var err error 70 if c, err = l.Accept(); err != nil { 71 return 72 } 73 wg.Add(1) 74 go func(c net.Conn) { 75 defer wg.Done() 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') 80 if err != nil { 81 break 82 } 83 done <- s 84 } 85 c.Close() 86 }(c) 87 } 88 } 89 90 func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, wg *sync.WaitGroup) { 91 if n == "udp" || n == "tcp" { 92 la = "127.0.0.1:0" 93 } else { 94 // unix and unixgram: choose an address if none given 95 if la == "" { 96 // use ioutil.TempFile to get a name that is unique 97 f, err := ioutil.TempFile("", "syslogtest") 98 if err != nil { 99 log.Fatal("TempFile: ", err) 100 } 101 f.Close() 102 la = f.Name() 103 } 104 os.Remove(la) 105 } 106 107 wg = new(sync.WaitGroup) 108 if n == "udp" || n == "unixgram" { 109 l, e := net.ListenPacket(n, la) 110 if e != nil { 111 log.Fatalf("startServer failed: %v", e) 112 } 113 addr = l.LocalAddr().String() 114 sock = l 115 wg.Add(1) 116 go func() { 117 defer wg.Done() 118 runPktSyslog(l, done) 119 }() 120 } else { 121 l, e := net.Listen(n, la) 122 if e != nil { 123 log.Fatalf("startServer failed: %v", e) 124 } 125 addr = l.Addr().String() 126 sock = l 127 wg.Add(1) 128 go func() { 129 defer wg.Done() 130 runStreamSyslog(l, done, wg) 131 }() 132 } 133 return 134 } 135 136 func TestWithSimulated(t *testing.T) { 137 msg := "Test 123" 138 var transport []string 139 for _, n := range []string{"unix", "unixgram", "udp", "tcp"} { 140 if testableNetwork(n) { 141 transport = append(transport, n) 142 } 143 } 144 145 for _, tr := range transport { 146 done := make(chan string) 147 addr, sock, srvWG := startServer(tr, "", done) 148 defer srvWG.Wait() 149 defer sock.Close() 150 if tr == "unix" || tr == "unixgram" { 151 defer os.Remove(addr) 152 } 153 s, err := Dial(tr, addr, LOG_INFO|LOG_USER, "syslog_test") 154 if err != nil { 155 t.Fatalf("Dial() failed: %v", err) 156 } 157 err = s.Info(msg) 158 if err != nil { 159 t.Fatalf("log failed: %v", err) 160 } 161 check(t, msg, <-done) 162 s.Close() 163 } 164 } 165 166 func TestFlap(t *testing.T) { 167 net := "unix" 168 if !testableNetwork(net) { 169 t.Skipf("skipping on %s/%s; 'unix' is not supported", runtime.GOOS, runtime.GOARCH) 170 } 171 172 done := make(chan string) 173 addr, sock, srvWG := startServer(net, "", done) 174 defer srvWG.Wait() 175 defer os.Remove(addr) 176 defer sock.Close() 177 178 s, err := Dial(net, addr, LOG_INFO|LOG_USER, "syslog_test") 179 if err != nil { 180 t.Fatalf("Dial() failed: %v", err) 181 } 182 msg := "Moo 2" 183 err = s.Info(msg) 184 if err != nil { 185 t.Fatalf("log failed: %v", err) 186 } 187 check(t, msg, <-done) 188 189 // restart the server 190 _, sock2, srvWG2 := startServer(net, addr, done) 191 defer srvWG2.Wait() 192 defer sock2.Close() 193 194 // and try retransmitting 195 msg = "Moo 3" 196 err = s.Info(msg) 197 if err != nil { 198 t.Fatalf("log failed: %v", err) 199 } 200 check(t, msg, <-done) 201 202 s.Close() 203 } 204 205 func TestNew(t *testing.T) { 206 if LOG_LOCAL7 != 23<<3 { 207 t.Fatalf("LOG_LOCAL7 has wrong value") 208 } 209 if testing.Short() { 210 // Depends on syslog daemon running, and sometimes it's not. 211 t.Skip("skipping syslog test during -short") 212 } 213 214 s, err := New(LOG_INFO|LOG_USER, "the_tag") 215 if err != nil { 216 t.Fatalf("New() failed: %s", err) 217 } 218 // Don't send any messages. 219 s.Close() 220 } 221 222 func TestNewLogger(t *testing.T) { 223 if testing.Short() { 224 t.Skip("skipping syslog test during -short") 225 } 226 f, err := NewLogger(LOG_USER|LOG_INFO, 0) 227 if f == nil { 228 t.Error(err) 229 } 230 } 231 232 func TestDial(t *testing.T) { 233 if testing.Short() { 234 t.Skip("skipping syslog test during -short") 235 } 236 f, err := Dial("", "", (LOG_LOCAL7|LOG_DEBUG)+1, "syslog_test") 237 if f != nil { 238 t.Fatalf("Should have trapped bad priority") 239 } 240 f, err = Dial("", "", -1, "syslog_test") 241 if f != nil { 242 t.Fatalf("Should have trapped bad priority") 243 } 244 l, err := Dial("", "", LOG_USER|LOG_ERR, "syslog_test") 245 if err != nil { 246 t.Fatalf("Dial() failed: %s", err) 247 } 248 l.Close() 249 } 250 251 func check(t *testing.T, in, out string) { 252 tmpl := fmt.Sprintf("<%d>%%s %%s syslog_test[%%d]: %s\n", LOG_USER+LOG_INFO, in) 253 if hostname, err := os.Hostname(); err != nil { 254 t.Error("Error retrieving hostname") 255 } else { 256 var parsedHostname, timestamp string 257 var pid int 258 if n, err := fmt.Sscanf(out, tmpl, ×tamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname { 259 t.Errorf("Got %q, does not match template %q (%d %s)", out, tmpl, n, err) 260 } 261 } 262 } 263 264 func TestWrite(t *testing.T) { 265 tests := []struct { 266 pri Priority 267 pre string 268 msg string 269 exp string 270 }{ 271 {LOG_USER | LOG_ERR, "syslog_test", "", "%s %s syslog_test[%d]: \n"}, 272 {LOG_USER | LOG_ERR, "syslog_test", "write test", "%s %s syslog_test[%d]: write test\n"}, 273 // Write should not add \n if there already is one 274 {LOG_USER | LOG_ERR, "syslog_test", "write test 2\n", "%s %s syslog_test[%d]: write test 2\n"}, 275 } 276 277 if hostname, err := os.Hostname(); err != nil { 278 t.Fatalf("Error retrieving hostname") 279 } else { 280 for _, test := range tests { 281 done := make(chan string) 282 addr, sock, srvWG := startServer("udp", "", done) 283 defer srvWG.Wait() 284 defer sock.Close() 285 l, err := Dial("udp", addr, test.pri, test.pre) 286 if err != nil { 287 t.Fatalf("syslog.Dial() failed: %v", err) 288 } 289 defer l.Close() 290 _, err = io.WriteString(l, test.msg) 291 if err != nil { 292 t.Fatalf("WriteString() failed: %v", err) 293 } 294 rcvd := <-done 295 test.exp = fmt.Sprintf("<%d>", test.pri) + test.exp 296 var parsedHostname, timestamp string 297 var pid int 298 if n, err := fmt.Sscanf(rcvd, test.exp, ×tamp, &parsedHostname, &pid); n != 3 || err != nil || hostname != parsedHostname { 299 t.Errorf("s.Info() = '%q', didn't match '%q' (%d %s)", rcvd, test.exp, n, err) 300 } 301 } 302 } 303 } 304 305 func TestConcurrentWrite(t *testing.T) { 306 addr, sock, srvWG := startServer("udp", "", make(chan string, 1)) 307 defer srvWG.Wait() 308 defer sock.Close() 309 w, err := Dial("udp", addr, LOG_USER|LOG_ERR, "how's it going?") 310 if err != nil { 311 t.Fatalf("syslog.Dial() failed: %v", err) 312 } 313 var wg sync.WaitGroup 314 for i := 0; i < 10; i++ { 315 wg.Add(1) 316 go func() { 317 defer wg.Done() 318 err := w.Info("test") 319 if err != nil { 320 t.Errorf("Info() failed: %v", err) 321 return 322 } 323 }() 324 } 325 wg.Wait() 326 } 327 328 func TestConcurrentReconnect(t *testing.T) { 329 crashy = true 330 defer func() { crashy = false }() 331 332 const N = 10 333 const M = 100 334 net := "unix" 335 if !testableNetwork(net) { 336 net = "tcp" 337 if !testableNetwork(net) { 338 t.Skipf("skipping on %s/%s; neither 'unix' or 'tcp' is supported", runtime.GOOS, runtime.GOARCH) 339 } 340 } 341 done := make(chan string, N*M) 342 addr, sock, srvWG := startServer(net, "", done) 343 if net == "unix" { 344 defer os.Remove(addr) 345 } 346 347 // count all the messages arriving 348 count := make(chan int) 349 go func() { 350 ct := 0 351 for range done { 352 ct++ 353 // we are looking for 500 out of 1000 events 354 // here because lots of log messages are lost 355 // in buffers (kernel and/or bufio) 356 if ct > N*M/2 { 357 break 358 } 359 } 360 count <- ct 361 }() 362 363 var wg sync.WaitGroup 364 wg.Add(N) 365 for i := 0; i < N; i++ { 366 go func() { 367 defer wg.Done() 368 w, err := Dial(net, addr, LOG_USER|LOG_ERR, "tag") 369 if err != nil { 370 t.Fatalf("syslog.Dial() failed: %v", err) 371 } 372 defer w.Close() 373 for i := 0; i < M; i++ { 374 err := w.Info("test") 375 if err != nil { 376 t.Errorf("Info() failed: %v", err) 377 return 378 } 379 } 380 }() 381 } 382 wg.Wait() 383 sock.Close() 384 srvWG.Wait() 385 close(done) 386 387 select { 388 case <-count: 389 case <-time.After(100 * time.Millisecond): 390 t.Error("timeout in concurrent reconnect") 391 } 392 }