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