xref: /aosp_15_r20/external/grpc-grpc/test/cpp/interop/istio_echo_server_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 // Copyright 2022 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include <memory>
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include "absl/strings/str_cat.h"
23 #include "absl/strings/str_format.h"
24 
25 #include <grpcpp/create_channel.h>
26 #include <grpcpp/security/credentials.h>
27 #include <grpcpp/server_builder.h>
28 #include <grpcpp/support/status.h>
29 
30 #include "src/core/lib/gprpp/crash.h"
31 #include "src/core/lib/gprpp/host_port.h"
32 #include "test/core/util/port.h"
33 #include "test/core/util/test_config.h"
34 #include "test/cpp/interop/istio_echo_server_lib.h"
35 
36 namespace grpc {
37 namespace testing {
38 namespace {
39 
40 using proto::EchoRequest;
41 using proto::EchoResponse;
42 using proto::EchoTestService;
43 using proto::ForwardEchoRequest;
44 using proto::ForwardEchoResponse;
45 
46 // A very simple EchoTestService implementation that just echoes back the
47 // message without handling any other expectations for ForwardEcho.
48 class SimpleEchoTestServerImpl : public proto::EchoTestService::Service {
49  public:
SimpleEchoTestServerImpl()50   explicit SimpleEchoTestServerImpl() {}
51 
Echo(grpc::ServerContext *,const proto::EchoRequest *,proto::EchoResponse *)52   grpc::Status Echo(grpc::ServerContext* /* context */,
53                     const proto::EchoRequest* /* request */,
54                     proto::EchoResponse* /* response */) override {
55     grpc_core::Crash("unreachable");
56     return Status(StatusCode::INVALID_ARGUMENT, "Unexpected");
57   }
58 
ForwardEcho(grpc::ServerContext *,const proto::ForwardEchoRequest * request,proto::ForwardEchoResponse * response)59   grpc::Status ForwardEcho(grpc::ServerContext* /*context*/,
60                            const proto::ForwardEchoRequest* request,
61                            proto::ForwardEchoResponse* response) override {
62     if (fail_rpc_) {
63       return Status(StatusCode::UNAVAILABLE, "fail rpc");
64     }
65     response->add_output(request->message());
66     return Status::OK;
67   }
68 
set_fail_rpc(bool fail_rpc)69   void set_fail_rpc(bool fail_rpc) { fail_rpc_ = fail_rpc; }
70 
71  private:
72   std::string hostname_;
73   std::string forwarding_address_;
74   std::atomic<bool> fail_rpc_{false};
75   // The following fields are not set yet. But we may need them later.
76   //  int port_;
77   //  std::string version_;
78   //  std::string cluster_;
79   //  std::string istio_version_;
80 };
81 
82 class EchoTest : public ::testing::Test {
83  protected:
EchoTest()84   EchoTest() {
85     // Start the simple server which will handle protocols that
86     // EchoTestServiceImpl does not handle.
87     int forwarding_port = grpc_pick_unused_port_or_die();
88     forwarding_address_ = grpc_core::JoinHostPort("localhost", forwarding_port);
89     ServerBuilder simple_builder;
90     simple_builder.RegisterService(&simple_test_service_impl_);
91     simple_builder.AddListeningPort(forwarding_address_,
92                                     InsecureServerCredentials());
93     simple_server_ = simple_builder.BuildAndStart();
94     // Start the EchoTestServiceImpl server
95     ServerBuilder builder;
96     echo_test_service_impl_ = std::make_unique<EchoTestServiceImpl>(
97         "hostname", "v1", forwarding_address_);
98     builder.RegisterService(echo_test_service_impl_.get());
99     int port = grpc_pick_unused_port_or_die();
100     server_address_ = grpc_core::JoinHostPort("localhost", port);
101     builder.AddListeningPort(server_address_, InsecureServerCredentials());
102     server_ = builder.BuildAndStart();
103 
104     auto channel = CreateChannel(server_address_, InsecureChannelCredentials());
105     stub_ = EchoTestService::NewStub(channel);
106   }
107 
108   std::string forwarding_address_;
109   SimpleEchoTestServerImpl simple_test_service_impl_;
110   std::unique_ptr<EchoTestServiceImpl> echo_test_service_impl_;
111   std::string server_address_;
112   std::unique_ptr<Server> server_;
113   std::unique_ptr<Server> simple_server_;
114   std::unique_ptr<EchoTestService::Stub> stub_;
115 };
116 
TEST_F(EchoTest,SimpleEchoTest)117 TEST_F(EchoTest, SimpleEchoTest) {
118   ClientContext context;
119   EchoRequest request;
120   EchoResponse response;
121   request.set_message("hello");
122   auto status = stub_->Echo(&context, request, &response);
123   ASSERT_TRUE(status.ok());
124   EXPECT_THAT(response.message(),
125               ::testing::AllOf(::testing::HasSubstr("StatusCode=200\n"),
126                                ::testing::HasSubstr("Hostname=hostname\n"),
127                                ::testing::HasSubstr("Echo=hello\n"),
128                                ::testing::HasSubstr("Host="),
129                                ::testing::HasSubstr("IP="),
130                                ::testing::HasSubstr("ServiceVersion=v1")));
131 }
132 
TEST_F(EchoTest,ForwardEchoTest)133 TEST_F(EchoTest, ForwardEchoTest) {
134   ClientContext context;
135   ForwardEchoRequest request;
136   ForwardEchoResponse response;
137   request.set_count(3);
138   request.set_qps(1);
139   request.set_timeout_micros(20 * 1000 * 1000);  // 20 seconds
140   request.set_url(absl::StrCat("grpc://", server_address_));
141   request.set_message("hello");
142   auto status = stub_->ForwardEcho(&context, request, &response);
143   ASSERT_TRUE(status.ok());
144   for (int i = 0; i < 3; ++i) {
145     EXPECT_THAT(
146         response.output()[i],
147         ::testing::AllOf(
148             ::testing::HasSubstr(
149                 absl::StrFormat("[%d body] StatusCode=200\n", i)),
150             ::testing::HasSubstr(
151                 absl::StrFormat("[%d body] Hostname=hostname\n", i)),
152             ::testing::HasSubstr(absl::StrFormat("[%d body] Echo=hello\n", i)),
153             ::testing::HasSubstr(absl::StrFormat("[%d body] Host=", i)),
154             ::testing::HasSubstr(
155                 absl::StrFormat("[%d body] ServiceVersion=v1", i))));
156   }
157 }
158 
TEST_F(EchoTest,ForwardEchoTestUnhandledProtocols)159 TEST_F(EchoTest, ForwardEchoTestUnhandledProtocols) {
160   ClientContext context;
161   ForwardEchoRequest request;
162   ForwardEchoResponse response;
163   request.set_count(3);
164   request.set_qps(1);
165   request.set_timeout_micros(20 * 1000 * 1000);  // 20 seconds
166   // http protocol is unhandled by EchoTestServiceImpl and should be forwarded
167   // to SimpleEchoTestServiceImpl
168   request.set_url(absl::StrCat("http://", server_address_));
169   request.set_message("hello");
170   auto status = stub_->ForwardEcho(&context, request, &response);
171   ASSERT_TRUE(status.ok()) << "Code = " << status.error_code()
172                            << " Message = " << status.error_message();
173   ASSERT_FALSE(response.output().empty());
174   EXPECT_EQ(response.output()[0], "hello");
175 }
176 
TEST_F(EchoTest,ForwardEchoFailure)177 TEST_F(EchoTest, ForwardEchoFailure) {
178   simple_test_service_impl_.set_fail_rpc(true);
179   ClientContext context;
180   ForwardEchoRequest request;
181   ForwardEchoResponse response;
182   request.set_count(3);
183   request.set_qps(1);
184   request.set_timeout_micros(20 * 1000 * 1000);  // 20 seconds
185   // Use the unhandled protocol to make sure that we forward the request to
186   // SimpleEchoTestServerImpl.
187   request.set_url(absl::StrCat("http://", server_address_));
188   request.set_message("hello");
189   auto status = stub_->ForwardEcho(&context, request, &response);
190   ASSERT_EQ(status.error_code(), StatusCode::UNAVAILABLE);
191 }
192 
193 }  // namespace
194 }  // namespace testing
195 }  // namespace grpc
196 
main(int argc,char ** argv)197 int main(int argc, char** argv) {
198   ::testing::InitGoogleTest(&argc, argv);
199   grpc::testing::TestEnvironment env(&argc, argv);
200   grpc_init();
201   auto result = RUN_ALL_TESTS();
202   grpc_shutdown();
203   return result;
204 }
205