Optimize openssl initialization
[platform/core/security/key-manager.git] / tests / test_descriptor-set.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16 /*
17  * @file       test_descriptor-set.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #include <unistd.h>
23 #include <errno.h>
24 #include <string.h>
25
26 #include <thread>
27 #include <memory>
28
29 #include <boost/test/unit_test.hpp>
30 #include <boost/test/results_reporter.hpp>
31
32 #include <test_common.h>
33 #include <test_watched-thread.h>
34
35 #include <descriptor-set.h>
36
37 using namespace CKM;
38
39 namespace {
40
41 const int POLL_TIMEOUT = 8000;
42 const int POLL_TIMEOUT_SHORT = 1000;
43
44 typedef std::unique_ptr<int[], std::function<void(int *)>> PipePtr;
45
46 const short POLLALL = std::numeric_limits<short>::max();
47
48 void closePipe(int* fd) {
49     close(fd[0]);
50     close(fd[1]);
51 }
52
53 /*
54  * Declares pipe descriptor array
55  * Creates pipe and checks for error
56  * Wraps pipe in unique_ptr
57  */
58 #define PIPE(fd) \
59     int (fd)[2]; \
60     BOOST_REQUIRE_MESSAGE(0 == pipe((fd)),"Pipe creation failed: " << strerror(errno)); \
61     PipePtr fd##Ptr((fd), closePipe);
62
63 void unexpectedCallback(int, short) {
64     BOOST_FAIL("Unexpected callback");
65 }
66
67 void readFd(int fd, int expectedFd, short revents) {
68     char buf[1];
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));
73 }
74
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));
80 }
81
82 } // anonymous namespace
83
84 BOOST_AUTO_TEST_SUITE(DESCRIPTOR_SET_TEST)
85
86 /*
87  * Wait on empty descriptor set. Function should return immediately.
88  */
89 BOOST_AUTO_TEST_CASE(T010_Empty) {
90     DescriptorSet descriptors;
91
92     BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
93 }
94
95 /*
96  * Add and remove (twice) descriptor. Wait on empty set. No callback should be called. wait() should
97  * return immediately.
98  */
99 BOOST_AUTO_TEST_CASE(T020_AddRemove) {
100     DescriptorSet descriptors;
101     descriptors.add(10, POLLALL, unexpectedCallback);
102     descriptors.remove(10);
103     descriptors.remove(10);
104
105     BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
106 }
107
108 /*
109  * Add 2 descriptors and purge all. Wait on empty set. No callback should be called. wait() should
110  * return immediately.
111  */
112 BOOST_AUTO_TEST_CASE(T030_AddPurge) {
113     DescriptorSet descriptors;
114     descriptors.add(10, POLLALL, unexpectedCallback);
115     descriptors.add(20, POLLALL, unexpectedCallback);
116     descriptors.purge();
117
118     BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
119 }
120
121 /*
122  * Add pipe[1] descriptor and wait for write possibility. Provided callback should be called
123  * immediately.
124  */
125 BOOST_AUTO_TEST_CASE(T040_Callback) {
126     DescriptorSet descriptors;
127     bool callback = false;
128
129     PIPE(fd);
130
131     descriptors.add(fd[1],POLLALL, [&callback](int, short revents)
132     {
133         callback = true;
134         BOOST_REQUIRE_MESSAGE(revents & POLLOUT, "Not able to write");
135     });
136
137     BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
138     BOOST_REQUIRE_MESSAGE(callback, "Callback was not called");
139 }
140
141 /*
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.
144  */
145 BOOST_AUTO_TEST_CASE(T050_DoubleAdd) {
146     DescriptorSet descriptors;
147     bool callback = false;
148
149     PIPE(fd);
150
151     descriptors.add(fd[1], POLLALL, unexpectedCallback);
152     descriptors.add(fd[1], POLLALL, [&callback](int, short revents)
153     {
154         callback = true;
155         BOOST_REQUIRE_MESSAGE(revents & POLLOUT, "Not able to write");
156     });
157
158     BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
159     BOOST_REQUIRE_MESSAGE(callback, "Callback was not called");
160 }
161
162 /*
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.
165  */
166 BOOST_AUTO_TEST_CASE(T060_Timeout) {
167     DescriptorSet descriptors;
168
169     PIPE(fd);
170
171     descriptors.add(fd[0],POLLALL, unexpectedCallback);
172
173     BOOST_REQUIRE_THROW(descriptors.wait(POLL_TIMEOUT_SHORT), CKM::DescriptorSet::Timeout);
174 }
175
176 /*
177  * Create pipe and try to write it. Start thread that will read it.
178  */
179 BOOST_AUTO_TEST_CASE(T070_Write) {
180     DescriptorSet descriptors;
181     bool callback = false;
182
183     PIPE(fd);
184
185     descriptors.add(fd[1],POLLOUT, [&fd, &callback](int desc, short revents)
186     {
187         callback = true;
188         writeFd(desc, fd[1], revents);
189     } );
190
191     {
192         auto thread = CreateWatchedThread([fd]
193         {
194             char buf[1];
195             ssize_t tmp = TEMP_FAILURE_RETRY(read(fd[0], buf, 1));
196             THREAD_REQUIRE_MESSAGE(tmp == 1, "Pipe reading failed " << strerror(errno));
197         });
198
199         BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
200     }
201
202     BOOST_REQUIRE_MESSAGE(callback, "Callback not called");
203 }
204
205 /*
206  * Create pipe and try to read it. Start thread that will write it.
207  */
208 BOOST_AUTO_TEST_CASE(T080_Read) {
209     DescriptorSet descriptors;
210     bool callback = false;
211
212     PIPE(fd);
213
214     descriptors.add(fd[0],POLLIN, [&](int desc, short revents)
215     {
216         callback = true;
217         readFd(desc, fd[0], revents);
218     } );
219
220     {
221         auto thread = CreateWatchedThread([fd]
222         {
223             ssize_t tmp = TEMP_FAILURE_RETRY(write(fd[1], "j", 1));
224             THREAD_REQUIRE_MESSAGE(tmp == 1, "Pipe writing failed " << strerror(errno));
225         });
226
227         BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
228     }
229
230     BOOST_REQUIRE_MESSAGE(callback, "Callback not called");
231 }
232
233 /*
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.
237  */
238 BOOST_AUTO_TEST_CASE(T090_WriteAfterRead) {
239     DescriptorSet descriptors;
240     bool callback1 = false;
241     bool callback2 = false;
242
243     PIPE(fd);
244     PIPE(fd2);
245
246     descriptors.add(fd[0],POLLIN, [&](int desc, short revents)
247     {
248         callback1 = true;
249         readFd(desc, fd[0], revents);
250
251         descriptors.remove(desc);
252         descriptors.add(fd2[1],POLLOUT, [&](int desc, short revents) {
253             callback2 = true;
254             writeFd(desc, fd2[1], revents);
255             descriptors.remove(desc);
256         } );
257     } );
258
259     {
260         auto thread = CreateWatchedThread([fd,fd2]
261         {
262             ssize_t tmp = TEMP_FAILURE_RETRY(write(fd[1], "j", 1));
263             BOOST_REQUIRE_MESSAGE(tmp == 1, "Pipe writing failed " << strerror(errno));
264
265             char buf[1];
266             tmp = TEMP_FAILURE_RETRY(read(fd2[0], buf, 1));
267             THREAD_REQUIRE_MESSAGE(tmp == 1, "Pipe reading failed " << strerror(errno));
268         });
269
270         BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
271         BOOST_REQUIRE_NO_THROW(descriptors.wait(POLL_TIMEOUT));
272     }
273
274     BOOST_REQUIRE_MESSAGE(callback1, "First callback not called");
275     BOOST_REQUIRE_MESSAGE(callback2, "Second callback not called");
276 }
277
278 BOOST_AUTO_TEST_SUITE_END()