1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*344aa361SAndroid Build Coastguard Worker *
4*344aa361SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker *
12*344aa361SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker *
15*344aa361SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker */
23*344aa361SAndroid Build Coastguard Worker
24*344aa361SAndroid Build Coastguard Worker #include <lib/unittest/unittest.h>
25*344aa361SAndroid Build Coastguard Worker
26*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/handle_set.h>
27*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/ipc.h>
28*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/ipc_msg.h>
29*344aa361SAndroid Build Coastguard Worker #include <stddef.h>
30*344aa361SAndroid Build Coastguard Worker #include <stdio.h>
31*344aa361SAndroid Build Coastguard Worker #include <stdlib.h>
32*344aa361SAndroid Build Coastguard Worker #include <string.h>
33*344aa361SAndroid Build Coastguard Worker
34*344aa361SAndroid Build Coastguard Worker #include <uapi/err.h>
35*344aa361SAndroid Build Coastguard Worker
36*344aa361SAndroid Build Coastguard Worker #define LOCAL_TRACE (0)
37*344aa361SAndroid Build Coastguard Worker
38*344aa361SAndroid Build Coastguard Worker #include <lk/trace.h>
39*344aa361SAndroid Build Coastguard Worker
40*344aa361SAndroid Build Coastguard Worker #define MAX_PORT_BUF_SIZE 4096 /* max size of per port buffer */
41*344aa361SAndroid Build Coastguard Worker
42*344aa361SAndroid Build Coastguard Worker enum test_message_header {
43*344aa361SAndroid Build Coastguard Worker TEST_PASSED = 0,
44*344aa361SAndroid Build Coastguard Worker TEST_FAILED = 1,
45*344aa361SAndroid Build Coastguard Worker TEST_MESSAGE = 2,
46*344aa361SAndroid Build Coastguard Worker TEST_MESSAGE_HEADER_COUNT = 3,
47*344aa361SAndroid Build Coastguard Worker };
48*344aa361SAndroid Build Coastguard Worker
49*344aa361SAndroid Build Coastguard Worker static struct handle* ipc_printf_handle;
50*344aa361SAndroid Build Coastguard Worker static struct mutex unittest_lock = MUTEX_INITIAL_VALUE(unittest_lock);
51*344aa361SAndroid Build Coastguard Worker static struct handle* unittest_handle_set;
52*344aa361SAndroid Build Coastguard Worker static thread_t* unittest_thread;
53*344aa361SAndroid Build Coastguard Worker
get_current_time_ns(void)54*344aa361SAndroid Build Coastguard Worker uint64_t get_current_time_ns(void) {
55*344aa361SAndroid Build Coastguard Worker return current_time_ns();
56*344aa361SAndroid Build Coastguard Worker }
57*344aa361SAndroid Build Coastguard Worker
send_msg_wait(struct handle * handle,struct ipc_msg_kern * msg)58*344aa361SAndroid Build Coastguard Worker static int send_msg_wait(struct handle* handle, struct ipc_msg_kern* msg) {
59*344aa361SAndroid Build Coastguard Worker int ret;
60*344aa361SAndroid Build Coastguard Worker uint32_t event;
61*344aa361SAndroid Build Coastguard Worker
62*344aa361SAndroid Build Coastguard Worker ASSERT(is_mutex_held(&unittest_lock));
63*344aa361SAndroid Build Coastguard Worker
64*344aa361SAndroid Build Coastguard Worker ret = ipc_send_msg(handle, msg);
65*344aa361SAndroid Build Coastguard Worker if (ret != ERR_NOT_ENOUGH_BUFFER) {
66*344aa361SAndroid Build Coastguard Worker return ret;
67*344aa361SAndroid Build Coastguard Worker }
68*344aa361SAndroid Build Coastguard Worker
69*344aa361SAndroid Build Coastguard Worker ret = handle_wait(handle, &event, INFINITE_TIME);
70*344aa361SAndroid Build Coastguard Worker if (ret < 0) {
71*344aa361SAndroid Build Coastguard Worker return ret;
72*344aa361SAndroid Build Coastguard Worker }
73*344aa361SAndroid Build Coastguard Worker
74*344aa361SAndroid Build Coastguard Worker if (event & IPC_HANDLE_POLL_SEND_UNBLOCKED) {
75*344aa361SAndroid Build Coastguard Worker return ipc_send_msg(handle, msg);
76*344aa361SAndroid Build Coastguard Worker }
77*344aa361SAndroid Build Coastguard Worker
78*344aa361SAndroid Build Coastguard Worker if (event & IPC_HANDLE_POLL_MSG) {
79*344aa361SAndroid Build Coastguard Worker return ERR_BUSY;
80*344aa361SAndroid Build Coastguard Worker }
81*344aa361SAndroid Build Coastguard Worker
82*344aa361SAndroid Build Coastguard Worker if (event & IPC_HANDLE_POLL_HUP) {
83*344aa361SAndroid Build Coastguard Worker return ERR_CHANNEL_CLOSED;
84*344aa361SAndroid Build Coastguard Worker }
85*344aa361SAndroid Build Coastguard Worker
86*344aa361SAndroid Build Coastguard Worker return ret;
87*344aa361SAndroid Build Coastguard Worker }
88*344aa361SAndroid Build Coastguard Worker
89*344aa361SAndroid Build Coastguard Worker /**
90*344aa361SAndroid Build Coastguard Worker * unittest_printf - Print a message that gets sent back to the client
91*344aa361SAndroid Build Coastguard Worker * @fmt: Format string.
92*344aa361SAndroid Build Coastguard Worker *
93*344aa361SAndroid Build Coastguard Worker * Print a message that gets sent back to the currently connected client. Should
94*344aa361SAndroid Build Coastguard Worker * only be called while the run_test function registered with unittest_add runs.
95*344aa361SAndroid Build Coastguard Worker * The length of the formatted string is limited to 254 bytes.
96*344aa361SAndroid Build Coastguard Worker *
97*344aa361SAndroid Build Coastguard Worker * Return: Formatted string length or (negative) error code.
98*344aa361SAndroid Build Coastguard Worker */
unittest_printf(const char * fmt,...)99*344aa361SAndroid Build Coastguard Worker int unittest_printf(const char* fmt, ...) {
100*344aa361SAndroid Build Coastguard Worker char buf[256];
101*344aa361SAndroid Build Coastguard Worker struct iovec_kern tx_iov = {buf, 1};
102*344aa361SAndroid Build Coastguard Worker struct ipc_msg_kern tx_msg = {1, &tx_iov, 0, NULL};
103*344aa361SAndroid Build Coastguard Worker va_list ap;
104*344aa361SAndroid Build Coastguard Worker int ret;
105*344aa361SAndroid Build Coastguard Worker int slen;
106*344aa361SAndroid Build Coastguard Worker
107*344aa361SAndroid Build Coastguard Worker va_start(ap, fmt);
108*344aa361SAndroid Build Coastguard Worker /* Format string into buf[1...]. buf[0] contains the message header. */
109*344aa361SAndroid Build Coastguard Worker ret = vsnprintf(buf + 1, sizeof(buf) - 1, fmt, ap);
110*344aa361SAndroid Build Coastguard Worker va_end(ap);
111*344aa361SAndroid Build Coastguard Worker
112*344aa361SAndroid Build Coastguard Worker if (ret < 0) {
113*344aa361SAndroid Build Coastguard Worker return ret;
114*344aa361SAndroid Build Coastguard Worker }
115*344aa361SAndroid Build Coastguard Worker
116*344aa361SAndroid Build Coastguard Worker /*
117*344aa361SAndroid Build Coastguard Worker * vsnprintf returns the length of the string it would produce if the buffer
118*344aa361SAndroid Build Coastguard Worker * was big enough. Compute the actual string length by clamping the return
119*344aa361SAndroid Build Coastguard Worker * value to the largest string that can fit in the buffer.
120*344aa361SAndroid Build Coastguard Worker */
121*344aa361SAndroid Build Coastguard Worker slen = MIN(ret, (int)sizeof(buf) - 1 - 1);
122*344aa361SAndroid Build Coastguard Worker
123*344aa361SAndroid Build Coastguard Worker buf[0] = TEST_MESSAGE;
124*344aa361SAndroid Build Coastguard Worker tx_iov.iov_len = 1 + slen;
125*344aa361SAndroid Build Coastguard Worker mutex_acquire(&unittest_lock);
126*344aa361SAndroid Build Coastguard Worker ret = send_msg_wait(ipc_printf_handle, &tx_msg);
127*344aa361SAndroid Build Coastguard Worker mutex_release(&unittest_lock);
128*344aa361SAndroid Build Coastguard Worker if (ret < 0) {
129*344aa361SAndroid Build Coastguard Worker return ret;
130*344aa361SAndroid Build Coastguard Worker }
131*344aa361SAndroid Build Coastguard Worker
132*344aa361SAndroid Build Coastguard Worker return slen;
133*344aa361SAndroid Build Coastguard Worker }
134*344aa361SAndroid Build Coastguard Worker
135*344aa361SAndroid Build Coastguard Worker /**
136*344aa361SAndroid Build Coastguard Worker * unittest_loop - Thread function handling all kernel unit-tests
137*344aa361SAndroid Build Coastguard Worker * arg: Unused thread argument.
138*344aa361SAndroid Build Coastguard Worker *
139*344aa361SAndroid Build Coastguard Worker * Wait on handle-set for a client to connect. When a client connects, run the
140*344aa361SAndroid Build Coastguard Worker * test function for the port the client connected to then sent the test status
141*344aa361SAndroid Build Coastguard Worker * back to the client. The test function can call unittest_printf to send text
142*344aa361SAndroid Build Coastguard Worker * back to the client.
143*344aa361SAndroid Build Coastguard Worker *
144*344aa361SAndroid Build Coastguard Worker * Return: error code is there was an unexpected error.
145*344aa361SAndroid Build Coastguard Worker */
unittest_loop(void * arg)146*344aa361SAndroid Build Coastguard Worker static int unittest_loop(void* arg) {
147*344aa361SAndroid Build Coastguard Worker int ret;
148*344aa361SAndroid Build Coastguard Worker struct handle* chandle;
149*344aa361SAndroid Build Coastguard Worker struct handle_ref evt;
150*344aa361SAndroid Build Coastguard Worker const uuid_t* unused_uuid_p;
151*344aa361SAndroid Build Coastguard Worker struct unittest* test;
152*344aa361SAndroid Build Coastguard Worker
153*344aa361SAndroid Build Coastguard Worker LTRACEF("waiting for connection\n");
154*344aa361SAndroid Build Coastguard Worker for (;;) {
155*344aa361SAndroid Build Coastguard Worker ret = handle_set_wait(unittest_handle_set, &evt, INFINITE_TIME);
156*344aa361SAndroid Build Coastguard Worker if (ret < 0) {
157*344aa361SAndroid Build Coastguard Worker TRACEF("handle_set_wait failed: %d\n", ret);
158*344aa361SAndroid Build Coastguard Worker break;
159*344aa361SAndroid Build Coastguard Worker }
160*344aa361SAndroid Build Coastguard Worker test = evt.cookie;
161*344aa361SAndroid Build Coastguard Worker LTRACEF("got event (ret=%d): ev=%x handle=%p port=%s\n", ret, evt.emask,
162*344aa361SAndroid Build Coastguard Worker evt.handle, test->port_name);
163*344aa361SAndroid Build Coastguard Worker if (evt.emask & IPC_HANDLE_POLL_READY) {
164*344aa361SAndroid Build Coastguard Worker /* get connection request */
165*344aa361SAndroid Build Coastguard Worker ret = ipc_port_accept(evt.handle, &chandle, &unused_uuid_p);
166*344aa361SAndroid Build Coastguard Worker LTRACEF("accept returned %d\n", ret);
167*344aa361SAndroid Build Coastguard Worker if (ret >= 0) {
168*344aa361SAndroid Build Coastguard Worker char tx_buffer[1];
169*344aa361SAndroid Build Coastguard Worker struct iovec_kern tx_iov = {
170*344aa361SAndroid Build Coastguard Worker tx_buffer,
171*344aa361SAndroid Build Coastguard Worker sizeof(tx_buffer),
172*344aa361SAndroid Build Coastguard Worker };
173*344aa361SAndroid Build Coastguard Worker struct ipc_msg_kern tx_msg = {1, &tx_iov, 0, NULL};
174*344aa361SAndroid Build Coastguard Worker
175*344aa361SAndroid Build Coastguard Worker /* then run unittest test */
176*344aa361SAndroid Build Coastguard Worker ipc_printf_handle = chandle;
177*344aa361SAndroid Build Coastguard Worker tx_buffer[0] = test->run_test(test) ? TEST_PASSED : TEST_FAILED;
178*344aa361SAndroid Build Coastguard Worker mutex_acquire(&unittest_lock);
179*344aa361SAndroid Build Coastguard Worker ipc_printf_handle = NULL;
180*344aa361SAndroid Build Coastguard Worker
181*344aa361SAndroid Build Coastguard Worker send_msg_wait(chandle, &tx_msg);
182*344aa361SAndroid Build Coastguard Worker mutex_release(&unittest_lock);
183*344aa361SAndroid Build Coastguard Worker
184*344aa361SAndroid Build Coastguard Worker /* and close it */
185*344aa361SAndroid Build Coastguard Worker handle_close(chandle);
186*344aa361SAndroid Build Coastguard Worker }
187*344aa361SAndroid Build Coastguard Worker }
188*344aa361SAndroid Build Coastguard Worker }
189*344aa361SAndroid Build Coastguard Worker
190*344aa361SAndroid Build Coastguard Worker return ret;
191*344aa361SAndroid Build Coastguard Worker }
192*344aa361SAndroid Build Coastguard Worker
193*344aa361SAndroid Build Coastguard Worker /**
194*344aa361SAndroid Build Coastguard Worker * unittest_add_locked - Internal helper function to add a kernel unit-test
195*344aa361SAndroid Build Coastguard Worker * @test: See unittest_add.
196*344aa361SAndroid Build Coastguard Worker *
197*344aa361SAndroid Build Coastguard Worker * unittest_lock must be locked before calling this.
198*344aa361SAndroid Build Coastguard Worker *
199*344aa361SAndroid Build Coastguard Worker * Return: See unittest_add.
200*344aa361SAndroid Build Coastguard Worker */
unittest_add_locked(struct unittest * test)201*344aa361SAndroid Build Coastguard Worker static int unittest_add_locked(struct unittest* test) {
202*344aa361SAndroid Build Coastguard Worker int ret;
203*344aa361SAndroid Build Coastguard Worker struct handle* phandle;
204*344aa361SAndroid Build Coastguard Worker
205*344aa361SAndroid Build Coastguard Worker ASSERT(is_mutex_held(&unittest_lock));
206*344aa361SAndroid Build Coastguard Worker
207*344aa361SAndroid Build Coastguard Worker if (!unittest_handle_set) {
208*344aa361SAndroid Build Coastguard Worker unittest_handle_set = handle_set_create();
209*344aa361SAndroid Build Coastguard Worker if (!unittest_handle_set) {
210*344aa361SAndroid Build Coastguard Worker ret = ERR_NO_MEMORY;
211*344aa361SAndroid Build Coastguard Worker goto err_handle_set_create;
212*344aa361SAndroid Build Coastguard Worker }
213*344aa361SAndroid Build Coastguard Worker }
214*344aa361SAndroid Build Coastguard Worker ret = ipc_port_create(&kernel_uuid, test->port_name, 1, MAX_PORT_BUF_SIZE,
215*344aa361SAndroid Build Coastguard Worker IPC_PORT_ALLOW_NS_CONNECT | IPC_PORT_ALLOW_TA_CONNECT,
216*344aa361SAndroid Build Coastguard Worker &phandle);
217*344aa361SAndroid Build Coastguard Worker if (ret) {
218*344aa361SAndroid Build Coastguard Worker goto err_port_create;
219*344aa361SAndroid Build Coastguard Worker }
220*344aa361SAndroid Build Coastguard Worker
221*344aa361SAndroid Build Coastguard Worker ret = ipc_port_publish(phandle);
222*344aa361SAndroid Build Coastguard Worker if (ret) {
223*344aa361SAndroid Build Coastguard Worker goto err_port_publish;
224*344aa361SAndroid Build Coastguard Worker }
225*344aa361SAndroid Build Coastguard Worker handle_incref(phandle);
226*344aa361SAndroid Build Coastguard Worker test->_href.handle = phandle;
227*344aa361SAndroid Build Coastguard Worker test->_href.emask = ~0U;
228*344aa361SAndroid Build Coastguard Worker test->_href.cookie = test;
229*344aa361SAndroid Build Coastguard Worker ret = handle_set_attach(unittest_handle_set, &test->_href);
230*344aa361SAndroid Build Coastguard Worker if (ret < 0) {
231*344aa361SAndroid Build Coastguard Worker goto err_handle_set_attach;
232*344aa361SAndroid Build Coastguard Worker }
233*344aa361SAndroid Build Coastguard Worker LTRACEF("added port %s handle, %p, to handleset %p\n", test->port_name,
234*344aa361SAndroid Build Coastguard Worker test->_href.handle, unittest_handle_set);
235*344aa361SAndroid Build Coastguard Worker
236*344aa361SAndroid Build Coastguard Worker if (!unittest_thread) {
237*344aa361SAndroid Build Coastguard Worker unittest_thread = thread_create("unittest", unittest_loop, NULL,
238*344aa361SAndroid Build Coastguard Worker HIGH_PRIORITY, DEFAULT_STACK_SIZE);
239*344aa361SAndroid Build Coastguard Worker if (!unittest_thread) {
240*344aa361SAndroid Build Coastguard Worker ret = ERR_NO_MEMORY;
241*344aa361SAndroid Build Coastguard Worker goto err_thread_create;
242*344aa361SAndroid Build Coastguard Worker }
243*344aa361SAndroid Build Coastguard Worker thread_resume(unittest_thread);
244*344aa361SAndroid Build Coastguard Worker }
245*344aa361SAndroid Build Coastguard Worker return 0;
246*344aa361SAndroid Build Coastguard Worker
247*344aa361SAndroid Build Coastguard Worker err_thread_create:
248*344aa361SAndroid Build Coastguard Worker handle_set_detach_ref(&test->_href);
249*344aa361SAndroid Build Coastguard Worker err_handle_set_attach:
250*344aa361SAndroid Build Coastguard Worker handle_decref(phandle);
251*344aa361SAndroid Build Coastguard Worker err_port_publish:
252*344aa361SAndroid Build Coastguard Worker handle_close(phandle);
253*344aa361SAndroid Build Coastguard Worker err_port_create:
254*344aa361SAndroid Build Coastguard Worker err_handle_set_create:
255*344aa361SAndroid Build Coastguard Worker TRACEF("Failed to add unittest: %d\n", ret);
256*344aa361SAndroid Build Coastguard Worker return ret;
257*344aa361SAndroid Build Coastguard Worker }
258*344aa361SAndroid Build Coastguard Worker
259*344aa361SAndroid Build Coastguard Worker /**
260*344aa361SAndroid Build Coastguard Worker * unittest_add - Add a kernel unit-test
261*344aa361SAndroid Build Coastguard Worker * @test: Test descriptor with port name and callback to start the test when
262*344aa361SAndroid Build Coastguard Worker * a client connects to the port. @test is used after unittest_add
263*344aa361SAndroid Build Coastguard Worker * returns so it must not be a temporary allocation.
264*344aa361SAndroid Build Coastguard Worker *
265*344aa361SAndroid Build Coastguard Worker * Creates a port for @test. when the first test is added, create a handle set
266*344aa361SAndroid Build Coastguard Worker * and thread that will be shared between all tests.
267*344aa361SAndroid Build Coastguard Worker *
268*344aa361SAndroid Build Coastguard Worker * Return: 0 if test was added, error-code otherwise.
269*344aa361SAndroid Build Coastguard Worker */
unittest_add(struct unittest * test)270*344aa361SAndroid Build Coastguard Worker int unittest_add(struct unittest* test) {
271*344aa361SAndroid Build Coastguard Worker int ret;
272*344aa361SAndroid Build Coastguard Worker
273*344aa361SAndroid Build Coastguard Worker mutex_acquire(&unittest_lock);
274*344aa361SAndroid Build Coastguard Worker ret = unittest_add_locked(test);
275*344aa361SAndroid Build Coastguard Worker mutex_release(&unittest_lock);
276*344aa361SAndroid Build Coastguard Worker
277*344aa361SAndroid Build Coastguard Worker return ret;
278*344aa361SAndroid Build Coastguard Worker }
279