1+ /*
2+ * Copyright (c) 2015-2021 University of Antwerp, Aloxy NV.
3+ *
4+ * This file is part of Sub-IoT.
5+ * See https://github.com/Sub-IoT/Sub-IoT-Stack for further info.
6+ *
7+ * Licensed under the Apache License, Version 2.0 (the "License");
8+ * you may not use this file except in compliance with the License.
9+ * You may obtain a copy of the License at
10+ *
11+ * http://www.apache.org/licenses/LICENSE-2.0
12+ *
13+ * Unless required by applicable law or agreed to in writing, software
14+ * distributed under the License is distributed on an "AS IS" BASIS,
15+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+ * See the License for the specific language governing permissions and
17+ * limitations under the License.
18+ */
19+ #include "stdio.h"
20+ #include <stdlib.h>
21+ #include "timer.c"
22+
23+ #define COUNTER_OVERFLOW_MAX 0xFFFF0000
24+
25+ static timer_event dummy_tester_event ;
26+ static timer_event dummy_tester_event2 ;
27+ static timer_event dummy_tester_event3 ;
28+ static timer_event dummy_tester_event4 ;
29+ static timer_event dummy_tester_event5 ;
30+ static timer_event dummy_tester_event6 ;
31+
32+ void dummy_function (){}
33+ void dummy_function2 (){}
34+ void dummy_function3 (){}
35+ void dummy_function4 (){}
36+ void dummy_function5 (){}
37+ void dummy_function6 (){}
38+ void dummy_function7 (){}
39+ void dummy_function8 (){}
40+
41+ void test_timer_events () {
42+ //can init event
43+ assert (timer_init_event (& dummy_tester_event , & dummy_function ) == SUCCESS );
44+ //cannot init same event multiple times
45+ assert (timer_init_event (& dummy_tester_event , & dummy_function ) == - EALREADY );
46+ //manually conf next_event
47+ dummy_tester_event .next_event = TIMER_TICKS_PER_SEC * 1 ;
48+ // can post a task from an event
49+ assert (timer_add_event (& dummy_tester_event ) == SUCCESS );
50+ // after adding event, associated task is scheduled
51+ assert (timer_is_task_scheduled (dummy_tester_event .f ));
52+ // cancel event
53+ timer_cancel_event (& dummy_tester_event );
54+ // after cancelling event, associated task is no longer scheduled
55+ assert (timer_is_task_scheduled (dummy_tester_event .f ) == false);
56+ }
57+
58+ void test_timer_post_tasks () {
59+ // cannot post task with less than min priority
60+ assert (timer_post_task_prio_delay (& dummy_function2 , TIMER_TICKS_PER_SEC * 5 , MIN_PRIORITY + 1 ) == EINVAL );
61+ // can post task
62+ assert (timer_post_task_prio_delay (& dummy_function2 , TIMER_TICKS_PER_SEC * 5 , DEFAULT_PRIORITY ) == SUCCESS );
63+ // after posting, task is scheduled
64+ assert (timer_is_task_scheduled (& dummy_function2 ));
65+ // can modify the fire time by posting the same task again
66+ assert (timer_post_task_prio_delay (& dummy_function2 , TIMER_TICKS_PER_SEC * 7 , DEFAULT_PRIORITY ) == SUCCESS );
67+ // cannot modify the priority by posting the same task again
68+ assert (timer_post_task_prio_delay (& dummy_function2 , TIMER_TICKS_PER_SEC * 7 , DEFAULT_PRIORITY - 1 ) == EALREADY );
69+ // can cancel the task
70+ assert (timer_cancel_task (& dummy_function2 ) == SUCCESS );
71+ // after cancelling, task is no longer scheduled
72+ assert (timer_is_task_scheduled (& dummy_function2 ) == false);
73+ // cannot cancel an unscheduled task
74+ assert (timer_cancel_task (& dummy_function2 ) == EALREADY );
75+
76+ // task posted with delay of 0 is scheduled immediately
77+ sched_register_task (& dummy_function3 );
78+ assert (timer_post_task_prio_delay (& dummy_function3 , TIMER_TICKS_PER_SEC * 0 , DEFAULT_PRIORITY ) == SUCCESS );
79+ assert (timer_is_task_scheduled (& dummy_function3 ) == false);
80+ }
81+
82+ void run_overflow_test (timer_tick_t timer_offset , timer_tick_t next_event_time ) {
83+ NG (timer_offset ) = timer_offset ;
84+ NG (timers )[NG (next_event )].next_event = next_event_time ;
85+ NG (hw_event_scheduled ) = false;
86+ run_overflow_c ();
87+ }
88+ void test_timer_overflow () {
89+ set_hw_timer_value (0 );
90+ //regular cases:
91+ //create an event
92+ assert (timer_init_event (& dummy_tester_event2 , & dummy_function4 ) == SUCCESS );
93+ dummy_tester_event2 .next_event = TIMER_TICKS_PER_SEC * 1 ;
94+ assert (timer_add_event (& dummy_tester_event2 ) == SUCCESS );
95+
96+ // event is in the next period
97+ run_overflow_test (COUNTER_OVERFLOW_INCREASE * 10 , COUNTER_OVERFLOW_INCREASE * 11 + 3000 );
98+ assert (NG (hw_event_scheduled ) == true); //i.e. event gets scheduled for the next period
99+
100+ // event is in the far future
101+ run_overflow_test (COUNTER_OVERFLOW_INCREASE * 10 , COUNTER_OVERFLOW_INCREASE * 12 + 3000 );
102+ assert ( (NG (hw_event_scheduled ) == false) && NG (timers )[NG (next_event )].f != 0x0 ); //i.e. event should not be scheduled yet
103+
104+ // event is in the distant past
105+ run_overflow_test (COUNTER_OVERFLOW_INCREASE * 10 , 0 );
106+ assert ( (NG (hw_event_scheduled ) == false) && NG (timers )[NG (next_event )].f != 0x0 ); //i.e. event doesn't get fired
107+
108+ // event is in this period but in near past (behind hw_timer time)
109+ set_hw_timer_value (4000 );
110+ run_overflow_test (COUNTER_OVERFLOW_INCREASE * 10 , COUNTER_OVERFLOW_INCREASE * 11 + 3000 );
111+ assert ( (NG (hw_event_scheduled ) == false) && get_next_event () == NO_EVENT ); //i.e. event got fired immediately
112+ set_hw_timer_value (0 );
113+
114+ timer_cancel_event (& dummy_tester_event2 );
115+
116+ //overflow cases:
117+ //create another event
118+ assert (timer_init_event (& dummy_tester_event3 , & dummy_function5 ) == SUCCESS );
119+ dummy_tester_event3 .next_event = TIMER_TICKS_PER_SEC * 1 ;
120+ assert (timer_add_event (& dummy_tester_event3 ) == SUCCESS );
121+
122+ // event is in the next period
123+ run_overflow_test (COUNTER_OVERFLOW_MAX , 3000 );
124+ assert (NG (hw_event_scheduled ) == true); //i.e. event gets scheduled for the next period
125+
126+ // event is in the far future
127+ run_overflow_test (COUNTER_OVERFLOW_MAX , COUNTER_OVERFLOW_INCREASE + 3000 );
128+ assert ( (NG (hw_event_scheduled ) == false) && NG (timers )[NG (next_event )].f != 0x0 ); //i.e. event should not be scheduled yet
129+
130+ // event is in the distant past
131+ set_hw_timer_value (0 );
132+ run_overflow_test (0 , COUNTER_OVERFLOW_MAX );
133+ assert ( (NG (hw_event_scheduled ) == false) && NG (timers )[NG (next_event )].f != 0x0 ); //i.e. event doesn't get fired
134+
135+ // event is in this period but in near past (behind hw_timer time)
136+ set_hw_timer_value (4000 );
137+ run_overflow_test (COUNTER_OVERFLOW_MAX , 3000 );
138+ assert ( (NG (hw_event_scheduled ) == false) && get_next_event () == NO_EVENT ); //i.e. event got fired immediately
139+
140+ timer_cancel_event (& dummy_tester_event3 );
141+ }
142+
143+ void setup_counter_test (timer_tick_t timer_offset , uint16_t hw_timer_value , bool is_overflow_pending ) {
144+ NG (timer_offset ) = timer_offset ;
145+ set_hw_timer_value (hw_timer_value );
146+ set_overflow_pending (is_overflow_pending );
147+ }
148+
149+ void test_timer_get_counter_value () {
150+ //regular cases:
151+ setup_counter_test (COUNTER_OVERFLOW_INCREASE , 0x00ff , false);
152+ assert (timer_get_counter_value () == COUNTER_OVERFLOW_INCREASE + 0x00ff );
153+ setup_counter_test (COUNTER_OVERFLOW_INCREASE , 0x00ff , true);
154+ assert (timer_get_counter_value () == COUNTER_OVERFLOW_INCREASE + 0x00ff + COUNTER_OVERFLOW_INCREASE );
155+
156+ //overflow cases:
157+ setup_counter_test (COUNTER_OVERFLOW_MAX , 0x00ff , false);
158+ assert (timer_get_counter_value () == COUNTER_OVERFLOW_MAX + 0x00ff );
159+ setup_counter_test (COUNTER_OVERFLOW_MAX , 0x00ff , true);
160+ assert (timer_get_counter_value () == COUNTER_OVERFLOW_MAX + 0x00ff + COUNTER_OVERFLOW_INCREASE );
161+ }
162+
163+ void test_timer_timed_events () {
164+ //reset time to 0
165+ NG (timer_offset ) = 0 ;
166+ set_hw_timer_value (0 );
167+ set_overflow_pending (false);
168+
169+ // - schedule three events of different times
170+ assert (timer_init_event (& dummy_tester_event4 , & dummy_function6 ) == SUCCESS );
171+ dummy_tester_event4 .next_event = TIMER_TICKS_PER_SEC * 1 ;
172+ assert (timer_init_event (& dummy_tester_event5 , & dummy_function7 ) == SUCCESS );
173+ dummy_tester_event5 .next_event = TIMER_TICKS_PER_SEC * 3 ;
174+ assert (timer_init_event (& dummy_tester_event6 , & dummy_function8 ) == SUCCESS );
175+ dummy_tester_event6 .next_event = TIMER_TICKS_PER_SEC * 5 ;
176+
177+ // post tasks from the events
178+ assert (timer_add_event (& dummy_tester_event4 ) == SUCCESS );
179+ assert (timer_add_event (& dummy_tester_event5 ) == SUCCESS );
180+ assert (timer_add_event (& dummy_tester_event6 ) == SUCCESS );
181+
182+ assert (timer_is_task_scheduled (dummy_tester_event4 .f ));
183+ // check event returned is as expected
184+ uint32_t next_event = get_next_event ();
185+ assert (NG (timers )[next_event ].f == dummy_tester_event4 .f );
186+ // move time forward till after that event
187+ NG (timer_offset ) = TIMER_TICKS_PER_SEC * 2 ;
188+ // events from the past should still get returned if they haven't fired yet
189+ next_event = get_next_event ();
190+ assert (NG (timers )[next_event ].f == dummy_tester_event4 .f );
191+ timer_cancel_event (& dummy_tester_event4 );
192+ next_event = get_next_event ();
193+ assert (NG (timers )[next_event ].f == dummy_tester_event5 .f );
194+ timer_cancel_event (& dummy_tester_event5 );
195+ next_event = get_next_event ();
196+ assert (NG (timers )[next_event ].f == dummy_tester_event6 .f );
197+ timer_cancel_event (& dummy_tester_event6 );
198+ //when no events listed, should return NO_EVENT
199+ next_event = get_next_event ();
200+ assert (next_event == NO_EVENT );
201+ }
202+
203+ int main (int argc , char * argv []){
204+ timer_init ();
205+ scheduler_init ();
206+
207+ test_timer_events ();
208+
209+ test_timer_post_tasks ();
210+
211+ test_timer_overflow ();
212+
213+ test_timer_get_counter_value ();
214+
215+ test_timer_timed_events ();
216+
217+ printf ("All timer tests passed!\n" );
218+
219+ exit (0 );
220+ }
0 commit comments