IPC: External polling loop with a Client
[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 // TODO: Callback wrapper that waits till the callback is called
29
30
31 #include "config.hpp"
32 #include "ut.hpp"
33
34 #include "ipc/service.hpp"
35 #include "ipc/client.hpp"
36 #include "ipc/ipc-gsource.hpp"
37 #include "ipc/types.hpp"
38 #include "utils/glib-loop.hpp"
39
40 #include "config/fields.hpp"
41 #include "logger/logger.hpp"
42
43 #include <atomic>
44 #include <random>
45 #include <string>
46 #include <thread>
47 #include <chrono>
48 #include <utility>
49 #include <boost/filesystem.hpp>
50
51 using namespace vasum;
52 using namespace vasum::ipc;
53 using namespace vasum::utils;
54 using namespace std::placeholders;
55 namespace fs = boost::filesystem;
56
57 namespace {
58 struct Fixture {
59     std::string socketPath;
60
61     Fixture()
62         : socketPath(fs::unique_path("/tmp/ipc-%%%%.socket").string())
63     {
64     }
65     ~Fixture()
66     {
67         fs::remove(socketPath);
68     }
69 };
70
71 struct SendData {
72     int intVal;
73     SendData(int i = 0): intVal(i) {}
74
75     CONFIG_REGISTER
76     (
77         intVal
78     )
79 };
80
81 struct LongSendData {
82     LongSendData(int i = 0, int waitTime = 1000): mSendData(i), mWaitTime(waitTime), intVal(i) {}
83
84     template<typename Visitor>
85     void accept(Visitor visitor)
86     {
87         std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTime));
88         mSendData.accept(visitor);
89     }
90     template<typename Visitor>
91     void accept(Visitor visitor) const
92     {
93         std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTime));
94         mSendData.accept(visitor);
95     }
96
97     SendData mSendData;
98     int mWaitTime;
99     int intVal;
100 };
101
102 struct EmptyData {
103     CONFIG_REGISTER_EMPTY
104 };
105
106 struct ThrowOnAcceptData {
107     template<typename Visitor>
108     void accept(Visitor)
109     {
110         throw std::runtime_error("intentional failure in accept");
111     }
112     template<typename Visitor>
113     void accept(Visitor) const
114     {
115         throw std::runtime_error("intentional failure in accept const");
116     }
117 };
118
119 std::shared_ptr<EmptyData> returnEmptyCallback(const FileDescriptor, std::shared_ptr<EmptyData>&)
120 {
121     return std::shared_ptr<EmptyData>(new EmptyData());
122 }
123
124 std::shared_ptr<SendData> returnDataCallback(const FileDescriptor, std::shared_ptr<SendData>&)
125 {
126     return std::shared_ptr<SendData>(new SendData(1));
127 }
128
129 std::shared_ptr<SendData> echoCallback(const FileDescriptor, std::shared_ptr<SendData>& data)
130 {
131     return data;
132 }
133
134 std::shared_ptr<SendData> longEchoCallback(const FileDescriptor, std::shared_ptr<SendData>& data)
135 {
136     std::this_thread::sleep_for(std::chrono::seconds(1));
137     return data;
138 }
139
140 FileDescriptor connect(Service& s, Client& c)
141 {
142     // Connects the Client to the Service and returns Clients FileDescriptor
143     std::mutex mutex;
144     std::condition_variable cv;
145
146     FileDescriptor peerFD = 0;
147     auto newPeerCallback = [&cv, &peerFD, &mutex](const FileDescriptor newFD) {
148         std::unique_lock<std::mutex> lock(mutex);
149         peerFD = newFD;
150         cv.notify_all();
151     };
152
153     // TODO: On timeout remove the callback
154     s.setNewPeerCallback(newPeerCallback);
155
156     if (!s.isStarted()) {
157         s.start();
158     }
159
160     c.start();
161
162
163     std::unique_lock<std::mutex> lock(mutex);
164     BOOST_REQUIRE(cv.wait_for(lock, std::chrono::milliseconds(2000), [&peerFD]() {
165         return peerFD != 0;
166     }));
167
168     return peerFD;
169 }
170
171
172
173 #if GLIB_CHECK_VERSION(2,36,0)
174
175 std::pair<FileDescriptor, IPCGSource::Pointer> connectServiceGSource(Service& s, Client& c)
176 {
177     std::mutex mutex;
178     std::condition_variable cv;
179
180     FileDescriptor peerFD = 0;
181     IPCGSource::Pointer ipcGSourcePtr = IPCGSource::create(s.getFDs(), std::bind(&Service::handle, &s, _1, _2));
182
183     auto newPeerCallback = [&cv, &peerFD, &mutex, ipcGSourcePtr](const FileDescriptor newFD) {
184         if (ipcGSourcePtr) {
185             //TODO: Remove this if
186             ipcGSourcePtr->addFD(newFD);
187         }
188         std::unique_lock<std::mutex> lock(mutex);
189         peerFD = newFD;
190         cv.notify_all();
191     };
192
193
194     // TODO: On timeout remove the callback
195     s.setNewPeerCallback(newPeerCallback);
196     s.setRemovedPeerCallback(std::bind(&IPCGSource::removeFD, ipcGSourcePtr, _1));
197
198     // Service starts to process
199     ipcGSourcePtr->attach();
200
201     c.start();
202
203     std::unique_lock<std::mutex> lock(mutex);
204     BOOST_REQUIRE(cv.wait_for(lock, std::chrono::milliseconds(2000), [&peerFD]() {
205         return peerFD != 0;
206     }));
207
208     return std::make_pair(peerFD, ipcGSourcePtr);
209 }
210
211 std::pair<FileDescriptor, IPCGSource::Pointer> connectClientGSource(Service& s, Client& c)
212 {
213     // Connects the Client to the Service and returns Clients FileDescriptor
214     std::mutex mutex;
215     std::condition_variable cv;
216
217     FileDescriptor peerFD = 0;
218     auto newPeerCallback = [&cv, &peerFD, &mutex](const FileDescriptor newFD) {
219         std::unique_lock<std::mutex> lock(mutex);
220         peerFD = newFD;
221         cv.notify_all();
222     };
223     // TODO: On timeout remove the callback
224     s.setNewPeerCallback(newPeerCallback);
225
226     if (!s.isStarted()) {
227         // Service starts to process
228         s.start();
229     }
230
231
232     c.connect();
233     IPCGSource::Pointer ipcGSourcePtr = IPCGSource::create(c.getFDs(),
234                                                            std::bind(&Client::handle, &c, _1, _2));
235
236     ipcGSourcePtr->attach();
237
238     std::unique_lock<std::mutex> lock(mutex);
239     BOOST_REQUIRE(cv.wait_for(lock, std::chrono::milliseconds(2000), [&peerFD]() {
240         return peerFD != 0;
241     }));
242
243     return std::make_pair(peerFD, ipcGSourcePtr);
244 }
245
246 #endif // GLIB_CHECK_VERSION
247
248
249 void testEcho(Client& c, const MethodID methodID)
250 {
251     std::shared_ptr<SendData> sentData(new SendData(34));
252     std::shared_ptr<SendData> recvData = c.callSync<SendData, SendData>(methodID, sentData, 1000);
253     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
254 }
255
256 void testEcho(Service& s, const MethodID methodID, const FileDescriptor peerFD)
257 {
258     std::shared_ptr<SendData> sentData(new SendData(56));
259     std::shared_ptr<SendData> recvData = s.callSync<SendData, SendData>(methodID, peerFD, sentData, 1000);
260     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
261 }
262
263 } // namespace
264
265
266 BOOST_FIXTURE_TEST_SUITE(IPCSuite, Fixture)
267
268 BOOST_AUTO_TEST_CASE(ConstructorDestructor)
269 {
270     Service s(socketPath);
271     Client c(socketPath);
272 }
273
274 BOOST_AUTO_TEST_CASE(ServiceAddRemoveMethod)
275 {
276     Service s(socketPath);
277
278     s.addMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
279     s.addMethodHandler<SendData, SendData>(1, returnDataCallback);
280
281     s.start();
282
283     s.addMethodHandler<SendData, SendData>(1, echoCallback);
284     s.addMethodHandler<SendData, SendData>(2, returnDataCallback);
285
286     Client c(socketPath);
287     c.start();
288     testEcho(c, 1);
289
290     s.removeMethod(1);
291     s.removeMethod(2);
292
293     BOOST_CHECK_THROW(testEcho(c, 2), IPCException);
294 }
295
296 BOOST_AUTO_TEST_CASE(ClientAddRemoveMethod)
297 {
298     Service s(socketPath);
299     Client c(socketPath);
300     c.addMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
301     c.addMethodHandler<SendData, SendData>(1, returnDataCallback);
302
303     FileDescriptor peerFD = connect(s, c);
304
305     c.addMethodHandler<SendData, SendData>(1, echoCallback);
306     c.addMethodHandler<SendData, SendData>(2, returnDataCallback);
307
308     testEcho(s, 1, peerFD);
309
310     c.removeMethod(1);
311     c.removeMethod(2);
312
313     BOOST_CHECK_THROW(testEcho(s, 1, peerFD), IPCException);
314 }
315
316 BOOST_AUTO_TEST_CASE(ServiceStartStop)
317 {
318     Service s(socketPath);
319
320     s.addMethodHandler<SendData, SendData>(1, returnDataCallback);
321
322     s.start();
323     s.stop();
324     s.start();
325     s.stop();
326
327     s.start();
328     s.start();
329 }
330
331 BOOST_AUTO_TEST_CASE(ClientStartStop)
332 {
333     Service s(socketPath);
334     Client c(socketPath);
335     c.addMethodHandler<SendData, SendData>(1, returnDataCallback);
336
337     c.start();
338     c.stop();
339     c.start();
340     c.stop();
341
342     c.start();
343     c.start();
344
345     c.stop();
346     c.stop();
347 }
348
349 BOOST_AUTO_TEST_CASE(SyncClientToServiceEcho)
350 {
351     Service s(socketPath);
352     s.addMethodHandler<SendData, SendData>(1, echoCallback);
353     s.addMethodHandler<SendData, SendData>(2, echoCallback);
354
355     s.start();
356     Client c(socketPath);
357     c.start();
358     testEcho(c, 1);
359     testEcho(c, 2);
360 }
361
362 BOOST_AUTO_TEST_CASE(Restart)
363 {
364     Service s(socketPath);
365     s.addMethodHandler<SendData, SendData>(1, echoCallback);
366     s.start();
367     s.addMethodHandler<SendData, SendData>(2, echoCallback);
368
369     Client c(socketPath);
370     c.start();
371     testEcho(c, 1);
372     testEcho(c, 2);
373
374     c.stop();
375     c.start();
376
377     testEcho(c, 1);
378     testEcho(c, 2);
379
380     s.stop();
381     s.start();
382
383     testEcho(c, 1);
384     testEcho(c, 2);
385 }
386
387 BOOST_AUTO_TEST_CASE(SyncServiceToClientEcho)
388 {
389     Service s(socketPath);
390     Client c(socketPath);
391     c.addMethodHandler<SendData, SendData>(1, echoCallback);
392     FileDescriptor peerFD = connect(s, c);
393
394     std::shared_ptr<SendData> sentData(new SendData(56));
395     std::shared_ptr<SendData> recvData = s.callSync<SendData, SendData>(1, peerFD, sentData);
396     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
397 }
398
399 BOOST_AUTO_TEST_CASE(AsyncClientToServiceEcho)
400 {
401     // Setup Service and Client
402     Service s(socketPath);
403     s.addMethodHandler<SendData, SendData>(1, echoCallback);
404     s.start();
405     Client c(socketPath);
406     c.start();
407
408     std::mutex mutex;
409     std::condition_variable cv;
410
411     //Async call
412     std::shared_ptr<SendData> sentData(new SendData(34));
413     std::shared_ptr<SendData> recvData;
414     auto dataBack = [&cv, &recvData, &mutex](ipc::Status status, std::shared_ptr<SendData>& data) {
415         BOOST_CHECK(status == ipc::Status::OK);
416         std::unique_lock<std::mutex> lock(mutex);
417         recvData = data;
418         cv.notify_one();
419     };
420     c.callAsync<SendData, SendData>(1, sentData, dataBack);
421
422     // Wait for the response
423     std::unique_lock<std::mutex> lock(mutex);
424     BOOST_CHECK(cv.wait_for(lock, std::chrono::milliseconds(100), [&recvData]() {
425         return static_cast<bool>(recvData);
426     }));
427
428     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
429 }
430
431 BOOST_AUTO_TEST_CASE(AsyncServiceToClientEcho)
432 {
433     Service s(socketPath);
434     Client c(socketPath);
435     c.addMethodHandler<SendData, SendData>(1, echoCallback);
436     FileDescriptor peerFD = connect(s, c);
437
438     // Async call
439     std::shared_ptr<SendData> sentData(new SendData(56));
440     std::shared_ptr<SendData> recvData;
441
442     std::mutex mutex;
443     std::condition_variable cv;
444     auto dataBack = [&cv, &recvData, &mutex](ipc::Status status, std::shared_ptr<SendData>& data) {
445         BOOST_CHECK(status == ipc::Status::OK);
446         std::unique_lock<std::mutex> lock(mutex);
447         recvData = data;
448         cv.notify_one();
449     };
450
451     s.callAsync<SendData, SendData>(1, peerFD, sentData, dataBack);
452
453     // Wait for the response
454     std::unique_lock<std::mutex> lock(mutex);
455     BOOST_CHECK(cv.wait_for(lock, std::chrono::milliseconds(1000), [&recvData]() {
456         return recvData.get() != nullptr;
457     }));
458
459     BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
460 }
461
462
463 BOOST_AUTO_TEST_CASE(SyncTimeout)
464 {
465     Service s(socketPath);
466     s.addMethodHandler<SendData, SendData>(1, longEchoCallback);
467
468     s.start();
469     Client c(socketPath);
470     c.start();
471
472     std::shared_ptr<SendData> sentData(new SendData(78));
473
474     BOOST_CHECK_THROW((c.callSync<SendData, SendData>(1, sentData, 10)), IPCException); //TODO it fails from time to time
475 }
476
477 BOOST_AUTO_TEST_CASE(SerializationError)
478 {
479     Service s(socketPath);
480     s.addMethodHandler<SendData, SendData>(1, echoCallback);
481     s.start();
482
483     Client c(socketPath);
484     c.start();
485
486     std::shared_ptr<ThrowOnAcceptData> throwingData(new ThrowOnAcceptData());
487
488     BOOST_CHECK_THROW((c.callSync<ThrowOnAcceptData, SendData>(1, throwingData)), IPCSerializationException);
489
490 }
491
492 BOOST_AUTO_TEST_CASE(ParseError)
493 {
494     Service s(socketPath);
495     s.addMethodHandler<SendData, SendData>(1, echoCallback);
496     s.start();
497
498     Client c(socketPath);
499     c.start();
500
501     std::shared_ptr<SendData> sentData(new SendData(78));
502     BOOST_CHECK_THROW((c.callSync<SendData, ThrowOnAcceptData>(1, sentData, 10000)), IPCParsingException);
503 }
504
505 BOOST_AUTO_TEST_CASE(DisconnectedPeerError)
506 {
507     Service s(socketPath);
508
509     auto method = [](const FileDescriptor, std::shared_ptr<ThrowOnAcceptData>&) {
510         return std::shared_ptr<SendData>(new SendData(1));
511     };
512
513     // Method will throw during serialization and disconnect automatically
514     s.addMethodHandler<SendData, ThrowOnAcceptData>(1, method);
515     s.start();
516
517     Client c(socketPath);
518     c.start();
519
520     std::mutex mutex;
521     std::condition_variable cv;
522     ipc::Status retStatus = ipc::Status::UNDEFINED;
523
524     auto dataBack = [&cv, &retStatus, &mutex](ipc::Status status, std::shared_ptr<SendData>&) {
525         std::unique_lock<std::mutex> lock(mutex);
526         retStatus = status;
527         cv.notify_one();
528     };
529
530     std::shared_ptr<SendData> sentData(new SendData(78));
531     c.callAsync<SendData, SendData>(1, sentData, dataBack);
532
533     // Wait for the response
534     std::unique_lock<std::mutex> lock(mutex);
535     BOOST_CHECK(cv.wait_for(lock, std::chrono::seconds(10), [&retStatus]() {
536         return retStatus != ipc::Status::UNDEFINED;
537     }));
538     BOOST_CHECK(retStatus == ipc::Status::PEER_DISCONNECTED); //TODO it fails from time to time
539 }
540
541
542 BOOST_AUTO_TEST_CASE(ReadTimeout)
543 {
544     Service s(socketPath);
545     auto longEchoCallback = [](const FileDescriptor, std::shared_ptr<SendData>& data) {
546         return std::shared_ptr<LongSendData>(new LongSendData(data->intVal, 4000 /*ms*/));
547     };
548     s.addMethodHandler<LongSendData, SendData>(1, longEchoCallback);
549
550     Client c(socketPath);
551     connect(s, c);
552
553     // Test timeout on read
554     std::shared_ptr<SendData> sentData(new SendData(334));
555     BOOST_CHECK_THROW((c.callSync<SendData, SendData>(1, sentData, 10)), IPCException);
556 }
557
558
559 BOOST_AUTO_TEST_CASE(WriteTimeout)
560 {
561     Service s(socketPath);
562     s.addMethodHandler<SendData, SendData>(1, echoCallback);
563     s.start();
564
565     Client c(socketPath);
566     c.start();
567
568     // Test echo with a minimal timeout
569     std::shared_ptr<LongSendData> sentDataA(new LongSendData(34, 10 /*ms*/));
570     std::shared_ptr<SendData> recvData = c.callSync<LongSendData, SendData>(1, sentDataA, 100);
571     BOOST_CHECK_EQUAL(recvData->intVal, sentDataA->intVal);
572
573     // Test timeout on write
574     std::shared_ptr<LongSendData> sentDataB(new LongSendData(34, 1000 /*ms*/));
575     BOOST_CHECK_THROW((c.callSync<LongSendData, SendData>(1, sentDataB, 100)), IPCTimeoutException);
576 }
577
578
579 BOOST_AUTO_TEST_CASE(AddSignalInRuntime)
580 {
581     Service s(socketPath);
582     Client c(socketPath);
583     connect(s, c);
584
585     std::atomic_bool isHandlerACalled(false);
586     auto handlerA = [&isHandlerACalled](const FileDescriptor, std::shared_ptr<SendData>&) {
587         isHandlerACalled = true;
588     };
589
590     std::atomic_bool isHandlerBCalled(false);
591     auto handlerB = [&isHandlerBCalled](const FileDescriptor, std::shared_ptr<SendData>&) {
592         isHandlerBCalled = true;
593     };
594
595     c.addSignalHandler<SendData>(1, handlerA);
596     c.addSignalHandler<SendData>(2, handlerB);
597
598     auto data = std::make_shared<SendData>(1);
599     s.signal<SendData>(2, data);
600     s.signal<SendData>(1, data);
601
602     // Wait for the signals to arrive
603     std::this_thread::sleep_for(std::chrono::milliseconds(100)); //TODO wait_for
604     BOOST_CHECK(isHandlerACalled && isHandlerBCalled);
605 }
606
607
608 BOOST_AUTO_TEST_CASE(AddSignalOffline)
609 {
610     Service s(socketPath);
611     Client c(socketPath);
612
613     std::atomic_bool isHandlerACalled(false);
614     auto handlerA = [&isHandlerACalled](const FileDescriptor, std::shared_ptr<SendData>&) {
615         isHandlerACalled = true;
616     };
617
618     std::atomic_bool isHandlerBCalled(false);
619     auto handlerB = [&isHandlerBCalled](const FileDescriptor, std::shared_ptr<SendData>&) {
620         isHandlerBCalled = true;
621     };
622
623     c.addSignalHandler<SendData>(1, handlerA);
624     c.addSignalHandler<SendData>(2, handlerB);
625
626     connect(s, c);
627
628     // Wait for the information about the signals to propagate
629     std::this_thread::sleep_for(std::chrono::milliseconds(100));
630     auto data = std::make_shared<SendData>(1);
631     s.signal<SendData>(2, data);
632     s.signal<SendData>(1, data);
633
634     // Wait for the signals to arrive
635     std::this_thread::sleep_for(std::chrono::milliseconds(100)); //TODO wait_for
636     BOOST_CHECK(isHandlerACalled && isHandlerBCalled);
637 }
638
639
640 #if GLIB_CHECK_VERSION(2,36,0)
641
642 BOOST_AUTO_TEST_CASE(ServiceGSource)
643 {
644     ScopedGlibLoop loop;
645
646     std::atomic_bool isSignalCalled(false);
647     auto signalHandler = [&isSignalCalled](const FileDescriptor, std::shared_ptr<SendData>&) {
648         isSignalCalled = true;
649     };
650
651     IPCGSource::Pointer serviceGSource;
652     Service s(socketPath);
653     s.addMethodHandler<SendData, SendData>(1, echoCallback);
654
655     Client c(socketPath);
656     s.addSignalHandler<SendData>(2, signalHandler);
657
658     auto ret = connectServiceGSource(s, c);
659     serviceGSource = ret.second;
660
661     testEcho(c, 1);
662
663     auto data = std::make_shared<SendData>(1);
664     c.signal<SendData>(2, data);
665
666     std::this_thread::sleep_for(std::chrono::milliseconds(100)); //TODO wait_for
667     BOOST_CHECK(isSignalCalled);
668 }
669
670 BOOST_AUTO_TEST_CASE(ClientGSource)
671 {
672     ScopedGlibLoop loop;
673
674     std::atomic_bool isSignalCalled(false);
675     auto signalHandler = [&isSignalCalled](const FileDescriptor, std::shared_ptr<SendData>&) {
676         isSignalCalled = true;
677     };
678
679     Service s(socketPath);
680     s.start();
681
682     IPCGSource::Pointer clientGSource;
683     Client c(socketPath);
684     c.addMethodHandler<SendData, SendData>(1, echoCallback);
685     c.addSignalHandler<SendData>(2, signalHandler);
686
687     auto ret = connectClientGSource(s, c);
688     FileDescriptor peerFD = ret.first;
689     clientGSource = ret.second;
690
691     testEcho(s, 1, peerFD);
692
693     auto data = std::make_shared<SendData>(1);
694     s.signal<SendData>(2, data);
695
696     std::this_thread::sleep_for(std::chrono::milliseconds(100)); //TODO wait_for
697     BOOST_CHECK(isSignalCalled);
698 }
699
700 #endif // GLIB_CHECK_VERSION
701
702 // BOOST_AUTO_TEST_CASE(ConnectionLimitTest)
703 // {
704 //     unsigned oldLimit = ipc::getMaxFDNumber();
705 //     ipc::setMaxFDNumber(50);
706
707 //     // Setup Service and many Clients
708 //     Service s(socketPath);
709 //     s.addMethodHandler<SendData, SendData>(1, echoCallback);
710 //     s.start();
711
712 //     std::list<Client> clients;
713 //     for (int i = 0; i < 100; ++i) {
714 //         try {
715 //             clients.push_back(Client(socketPath));
716 //             clients.back().start();
717 //         } catch (...) {}
718 //     }
719
720 //     unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
721 //     std::mt19937 generator(seed);
722 //     for (auto it = clients.begin(); it != clients.end(); ++it) {
723 //         try {
724 //             std::shared_ptr<SendData> sentData(new SendData(generator()));
725 //             std::shared_ptr<SendData> recvData = it->callSync<SendData, SendData>(1, sentData);
726 //             BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
727 //         } catch (...) {}
728 //     }
729
730 //     ipc::setMaxFDNumber(oldLimit);
731 // }
732
733
734
735 BOOST_AUTO_TEST_SUITE_END()