blob: 05d19edd9673dd26758492ec610151f776a6c9d6 [file] [log] [blame]
Roger Meier2be7f242012-05-10 09:01:45 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19#ifndef _THRIFT_PROCESSOR_TEST_HANDLERS_H_
20#define _THRIFT_PROCESSOR_TEST_HANDLERS_H_ 1
21
Roger Meier2b1a5282012-05-11 10:12:39 +000022#include "EventLog.h"
Roger Meier2be7f242012-05-10 09:01:45 +000023#include "gen-cpp/ParentService.h"
24#include "gen-cpp/ChildService.h"
25
Konrad Grochowski16a23a62014-11-13 15:33:38 +010026namespace apache {
27namespace thrift {
28namespace test {
Roger Meier2be7f242012-05-10 09:01:45 +000029
30class ParentHandler : virtual public ParentServiceIf {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010031public:
cyy316723a2019-01-05 16:35:14 +080032 ParentHandler(const std::shared_ptr<EventLog>& log)
Konrad Grochowski16a23a62014-11-13 15:33:38 +010033 : triggerMonitor(&mutex_), generation_(0), wait_(false), log_(log) {}
Roger Meier2be7f242012-05-10 09:01:45 +000034
Sebastian Zenker042580f2019-01-29 15:48:12 +010035 int32_t incrementGeneration() override {
Roger Meier2be7f242012-05-10 09:01:45 +000036 concurrency::Guard g(mutex_);
37 log_->append(EventLog::ET_CALL_INCREMENT_GENERATION, 0, 0);
38 return ++generation_;
39 }
40
Sebastian Zenker042580f2019-01-29 15:48:12 +010041 int32_t getGeneration() override {
Roger Meier2be7f242012-05-10 09:01:45 +000042 concurrency::Guard g(mutex_);
43 log_->append(EventLog::ET_CALL_GET_GENERATION, 0, 0);
44 return generation_;
45 }
46
Sebastian Zenker042580f2019-01-29 15:48:12 +010047 void addString(const std::string& s) override {
Roger Meier2be7f242012-05-10 09:01:45 +000048 concurrency::Guard g(mutex_);
49 log_->append(EventLog::ET_CALL_ADD_STRING, 0, 0);
50 strings_.push_back(s);
51 }
52
Sebastian Zenker042580f2019-01-29 15:48:12 +010053 void getStrings(std::vector<std::string>& _return) override {
Roger Meier2be7f242012-05-10 09:01:45 +000054 concurrency::Guard g(mutex_);
55 log_->append(EventLog::ET_CALL_GET_STRINGS, 0, 0);
56 _return = strings_;
57 }
58
Sebastian Zenker042580f2019-01-29 15:48:12 +010059 void getDataWait(std::string& _return, const int32_t length) override {
Roger Meier2be7f242012-05-10 09:01:45 +000060 concurrency::Guard g(mutex_);
61 log_->append(EventLog::ET_CALL_GET_DATA_WAIT, 0, 0);
62
63 blockUntilTriggered();
64
65 _return.append(length, 'a');
66 }
67
Sebastian Zenker042580f2019-01-29 15:48:12 +010068 void onewayWait() override {
Roger Meier2be7f242012-05-10 09:01:45 +000069 concurrency::Guard g(mutex_);
70 log_->append(EventLog::ET_CALL_ONEWAY_WAIT, 0, 0);
71
72 blockUntilTriggered();
73 }
74
Sebastian Zenker042580f2019-01-29 15:48:12 +010075 void exceptionWait(const std::string& message) override {
Roger Meier2be7f242012-05-10 09:01:45 +000076 concurrency::Guard g(mutex_);
77 log_->append(EventLog::ET_CALL_EXCEPTION_WAIT, 0, 0);
78
79 blockUntilTriggered();
80
81 MyError e;
82 e.message = message;
83 throw e;
84 }
85
Sebastian Zenker042580f2019-01-29 15:48:12 +010086 void unexpectedExceptionWait(const std::string& message) override {
Roger Meier2be7f242012-05-10 09:01:45 +000087 concurrency::Guard g(mutex_);
88 log_->append(EventLog::ET_CALL_UNEXPECTED_EXCEPTION_WAIT, 0, 0);
89
90 blockUntilTriggered();
91
92 MyError e;
93 e.message = message;
94 throw e;
95 }
96
97 /**
98 * After prepareTriggeredCall() is invoked, calls to any of the *Wait()
99 * functions won't return until triggerPendingCalls() is invoked
100 *
101 * This has to be a separate function invoked by the main test thread
102 * in order to to avoid race conditions.
103 */
104 void prepareTriggeredCall() {
105 concurrency::Guard g(mutex_);
106 wait_ = true;
107 }
108
109 /**
110 * Wake up all calls waiting in blockUntilTriggered()
111 */
112 void triggerPendingCalls() {
113 concurrency::Guard g(mutex_);
114 wait_ = false;
115 triggerMonitor.notifyAll();
116 }
117
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100118protected:
Roger Meier2be7f242012-05-10 09:01:45 +0000119 /**
120 * blockUntilTriggered() won't return until triggerPendingCalls() is invoked
121 * in another thread.
122 *
123 * This should only be called when already holding mutex_.
124 */
125 void blockUntilTriggered() {
126 while (wait_) {
127 triggerMonitor.waitForever();
128 }
129
130 // Log an event when we return
131 log_->append(EventLog::ET_WAIT_RETURN, 0, 0);
132 }
133
134 concurrency::Mutex mutex_;
135 concurrency::Monitor triggerMonitor;
136 int32_t generation_;
137 bool wait_;
138 std::vector<std::string> strings_;
cyy316723a2019-01-05 16:35:14 +0800139 std::shared_ptr<EventLog> log_;
Roger Meier2be7f242012-05-10 09:01:45 +0000140};
141
ben-craigfae08e72015-07-15 11:34:47 -0500142#ifdef _WIN32
143 #pragma warning( push )
144 #pragma warning (disable : 4250 ) //inheriting methods via dominance
Jens Geyerb141fd02015-07-24 00:07:02 +0200145#endif
ben-craigfae08e72015-07-15 11:34:47 -0500146
Roger Meier2be7f242012-05-10 09:01:45 +0000147class ChildHandler : public ParentHandler, virtual public ChildServiceIf {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100148public:
cyy316723a2019-01-05 16:35:14 +0800149 ChildHandler(const std::shared_ptr<EventLog>& log) : ParentHandler(log), value_(0) {}
Roger Meier2be7f242012-05-10 09:01:45 +0000150
Sebastian Zenker042580f2019-01-29 15:48:12 +0100151 int32_t setValue(const int32_t value) override {
Roger Meier2be7f242012-05-10 09:01:45 +0000152 concurrency::Guard g(mutex_);
153 log_->append(EventLog::ET_CALL_SET_VALUE, 0, 0);
154
155 int32_t oldValue = value_;
156 value_ = value;
157 return oldValue;
158 }
159
Sebastian Zenker042580f2019-01-29 15:48:12 +0100160 int32_t getValue() override {
Roger Meier2be7f242012-05-10 09:01:45 +0000161 concurrency::Guard g(mutex_);
162 log_->append(EventLog::ET_CALL_GET_VALUE, 0, 0);
163
164 return value_;
165 }
166
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100167protected:
Roger Meier2be7f242012-05-10 09:01:45 +0000168 int32_t value_;
169};
170
ben-craigfae08e72015-07-15 11:34:47 -0500171#ifdef _WIN32
172 #pragma warning( pop )
173#endif
174
Roger Meier2be7f242012-05-10 09:01:45 +0000175struct ConnContext {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100176public:
cyy316723a2019-01-05 16:35:14 +0800177 ConnContext(std::shared_ptr<protocol::TProtocol> in,
178 std::shared_ptr<protocol::TProtocol> out,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100179 uint32_t id)
180 : input(in), output(out), id(id) {}
Roger Meier2be7f242012-05-10 09:01:45 +0000181
cyy316723a2019-01-05 16:35:14 +0800182 std::shared_ptr<protocol::TProtocol> input;
183 std::shared_ptr<protocol::TProtocol> output;
Roger Meier2be7f242012-05-10 09:01:45 +0000184 uint32_t id;
185};
186
187struct CallContext {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100188public:
189 CallContext(ConnContext* context, uint32_t id, const std::string& name)
190 : connContext(context), name(name), id(id) {}
Roger Meier2be7f242012-05-10 09:01:45 +0000191
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100192 ConnContext* connContext;
Roger Meier2be7f242012-05-10 09:01:45 +0000193 std::string name;
194 uint32_t id;
195};
196
197class ServerEventHandler : public server::TServerEventHandler {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100198public:
cyy316723a2019-01-05 16:35:14 +0800199 ServerEventHandler(const std::shared_ptr<EventLog>& log) : nextId_(1), log_(log) {}
Roger Meier2be7f242012-05-10 09:01:45 +0000200
Sebastian Zenker042580f2019-01-29 15:48:12 +0100201 void preServe() override {}
Roger Meier2be7f242012-05-10 09:01:45 +0000202
Sebastian Zenker042580f2019-01-29 15:48:12 +0100203 void* createContext(std::shared_ptr<protocol::TProtocol> input,
204 std::shared_ptr<protocol::TProtocol> output) override {
Roger Meier2be7f242012-05-10 09:01:45 +0000205 ConnContext* context = new ConnContext(input, output, nextId_);
206 ++nextId_;
207 log_->append(EventLog::ET_CONN_CREATED, context->id, 0);
208 return context;
209 }
210
Sebastian Zenker042580f2019-01-29 15:48:12 +0100211 void deleteContext(void* serverContext,
cyy316723a2019-01-05 16:35:14 +0800212 std::shared_ptr<protocol::TProtocol> input,
Sebastian Zenker042580f2019-01-29 15:48:12 +0100213 std::shared_ptr<protocol::TProtocol> output) override {
214 auto* context = reinterpret_cast<ConnContext*>(serverContext);
Roger Meier2be7f242012-05-10 09:01:45 +0000215
216 if (input != context->input) {
217 abort();
218 }
219 if (output != context->output) {
220 abort();
221 }
222
223 log_->append(EventLog::ET_CONN_DESTROYED, context->id, 0);
224
225 delete context;
226 }
227
Sebastian Zenker042580f2019-01-29 15:48:12 +0100228 void processContext(void* serverContext,
229 std::shared_ptr<transport::TTransport> transport) override {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100230// TODO: We currently don't test the behavior of the processContext()
231// calls. The various server implementations call processContext() at
232// slightly different times, and it is too annoying to try and account for
233// their various differences.
234//
235// TThreadedServer, TThreadPoolServer, and TSimpleServer usually wait until
236// they see the first byte of a request before calling processContext().
237// However, they don't wait for the first byte of the very first request,
238// and instead immediately call processContext() before any data is
239// received.
240//
241// TNonblockingServer always waits until receiving the full request before
242// calling processContext().
Roger Meier2be7f242012-05-10 09:01:45 +0000243#if 0
244 ConnContext* context = reinterpret_cast<ConnContext*>(serverContext);
245 log_->append(EventLog::ET_PROCESS, context->id, 0);
Konrad Grochowskib3f5ffc2014-11-06 19:32:59 +0100246#else
247 THRIFT_UNUSED_VARIABLE(serverContext);
248 THRIFT_UNUSED_VARIABLE(transport);
Roger Meier2be7f242012-05-10 09:01:45 +0000249#endif
250 }
251
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100252protected:
Roger Meier2be7f242012-05-10 09:01:45 +0000253 uint32_t nextId_;
cyy316723a2019-01-05 16:35:14 +0800254 std::shared_ptr<EventLog> log_;
Roger Meier2be7f242012-05-10 09:01:45 +0000255};
256
257class ProcessorEventHandler : public TProcessorEventHandler {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100258public:
cyy316723a2019-01-05 16:35:14 +0800259 ProcessorEventHandler(const std::shared_ptr<EventLog>& log) : nextId_(1), log_(log) {}
Roger Meier2be7f242012-05-10 09:01:45 +0000260
Sebastian Zenker042580f2019-01-29 15:48:12 +0100261 void* getContext(const char* fnName, void* serverContext) override {
262 auto* connContext = reinterpret_cast<ConnContext*>(serverContext);
Roger Meier2be7f242012-05-10 09:01:45 +0000263
264 CallContext* context = new CallContext(connContext, nextId_, fnName);
265 ++nextId_;
266
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100267 log_->append(EventLog::ET_CALL_STARTED, connContext->id, context->id, fnName);
Roger Meier2be7f242012-05-10 09:01:45 +0000268 return context;
269 }
270
Sebastian Zenker042580f2019-01-29 15:48:12 +0100271 void freeContext(void* ctx, const char* fnName) override {
272 auto* context = reinterpret_cast<CallContext*>(ctx);
Roger Meier2be7f242012-05-10 09:01:45 +0000273 checkName(context, fnName);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100274 log_->append(EventLog::ET_CALL_FINISHED, context->connContext->id, context->id, fnName);
Roger Meier2be7f242012-05-10 09:01:45 +0000275 delete context;
276 }
277
Sebastian Zenker042580f2019-01-29 15:48:12 +0100278 void preRead(void* ctx, const char* fnName) override {
279 auto* context = reinterpret_cast<CallContext*>(ctx);
Roger Meier2be7f242012-05-10 09:01:45 +0000280 checkName(context, fnName);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100281 log_->append(EventLog::ET_PRE_READ, context->connContext->id, context->id, fnName);
Roger Meier2be7f242012-05-10 09:01:45 +0000282 }
283
Sebastian Zenker042580f2019-01-29 15:48:12 +0100284 void postRead(void* ctx, const char* fnName, uint32_t bytes) override {
Konrad Grochowskib3f5ffc2014-11-06 19:32:59 +0100285 THRIFT_UNUSED_VARIABLE(bytes);
Sebastian Zenker042580f2019-01-29 15:48:12 +0100286 auto* context = reinterpret_cast<CallContext*>(ctx);
Roger Meier2be7f242012-05-10 09:01:45 +0000287 checkName(context, fnName);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100288 log_->append(EventLog::ET_POST_READ, context->connContext->id, context->id, fnName);
Roger Meier2be7f242012-05-10 09:01:45 +0000289 }
290
Sebastian Zenker042580f2019-01-29 15:48:12 +0100291 void preWrite(void* ctx, const char* fnName) override {
292 auto* context = reinterpret_cast<CallContext*>(ctx);
Roger Meier2be7f242012-05-10 09:01:45 +0000293 checkName(context, fnName);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100294 log_->append(EventLog::ET_PRE_WRITE, context->connContext->id, context->id, fnName);
Roger Meier2be7f242012-05-10 09:01:45 +0000295 }
296
Sebastian Zenker042580f2019-01-29 15:48:12 +0100297 void postWrite(void* ctx, const char* fnName, uint32_t bytes) override {
Konrad Grochowskib3f5ffc2014-11-06 19:32:59 +0100298 THRIFT_UNUSED_VARIABLE(bytes);
Sebastian Zenker042580f2019-01-29 15:48:12 +0100299 auto* context = reinterpret_cast<CallContext*>(ctx);
Roger Meier2be7f242012-05-10 09:01:45 +0000300 checkName(context, fnName);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100301 log_->append(EventLog::ET_POST_WRITE, context->connContext->id, context->id, fnName);
Roger Meier2be7f242012-05-10 09:01:45 +0000302 }
303
Sebastian Zenker042580f2019-01-29 15:48:12 +0100304 void asyncComplete(void* ctx, const char* fnName) override {
305 auto* context = reinterpret_cast<CallContext*>(ctx);
Roger Meier2be7f242012-05-10 09:01:45 +0000306 checkName(context, fnName);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100307 log_->append(EventLog::ET_ASYNC_COMPLETE, context->connContext->id, context->id, fnName);
Roger Meier2be7f242012-05-10 09:01:45 +0000308 }
309
Sebastian Zenker042580f2019-01-29 15:48:12 +0100310 void handlerError(void* ctx, const char* fnName) override {
311 auto* context = reinterpret_cast<CallContext*>(ctx);
Roger Meier2be7f242012-05-10 09:01:45 +0000312 checkName(context, fnName);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100313 log_->append(EventLog::ET_HANDLER_ERROR, context->connContext->id, context->id, fnName);
Roger Meier2be7f242012-05-10 09:01:45 +0000314 }
315
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100316protected:
Roger Meier2be7f242012-05-10 09:01:45 +0000317 void checkName(const CallContext* context, const char* fnName) {
318 // Note: we can't use BOOST_CHECK_EQUAL here, since the handler runs in a
319 // different thread from the test functions. Just abort if the names are
320 // different
321 if (context->name != fnName) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100322 fprintf(stderr,
323 "call context name mismatch: \"%s\" != \"%s\"\n",
324 context->name.c_str(),
325 fnName);
Roger Meier2be7f242012-05-10 09:01:45 +0000326 fflush(stderr);
327 abort();
328 }
329 }
330
331 uint32_t nextId_;
cyy316723a2019-01-05 16:35:14 +0800332 std::shared_ptr<EventLog> log_;
Roger Meier2be7f242012-05-10 09:01:45 +0000333};
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100334}
335}
336} // apache::thrift::test
Roger Meier2be7f242012-05-10 09:01:45 +0000337
338#endif // _THRIFT_PROCESSOR_TEST_HANDLERS_H_