2 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 * @file test_descriptor-set.cpp
18 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
29 #include <boost/test/unit_test.hpp>
30 #include <boost/test/results_reporter.hpp>
32 #include <test_common.h>
33 #include <test_watched-thread.h>
35 #include <descriptor-set.h>
36 #include <dpl/errno_string.h>
42 const int POLL_TIMEOUT = 8000;
43 const int POLL_TIMEOUT_SHORT = 1000;
45 typedef std::unique_ptr<int[], std::function<void(int *)>> PipePtr;
47 const short POLLALL = std::numeric_limits<short>::max();
49 void closePipe(int *fd)
56 * Declares pipe descriptor array
57 * Creates pipe and checks for error
58 * Wraps pipe in unique_ptr
62 BOOST_REQUIRE_MESSAGE(0 == pipe((fd)), "Pipe creation failed: " << GetErrnoString()); \
63 PipePtr fd##Ptr((fd), closePipe);
65 void unexpectedCallback(int, short)
67 BOOST_FAIL("Unexpected callback");
70 void readFd(int fd, int expectedFd, short revents)
73 BOOST_REQUIRE_MESSAGE(fd == expectedFd, "Unexpected descriptor");
74 BOOST_REQUIRE_MESSAGE(revents & POLLIN, "Unexpected event");
75 BOOST_REQUIRE_MESSAGE(1 == TEMP_FAILURE_RETRY(read(fd, buf, 1)),
76 "Pipe read failed" << GetErrnoString());
79 void writeFd(int fd, int expectedFd, short revents)
81 BOOST_REQUIRE_MESSAGE(fd == expectedFd, "Unexpected descriptor");
82 BOOST_REQUIRE_MESSAGE(revents & POLLOUT, "Unexpected event");
83 BOOST_REQUIRE_MESSAGE(1 == TEMP_FAILURE_RETRY(write(fd, "j", 1)),
84 "Pipe writing failed" << GetErrnoString());
87 } // anonymous namespace
89 BOOST_AUTO_TEST_SUITE(DESCRIPTOR_SET_TEST)
92 * Wait on empty descriptor set. Function should return immediately.
94 BOOST_AUTO_TEST_CASE(T010_Empty)
96 DescriptorSet descriptors;
98 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
102 * Add and remove (twice) descriptor. Wait on empty set. No callback should be called. wait() should
103 * return immediately.
105 BOOST_AUTO_TEST_CASE(T020_AddRemove)
107 DescriptorSet descriptors;
108 descriptors.add(10, POLLALL, unexpectedCallback);
109 descriptors.remove(10);
110 descriptors.remove(10);
112 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
116 * Add 2 descriptors and purge all. Wait on empty set. No callback should be called. wait() should
117 * return immediately.
119 BOOST_AUTO_TEST_CASE(T030_AddPurge)
121 DescriptorSet descriptors;
122 descriptors.add(10, POLLALL, unexpectedCallback);
123 descriptors.add(20, POLLALL, unexpectedCallback);
126 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
130 * Add pipe[1] descriptor and wait for write possibility. Provided callback should be called
133 BOOST_AUTO_TEST_CASE(T040_Callback)
135 DescriptorSet descriptors;
136 bool callback = false;
140 descriptors.add(fd[1], POLLALL, [&callback](int, short revents) {
142 BOOST_REQUIRE_MESSAGE(revents & POLLOUT, "Not able to write");
145 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
146 BOOST_REQUIRE_MESSAGE(callback, "Callback was not called");
150 * Add pipe[1] descriptor twice with different callbacks. The first one should be overwritten and
151 * shouldn't be called. The second one should be called instead.
153 BOOST_AUTO_TEST_CASE(T050_DoubleAdd)
155 DescriptorSet descriptors;
156 bool callback = false;
160 descriptors.add(fd[1], POLLALL, unexpectedCallback);
161 descriptors.add(fd[1], POLLALL, [&callback](int, short revents) {
163 BOOST_REQUIRE_MESSAGE(revents & POLLOUT, "Not able to write");
166 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
167 BOOST_REQUIRE_MESSAGE(callback, "Callback was not called");
171 * Add pipe[0] descriptor and wait. Callback should not be called. Instead the 8s timeout should
172 * occur and a proper exception should be thrown.
174 BOOST_AUTO_TEST_CASE(T060_Timeout)
176 DescriptorSet descriptors;
180 descriptors.add(fd[0], POLLALL, unexpectedCallback);
182 BOOST_REQUIRE_THROW(descriptors.wait(POLL_TIMEOUT_SHORT),
183 CKM::DescriptorSet::Timeout);
187 * Create pipe and try to write it. Start thread that will read it.
189 BOOST_AUTO_TEST_CASE(T070_Write)
191 DescriptorSet descriptors;
192 bool callback = false;
196 descriptors.add(fd[1], POLLOUT, [&fd, &callback](int desc, short revents) {
198 writeFd(desc, fd[1], revents);
202 auto thread = CreateWatchedThread([fd] {
204 ssize_t tmp = TEMP_FAILURE_RETRY(read(fd[0], buf, 1));
205 THREAD_REQUIRE_MESSAGE(tmp == 1, "Pipe reading failed " << GetErrnoString());
208 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
211 BOOST_REQUIRE_MESSAGE(callback, "Callback not called");
215 * Create pipe and try to read it. Start thread that will write it.
217 BOOST_AUTO_TEST_CASE(T080_Read)
219 DescriptorSet descriptors;
220 bool callback = false;
224 descriptors.add(fd[0], POLLIN, [&](int desc, short revents) {
226 readFd(desc, fd[0], revents);
230 auto thread = CreateWatchedThread([fd] {
231 ssize_t tmp = TEMP_FAILURE_RETRY(write(fd[1], "j", 1));
232 THREAD_REQUIRE_MESSAGE(tmp == 1, "Pipe writing failed " << GetErrnoString());
235 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
238 BOOST_REQUIRE_MESSAGE(callback, "Callback not called");
242 * Create two pipes. Try to read first one. Start the thread that writes it. In the callback read
243 * the pipe, remove it from the descriptor set and try to write the second pipe. The thread will
244 * read it. In second pipe callback remove the second pipe descriptor from the set.
246 BOOST_AUTO_TEST_CASE(T090_WriteAfterRead)
248 DescriptorSet descriptors;
249 bool callback1 = false;
250 bool callback2 = false;
255 descriptors.add(fd[0], POLLIN, [&](int desc, short revents) {
257 readFd(desc, fd[0], revents);
259 descriptors.remove(desc);
260 descriptors.add(fd2[1], POLLOUT, [&](int desc, short revents) {
262 writeFd(desc, fd2[1], revents);
263 descriptors.remove(desc);
268 auto thread = CreateWatchedThread([fd, fd2] {
269 ssize_t tmp = TEMP_FAILURE_RETRY(write(fd[1], "j", 1));
270 BOOST_REQUIRE_MESSAGE(tmp == 1, "Pipe writing failed " << GetErrnoString());
273 tmp = TEMP_FAILURE_RETRY(read(fd2[0], buf, 1));
274 THREAD_REQUIRE_MESSAGE(tmp == 1, "Pipe reading failed " << GetErrnoString());
277 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
278 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
281 BOOST_REQUIRE_MESSAGE(callback1, "First callback not called");
282 BOOST_REQUIRE_MESSAGE(callback2, "Second callback not called");
285 BOOST_AUTO_TEST_SUITE_END()