xref: /aosp_15_r20/external/grpc-grpc/test/core/surface/num_external_connectivity_watchers_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 <stddef.h>
20 
21 #include <string>
22 
23 #include "gtest/gtest.h"
24 
25 #include <grpc/grpc.h>
26 #include <grpc/grpc_security.h>
27 #include <grpc/impl/channel_arg_names.h>
28 #include <grpc/slice.h>
29 #include <grpc/support/log.h>
30 #include <grpc/support/time.h>
31 
32 #include "src/core/lib/channel/channel_args.h"
33 #include "src/core/lib/gprpp/host_port.h"
34 #include "src/core/lib/iomgr/error.h"
35 #include "src/core/lib/iomgr/exec_ctx.h"
36 #include "test/core/util/port.h"
37 #include "test/core/util/test_config.h"
38 #include "test/core/util/tls_utils.h"
39 
40 #define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
41 
42 typedef struct test_fixture {
43   const char* name;
44   grpc_channel* (*create_channel)(const char* addr);
45 } test_fixture;
46 
47 static size_t next_tag = 1;
48 
channel_idle_start_watch(grpc_channel * channel,grpc_completion_queue * cq)49 static void channel_idle_start_watch(grpc_channel* channel,
50                                      grpc_completion_queue* cq) {
51   gpr_timespec connect_deadline = grpc_timeout_milliseconds_to_deadline(1);
52   ASSERT_EQ(grpc_channel_check_connectivity_state(channel, 0),
53             GRPC_CHANNEL_IDLE);
54 
55   grpc_channel_watch_connectivity_state(channel, GRPC_CHANNEL_IDLE,
56                                         connect_deadline, cq,
57                                         reinterpret_cast<void*>(next_tag++));
58 }
59 
channel_idle_poll_for_timeout(grpc_channel * channel,grpc_completion_queue * cq)60 static void channel_idle_poll_for_timeout(grpc_channel* channel,
61                                           grpc_completion_queue* cq) {
62   grpc_event ev = grpc_completion_queue_next(
63       cq, gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
64 
65   // expect watch_connectivity_state to end with a timeout
66   ASSERT_EQ(ev.type, GRPC_OP_COMPLETE);
67   ASSERT_EQ(ev.success, false);
68   ASSERT_EQ(grpc_channel_check_connectivity_state(channel, 0),
69             GRPC_CHANNEL_IDLE);
70 }
71 
72 // Test to make sure that "connectivity watcher" structs are free'd just
73 // after, if their corresponding timeouts occur.
run_timeouts_test(const test_fixture * fixture)74 static void run_timeouts_test(const test_fixture* fixture) {
75   gpr_log(GPR_INFO, "TEST: %s", fixture->name);
76 
77   grpc_init();
78   std::string addr =
79       grpc_core::JoinHostPort("localhost", grpc_pick_unused_port_or_die());
80 
81   grpc_channel* channel = fixture->create_channel(addr.c_str());
82   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
83 
84   // start 1 watcher and then let it time out
85   channel_idle_start_watch(channel, cq);
86   channel_idle_poll_for_timeout(channel, cq);
87 
88   // start 3 watchers and then let them all time out
89   for (size_t i = 1; i <= 3; i++) {
90     channel_idle_start_watch(channel, cq);
91   }
92   for (size_t i = 1; i <= 3; i++) {
93     channel_idle_poll_for_timeout(channel, cq);
94   }
95 
96   // start 3 watchers, see one time out, start another 3, and then see them all
97   // time out
98   for (size_t i = 1; i <= 3; i++) {
99     channel_idle_start_watch(channel, cq);
100   }
101   channel_idle_poll_for_timeout(channel, cq);
102   for (size_t i = 3; i <= 5; i++) {
103     channel_idle_start_watch(channel, cq);
104   }
105   for (size_t i = 1; i <= 5; i++) {
106     channel_idle_poll_for_timeout(channel, cq);
107   }
108 
109   grpc_channel_destroy(channel);
110   grpc_completion_queue_shutdown(cq);
111   ASSERT_EQ(grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME),
112                                        nullptr)
113                 .type,
114             GRPC_QUEUE_SHUTDOWN);
115   grpc_completion_queue_destroy(cq);
116 
117   grpc_shutdown();
118 }
119 
120 // An edge scenario; sets channel state to explicitly, and outside
121 // of a polling call.
run_channel_shutdown_before_timeout_test(const test_fixture * fixture)122 static void run_channel_shutdown_before_timeout_test(
123     const test_fixture* fixture) {
124   gpr_log(GPR_INFO, "TEST: %s", fixture->name);
125 
126   grpc_init();
127   std::string addr =
128       grpc_core::JoinHostPort("localhost", grpc_pick_unused_port_or_die());
129 
130   grpc_channel* channel = fixture->create_channel(addr.c_str());
131   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
132 
133   // start 1 watcher and then shut down the channel before the timer goes off.
134   // expecting a 30 second timeout to go off much later than the shutdown.
135   gpr_timespec connect_deadline = grpc_timeout_seconds_to_deadline(30);
136   ASSERT_EQ(grpc_channel_check_connectivity_state(channel, 0),
137             GRPC_CHANNEL_IDLE);
138 
139   grpc_channel_watch_connectivity_state(channel, GRPC_CHANNEL_IDLE,
140                                         connect_deadline, cq,
141                                         reinterpret_cast<void*>(1));
142   grpc_channel_destroy(channel);
143 
144   grpc_event ev = grpc_completion_queue_next(
145       cq, gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
146   ASSERT_EQ(ev.type, GRPC_OP_COMPLETE);
147   // expect success with a state transition to CHANNEL_SHUTDOWN
148   ASSERT_EQ(ev.success, true);
149 
150   grpc_completion_queue_shutdown(cq);
151   ASSERT_EQ(grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME),
152                                        nullptr)
153                 .type,
154             GRPC_QUEUE_SHUTDOWN);
155   grpc_completion_queue_destroy(cq);
156 
157   grpc_shutdown();
158 }
159 
insecure_test_create_channel(const char * addr)160 static grpc_channel* insecure_test_create_channel(const char* addr) {
161   grpc_channel_credentials* creds = grpc_insecure_credentials_create();
162   grpc_channel* channel = grpc_channel_create(addr, creds, nullptr);
163   grpc_channel_credentials_release(creds);
164   return channel;
165 }
166 
167 static const test_fixture insecure_test = {
168     "insecure",
169     insecure_test_create_channel,
170 };
171 
secure_test_create_channel(const char * addr)172 static grpc_channel* secure_test_create_channel(const char* addr) {
173   std::string test_root_cert =
174       grpc_core::testing::GetFileContents(CA_CERT_PATH);
175   grpc_channel_credentials* ssl_creds = grpc_ssl_credentials_create(
176       test_root_cert.c_str(), nullptr, nullptr, nullptr);
177   grpc_arg ssl_name_override = {
178       GRPC_ARG_STRING,
179       const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
180       {const_cast<char*>("foo.test.google.fr")}};
181   grpc_channel_args* new_client_args =
182       grpc_channel_args_copy_and_add(nullptr, &ssl_name_override, 1);
183   grpc_channel* channel = grpc_channel_create(addr, ssl_creds, new_client_args);
184   {
185     grpc_core::ExecCtx exec_ctx;
186     grpc_channel_args_destroy(new_client_args);
187   }
188   grpc_channel_credentials_release(ssl_creds);
189   return channel;
190 }
191 
192 static const test_fixture secure_test = {
193     "secure",
194     secure_test_create_channel,
195 };
196 
TEST(NumExternalConnectivityWatchersTest,MainTest)197 TEST(NumExternalConnectivityWatchersTest, MainTest) {
198   run_timeouts_test(&insecure_test);
199   run_timeouts_test(&secure_test);
200 
201   run_channel_shutdown_before_timeout_test(&insecure_test);
202   run_channel_shutdown_before_timeout_test(&secure_test);
203 }
204 
main(int argc,char ** argv)205 int main(int argc, char** argv) {
206   grpc::testing::TestEnvironment env(&argc, argv);
207   ::testing::InitGoogleTest(&argc, argv);
208   return RUN_ALL_TESTS();
209 }
210