-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathTaskTest.Mod
More file actions
128 lines (111 loc) · 3.38 KB
/
TaskTest.Mod
File metadata and controls
128 lines (111 loc) · 3.38 KB
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
121
122
123
124
125
126
127
128
(**
TaskTest.Mod - Minimal tests for Task cooperative scheduler and channels
Copyright (C) 2025
Released under The 3-Clause BSD License.
*)
MODULE TaskTest;
IMPORT Task, Tests, Collections;
TYPE
(** Wrapper for INTEGER - a Collections.Item *)
IntegerWrapper* = RECORD(Collections.Item)
value*: INTEGER
END;
IntegerWrapperPtr* = POINTER TO IntegerWrapper;
(* Context descriptor - pass data to tasks. *)
MyContext = POINTER TO MyContextDesc;
MyContextDesc = RECORD (Task.TaskContextDesc)
value: INTEGER;
counter: INTEGER
END;
VAR ts: Tests.TestSet;
(** Create a new INTEGER wrapper *)
PROCEDURE NewIntegerWrapper(i: INTEGER): Collections.ItemPtr;
VAR wrapper: IntegerWrapperPtr; result: Collections.ItemPtr;
BEGIN
NEW(wrapper);
wrapper.value := i;
result := wrapper;
RETURN result
END NewIntegerWrapper;
PROCEDURE MyTask(ctx: Task.TaskContext);
VAR myCtx: MyContext;
BEGIN
myCtx := ctx(MyContext);
CASE myCtx.resumePoint OF
| 0: (* Initialization *)
myCtx.counter := 0; Task.Yield(ctx)
| 1: (* Work phase *)
INC(myCtx.counter);
IF myCtx.counter < 3 THEN Task.YieldAt(ctx, 1) ELSE Task.Yield(ctx) END
| 2: (* Completion *)
myCtx.value := 255
END
END MyTask;
PROCEDURE TestChannelSendReceive(): BOOLEAN;
VAR ch: Task.Channel; ok: BOOLEAN; pass: BOOLEAN; msg, out : Collections.ItemPtr;
BEGIN
msg := NewIntegerWrapper(42);
pass := TRUE;
ch := Task.NewChannel(2);
ok := Task.Send(ch, msg);
pass := pass & (ok = TRUE);
ok := Task.Receive(ch, out);
pass := pass & (ok = TRUE);
pass := pass & (out(IntegerWrapperPtr).value = 42);
RETURN pass
END TestChannelSendReceive;
PROCEDURE TestChannelBufferLimits(): BOOLEAN;
VAR ch: Task.Channel; ok: BOOLEAN; pass: BOOLEAN;
BEGIN
pass := TRUE;
ch := Task.NewChannel(1);
ok := Task.Send(ch, NewIntegerWrapper(1));
pass := pass & (ok = TRUE);
ok := Task.Send(ch, NewIntegerWrapper(2));
pass := pass & (ok = FALSE);
RETURN pass
END TestChannelBufferLimits;
PROCEDURE TestChannelEmptyReceive(): BOOLEAN;
VAR ch: Task.Channel; out: Collections.ItemPtr; ok: BOOLEAN; pass: BOOLEAN;
BEGIN
pass := TRUE;
ch := Task.NewChannel(1);
ok := Task.Receive(ch, out);
pass := pass & (ok = FALSE);
RETURN pass
END TestChannelEmptyReceive;
PROCEDURE TestScheduler(): BOOLEAN;
VAR sched: Task.Scheduler; ctx : MyContext; pass: BOOLEAN;
BEGIN
pass := TRUE;
sched := Task.NewScheduler();
NEW(ctx); ctx.value := 42;
Task.AddTask(sched, MyTask, ctx);
Task.Run(sched);
pass := pass & (ctx.value = 255);
RETURN pass
END TestScheduler;
PROCEDURE TestYielding(): BOOLEAN;
VAR sched: Task.Scheduler; ctx1, ctx2: MyContext; pass: BOOLEAN;
BEGIN
pass := TRUE;
sched := Task.NewScheduler();
(* Add two tasks that will interleave *)
NEW(ctx1); ctx1.value := 10;
NEW(ctx2); ctx2.value := 20;
Task.AddTask(sched, MyTask, ctx1);
Task.AddTask(sched, MyTask, ctx2);
Task.Run(sched);
pass := pass & (ctx1.value = 255);
pass := pass & (ctx2.value = 255);
RETURN pass
END TestYielding;
BEGIN
Tests.Init(ts, "Task Tests");
Tests.Add(ts, TestChannelSendReceive);
Tests.Add(ts, TestChannelBufferLimits);
Tests.Add(ts, TestChannelEmptyReceive);
Tests.Add(ts, TestScheduler);
Tests.Add(ts, TestYielding);
ASSERT(Tests.Run(ts));
END TaskTest.