error_test.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package ldap
  2. import (
  3. "errors"
  4. "net"
  5. "strings"
  6. "testing"
  7. "time"
  8. "gopkg.in/asn1-ber.v1"
  9. )
  10. // TestNilPacket tests that nil packets don't cause a panic.
  11. func TestNilPacket(t *testing.T) {
  12. // Test for nil packet
  13. code, _ := getLDAPResultCode(nil)
  14. if code != ErrorUnexpectedResponse {
  15. t.Errorf("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v", code)
  16. }
  17. // Test for nil result
  18. kids := []*ber.Packet{
  19. {}, // Unused
  20. nil, // Can't be nil
  21. }
  22. pack := &ber.Packet{Children: kids}
  23. code, _ = getLDAPResultCode(pack)
  24. if code != ErrorUnexpectedResponse {
  25. t.Errorf("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v", code)
  26. }
  27. }
  28. // TestConnReadErr tests that an unexpected error reading from underlying
  29. // connection bubbles up to the goroutine which makes a request.
  30. func TestConnReadErr(t *testing.T) {
  31. conn := &signalErrConn{
  32. signals: make(chan error),
  33. }
  34. ldapConn := NewConn(conn, false)
  35. ldapConn.Start()
  36. // Make a dummy search request.
  37. searchReq := NewSearchRequest("dc=example,dc=com", ScopeWholeSubtree, DerefAlways, 0, 0, false, "(objectClass=*)", nil, nil)
  38. expectedError := errors.New("this is the error you are looking for")
  39. // Send the signal after a short amount of time.
  40. time.AfterFunc(10*time.Millisecond, func() { conn.signals <- expectedError })
  41. // This should block until the underlying conn gets the error signal
  42. // which should bubble up through the reader() goroutine, close the
  43. // connection, and
  44. _, err := ldapConn.Search(searchReq)
  45. if err == nil || !strings.Contains(err.Error(), expectedError.Error()) {
  46. t.Errorf("not the expected error: %s", err)
  47. }
  48. }
  49. // signalErrConn is a helpful type used with TestConnReadErr. It implements the
  50. // net.Conn interface to be used as a connection for the test. Most methods are
  51. // no-ops but the Read() method blocks until it receives a signal which it
  52. // returns as an error.
  53. type signalErrConn struct {
  54. signals chan error
  55. }
  56. // Read blocks until an error is sent on the internal signals channel. That
  57. // error is returned.
  58. func (c *signalErrConn) Read(b []byte) (n int, err error) {
  59. return 0, <-c.signals
  60. }
  61. func (c *signalErrConn) Write(b []byte) (n int, err error) {
  62. return len(b), nil
  63. }
  64. func (c *signalErrConn) Close() error {
  65. close(c.signals)
  66. return nil
  67. }
  68. func (c *signalErrConn) LocalAddr() net.Addr {
  69. return (*net.TCPAddr)(nil)
  70. }
  71. func (c *signalErrConn) RemoteAddr() net.Addr {
  72. return (*net.TCPAddr)(nil)
  73. }
  74. func (c *signalErrConn) SetDeadline(t time.Time) error {
  75. return nil
  76. }
  77. func (c *signalErrConn) SetReadDeadline(t time.Time) error {
  78. return nil
  79. }
  80. func (c *signalErrConn) SetWriteDeadline(t time.Time) error {
  81. return nil
  82. }