github.com/letsencrypt/boulder@v0.20251208.0/grpc/errors_test.go (about) 1 package grpc 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net" 8 "testing" 9 "time" 10 11 "google.golang.org/grpc" 12 "google.golang.org/grpc/credentials/insecure" 13 14 "github.com/jmhodges/clock" 15 16 berrors "github.com/letsencrypt/boulder/errors" 17 "github.com/letsencrypt/boulder/grpc/test_proto" 18 "github.com/letsencrypt/boulder/identifier" 19 "github.com/letsencrypt/boulder/metrics" 20 "github.com/letsencrypt/boulder/test" 21 ) 22 23 type errorServer struct { 24 test_proto.UnimplementedChillerServer 25 err error 26 } 27 28 func (s *errorServer) Chill(_ context.Context, _ *test_proto.Time) (*test_proto.Time, error) { 29 return nil, s.err 30 } 31 32 func TestErrorWrapping(t *testing.T) { 33 serverMetrics, err := newServerMetrics(metrics.NoopRegisterer) 34 test.AssertNotError(t, err, "creating server metrics") 35 smi := newServerMetadataInterceptor(serverMetrics, clock.NewFake()) 36 clientMetrics, err := newClientMetrics(metrics.NoopRegisterer) 37 test.AssertNotError(t, err, "creating client metrics") 38 cmi := clientMetadataInterceptor{time.Second, clientMetrics, clock.NewFake(), true} 39 srv := grpc.NewServer(grpc.UnaryInterceptor(smi.Unary)) 40 es := &errorServer{} 41 test_proto.RegisterChillerServer(srv, es) 42 lis, err := net.Listen("tcp", "127.0.0.1:") 43 test.AssertNotError(t, err, "Failed to create listener") 44 go func() { _ = srv.Serve(lis) }() 45 defer srv.Stop() 46 47 conn, err := grpc.Dial( 48 lis.Addr().String(), 49 grpc.WithTransportCredentials(insecure.NewCredentials()), 50 grpc.WithUnaryInterceptor(cmi.Unary), 51 ) 52 test.AssertNotError(t, err, "Failed to dial grpc test server") 53 client := test_proto.NewChillerClient(conn) 54 55 // RateLimitError with a RetryAfter of 500ms. 56 expectRetryAfter := time.Millisecond * 500 57 es.err = berrors.RateLimitError(expectRetryAfter, "yup") 58 _, err = client.Chill(context.Background(), &test_proto.Time{}) 59 test.Assert(t, err != nil, fmt.Sprintf("nil error returned, expected: %s", err)) 60 test.AssertDeepEquals(t, err, es.err) 61 var bErr *berrors.BoulderError 62 ok := errors.As(err, &bErr) 63 test.Assert(t, ok, "asserting error as boulder error") 64 // Ensure we got a RateLimitError 65 test.AssertErrorIs(t, bErr, berrors.RateLimit) 66 // Ensure our RetryAfter is still 500ms. 67 test.AssertEquals(t, bErr.RetryAfter, expectRetryAfter) 68 69 test.AssertNil(t, wrapError(context.Background(), nil), "Wrapping nil should still be nil") 70 test.AssertNil(t, unwrapError(nil, nil), "Unwrapping nil should still be nil") 71 } 72 73 // TestSubErrorWrapping tests that a boulder error with suberrors can be 74 // correctly wrapped and unwrapped across the RPC layer. 75 func TestSubErrorWrapping(t *testing.T) { 76 serverMetrics, err := newServerMetrics(metrics.NoopRegisterer) 77 test.AssertNotError(t, err, "creating server metrics") 78 smi := newServerMetadataInterceptor(serverMetrics, clock.NewFake()) 79 clientMetrics, err := newClientMetrics(metrics.NoopRegisterer) 80 test.AssertNotError(t, err, "creating client metrics") 81 cmi := clientMetadataInterceptor{time.Second, clientMetrics, clock.NewFake(), true} 82 srv := grpc.NewServer(grpc.UnaryInterceptor(smi.Unary)) 83 es := &errorServer{} 84 test_proto.RegisterChillerServer(srv, es) 85 lis, err := net.Listen("tcp", "127.0.0.1:") 86 test.AssertNotError(t, err, "Failed to create listener") 87 go func() { _ = srv.Serve(lis) }() 88 defer srv.Stop() 89 90 conn, err := grpc.Dial( 91 lis.Addr().String(), 92 grpc.WithTransportCredentials(insecure.NewCredentials()), 93 grpc.WithUnaryInterceptor(cmi.Unary), 94 ) 95 test.AssertNotError(t, err, "Failed to dial grpc test server") 96 client := test_proto.NewChillerClient(conn) 97 98 subErrors := []berrors.SubBoulderError{ 99 { 100 Identifier: identifier.NewDNS("chillserver.com"), 101 BoulderError: &berrors.BoulderError{ 102 Type: berrors.RejectedIdentifier, 103 Detail: "2 ill 2 chill", 104 }, 105 }, 106 } 107 108 es.err = (&berrors.BoulderError{ 109 Type: berrors.Malformed, 110 Detail: "malformed chill req", 111 }).WithSubErrors(subErrors) 112 113 _, err = client.Chill(context.Background(), &test_proto.Time{}) 114 test.Assert(t, err != nil, fmt.Sprintf("nil error returned, expected: %s", err)) 115 test.AssertDeepEquals(t, err, es.err) 116 }