GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tests/gatecore_test/test_functions.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 83 119 69.7%
Functions: 8 15 53.3%
Branches: 20 50 40.0%

Line Branch Exec Source
1 #include "test_functions.h"
2
3 #include "gate/tests.h"
4 #include "gate/functions.h"
5 #include "gate/callstacks.h"
6 #include "gate/console.h"
7
8 static int volatile callstack_run_checkpoint = 0;
9
10 1 static gate_result_t test_callstack_entry_point(void* ptr)
11 {
12 1 gate_console_t* con = (gate_console_t*)ptr;
13 1 gate_stream_t* strm = (gate_stream_t*)con;
14 1 gate_stream_println_cstr(strm, "Hello World");
15 1 callstack_run_checkpoint = 1;
16 1 return GATE_RESULT_OK;
17 }
18
19 static int volatile callstack_fork_checkpoint_1 = 0;
20 static int volatile callstack_fork_checkpoint_2 = 0;
21
22 1 static gate_result_t callstack_fork_entry1(void* arg)
23 {
24 1 gate_callstack_jmpbuf_t* ptr_fork_anchor = (gate_callstack_jmpbuf_t*)arg;
25
26 1 callstack_fork_checkpoint_1 = 1;
27
28 1 gate_callstack_jump(ptr_fork_anchor);
29 return 123;
30 }
31
32 1 static gate_result_t callstack_fork_entry1_no_jump(void* arg)
33 {
34 1 gate_callstack_jmpbuf_t* ptr_fork_anchor = (gate_callstack_jmpbuf_t*)arg;
35
36
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK(ptr_fork_anchor != NULL);
37 1 callstack_fork_checkpoint_1 = 1;
38 1 return 123;
39 }
40
41
42 1 static gate_result_t callstack_fork_entry2(void* arg)
43 {
44 1 gate_callstack_jmpbuf_t* ptr_fork_anchor = (gate_callstack_jmpbuf_t*)arg;
45
46
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK(ptr_fork_anchor != NULL);
47 1 callstack_fork_checkpoint_2 = 2;
48 1 return 456;
49 }
50
51 1 GATE_TEST_FUNCTION(test_callstack)
52 {
53 gate_callstack_jmpbuf_t fork_anchor;
54 1 gate_size_t stack_size = 0; /* default */
55 1 void* stack_ptr = NULL;
56 1 void* param = gate_console();
57 gate_result_t callstack_run_result;
58 1 gate_result_t retval = GATE_RESULT_FAILED;
59
60 1 GATE_TEST_UNIT_BEGIN(test_callstack);
61
62 1 callstack_run_checkpoint = 0;
63
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_callstack_create(&stack_size, &stack_ptr));
64 1 callstack_run_result = gate_callstack_run(stack_ptr, stack_size, NULL, &test_callstack_entry_point, param, &retval);
65
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (callstack_run_result == GATE_RESULT_NOTSUPPORTED)
66 {
67 /* callstack switching is not supported on this platform, tests are meaningless */
68 }
69 else
70 {
71
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_OK(callstack_run_result);
72
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_OK(retval);
73
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK(callstack_run_checkpoint == 1); /* other callstack invocation should have changed the value */
74 }
75
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_callstack_destroy(stack_ptr, stack_size));
76
77 1 callstack_fork_checkpoint_1 = 0;
78 1 callstack_fork_checkpoint_2 = 0;
79 1 retval = gate_callstack_fork(&fork_anchor, &callstack_fork_entry1_no_jump, &fork_anchor, &callstack_fork_entry2, &fork_anchor);
80
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK(callstack_fork_checkpoint_1 == 1); /* expect reached */
81
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK(callstack_fork_checkpoint_2 == 0); /* expect not reached */
82
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK(retval == 123);
83
84
85 1 callstack_fork_checkpoint_1 = 0;
86 1 callstack_fork_checkpoint_2 = 0;
87 1 retval = gate_callstack_fork(&fork_anchor, &callstack_fork_entry1, &fork_anchor, &callstack_fork_entry2, &fork_anchor);
88
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK(callstack_fork_checkpoint_1 == 1); /* expect reached */
89
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK(callstack_fork_checkpoint_2 == 2); /* expect reached */
90
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK(retval == 456);
91
92 1 GATE_TEST_UNIT_END;
93 }
94
95 #define ARG_A 0xa0
96 #define ARG_B 0xb000
97 #define ARG_C 0xc0000000
98 #define ARG_D 0xd000000000000000ULL
99 #define ARG_RESULT (ARG_D + ARG_C + ARG_B + ARG_A)
100
101 1 static gate_int32_t generic_function(gate_uint8_t a, gate_uint16_t b, gate_uint32_t c, gate_uint64_t d, gate_uint64_t* result)
102 {
103 1 GATE_TEST_TRACE_VALUE(a);
104
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_EQUAL(a, ARG_A);
105 1 GATE_TEST_TRACE_VALUE(b);
106
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_EQUAL(b, ARG_B);
107 1 GATE_TEST_TRACE_VALUE(c);
108
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_EQUAL(c, ARG_C);
109 1 GATE_TEST_TRACE_VALUE(d);
110
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_EQUAL(d, ARG_D);
111 2 *result = (gate_uint64_t)a
112 1 + (gate_uint64_t)b
113 1 + (gate_uint64_t)c
114 1 + (gate_uint64_t)d;
115 1 return -1;
116 }
117
118
119 1 GATE_TEST_FUNCTION(test_function_generic_call)
120 {
121 gate_function_argument_t args[5];
122 gate_function_argument_t retval;
123
124 gate_result_t ret;
125 1 gate_uint64_t result = 0xdeadbeaf;
126
127 1 GATE_TEST_UNIT_BEGIN(test_function_generic_call);
128
129 1 args[0].arg_type = GATE_FUNCTION_ARG_UCHAR;
130 1 args[0].arg_value.u_chr = ARG_A;
131 1 args[1].arg_type = GATE_FUNCTION_ARG_USHORT;
132 1 args[1].arg_value.u_short = ARG_B;
133 1 args[2].arg_type = GATE_FUNCTION_ARG_ULONG;
134 1 args[2].arg_value.u_long = ARG_C;
135 1 args[3].arg_type = GATE_FUNCTION_ARG_ULONGLONG;
136 1 args[3].arg_value.u_long_long = ARG_D;
137 1 args[4].arg_type = GATE_FUNCTION_ARG_POINTER;
138 1 args[4].arg_value.ptr = &result;
139 1 retval.arg_type = GATE_FUNCTION_ARG_SLONG;
140 1 retval.arg_value.s_long = 0;
141
142 1 ret = gate_function_invoke_generic((gate_funcptr_t)&generic_function, 0, args, 5, &retval);
143
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_REQUIRE_OK(ret);
144
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_EQUAL(result, ARG_RESULT);
145
146 1 GATE_TEST_UNIT_END;
147 }
148
149
150
151 static gate_result_t no_fault_entry(void* arg)
152 {
153 GATE_UNUSED_ARG(arg);
154 return GATE_RESULT_OK;
155 }
156
157
158 static gate_result_t seg_fault_entry(void* arg)
159 {
160 int volatile* volatile ptr = (int volatile*)arg;
161 volatile int n = *ptr;
162 *ptr = n;
163 return GATE_RESULT_OK;
164 }
165 static volatile int zero = 0;
166 static gate_result_t div_fault_entry(void* arg)
167 {
168 int volatile value = 42;
169 int volatile result;
170
171 (void)arg;
172 result = value / zero;
173 return GATE_RESULT_OK;
174 }
175 static volatile float zerof = 0.0f;
176 static gate_result_t float_fault_entry(void* arg)
177 {
178 float value = 42.0f;
179 float result;
180
181 (void)arg;
182 result = value / zerof;
183 return GATE_RESULT_OK;
184 }
185
186 static gate_result_t fault_handler(unsigned fault_code, void* fault_arg)
187 {
188 unsigned* volatile ptr = (unsigned*)fault_arg;
189 GATE_TEST_CHECK(fault_arg != NULL);
190 *ptr = fault_code;
191 return GATE_RESULT_OK;
192 }
193
194 static void test_function_fault_succeed(gate_entrypoint_t entry, void* arg)
195 {
196 gate_result_t result;
197 unsigned fault_code = 0;
198 GATE_UNUSED_ARG(arg);
199
200 result = gate_function_invoke_guarded(entry, NULL, &fault_handler, &fault_code);
201 GATE_TEST_CHECK_RESULT(GATE_RESULT_OK, result);
202 GATE_TEST_CHECK_EQUAL(fault_code, 0);
203 }
204
205 static void test_function_fault_fail(gate_entrypoint_t entry, void* arg, unsigned expected_fault)
206 {
207 gate_result_t result;
208 unsigned fault_code = 0;
209 GATE_UNUSED_ARG(arg);
210
211 result = gate_function_invoke_guarded(entry, NULL, &fault_handler, &fault_code);
212 GATE_TEST_CHECK_RESULT(GATE_RESULT_BADINSTRUCTION, result);
213 GATE_TEST_CHECK_EQUAL(fault_code, expected_fault);
214
215 GATE_TEST_TRACE_MESSAGE("Result codes");
216 GATE_TEST_TRACE_VALUE(fault_code);
217 GATE_TEST_TRACE_VALUE(expected_fault);
218
219 return;
220 }
221
222
223 1 GATE_TEST_FUNCTION(test_function_fault_guard)
224 {
225
226 1 GATE_TEST_UNIT_BEGIN(test_function_fault_guard);
227
228 /* NOTICE: Fault guard code triggers debuggers and unit test executors (like CTest).
229 So this test is not executed by default */
230 #if defined(GATECORE_TEST_EXECUTE_FAULT_GUARD)
231
232 #if !defined(GATE_SYS_BSD)
233 test_function_fault_succeed(&no_fault_entry, NULL);
234 #if !defined(GATE_SYS_DOS)
235 test_function_fault_fail(&seg_fault_entry, NULL, GATE_FUNCTION_FAULT_ADDRESS);
236 test_function_fault_fail(&div_fault_entry, NULL, GATE_FUNCTION_FAULT_ARITHMETIC);
237 #endif
238 /*test_function_fault_fail(&float_fault_entry, NULL, GATE_FUNCTION_FAULT_FLOAT);*/
239 #endif
240
241 #endif
242
243 1 GATE_TEST_UNIT_END;
244 }
245