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>
41 const int POLL_TIMEOUT = 8000;
42 const int POLL_TIMEOUT_SHORT = 1000;
44 typedef std::unique_ptr<int[], std::function<void(int *)>> PipePtr;
46 const short POLLALL = std::numeric_limits<short>::max();
48 void closePipe(int* fd) {
54 * Declares pipe descriptor array
55 * Creates pipe and checks for error
56 * Wraps pipe in unique_ptr
60 BOOST_REQUIRE_MESSAGE(0 == pipe((fd)),"Pipe creation failed: " << strerror(errno)); \
61 PipePtr fd##Ptr((fd), closePipe);
63 void unexpectedCallback(int, short) {
64 BOOST_FAIL("Unexpected callback");
67 void readFd(int fd, int expectedFd, short revents) {
69 BOOST_REQUIRE_MESSAGE(fd == expectedFd, "Unexpected descriptor");
70 BOOST_REQUIRE_MESSAGE(revents & POLLIN, "Unexpected event");
71 BOOST_REQUIRE_MESSAGE(1 == TEMP_FAILURE_RETRY(read(fd,buf,1)),
72 "Pipe read failed" << strerror(errno));
75 void writeFd(int fd, int expectedFd, short revents) {
76 BOOST_REQUIRE_MESSAGE(fd == expectedFd, "Unexpected descriptor");
77 BOOST_REQUIRE_MESSAGE(revents & POLLOUT, "Unexpected event");
78 BOOST_REQUIRE_MESSAGE(1 == TEMP_FAILURE_RETRY(write(fd,"j",1)),
79 "Pipe writing failed" << strerror(errno));
82 } // anonymous namespace
84 BOOST_AUTO_TEST_SUITE(DESCRIPTOR_SET_TEST)
87 * Wait on empty descriptor set. Function should return immediately.
89 BOOST_AUTO_TEST_CASE(T010_Empty) {
90 DescriptorSet descriptors;
92 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
96 * Add and remove (twice) descriptor. Wait on empty set. No callback should be called. wait() should
99 BOOST_AUTO_TEST_CASE(T020_AddRemove) {
100 DescriptorSet descriptors;
101 descriptors.add(10, POLLALL, unexpectedCallback);
102 descriptors.remove(10);
103 descriptors.remove(10);
105 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
109 * Add 2 descriptors and purge all. Wait on empty set. No callback should be called. wait() should
110 * return immediately.
112 BOOST_AUTO_TEST_CASE(T030_AddPurge) {
113 DescriptorSet descriptors;
114 descriptors.add(10, POLLALL, unexpectedCallback);
115 descriptors.add(20, POLLALL, unexpectedCallback);
118 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
122 * Add pipe[1] descriptor and wait for write possibility. Provided callback should be called
125 BOOST_AUTO_TEST_CASE(T040_Callback) {
126 DescriptorSet descriptors;
127 bool callback = false;
131 descriptors.add(fd[1],POLLALL, [&callback](int, short revents)
134 BOOST_REQUIRE_MESSAGE(revents & POLLOUT, "Not able to write");
137 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
138 BOOST_REQUIRE_MESSAGE(callback, "Callback was not called");
142 * Add pipe[1] descriptor twice with different callbacks. The first one should be overwritten and
143 * shouldn't be called. The second one should be called instead.
145 BOOST_AUTO_TEST_CASE(T050_DoubleAdd) {
146 DescriptorSet descriptors;
147 bool callback = false;
151 descriptors.add(fd[1], POLLALL, unexpectedCallback);
152 descriptors.add(fd[1], POLLALL, [&callback](int, short revents)
155 BOOST_REQUIRE_MESSAGE(revents & POLLOUT, "Not able to write");
158 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
159 BOOST_REQUIRE_MESSAGE(callback, "Callback was not called");
163 * Add pipe[0] descriptor and wait. Callback should not be called. Instead the 8s timeout should
164 * occur and a proper exception should be thrown.
166 BOOST_AUTO_TEST_CASE(T060_Timeout) {
167 DescriptorSet descriptors;
171 descriptors.add(fd[0],POLLALL, unexpectedCallback);
173 BOOST_REQUIRE_THROW(descriptors.wait(POLL_TIMEOUT_SHORT), CKM::DescriptorSet::Timeout);
177 * Create pipe and try to write it. Start thread that will read it.
179 BOOST_AUTO_TEST_CASE(T070_Write) {
180 DescriptorSet descriptors;
181 bool callback = false;
185 descriptors.add(fd[1],POLLOUT, [&fd, &callback](int desc, short revents)
188 writeFd(desc, fd[1], revents);
192 auto thread = CreateWatchedThread([fd]
195 ssize_t tmp = TEMP_FAILURE_RETRY(read(fd[0], buf, 1));
196 THREAD_REQUIRE_MESSAGE(tmp == 1, "Pipe reading failed " << strerror(errno));
199 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
202 BOOST_REQUIRE_MESSAGE(callback, "Callback not called");
206 * Create pipe and try to read it. Start thread that will write it.
208 BOOST_AUTO_TEST_CASE(T080_Read) {
209 DescriptorSet descriptors;
210 bool callback = false;
214 descriptors.add(fd[0],POLLIN, [&](int desc, short revents)
217 readFd(desc, fd[0], revents);
221 auto thread = CreateWatchedThread([fd]
223 ssize_t tmp = TEMP_FAILURE_RETRY(write(fd[1], "j", 1));
224 THREAD_REQUIRE_MESSAGE(tmp == 1, "Pipe writing failed " << strerror(errno));
227 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
230 BOOST_REQUIRE_MESSAGE(callback, "Callback not called");
234 * Create two pipes. Try to read first one. Start the thread that writes it. In the callback read
235 * the pipe, remove it from the descriptor set and try to write the second pipe. The thread will
236 * read it. In second pipe callback remove the second pipe descriptor from the set.
238 BOOST_AUTO_TEST_CASE(T090_WriteAfterRead) {
239 DescriptorSet descriptors;
240 bool callback1 = false;
241 bool callback2 = false;
246 descriptors.add(fd[0],POLLIN, [&](int desc, short revents)
249 readFd(desc, fd[0], revents);
251 descriptors.remove(desc);
252 descriptors.add(fd2[1],POLLOUT, [&](int desc, short revents) {
254 writeFd(desc, fd2[1], revents);
255 descriptors.remove(desc);
260 auto thread = CreateWatchedThread([fd,fd2]
262 ssize_t tmp = TEMP_FAILURE_RETRY(write(fd[1], "j", 1));
263 BOOST_REQUIRE_MESSAGE(tmp == 1, "Pipe writing failed " << strerror(errno));
266 tmp = TEMP_FAILURE_RETRY(read(fd2[0], buf, 1));
267 THREAD_REQUIRE_MESSAGE(tmp == 1, "Pipe reading failed " << strerror(errno));
270 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
271 BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
274 BOOST_REQUIRE_MESSAGE(callback1, "First callback not called");
275 BOOST_REQUIRE_MESSAGE(callback2, "Second callback not called");
278 BOOST_AUTO_TEST_SUITE_END()