blob: 4d045da09816dfc47bdb8d78a0b2928398a7ca9f [file] [log] [blame]
Yang Gaob946b5e2015-03-27 13:20:59 -07001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Yang Gaob946b5e2015-03-27 13:20:59 -07004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "test/cpp/util/cli_call.h"
35
36#include <iostream>
37
yang-g9e2f90c2015-08-21 15:35:03 -070038#include <grpc++/channel.h>
39#include <grpc++/client_context.h>
Sree Kuchibhotlab0d0c8e2016-01-13 22:52:17 -080040#include <grpc++/support/byte_buffer.h>
41#include <grpc/grpc.h>
Craig Tillerb37d53e2016-10-26 16:16:35 -070042#include <grpc/slice.h>
Craig Tiller28b72422016-10-26 21:15:29 -070043#include <grpc/support/log.h>
Yang Gaob946b5e2015-03-27 13:20:59 -070044
45namespace grpc {
46namespace testing {
47namespace {
Craig Tiller7536af02015-12-22 13:49:30 -080048void* tag(int i) { return (void*)(intptr_t)i; }
Yang Gaob946b5e2015-03-27 13:20:59 -070049} // namespace
50
yang-g8c2be9f2015-08-19 16:28:09 -070051Status CliCall::Call(std::shared_ptr<grpc::Channel> channel,
Yang Gao102eccb62015-06-16 00:43:25 -070052 const grpc::string& method, const grpc::string& request,
yang-ge21908f2015-08-25 13:47:51 -070053 grpc::string* response,
54 const OutgoingMetadataContainer& metadata,
55 IncomingMetadataContainer* server_initial_metadata,
56 IncomingMetadataContainer* server_trailing_metadata) {
Yuchen Zengf9329212016-09-09 14:27:12 -070057 CliCall call(channel, method, metadata);
58 call.Write(request);
59 call.WritesDone();
Yuchen Zengd37f6422016-09-09 20:05:37 -070060 if (!call.Read(response, server_initial_metadata)) {
61 fprintf(stderr, "Failed to read response.\n");
62 }
Yuchen Zengf9329212016-09-09 14:27:12 -070063 return call.Finish(server_trailing_metadata);
64}
65
66CliCall::CliCall(std::shared_ptr<grpc::Channel> channel,
67 const grpc::string& method,
68 const OutgoingMetadataContainer& metadata)
69 : stub_(new grpc::GenericStub(channel)) {
Yuchen Zeng8d2d70c2016-09-16 15:42:57 -070070 gpr_mu_init(&write_mu_);
71 gpr_cv_init(&write_cv_);
Yang Gao102eccb62015-06-16 00:43:25 -070072 if (!metadata.empty()) {
yang-ge21908f2015-08-25 13:47:51 -070073 for (OutgoingMetadataContainer::const_iterator iter = metadata.begin();
Yang Gao102eccb62015-06-16 00:43:25 -070074 iter != metadata.end(); ++iter) {
Yuchen Zengf9329212016-09-09 14:27:12 -070075 ctx_.AddMetadata(iter->first, iter->second);
Yang Gao102eccb62015-06-16 00:43:25 -070076 }
77 }
Yuchen Zengf9329212016-09-09 14:27:12 -070078 call_ = stub_->Call(&ctx_, method, &cq_, tag(1));
Yang Gaob946b5e2015-03-27 13:20:59 -070079 void* got_tag;
80 bool ok;
Yuchen Zengf9329212016-09-09 14:27:12 -070081 cq_.Next(&got_tag, &ok);
Yang Gaob946b5e2015-03-27 13:20:59 -070082 GPR_ASSERT(ok);
Yuchen Zengf9329212016-09-09 14:27:12 -070083}
84
Yuchen Zeng8d2d70c2016-09-16 15:42:57 -070085CliCall::~CliCall() {
86 gpr_cv_destroy(&write_cv_);
87 gpr_mu_destroy(&write_mu_);
88}
89
Yuchen Zengf9329212016-09-09 14:27:12 -070090void CliCall::Write(const grpc::string& request) {
91 void* got_tag;
92 bool ok;
Yang Gaob946b5e2015-03-27 13:20:59 -070093
Craig Tillerd41a4a72016-10-26 16:16:06 -070094 grpc_slice s = grpc_slice_from_copied_string(request.c_str());
Yang Gaob946b5e2015-03-27 13:20:59 -070095 grpc::Slice req_slice(s, grpc::Slice::STEAL_REF);
96 grpc::ByteBuffer send_buffer(&req_slice, 1);
Yuchen Zengf9329212016-09-09 14:27:12 -070097 call_->Write(send_buffer, tag(2));
98 cq_.Next(&got_tag, &ok);
Yang Gaob946b5e2015-03-27 13:20:59 -070099 GPR_ASSERT(ok);
Yuchen Zengf9329212016-09-09 14:27:12 -0700100}
Yang Gaob946b5e2015-03-27 13:20:59 -0700101
Yuchen Zengd37f6422016-09-09 20:05:37 -0700102bool CliCall::Read(grpc::string* response,
Yuchen Zengf9329212016-09-09 14:27:12 -0700103 IncomingMetadataContainer* server_initial_metadata) {
104 void* got_tag;
105 bool ok;
106
107 grpc::ByteBuffer recv_buffer;
Yuchen Zengd37f6422016-09-09 20:05:37 -0700108 call_->Read(&recv_buffer, tag(3));
Yang Gaob946b5e2015-03-27 13:20:59 -0700109
Yuchen Zengd37f6422016-09-09 20:05:37 -0700110 if (!cq_.Next(&got_tag, &ok) || !ok) {
111 return false;
Yuchen Zengf9329212016-09-09 14:27:12 -0700112 }
Yuchen Zengd37f6422016-09-09 20:05:37 -0700113 std::vector<grpc::Slice> slices;
114 recv_buffer.Dump(&slices);
115
116 response->clear();
117 for (size_t i = 0; i < slices.size(); i++) {
118 response->append(reinterpret_cast<const char*>(slices[i].begin()),
119 slices[i].size());
120 }
121 if (server_initial_metadata) {
122 *server_initial_metadata = ctx_.GetServerInitialMetadata();
123 }
124 return true;
Yuchen Zengf9329212016-09-09 14:27:12 -0700125}
126
127void CliCall::WritesDone() {
128 void* got_tag;
129 bool ok;
130
Yuchen Zengd37f6422016-09-09 20:05:37 -0700131 call_->WritesDone(tag(4));
Yuchen Zengf9329212016-09-09 14:27:12 -0700132 cq_.Next(&got_tag, &ok);
133 GPR_ASSERT(ok);
134}
135
Yuchen Zeng8d2d70c2016-09-16 15:42:57 -0700136void CliCall::WriteAndWait(const grpc::string& request) {
137 grpc_slice s = grpc_slice_from_copied_string(request.c_str());
138 grpc::Slice req_slice(s, grpc::Slice::STEAL_REF);
139 grpc::ByteBuffer send_buffer(&req_slice, 1);
140
141 gpr_mu_lock(&write_mu_);
142 call_->Write(send_buffer, tag(2));
143 write_done_ = false;
144 while (!write_done_) {
145 gpr_cv_wait(&write_cv_, &write_mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
146 }
147 gpr_mu_unlock(&write_mu_);
148}
149
150void CliCall::WritesDoneAndWait() {
151 gpr_mu_lock(&write_mu_);
152 call_->WritesDone(tag(4));
153 write_done_ = false;
154 while (!write_done_) {
155 gpr_cv_wait(&write_cv_, &write_mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
156 }
157 gpr_mu_unlock(&write_mu_);
158}
159
160bool CliCall::ReadAndMaybeNotifyWrite(
161 grpc::string* response,
162 IncomingMetadataContainer* server_initial_metadata) {
163 void* got_tag;
164 bool ok;
165 grpc::ByteBuffer recv_buffer;
166
167 call_->Read(&recv_buffer, tag(3));
168 bool cq_result = cq_.Next(&got_tag, &ok);
169
170 while (got_tag != tag(3)) {
171 gpr_mu_lock(&write_mu_);
172 write_done_ = true;
173 gpr_cv_signal(&write_cv_);
174 gpr_mu_unlock(&write_mu_);
175
176 cq_result = cq_.Next(&got_tag, &ok);
177 if (got_tag == tag(2)) {
178 GPR_ASSERT(ok);
179 }
180 }
181
182 if (!cq_result || !ok) {
183 // If the RPC is ended on the server side, we should still wait for the
184 // pending write on the client side to be done.
185 if (!ok) {
186 gpr_mu_lock(&write_mu_);
187 if (!write_done_) {
188 cq_.Next(&got_tag, &ok);
189 GPR_ASSERT(got_tag != tag(2));
190 write_done_ = true;
191 gpr_cv_signal(&write_cv_);
192 }
193 gpr_mu_unlock(&write_mu_);
194 }
195 return false;
196 }
197
198 std::vector<grpc::Slice> slices;
199 recv_buffer.Dump(&slices);
200 response->clear();
201 for (size_t i = 0; i < slices.size(); i++) {
202 response->append(reinterpret_cast<const char*>(slices[i].begin()),
203 slices[i].size());
204 }
205 if (server_initial_metadata) {
206 *server_initial_metadata = ctx_.GetServerInitialMetadata();
207 }
208 return true;
209}
210
Yuchen Zengf9329212016-09-09 14:27:12 -0700211Status CliCall::Finish(IncomingMetadataContainer* server_trailing_metadata) {
212 void* got_tag;
213 bool ok;
214 grpc::Status status;
215
216 call_->Finish(&status, tag(5));
217 cq_.Next(&got_tag, &ok);
218 GPR_ASSERT(ok);
219 if (server_trailing_metadata) {
220 *server_trailing_metadata = ctx_.GetServerTrailingMetadata();
Yang Gaob946b5e2015-03-27 13:20:59 -0700221 }
yang-gdf012d02016-05-18 15:44:06 -0700222
Yang Gao102eccb62015-06-16 00:43:25 -0700223 return status;
Yang Gaob946b5e2015-03-27 13:20:59 -0700224}
225
226} // namespace testing
David Garcia Quintas2bf574f2016-01-14 15:27:08 -0800227} // namespace grpc