github.com/mikelsr/quic-go@v0.36.1-0.20230701132136-1d9415b66898/internal/qerr/errors_test.go (about)

     1  package qerr
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  
     7  	"github.com/mikelsr/quic-go/internal/protocol"
     8  
     9  	. "github.com/onsi/ginkgo/v2"
    10  	. "github.com/onsi/gomega"
    11  )
    12  
    13  var _ = Describe("QUIC Errors", func() {
    14  	Context("Transport Errors", func() {
    15  		It("has a string representation", func() {
    16  			Expect((&TransportError{
    17  				ErrorCode:    FlowControlError,
    18  				ErrorMessage: "foobar",
    19  			}).Error()).To(Equal("FLOW_CONTROL_ERROR (local): foobar"))
    20  		})
    21  
    22  		It("has a string representation for empty error phrases", func() {
    23  			Expect((&TransportError{ErrorCode: FlowControlError}).Error()).To(Equal("FLOW_CONTROL_ERROR (local)"))
    24  		})
    25  
    26  		It("includes the frame type, for errors without a message", func() {
    27  			Expect((&TransportError{
    28  				Remote:    true,
    29  				ErrorCode: FlowControlError,
    30  				FrameType: 0x1337,
    31  			}).Error()).To(Equal("FLOW_CONTROL_ERROR (remote) (frame type: 0x1337)"))
    32  		})
    33  
    34  		It("includes the frame type, for errors with a message", func() {
    35  			Expect((&TransportError{
    36  				ErrorCode:    FlowControlError,
    37  				FrameType:    0x1337,
    38  				ErrorMessage: "foobar",
    39  			}).Error()).To(Equal("FLOW_CONTROL_ERROR (local) (frame type: 0x1337): foobar"))
    40  		})
    41  
    42  		Context("crypto errors", func() {
    43  			It("has a string representation for errors with a message", func() {
    44  				err := NewLocalCryptoError(0x42, "foobar")
    45  				Expect(err.Error()).To(Equal("CRYPTO_ERROR 0x142 (local): foobar"))
    46  			})
    47  
    48  			It("has a string representation for errors without a message", func() {
    49  				err := NewLocalCryptoError(0x2a, "")
    50  				Expect(err.Error()).To(Equal("CRYPTO_ERROR 0x12a (local): tls: bad certificate"))
    51  			})
    52  		})
    53  	})
    54  
    55  	Context("Application Errors", func() {
    56  		It("has a string representation for errors with a message", func() {
    57  			Expect((&ApplicationError{
    58  				ErrorCode:    0x42,
    59  				ErrorMessage: "foobar",
    60  			}).Error()).To(Equal("Application error 0x42 (local): foobar"))
    61  		})
    62  
    63  		It("has a string representation for errors without a message", func() {
    64  			Expect((&ApplicationError{
    65  				ErrorCode: 0x42,
    66  				Remote:    true,
    67  			}).Error()).To(Equal("Application error 0x42 (remote)"))
    68  		})
    69  	})
    70  
    71  	Context("timeout errors", func() {
    72  		It("handshake timeouts", func() {
    73  			//nolint:gosimple // we need to assign to an interface here
    74  			var err error
    75  			err = &HandshakeTimeoutError{}
    76  			nerr, ok := err.(net.Error)
    77  			Expect(ok).To(BeTrue())
    78  			Expect(nerr.Timeout()).To(BeTrue())
    79  			Expect(err.Error()).To(Equal("timeout: handshake did not complete in time"))
    80  		})
    81  
    82  		It("idle timeouts", func() {
    83  			//nolint:gosimple // we need to assign to an interface here
    84  			var err error
    85  			err = &IdleTimeoutError{}
    86  			nerr, ok := err.(net.Error)
    87  			Expect(ok).To(BeTrue())
    88  			Expect(nerr.Timeout()).To(BeTrue())
    89  			Expect(err.Error()).To(Equal("timeout: no recent network activity"))
    90  		})
    91  	})
    92  
    93  	Context("Version Negotiation errors", func() {
    94  		It("has a string representation", func() {
    95  			Expect((&VersionNegotiationError{
    96  				Ours:   []protocol.VersionNumber{2, 3},
    97  				Theirs: []protocol.VersionNumber{4, 5, 6},
    98  			}).Error()).To(Equal("no compatible QUIC version found (we support [0x2 0x3], server offered [0x4 0x5 0x6])"))
    99  		})
   100  	})
   101  
   102  	Context("Stateless Reset errors", func() {
   103  		token := protocol.StatelessResetToken{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}
   104  
   105  		It("has a string representation", func() {
   106  			Expect((&StatelessResetError{Token: token}).Error()).To(Equal("received a stateless reset with token 000102030405060708090a0b0c0d0e0f"))
   107  		})
   108  
   109  		It("is a net.Error", func() {
   110  			//nolint:gosimple // we need to assign to an interface here
   111  			var err error
   112  			err = &StatelessResetError{}
   113  			nerr, ok := err.(net.Error)
   114  			Expect(ok).To(BeTrue())
   115  			Expect(nerr.Timeout()).To(BeFalse())
   116  		})
   117  	})
   118  
   119  	It("says that errors are net.ErrClosed errors", func() {
   120  		Expect(errors.Is(&TransportError{}, net.ErrClosed)).To(BeTrue())
   121  		Expect(errors.Is(&ApplicationError{}, net.ErrClosed)).To(BeTrue())
   122  		Expect(errors.Is(&IdleTimeoutError{}, net.ErrClosed)).To(BeTrue())
   123  		Expect(errors.Is(&HandshakeTimeoutError{}, net.ErrClosed)).To(BeTrue())
   124  		Expect(errors.Is(&StatelessResetError{}, net.ErrClosed)).To(BeTrue())
   125  		Expect(errors.Is(&VersionNegotiationError{}, net.ErrClosed)).To(BeTrue())
   126  	})
   127  })