source: mainline/uspace/lib/system/test/system.c@ a72f3b8

Last change on this file since a72f3b8 was a72f3b8, checked in by Jiri Svoboda <jiri@…>, 8 months ago

System protocol library, incl. unit tests

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/*
2 * Copyright (c) 2024 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <async.h>
30#include <errno.h>
31#include <fibril_synch.h>
32#include <loc.h>
33#include <pcut/pcut.h>
34#include <str.h>
35#include <system.h>
36#include <system_srv.h>
37#include "../private/system.h"
38
39PCUT_INIT;
40
41PCUT_TEST_SUITE(system);
42
43static const char *test_system_server = "test-system";
44static const char *test_system_svc = "test/system";
45
46void test_system_conn(ipc_call_t *, void *);
47
48static errno_t test_shutdown(void *);
49
50static void test_sys_shutdown_complete(void *);
51static void test_sys_shutdown_failed(void *);
52
53static system_ops_t test_system_srv_ops = {
54 .shutdown = test_shutdown
55};
56
57system_cb_t test_system_cb = {
58 .shutdown_complete = test_sys_shutdown_complete,
59 .shutdown_failed = test_sys_shutdown_failed
60};
61
62/** Describes to the server how to respond to our request and pass tracking
63 * data back to the client.
64 */
65typedef struct {
66 errno_t rc;
67
68 bool shutdown_called;
69 bool shutdown_complete_called;
70 bool shutdown_failed_called;
71
72 fibril_condvar_t event_cv;
73 fibril_mutex_t event_lock;
74 system_srv_t *srv;
75} test_response_t;
76
77/** system_open(), system_close() work for valid system control service */
78PCUT_TEST(open_close)
79{
80 errno_t rc;
81 service_id_t sid;
82 system_t *system = NULL;
83 test_response_t resp;
84 loc_srv_t *srv;
85
86 async_set_fallback_port_handler(test_system_conn, &resp);
87
88 // FIXME This causes this test to be non-reentrant!
89 rc = loc_server_register(test_system_server, &srv);
90 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
91
92 rc = loc_service_register(srv, test_system_svc, &sid);
93 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
94
95 rc = system_open(test_system_svc, NULL, NULL, &system);
96 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
97 PCUT_ASSERT_NOT_NULL(system);
98
99 system_close(system);
100 rc = loc_service_unregister(srv, sid);
101 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
102 loc_server_unregister(srv);
103}
104
105/** system_shutdown() with server returning error response works */
106PCUT_TEST(shutdown_failure)
107{
108 errno_t rc;
109 service_id_t sid;
110 system_t *system = NULL;
111 test_response_t resp;
112 loc_srv_t *srv;
113
114 async_set_fallback_port_handler(test_system_conn, &resp);
115
116 // FIXME This causes this test to be non-reentrant!
117 rc = loc_server_register(test_system_server, &srv);
118 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
119
120 rc = loc_service_register(srv, test_system_svc, &sid);
121 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
122
123 rc = system_open(test_system_svc, NULL, NULL, &system);
124 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
125 PCUT_ASSERT_NOT_NULL(system);
126
127 resp.rc = ENOMEM;
128 resp.shutdown_called = false;
129
130 rc = system_shutdown(system);
131 PCUT_ASSERT_TRUE(resp.shutdown_called);
132 PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
133
134 system_close(system);
135 rc = loc_service_unregister(srv, sid);
136 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
137 loc_server_unregister(srv);
138}
139
140/** system_shutdown() with server returning success response works */
141PCUT_TEST(shutdown_success)
142{
143 errno_t rc;
144 service_id_t sid;
145 system_t *system = NULL;
146 test_response_t resp;
147 loc_srv_t *srv;
148
149 async_set_fallback_port_handler(test_system_conn, &resp);
150
151 // FIXME This causes this test to be non-reentrant!
152 rc = loc_server_register(test_system_server, &srv);
153 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
154
155 rc = loc_service_register(srv, test_system_svc, &sid);
156 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
157
158 rc = system_open(test_system_svc, NULL, NULL, &system);
159 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
160 PCUT_ASSERT_NOT_NULL(system);
161
162 resp.rc = EOK;
163 resp.shutdown_called = false;
164
165 rc = system_shutdown(system);
166 PCUT_ASSERT_TRUE(resp.shutdown_called);
167 PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
168
169 system_close(system);
170 rc = loc_service_unregister(srv, sid);
171 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
172 loc_server_unregister(srv);
173}
174
175/** 'Shutdown complete' event is delivered from server to client callback
176 * function.
177 */
178PCUT_TEST(shutdown_complete)
179{
180 errno_t rc;
181 service_id_t sid;
182 system_t *system = NULL;
183 test_response_t resp;
184 loc_srv_t *srv;
185
186 async_set_fallback_port_handler(test_system_conn, &resp);
187
188 // FIXME This causes this test to be non-reentrant!
189 rc = loc_server_register(test_system_server, &srv);
190 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
191
192 rc = loc_service_register(srv, test_system_svc, &sid);
193 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
194
195 rc = system_open(test_system_svc, &test_system_cb, &resp, &system);
196 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
197 PCUT_ASSERT_NOT_NULL(system);
198 PCUT_ASSERT_NOT_NULL(resp.srv);
199
200 resp.shutdown_complete_called = false;
201 fibril_mutex_initialize(&resp.event_lock);
202 fibril_condvar_initialize(&resp.event_cv);
203 system_srv_shutdown_complete(resp.srv);
204
205 /* Wait for the event handler to be called. */
206 fibril_mutex_lock(&resp.event_lock);
207 while (!resp.shutdown_complete_called) {
208 fibril_condvar_wait(&resp.event_cv, &resp.event_lock);
209 }
210 fibril_mutex_unlock(&resp.event_lock);
211
212 system_close(system);
213
214 rc = loc_service_unregister(srv, sid);
215 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
216 loc_server_unregister(srv);
217}
218
219/** 'Shutdown failed' event is delivered from server to client callback
220 * function.
221 */
222PCUT_TEST(shutdown_failed)
223{
224 errno_t rc;
225 service_id_t sid;
226 system_t *system = NULL;
227 test_response_t resp;
228 loc_srv_t *srv;
229
230 async_set_fallback_port_handler(test_system_conn, &resp);
231
232 // FIXME This causes this test to be non-reentrant!
233 rc = loc_server_register(test_system_server, &srv);
234 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
235
236 rc = loc_service_register(srv, test_system_svc, &sid);
237 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
238
239 rc = system_open(test_system_svc, &test_system_cb, &resp, &system);
240 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
241 PCUT_ASSERT_NOT_NULL(system);
242 PCUT_ASSERT_NOT_NULL(resp.srv);
243
244 resp.shutdown_failed_called = false;
245 fibril_mutex_initialize(&resp.event_lock);
246 fibril_condvar_initialize(&resp.event_cv);
247 system_srv_shutdown_failed(resp.srv);
248
249 /* Wait for the event handler to be called. */
250 fibril_mutex_lock(&resp.event_lock);
251 while (!resp.shutdown_failed_called) {
252 fibril_condvar_wait(&resp.event_cv, &resp.event_lock);
253 }
254 fibril_mutex_unlock(&resp.event_lock);
255
256 system_close(system);
257
258 rc = loc_service_unregister(srv, sid);
259 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
260 loc_server_unregister(srv);
261}
262
263/** Test system control service connection. */
264void test_system_conn(ipc_call_t *icall, void *arg)
265{
266 test_response_t *resp = (test_response_t *)arg;
267 system_srv_t srv;
268
269 /* Set up protocol structure */
270 system_srv_initialize(&srv);
271 srv.ops = &test_system_srv_ops;
272 srv.arg = arg;
273 resp->srv = &srv;
274
275 /* Handle connection */
276 system_conn(icall, &srv);
277
278 resp->srv = NULL;
279}
280
281/** Test system shutdown.
282 *
283 * @param arg Argument (test_response_t *)
284 */
285static errno_t test_shutdown(void *arg)
286{
287 test_response_t *resp = (test_response_t *)arg;
288
289 resp->shutdown_called = true;
290 return resp->rc;
291}
292
293/** Test system shutdown complete.
294 *
295 * @param arg Argument (test_response_t *)
296 */
297static void test_sys_shutdown_complete(void *arg)
298{
299 test_response_t *resp = (test_response_t *)arg;
300
301 resp->shutdown_complete_called = true;
302 fibril_condvar_signal(&resp->event_cv);
303}
304
305/** Test system shutdown failed.
306 *
307 * @param arg Argument (test_response_t *)
308 */
309static void test_sys_shutdown_failed(void *arg)
310{
311 test_response_t *resp = (test_response_t *)arg;
312
313 resp->shutdown_failed_called = true;
314}
315
316PCUT_EXPORT(system);
Note: See TracBrowser for help on using the repository browser.