1 /*
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 <string.h>
20
21 #include <grpc/grpc.h>
22 #include <grpc/support/alloc.h>
23 #include <grpc/support/log.h>
24 #include "src/core/lib/channel/channel_stack.h"
25 #include "src/core/lib/iomgr/closure.h"
26 #include "src/core/lib/surface/channel.h"
27 #include "src/core/lib/transport/transport.h"
28 #include "test/core/end2end/cq_verifier.h"
29 #include "test/core/util/test_config.h"
30
31 grpc_closure transport_op_cb;
32
tag(intptr_t x)33 static void* tag(intptr_t x) { return (void*)x; }
34
verify_connectivity(void * arg,grpc_error * error)35 void verify_connectivity(void* arg, grpc_error* error) {
36 grpc_connectivity_state* state = static_cast<grpc_connectivity_state*>(arg);
37 GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *state);
38 GPR_ASSERT(error == GRPC_ERROR_NONE);
39 }
40
do_nothing(void * arg,grpc_error * error)41 void do_nothing(void* arg, grpc_error* error) {}
42
test_transport_op(grpc_channel * channel)43 void test_transport_op(grpc_channel* channel) {
44 grpc_transport_op* op;
45 grpc_channel_element* elem;
46 grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
47 grpc_core::ExecCtx exec_ctx;
48
49 GRPC_CLOSURE_INIT(&transport_op_cb, verify_connectivity, &state,
50 grpc_schedule_on_exec_ctx);
51
52 op = grpc_make_transport_op(nullptr);
53 op->on_connectivity_state_change = &transport_op_cb;
54 op->connectivity_state = &state;
55 elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
56 elem->filter->start_transport_op(elem, op);
57
58 GRPC_CLOSURE_INIT(&transport_op_cb, do_nothing, nullptr,
59 grpc_schedule_on_exec_ctx);
60 op = grpc_make_transport_op(&transport_op_cb);
61 elem->filter->start_transport_op(elem, op);
62 }
63
main(int argc,char ** argv)64 int main(int argc, char** argv) {
65 grpc_channel* chan;
66 grpc_call* call;
67 grpc_completion_queue* cq;
68 cq_verifier* cqv;
69 grpc_op ops[6];
70 grpc_op* op;
71 grpc_metadata_array initial_metadata_recv;
72 grpc_metadata_array trailing_metadata_recv;
73 grpc_status_code status;
74 grpc_call_error error;
75 grpc_slice details;
76 char* peer;
77
78 grpc_test_init(argc, argv);
79 grpc_init();
80
81 grpc_metadata_array_init(&initial_metadata_recv);
82 grpc_metadata_array_init(&trailing_metadata_recv);
83
84 chan = grpc_lame_client_channel_create(
85 "lampoon:national", GRPC_STATUS_UNKNOWN, "Rpc sent on a lame channel.");
86 GPR_ASSERT(chan);
87
88 test_transport_op(chan);
89
90 GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN ==
91 grpc_channel_check_connectivity_state(chan, 0));
92
93 cq = grpc_completion_queue_create_for_next(nullptr);
94
95 grpc_slice host = grpc_slice_from_static_string("anywhere");
96 call =
97 grpc_channel_create_call(chan, nullptr, GRPC_PROPAGATE_DEFAULTS, cq,
98 grpc_slice_from_static_string("/Foo"), &host,
99 grpc_timeout_seconds_to_deadline(100), nullptr);
100 GPR_ASSERT(call);
101 cqv = cq_verifier_create(cq);
102
103 memset(ops, 0, sizeof(ops));
104 op = ops;
105 op->op = GRPC_OP_SEND_INITIAL_METADATA;
106 op->data.send_initial_metadata.count = 0;
107 op->flags = 0;
108 op->reserved = nullptr;
109 op++;
110 op->op = GRPC_OP_RECV_INITIAL_METADATA;
111 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
112 op->flags = 0;
113 op->reserved = nullptr;
114 op++;
115 error = grpc_call_start_batch(call, ops, static_cast<size_t>(op - ops),
116 tag(1), nullptr);
117 GPR_ASSERT(GRPC_CALL_OK == error);
118
119 /* the call should immediately fail */
120 CQ_EXPECT_COMPLETION(cqv, tag(1), 0);
121 cq_verify(cqv);
122
123 memset(ops, 0, sizeof(ops));
124 op = ops;
125 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
126 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
127 op->data.recv_status_on_client.status = &status;
128 op->data.recv_status_on_client.status_details = &details;
129 op->flags = 0;
130 op->reserved = nullptr;
131 op++;
132 error = grpc_call_start_batch(call, ops, static_cast<size_t>(op - ops),
133 tag(2), nullptr);
134 GPR_ASSERT(GRPC_CALL_OK == error);
135
136 /* the call should immediately fail */
137 CQ_EXPECT_COMPLETION(cqv, tag(2), 1);
138 cq_verify(cqv);
139
140 peer = grpc_call_get_peer(call);
141 GPR_ASSERT(strcmp(peer, "lampoon:national") == 0);
142 gpr_free(peer);
143
144 grpc_call_unref(call);
145 grpc_channel_destroy(chan);
146 cq_verifier_destroy(cqv);
147 grpc_completion_queue_destroy(cq);
148
149 grpc_metadata_array_destroy(&initial_metadata_recv);
150 grpc_metadata_array_destroy(&trailing_metadata_recv);
151 grpc_slice_unref(details);
152
153 grpc_shutdown();
154
155 return 0;
156 }
157