Fix IPCSuite/WriteTimeout
[platform/core/security/vasum.git] / tests / unit_tests / ipc / ut-ipc.cpp
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Jan Olszak <j.olszak@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  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, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18
19
20 /**
21  * @file
22  * @author  Jan Olszak (j.olszak@samsung.com)
23  * @brief   Tests of the IPC
24  */
25
26 // TODO: Test connection limit
27 // TODO: Refactor tests - function for setting up env
28
29
30 #include "config.hpp"
31 #include "ut.hpp"
32
33 #include "ipc/service.hpp"
34 #include "ipc/client.hpp"
35 #include "ipc/types.hpp"
36 #include "ipc/result.hpp"
37 #include "ipc/epoll/thread-dispatcher.hpp"
38 #include "ipc/epoll/glib-dispatcher.hpp"
39 #include "utils/glib-loop.hpp"
40 #include "utils/latch.hpp"
41 #include "utils/value-latch.hpp"
42 #include "utils/scoped-dir.hpp"
43
44 #include "config/fields.hpp"
45 #include "logger/logger.hpp"
46
47 #include <atomic>
48 #include <string>
49 #include <thread>
50 #include <chrono>
51 #include <utility>
52 #include <future>
53
54 using namespace ipc;
55 using namespace epoll;
56 using namespace utils;
57 using namespace std::placeholders;
58
59 // Timeout for sending one message
60 const int TIMEOUT = 1000 /*ms*/;
61
62 // Time that won't cause "TIMEOUT" methods to throw
63 const int SHORT_OPERATION_TIME = TIMEOUT / 100;
64
65 // Time that will cause "TIMEOUT" methods to throw
66 const int LONG_OPERATION_TIME = 1000 + TIMEOUT;
67
68 const std::string TEST_DIR = "/tmp/ut-ipc";
69 const std::string SOCKET_PATH = TEST_DIR + "/test.socket";
70
71 struct FixtureBase {
72     ScopedDir mTestPathGuard;
73
74     FixtureBase()
75         : mTestPathGuard(TEST_DIR)
76     {
77     }
78 };
79
80 struct ThreadedFixture : FixtureBase {
81     ThreadDispatcher dispatcher;
82
83     EventPoll& getPoll() { return dispatcher.getPoll(); }
84 };
85
86 struct GlibFixture : FixtureBase {
87     ScopedGlibLoop glibLoop;
88     GlibDispatcher dispatcher;
89
90     EventPoll& getPoll() { return dispatcher.getPoll(); }
91 };
92
93 struct SendData {
94     int intVal;
95     SendData(int i): intVal(i) {}
96
97     CONFIG_REGISTER
98     (
99         intVal
100     )
101 };
102
103 struct RecvData {
104     int intVal;
105     RecvData(): intVal(-1) {}
106
107     CONFIG_REGISTER
108     (
109         intVal
110     )
111 };
112
113 struct LongSendData {
114     LongSendData(int i, int waitTime): mSendData(i), mWaitTime(waitTime), intVal(i) {}
115
116     template<typename Visitor>
117     void accept(Visitor visitor)
118     {
119         std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTime));
120         mSendData.accept(visitor);
121     }
122     template<typename Visitor>
123     void accept(Visitor visitor) const
124     {
125         std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTime));
126         mSendData.accept(visitor);
127     }
128
129     SendData mSendData;
130     int mWaitTime;
131     int intVal;
132 };
133
134 struct EmptyData {
135     CONFIG_REGISTER_EMPTY
136 };
137
138 struct ThrowOnAcceptData {
139     template<typename Visitor>
140     void accept(Visitor)
141     {
142         throw std::runtime_error("intentional failure in accept");
143     }
144     template<typename Visitor>
145     void accept(Visitor) const
146     {
147         throw std::runtime_error("intentional failure in accept const");
148     }
149 };
150
151 void returnEmptyCallback(const PeerID,
152                          std::shared_ptr<EmptyData>&,
153                          MethodResult::Pointer methodResult)
154 {
155     methodResult->setVoid();
156 }
157
158 void returnDataCallback(const PeerID,
159                         std::shared_ptr<RecvData>&,
160                         MethodResult::Pointer methodResult)
161 {
162     auto returnData = std::make_shared<SendData>(1);
163     methodResult->set(returnData);
164 }
165
166 void echoCallback(const PeerID,
167                   std::shared_ptr<RecvData>& data,
168                   MethodResult::Pointer methodResult)
169 {
170     auto returnData = std::make_shared<SendData>(data->intVal);
171     methodResult->set(returnData);
172 }
173
174 void longEchoCallback(const PeerID,
175                       std::shared_ptr<RecvData>& data,
176                       MethodResult::Pointer methodResult)
177 {
178     std::this_thread::sleep_for(std::chrono::milliseconds(LONG_OPERATION_TIME));
179     auto returnData = std::make_shared<SendData>(data->intVal);
180     methodResult->set(returnData);
181 }
182
183 void shortEchoCallback(const PeerID,
184                        std::shared_ptr<RecvData>& data,
185                        MethodResult::Pointer methodResult)
186 {
187     std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_OPERATION_TIME));
188     auto returnData = std::make_shared<SendData>(data->intVal);
189     methodResult->set(returnData);
190 }
191
192 PeerID connect(Service& s, Client& c)
193 {
194     // Connects the Client to the Service and returns Clients PeerID
195     ValueLatch<PeerID> peerIDLatch;
196     auto newPeerCallback = [&peerIDLatch](const PeerID newID, const FileDescriptor) {
197         peerIDLatch.set(newID);
198     };
199
200     s.setNewPeerCallback(newPeerCallback);
201
202     if (!s.isStarted()) {
203         s.start();
204     }
205
206     c.start();
207
208     PeerID peerID = peerIDLatch.get(TIMEOUT);
209     s.setNewPeerCallback(nullptr);
210     BOOST_REQUIRE_NE(peerID, 0);
211     return peerID;
212 }
213
214 void testEcho(Client& c, const MethodID methodID)
215 {
216     std::shared_ptr<SendData> sentData(new SendData(34));
217     std::shared_ptr<RecvData> recvData = c.callSync<SendData, RecvData>(methodID, sentData, TIMEOUT);
218     BOOST_REQUIRE(recvData);
219     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
220 }
221
222 void testEcho(Service& s, const MethodID methodID, const PeerID peerID)
223 {
224     std::shared_ptr<SendData> sentData(new SendData(56));
225     std::shared_ptr<RecvData> recvData = s.callSync<SendData, RecvData>(methodID, peerID, sentData, TIMEOUT);
226     BOOST_REQUIRE(recvData);
227     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
228 }
229
230 BOOST_AUTO_TEST_SUITE(IPCSuite)
231
232 MULTI_FIXTURE_TEST_CASE(ConstructorDestructor, F, ThreadedFixture, GlibFixture)
233 {
234     Service s(F::getPoll(), SOCKET_PATH);
235     Client c(F::getPoll(), SOCKET_PATH);
236 }
237
238 MULTI_FIXTURE_TEST_CASE(ServiceAddRemoveMethod, F, ThreadedFixture, GlibFixture)
239 {
240     Service s(F::getPoll(), SOCKET_PATH);
241     s.setMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
242     s.setMethodHandler<SendData, RecvData>(1, returnDataCallback);
243
244     s.start();
245
246     s.setMethodHandler<SendData, RecvData>(1, echoCallback);
247     s.setMethodHandler<SendData, RecvData>(2, returnDataCallback);
248
249     Client c(F::getPoll(), SOCKET_PATH);
250     connect(s, c);
251     testEcho(c, 1);
252
253     s.removeMethod(1);
254     s.removeMethod(2);
255
256     BOOST_CHECK_THROW(testEcho(c, 2), IPCException);
257 }
258
259 MULTI_FIXTURE_TEST_CASE(ClientAddRemoveMethod, F, ThreadedFixture, GlibFixture)
260 {
261     Service s(F::getPoll(), SOCKET_PATH);
262     Client c(F::getPoll(), SOCKET_PATH);
263     c.setMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
264     c.setMethodHandler<SendData, RecvData>(1, returnDataCallback);
265
266     PeerID peerID = connect(s, c);
267
268     c.setMethodHandler<SendData, RecvData>(1, echoCallback);
269     c.setMethodHandler<SendData, RecvData>(2, returnDataCallback);
270
271     testEcho(s, 1, peerID);
272
273     c.removeMethod(1);
274     c.removeMethod(2);
275
276     BOOST_CHECK_THROW(testEcho(s, 1, peerID), IPCException);
277 }
278
279 MULTI_FIXTURE_TEST_CASE(ServiceStartStop, F, ThreadedFixture, GlibFixture)
280 {
281     Service s(F::getPoll(), SOCKET_PATH);
282
283     s.setMethodHandler<SendData, RecvData>(1, returnDataCallback);
284
285     s.start();
286     s.stop();
287     s.start();
288     s.stop();
289
290     s.start();
291     s.start();
292 }
293
294 MULTI_FIXTURE_TEST_CASE(ClientStartStop, F, ThreadedFixture, GlibFixture)
295 {
296     Service s(F::getPoll(), SOCKET_PATH);
297     Client c(F::getPoll(), SOCKET_PATH);
298     c.setMethodHandler<SendData, RecvData>(1, returnDataCallback);
299
300     c.start();
301     c.stop();
302     c.start();
303     c.stop();
304
305     c.start();
306     c.start();
307
308     c.stop();
309     c.stop();
310 }
311
312 MULTI_FIXTURE_TEST_CASE(SyncClientToServiceEcho, F, ThreadedFixture, GlibFixture)
313 {
314     Service s(F::getPoll(), SOCKET_PATH);
315     s.setMethodHandler<SendData, RecvData>(1, echoCallback);
316     s.setMethodHandler<SendData, RecvData>(2, echoCallback);
317
318     Client c(F::getPoll(), SOCKET_PATH);
319     connect(s, c);
320
321     testEcho(c, 1);
322     testEcho(c, 2);
323 }
324
325 MULTI_FIXTURE_TEST_CASE(Restart, F, ThreadedFixture, GlibFixture)
326 {
327     Service s(F::getPoll(), SOCKET_PATH);
328     s.setMethodHandler<SendData, RecvData>(1, echoCallback);
329     s.start();
330     s.setMethodHandler<SendData, RecvData>(2, echoCallback);
331
332     Client c(F::getPoll(), SOCKET_PATH);
333     c.start();
334     testEcho(c, 1);
335     testEcho(c, 2);
336
337     c.stop();
338     c.start();
339
340     testEcho(c, 1);
341     testEcho(c, 2);
342
343     s.stop();
344     s.start();
345
346     BOOST_CHECK_THROW(testEcho(c, 2), IPCException);
347
348     c.stop();
349     c.start();
350
351     testEcho(c, 1);
352     testEcho(c, 2);
353 }
354
355 MULTI_FIXTURE_TEST_CASE(SyncServiceToClientEcho, F, ThreadedFixture, GlibFixture)
356 {
357     Service s(F::getPoll(), SOCKET_PATH);
358     Client c(F::getPoll(), SOCKET_PATH);
359     c.setMethodHandler<SendData, RecvData>(1, echoCallback);
360     PeerID peerID = connect(s, c);
361
362     std::shared_ptr<SendData> sentData(new SendData(56));
363     std::shared_ptr<RecvData> recvData = s.callSync<SendData, RecvData>(1, peerID, sentData);
364     BOOST_REQUIRE(recvData);
365     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
366 }
367
368 MULTI_FIXTURE_TEST_CASE(AsyncClientToServiceEcho, F, ThreadedFixture, GlibFixture)
369 {
370     std::shared_ptr<SendData> sentData(new SendData(34));
371     ValueLatch<std::shared_ptr<RecvData>> recvDataLatch;
372
373     // Setup Service and Client
374     Service s(F::getPoll(), SOCKET_PATH);
375     s.setMethodHandler<SendData, RecvData>(1, echoCallback);
376     s.start();
377     Client c(F::getPoll(), SOCKET_PATH);
378     c.start();
379
380     //Async call
381     auto dataBack = [&recvDataLatch](Result<RecvData> && r) {
382         recvDataLatch.set(r.get());
383     };
384     c.callAsync<SendData, RecvData>(1, sentData, dataBack);
385
386     // Wait for the response
387     std::shared_ptr<RecvData> recvData(recvDataLatch.get(TIMEOUT));
388     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
389 }
390
391 MULTI_FIXTURE_TEST_CASE(AsyncServiceToClientEcho, F, ThreadedFixture, GlibFixture)
392 {
393     std::shared_ptr<SendData> sentData(new SendData(56));
394     ValueLatch<std::shared_ptr<RecvData>> recvDataLatch;
395
396     Service s(F::getPoll(), SOCKET_PATH);
397     Client c(F::getPoll(), SOCKET_PATH);
398     c.setMethodHandler<SendData, RecvData>(1, echoCallback);
399     PeerID peerID = connect(s, c);
400
401     // Async call
402     auto dataBack = [&recvDataLatch](Result<RecvData> && r) {
403         recvDataLatch.set(r.get());
404     };
405
406     s.callAsync<SendData, RecvData>(1, peerID, sentData, dataBack);
407
408     // Wait for the response
409     std::shared_ptr<RecvData> recvData(recvDataLatch.get(TIMEOUT));
410     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
411 }
412
413
414 MULTI_FIXTURE_TEST_CASE(SyncTimeout, F, ThreadedFixture, GlibFixture)
415 {
416     Service s(F::getPoll(), SOCKET_PATH);
417     s.setMethodHandler<SendData, RecvData>(1, longEchoCallback);
418
419     Client c(F::getPoll(), SOCKET_PATH);
420     connect(s, c);
421
422     std::shared_ptr<SendData> sentData(new SendData(78));
423     BOOST_REQUIRE_THROW((c.callSync<SendData, RecvData>(1, sentData, TIMEOUT)), IPCException);
424 }
425
426 MULTI_FIXTURE_TEST_CASE(SerializationError, F, ThreadedFixture, GlibFixture)
427 {
428     Service s(F::getPoll(), SOCKET_PATH);
429     s.setMethodHandler<SendData, RecvData>(1, echoCallback);
430
431     Client c(F::getPoll(), SOCKET_PATH);
432     connect(s, c);
433
434     std::shared_ptr<ThrowOnAcceptData> throwingData(new ThrowOnAcceptData());
435
436     BOOST_CHECK_THROW((c.callSync<ThrowOnAcceptData, RecvData>(1, throwingData)), IPCSerializationException);
437
438 }
439
440 MULTI_FIXTURE_TEST_CASE(ParseError, F, ThreadedFixture, GlibFixture)
441 {
442     Service s(F::getPoll(), SOCKET_PATH);
443     s.setMethodHandler<SendData, RecvData>(1, echoCallback);
444     s.start();
445
446     Client c(F::getPoll(), SOCKET_PATH);
447     c.start();
448
449     std::shared_ptr<SendData> sentData(new SendData(78));
450     BOOST_CHECK_THROW((c.callSync<SendData, ThrowOnAcceptData>(1, sentData, 10000)), IPCParsingException);
451 }
452
453 MULTI_FIXTURE_TEST_CASE(DisconnectedPeerError, F, ThreadedFixture, GlibFixture)
454 {
455     ValueLatch<Result<RecvData>> retStatusLatch;
456
457     Service s(F::getPoll(), SOCKET_PATH);
458
459     auto method = [](const PeerID, std::shared_ptr<ThrowOnAcceptData>&, MethodResult::Pointer methodResult) {
460         auto resultData = std::make_shared<SendData>(1);
461         methodResult->set<SendData>(resultData);
462     };
463
464     // Method will throw during serialization and disconnect automatically
465     s.setMethodHandler<SendData, ThrowOnAcceptData>(1, method);
466     s.start();
467
468     Client c(F::getPoll(), SOCKET_PATH);
469     c.start();
470
471     auto dataBack = [&retStatusLatch](Result<RecvData> && r) {
472         retStatusLatch.set(std::move(r));
473     };
474
475     std::shared_ptr<SendData> sentData(new SendData(78));
476     c.callAsync<SendData, RecvData>(1, sentData, dataBack);
477
478     // Wait for the response
479     Result<RecvData> result = retStatusLatch.get(TIMEOUT);
480
481     // The disconnection might have happened:
482     // - after sending the message (PEER_DISCONNECTED)
483     // - during external serialization (SERIALIZATION_ERROR)
484     BOOST_CHECK_THROW(result.get(), IPCException);
485 }
486
487
488 MULTI_FIXTURE_TEST_CASE(ReadTimeout, F, ThreadedFixture, GlibFixture)
489 {
490     Service s(F::getPoll(), SOCKET_PATH);
491     auto longEchoCallback = [](const PeerID, std::shared_ptr<RecvData>& data, MethodResult::Pointer methodResult) {
492         auto resultData = std::make_shared<LongSendData>(data->intVal, LONG_OPERATION_TIME);
493         methodResult->set<LongSendData>(resultData);
494     };
495     s.setMethodHandler<LongSendData, RecvData>(1, longEchoCallback);
496
497     Client c(F::getPoll(), SOCKET_PATH);
498     connect(s, c);
499
500     // Test timeout on read
501     std::shared_ptr<SendData> sentData(new SendData(334));
502     BOOST_CHECK_THROW((c.callSync<SendData, RecvData>(1, sentData, TIMEOUT)), IPCException);
503 }
504
505
506 MULTI_FIXTURE_TEST_CASE(WriteTimeout, F, ThreadedFixture, GlibFixture)
507 {
508     Service s(F::getPoll(), SOCKET_PATH);
509     s.setMethodHandler<SendData, RecvData>(1, shortEchoCallback);
510     s.start();
511
512     Client c(F::getPoll(), SOCKET_PATH);
513     c.start();
514
515     // Test echo with a minimal timeout
516     std::shared_ptr<LongSendData> sentDataA(new LongSendData(34, SHORT_OPERATION_TIME));
517     std::shared_ptr<RecvData> recvData = c.callSync<LongSendData, RecvData>(1, sentDataA, TIMEOUT);
518     BOOST_REQUIRE(recvData);
519     BOOST_CHECK_EQUAL(recvData->intVal, sentDataA->intVal);
520
521     // Test timeout on write
522     std::shared_ptr<LongSendData> sentDataB(new LongSendData(34, LONG_OPERATION_TIME));
523     BOOST_CHECK_THROW((c.callSync<LongSendData, RecvData>(1, sentDataB, TIMEOUT)), IPCTimeoutException);
524 }
525
526
527 MULTI_FIXTURE_TEST_CASE(AddSignalInRuntime, F, ThreadedFixture, GlibFixture)
528 {
529     ValueLatch<std::shared_ptr<RecvData>> recvDataLatchA;
530     ValueLatch<std::shared_ptr<RecvData>> recvDataLatchB;
531
532     Service s(F::getPoll(), SOCKET_PATH);
533     Client c(F::getPoll(), SOCKET_PATH);
534     connect(s, c);
535
536     auto handlerA = [&recvDataLatchA](const PeerID, std::shared_ptr<RecvData>& data) {
537         recvDataLatchA.set(data);
538     };
539
540     auto handlerB = [&recvDataLatchB](const PeerID, std::shared_ptr<RecvData>& data) {
541         recvDataLatchB.set(data);
542     };
543
544     c.setSignalHandler<RecvData>(1, handlerA);
545     c.setSignalHandler<RecvData>(2, handlerB);
546
547     // Wait for the signals to propagate to the Service
548     std::this_thread::sleep_for(std::chrono::milliseconds(2 * TIMEOUT));
549
550     auto sendDataA = std::make_shared<SendData>(1);
551     auto sendDataB = std::make_shared<SendData>(2);
552     s.signal<SendData>(2, sendDataB);
553     s.signal<SendData>(1, sendDataA);
554
555     // Wait for the signals to arrive
556     std::shared_ptr<RecvData> recvDataA(recvDataLatchA.get(TIMEOUT));
557     std::shared_ptr<RecvData> recvDataB(recvDataLatchB.get(TIMEOUT));
558     BOOST_CHECK_EQUAL(recvDataA->intVal, sendDataA->intVal);
559     BOOST_CHECK_EQUAL(recvDataB->intVal, sendDataB->intVal);
560 }
561
562
563 MULTI_FIXTURE_TEST_CASE(AddSignalOffline, F, ThreadedFixture, GlibFixture)
564 {
565     ValueLatch<std::shared_ptr<RecvData>> recvDataLatchA;
566     ValueLatch<std::shared_ptr<RecvData>> recvDataLatchB;
567
568     Service s(F::getPoll(), SOCKET_PATH);
569     Client c(F::getPoll(), SOCKET_PATH);
570
571     auto handlerA = [&recvDataLatchA](const PeerID, std::shared_ptr<RecvData>& data) {
572         recvDataLatchA.set(data);
573     };
574
575     auto handlerB = [&recvDataLatchB](const PeerID, std::shared_ptr<RecvData>& data) {
576         recvDataLatchB.set(data);
577     };
578
579     c.setSignalHandler<RecvData>(1, handlerA);
580     c.setSignalHandler<RecvData>(2, handlerB);
581
582     connect(s, c);
583
584     // Wait for the information about the signals to propagate
585     std::this_thread::sleep_for(std::chrono::milliseconds(TIMEOUT));
586
587     auto sendDataA = std::make_shared<SendData>(1);
588     auto sendDataB = std::make_shared<SendData>(2);
589     s.signal<SendData>(2, sendDataB);
590     s.signal<SendData>(1, sendDataA);
591
592     // Wait for the signals to arrive
593     std::shared_ptr<RecvData> recvDataA(recvDataLatchA.get(TIMEOUT));
594     std::shared_ptr<RecvData> recvDataB(recvDataLatchB.get(TIMEOUT));
595     BOOST_CHECK_EQUAL(recvDataA->intVal, sendDataA->intVal);
596     BOOST_CHECK_EQUAL(recvDataB->intVal, sendDataB->intVal);
597 }
598
599 MULTI_FIXTURE_TEST_CASE(UsersError, F, ThreadedFixture, GlibFixture)
600 {
601     const int TEST_ERROR_CODE = -234;
602     const std::string TEST_ERROR_MESSAGE = "Ay, caramba!";
603
604     Service s(F::getPoll(), SOCKET_PATH);
605     Client c(F::getPoll(), SOCKET_PATH);
606     auto clientID = connect(s, c);
607
608     auto throwingMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>&, MethodResult::Pointer) {
609         throw IPCUserException(TEST_ERROR_CODE, TEST_ERROR_MESSAGE);
610     };
611
612     auto sendErrorMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>&, MethodResult::Pointer methodResult) {
613         methodResult->setError(TEST_ERROR_CODE, TEST_ERROR_MESSAGE);
614     };
615
616     s.setMethodHandler<SendData, RecvData>(1, throwingMethodHandler);
617     s.setMethodHandler<SendData, RecvData>(2, sendErrorMethodHandler);
618     c.setMethodHandler<SendData, RecvData>(1, throwingMethodHandler);
619     c.setMethodHandler<SendData, RecvData>(2, sendErrorMethodHandler);
620
621     std::shared_ptr<SendData> sentData(new SendData(78));
622
623     auto hasProperData = [&](const IPCUserException & e) {
624         return e.getCode() == TEST_ERROR_CODE && e.what() == TEST_ERROR_MESSAGE;
625     };
626
627     BOOST_CHECK_EXCEPTION((c.callSync<SendData, RecvData>(1, sentData, TIMEOUT)), IPCUserException, hasProperData);
628     BOOST_CHECK_EXCEPTION((s.callSync<SendData, RecvData>(1, clientID, sentData, TIMEOUT)), IPCUserException, hasProperData);
629     BOOST_CHECK_EXCEPTION((c.callSync<SendData, RecvData>(2, sentData, TIMEOUT)), IPCUserException, hasProperData);
630     BOOST_CHECK_EXCEPTION((s.callSync<SendData, RecvData>(2, clientID, sentData, TIMEOUT)), IPCUserException, hasProperData);
631 }
632
633 MULTI_FIXTURE_TEST_CASE(AsyncResult, F, ThreadedFixture, GlibFixture)
634 {
635     const int TEST_ERROR_CODE = -567;
636     const std::string TEST_ERROR_MESSAGE = "Ooo jooo!";
637
638     Service s(F::getPoll(), SOCKET_PATH);
639     Client c(F::getPoll(), SOCKET_PATH);
640     auto clientID = connect(s, c);
641
642     auto errorMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>&, MethodResult::Pointer methodResult) {
643         std::async(std::launch::async, [&, methodResult] {
644             std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_OPERATION_TIME));
645             methodResult->setError(TEST_ERROR_CODE, TEST_ERROR_MESSAGE);
646         });
647     };
648
649     auto voidMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>&, MethodResult::Pointer methodResult) {
650         std::async(std::launch::async, [methodResult] {
651             std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_OPERATION_TIME));
652             methodResult->setVoid();
653         });
654     };
655
656     auto dataMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>& data, MethodResult::Pointer methodResult) {
657         std::async(std::launch::async, [data, methodResult] {
658             std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_OPERATION_TIME));
659             methodResult->set(data);
660         });
661     };
662
663     s.setMethodHandler<SendData, RecvData>(1, errorMethodHandler);
664     s.setMethodHandler<EmptyData, RecvData>(2, voidMethodHandler);
665     s.setMethodHandler<SendData, RecvData>(3, dataMethodHandler);
666     c.setMethodHandler<SendData, RecvData>(1, errorMethodHandler);
667     c.setMethodHandler<EmptyData, RecvData>(2, voidMethodHandler);
668     c.setMethodHandler<SendData, RecvData>(3, dataMethodHandler);
669
670     std::shared_ptr<SendData> sentData(new SendData(90));
671
672     auto hasProperData = [&](const IPCUserException & e) {
673         return e.getCode() == TEST_ERROR_CODE && e.what() == TEST_ERROR_MESSAGE;
674     };
675
676     BOOST_CHECK_EXCEPTION((s.callSync<SendData, RecvData>(1, clientID, sentData, TIMEOUT)), IPCUserException, hasProperData);
677     BOOST_CHECK_EXCEPTION((c.callSync<SendData, RecvData>(1, sentData, TIMEOUT)), IPCUserException, hasProperData);
678
679     BOOST_CHECK_NO_THROW((s.callSync<SendData, EmptyData>(2, clientID, sentData, TIMEOUT)));
680     BOOST_CHECK_NO_THROW((c.callSync<SendData, EmptyData>(2, sentData, TIMEOUT)));
681
682     std::shared_ptr<RecvData> recvData;
683     recvData = s.callSync<SendData, RecvData>(3, clientID, sentData, TIMEOUT);
684     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
685     recvData = c.callSync<SendData, RecvData>(3, sentData, TIMEOUT);
686     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
687 }
688
689 MULTI_FIXTURE_TEST_CASE(MixOperations, F, ThreadedFixture, GlibFixture)
690 {
691     utils::Latch l;
692
693     auto signalHandler = [&l](const PeerID, std::shared_ptr<RecvData>&) {
694         l.set();
695     };
696
697     Service s(F::getPoll(), SOCKET_PATH);
698     s.setMethodHandler<SendData, RecvData>(1, echoCallback);
699
700     Client c(F::getPoll(), SOCKET_PATH);
701     s.setSignalHandler<RecvData>(2, signalHandler);
702
703     connect(s, c);
704
705     testEcho(c, 1);
706
707     auto data = std::make_shared<SendData>(1);
708     c.signal<SendData>(2, data);
709
710     BOOST_CHECK(l.wait(TIMEOUT));
711 }
712
713 // MULTI_FIXTURE_TEST_CASE(ConnectionLimit, F, ThreadedFixture, GlibFixture)
714 // {
715 //     unsigned oldLimit = ipc::getMaxFDNumber();
716 //     ipc::setMaxFDNumber(50);
717
718 //     // Setup Service and many Clients
719 //     Service s(F::getPoll(), SOCKET_PATH);
720 //     s.setMethodHandler<SendData, RecvData>(1, echoCallback);
721 //     s.start();
722
723 //     std::list<Client> clients;
724 //     for (int i = 0; i < 100; ++i) {
725 //         try {
726 //             clients.push_back(Client(F::getPoll(), SOCKET_PATH));
727 //             clients.back().start();
728 //         } catch (...) {}
729 //     }
730
731 //     unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
732 //     std::mt19937 generator(seed);
733 //     for (auto it = clients.begin(); it != clients.end(); ++it) {
734 //         try {
735 //             std::shared_ptr<SendData> sentData(new SendData(generator()));
736 //             std::shared_ptr<RecvData> recvData = it->callSync<SendData, RecvData>(1, sentData);
737 //             BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
738 //         } catch (...) {}
739 //     }
740
741 //     ipc::setMaxFDNumber(oldLimit);
742 // }
743
744
745
746 BOOST_AUTO_TEST_SUITE_END()