2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Jan Olszak <j.olszak@samsung.com>
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
22 * @author Jan Olszak (j.olszak@samsung.com)
23 * @brief Tests of the IPC
26 // TODO: Test connection limit
27 // TODO: Refactor tests - function for setting up env
33 #include "ipc/service.hpp"
34 #include "ipc/client.hpp"
35 #include "ipc/types.hpp"
36 #include "ipc/unique-id.hpp"
37 #include "ipc/result.hpp"
38 #include "ipc/epoll/thread-dispatcher.hpp"
39 #include "ipc/epoll/glib-dispatcher.hpp"
40 #include "utils/channel.hpp"
41 #include "utils/glib-loop.hpp"
42 #include "utils/latch.hpp"
43 #include "utils/value-latch.hpp"
44 #include "utils/scoped-dir.hpp"
46 #include "config/fields.hpp"
47 #include "logger/logger.hpp"
49 #include <boost/filesystem.hpp>
57 #include <semaphore.h>
58 #include <sys/types.h>
65 using namespace epoll;
66 using namespace utils;
67 using namespace std::placeholders;
68 namespace fs = boost::filesystem;
70 // Timeout for sending one message
71 const int TIMEOUT = 1000 /*ms*/;
73 // Time that won't cause "TIMEOUT" methods to throw
74 const int SHORT_OPERATION_TIME = TIMEOUT / 100;
76 // Time that will cause "TIMEOUT" methods to throw
77 const int LONG_OPERATION_TIME = 1000 + TIMEOUT;
79 const std::string TEST_DIR = "/tmp/ut-ipc";
80 const std::string SOCKET_PATH = TEST_DIR + "/test.socket";
81 const std::string TEST_FILE = TEST_DIR + "/file.txt";
84 ScopedDir mTestPathGuard;
87 : mTestPathGuard(TEST_DIR)
92 struct ThreadedFixture : FixtureBase {
93 ThreadDispatcher dispatcher;
95 EventPoll& getPoll() {
96 return dispatcher.getPoll();
100 struct GlibFixture : FixtureBase {
101 ScopedGlibLoop glibLoop;
102 GlibDispatcher dispatcher;
104 EventPoll& getPoll() {
105 return dispatcher.getPoll();
111 SendData(int i): intVal(i) {}
121 RecvData(): intVal(-1) {}
130 config::FileDescriptor fd;
131 FDData(int fd = -1): fd(fd) {}
139 struct LongSendData {
140 LongSendData(int i, int waitTime): mSendData(i), mWaitTime(waitTime), intVal(i) {}
142 template<typename Visitor>
143 void accept(Visitor visitor)
145 std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTime));
146 mSendData.accept(visitor);
148 template<typename Visitor>
149 void accept(Visitor visitor) const
151 std::this_thread::sleep_for(std::chrono::milliseconds(mWaitTime));
152 mSendData.accept(visitor);
161 CONFIG_REGISTER_EMPTY
164 struct ThrowOnAcceptData {
165 template<typename Visitor>
166 static void accept(Visitor)
168 throw std::runtime_error("intentional failure in accept");
172 void returnEmptyCallback(const PeerID,
173 std::shared_ptr<EmptyData>&,
174 MethodResult::Pointer methodResult)
176 methodResult->setVoid();
179 void returnDataCallback(const PeerID,
180 std::shared_ptr<RecvData>&,
181 MethodResult::Pointer methodResult)
183 auto returnData = std::make_shared<SendData>(1);
184 methodResult->set(returnData);
187 void echoCallback(const PeerID,
188 std::shared_ptr<RecvData>& data,
189 MethodResult::Pointer methodResult)
191 auto returnData = std::make_shared<SendData>(data->intVal);
192 methodResult->set(returnData);
195 void longEchoCallback(const PeerID,
196 std::shared_ptr<RecvData>& data,
197 MethodResult::Pointer methodResult)
199 std::this_thread::sleep_for(std::chrono::milliseconds(LONG_OPERATION_TIME));
200 auto returnData = std::make_shared<SendData>(data->intVal);
201 methodResult->set(returnData);
204 void shortEchoCallback(const PeerID,
205 std::shared_ptr<RecvData>& data,
206 MethodResult::Pointer methodResult)
208 std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_OPERATION_TIME));
209 auto returnData = std::make_shared<SendData>(data->intVal);
210 methodResult->set(returnData);
213 PeerID connectPeer(Service& s, Client& c)
215 // Connects the Client to the Service and returns Clients PeerID
216 ValueLatch<PeerID> peerIDLatch;
217 auto newPeerCallback = [&peerIDLatch](const PeerID newID, const FileDescriptor) {
218 peerIDLatch.set(newID);
221 s.setNewPeerCallback(newPeerCallback);
223 if (!s.isStarted()) {
229 PeerID peerID = peerIDLatch.get(TIMEOUT);
230 s.setNewPeerCallback(nullptr);
231 BOOST_REQUIRE_NE(peerID, static_cast<std::string>(ipc::UniqueID()));
235 void testEcho(Client& c, const MethodID methodID)
237 std::shared_ptr<SendData> sentData(new SendData(34));
238 std::shared_ptr<RecvData> recvData = c.callSync<SendData, RecvData>(methodID, sentData, TIMEOUT);
239 BOOST_REQUIRE(recvData);
240 BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
243 void testEcho(Service& s, const MethodID methodID, const PeerID& peerID)
245 std::shared_ptr<SendData> sentData(new SendData(56));
246 std::shared_ptr<RecvData> recvData = s.callSync<SendData, RecvData>(methodID, peerID, sentData, TIMEOUT);
247 BOOST_REQUIRE(recvData);
248 BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
251 BOOST_AUTO_TEST_SUITE(IPCSuite)
253 MULTI_FIXTURE_TEST_CASE(ConstructorDestructor, F, ThreadedFixture, GlibFixture)
255 Service s(F::getPoll(), SOCKET_PATH);
256 Client c(F::getPoll(), SOCKET_PATH);
259 MULTI_FIXTURE_TEST_CASE(ServiceAddRemoveMethod, F, ThreadedFixture, GlibFixture)
261 Service s(F::getPoll(), SOCKET_PATH);
262 s.setMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
263 s.setMethodHandler<SendData, RecvData>(1, returnDataCallback);
267 s.setMethodHandler<SendData, RecvData>(1, echoCallback);
268 s.setMethodHandler<SendData, RecvData>(2, returnDataCallback);
270 Client c(F::getPoll(), SOCKET_PATH);
277 BOOST_CHECK_THROW(testEcho(c, 2), IPCException);
280 MULTI_FIXTURE_TEST_CASE(ClientAddRemoveMethod, F, ThreadedFixture, GlibFixture)
282 Service s(F::getPoll(), SOCKET_PATH);
283 Client c(F::getPoll(), SOCKET_PATH);
284 c.setMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
285 c.setMethodHandler<SendData, RecvData>(1, returnDataCallback);
287 PeerID peerID = connectPeer(s, c);
289 c.setMethodHandler<SendData, RecvData>(1, echoCallback);
290 c.setMethodHandler<SendData, RecvData>(2, returnDataCallback);
292 testEcho(s, 1, peerID);
297 BOOST_CHECK_THROW(testEcho(s, 1, peerID), IPCException);
300 MULTI_FIXTURE_TEST_CASE(MethodResultGetPeerID, F, ThreadedFixture, GlibFixture)
302 Service s(F::getPoll(), SOCKET_PATH);
303 Client c(F::getPoll(), SOCKET_PATH);
305 PeerID peerID = connectPeer(s, c);
307 s.setMethodHandler<SendData, RecvData>(
309 [&peerID](const PeerID,
310 std::shared_ptr<RecvData>&,
311 MethodResult::Pointer methodResult) {
312 methodResult->setVoid();
313 BOOST_CHECK_EQUAL(peerID, methodResult->getPeerID());
317 std::shared_ptr<SendData> sentData(new SendData(32));
318 std::shared_ptr<RecvData> recvData = c.callSync<SendData, RecvData>(1,
323 MULTI_FIXTURE_TEST_CASE(ServiceStartStop, F, ThreadedFixture, GlibFixture)
325 Service s(F::getPoll(), SOCKET_PATH);
327 s.setMethodHandler<SendData, RecvData>(1, returnDataCallback);
338 MULTI_FIXTURE_TEST_CASE(ClientStartStop, F, ThreadedFixture, GlibFixture)
340 Service s(F::getPoll(), SOCKET_PATH);
341 Client c(F::getPoll(), SOCKET_PATH);
342 c.setMethodHandler<SendData, RecvData>(1, returnDataCallback);
356 MULTI_FIXTURE_TEST_CASE(SyncClientToServiceEcho, F, ThreadedFixture, GlibFixture)
358 Service s(F::getPoll(), SOCKET_PATH);
359 s.setMethodHandler<SendData, RecvData>(1, echoCallback);
360 s.setMethodHandler<SendData, RecvData>(2, echoCallback);
362 Client c(F::getPoll(), SOCKET_PATH);
369 MULTI_FIXTURE_TEST_CASE(Restart, F, ThreadedFixture, GlibFixture)
371 Service s(F::getPoll(), SOCKET_PATH);
372 s.setMethodHandler<SendData, RecvData>(1, echoCallback);
374 s.setMethodHandler<SendData, RecvData>(2, echoCallback);
376 Client c(F::getPoll(), SOCKET_PATH);
390 BOOST_CHECK_THROW(testEcho(c, 2), IPCException);
399 MULTI_FIXTURE_TEST_CASE(SyncServiceToClientEcho, F, ThreadedFixture, GlibFixture)
401 Service s(F::getPoll(), SOCKET_PATH);
402 Client c(F::getPoll(), SOCKET_PATH);
403 c.setMethodHandler<SendData, RecvData>(1, echoCallback);
404 PeerID peerID = connectPeer(s, c);
406 std::shared_ptr<SendData> sentData(new SendData(56));
407 std::shared_ptr<RecvData> recvData = s.callSync<SendData, RecvData>(1, peerID, sentData);
408 BOOST_REQUIRE(recvData);
409 BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
412 MULTI_FIXTURE_TEST_CASE(AsyncClientToServiceEcho, F, ThreadedFixture, GlibFixture)
414 std::shared_ptr<SendData> sentData(new SendData(34));
415 ValueLatch<std::shared_ptr<RecvData>> recvDataLatch;
417 // Setup Service and Client
418 Service s(F::getPoll(), SOCKET_PATH);
419 s.setMethodHandler<SendData, RecvData>(1, echoCallback);
421 Client c(F::getPoll(), SOCKET_PATH);
425 auto dataBack = [&recvDataLatch](Result<RecvData> && r) {
426 recvDataLatch.set(r.get());
428 c.callAsync<SendData, RecvData>(1, sentData, dataBack);
430 // Wait for the response
431 std::shared_ptr<RecvData> recvData(recvDataLatch.get(TIMEOUT));
432 BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
435 MULTI_FIXTURE_TEST_CASE(AsyncServiceToClientEcho, F, ThreadedFixture, GlibFixture)
437 std::shared_ptr<SendData> sentData(new SendData(56));
438 ValueLatch<std::shared_ptr<RecvData>> recvDataLatch;
440 Service s(F::getPoll(), SOCKET_PATH);
441 Client c(F::getPoll(), SOCKET_PATH);
442 c.setMethodHandler<SendData, RecvData>(1, echoCallback);
443 PeerID peerID = connectPeer(s, c);
446 auto dataBack = [&recvDataLatch](Result<RecvData> && r) {
447 recvDataLatch.set(r.get());
450 s.callAsync<SendData, RecvData>(1, peerID, sentData, dataBack);
452 // Wait for the response
453 std::shared_ptr<RecvData> recvData(recvDataLatch.get(TIMEOUT));
454 BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
458 MULTI_FIXTURE_TEST_CASE(SyncTimeout, F, ThreadedFixture, GlibFixture)
460 Service s(F::getPoll(), SOCKET_PATH);
461 s.setMethodHandler<SendData, RecvData>(1, longEchoCallback);
463 Client c(F::getPoll(), SOCKET_PATH);
466 std::shared_ptr<SendData> sentData(new SendData(78));
467 BOOST_REQUIRE_THROW((c.callSync<SendData, RecvData>(1, sentData, TIMEOUT)), IPCException);
470 MULTI_FIXTURE_TEST_CASE(SerializationError, F, ThreadedFixture, GlibFixture)
472 Service s(F::getPoll(), SOCKET_PATH);
473 s.setMethodHandler<SendData, RecvData>(1, echoCallback);
475 Client c(F::getPoll(), SOCKET_PATH);
478 std::shared_ptr<ThrowOnAcceptData> throwingData(new ThrowOnAcceptData());
480 BOOST_CHECK_THROW((c.callSync<ThrowOnAcceptData, RecvData>(1, throwingData)), IPCSerializationException);
484 MULTI_FIXTURE_TEST_CASE(ParseError, F, ThreadedFixture, GlibFixture)
486 Service s(F::getPoll(), SOCKET_PATH);
487 s.setMethodHandler<SendData, RecvData>(1, echoCallback);
490 Client c(F::getPoll(), SOCKET_PATH);
493 std::shared_ptr<SendData> sentData(new SendData(78));
494 BOOST_CHECK_THROW((c.callSync<SendData, ThrowOnAcceptData>(1, sentData, 10000)), IPCParsingException);
497 MULTI_FIXTURE_TEST_CASE(DisconnectedPeerError, F, ThreadedFixture, GlibFixture)
499 ValueLatch<Result<RecvData>> retStatusLatch;
501 Service s(F::getPoll(), SOCKET_PATH);
503 auto method = [](const PeerID, std::shared_ptr<ThrowOnAcceptData>&, MethodResult::Pointer methodResult) {
504 auto resultData = std::make_shared<SendData>(1);
505 methodResult->set<SendData>(resultData);
508 // Method will throw during serialization and disconnect automatically
509 s.setMethodHandler<SendData, ThrowOnAcceptData>(1, method);
512 Client c(F::getPoll(), SOCKET_PATH);
515 auto dataBack = [&retStatusLatch](Result<RecvData> && r) {
516 retStatusLatch.set(std::move(r));
519 std::shared_ptr<SendData> sentData(new SendData(78));
520 c.callAsync<SendData, RecvData>(1, sentData, dataBack);
522 // Wait for the response
523 Result<RecvData> result = retStatusLatch.get(TIMEOUT);
525 // The disconnection might have happened:
526 // - after sending the message (PEER_DISCONNECTED)
527 // - during external serialization (SERIALIZATION_ERROR)
528 BOOST_CHECK_THROW(result.get(), IPCException);
532 MULTI_FIXTURE_TEST_CASE(ReadTimeout, F, ThreadedFixture, GlibFixture)
534 Service s(F::getPoll(), SOCKET_PATH);
535 auto longEchoCallback = [](const PeerID, std::shared_ptr<RecvData>& data, MethodResult::Pointer methodResult) {
536 auto resultData = std::make_shared<LongSendData>(data->intVal, LONG_OPERATION_TIME);
537 methodResult->set<LongSendData>(resultData);
539 s.setMethodHandler<LongSendData, RecvData>(1, longEchoCallback);
541 Client c(F::getPoll(), SOCKET_PATH);
544 // Test timeout on read
545 std::shared_ptr<SendData> sentData(new SendData(334));
546 BOOST_CHECK_THROW((c.callSync<SendData, RecvData>(1, sentData, TIMEOUT)), IPCException);
550 MULTI_FIXTURE_TEST_CASE(WriteTimeout, F, ThreadedFixture, GlibFixture)
552 Service s(F::getPoll(), SOCKET_PATH);
553 s.setMethodHandler<SendData, RecvData>(1, shortEchoCallback);
556 Client c(F::getPoll(), SOCKET_PATH);
559 // Test echo with a minimal timeout
560 std::shared_ptr<LongSendData> sentDataA(new LongSendData(34, SHORT_OPERATION_TIME));
561 std::shared_ptr<RecvData> recvData = c.callSync<LongSendData, RecvData>(1, sentDataA, TIMEOUT);
562 BOOST_REQUIRE(recvData);
563 BOOST_CHECK_EQUAL(recvData->intVal, sentDataA->intVal);
565 // Test timeout on write
566 std::shared_ptr<LongSendData> sentDataB(new LongSendData(34, LONG_OPERATION_TIME));
567 BOOST_CHECK_THROW((c.callSync<LongSendData, RecvData>(1, sentDataB, TIMEOUT)), IPCTimeoutException);
571 MULTI_FIXTURE_TEST_CASE(AddSignalInRuntime, F, ThreadedFixture, GlibFixture)
573 ValueLatch<std::shared_ptr<RecvData>> recvDataLatchA;
574 ValueLatch<std::shared_ptr<RecvData>> recvDataLatchB;
576 Service s(F::getPoll(), SOCKET_PATH);
577 Client c(F::getPoll(), SOCKET_PATH);
580 auto handlerA = [&recvDataLatchA](const PeerID, std::shared_ptr<RecvData>& data) {
581 recvDataLatchA.set(data);
584 auto handlerB = [&recvDataLatchB](const PeerID, std::shared_ptr<RecvData>& data) {
585 recvDataLatchB.set(data);
588 c.setSignalHandler<RecvData>(1, handlerA);
589 c.setSignalHandler<RecvData>(2, handlerB);
591 // Wait for the signals to propagate to the Service
592 std::this_thread::sleep_for(std::chrono::milliseconds(2 * TIMEOUT));
594 auto sendDataA = std::make_shared<SendData>(1);
595 auto sendDataB = std::make_shared<SendData>(2);
596 s.signal<SendData>(2, sendDataB);
597 s.signal<SendData>(1, sendDataA);
599 // Wait for the signals to arrive
600 std::shared_ptr<RecvData> recvDataA(recvDataLatchA.get(TIMEOUT));
601 std::shared_ptr<RecvData> recvDataB(recvDataLatchB.get(TIMEOUT));
602 BOOST_CHECK_EQUAL(recvDataA->intVal, sendDataA->intVal);
603 BOOST_CHECK_EQUAL(recvDataB->intVal, sendDataB->intVal);
607 MULTI_FIXTURE_TEST_CASE(AddSignalOffline, F, ThreadedFixture, GlibFixture)
609 ValueLatch<std::shared_ptr<RecvData>> recvDataLatchA;
610 ValueLatch<std::shared_ptr<RecvData>> recvDataLatchB;
612 Service s(F::getPoll(), SOCKET_PATH);
613 Client c(F::getPoll(), SOCKET_PATH);
615 auto handlerA = [&recvDataLatchA](const PeerID, std::shared_ptr<RecvData>& data) {
616 recvDataLatchA.set(data);
619 auto handlerB = [&recvDataLatchB](const PeerID, std::shared_ptr<RecvData>& data) {
620 recvDataLatchB.set(data);
623 c.setSignalHandler<RecvData>(1, handlerA);
624 c.setSignalHandler<RecvData>(2, handlerB);
628 // Wait for the information about the signals to propagate
629 std::this_thread::sleep_for(std::chrono::milliseconds(TIMEOUT));
631 auto sendDataA = std::make_shared<SendData>(1);
632 auto sendDataB = std::make_shared<SendData>(2);
633 s.signal<SendData>(2, sendDataB);
634 s.signal<SendData>(1, sendDataA);
636 // Wait for the signals to arrive
637 std::shared_ptr<RecvData> recvDataA(recvDataLatchA.get(TIMEOUT));
638 std::shared_ptr<RecvData> recvDataB(recvDataLatchB.get(TIMEOUT));
639 BOOST_CHECK_EQUAL(recvDataA->intVal, sendDataA->intVal);
640 BOOST_CHECK_EQUAL(recvDataB->intVal, sendDataB->intVal);
643 MULTI_FIXTURE_TEST_CASE(UsersError, F, ThreadedFixture, GlibFixture)
645 const int TEST_ERROR_CODE = -234;
646 const std::string TEST_ERROR_MESSAGE = "Ay, caramba!";
648 Service s(F::getPoll(), SOCKET_PATH);
649 Client c(F::getPoll(), SOCKET_PATH);
650 auto clientID = connectPeer(s, c);
652 auto throwingMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>&, MethodResult::Pointer) {
653 throw IPCUserException(TEST_ERROR_CODE, TEST_ERROR_MESSAGE);
656 auto sendErrorMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>&, MethodResult::Pointer methodResult) {
657 methodResult->setError(TEST_ERROR_CODE, TEST_ERROR_MESSAGE);
660 s.setMethodHandler<SendData, RecvData>(1, throwingMethodHandler);
661 s.setMethodHandler<SendData, RecvData>(2, sendErrorMethodHandler);
662 c.setMethodHandler<SendData, RecvData>(1, throwingMethodHandler);
663 c.setMethodHandler<SendData, RecvData>(2, sendErrorMethodHandler);
665 std::shared_ptr<SendData> sentData(new SendData(78));
667 auto hasProperData = [&](const IPCUserException & e) {
668 return e.getCode() == TEST_ERROR_CODE && e.what() == TEST_ERROR_MESSAGE;
671 BOOST_CHECK_EXCEPTION((c.callSync<SendData, RecvData>(1, sentData, TIMEOUT)), IPCUserException, hasProperData);
672 BOOST_CHECK_EXCEPTION((s.callSync<SendData, RecvData>(1, clientID, sentData, TIMEOUT)), IPCUserException, hasProperData);
673 BOOST_CHECK_EXCEPTION((c.callSync<SendData, RecvData>(2, sentData, TIMEOUT)), IPCUserException, hasProperData);
674 BOOST_CHECK_EXCEPTION((s.callSync<SendData, RecvData>(2, clientID, sentData, TIMEOUT)), IPCUserException, hasProperData);
677 MULTI_FIXTURE_TEST_CASE(AsyncResult, F, ThreadedFixture, GlibFixture)
679 const int TEST_ERROR_CODE = -567;
680 const std::string TEST_ERROR_MESSAGE = "Ooo jooo!";
682 Service s(F::getPoll(), SOCKET_PATH);
683 Client c(F::getPoll(), SOCKET_PATH);
684 auto clientID = connectPeer(s, c);
686 auto errorMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>&, MethodResult::Pointer methodResult) {
687 std::async(std::launch::async, [&, methodResult] {
688 std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_OPERATION_TIME));
689 methodResult->setError(TEST_ERROR_CODE, TEST_ERROR_MESSAGE);
693 auto voidMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>&, MethodResult::Pointer methodResult) {
694 std::async(std::launch::async, [methodResult] {
695 std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_OPERATION_TIME));
696 methodResult->setVoid();
700 auto dataMethodHandler = [&](const PeerID, std::shared_ptr<RecvData>& data, MethodResult::Pointer methodResult) {
701 std::async(std::launch::async, [data, methodResult] {
702 std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_OPERATION_TIME));
703 methodResult->set(data);
707 s.setMethodHandler<SendData, RecvData>(1, errorMethodHandler);
708 s.setMethodHandler<EmptyData, RecvData>(2, voidMethodHandler);
709 s.setMethodHandler<SendData, RecvData>(3, dataMethodHandler);
710 c.setMethodHandler<SendData, RecvData>(1, errorMethodHandler);
711 c.setMethodHandler<EmptyData, RecvData>(2, voidMethodHandler);
712 c.setMethodHandler<SendData, RecvData>(3, dataMethodHandler);
714 std::shared_ptr<SendData> sentData(new SendData(90));
716 auto hasProperData = [&](const IPCUserException & e) {
717 return e.getCode() == TEST_ERROR_CODE && e.what() == TEST_ERROR_MESSAGE;
720 BOOST_CHECK_EXCEPTION((s.callSync<SendData, RecvData>(1, clientID, sentData, TIMEOUT)), IPCUserException, hasProperData);
721 BOOST_CHECK_EXCEPTION((c.callSync<SendData, RecvData>(1, sentData, TIMEOUT)), IPCUserException, hasProperData);
723 BOOST_CHECK_NO_THROW((s.callSync<SendData, EmptyData>(2, clientID, sentData, TIMEOUT)));
724 BOOST_CHECK_NO_THROW((c.callSync<SendData, EmptyData>(2, sentData, TIMEOUT)));
726 std::shared_ptr<RecvData> recvData;
727 recvData = s.callSync<SendData, RecvData>(3, clientID, sentData, TIMEOUT);
728 BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
729 recvData = c.callSync<SendData, RecvData>(3, sentData, TIMEOUT);
730 BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
733 MULTI_FIXTURE_TEST_CASE(MixOperations, F, ThreadedFixture, GlibFixture)
737 auto signalHandler = [&l](const PeerID, std::shared_ptr<RecvData>&) {
741 Service s(F::getPoll(), SOCKET_PATH);
742 s.setMethodHandler<SendData, RecvData>(1, echoCallback);
744 Client c(F::getPoll(), SOCKET_PATH);
745 s.setSignalHandler<RecvData>(2, signalHandler);
751 auto data = std::make_shared<SendData>(1);
752 c.signal<SendData>(2, data);
754 BOOST_CHECK(l.wait(TIMEOUT));
757 MULTI_FIXTURE_TEST_CASE(FDSendReceive, F, ThreadedFixture, GlibFixture)
759 const char DATA[] = "Content of the file";
762 fs::remove(TEST_FILE);
763 std::ofstream file(TEST_FILE);
768 auto methodHandler = [&](const PeerID, std::shared_ptr<EmptyData>&, MethodResult::Pointer methodResult) {
769 int fd = ::open(TEST_FILE.c_str(), O_RDONLY);
770 auto returnData = std::make_shared<FDData>(fd);
771 methodResult->set(returnData);
774 Service s(F::getPoll(), SOCKET_PATH);
775 s.setMethodHandler<FDData, EmptyData>(1, methodHandler);
777 Client c(F::getPoll(), SOCKET_PATH);
780 std::shared_ptr<FDData> fdData;
781 std::shared_ptr<EmptyData> sentData(new EmptyData());
782 fdData = c.callSync<EmptyData, FDData>(1, sentData, TIMEOUT);
784 // Use the file descriptor
785 char buffer[sizeof(DATA)];
786 BOOST_REQUIRE(::read(fdData->fd.value, buffer, sizeof(buffer))>0);
787 BOOST_REQUIRE(strncmp(DATA, buffer, strlen(DATA))==0);
788 ::close(fdData->fd.value);
791 BOOST_AUTO_TEST_CASE(ConnectionLimit)
793 const unsigned oldLimit = utils::getMaxFDNumber();
794 const unsigned newLimit = 32;
795 ScopedDir scopedDir(TEST_DIR);
799 const pid_t chpid = ::fork();
800 BOOST_CHECK_NE(chpid, -1);
805 Service s(td.getPoll(), SOCKET_PATH);
806 s.setMethodHandler<SendData, RecvData>(1, echoCallback);
819 BOOST_CHECK_EQUAL(::waitpid(chpid, &status, 0), chpid);
820 BOOST_CHECK_EQUAL(status, EXIT_SUCCESS);
822 int ret = EXIT_FAILURE;
823 utils::setMaxFDNumber(newLimit);
827 // wait for the Service
830 ::_exit(EXIT_FAILURE);
835 std::list<Client> clients;
837 for (unsigned i = 0; i < 2 * newLimit; ++i) {
838 clients.emplace_back(td.getPoll(), SOCKET_PATH);
839 clients.back().start();
841 } catch (const EventFDException& e) {
843 } catch (const IPCSocketException& e) {
844 if (e.getCode() == EMFILE) {
849 utils::setMaxFDNumber(oldLimit);
857 BOOST_AUTO_TEST_SUITE_END()