| /* | |
| * | |
| * Copyright 2022 gRPC authors. | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * https://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| * | |
| */ | |
| package test | |
| import ( | |
| "context" | |
| "strings" | |
| "testing" | |
| "google.golang.org/grpc" | |
| "google.golang.org/grpc/codes" | |
| "google.golang.org/grpc/internal/stubserver" | |
| testpb "google.golang.org/grpc/interop/grpc_testing" | |
| "google.golang.org/grpc/status" | |
| ) | |
| // TestInvoke verifies a straightforward invocation of ClientConn.Invoke(). | |
| func (s) TestInvoke(t *testing.T) { | |
| ss := &stubserver.StubServer{ | |
| EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { return &testpb.Empty{}, nil }, | |
| } | |
| if err := ss.Start(nil); err != nil { | |
| t.Fatalf("Failed to start stub server: %v", err) | |
| } | |
| defer ss.Stop() | |
| ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) | |
| defer cancel() | |
| if err := ss.CC.Invoke(ctx, "/grpc.testing.TestService/EmptyCall", &testpb.Empty{}, &testpb.Empty{}); err != nil { | |
| t.Fatalf("grpc.Invoke(\"/grpc.testing.TestService/EmptyCall\") failed: %v", err) | |
| } | |
| } | |
| // TestInvokeLargeErr verifies an invocation of ClientConn.Invoke() where the | |
| // server returns a really large error message. | |
| func (s) TestInvokeLargeErr(t *testing.T) { | |
| largeErrorStr := strings.Repeat("A", 1024*1024) | |
| ss := &stubserver.StubServer{ | |
| EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { | |
| return &testpb.Empty{}, status.Error(codes.Internal, largeErrorStr) | |
| }, | |
| } | |
| if err := ss.Start(nil); err != nil { | |
| t.Fatalf("Failed to start stub server: %v", err) | |
| } | |
| defer ss.Stop() | |
| ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) | |
| defer cancel() | |
| err := ss.CC.Invoke(ctx, "/grpc.testing.TestService/EmptyCall", &testpb.Empty{}, &testpb.Empty{}) | |
| if err == nil { | |
| t.Fatal("grpc.Invoke(\"/grpc.testing.TestService/EmptyCall\") succeeded when expected to fail") | |
| } | |
| st, ok := status.FromError(err) | |
| if !ok { | |
| t.Fatal("grpc.Invoke(\"/grpc.testing.TestService/EmptyCall\") received non-status error") | |
| } | |
| if status.Code(err) != codes.Internal || st.Message() != largeErrorStr { | |
| t.Fatalf("grpc.Invoke(\"/grpc.testing.TestService/EmptyCall\") failed with error: %v, want an error of code %d and desc size %d", err, codes.Internal, len(largeErrorStr)) | |
| } | |
| } | |
| // TestInvokeErrorSpecialChars tests an invocation of ClientConn.Invoke() and | |
| // verifies that error messages don't get mangled. | |
| func (s) TestInvokeErrorSpecialChars(t *testing.T) { | |
| const weirdError = "format verbs: %v%s" | |
| ss := &stubserver.StubServer{ | |
| EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { | |
| return &testpb.Empty{}, status.Error(codes.Internal, weirdError) | |
| }, | |
| } | |
| if err := ss.Start(nil); err != nil { | |
| t.Fatalf("Failed to start stub server: %v", err) | |
| } | |
| defer ss.Stop() | |
| ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) | |
| defer cancel() | |
| err := ss.CC.Invoke(ctx, "/grpc.testing.TestService/EmptyCall", &testpb.Empty{}, &testpb.Empty{}) | |
| if err == nil { | |
| t.Fatal("grpc.Invoke(\"/grpc.testing.TestService/EmptyCall\") succeeded when expected to fail") | |
| } | |
| st, ok := status.FromError(err) | |
| if !ok { | |
| t.Fatal("grpc.Invoke(\"/grpc.testing.TestService/EmptyCall\") received non-status error") | |
| } | |
| if status.Code(err) != codes.Internal || st.Message() != weirdError { | |
| t.Fatalf("grpc.Invoke(\"/grpc.testing.TestService/EmptyCall\") failed with error: %v, want %v", err, weirdError) | |
| } | |
| } | |
| // TestInvokeCancel tests an invocation of ClientConn.Invoke() with a cancelled | |
| // context and verifies that the request is not actually sent to the server. | |
| func (s) TestInvokeCancel(t *testing.T) { | |
| cancelled := 0 | |
| ss := &stubserver.StubServer{ | |
| EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { | |
| cancelled++ | |
| return &testpb.Empty{}, nil | |
| }, | |
| } | |
| if err := ss.Start(nil); err != nil { | |
| t.Fatalf("Failed to start stub server: %v", err) | |
| } | |
| defer ss.Stop() | |
| for i := 0; i < 100; i++ { | |
| ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) | |
| cancel() | |
| ss.CC.Invoke(ctx, "/grpc.testing.TestService/EmptyCall", &testpb.Empty{}, &testpb.Empty{}) | |
| } | |
| if cancelled != 0 { | |
| t.Fatalf("server received %d of 100 cancelled requests", cancelled) | |
| } | |
| } | |
| // TestInvokeCancelClosedNonFail tests an invocation of ClientConn.Invoke() with | |
| // a cancelled non-failfast RPC on a closed ClientConn and verifies that the | |
| // call terminates with an error. | |
| func (s) TestInvokeCancelClosedNonFailFast(t *testing.T) { | |
| ss := &stubserver.StubServer{ | |
| EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { return &testpb.Empty{}, nil }, | |
| } | |
| if err := ss.Start(nil); err != nil { | |
| t.Fatalf("Failed to start stub server: %v", err) | |
| } | |
| defer ss.Stop() | |
| ss.CC.Close() | |
| ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) | |
| cancel() | |
| if err := ss.CC.Invoke(ctx, "/grpc.testing.TestService/EmptyCall", &testpb.Empty{}, &testpb.Empty{}, grpc.WaitForReady(true)); err == nil { | |
| t.Fatal("ClientConn.Invoke() on closed connection succeeded when expected to fail") | |
| } | |
| } |