email_deadline_test.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package email
  2. import (
  3. "net"
  4. "testing"
  5. "time"
  6. )
  7. // A server that accepts the TCP connection but then never speaks must not block
  8. // the sender goroutine indefinitely: sendPlain arms a connection deadline so the
  9. // SMTP greeting read fails instead of hanging until the OS TCP timeout, long
  10. // after the caller's own 30s budget has passed.
  11. func TestSendPlainReturnsOnStalledServer(t *testing.T) {
  12. orig := smtpDeadline
  13. smtpDeadline = 300 * time.Millisecond
  14. t.Cleanup(func() { smtpDeadline = orig })
  15. ln, err := net.Listen("tcp", "127.0.0.1:0")
  16. if err != nil {
  17. t.Fatalf("listen: %v", err)
  18. }
  19. defer ln.Close()
  20. stall := make(chan struct{})
  21. defer close(stall)
  22. go func() {
  23. conn, err := ln.Accept()
  24. if err != nil {
  25. return
  26. }
  27. defer conn.Close()
  28. <-stall
  29. }()
  30. s := &EmailService{}
  31. done := make(chan error, 1)
  32. go func() {
  33. done <- s.sendPlain(ln.Addr().String(), nil, "[email protected]",
  34. []string{"[email protected]"}, []byte("body"), "example.com")
  35. }()
  36. select {
  37. case err := <-done:
  38. if err == nil {
  39. t.Fatal("expected an error from a silent SMTP server, got nil")
  40. }
  41. case <-time.After(3 * time.Second):
  42. t.Fatal("sendPlain did not return on a stalled server within the deadline")
  43. }
  44. }