blob: 06343c46b4f7112eb7fed9111db8bdae9c950b7c [file] [log] [blame]
ncteisenb8a52e02018-06-07 18:58:03 -07001/*
2 *
3 * Copyright 2015 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 "test/core/end2end/end2end_tests.h"
20
21#include <stdio.h>
22#include <string.h>
23
24#include "src/core/lib/surface/channel.h"
25
26#include <grpc/byte_buffer.h>
27#include <grpc/grpc.h>
28#include <grpc/support/alloc.h>
29#include <grpc/support/log.h>
30#include <grpc/support/time.h>
31#include "src/core/lib/gpr/string.h"
32#include "test/core/end2end/cq_verifier.h"
33
34static void* tag(intptr_t t) { return (void*)t; }
35
36static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
37 const char* test_name,
38 grpc_channel_args* client_args,
39 grpc_channel_args* server_args) {
40 grpc_end2end_test_fixture f;
41 gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
42 f = config.create_fixture(client_args, server_args);
43 config.init_server(&f, server_args);
44 config.init_client(&f, client_args);
45 return f;
46}
47
48static gpr_timespec n_seconds_from_now(int n) {
49 return grpc_timeout_seconds_to_deadline(n);
50}
51
52static gpr_timespec five_seconds_from_now(void) {
53 return n_seconds_from_now(5);
54}
55
56static void drain_cq(grpc_completion_queue* cq) {
57 grpc_event ev;
58 do {
59 ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
60 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
61}
62
63static void shutdown_server(grpc_end2end_test_fixture* f) {
64 if (!f->server) return;
65 grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
66 GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
67 grpc_timeout_seconds_to_deadline(5),
68 nullptr)
69 .type == GRPC_OP_COMPLETE);
70 grpc_server_destroy(f->server);
71 f->server = nullptr;
72}
73
74static void shutdown_client(grpc_end2end_test_fixture* f) {
75 if (!f->client) return;
76 grpc_channel_destroy(f->client);
77 f->client = nullptr;
78}
79
80static void end_test(grpc_end2end_test_fixture* f) {
81 shutdown_server(f);
82 shutdown_client(f);
83
84 grpc_completion_queue_shutdown(f->cq);
85 drain_cq(f->cq);
86 grpc_completion_queue_destroy(f->cq);
87 grpc_completion_queue_destroy(f->shutdown_cq);
88}
89
90static void run_one_request(grpc_end2end_test_config config,
91 grpc_end2end_test_fixture f,
92 bool request_is_success) {
93 grpc_call* c;
94 grpc_call* s;
95 cq_verifier* cqv = cq_verifier_create(f.cq);
96 grpc_op ops[6];
97 grpc_op* op;
98 grpc_metadata_array initial_metadata_recv;
99 grpc_metadata_array trailing_metadata_recv;
100 grpc_metadata_array request_metadata_recv;
101 grpc_call_details call_details;
102 grpc_status_code status;
103 grpc_call_error error;
104 grpc_slice details;
105 int was_cancelled = 2;
106
107 gpr_timespec deadline = five_seconds_from_now();
108 c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
109 grpc_slice_from_static_string("/foo"), nullptr,
110 deadline, nullptr);
111 GPR_ASSERT(c);
112
113 grpc_metadata_array_init(&initial_metadata_recv);
114 grpc_metadata_array_init(&trailing_metadata_recv);
115 grpc_metadata_array_init(&request_metadata_recv);
116 grpc_call_details_init(&call_details);
117
118 memset(ops, 0, sizeof(ops));
119 op = ops;
120 op->op = GRPC_OP_SEND_INITIAL_METADATA;
121 op->data.send_initial_metadata.count = 0;
122 op->flags = 0;
123 op->reserved = nullptr;
124 op++;
125 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
126 op->flags = 0;
127 op->reserved = nullptr;
128 op++;
129 op->op = GRPC_OP_RECV_INITIAL_METADATA;
130 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
131 op->flags = 0;
132 op->reserved = nullptr;
133 op++;
134 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
135 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
136 op->data.recv_status_on_client.status = &status;
137 op->data.recv_status_on_client.status_details = &details;
138 op->data.recv_status_on_client.error_string = nullptr;
139 op->flags = 0;
140 op->reserved = nullptr;
141 op++;
142 error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
143 nullptr);
144 GPR_ASSERT(GRPC_CALL_OK == error);
145
146 error =
147 grpc_server_request_call(f.server, &s, &call_details,
148 &request_metadata_recv, f.cq, f.cq, tag(101));
149 GPR_ASSERT(GRPC_CALL_OK == error);
150 CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
151 cq_verify(cqv);
152
153 memset(ops, 0, sizeof(ops));
154 op = ops;
155 op->op = GRPC_OP_SEND_INITIAL_METADATA;
156 op->data.send_initial_metadata.count = 0;
157 op->flags = 0;
158 op->reserved = nullptr;
159 op++;
160 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
161 op->data.send_status_from_server.trailing_metadata_count = 0;
162 op->data.send_status_from_server.status =
163 request_is_success ? GRPC_STATUS_OK : GRPC_STATUS_UNIMPLEMENTED;
164 grpc_slice status_details = grpc_slice_from_static_string("xyz");
165 op->data.send_status_from_server.status_details = &status_details;
166 op->flags = 0;
167 op->reserved = nullptr;
168 op++;
169 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
170 op->data.recv_close_on_server.cancelled = &was_cancelled;
171 op->flags = 0;
172 op->reserved = nullptr;
173 op++;
174 error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
175 nullptr);
176 GPR_ASSERT(GRPC_CALL_OK == error);
177
178 CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
179 CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
180 cq_verify(cqv);
181
182 GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
183 GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
184 GPR_ASSERT(0 == call_details.flags);
185
186 grpc_slice_unref(details);
187 grpc_metadata_array_destroy(&initial_metadata_recv);
188 grpc_metadata_array_destroy(&trailing_metadata_recv);
189 grpc_metadata_array_destroy(&request_metadata_recv);
190 grpc_call_details_destroy(&call_details);
191
192 grpc_call_unref(c);
193 grpc_call_unref(s);
194
195 cq_verifier_destroy(cqv);
196}
197
198static void test_channelz(grpc_end2end_test_config config) {
199 grpc_end2end_test_fixture f;
200
ncteisenc7166ae2018-06-15 11:04:37 -0400201 grpc_arg client_a;
202 client_a.type = GRPC_ARG_INTEGER;
203 client_a.key = const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ);
204 client_a.value.integer = true;
205 grpc_channel_args client_args = {1, &client_a};
206
207 f = begin_test(config, "test_channelz", &client_args, nullptr);
ncteisendb6593e2018-06-08 09:46:55 -0700208 grpc_core::channelz::ChannelNode* channelz_channel =
ncteisenb8a52e02018-06-07 18:58:03 -0700209 grpc_channel_get_channelz_node(f.client);
210
211 char* json = channelz_channel->RenderJSON();
ncteisenc7166ae2018-06-15 11:04:37 -0400212 GPR_ASSERT(json != nullptr);
ncteisenb8a52e02018-06-07 18:58:03 -0700213 GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"0\""));
214 GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\""));
215 GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"0\""));
216 gpr_free(json);
217
218 // one successful request
219 run_one_request(config, f, true);
220
221 json = channelz_channel->RenderJSON();
ncteisenc7166ae2018-06-15 11:04:37 -0400222 GPR_ASSERT(json != nullptr);
ncteisenb8a52e02018-06-07 18:58:03 -0700223 GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"1\""));
224 GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\""));
225 GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
226 gpr_free(json);
227
228 // one failed request
229 run_one_request(config, f, false);
230
231 json = channelz_channel->RenderJSON();
ncteisenc7166ae2018-06-15 11:04:37 -0400232 GPR_ASSERT(json != nullptr);
ncteisenb8a52e02018-06-07 18:58:03 -0700233 gpr_log(GPR_INFO, "%s", json);
234 GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\""));
235 GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\""));
236 GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
ncteisenc7166ae2018-06-15 11:04:37 -0400237 // channel tracing is not enables, so these should not be preset.
238 GPR_ASSERT(nullptr == strstr(json, "\"trace\""));
239 GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\""));
240 GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\""));
ncteisenb8a52e02018-06-07 18:58:03 -0700241 gpr_free(json);
242
243 end_test(&f);
244 config.tear_down_data(&f);
245}
246
247static void test_channelz_with_channel_trace(grpc_end2end_test_config config) {
248 grpc_end2end_test_fixture f;
249
ncteisenc7166ae2018-06-15 11:04:37 -0400250 grpc_arg client_a[2];
251 client_a[0].type = GRPC_ARG_INTEGER;
252 client_a[0].key =
253 const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
254 client_a[0].value.integer = 5;
255 client_a[1].type = GRPC_ARG_INTEGER;
256 client_a[1].key = const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ);
257 client_a[1].value.integer = true;
258 grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
ncteisenb8a52e02018-06-07 18:58:03 -0700259
260 f = begin_test(config, "test_channelz_with_channel_trace", &client_args,
261 nullptr);
ncteisendb6593e2018-06-08 09:46:55 -0700262 grpc_core::channelz::ChannelNode* channelz_channel =
ncteisenb8a52e02018-06-07 18:58:03 -0700263 grpc_channel_get_channelz_node(f.client);
264
265 char* json = channelz_channel->RenderJSON();
ncteisenc7166ae2018-06-15 11:04:37 -0400266 GPR_ASSERT(json != nullptr);
ncteisenb8a52e02018-06-07 18:58:03 -0700267 gpr_log(GPR_INFO, "%s", json);
268 GPR_ASSERT(nullptr != strstr(json, "\"trace\""));
269 GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Channel created\""));
270 GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\""));
271 gpr_free(json);
272
273 end_test(&f);
274 config.tear_down_data(&f);
275}
ncteisenc7166ae2018-06-15 11:04:37 -0400276
277static void test_channelz_disabled(grpc_end2end_test_config config) {
278 grpc_end2end_test_fixture f;
279
280 f = begin_test(config, "test_channelz_disabled", nullptr, nullptr);
281 grpc_core::channelz::ChannelNode* channelz_channel =
282 grpc_channel_get_channelz_node(f.client);
283 char* json_str = channelz_channel->RenderJSON();
284 GPR_ASSERT(json_str == nullptr);
285 grpc_json* json = channelz_channel->trace()->RenderJSON();
286 GPR_ASSERT(json == nullptr);
287 // one successful request
288 run_one_request(config, f, true);
289 json_str = channelz_channel->RenderJSON();
290 GPR_ASSERT(json_str == nullptr);
291 GPR_ASSERT(json == nullptr);
292 end_test(&f);
293 config.tear_down_data(&f);
294}
295
296static void test_channelz_disabled_with_channel_trace(
297 grpc_end2end_test_config config) {
298 grpc_end2end_test_fixture f;
299
300 grpc_arg client_a;
301 client_a.type = GRPC_ARG_INTEGER;
302 client_a.key = const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
303 client_a.value.integer = 5;
304 grpc_channel_args client_args = {1, &client_a};
305
306 f = begin_test(config, "test_channelz_disabled_with_channel_trace",
307 &client_args, nullptr);
308 grpc_core::channelz::ChannelNode* channelz_channel =
309 grpc_channel_get_channelz_node(f.client);
310 // channelz is disabled so rendering return null.
311 char* json_str = channelz_channel->RenderJSON();
312 GPR_ASSERT(json_str == nullptr);
313 // channel trace is explicitly requested, so this works as it should
314 grpc_json* json = channelz_channel->trace()->RenderJSON();
315 GPR_ASSERT(json != nullptr);
316 json_str = grpc_json_dump_to_string(json, 0);
317 GPR_ASSERT(json_str != nullptr);
318 gpr_log(GPR_INFO, "%s", json_str);
319 GPR_ASSERT(nullptr !=
320 strstr(json_str, "\"description\":\"Channel created\""));
321 GPR_ASSERT(nullptr != strstr(json_str, "\"severity\":\"CT_INFO\""));
322 GPR_ASSERT(nullptr != strstr(json_str, "\"numEventsLogged\":"));
323 grpc_json_destroy(json);
324 gpr_free(json_str);
325
326 end_test(&f);
327 config.tear_down_data(&f);
328}
329
ncteisenb8a52e02018-06-07 18:58:03 -0700330void channelz(grpc_end2end_test_config config) {
331 test_channelz(config);
332 test_channelz_with_channel_trace(config);
ncteisenc7166ae2018-06-15 11:04:37 -0400333 test_channelz_disabled(config);
334 test_channelz_disabled_with_channel_trace(config);
ncteisenb8a52e02018-06-07 18:58:03 -0700335}
336
337void channelz_pre_init(void) {}