1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#ifndef EXITEST_TEST_H_INCLUDED
#define EXITEST_TEST_H_INCLUDED
#include <gccore.h>
#include <assert.h>
#include "state.h"
#include "macros.h"
typedef enum {
TEST_INTERACTIVE = 0x01u,
TEST_PAUSE_ON_ERROR = 0x02u /* for "essential" tests that should pass */
} et_test_flags;
struct et_test;
struct et_test_plan;
struct et_test {
struct et_state parent;
const char *name;
et_test_flags flags;
et_state_init_f *test_init_f;
et_state_cleanup_f *test_cleanup_f;
};
/* 0000eeee eeeeeeee eeeeeeee x00000ss */
/* e = error code bits,
* x = 1 if this test is still in the "clean" (not executed) state
* ss = status type (pass/fail/etc.) */
typedef u32 et_test_status;
typedef enum {
TEST_ENONE = (u32)0,
/* test was aborted (i.e., requested to go to next test without setting a status code) */
TEST_EABORT,
/* minimum private test error (define test-private error codes as TEST_EPRIV_BASE+n) */
TEST_EPRIV_BASE = 32,
/* largest error code allowed */
TEST_EMAX = ((u32)1 << 20) - 1
} et_test_error;
typedef enum {
TEST_SSKIPPED = 0u,
TEST_SERROR,
TEST_SFAIL,
TEST_SPASS,
TEST_SMAX = ((u32)1 << 2) - 1
} et_test_status_type;
#define TEST_STATUS_GET_ERROR(_status) (et_test_error)(((u32)(_status) >> 8) & TEST_EMAX)
#define TEST_STATUS_GET_TYPE(_status) (et_test_status_type)((u32)(_status) & TEST_SMAX)
#define TEST_STATUS_IS_CLEAN(_status) (!!((u32)(_status) & 0x80u))
#define TEST_MAKE_STATUS(_type, _error, _clean) (et_test_status) \
(((u32)(_type) & TEST_SMAX) | \
(((u32)(_clean) & 1) << 7) | \
(((u32)(_error) & TEST_EMAX) << 8))
#define TEST_SKIPPED TEST_MAKE_STATUS(TEST_SSKIPPED, TEST_ENONE, 0)
#define TEST_FAIL TEST_MAKE_STATUS(TEST_SFAIL, TEST_ENONE, 0)
#define TEST_PASS TEST_MAKE_STATUS(TEST_SPASS, TEST_ENONE, 0)
#define TEST_ERROR(_e) TEST_MAKE_STATUS(TEST_SERROR, _e, 0)
#define TEST_PRIMORDIAL TEST_MAKE_STATUS(TEST_SSKIPPED, TEST_ENONE, 1)
/* Expected setup date: pointer to test plan */
extern const struct et_state *et_state_begin_testing;
extern const struct et_state *et_state_summarize_test_plan;
const char *et_test_get_status_mnemonic(et_test_status status);
struct et_test_plan_entry {
const struct et_test *test;
et_test_status status;
const char *ext_status;
void (*ext_status_free)(void *);
};
/* a properly initialized test plan will have all the tests' statuses set to TEST_PRIMORDIAL */
struct et_test_plan {
int exi_channel;
/* this state will be set after testing is complete.
* NOTE: next_state_init should somehow point to this test plan,
* since it's probably dynamically allocated and will be leaked if not
* freed. */
const struct et_state *next_state;
et_state_init_data next_state_init;
size_t num_tests;
size_t current_test;
struct et_test_plan_entry *tests;
};
void et_test_plan_entry_cleanup(struct et_test_plan_entry *entry);
#define FOREACH_TEST(O, _sep) \
O(check_id)
#define TEST_SYM(_name) PASTE(et_test_, _name)
#define DECL_TEST(_name) extern const struct et_test *const TEST_SYM(_name)
FOREACH_TEST(DECL_TEST, ;);
#undef DECL_TEST
const struct et_test *const *et_get_tests(size_t *ntests);
#if defined(ET_TEST_IMPL) || defined(TEST_INTERNAL)
#define ET__ALLOW_TEST_IMPL_INC
#include "test-impl.inc.h"
#else
#undef FOREACH_TEST
#undef TEST_SYM
#endif
#endif /* include guard */
|