1 /*
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 
20 /*
21  * This file contains tests that ensure TProcessorEventHandler and
22  * TServerEventHandler are invoked properly by the various server
23  * implementations.
24  */
25 
26 #include <boost/test/unit_test.hpp>
27 
28 #include <thrift/concurrency/PlatformThreadFactory.h>
29 #include <thrift/concurrency/Monitor.h>
30 #include <thrift/protocol/TBinaryProtocol.h>
31 #include <thrift/server/TThreadedServer.h>
32 #include <thrift/server/TThreadPoolServer.h>
33 #include <thrift/server/TNonblockingServer.h>
34 #include <thrift/server/TSimpleServer.h>
35 #include <thrift/transport/TSocket.h>
36 #include <thrift/transport/TNonblockingServerSocket.h>
37 
38 #include "EventLog.h"
39 #include "ServerThread.h"
40 #include "Handlers.h"
41 #include "gen-cpp/ChildService.h"
42 
43 using namespace apache::thrift;
44 using namespace apache::thrift::concurrency;
45 using namespace apache::thrift::protocol;
46 using namespace apache::thrift::server;
47 using namespace apache::thrift::test;
48 using namespace apache::thrift::transport;
49 using std::string;
50 using std::vector;
51 
52 /*
53  * Traits classes that encapsulate how to create various types of servers.
54  */
55 
56 class TSimpleServerTraits {
57 public:
58   typedef TSimpleServer ServerType;
59 
createServer(const stdcxx::shared_ptr<TProcessor> & processor,uint16_t port,const stdcxx::shared_ptr<TTransportFactory> & transportFactory,const stdcxx::shared_ptr<TProtocolFactory> & protocolFactory)60   stdcxx::shared_ptr<TSimpleServer> createServer(
61       const stdcxx::shared_ptr<TProcessor>& processor,
62       uint16_t port,
63       const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
64       const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
65     stdcxx::shared_ptr<TServerSocket> socket(new TServerSocket(port));
66     return stdcxx::shared_ptr<TSimpleServer>(
67         new TSimpleServer(processor, socket, transportFactory, protocolFactory));
68   }
69 };
70 
71 class TThreadedServerTraits {
72 public:
73   typedef TThreadedServer ServerType;
74 
createServer(const stdcxx::shared_ptr<TProcessor> & processor,uint16_t port,const stdcxx::shared_ptr<TTransportFactory> & transportFactory,const stdcxx::shared_ptr<TProtocolFactory> & protocolFactory)75   stdcxx::shared_ptr<TThreadedServer> createServer(
76       const stdcxx::shared_ptr<TProcessor>& processor,
77       uint16_t port,
78       const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
79       const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
80     stdcxx::shared_ptr<TServerSocket> socket(new TServerSocket(port));
81     return stdcxx::shared_ptr<TThreadedServer>(
82         new TThreadedServer(processor, socket, transportFactory, protocolFactory));
83   }
84 };
85 
86 class TThreadPoolServerTraits {
87 public:
88   typedef TThreadPoolServer ServerType;
89 
createServer(const stdcxx::shared_ptr<TProcessor> & processor,uint16_t port,const stdcxx::shared_ptr<TTransportFactory> & transportFactory,const stdcxx::shared_ptr<TProtocolFactory> & protocolFactory)90   stdcxx::shared_ptr<TThreadPoolServer> createServer(
91       const stdcxx::shared_ptr<TProcessor>& processor,
92       uint16_t port,
93       const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
94       const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
95     stdcxx::shared_ptr<TServerSocket> socket(new TServerSocket(port));
96 
97     stdcxx::shared_ptr<PlatformThreadFactory> threadFactory(new PlatformThreadFactory);
98     stdcxx::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(8);
99     threadManager->threadFactory(threadFactory);
100     threadManager->start();
101 
102     return stdcxx::shared_ptr<TThreadPoolServer>(
103         new TThreadPoolServer(processor, socket, transportFactory, protocolFactory, threadManager));
104   }
105 };
106 
107 class TNonblockingServerTraits {
108 public:
109   typedef TNonblockingServer ServerType;
110 
createServer(const stdcxx::shared_ptr<TProcessor> & processor,uint16_t port,const stdcxx::shared_ptr<TTransportFactory> & transportFactory,const stdcxx::shared_ptr<TProtocolFactory> & protocolFactory)111   stdcxx::shared_ptr<TNonblockingServer> createServer(
112       const stdcxx::shared_ptr<TProcessor>& processor,
113       uint16_t port,
114       const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
115       const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
116     // TNonblockingServer automatically uses TFramedTransport.
117     // Raise an exception if the supplied transport factory is not a
118     // TFramedTransportFactory
119     TFramedTransportFactory* framedFactory
120         = dynamic_cast<TFramedTransportFactory*>(transportFactory.get());
121     if (framedFactory == NULL) {
122       throw TException("TNonblockingServer must use TFramedTransport");
123     }
124 
125     stdcxx::shared_ptr<TNonblockingServerSocket> socket(new TNonblockingServerSocket(port));
126     stdcxx::shared_ptr<PlatformThreadFactory> threadFactory(new PlatformThreadFactory);
127     stdcxx::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(8);
128     threadManager->threadFactory(threadFactory);
129     threadManager->start();
130 
131     return stdcxx::shared_ptr<TNonblockingServer>(
132         new TNonblockingServer(processor, protocolFactory, socket, threadManager));
133   }
134 };
135 
136 class TNonblockingServerNoThreadsTraits {
137 public:
138   typedef TNonblockingServer ServerType;
139 
createServer(const stdcxx::shared_ptr<TProcessor> & processor,uint16_t port,const stdcxx::shared_ptr<TTransportFactory> & transportFactory,const stdcxx::shared_ptr<TProtocolFactory> & protocolFactory)140   stdcxx::shared_ptr<TNonblockingServer> createServer(
141       const stdcxx::shared_ptr<TProcessor>& processor,
142       uint16_t port,
143       const stdcxx::shared_ptr<TTransportFactory>& transportFactory,
144       const stdcxx::shared_ptr<TProtocolFactory>& protocolFactory) {
145     // TNonblockingServer automatically uses TFramedTransport.
146     // Raise an exception if the supplied transport factory is not a
147     // TFramedTransportFactory
148     TFramedTransportFactory* framedFactory
149         = dynamic_cast<TFramedTransportFactory*>(transportFactory.get());
150     if (framedFactory == NULL) {
151       throw TException("TNonblockingServer must use TFramedTransport");
152     }
153 
154     stdcxx::shared_ptr<TNonblockingServerSocket> socket(new TNonblockingServerSocket(port));
155     // Use a NULL ThreadManager
156     stdcxx::shared_ptr<ThreadManager> threadManager;
157     return stdcxx::shared_ptr<TNonblockingServer>(
158         new TNonblockingServer(processor, protocolFactory, socket, threadManager));
159   }
160 };
161 
162 /*
163  * Traits classes for controlling if we instantiate templated or generic
164  * protocol factories, processors, clients, etc.
165  *
166  * The goal is to allow the outer test code to select which server type is
167  * being tested, and whether or not we are testing the templated classes, or
168  * the generic classes.
169  *
170  * Each specific test case can control whether we create a child or parent
171  * server, and whether we use TFramedTransport or TBufferedTransport.
172  */
173 
174 class UntemplatedTraits {
175 public:
176   typedef TBinaryProtocolFactory ProtocolFactory;
177   typedef TBinaryProtocol Protocol;
178 
179   typedef ParentServiceProcessor ParentProcessor;
180   typedef ChildServiceProcessor ChildProcessor;
181   typedef ParentServiceClient ParentClient;
182   typedef ChildServiceClient ChildClient;
183 };
184 
185 class TemplatedTraits {
186 public:
187   typedef TBinaryProtocolFactoryT<TBufferBase> ProtocolFactory;
188   typedef TBinaryProtocolT<TBufferBase> Protocol;
189 
190   typedef ParentServiceProcessorT<Protocol> ParentProcessor;
191   typedef ChildServiceProcessorT<Protocol> ChildProcessor;
192   typedef ParentServiceClientT<Protocol> ParentClient;
193   typedef ChildServiceClientT<Protocol> ChildClient;
194 };
195 
196 template <typename TemplateTraits_>
197 class ParentServiceTraits {
198 public:
199   typedef typename TemplateTraits_::ParentProcessor Processor;
200   typedef typename TemplateTraits_::ParentClient Client;
201   typedef ParentHandler Handler;
202 
203   typedef typename TemplateTraits_::ProtocolFactory ProtocolFactory;
204   typedef typename TemplateTraits_::Protocol Protocol;
205 };
206 
207 template <typename TemplateTraits_>
208 class ChildServiceTraits {
209 public:
210   typedef typename TemplateTraits_::ChildProcessor Processor;
211   typedef typename TemplateTraits_::ChildClient Client;
212   typedef ChildHandler Handler;
213 
214   typedef typename TemplateTraits_::ProtocolFactory ProtocolFactory;
215   typedef typename TemplateTraits_::Protocol Protocol;
216 };
217 
218 // TODO: It would be nicer if the TTransportFactory types defined a typedef,
219 // to allow us to figure out the exact transport type without having to pass it
220 // in as a separate template parameter here.
221 //
222 // It would also be niec if they used covariant return types.  Unfortunately,
223 // since they return shared_ptr instead of raw pointers, covariant return types
224 // won't work.
225 template <typename ServerTraits_,
226           typename ServiceTraits_,
227           typename TransportFactory_ = TFramedTransportFactory,
228           typename Transport_ = TFramedTransport>
229 class ServiceState : public ServerState {
230 public:
231   typedef typename ServiceTraits_::Processor Processor;
232   typedef typename ServiceTraits_::Client Client;
233   typedef typename ServiceTraits_::Handler Handler;
234 
ServiceState()235   ServiceState()
236     : port_(0),
237       log_(new EventLog),
238       handler_(new Handler(log_)),
239       processor_(new Processor(handler_)),
240       transportFactory_(new TransportFactory_),
241       protocolFactory_(new typename ServiceTraits_::ProtocolFactory),
242       serverEventHandler_(new ServerEventHandler(log_)),
243       processorEventHandler_(new ProcessorEventHandler(log_)) {
244     processor_->setEventHandler(processorEventHandler_);
245   }
246 
createServer(uint16_t port)247   stdcxx::shared_ptr<TServer> createServer(uint16_t port) {
248     ServerTraits_ serverTraits;
249     return serverTraits.createServer(processor_, port, transportFactory_, protocolFactory_);
250   }
251 
getServerEventHandler()252   stdcxx::shared_ptr<TServerEventHandler> getServerEventHandler() { return serverEventHandler_; }
253 
bindSuccessful(uint16_t port)254   void bindSuccessful(uint16_t port) { port_ = port; }
255 
getPort() const256   uint16_t getPort() const { return port_; }
257 
getLog() const258   const stdcxx::shared_ptr<EventLog>& getLog() const { return log_; }
259 
getHandler() const260   const stdcxx::shared_ptr<Handler>& getHandler() const { return handler_; }
261 
createClient()262   stdcxx::shared_ptr<Client> createClient() {
263     typedef typename ServiceTraits_::Protocol Protocol;
264 
265     stdcxx::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port_));
266     stdcxx::shared_ptr<Transport_> transport(new Transport_(socket));
267     stdcxx::shared_ptr<Protocol> protocol(new Protocol(transport));
268     transport->open();
269 
270     stdcxx::shared_ptr<Client> client(new Client(protocol));
271     return client;
272   }
273 
274 private:
275   uint16_t port_;
276   stdcxx::shared_ptr<EventLog> log_;
277   stdcxx::shared_ptr<Handler> handler_;
278   stdcxx::shared_ptr<Processor> processor_;
279   stdcxx::shared_ptr<TTransportFactory> transportFactory_;
280   stdcxx::shared_ptr<TProtocolFactory> protocolFactory_;
281   stdcxx::shared_ptr<TServerEventHandler> serverEventHandler_;
282   stdcxx::shared_ptr<TProcessorEventHandler> processorEventHandler_;
283 };
284 
285 /**
286  * Check that there are no more events in the log
287  */
checkNoEvents(const stdcxx::shared_ptr<EventLog> & log)288 void checkNoEvents(const stdcxx::shared_ptr<EventLog>& log) {
289   // Wait for an event with a very short timeout period.  We don't expect
290   // anything to be present, so we will normally wait for the full timeout.
291   // On the other hand, a non-zero timeout is nice since it does give a short
292   // window for events to arrive in case there is a problem.
293   Event event = log->waitForEvent(10);
294   BOOST_CHECK_EQUAL(EventLog::ET_LOG_END, event.type);
295 }
296 
297 /**
298  * Check for the events that should be logged when a new connection is created.
299  *
300  * Returns the connection ID allocated by the server.
301  */
checkNewConnEvents(const stdcxx::shared_ptr<EventLog> & log)302 uint32_t checkNewConnEvents(const stdcxx::shared_ptr<EventLog>& log) {
303   // Check for an ET_CONN_CREATED event
304   Event event = log->waitForEvent(2500);
305   BOOST_CHECK_EQUAL(EventLog::ET_CONN_CREATED, event.type);
306 
307   // Some servers call the processContext() hook immediately.
308   // Others (TNonblockingServer) only call it once a full request is received.
309   // We don't check for it yet, to allow either behavior.
310 
311   return event.connectionId;
312 }
313 
314 /**
315  * Check for the events that should be logged when a connection is closed.
316  */
checkCloseEvents(const stdcxx::shared_ptr<EventLog> & log,uint32_t connId)317 void checkCloseEvents(const stdcxx::shared_ptr<EventLog>& log, uint32_t connId) {
318   // Check for an ET_CONN_DESTROYED event
319   Event event = log->waitForEvent();
320   BOOST_CHECK_EQUAL(EventLog::ET_CONN_DESTROYED, event.type);
321   BOOST_CHECK_EQUAL(connId, event.connectionId);
322 
323   // Make sure there are no more events
324   checkNoEvents(log);
325 }
326 
327 /**
328  * Check for the events that should be logged when a call is received
329  * and the handler is invoked.
330  *
331  * It does not check for anything after the handler invocation.
332  *
333  * Returns the call ID allocated by the server.
334  */
checkCallHandlerEvents(const stdcxx::shared_ptr<EventLog> & log,uint32_t connId,EventType callType,const string & callName)335 uint32_t checkCallHandlerEvents(const stdcxx::shared_ptr<EventLog>& log,
336                                 uint32_t connId,
337                                 EventType callType,
338                                 const string& callName) {
339   // Call started
340   Event event = log->waitForEvent();
341   BOOST_CHECK_EQUAL(EventLog::ET_CALL_STARTED, event.type);
342   BOOST_CHECK_EQUAL(connId, event.connectionId);
343   BOOST_CHECK_EQUAL(callName, event.message);
344   uint32_t callId = event.callId;
345 
346   // Pre-read
347   event = log->waitForEvent();
348   BOOST_CHECK_EQUAL(EventLog::ET_PRE_READ, event.type);
349   BOOST_CHECK_EQUAL(connId, event.connectionId);
350   BOOST_CHECK_EQUAL(callId, event.callId);
351   BOOST_CHECK_EQUAL(callName, event.message);
352 
353   // Post-read
354   event = log->waitForEvent();
355   BOOST_CHECK_EQUAL(EventLog::ET_POST_READ, event.type);
356   BOOST_CHECK_EQUAL(connId, event.connectionId);
357   BOOST_CHECK_EQUAL(callId, event.callId);
358   BOOST_CHECK_EQUAL(callName, event.message);
359 
360   // Handler invocation
361   event = log->waitForEvent();
362   BOOST_CHECK_EQUAL(callType, event.type);
363   // The handler doesn't have any connection or call context,
364   // so the connectionId and callId in this event aren't valid
365 
366   return callId;
367 }
368 
369 /**
370  * Check for the events that should be after a handler returns.
371  */
checkCallPostHandlerEvents(const stdcxx::shared_ptr<EventLog> & log,uint32_t connId,uint32_t callId,const string & callName)372 void checkCallPostHandlerEvents(const stdcxx::shared_ptr<EventLog>& log,
373                                 uint32_t connId,
374                                 uint32_t callId,
375                                 const string& callName) {
376   // Pre-write
377   Event event = log->waitForEvent();
378   BOOST_CHECK_EQUAL(EventLog::ET_PRE_WRITE, event.type);
379   BOOST_CHECK_EQUAL(connId, event.connectionId);
380   BOOST_CHECK_EQUAL(callId, event.callId);
381   BOOST_CHECK_EQUAL(callName, event.message);
382 
383   // Post-write
384   event = log->waitForEvent();
385   BOOST_CHECK_EQUAL(EventLog::ET_POST_WRITE, event.type);
386   BOOST_CHECK_EQUAL(connId, event.connectionId);
387   BOOST_CHECK_EQUAL(callId, event.callId);
388   BOOST_CHECK_EQUAL(callName, event.message);
389 
390   // Call finished
391   event = log->waitForEvent();
392   BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type);
393   BOOST_CHECK_EQUAL(connId, event.connectionId);
394   BOOST_CHECK_EQUAL(callId, event.callId);
395   BOOST_CHECK_EQUAL(callName, event.message);
396 
397   // It is acceptable for servers to call processContext() again immediately
398   // to start waiting on the next request.  However, some servers wait before
399   // getting either a partial request or the full request before calling
400   // processContext().  We don't check for the next call to processContext()
401   // yet.
402 }
403 
404 /**
405  * Check for the events that should be logged when a call is made.
406  *
407  * This just calls checkCallHandlerEvents() followed by
408  * checkCallPostHandlerEvents().
409  *
410  * Returns the call ID allocated by the server.
411  */
checkCallEvents(const stdcxx::shared_ptr<EventLog> & log,uint32_t connId,EventType callType,const string & callName)412 uint32_t checkCallEvents(const stdcxx::shared_ptr<EventLog>& log,
413                          uint32_t connId,
414                          EventType callType,
415                          const string& callName) {
416   uint32_t callId = checkCallHandlerEvents(log, connId, callType, callName);
417   checkCallPostHandlerEvents(log, connId, callId, callName);
418 
419   return callId;
420 }
421 
422 /*
423  * Test functions
424  */
425 
426 template <typename State_>
testParentService(const stdcxx::shared_ptr<State_> & state)427 void testParentService(const stdcxx::shared_ptr<State_>& state) {
428   stdcxx::shared_ptr<typename State_::Client> client = state->createClient();
429 
430   int32_t gen = client->getGeneration();
431   int32_t newGen = client->incrementGeneration();
432   BOOST_CHECK_EQUAL(gen + 1, newGen);
433   newGen = client->getGeneration();
434   BOOST_CHECK_EQUAL(gen + 1, newGen);
435 
436   client->addString("foo");
437   client->addString("bar");
438   client->addString("asdf");
439 
440   vector<string> strings;
441   client->getStrings(strings);
442   BOOST_REQUIRE_EQUAL(3, strings.size());
443   BOOST_REQUIRE_EQUAL("foo", strings[0]);
444   BOOST_REQUIRE_EQUAL("bar", strings[1]);
445   BOOST_REQUIRE_EQUAL("asdf", strings[2]);
446 }
447 
448 template <typename State_>
testChildService(const stdcxx::shared_ptr<State_> & state)449 void testChildService(const stdcxx::shared_ptr<State_>& state) {
450   stdcxx::shared_ptr<typename State_::Client> client = state->createClient();
451 
452   // Test calling some of the parent methids via the a child client
453   int32_t gen = client->getGeneration();
454   int32_t newGen = client->incrementGeneration();
455   BOOST_CHECK_EQUAL(gen + 1, newGen);
456   newGen = client->getGeneration();
457   BOOST_CHECK_EQUAL(gen + 1, newGen);
458 
459   // Test some of the child methods
460   client->setValue(10);
461   BOOST_CHECK_EQUAL(10, client->getValue());
462   BOOST_CHECK_EQUAL(10, client->setValue(99));
463   BOOST_CHECK_EQUAL(99, client->getValue());
464 }
465 
466 template <typename ServerTraits, typename TemplateTraits>
testBasicService()467 void testBasicService() {
468   typedef ServiceState<ServerTraits, ParentServiceTraits<TemplateTraits> > State;
469 
470   // Start the server
471   stdcxx::shared_ptr<State> state(new State);
472   ServerThread serverThread(state, true);
473 
474   testParentService(state);
475 }
476 
477 template <typename ServerTraits, typename TemplateTraits>
testInheritedService()478 void testInheritedService() {
479   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
480 
481   // Start the server
482   stdcxx::shared_ptr<State> state(new State);
483   ServerThread serverThread(state, true);
484 
485   testParentService(state);
486   testChildService(state);
487 }
488 
489 /**
490  * Test to make sure that the TServerEventHandler and TProcessorEventHandler
491  * methods are invoked in the correct order with the actual events.
492  */
493 template <typename ServerTraits, typename TemplateTraits>
testEventSequencing()494 void testEventSequencing() {
495   // We use TBufferedTransport for this test, instead of TFramedTransport.
496   // This way the server will start processing data as soon as it is received,
497   // instead of waiting for the full request.  This is necessary so we can
498   // separate the preRead() and postRead() events.
499   typedef ServiceState<ServerTraits,
500                        ChildServiceTraits<TemplateTraits>,
501                        TBufferedTransportFactory,
502                        TBufferedTransport> State;
503 
504   // Start the server
505   stdcxx::shared_ptr<State> state(new State);
506   ServerThread serverThread(state, true);
507 
508   const stdcxx::shared_ptr<EventLog>& log = state->getLog();
509 
510   // Make sure we're at the end of the log
511   checkNoEvents(log);
512 
513   state->getHandler()->prepareTriggeredCall();
514 
515   // Make sure createContext() is called after a connection has been
516   // established.  We open a plain socket instead of creating a client.
517   stdcxx::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", state->getPort()));
518   socket->open();
519 
520   // Make sure the proper events occurred after a new connection
521   uint32_t connId = checkNewConnEvents(log);
522 
523   // Send a message header.  We manually construct the request so that we
524   // can test the timing for the preRead() call.
525   string requestName = "getDataWait";
526   string eventName = "ParentService.getDataWait";
527   int32_t seqid = int32_t(time(NULL));
528   TBinaryProtocol protocol(socket);
529   protocol.writeMessageBegin(requestName, T_CALL, seqid);
530   socket->flush();
531 
532   // Make sure we saw the call started and pre-read events
533   Event event = log->waitForEvent();
534   BOOST_CHECK_EQUAL(EventLog::ET_CALL_STARTED, event.type);
535   BOOST_CHECK_EQUAL(eventName, event.message);
536   BOOST_CHECK_EQUAL(connId, event.connectionId);
537   uint32_t callId = event.callId;
538 
539   event = log->waitForEvent();
540   BOOST_CHECK_EQUAL(EventLog::ET_PRE_READ, event.type);
541   BOOST_CHECK_EQUAL(eventName, event.message);
542   BOOST_CHECK_EQUAL(connId, event.connectionId);
543   BOOST_CHECK_EQUAL(callId, event.callId);
544 
545   // Make sure there are no new events
546   checkNoEvents(log);
547 
548   // Send the rest of the request
549   protocol.writeStructBegin("ParentService_getDataNotified_pargs");
550   protocol.writeFieldBegin("length", apache::thrift::protocol::T_I32, 1);
551   protocol.writeI32(8 * 1024 * 1024);
552   protocol.writeFieldEnd();
553   protocol.writeFieldStop();
554   protocol.writeStructEnd();
555   protocol.writeMessageEnd();
556   socket->writeEnd();
557   socket->flush();
558 
559   // We should then see postRead()
560   event = log->waitForEvent();
561   BOOST_CHECK_EQUAL(EventLog::ET_POST_READ, event.type);
562   BOOST_CHECK_EQUAL(eventName, event.message);
563   BOOST_CHECK_EQUAL(connId, event.connectionId);
564   BOOST_CHECK_EQUAL(callId, event.callId);
565 
566   // Then the handler should be invoked
567   event = log->waitForEvent();
568   BOOST_CHECK_EQUAL(EventLog::ET_CALL_GET_DATA_WAIT, event.type);
569 
570   // The handler won't respond until we notify it.
571   // Make sure there are no more events.
572   checkNoEvents(log);
573 
574   // Notify the handler that it should return
575   // We just use a global lock for now, since it is easiest
576   state->getHandler()->triggerPendingCalls();
577 
578   // The handler will log a separate event before it returns
579   event = log->waitForEvent();
580   BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type);
581 
582   // We should then see preWrite()
583   event = log->waitForEvent();
584   BOOST_CHECK_EQUAL(EventLog::ET_PRE_WRITE, event.type);
585   BOOST_CHECK_EQUAL(eventName, event.message);
586   BOOST_CHECK_EQUAL(connId, event.connectionId);
587   BOOST_CHECK_EQUAL(callId, event.callId);
588 
589   // We requested more data than can be buffered, and we aren't reading it,
590   // so the server shouldn't be able to finish its write yet.
591   // Make sure there are no more events.
592   checkNoEvents(log);
593 
594   // Read the response header
595   string responseName;
596   int32_t responseSeqid = 0;
597   apache::thrift::protocol::TMessageType responseType;
598   protocol.readMessageBegin(responseName, responseType, responseSeqid);
599   BOOST_CHECK_EQUAL(responseSeqid, seqid);
600   BOOST_CHECK_EQUAL(requestName, responseName);
601   BOOST_CHECK_EQUAL(responseType, T_REPLY);
602   // Read the body.  We just ignore it for now.
603   protocol.skip(T_STRUCT);
604 
605   // Now that we have read, the server should have finished sending the data
606   // and called the postWrite() handler
607   event = log->waitForEvent();
608   BOOST_CHECK_EQUAL(EventLog::ET_POST_WRITE, event.type);
609   BOOST_CHECK_EQUAL(eventName, event.message);
610   BOOST_CHECK_EQUAL(connId, event.connectionId);
611   BOOST_CHECK_EQUAL(callId, event.callId);
612 
613   // Call finished should be last
614   event = log->waitForEvent();
615   BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type);
616   BOOST_CHECK_EQUAL(eventName, event.message);
617   BOOST_CHECK_EQUAL(connId, event.connectionId);
618   BOOST_CHECK_EQUAL(callId, event.callId);
619 
620   // There should be no more events
621   checkNoEvents(log);
622 
623   // Close the connection, and make sure we get a connection destroyed event
624   socket->close();
625   event = log->waitForEvent();
626   BOOST_CHECK_EQUAL(EventLog::ET_CONN_DESTROYED, event.type);
627   BOOST_CHECK_EQUAL(connId, event.connectionId);
628 
629   // There should be no more events
630   checkNoEvents(log);
631 }
632 
633 template <typename ServerTraits, typename TemplateTraits>
testSeparateConnections()634 void testSeparateConnections() {
635   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
636 
637   // Start the server
638   stdcxx::shared_ptr<State> state(new State);
639   ServerThread serverThread(state, true);
640 
641   const stdcxx::shared_ptr<EventLog>& log = state->getLog();
642 
643   // Create a client
644   stdcxx::shared_ptr<typename State::Client> client1 = state->createClient();
645 
646   // Make sure the expected events were logged
647   uint32_t client1Id = checkNewConnEvents(log);
648 
649   // Create a second client
650   stdcxx::shared_ptr<typename State::Client> client2 = state->createClient();
651 
652   // Make sure the expected events were logged
653   uint32_t client2Id = checkNewConnEvents(log);
654 
655   // The two connections should have different IDs
656   BOOST_CHECK_NE(client1Id, client2Id);
657 
658   // Make a call, and check for the proper events
659   int32_t value = 5;
660   client1->setValue(value);
661   uint32_t call1
662       = checkCallEvents(log, client1Id, EventLog::ET_CALL_SET_VALUE, "ChildService.setValue");
663 
664   // Make a call with client2
665   int32_t v = client2->getValue();
666   BOOST_CHECK_EQUAL(value, v);
667   checkCallEvents(log, client2Id, EventLog::ET_CALL_GET_VALUE, "ChildService.getValue");
668 
669   // Make another call with client1
670   v = client1->getValue();
671   BOOST_CHECK_EQUAL(value, v);
672   uint32_t call2
673       = checkCallEvents(log, client1Id, EventLog::ET_CALL_GET_VALUE, "ChildService.getValue");
674   BOOST_CHECK_NE(call1, call2);
675 
676   // Close the second client, and check for the appropriate events
677   client2.reset();
678   checkCloseEvents(log, client2Id);
679 }
680 
681 template <typename ServerTraits, typename TemplateTraits>
testOnewayCall()682 void testOnewayCall() {
683   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
684 
685   // Start the server
686   stdcxx::shared_ptr<State> state(new State);
687   ServerThread serverThread(state, true);
688 
689   const stdcxx::shared_ptr<EventLog>& log = state->getLog();
690 
691   // Create a client
692   stdcxx::shared_ptr<typename State::Client> client = state->createClient();
693   uint32_t connId = checkNewConnEvents(log);
694 
695   // Make a oneway call
696   // It should return immediately, even though the server's handler
697   // won't return right away
698   state->getHandler()->prepareTriggeredCall();
699   client->onewayWait();
700   string callName = "ParentService.onewayWait";
701   uint32_t callId = checkCallHandlerEvents(log, connId, EventLog::ET_CALL_ONEWAY_WAIT, callName);
702 
703   // There shouldn't be any more events
704   checkNoEvents(log);
705 
706   // Trigger the handler to return
707   state->getHandler()->triggerPendingCalls();
708 
709   // The handler will log an ET_WAIT_RETURN event when it wakes up
710   Event event = log->waitForEvent();
711   BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type);
712 
713   // Now we should see the async complete event, then call finished
714   event = log->waitForEvent();
715   BOOST_CHECK_EQUAL(EventLog::ET_ASYNC_COMPLETE, event.type);
716   BOOST_CHECK_EQUAL(connId, event.connectionId);
717   BOOST_CHECK_EQUAL(callId, event.callId);
718   BOOST_CHECK_EQUAL(callName, event.message);
719 
720   event = log->waitForEvent();
721   BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type);
722   BOOST_CHECK_EQUAL(connId, event.connectionId);
723   BOOST_CHECK_EQUAL(callId, event.callId);
724   BOOST_CHECK_EQUAL(callName, event.message);
725 
726   // Destroy the client, and check for connection closed events
727   client.reset();
728   checkCloseEvents(log, connId);
729 
730   checkNoEvents(log);
731 }
732 
733 template <typename ServerTraits, typename TemplateTraits>
testExpectedError()734 void testExpectedError() {
735   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
736 
737   // Start the server
738   stdcxx::shared_ptr<State> state(new State);
739   ServerThread serverThread(state, true);
740 
741   const stdcxx::shared_ptr<EventLog>& log = state->getLog();
742 
743   // Create a client
744   stdcxx::shared_ptr<typename State::Client> client = state->createClient();
745   uint32_t connId = checkNewConnEvents(log);
746 
747   // Send the exceptionWait() call
748   state->getHandler()->prepareTriggeredCall();
749   string message = "test 1234 test";
750   client->send_exceptionWait(message);
751   string callName = "ParentService.exceptionWait";
752   uint32_t callId = checkCallHandlerEvents(log, connId, EventLog::ET_CALL_EXCEPTION_WAIT, callName);
753 
754   // There shouldn't be any more events
755   checkNoEvents(log);
756 
757   // Trigger the handler to return
758   state->getHandler()->triggerPendingCalls();
759 
760   // The handler will log an ET_WAIT_RETURN event when it wakes up
761   Event event = log->waitForEvent();
762   BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type);
763 
764   // Now receive the response
765   try {
766     client->recv_exceptionWait();
767     BOOST_FAIL("expected MyError to be thrown");
768   } catch (const MyError& e) {
769     BOOST_CHECK_EQUAL(message, e.message);
770     // Check if std::exception::what() is handled properly
771     size_t message_pos = string(e.what()).find("TException - service has thrown: MyError");
772     BOOST_CHECK_NE(message_pos, string::npos);
773   }
774 
775   // Now we should see the events for a normal call finish
776   checkCallPostHandlerEvents(log, connId, callId, callName);
777 
778   // There shouldn't be any more events
779   checkNoEvents(log);
780 
781   // Destroy the client, and check for connection closed events
782   client.reset();
783   checkCloseEvents(log, connId);
784 
785   checkNoEvents(log);
786 }
787 
788 template <typename ServerTraits, typename TemplateTraits>
testUnexpectedError()789 void testUnexpectedError() {
790   typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
791 
792   // Start the server
793   stdcxx::shared_ptr<State> state(new State);
794   ServerThread serverThread(state, true);
795 
796   const stdcxx::shared_ptr<EventLog>& log = state->getLog();
797 
798   // Create a client
799   stdcxx::shared_ptr<typename State::Client> client = state->createClient();
800   uint32_t connId = checkNewConnEvents(log);
801 
802   // Send the unexpectedExceptionWait() call
803   state->getHandler()->prepareTriggeredCall();
804   string message = "1234 test 5678";
805   client->send_unexpectedExceptionWait(message);
806   string callName = "ParentService.unexpectedExceptionWait";
807   uint32_t callId
808       = checkCallHandlerEvents(log, connId, EventLog::ET_CALL_UNEXPECTED_EXCEPTION_WAIT, callName);
809 
810   // There shouldn't be any more events
811   checkNoEvents(log);
812 
813   // Trigger the handler to return
814   state->getHandler()->triggerPendingCalls();
815 
816   // The handler will log an ET_WAIT_RETURN event when it wakes up
817   Event event = log->waitForEvent();
818   BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type);
819 
820   // Now receive the response
821   try {
822     client->recv_unexpectedExceptionWait();
823     BOOST_FAIL("expected TApplicationError to be thrown");
824   } catch (const TApplicationException&) {
825   }
826 
827   // Now we should see a handler error event
828   event = log->waitForEvent();
829   BOOST_CHECK_EQUAL(EventLog::ET_HANDLER_ERROR, event.type);
830   BOOST_CHECK_EQUAL(connId, event.connectionId);
831   BOOST_CHECK_EQUAL(callId, event.callId);
832   BOOST_CHECK_EQUAL(callName, event.message);
833 
834   // pre-write and post-write events aren't generated after a handler error
835   // (Even for non-oneway calls where a response is written.)
836   //
837   // A call finished event is logged when the call context is destroyed
838   event = log->waitForEvent();
839   BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type);
840   BOOST_CHECK_EQUAL(connId, event.connectionId);
841   BOOST_CHECK_EQUAL(callId, event.callId);
842   BOOST_CHECK_EQUAL(callName, event.message);
843 
844   // There shouldn't be any more events
845   checkNoEvents(log);
846 
847   // Destroy the client, and check for connection closed events
848   client.reset();
849   checkCloseEvents(log, connId);
850 
851   checkNoEvents(log);
852 }
853 
854 // Macro to define simple tests that can be used with all server types
855 #define DEFINE_SIMPLE_TESTS(Server, Template)                                                      \
856   BOOST_AUTO_TEST_CASE(Server##_##Template##_basicService) {                                       \
857     testBasicService<Server##Traits, Template##Traits>();                                          \
858   }                                                                                                \
859   BOOST_AUTO_TEST_CASE(Server##_##Template##_inheritedService) {                                   \
860     testInheritedService<Server##Traits, Template##Traits>();                                      \
861   }                                                                                                \
862   BOOST_AUTO_TEST_CASE(Server##_##Template##_oneway) {                                             \
863     testOnewayCall<Server##Traits, Template##Traits>();                                            \
864   }                                                                                                \
865   BOOST_AUTO_TEST_CASE(Server##_##Template##_exception) {                                          \
866     testExpectedError<Server##Traits, Template##Traits>();                                         \
867   }                                                                                                \
868   BOOST_AUTO_TEST_CASE(Server##_##Template##_unexpectedException) {                                \
869     testUnexpectedError<Server##Traits, Template##Traits>();                                       \
870   }
871 
872 // Tests that require the server to process multiple connections concurrently
873 // (i.e., not TSimpleServer)
874 #define DEFINE_CONCURRENT_SERVER_TESTS(Server, Template)                                           \
875   BOOST_AUTO_TEST_CASE(Server##_##Template##_separateConnections) {                                \
876     testSeparateConnections<Server##Traits, Template##Traits>();                                   \
877   }
878 
879 // The testEventSequencing() test manually generates a request for the server,
880 // and doesn't work with TFramedTransport.  Therefore we can't test it with
881 // TNonblockingServer.
882 #define DEFINE_NOFRAME_TESTS(Server, Template)                                                     \
883   BOOST_AUTO_TEST_CASE(Server##_##Template##_eventSequencing) {                                    \
884     testEventSequencing<Server##Traits, Template##Traits>();                                       \
885   }
886 
887 #define DEFINE_TNONBLOCKINGSERVER_TESTS(Server, Template)                                          \
888   DEFINE_SIMPLE_TESTS(Server, Template)                                                            \
889   DEFINE_CONCURRENT_SERVER_TESTS(Server, Template)
890 
891 #define DEFINE_ALL_SERVER_TESTS(Server, Template)                                                  \
892   DEFINE_SIMPLE_TESTS(Server, Template)                                                            \
893   DEFINE_CONCURRENT_SERVER_TESTS(Server, Template)                                                 \
894   DEFINE_NOFRAME_TESTS(Server, Template)
895 
DEFINE_ALL_SERVER_TESTS(TThreadedServer,Templated)896 DEFINE_ALL_SERVER_TESTS(TThreadedServer, Templated)
897 DEFINE_ALL_SERVER_TESTS(TThreadedServer, Untemplated)
898 DEFINE_ALL_SERVER_TESTS(TThreadPoolServer, Templated)
899 DEFINE_ALL_SERVER_TESTS(TThreadPoolServer, Untemplated)
900 
901 DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServer, Templated)
902 DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServer, Untemplated)
903 DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServerNoThreads, Templated)
904 DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServerNoThreads, Untemplated)
905 
906 DEFINE_SIMPLE_TESTS(TSimpleServer, Templated)
907 DEFINE_SIMPLE_TESTS(TSimpleServer, Untemplated)
908 DEFINE_NOFRAME_TESTS(TSimpleServer, Templated)
909 DEFINE_NOFRAME_TESTS(TSimpleServer, Untemplated)
910 
911 // TODO: We should test TEventServer in the future.
912 // For now, it is known not to work correctly with TProcessorEventHandler.
913 #ifdef BOOST_TEST_DYN_LINK
914 bool init_unit_test_suite() {
915   ::boost::unit_test::framework::master_test_suite().p_name.value = "ProcessorTest";
916   return true;
917 }
918 
main(int argc,char * argv[])919 int main( int argc, char* argv[] ) {
920   return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv);
921 }
922 #else
923 ::boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
924   THRIFT_UNUSED_VARIABLE(argc);
925   THRIFT_UNUSED_VARIABLE(argv);
926   ::boost::unit_test::framework::master_test_suite().p_name.value = "ProcessorTest";
927   return NULL;
928 }
929 #endif
930