117 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
| package grpc
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"net"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	"google.golang.org/grpc"
 | |
| 	"google.golang.org/grpc/credentials/insecure"
 | |
| 
 | |
| 	"github.com/jmhodges/clock"
 | |
| 
 | |
| 	berrors "github.com/letsencrypt/boulder/errors"
 | |
| 	"github.com/letsencrypt/boulder/grpc/test_proto"
 | |
| 	"github.com/letsencrypt/boulder/identifier"
 | |
| 	"github.com/letsencrypt/boulder/metrics"
 | |
| 	"github.com/letsencrypt/boulder/test"
 | |
| )
 | |
| 
 | |
| type errorServer struct {
 | |
| 	test_proto.UnimplementedChillerServer
 | |
| 	err error
 | |
| }
 | |
| 
 | |
| func (s *errorServer) Chill(_ context.Context, _ *test_proto.Time) (*test_proto.Time, error) {
 | |
| 	return nil, s.err
 | |
| }
 | |
| 
 | |
| func TestErrorWrapping(t *testing.T) {
 | |
| 	serverMetrics, err := newServerMetrics(metrics.NoopRegisterer)
 | |
| 	test.AssertNotError(t, err, "creating server metrics")
 | |
| 	smi := newServerMetadataInterceptor(serverMetrics, clock.NewFake())
 | |
| 	clientMetrics, err := newClientMetrics(metrics.NoopRegisterer)
 | |
| 	test.AssertNotError(t, err, "creating client metrics")
 | |
| 	cmi := clientMetadataInterceptor{time.Second, clientMetrics, clock.NewFake(), true}
 | |
| 	srv := grpc.NewServer(grpc.UnaryInterceptor(smi.Unary))
 | |
| 	es := &errorServer{}
 | |
| 	test_proto.RegisterChillerServer(srv, es)
 | |
| 	lis, err := net.Listen("tcp", "127.0.0.1:")
 | |
| 	test.AssertNotError(t, err, "Failed to create listener")
 | |
| 	go func() { _ = srv.Serve(lis) }()
 | |
| 	defer srv.Stop()
 | |
| 
 | |
| 	conn, err := grpc.Dial(
 | |
| 		lis.Addr().String(),
 | |
| 		grpc.WithTransportCredentials(insecure.NewCredentials()),
 | |
| 		grpc.WithUnaryInterceptor(cmi.Unary),
 | |
| 	)
 | |
| 	test.AssertNotError(t, err, "Failed to dial grpc test server")
 | |
| 	client := test_proto.NewChillerClient(conn)
 | |
| 
 | |
| 	// RateLimitError with a RetryAfter of 500ms.
 | |
| 	expectRetryAfter := time.Millisecond * 500
 | |
| 	es.err = berrors.RateLimitError(expectRetryAfter, "yup")
 | |
| 	_, err = client.Chill(context.Background(), &test_proto.Time{})
 | |
| 	test.Assert(t, err != nil, fmt.Sprintf("nil error returned, expected: %s", err))
 | |
| 	test.AssertDeepEquals(t, err, es.err)
 | |
| 	var bErr *berrors.BoulderError
 | |
| 	ok := errors.As(err, &bErr)
 | |
| 	test.Assert(t, ok, "asserting error as boulder error")
 | |
| 	// Ensure we got a RateLimitError
 | |
| 	test.AssertErrorIs(t, bErr, berrors.RateLimit)
 | |
| 	// Ensure our RetryAfter is still 500ms.
 | |
| 	test.AssertEquals(t, bErr.RetryAfter, expectRetryAfter)
 | |
| 
 | |
| 	test.AssertNil(t, wrapError(context.Background(), nil), "Wrapping nil should still be nil")
 | |
| 	test.AssertNil(t, unwrapError(nil, nil), "Unwrapping nil should still be nil")
 | |
| }
 | |
| 
 | |
| // TestSubErrorWrapping tests that a boulder error with suberrors can be
 | |
| // correctly wrapped and unwrapped across the RPC layer.
 | |
| func TestSubErrorWrapping(t *testing.T) {
 | |
| 	serverMetrics, err := newServerMetrics(metrics.NoopRegisterer)
 | |
| 	test.AssertNotError(t, err, "creating server metrics")
 | |
| 	smi := newServerMetadataInterceptor(serverMetrics, clock.NewFake())
 | |
| 	clientMetrics, err := newClientMetrics(metrics.NoopRegisterer)
 | |
| 	test.AssertNotError(t, err, "creating client metrics")
 | |
| 	cmi := clientMetadataInterceptor{time.Second, clientMetrics, clock.NewFake(), true}
 | |
| 	srv := grpc.NewServer(grpc.UnaryInterceptor(smi.Unary))
 | |
| 	es := &errorServer{}
 | |
| 	test_proto.RegisterChillerServer(srv, es)
 | |
| 	lis, err := net.Listen("tcp", "127.0.0.1:")
 | |
| 	test.AssertNotError(t, err, "Failed to create listener")
 | |
| 	go func() { _ = srv.Serve(lis) }()
 | |
| 	defer srv.Stop()
 | |
| 
 | |
| 	conn, err := grpc.Dial(
 | |
| 		lis.Addr().String(),
 | |
| 		grpc.WithTransportCredentials(insecure.NewCredentials()),
 | |
| 		grpc.WithUnaryInterceptor(cmi.Unary),
 | |
| 	)
 | |
| 	test.AssertNotError(t, err, "Failed to dial grpc test server")
 | |
| 	client := test_proto.NewChillerClient(conn)
 | |
| 
 | |
| 	subErrors := []berrors.SubBoulderError{
 | |
| 		{
 | |
| 			Identifier: identifier.NewDNS("chillserver.com"),
 | |
| 			BoulderError: &berrors.BoulderError{
 | |
| 				Type:   berrors.RejectedIdentifier,
 | |
| 				Detail: "2 ill 2 chill",
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	es.err = (&berrors.BoulderError{
 | |
| 		Type:   berrors.Malformed,
 | |
| 		Detail: "malformed chill req",
 | |
| 	}).WithSubErrors(subErrors)
 | |
| 
 | |
| 	_, err = client.Chill(context.Background(), &test_proto.Time{})
 | |
| 	test.Assert(t, err != nil, fmt.Sprintf("nil error returned, expected: %s", err))
 | |
| 	test.AssertDeepEquals(t, err, es.err)
 | |
| }
 |