xref: /aosp_15_r20/external/grpc-grpc/test/cpp/end2end/server_builder_plugin_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2016 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include <thread>
20 
21 #include <gtest/gtest.h>
22 
23 #include "absl/memory/memory.h"
24 
25 #include <grpc/grpc.h>
26 #include <grpcpp/channel.h>
27 #include <grpcpp/client_context.h>
28 #include <grpcpp/create_channel.h>
29 #include <grpcpp/impl/server_builder_option.h>
30 #include <grpcpp/impl/server_builder_plugin.h>
31 #include <grpcpp/impl/server_initializer.h>
32 #include <grpcpp/security/credentials.h>
33 #include <grpcpp/security/server_credentials.h>
34 #include <grpcpp/server.h>
35 #include <grpcpp/server_builder.h>
36 #include <grpcpp/server_context.h>
37 
38 #include "src/proto/grpc/testing/echo.grpc.pb.h"
39 #include "test/core/util/port.h"
40 #include "test/core/util/test_config.h"
41 #include "test/cpp/end2end/test_service_impl.h"
42 
43 #define PLUGIN_NAME "TestServerBuilderPlugin"
44 
45 namespace grpc {
46 namespace testing {
47 
48 class TestServerBuilderPlugin : public ServerBuilderPlugin {
49  public:
TestServerBuilderPlugin()50   TestServerBuilderPlugin() : service_(new TestServiceImpl()) {
51     init_server_is_called_ = false;
52     finish_is_called_ = false;
53     change_arguments_is_called_ = false;
54     register_service_ = false;
55   }
56 
name()57   std::string name() override { return PLUGIN_NAME; }
58 
InitServer(ServerInitializer * si)59   void InitServer(ServerInitializer* si) override {
60     init_server_is_called_ = true;
61     if (register_service_) {
62       si->RegisterService(service_);
63     }
64   }
65 
Finish(ServerInitializer *)66   void Finish(ServerInitializer* /*si*/) override { finish_is_called_ = true; }
67 
ChangeArguments(const std::string &,void *)68   void ChangeArguments(const std::string& /*name*/, void* /*value*/) override {
69     change_arguments_is_called_ = true;
70   }
71 
has_async_methods() const72   bool has_async_methods() const override {
73     if (register_service_) {
74       return service_->has_async_methods();
75     }
76     return false;
77   }
78 
has_sync_methods() const79   bool has_sync_methods() const override {
80     if (register_service_) {
81       return service_->has_synchronous_methods();
82     }
83     return false;
84   }
85 
SetRegisterService()86   void SetRegisterService() { register_service_ = true; }
87 
init_server_is_called()88   bool init_server_is_called() { return init_server_is_called_; }
finish_is_called()89   bool finish_is_called() { return finish_is_called_; }
change_arguments_is_called()90   bool change_arguments_is_called() { return change_arguments_is_called_; }
91 
92  private:
93   bool init_server_is_called_;
94   bool finish_is_called_;
95   bool change_arguments_is_called_;
96   bool register_service_;
97   std::shared_ptr<TestServiceImpl> service_;
98 };
99 
100 class InsertPluginServerBuilderOption : public ServerBuilderOption {
101  public:
InsertPluginServerBuilderOption()102   InsertPluginServerBuilderOption() { register_service_ = false; }
103 
UpdateArguments(ChannelArguments *)104   void UpdateArguments(ChannelArguments* /*arg*/) override {}
105 
UpdatePlugins(std::vector<std::unique_ptr<ServerBuilderPlugin>> * plugins)106   void UpdatePlugins(
107       std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) override {
108     plugins->clear();
109 
110     std::unique_ptr<TestServerBuilderPlugin> plugin(
111         new TestServerBuilderPlugin());
112     if (register_service_) plugin->SetRegisterService();
113     plugins->emplace_back(std::move(plugin));
114   }
115 
SetRegisterService()116   void SetRegisterService() { register_service_ = true; }
117 
118  private:
119   bool register_service_;
120 };
121 
CreateTestServerBuilderPlugin()122 std::unique_ptr<ServerBuilderPlugin> CreateTestServerBuilderPlugin() {
123   return std::unique_ptr<ServerBuilderPlugin>(new TestServerBuilderPlugin());
124 }
125 
126 // Force AddServerBuilderPlugin() to be called at static initialization time.
127 struct StaticTestPluginInitializer {
StaticTestPluginInitializergrpc::testing::StaticTestPluginInitializer128   StaticTestPluginInitializer() {
129     grpc::ServerBuilder::InternalAddPluginFactory(
130         &CreateTestServerBuilderPlugin);
131   }
132 } static_plugin_initializer_test_;
133 
134 // When the param boolean is true, the ServerBuilder plugin will be added at the
135 // time of static initialization. When it's false, the ServerBuilder plugin will
136 // be added using ServerBuilder::SetOption().
137 class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
138  public:
ServerBuilderPluginTest()139   ServerBuilderPluginTest() {}
140 
SetUp()141   void SetUp() override {
142     port_ = grpc_pick_unused_port_or_die();
143     builder_ = std::make_unique<ServerBuilder>();
144   }
145 
InsertPlugin()146   void InsertPlugin() {
147     if (GetParam()) {
148       // Add ServerBuilder plugin in static initialization
149       CheckPresent();
150     } else {
151       // Add ServerBuilder plugin using ServerBuilder::SetOption()
152       builder_->SetOption(std::unique_ptr<ServerBuilderOption>(
153           new InsertPluginServerBuilderOption()));
154     }
155   }
156 
InsertPluginWithTestService()157   void InsertPluginWithTestService() {
158     if (GetParam()) {
159       // Add ServerBuilder plugin in static initialization
160       auto plugin = CheckPresent();
161       EXPECT_TRUE(plugin);
162       plugin->SetRegisterService();
163     } else {
164       // Add ServerBuilder plugin using ServerBuilder::SetOption()
165       std::unique_ptr<InsertPluginServerBuilderOption> option(
166           new InsertPluginServerBuilderOption());
167       option->SetRegisterService();
168       builder_->SetOption(std::move(option));
169     }
170   }
171 
StartServer()172   void StartServer() {
173     std::string server_address = "localhost:" + to_string(port_);
174     builder_->AddListeningPort(server_address, InsecureServerCredentials());
175     // we run some tests without a service, and for those we need to supply a
176     // frequently polled completion queue
177     cq_ = builder_->AddCompletionQueue();
178     cq_thread_ = new std::thread(&ServerBuilderPluginTest::RunCQ, this);
179     server_ = builder_->BuildAndStart();
180     EXPECT_TRUE(CheckPresent());
181   }
182 
ResetStub()183   void ResetStub() {
184     string target = "dns:localhost:" + to_string(port_);
185     channel_ = grpc::CreateChannel(target, InsecureChannelCredentials());
186     stub_ = grpc::testing::EchoTestService::NewStub(channel_);
187   }
188 
TearDown()189   void TearDown() override {
190     auto plugin = CheckPresent();
191     EXPECT_TRUE(plugin);
192     EXPECT_TRUE(plugin->init_server_is_called());
193     EXPECT_TRUE(plugin->finish_is_called());
194     server_->Shutdown();
195     cq_->Shutdown();
196     cq_thread_->join();
197     delete cq_thread_;
198   }
199 
to_string(const int number)200   string to_string(const int number) {
201     std::stringstream strs;
202     strs << number;
203     return strs.str();
204   }
205 
206  protected:
207   std::shared_ptr<Channel> channel_;
208   std::unique_ptr<ServerBuilder> builder_;
209   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
210   std::unique_ptr<ServerCompletionQueue> cq_;
211   std::unique_ptr<Server> server_;
212   std::thread* cq_thread_;
213   TestServiceImpl service_;
214   int port_;
215 
216  private:
CheckPresent()217   TestServerBuilderPlugin* CheckPresent() {
218     auto it = builder_->plugins_.begin();
219     for (; it != builder_->plugins_.end(); it++) {
220       if ((*it)->name() == PLUGIN_NAME) break;
221     }
222     if (it != builder_->plugins_.end()) {
223       return static_cast<TestServerBuilderPlugin*>(it->get());
224     } else {
225       return nullptr;
226     }
227   }
228 
RunCQ()229   void RunCQ() {
230     void* tag;
231     bool ok;
232     while (cq_->Next(&tag, &ok)) {
233     }
234   }
235 };
236 
TEST_P(ServerBuilderPluginTest,PluginWithoutServiceTest)237 TEST_P(ServerBuilderPluginTest, PluginWithoutServiceTest) {
238   InsertPlugin();
239   StartServer();
240 }
241 
TEST_P(ServerBuilderPluginTest,PluginWithServiceTest)242 TEST_P(ServerBuilderPluginTest, PluginWithServiceTest) {
243   InsertPluginWithTestService();
244   StartServer();
245   ResetStub();
246 
247   EchoRequest request;
248   EchoResponse response;
249   request.set_message("Hello hello hello hello");
250   ClientContext context;
251   context.set_compression_algorithm(GRPC_COMPRESS_GZIP);
252   Status s = stub_->Echo(&context, request, &response);
253   EXPECT_EQ(response.message(), request.message());
254   EXPECT_TRUE(s.ok());
255 }
256 
257 INSTANTIATE_TEST_SUITE_P(ServerBuilderPluginTest, ServerBuilderPluginTest,
258                          ::testing::Values(false, true));
259 
260 }  // namespace testing
261 }  // namespace grpc
262 
main(int argc,char ** argv)263 int main(int argc, char** argv) {
264   grpc::testing::TestEnvironment env(&argc, argv);
265   ::testing::InitGoogleTest(&argc, argv);
266   return RUN_ALL_TESTS();
267 }
268