SuperTinyKernel™ RTOS 1.05.3
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stktest_misc.cpp
Go to the documentation of this file.
1/*
2 * SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
3 *
4 * Source: https://github.com/SuperTinyKernel-RTOS
5 *
6 * Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
7 * License: MIT License, see LICENSE for a full text.
8 */
9
10#include "stktest.h"
11
12namespace stk {
13namespace test {
14
15// ============================================================================ //
16// =============================== Basic ====================================== //
17// ============================================================================ //
18
20{
21 void setup() {}
22 void teardown() {}
23};
24
25TEST(Basic, MinMax)
26{
27 static_assert(stk::Min(10, 20) == 10, "Min failed at compile time");
28 static_assert(stk::Max(10, 20) == 20, "Max failed at compile time");
29
30 // basic & symmetry
31 CHECK_EQUAL(1, stk::Min(1, 2));
32 CHECK_EQUAL(1, stk::Min(2, 1));
33
34 // negatives
35 CHECK_EQUAL(-5, stk::Min(-5, -2));
36 CHECK_EQUAL(-2, stk::Max(-5, -2));
37
38 // equality
39 CHECK_EQUAL(42, stk::Max(42, 42));
40
41 // boundaries (assuming 32-bit ints)
42 CHECK_EQUAL(2147483647, stk::Max(0, 2147483647));
43
44 // support const vars
45 {
46 const int32_t a = 10;
47 const int32_t b = 20;
48 CHECK_EQUAL(10, stk::Min(a, b));
49 }
50
51 // no duplicate operation
52 {
53 int32_t x = 1;
54 int32_t y = 5;
55
56 // in a macro-based MIN(x++, y), x would become 3, with STK's template-based stk::Min, x should become 2
57 int32_t result = stk::Min(x++, y);
58
59 CHECK_EQUAL(1, result); // the value before increment
60 CHECK_EQUAL(2, x); // x should only have been incremented once
61 CHECK_EQUAL(5, y); // y remains untouched
62 }
63}
64
65// ============================================================================ //
66// ============================= UserTask ===================================== //
67// ============================================================================ //
68
69TEST_GROUP(UserTask)
70{
71 void setup() {}
72 void teardown() {}
73};
74
75TEST(UserTask, GetStackSize)
76{
79
82}
83
84TEST(UserTask, GetStackSizeBytes)
85{
88
89 CHECK_EQUAL(TaskMock<ACCESS_USER>::STACK_SIZE * sizeof(Word), task.GetStackSizeBytes());
90 CHECK_EQUAL(TaskMock<ACCESS_USER>::STACK_SIZE * sizeof(Word), taskw.GetStackSizeBytes());
91}
92
93TEST(UserTask, GetStackSpace)
94{
97
98 // not initialized with STK_STACK_MEMORY_FILLER
99 CHECK_EQUAL(0, task.GetStackSpace());
100
101 kernel.Initialize();
102 kernel.AddTask(&task);
103 kernel.Start();
104
105 size_t space = task.GetStackSpace();
106
107 // initialized with STK_STACK_MEMORY_FILLER, all free
108 CHECK_EQUAL(TaskMock<ACCESS_USER>::STACK_SIZE, space);
109
110 // write something to bottom
111 task.GetStack()[task.GetStackSize() - 1] = 0x12345678;
112 task.GetStack()[task.GetStackSize() - 2] = 0x12345678;
113
114 space = task.GetStackSpace();
115
116 // consumed 1 Word
117 CHECK_EQUAL(TaskMock<ACCESS_USER>::STACK_SIZE - 2, space);
118}
119
120TEST(UserTask, GetWeight)
121{
124
125 // TaskMock inherits Task and Task does not support weights (1)
126 CHECK_EQUAL(1, task.GetWeight());
127
128 // TaskMockW supports weights as it inherits TaskW
129 CHECK_EQUAL(10, taskw.GetWeight());
130}
131
132TEST(UserTask, GetIdAndName)
133{
136
137 CHECK_EQUAL((Word)&task, task.GetId());
138 CHECK_EQUAL((Word)&taskw, taskw.GetId());
139
140 // expect NULL name by default
141 CHECK_EQUAL((const char *)NULL, task.GetTraceName());
142 CHECK_EQUAL((const char *)NULL, taskw.GetTraceName());
143}
144
145TEST(UserTask, TaskWUnsupportedHrt)
146{
148
149 try
150 {
151 g_TestContext.ExpectAssert(true);
152 // on next tick kernel will attempt to remove pending task and will check its deadline
153 taskw.OnDeadlineMissed(0);
154 CHECK_TEXT(false, "expecting assertion - task with weights do not support HRT");
155 }
156 catch (TestAssertPassed &pass)
157 {
158 CHECK(true);
159 g_TestContext.ExpectAssert(false);
160 }
161}
162
164{
165 void setup() {}
166 void teardown() {}
167};
168
170{
173
174 CHECK_TRUE(NULL != wrapper.GetStack());
175 CHECK_EQUAL((Word *)&memory, wrapper.GetStack());
176}
177
179{
182
183 CHECK_EQUAL(STACK_SIZE_MIN, wrapper.GetStackSize());
184 CHECK_EQUAL(sizeof(memory) / sizeof(Word), wrapper.GetStackSize());
185}
186
187TEST(StackMemoryWrapper, GetStackSizeBytes)
188{
191
192 CHECK_EQUAL(STACK_SIZE_MIN * sizeof(Word), wrapper.GetStackSizeBytes());
193 CHECK_EQUAL(sizeof(memory), wrapper.GetStackSizeBytes());
194}
195
197{
198 void setup() {}
199 void teardown() {}
200
201 struct ListEntry : public stk::util::DListEntry<ListEntry, true>
202 {
203 int32_t m_id;
204 ListEntry(int32_t id) : m_id(id) {}
205 };
206
208};
209
210TEST(DList, Empty)
211{
212 ListHead list;
213
214 CHECK_EQUAL_ZERO(list.GetSize());
215 CHECK_TRUE(list.IsEmpty());
216 CHECK_TRUE(NULL == list.GetFirst());
217 CHECK_TRUE(NULL == list.GetLast());
218
219 list.Clear();
220}
221
222TEST(DList, LinkFront)
223{
224 ListHead list;
225 ListEntry e1(1), e2(2), e3(3);
226
227 list.LinkFront(e1);
228 CHECK_EQUAL(&e1, list.GetFirst());
229 CHECK_EQUAL(&e1, list.GetLast());
230 CHECK_EQUAL(&list, e1.GetHead());
231
232 list.LinkFront(e2);
233 CHECK_EQUAL(&e2, list.GetFirst());
234 CHECK_EQUAL(&e1, list.GetLast());
235
236 list.LinkFront(e3);
237 CHECK_EQUAL(&e3, list.GetFirst());
238 CHECK_EQUAL(&e1, list.GetLast());
239
240 CHECK_EQUAL(3, list.GetSize());
241}
242
243TEST(DList, LinkBack)
244{
245 ListHead list;
246 ListEntry e1(1), e2(2), e3(3);
247
248 list.LinkBack(e1);
249 CHECK_EQUAL(&e1, list.GetFirst());
250 CHECK_EQUAL(&e1, list.GetLast());
251 CHECK_EQUAL(&list, e1.GetHead());
252
253 list.LinkBack(e2);
254 CHECK_EQUAL(&e1, list.GetFirst());
255 CHECK_EQUAL(&e2, list.GetLast());
256
257 list.LinkBack(e3);
258 CHECK_EQUAL(&e1, list.GetFirst());
259 CHECK_EQUAL(&e3, list.GetLast());
260
261 CHECK_EQUAL(3, list.GetSize());
262}
263
264TEST(DList, PopFront)
265{
266 ListHead list;
267 ListEntry e1(1), e2(2), e3(3);
268
269 list.LinkBack(e1);
270 list.LinkBack(e2);
271 list.LinkBack(e3);
272
273 list.PopFront();
274
275 CHECK_EQUAL(&e2, list.GetFirst());
276 CHECK_EQUAL(&e3, list.GetLast());
277
278 list.PopFront();
279
280 CHECK_EQUAL(&e3, list.GetFirst());
281 CHECK_EQUAL(&e3, list.GetLast());
282
283 list.PopFront();
284
285 CHECK_EQUAL_ZERO(list.GetSize());
286 CHECK_TRUE(list.IsEmpty());
287 CHECK_TRUE(NULL == list.GetFirst());
288 CHECK_TRUE(NULL == list.GetLast());
289}
290
291TEST(DList, PopBack)
292{
293 ListHead list;
294 ListEntry e1(1), e2(2), e3(3);
295
296 list.LinkBack(e1);
297 list.LinkBack(e2);
298 list.LinkBack(e3);
299
300 list.PopBack();
301
302 CHECK_EQUAL(&e1, list.GetFirst());
303 CHECK_EQUAL(&e2, list.GetLast());
304
305 list.PopBack();
306
307 CHECK_EQUAL(&e1, list.GetFirst());
308 CHECK_EQUAL(&e1, list.GetLast());
309
310 list.PopBack();
311
312 CHECK_EQUAL_ZERO(list.GetSize());
313 CHECK_TRUE(list.IsEmpty());
314 CHECK_TRUE(NULL == list.GetFirst());
315 CHECK_TRUE(NULL == list.GetLast());
316}
317
318TEST(DList, Clear)
319{
320 ListHead list;
321 ListEntry e1(1), e2(2), e3(3);
322
323 list.LinkBack(e1);
324 list.LinkBack(e2);
325 list.LinkBack(e3);
326
327 list.Clear();
328
329 CHECK_EQUAL_ZERO(list.GetSize());
330 CHECK_TRUE(list.IsEmpty());
331 CHECK_TRUE(NULL == list.GetFirst());
332 CHECK_TRUE(NULL == list.GetLast());
333}
334
335TEST(DList, Iteration)
336{
337 ListHead list;
338 ListEntry e1(1), e2(2), e3(3);
339
340 list.LinkBack(e1);
341 list.LinkBack(e2);
342 list.LinkBack(e3);
343
344 ListHead::DLEntryType *itr = list.GetFirst();
345 CHECK_EQUAL(&e1, itr);
346
347 itr = itr->GetNext();
348 CHECK_EQUAL(&e2, itr);
349
350 itr = itr->GetNext();
351 CHECK_EQUAL(&e3, itr);
352
353 itr = itr->GetNext();
354 CHECK_EQUAL(&e1, itr);
355}
356
357TEST(DList, Relink)
358{
359 ListHead list;
360 ListEntry e1(1), e2(2), e3(3);
361
362 list.LinkBack(e1);
363 list.LinkBack(e2);
364 list.LinkBack(e3);
365
366 ListHead list2;
367 list.RelinkTo(list2);
368
369 CHECK_EQUAL_ZERO(list.GetSize());
370 CHECK_TRUE(list.IsEmpty());
371 CHECK_TRUE(NULL == list.GetFirst());
372 CHECK_TRUE(NULL == list.GetLast());
373
374 CHECK_EQUAL(3, list2.GetSize());
375 CHECK_EQUAL(&list2, e1.GetHead());
376 CHECK_EQUAL(&list2, e2.GetHead());
377 CHECK_EQUAL(&list2, e3.GetHead());
378}
379
380} // namespace stk
381} // namespace test
Namespace of STK package.
uintptr_t Word
Native processor word type.
Definition stk_common.h:113
static constexpr T Max(T a, T b)
Compile-time maximum of two values.
Definition stk_defs.h:541
@ STACK_SIZE_MIN
Minimum stack size in elements of Word. Used as a lower bound for all stack allocations (user task,...
Definition stk_common.h:83
static constexpr T Min(T a, T b)
Compile-time minimum of two values.
Definition stk_defs.h:535
Memory-related primitives.
Namespace of the test inventory.
TestContext g_TestContext
Global instance of the TestContext.
Definition stktest.cpp:16
TEST_GROUP(Kernel)
TEST(Kernel, MaxTasks)
Concrete implementation of IKernel.
Definition stk.h:81
void Initialize(uint32_t resolution_us=PERIODICITY_DEFAULT)
Initialize kernel.
Definition stk.h:832
void Start()
Start the scheduler. This call does not return until all tasks have exited (KERNEL_DYNAMIC mode) or i...
Definition stk.h:1050
void AddTask(ITask *user_task)
Register task for a soft real-time (SRT) scheduling.
Definition stk.h:859
virtual size_t GetStackSpace()
Get available stack space.
Definition stk_common.h:252
virtual const char * GetTraceName() const
Override in subclass to supply a name for SEGGER SystemView tracing. Returns NULL by default.
Definition stk_helper.h:81
size_t GetStackSizeBytes() const
Get size of the memory in bytes.
Definition stk_helper.h:56
virtual TId GetId() const
Get object's own address as its Id. Unique per task instance, requires no manual assignment.
Definition stk_helper.h:77
size_t GetStackSize() const
Get number of elements of the stack memory array.
Definition stk_helper.h:55
virtual int32_t GetWeight() const
Default weight of 1. Override in subclass if custom scheduling weight is needed.
Definition stk_helper.h:73
Word * GetStack() const
Get pointer to the stack memory.
Definition stk_helper.h:54
virtual const char * GetTraceName() const
Override in subclass to supply a name for SEGGER SystemView tracing. Returns NULL by default.
Definition stk_helper.h:151
size_t GetStackSize() const
Get number of elements of the stack memory array.
Definition stk_helper.h:127
virtual int32_t GetWeight() const
Returns the compile-time weight _Weight.
Definition stk_helper.h:143
virtual void OnDeadlineMissed(uint32_t duration)
Hard Real-Time mode is unsupported for weighted tasks. Triggers an assertion if called.
Definition stk_helper.h:134
virtual TId GetId() const
Get object's own address as its Id. Unique per task instance, requires no manual assignment.
Definition stk_helper.h:147
size_t GetStackSizeBytes() const
Get size of the memory in bytes.
Definition stk_helper.h:128
Adapts an externally-owned stack memory array to the IStackMemory interface.
Definition stk_helper.h:184
size_t GetStackSize() const
Get number of elements in the wrapped stack array.
Definition stk_helper.h:213
StackMemoryDef< _StackSize >::Type MemoryType
The concrete array type that this wrapper accepts, equivalent to StackMemoryDef<_StackSize>::Type.
Definition stk_helper.h:189
size_t GetStackSizeBytes() const
Get size of the wrapped stack array in bytes.
Definition stk_helper.h:217
Word * GetStack() const
Get pointer to the first element of the wrapped stack array.
Definition stk_helper.h:209
Intrusive doubly-linked list container. Manages a collection of DListEntry nodes embedded in host obj...
Intrusive doubly-linked list node. Embed this as a base class in any object (T) that needs to partici...
Throwable class for catching assertions from STK_ASSERT_HANDLER().
Definition stktest.h:67
Task mock for SwitchStrategySmoothWeightedRoundRobin and similar algorithms.
Definition stktest.h:408