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#pragma once
14
15/* Include Kconfig variables. */
16#include <autoconf.h>
17#include <sel4test/gen_config.h>
18
19#include <sel4/sel4.h>
20
21#include <utils/attribute.h>
22#include <sel4test/testutil.h>
23#include <vka/vka.h>
24#include <vspace/vspace.h>
25#include <sel4platsupport/timer.h>
26#include <sync/mutex.h>
27#include <sel4utils/elf.h>
28#include <sel4rpc/client.h>
29
30#include <inttypes.h>
31#include <stdbool.h>
32#include <stddef.h>
33#include <stdint.h>
34#include <stdio.h>
35#include <string.h>
36
37/* max test name size */
38#define TEST_NAME_MAX (64 - 4 * sizeof(seL4_Word))
39
40#define MAX_REGIONS 4
41
42/* Contains information about the test environment for regular tests, bootstrap tests do
43 * not use this environment */
44struct env {
45    /* An initialised vka that may be used by the test. */
46    vka_t vka;
47    /* virtual memory management interface */
48    vspace_t vspace;
49    /* abstract interface over application init */
50    simple_t simple;
51    /* notification for timer */
52    vka_object_t timer_notification;
53    /* RPC client for serial server resource allocation */
54    sel4rpc_client_t rpc_client;
55
56    /* caps for the current process */
57    seL4_CPtr cspace_root;
58    seL4_CPtr page_directory;
59    seL4_CPtr endpoint;
60    seL4_CPtr tcb;
61    seL4_CPtr timer_untyped;
62    seL4_CPtr asid_pool;
63    seL4_CPtr asid_ctrl;
64    seL4_CPtr sched_ctrl;
65#ifdef CONFIG_IOMMU
66    seL4_CPtr io_space;
67#endif /* CONFIG_IOMMU */
68#ifdef CONFIG_TK1_SMMU
69    seL4_SlotRegion io_space_caps;
70#endif
71    seL4_Word cores;
72    seL4_CPtr domain;
73    seL4_CPtr device_frame;
74
75    int priority;
76    int cspace_size_bits;
77    int num_regions;
78    sel4utils_elf_region_t regions[MAX_REGIONS];
79};
80typedef struct env *env_t;
81
82/* Prototype of a test function. Returns false on failure. */
83typedef int (*test_fn)(uintptr_t environment);
84
85/* Test type definitions. */
86typedef enum test_type_name {BOOTSTRAP = 0, BASIC} test_type_name_t;
87typedef struct testcase testcase_t; // Forward type declaration.
88typedef struct test_type {
89    /* Represents a single test type. See comment for `struct testcase` for info about ALIGN(32). */
90    const char *name;
91    test_type_name_t id;
92    // Function called before and after all the tests for this test type have been run.
93    void (*set_up_test_type)(uintptr_t e);
94    void (*tear_down_test_type)(uintptr_t e);
95    // Function called before and after each test for this test type.
96    void (*set_up)(uintptr_t e);
97    void (*tear_down)(uintptr_t e);
98    // Run the test. Different tests take different environments
99    test_result_t (*run_test)(struct testcase *test, uintptr_t e);
100} ALIGN(32) test_type_t;
101
102/* Declare a test type.
103 * For now, we put the test types in a separate elf section. */
104#define DEFINE_TEST_TYPE(_name, _id, _set_up_test_type, _tear_down_test_type, _set_up, _tear_down, _run_test) \
105    __attribute__((used)) __attribute__((section("_test_type"))) struct test_type TEST_TYPE_ ##_name = { \
106    .name = #_name, \
107    .id = _id, \
108    .set_up_test_type = _set_up_test_type, \
109    .tear_down_test_type = _tear_down_test_type, \
110    .set_up = _set_up, \
111    .tear_down = _tear_down, \
112    .run_test = _run_test, \
113};
114
115/* Represents a single testcase.
116 * Because this struct is used to declare variables that get
117 * placed into custom sections, that we later treat as an array,
118 * we need to make sure the struct is aligned and filled to the
119 * nearest power of two to avoid gcc placing arbitrary padding between them.
120 *
121 * The declaration below ensures that the actual size of
122 * the objects in the section is the same as the size reported
123 * by sizeof(struct testcase), allowing as to treat the items
124 * in the section as an array */
125struct testcase {
126    char name[TEST_NAME_MAX];
127    const char *description;
128    test_fn function;
129    seL4_Word test_type;
130    seL4_Word enabled;
131} PACKED;
132typedef struct testcase ALIGN(sizeof(struct testcase)) testcase_t;
133
134/* Declare a testcase.
135 * Must be declared using C89 style (#_name, _desc, _func...) instead of
136 * C99 style (name = _name, desc = _desc, func = _func...) to make sure
137 * that it is accepted by C++ compilers.
138 */
139#define DEFINE_TEST_WITH_TYPE(_name, _description, _function, _test_type, _enabled) \
140    __attribute__((used)) __attribute__((section("_test_case"))) struct testcase TEST_ ## _name = { \
141    #_name, \
142    _description, \
143    (test_fn)_function, \
144    _test_type, \
145    _enabled, \
146};
147
148#define DEFINE_TEST(_name, _description, _function, _enabled) DEFINE_TEST_WITH_TYPE(_name, _description, _function, BASIC, _enabled)
149
150#define DEFINE_TEST_BOOTSTRAP(_name, _description, _function, _enabled) DEFINE_TEST_WITH_TYPE(_name, _description, _function, BOOTSTRAP, _enabled)
151/**/
152
153/* Definitions so that we can find the test types */
154extern struct test_type __start__test_type[];
155extern struct test_type __stop__test_type[];
156
157/* Definitions so that we can find the test cases */
158extern testcase_t __start__test_case[];
159extern testcase_t __stop__test_case[];
160
161static inline int test_type_comparator(const void *a, const void *b)
162{
163    const struct test_type **ta = (const struct test_type **) a;
164    const struct test_type **tb = (const struct test_type **) b;
165    if ((*ta)->id > (*tb)->id) {
166        return 1;
167    } else if ((*ta)->id < (*tb)->id) {
168        return -1;
169    }
170
171    return 0;
172}
173
174static inline int test_comparator(const void *a, const void *b)
175{
176    const struct testcase **ta = (const struct testcase **)a;
177    const struct testcase **tb = (const struct testcase **)b;
178    return strcmp((*ta)->name, (*tb)->name);
179}
180
181/* Fails a test case, stop running the rest of the test, but keep running other tests. */
182static inline test_result_t _test_fail(const char *condition, const char *file, int line)
183{
184    _sel4test_failure(condition, file, line);
185    return FAILURE;
186}
187
188/* Fails a test case, keep running the rest of the test, then keep running other tests. */
189static inline void _test_error(const char *condition, const char *file, int line)
190{
191
192    _sel4test_report_error(condition, file, line);
193}
194
195/* Fails a test case, stop everything. */
196static inline test_result_t _test_abort(const char *condition, const char *file, int line)
197{
198    _sel4test_failure(condition, file, line);
199    return ABORT;
200}
201
202static inline void print_error_in_ipc(seL4_Error e)
203{
204#ifdef CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC
205    // If it hasnt been printed already
206    if (!seL4_CanPrintError() && e != seL4_NoError) {
207        printf("%s", seL4_GetDebugError());
208    }
209#endif
210}
211
212#define test_error_eq(e, c) \
213    if (!((e) == (c))) { \
214        print_error_in_ipc(e); \
215        return _test_fail(#e, __FILE__, __LINE__); \
216    }
217#define test_assert(e) if (!(e)) return _test_fail(#e, __FILE__, __LINE__)
218#define test_check(e) if (!(e)) _test_error(#e, __FILE__, __LINE__)
219#define test_assert_fatal(e) if (!(e)) return _test_abort(#e, __FILE__, __LINE__)
220
221#define __TEST_BUFFER_SIZE 200
222#define test_op_type(a, b, op, t, name_a, name_b, cast) \
223    do {\
224        if (!(a op b)) { \
225            int len = snprintf(NULL, 0, "Check %s(" t ") %s %s(" t ") failed.",\
226                               #name_a, (cast) a, #op, #name_b, (cast) b) + 1; \
227            char buffer[len]; \
228            snprintf(buffer, len, "Check %s(" t ") %s %s(" t ") failed.",\
229                     #name_a, (cast) a, #op, #name_b, (cast) b); \
230            _test_error(buffer, __FILE__, __LINE__); \
231        }\
232    } while (0)
233
234#define test_op(a, b, op) \
235    do { \
236         typeof (a) _a = (a); \
237         typeof (b) _b = (b); \
238         if (sizeof(_a) != sizeof(_b)) { \
239             int len = snprintf(NULL, 0, "%s (size %zu) != %s (size %zu), use of test_eq incorrect", #a,\
240                     sizeof(_a), #b, sizeof(_b)) + 1;\
241             char buffer[len];\
242             snprintf(buffer, len, "%s (size %zu) != %s (size %zu), use of test_eq incorrect", #a, sizeof(_a),\
243                     #b, sizeof(_b));\
244             _test_error(buffer, __FILE__, __LINE__);\
245         } else if (TYPES_COMPATIBLE(typeof(_a), int)) {\
246             test_op_type(_a, _b, op, "%d", a, b, int); \
247         } else if (TYPES_COMPATIBLE(typeof(_a), long)) {\
248             test_op_type(_a, _b, op, "%ld", a, b, long); \
249         } else if (TYPES_COMPATIBLE(typeof(_a), long long)) {\
250             test_op_type(_a, _b, op, "%lld", a, b, long long); \
251         } else if (TYPES_COMPATIBLE(typeof(_a), unsigned int)) {\
252             test_op_type(_a, _b, op, "%u", a, b, unsigned int); \
253         } else if (TYPES_COMPATIBLE(typeof(_a), unsigned long)) {\
254             test_op_type(_a, _b, op, "%lu", a, b, unsigned long); \
255         } else if (TYPES_COMPATIBLE(typeof(_a), unsigned long long)) {\
256             test_op_type(_a, _b, op, "%llu", a, b, unsigned long long); \
257         } else if (TYPES_COMPATIBLE(typeof(_a), char)) {\
258             test_op_type(_a, _b, op, "%c", a, b, char); \
259         } else if (TYPES_COMPATIBLE(typeof(_a), uintptr_t)) {\
260             test_op_type(_a, _b, op, "0x%" PRIxPTR, a, b, uintptr_t);\
261         } else { \
262             _test_error("Cannot use test_op on this type", __FILE__, __LINE__);\
263         }\
264    } while (0)
265
266/* Pretty printed test_check wrapper macros for basic comparisons on base types,
267 * which output the values and variable names to aid debugging */
268#define test_eq(a, b)  test_op(a, b, ==)
269#define test_neq(a, b) test_op(a, b, !=)
270#define test_gt(a, b)  test_op(a, b, >)
271#define test_geq(a, b) test_op(a, b, >=)
272#define test_lt(a, b)  test_op(a, b, <)
273#define test_leq(a, b) test_op(a, b, <=)
274
275#define __TEST_MAX_STRING 50
276#define test_strop(a, b, op) \
277     do {\
278          if (strnlen(a, __TEST_MAX_STRING) == __TEST_MAX_STRING) {\
279              _test_error("String " #a " too long for test_str* macros", __FILE__, __LINE__);\
280          } else if (strnlen(b, __TEST_MAX_STRING) == __TEST_MAX_STRING) {\
281              _test_error("String " #b " too long for test_str* macros", __FILE__, __LINE__);\
282          } else if (!(strncmp(a, b, __TEST_MAX_STRING)) op 0) {\
283              char buffer[__TEST_BUFFER_SIZE + 2 * __TEST_MAX_STRING];\
284              snprintf(buffer, sizeof(buffer),\
285                       "Check %s(%s) %s %s(%s) failed.", #a, a, #op, #b, b);\
286              _test_error(buffer, __FILE__, __LINE__); \
287          }\
288    } while (0)
289
290/* Pretty printed test_check wrapper macros for basic comparisons on c strings,
291 * which output the values and variable names to aid debugging */
292#define test_streq(a, b)  test_strop(a, b, ==)
293#define test_strneq(a, b) test_strop(a, b, !=)
294#define test_strge(a, b)  test_strop(a, b, >)
295#define test_strgeq(a, b) test_strop(a, b, >=)
296#define test_strle(a, b)  test_strop(a, b, <)
297#define test_strleq(a, b) test_strop(a, b, <=)
298
299env_t sel4test_get_env(void);
300
301