github.com/openfga/openfga@v1.5.4-rc1/pkg/middleware/recovery/recovery_test.go (about) 1 package recovery 2 3 import ( 4 "context" 5 "net" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9 10 grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" 11 "github.com/stretchr/testify/require" 12 "go.uber.org/goleak" 13 "google.golang.org/grpc" 14 "google.golang.org/grpc/codes" 15 "google.golang.org/grpc/credentials/insecure" 16 "google.golang.org/grpc/status" 17 "google.golang.org/grpc/test/bufconn" 18 19 openfgav1 "github.com/openfga/api/proto/openfga/v1" 20 21 "github.com/openfga/openfga/pkg/logger" 22 ) 23 24 func TestPanic(t *testing.T) { 25 panicHandlerFunc := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 26 panic("Unexpected error!") 27 }) 28 29 handler := HTTPPanicRecoveryHandler(panicHandlerFunc, logger.MustNewLogger("text", "info", "unix")) 30 31 req, err := http.NewRequest(http.MethodGet, "/", nil) 32 require.NoError(t, err) 33 34 resp := httptest.NewRecorder() 35 require.NotPanics(t, func() { 36 handler.ServeHTTP(resp, req) 37 }) 38 39 require.Equal(t, http.StatusInternalServerError, resp.Code) 40 } 41 42 func TestUnaryPanicInterceptor(t *testing.T) { 43 listner := bufconn.Listen(1024 * 1024) 44 t.Cleanup(func() { 45 listner.Close() 46 goleak.VerifyNone(t) 47 }) 48 49 serverOpts := []grpc.ServerOption{ 50 grpc.ChainUnaryInterceptor( 51 []grpc.UnaryServerInterceptor{ 52 grpc_recovery.UnaryServerInterceptor( 53 grpc_recovery.WithRecoveryHandlerContext( 54 PanicRecoveryHandler(logger.MustNewLogger("text", "info", "unix")), 55 ), 56 ), 57 }..., 58 ), 59 } 60 61 srv := grpc.NewServer(serverOpts...) 62 t.Cleanup(srv.Stop) 63 64 openfgav1.RegisterOpenFGAServiceServer(srv, &unimplementedOpenFGAServiceServer{}) 65 66 go func() { 67 err := srv.Serve(listner) 68 if err != nil { 69 t.Fail() 70 } 71 }() 72 73 dialer := func(context.Context, string) (net.Conn, error) { 74 return listner.Dial() 75 } 76 77 ctx, cancel := context.WithCancel(context.Background()) 78 t.Cleanup(cancel) 79 80 opts := []grpc.DialOption{ 81 grpc.WithContextDialer(dialer), 82 grpc.WithTransportCredentials(insecure.NewCredentials())} 83 84 conn, err := grpc.DialContext(ctx, "", opts...) 85 require.NoError(t, err) 86 87 t.Cleanup(func() { 88 conn.Close() 89 }) 90 91 cli := openfgav1.NewOpenFGAServiceClient(conn) 92 93 _, err = cli.Check(ctx, &openfgav1.CheckRequest{}) 94 st, ok := status.FromError(err) 95 require.True(t, ok) 96 97 require.Equal(t, codes.Internal, st.Code()) 98 } 99 100 func TestStreamPanicInterceptor(t *testing.T) { 101 listner := bufconn.Listen(1024 * 1024) 102 t.Cleanup(func() { 103 listner.Close() 104 }) 105 106 serverOpts := []grpc.ServerOption{ 107 grpc.ChainStreamInterceptor( 108 []grpc.StreamServerInterceptor{ 109 grpc_recovery.StreamServerInterceptor( 110 grpc_recovery.WithRecoveryHandlerContext( 111 PanicRecoveryHandler(logger.MustNewLogger("text", "info", "unix")), 112 ), 113 )}..., 114 ), 115 } 116 117 srv := grpc.NewServer(serverOpts...) 118 t.Cleanup(srv.Stop) 119 120 openfgav1.RegisterOpenFGAServiceServer(srv, &unimplementedOpenFGAServiceServer{}) 121 122 go func() { 123 _ = srv.Serve(listner) 124 }() 125 126 dialer := func(context.Context, string) (net.Conn, error) { 127 return listner.Dial() 128 } 129 130 ctx, cancel := context.WithCancel(context.Background()) 131 t.Cleanup(cancel) 132 133 opts := []grpc.DialOption{ 134 grpc.WithContextDialer(dialer), 135 grpc.WithTransportCredentials(insecure.NewCredentials())} 136 137 conn, err := grpc.DialContext(ctx, "", opts...) 138 require.NoError(t, err) 139 140 cli := openfgav1.NewOpenFGAServiceClient(conn) 141 stream, err := cli.StreamedListObjects(ctx, &openfgav1.StreamedListObjectsRequest{}) 142 require.NoError(t, err) 143 144 _, err = stream.Recv() 145 st, ok := status.FromError(err) 146 require.True(t, ok) 147 148 require.Equal(t, codes.Internal, st.Code()) 149 } 150 151 type unimplementedOpenFGAServiceServer struct { 152 openfgav1.UnimplementedOpenFGAServiceServer 153 } 154 155 func (unimplementedOpenFGAServiceServer) Check(context.Context, *openfgav1.CheckRequest) (*openfgav1.CheckResponse, error) { 156 panic("Unexpected error!") 157 } 158 159 func (unimplementedOpenFGAServiceServer) StreamedListObjects(m *openfgav1.StreamedListObjectsRequest, stream openfgav1.OpenFGAService_StreamedListObjectsServer) error { 160 _ = stream.RecvMsg(m) 161 162 panic("Unexpected error!") 163 }