Coloring compiler's output
[platform/core/security/vasum.git] / tests / unit_tests / utils / ut-event-poll.cpp
1 /*
2  *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Piotr Bartosiewicz <p.bartosiewi@partner.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  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
23  * @brief   Unit tests of event poll
24  */
25
26 #include "config.hpp"
27 #include "ut.hpp"
28
29 #include "utils/event-poll.hpp"
30 #include "logger/logger.hpp"
31 #include "ipc/internals/socket.hpp"
32 #include "utils/latch.hpp"
33 #include "utils/glib-loop.hpp"
34 #include "utils/glib-poll-dispatcher.hpp"
35 #include "utils/thread-poll-dispatcher.hpp"
36
37 #include <map>
38 #include <sys/epoll.h>
39
40 using namespace vasum::utils;
41 using namespace vasum::ipc;
42
43 namespace {
44
45 const int unsigned TIMEOUT = 1000;
46 #define ADD_EVENT(e) {EPOLL##e, #e}
47 const std::map<EventPoll::Events, std::string> EVENT_NAMES = {
48     ADD_EVENT(IN),
49     ADD_EVENT(OUT),
50     ADD_EVENT(ERR),
51     ADD_EVENT(HUP),
52     ADD_EVENT(RDHUP),
53 };
54 #undef ADD_EVENT
55
56 std::string strEvents(EventPoll::Events events)
57 {
58     if (events == 0) {
59         return "<none>";
60     }
61     std::ostringstream ss;
62     for (const auto& p : EVENT_NAMES) {
63         if (events & p.first) {
64             ss << p.second << ", ";
65             events &= ~p.first;
66         }
67     }
68     if (events != 0) {
69         ss << std::hex << events;
70         return ss.str();
71     } else {
72         std::string ret = ss.str();
73         ret.resize(ret.size() - 2);
74         return ret;
75     }
76 }
77
78 } // namespace
79
80 BOOST_AUTO_TEST_SUITE(EventPollSuite)
81
82 BOOST_AUTO_TEST_CASE(EmptyPoll)
83 {
84     EventPoll poll;
85     BOOST_CHECK(!poll.dispatchIteration(0));
86 }
87
88 BOOST_AUTO_TEST_CASE(ThreadedPoll)
89 {
90     EventPoll poll;
91     ThreadPollDispatcher dispatcher(poll);
92 }
93
94 BOOST_AUTO_TEST_CASE(GlibPoll)
95 {
96     ScopedGlibLoop loop;
97
98     EventPoll poll;
99     GlibPollDispatcher dispatcher(poll);
100 }
101
102 void doSocketTest(EventPoll& poll, Latch& goodMessage, Latch& remoteClosed)
103 {
104     const std::string PATH = "/tmp/ut-poll.sock";
105     const std::string MESSAGE = "This is a test message";
106
107     Socket listen = Socket::createSocket(PATH);
108     std::shared_ptr<Socket> server;
109
110     auto serverCallback = [&](int, EventPoll::Events events) -> bool {
111         LOGD("Server events: " << strEvents(events));
112
113         if (events & EPOLLOUT) {
114             server->write(MESSAGE.data(), MESSAGE.size());
115             poll.removeFD(server->getFD());
116             server.reset();
117         }
118         return true;
119     };
120
121     auto listenCallback = [&](int, EventPoll::Events events) -> bool {
122         LOGD("Listen events: " << strEvents(events));
123         if (events & EPOLLIN) {
124             server = listen.accept();
125             poll.addFD(server->getFD(), EPOLLHUP | EPOLLRDHUP | EPOLLOUT, serverCallback);
126         }
127         return true;
128     };
129
130     poll.addFD(listen.getFD(), EPOLLIN, listenCallback);
131
132     Socket client = Socket::connectSocket(PATH);
133
134     auto clientCallback = [&](int, EventPoll::Events events) -> bool {
135         LOGD("Client events: " << strEvents(events));
136
137         if (events & EPOLLIN) {
138             std::string ret(MESSAGE.size(), 'x');
139             client.read(&ret.front(), ret.size());
140             if (ret == MESSAGE) {
141                 goodMessage.set();
142             }
143         }
144         if (events & EPOLLRDHUP) {
145             poll.removeFD(client.getFD());
146             remoteClosed.set();
147         }
148         return true;
149     };
150
151     poll.addFD(client.getFD(), EPOLLHUP | EPOLLRDHUP | EPOLLIN, clientCallback);
152
153     BOOST_CHECK(goodMessage.wait(TIMEOUT));
154     BOOST_CHECK(remoteClosed.wait(TIMEOUT));
155
156     poll.removeFD(listen.getFD());
157 }
158
159 BOOST_AUTO_TEST_CASE(ThreadedPollSocket)
160 {
161     Latch goodMessage;
162     Latch remoteClosed;
163
164     EventPoll poll;
165     ThreadPollDispatcher dispatcher(poll);
166
167     doSocketTest(poll, goodMessage, remoteClosed);
168 }
169
170 BOOST_AUTO_TEST_CASE(GlibPollSocket)
171 {
172     Latch goodMessage;
173     Latch remoteClosed;
174
175     ScopedGlibLoop loop;
176
177     EventPoll poll;
178     GlibPollDispatcher dispatcher(poll);
179
180     doSocketTest(poll, goodMessage, remoteClosed);
181 }
182
183 BOOST_AUTO_TEST_CASE(PollStacking)
184 {
185     Latch goodMessage;
186     Latch remoteClosed;
187
188     EventPoll outer;
189     EventPoll inner;
190
191     auto dispatchInner = [&](int, EventPoll::Events) -> bool {
192         inner.dispatchIteration(0);
193         return true;
194     };
195
196     outer.addFD(inner.getPollFD(), EPOLLIN, dispatchInner);
197
198     ThreadPollDispatcher dispatcher(outer);
199     doSocketTest(inner, goodMessage, remoteClosed);
200
201     outer.removeFD(inner.getPollFD());
202 }
203
204 BOOST_AUTO_TEST_SUITE_END()
205