| /* | |
| * Copyright 2017, Data61 | |
| * Commonwealth Scientific and Industrial Research Organisation (CSIRO) | |
| * ABN 41 687 119 230. | |
| * | |
| * This software may be distributed and modified according to the terms of | |
| * the BSD 2-Clause license. Note that NO WARRANTY is provided. | |
| * See "LICENSE_BSD2.txt" for details. | |
| * | |
| * @TAG(DATA61_BSD) | |
| */ | |
| #include <string.h> | |
| #include <stdio.h> | |
| #include <sel4/sel4.h> | |
| #include <vka/capops.h> | |
| #include <sel4utils/thread.h> | |
| #include <serial_server/parent.h> | |
| #include <serial_server/client.h> | |
| #include <sel4test/test.h> | |
| #include <sel4test/testutil.h> | |
| #define SERSERV_TEST_PRIO_SERVER (seL4_MaxPrio - 1) | |
| static const char *test_str = "Hello, world!\n"; | |
| void get_serial_server_parent_tests() | |
| { | |
| } | |
| static int | |
| test_server_spawn(struct env *env) | |
| { | |
| int error; | |
| error = serial_server_parent_spawn_thread(&env->simple, | |
| &env->vka, &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_eq(error, 0); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_001, "Serial server spawn test", test_server_spawn, true) | |
| static int | |
| test_parent_connect(struct env *env) | |
| { | |
| int error; | |
| serial_client_context_t conn; | |
| cspacepath_t badged_server_ep_cspath; | |
| error = serial_server_parent_spawn_thread(&env->simple, | |
| &env->vka, &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_eq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); | |
| test_eq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, &env->vspace, &conn); | |
| test_eq(error, 0); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_002, "Test connecting to the server from a parent thread", test_parent_connect, true) | |
| static int | |
| test_parent_printf(struct env *env) | |
| { | |
| int error; | |
| serial_client_context_t conn; | |
| cspacepath_t badged_server_ep_cspath; | |
| error = serial_server_parent_spawn_thread(&env->simple, | |
| &env->vka, &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_eq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); | |
| test_eq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, &env->vspace, &conn); | |
| test_eq(error, 0); | |
| error = serial_server_printf(&conn, test_str); | |
| test_eq(error, (int)strlen(test_str)); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_003, "Printf() from a connected parent thread", test_parent_printf, true) | |
| static int | |
| test_parent_write(struct env *env) | |
| { | |
| int error; | |
| serial_client_context_t conn; | |
| cspacepath_t badged_server_ep_cspath; | |
| error = serial_server_parent_spawn_thread(&env->simple, | |
| &env->vka, &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_eq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); | |
| test_eq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, &env->vspace, &conn); | |
| test_eq(error, 0); | |
| error = serial_server_write(&conn, test_str, strlen(test_str)); | |
| test_eq(error, (int)strlen(test_str)); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_004, "Write() from a connected parent thread", test_parent_write, true) | |
| static int | |
| test_parent_disconnect_reconnect_write_and_printf(struct env *env) | |
| { | |
| int error; | |
| serial_client_context_t conn; | |
| cspacepath_t badged_server_ep_cspath; | |
| error = serial_server_parent_spawn_thread(&env->simple, | |
| &env->vka, &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_eq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); | |
| test_eq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, &env->vspace, &conn); | |
| test_eq(error, 0); | |
| error = serial_server_printf(&conn, test_str); | |
| test_eq(error, (int)strlen(test_str)); | |
| error = serial_server_write(&conn, test_str, strlen(test_str)); | |
| test_eq(error, (int)strlen(test_str)); | |
| /* Disconnect then reconnect and attempt to print */ | |
| serial_server_disconnect(&conn); | |
| /* Need to re-obtain new badge values, as the Server may not hand out the | |
| * same badge values the second time. Free the previous Endpoint cap. | |
| */ | |
| vka_cnode_delete(&badged_server_ep_cspath); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); | |
| test_eq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, &env->vspace, &conn); | |
| test_eq(error, 0); | |
| error = serial_server_write(&conn, test_str, strlen(test_str)); | |
| test_eq(error, (int)strlen(test_str)); | |
| error = serial_server_printf(&conn, test_str); | |
| test_eq(error, (int)strlen(test_str)); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_005, | |
| "Test printf() and write() from a parent thread when after a " | |
| "connection reset (disconnect/reconnect)", | |
| test_parent_disconnect_reconnect_write_and_printf, | |
| true) | |
| static int | |
| test_kill_from_parent(struct env *env) | |
| { | |
| int error; | |
| serial_client_context_t conn; | |
| cspacepath_t badged_server_ep_cspath; | |
| error = serial_server_parent_spawn_thread(&env->simple, | |
| &env->vka, &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_eq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); | |
| test_eq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, &env->vspace, &conn); | |
| test_eq(error, 0); | |
| /* Kill the Server from the parent. */ | |
| error = serial_server_kill(&conn); | |
| test_eq(error, 0); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_006, "Kill the Server from the Parent thread", | |
| test_kill_from_parent, true) | |
| static int | |
| test_spawn_thread_inputs(struct env *env) | |
| { | |
| int error; | |
| /* Test NULL inputs to spawn_thread(). */ | |
| error = serial_server_parent_spawn_thread(NULL, &env->vka, | |
| &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_neq(error, 0); | |
| error = serial_server_parent_spawn_thread(&env->simple, NULL, | |
| &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_neq(error, 0); | |
| error = serial_server_parent_spawn_thread(&env->simple, &env->vka, | |
| NULL, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_neq(error, 0); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_007, "Test a series of unexpected input values to spawn_thread", | |
| test_spawn_thread_inputs, true) | |
| static int | |
| test_connect_inputs(struct env *env) | |
| { | |
| int error; | |
| serial_client_context_t conn; | |
| cspacepath_t badged_server_ep_cspath; | |
| /* Test NULL inputs to connect(). */ | |
| error = serial_server_parent_spawn_thread(&env->simple, &env->vka, | |
| &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_eq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(NULL, &badged_server_ep_cspath); | |
| test_neq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, NULL); | |
| test_neq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); | |
| test_eq(error, 0); | |
| error = serial_server_client_connect(0, | |
| &env->vka, &env->vspace, &conn); | |
| test_neq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| NULL, &env->vspace, &conn); | |
| test_neq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, NULL, &conn); | |
| test_neq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, &env->vspace, NULL); | |
| test_neq(error, 0); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_008, "Test a series of unexpected input values to connect()", | |
| test_connect_inputs, true) | |
| static int | |
| test_printf_inputs(struct env *env) | |
| { | |
| int error; | |
| serial_client_context_t conn; | |
| cspacepath_t badged_server_ep_cspath; | |
| /* Test NULL inputs to printf(). */ | |
| error = serial_server_parent_spawn_thread(&env->simple, &env->vka, | |
| &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_eq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); | |
| test_eq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, &env->vspace, &conn); | |
| test_eq(error, 0); | |
| error = serial_server_printf(NULL, test_str); | |
| test_neq(error, (int)strlen(test_str)); | |
| error = serial_server_printf(&conn, NULL); | |
| test_neq(error, (int)strlen(test_str)); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_009, "Test a series of unexpected input values to printf()", | |
| test_printf_inputs, true) | |
| static int | |
| test_write_inputs(struct env *env) | |
| { | |
| int error; | |
| serial_client_context_t conn; | |
| cspacepath_t badged_server_ep_cspath; | |
| /* Test NULL inputs to printf(). */ | |
| error = serial_server_parent_spawn_thread(&env->simple, &env->vka, | |
| &env->vspace, | |
| SERSERV_TEST_PRIO_SERVER); | |
| test_eq(error, 0); | |
| error = serial_server_parent_vka_mint_endpoint(&env->vka, &badged_server_ep_cspath); | |
| test_eq(error, 0); | |
| error = serial_server_client_connect(badged_server_ep_cspath.capPtr, | |
| &env->vka, &env->vspace, &conn); | |
| test_eq(error, 0); | |
| error = serial_server_write(NULL, test_str, strlen(test_str)); | |
| test_neq(error, (int)strlen(test_str)); | |
| error = serial_server_write(&conn, NULL, 500); | |
| test_neq(error, (int)strlen(test_str)); | |
| error = serial_server_write(&conn, test_str, 0); | |
| test_neq(error, (int)strlen(test_str)); | |
| return sel4test_get_result(); | |
| } | |
| DEFINE_TEST(SERSERV_PARENT_010, "Test a series of unexpected input values to write()", | |
| test_write_inputs, true) | |