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