1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <string.h> 14#include <stdio.h> 15 16#include <sel4/sel4.h> 17#include <vka/capops.h> 18#include <sel4utils/thread.h> 19#include <serial_server/parent.h> 20#include <serial_server/client.h> 21 22#include <sel4test/test.h> 23#include <sel4test/testutil.h> 24 25#define SERSERV_TEST_PRIO_SERVER (seL4_MaxPrio - 1) 26 27static const char *test_str = "Hello, world!\n"; 28 29void get_serial_server_parent_tests() 30{ 31} 32 33static int 34test_server_spawn(struct env *env) 35{ 36 int error; 37 38 error = serial_server_parent_spawn_thread(&env->simple, 39 &env->vka, &env->vspace, 40 SERSERV_TEST_PRIO_SERVER); 41 42 test_eq(error, 0); 43 return sel4test_get_result(); 44} 45DEFINE_TEST(SERSERV_PARENT_001, "Serial server spawn test", test_server_spawn, true) 46 47static int 48test_parent_connect(struct env *env) 49{ 50 int error; 51 serial_client_context_t conn; 52 cspacepath_t badged_server_ep_cspath; 53 54 error = serial_server_parent_spawn_thread(&env->simple, 55 &env->vka, &env->vspace, 56 SERSERV_TEST_PRIO_SERVER); 57 58 test_eq(error, 0); 59 60 error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); 61 test_eq(error, 0); 62 63 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 64 &env->vka, &env->vspace, &conn); 65 test_eq(error, 0); 66 67 return sel4test_get_result(); 68} 69DEFINE_TEST(SERSERV_PARENT_002, "Test connecting to the server from a parent thread", test_parent_connect, true) 70 71static int 72test_parent_printf(struct env *env) 73{ 74 int error; 75 serial_client_context_t conn; 76 cspacepath_t badged_server_ep_cspath; 77 78 error = serial_server_parent_spawn_thread(&env->simple, 79 &env->vka, &env->vspace, 80 SERSERV_TEST_PRIO_SERVER); 81 82 test_eq(error, 0); 83 84 error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); 85 test_eq(error, 0); 86 87 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 88 &env->vka, &env->vspace, &conn); 89 test_eq(error, 0); 90 91 error = serial_server_printf(&conn, test_str); 92 test_eq(error, (int)strlen(test_str)); 93 return sel4test_get_result(); 94} 95DEFINE_TEST(SERSERV_PARENT_003, "Printf() from a connected parent thread", test_parent_printf, true) 96 97static int 98test_parent_write(struct env *env) 99{ 100 int error; 101 serial_client_context_t conn; 102 cspacepath_t badged_server_ep_cspath; 103 104 error = serial_server_parent_spawn_thread(&env->simple, 105 &env->vka, &env->vspace, 106 SERSERV_TEST_PRIO_SERVER); 107 108 test_eq(error, 0); 109 110 error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); 111 test_eq(error, 0); 112 113 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 114 &env->vka, &env->vspace, &conn); 115 test_eq(error, 0); 116 117 error = serial_server_write(&conn, test_str, strlen(test_str)); 118 test_eq(error, (int)strlen(test_str)); 119 120 return sel4test_get_result(); 121} 122DEFINE_TEST(SERSERV_PARENT_004, "Write() from a connected parent thread", test_parent_write, true) 123 124static int 125test_parent_disconnect_reconnect_write_and_printf(struct env *env) 126{ 127 int error; 128 serial_client_context_t conn; 129 cspacepath_t badged_server_ep_cspath; 130 131 error = serial_server_parent_spawn_thread(&env->simple, 132 &env->vka, &env->vspace, 133 SERSERV_TEST_PRIO_SERVER); 134 135 test_eq(error, 0); 136 137 error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); 138 test_eq(error, 0); 139 140 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 141 &env->vka, &env->vspace, &conn); 142 test_eq(error, 0); 143 144 error = serial_server_printf(&conn, test_str); 145 test_eq(error, (int)strlen(test_str)); 146 error = serial_server_write(&conn, test_str, strlen(test_str)); 147 test_eq(error, (int)strlen(test_str)); 148 149 /* Disconnect then reconnect and attempt to print */ 150 serial_server_disconnect(&conn); 151 152 /* Need to re-obtain new badge values, as the Server may not hand out the 153 * same badge values the second time. Free the previous Endpoint cap. 154 */ 155 vka_cnode_delete(&badged_server_ep_cspath); 156 error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); 157 test_eq(error, 0); 158 159 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 160 &env->vka, &env->vspace, &conn); 161 test_eq(error, 0); 162 163 error = serial_server_write(&conn, test_str, strlen(test_str)); 164 test_eq(error, (int)strlen(test_str)); 165 error = serial_server_printf(&conn, test_str); 166 test_eq(error, (int)strlen(test_str)); 167 168 return sel4test_get_result(); 169} 170DEFINE_TEST(SERSERV_PARENT_005, 171 "Test printf() and write() from a parent thread when after a " 172 "connection reset (disconnect/reconnect)", 173 test_parent_disconnect_reconnect_write_and_printf, 174 true) 175 176static int 177test_kill_from_parent(struct env *env) 178{ 179 int error; 180 serial_client_context_t conn; 181 cspacepath_t badged_server_ep_cspath; 182 183 error = serial_server_parent_spawn_thread(&env->simple, 184 &env->vka, &env->vspace, 185 SERSERV_TEST_PRIO_SERVER); 186 test_eq(error, 0); 187 188 error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); 189 test_eq(error, 0); 190 191 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 192 &env->vka, &env->vspace, &conn); 193 test_eq(error, 0); 194 195 /* Kill the Server from the parent. */ 196 error = serial_server_kill(&conn); 197 test_eq(error, 0); 198 199 return sel4test_get_result(); 200} 201DEFINE_TEST(SERSERV_PARENT_006, "Kill the Server from the Parent thread", 202 test_kill_from_parent, true) 203 204static int 205test_spawn_thread_inputs(struct env *env) 206{ 207 int error; 208 209 /* Test NULL inputs to spawn_thread(). */ 210 error = serial_server_parent_spawn_thread(NULL, &env->vka, 211 &env->vspace, 212 SERSERV_TEST_PRIO_SERVER); 213 test_neq(error, 0); 214 error = serial_server_parent_spawn_thread(&env->simple, NULL, 215 &env->vspace, 216 SERSERV_TEST_PRIO_SERVER); 217 test_neq(error, 0); 218 error = serial_server_parent_spawn_thread(&env->simple, &env->vka, 219 NULL, 220 SERSERV_TEST_PRIO_SERVER); 221 test_neq(error, 0); 222 223 return sel4test_get_result(); 224} 225DEFINE_TEST(SERSERV_PARENT_007, "Test a series of unexpected input values to spawn_thread", 226 test_spawn_thread_inputs, true) 227 228static int 229test_connect_inputs(struct env *env) 230{ 231 int error; 232 serial_client_context_t conn; 233 cspacepath_t badged_server_ep_cspath; 234 235 /* Test NULL inputs to connect(). */ 236 error = serial_server_parent_spawn_thread(&env->simple, &env->vka, 237 &env->vspace, 238 SERSERV_TEST_PRIO_SERVER); 239 test_eq(error, 0); 240 error = serial_server_parent_vka_mint_endpoint(NULL, &badged_server_ep_cspath); 241 test_neq(error, 0); 242 error = serial_server_parent_vka_mint_endpoint(&env->vka, NULL); 243 test_neq(error, 0); 244 error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); 245 test_eq(error, 0); 246 247 error = serial_server_client_connect(0, 248 &env->vka, &env->vspace, &conn); 249 test_neq(error, 0); 250 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 251 NULL, &env->vspace, &conn); 252 test_neq(error, 0); 253 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 254 &env->vka, NULL, &conn); 255 test_neq(error, 0); 256 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 257 &env->vka, &env->vspace, NULL); 258 test_neq(error, 0); 259 260 return sel4test_get_result(); 261} 262DEFINE_TEST(SERSERV_PARENT_008, "Test a series of unexpected input values to connect()", 263 test_connect_inputs, true) 264 265static int 266test_printf_inputs(struct env *env) 267{ 268 int error; 269 serial_client_context_t conn; 270 cspacepath_t badged_server_ep_cspath; 271 272 /* Test NULL inputs to printf(). */ 273 error = serial_server_parent_spawn_thread(&env->simple, &env->vka, 274 &env->vspace, 275 SERSERV_TEST_PRIO_SERVER); 276 test_eq(error, 0); 277 error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); 278 test_eq(error, 0); 279 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 280 &env->vka, &env->vspace, &conn); 281 test_eq(error, 0); 282 283 error = serial_server_printf(NULL, test_str); 284 test_neq(error, (int)strlen(test_str)); 285 error = serial_server_printf(&conn, NULL); 286 test_neq(error, (int)strlen(test_str)); 287 288 return sel4test_get_result(); 289} 290DEFINE_TEST(SERSERV_PARENT_009, "Test a series of unexpected input values to printf()", 291 test_printf_inputs, true) 292 293static int 294test_write_inputs(struct env *env) 295{ 296 int error; 297 serial_client_context_t conn; 298 cspacepath_t badged_server_ep_cspath; 299 300 /* Test NULL inputs to printf(). */ 301 error = serial_server_parent_spawn_thread(&env->simple, &env->vka, 302 &env->vspace, 303 SERSERV_TEST_PRIO_SERVER); 304 test_eq(error, 0); 305 error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); 306 test_eq(error, 0); 307 error = serial_server_client_connect(badged_server_ep_cspath.capPtr, 308 &env->vka, &env->vspace, &conn); 309 test_eq(error, 0); 310 311 error = serial_server_write(NULL, test_str, strlen(test_str)); 312 test_neq(error, (int)strlen(test_str)); 313 error = serial_server_write(&conn, NULL, 500); 314 test_neq(error, (int)strlen(test_str)); 315 error = serial_server_write(&conn, test_str, 0); 316 test_neq(error, (int)strlen(test_str)); 317 318 return sel4test_get_result(); 319} 320DEFINE_TEST(SERSERV_PARENT_010, "Test a series of unexpected input values to write()", 321 test_write_inputs, true) 322 323