time_test.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Fri Feb 11 15:59:13 CET 2005 time_test.cpp
3 
4  time_test.cpp - description
5  -------------------
6  begin : Fri February 11 2005
7  copyright : (C) 2005 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10  ***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "unit.hpp"
20 
21 #include "time_test.hpp"
22 #include <boost/bind.hpp>
23 #include <os/Timer.hpp>
24 #include <rtt-detail-fwd.hpp>
25 #include <iostream>
26 
27 #define EPSILON 0.000000002
28 
29 // Registers the fixture into the 'registry'
30 //CPPUNIT_TEST_SUITE_REGISTRATION( TimeTest );
31 
32 using namespace std;
33 using namespace RTT;
34 using namespace RTT::detail;
35 using namespace boost;
36 
38 {
39  hbg = TimeService::Instance();
40  long_ns = 9007199254740992LL; // == 2^53
41  //long_ns = 4503599627370496LL; // == 2^52
42  //long_ns = 123456789123456789LL; // 1.234...e17 ns == approx 4 years, but double can not represent this.
43  long_S = 9007199.254740992;
44  //long_S = 4.503599627370496e14;
45  normal_ns = 1000000000; // 1s
46  normal_S = 1.0; // 1s
47  small_ns = 10; // 10ns
48  small_S = 10e-9; // 10ns
49  small_t = 10;
50  normal_t = 1000000000; // 1e9 ticks
51  long_t = long_ns; // == 2^53
52 }
53 
55 {
56  hbg->enableSystemClock( true );
57 }
58 
59 struct TestTimer
60  : public Timer
61 {
62  std::vector< std::pair<Timer::TimerId, Seconds> > occured;
64  boost::function<void(Timer::TimerId)> mcallback;
67  {
68  occured.reserve(100);
69  mstart = TimeService::Instance()->secondsSince(0);
70  }
71  void timeout(Timer::TimerId id)
72  {
73  Seconds now = TimeService::Instance()->secondsSince( 0 );
74  occured.push_back( std::make_pair(id, now) );
75  //cout << "Occured: "<< id <<" on " << now - mstart <<"\n";
76 
77  if (mcallback) {
78  mcallback(id);
79  mcallback = NULL;
80  }
81  }
82 
84  {
85  cout.flush();
86  }
87 };
88 
89 BOOST_FIXTURE_TEST_SUITE( TimeTestSuite, TimeTest )
90 
91 BOOST_AUTO_TEST_CASE( testSecondsConversion )
92 {
93  // Test one way
94  BOOST_REQUIRE_EQUAL( long_ns , Seconds_to_nsecs(long_S) );
95  BOOST_REQUIRE_EQUAL( normal_ns, Seconds_to_nsecs(normal_S));
96  BOOST_REQUIRE_EQUAL( small_ns , Seconds_to_nsecs(small_S) );
97 
98  // Test other way
99  BOOST_REQUIRE_EQUAL( long_S , nsecs_to_Seconds(long_ns));
100  BOOST_REQUIRE_EQUAL( normal_S, nsecs_to_Seconds(normal_ns));
101  BOOST_REQUIRE_EQUAL( small_S , nsecs_to_Seconds(small_ns));
102 
103  // Test invariance of conversions :
104  BOOST_REQUIRE_EQUAL( long_ns , Seconds_to_nsecs( nsecs_to_Seconds(long_ns) ));
105  BOOST_REQUIRE_EQUAL( normal_ns, Seconds_to_nsecs( nsecs_to_Seconds(normal_ns) ));
106  BOOST_REQUIRE_EQUAL( small_ns , Seconds_to_nsecs( nsecs_to_Seconds(small_ns) ));
107  BOOST_REQUIRE_EQUAL( long_S , nsecs_to_Seconds( Seconds_to_nsecs(long_S) ));
108  BOOST_REQUIRE_EQUAL( normal_S, nsecs_to_Seconds( Seconds_to_nsecs(normal_S) ));
109  BOOST_REQUIRE_EQUAL( small_S , nsecs_to_Seconds( Seconds_to_nsecs(small_S) ));
110 }
111 
112 BOOST_AUTO_TEST_CASE( testTicksConversion )
113 {
114  // Test ticks conversion invariance :
115  // margin is in % rounding error.
116  int margin = 1;
117 //#if defined( OROCOS_TARGET_LXRT) || defined(OROCOS_TARGET_XENOMAI)
118 // int small_margin = 25; // 25% of 8ns : allow a two-off.
119 //#else
120 // int small_margin = 10; // 10% of 8ns : allow a one-off.
121 //#endif
122 
123  // I'm removing the small conversions because they test more the underlying RTOS than Orocos and the underlying RTOS
124  // isn't fixing this for years...
125  BOOST_REQUIRE_CLOSE( (double)long_ns , (double)TimeService::ticks2nsecs( TimeService::nsecs2ticks( long_ns )), margin );
126  BOOST_REQUIRE_CLOSE( (double)normal_ns, (double)TimeService::ticks2nsecs( TimeService::nsecs2ticks( normal_ns )), margin );
127  //BOOST_REQUIRE_CLOSE( (double)small_ns , (double)TimeService::ticks2nsecs( TimeService::nsecs2ticks( small_ns )), small_margin );
128  BOOST_REQUIRE_CLOSE( (double)long_t , (double)TimeService::nsecs2ticks( TimeService::ticks2nsecs( long_t )), margin );
129  BOOST_REQUIRE_CLOSE( (double)normal_t, (double)TimeService::nsecs2ticks( TimeService::ticks2nsecs( normal_t )), margin );
130  //BOOST_REQUIRE_CLOSE( (double)small_t , (double)TimeService::nsecs2ticks( TimeService::ticks2nsecs( small_t )), small_margin );
131 }
132 
133 BOOST_AUTO_TEST_CASE( testTimeProgress )
134 {
135  // A time measurement takes time :
136  TimeService::ticks t = hbg->getTicks();
137  usleep(100000);
138  BOOST_CHECK( t != hbg->getTicks() );
139  BOOST_CHECK( 0 != hbg->ticksSince(t) );
140  BOOST_CHECK( 0 != hbg->secondsSince(t) );
141 
142  // With Re-init of t :
143  t = 0;
144  BOOST_REQUIRE_EQUAL( TimeService::ticks(0) , hbg->getTicks( t ) );
145  t = 0;
146  // BOOST_REQUIRE_EQUAL( Seconds(0.0) , hbg->getSeconds( t ) );
147 
148  // Stop Time Progress:
149  hbg->enableSystemClock( false );
150  t = hbg->getTicks();
151  BOOST_REQUIRE_EQUAL( t , hbg->getTicks() );
152  BOOST_REQUIRE_EQUAL( TimeService::ticks(0) , hbg->ticksSince(t) );
153  // BOOST_REQUIRE_EQUAL( Seconds(0.0) , hbg->secondsSince(t) );
154 
155  Seconds change_S = 0.123456789;
156 
157  hbg->secondsChange( change_S );
158  BOOST_CHECK( t != hbg->getTicks() ); // ticks must have changed
159  BOOST_CHECK( -EPSILON < (change_S - hbg->secondsSince(t)) &&
160  EPSILON > (change_S - hbg->secondsSince(t)) );
161 
162  // Restart Time Progress
163  hbg->enableSystemClock( true );
164  BOOST_CHECK( t != hbg->getTicks() );
165  BOOST_CHECK( TimeService::ticks(0) != hbg->ticksSince(t) );
166  BOOST_CHECK( Seconds(0.0) != hbg->secondsSince(t) );
167 
168 }
169 
170 BOOST_AUTO_TEST_CASE( testTimers )
171 {
172  TestTimer timer;
173  Seconds now = hbg->secondsSince( 0 );
174  // Test arming
175  BOOST_CHECK( timer.arm(0, 0.5) );
176  BOOST_CHECK( timer.arm(1, 0.6) );
177  BOOST_CHECK( timer.arm(2, 0.5) );
178 
179  BOOST_CHECK( timer.arm(3, 0.8) );
180  BOOST_CHECK( timer.arm(3, 0.9) );
181 
182  BOOST_CHECK( timer.isArmed( 0 ) );
183  BOOST_CHECK( timer.isArmed( 1 ) );
184  BOOST_CHECK( timer.isArmed( 2 ) );
185  BOOST_CHECK( timer.isArmed( 3 ) );
186 
187  sleep(2);
188 
189  // Test clearing
190  BOOST_CHECK( !timer.isArmed( 0 ) );
191  BOOST_CHECK( !timer.isArmed( 1 ) );
192  BOOST_CHECK( !timer.isArmed( 2 ) );
193  BOOST_CHECK( !timer.isArmed( 3 ) );
194 
195  // Test sequence
196  BOOST_CHECK( timer.occured.size() == 4 );
197  BOOST_CHECK( timer.occured[0].first == 0 );
198  BOOST_CHECK( timer.occured[1].first == 2 );
199  BOOST_CHECK( timer.occured[2].first == 1 );
200  BOOST_CHECK( timer.occured[3].first == 3 );
201 
202  // Test timeliness
203  BOOST_REQUIRE_CLOSE( timer.occured[0].second, now+0.5, 0.1 );
204  BOOST_REQUIRE_CLOSE( timer.occured[1].second, now+0.5, 0.1 );
205  BOOST_REQUIRE_CLOSE( timer.occured[2].second, now+0.6, 0.1 );
206  BOOST_REQUIRE_CLOSE( timer.occured[3].second, now+0.9, 0.1 );
207 
208  // Test wrong parameters.
209  BOOST_CHECK( timer.arm(4, -0.1) == false);
210  BOOST_CHECK( timer.arm(32, 0.1) == false);
211 
212  timer.occured.clear();
213 
214  // Test resize.
215  BOOST_CHECK( timer.arm(10, 0.5) );
216  timer.setMaxTimers( 5 ); // clears the timer
217  sleep(1);
218  BOOST_CHECK( timer.occured.size() == 0 );
219 }
220 
221 BOOST_AUTO_TEST_CASE( testTimerPeriod )
222 {
223  TestTimer timer;
224  Seconds now = hbg->secondsSince( 0 );
225  // Test starting periodics
226  BOOST_CHECK( timer.startTimer(0, 0.1) );
227  BOOST_CHECK( timer.startTimer(1, 0.6) );
228  BOOST_CHECK( timer.startTimer(2, 0.5) );
229 
230  BOOST_CHECK( timer.startTimer(3, 0.5) );
231  BOOST_CHECK( timer.startTimer(3, 0.2) );
232 
233  BOOST_CHECK( timer.isArmed( 0 ) );
234  BOOST_CHECK( timer.isArmed( 1 ) );
235  BOOST_CHECK( timer.isArmed( 2 ) );
236  BOOST_CHECK( timer.isArmed( 3 ) );
237 
238  sleep(2);
239 
240  // Test clearing
241  BOOST_CHECK( timer.killTimer( 0 ) );
242  BOOST_CHECK( timer.killTimer( 1 ) );
243  BOOST_CHECK( timer.killTimer( 2 ) );
244  BOOST_CHECK( timer.killTimer( 3 ) );
245  BOOST_CHECK( !timer.isArmed( 0 ) );
246  BOOST_CHECK( !timer.isArmed( 1 ) );
247  BOOST_CHECK( !timer.isArmed( 2 ) );
248  BOOST_CHECK( !timer.isArmed( 3 ) );
249 
250  // Test sequence
251  //BOOST_CHECK( timer.occured.size() == 4 ); hard to estimate
252  BOOST_CHECK( timer.occured[0].first == 0 );
253  BOOST_CHECK( timer.occured[1].first == 0 );
254  BOOST_CHECK( timer.occured[2].first == 3 );
255  BOOST_CHECK( timer.occured[3].first == 0 );
256  BOOST_CHECK( timer.occured[4].first == 0 );
257  BOOST_CHECK( timer.occured[5].first == 3 );
258 
259  BOOST_CHECK( timer.occured[6].first == 0 );
260  BOOST_CHECK( timer.occured[7].first == 2 );
261 
262  BOOST_CHECK( timer.occured[8].first == 0 );
263  BOOST_CHECK( timer.occured[9].first == 1 );
264  BOOST_CHECK( timer.occured[10].first == 3 );
265  BOOST_CHECK( timer.occured[11].first == 0 );
266  BOOST_CHECK( timer.occured[12].first == 0 );
267  BOOST_CHECK( timer.occured[13].first == 3 );
268  BOOST_CHECK( timer.occured[14].first == 0 );
269 
270  // Test timeliness
271  BOOST_REQUIRE_CLOSE( timer.occured[0].second, now+0.1, 0.1 );
272  BOOST_REQUIRE_CLOSE( timer.occured[1].second, now+0.2, 0.1 );
273  BOOST_REQUIRE_CLOSE( timer.occured[2].second, now+0.2, 0.1 );
274  BOOST_REQUIRE_CLOSE( timer.occured[3].second, now+0.3, 0.1 );
275  BOOST_REQUIRE_CLOSE( timer.occured[4].second, now+0.4, 0.1 );
276  BOOST_REQUIRE_CLOSE( timer.occured[5].second, now+0.4, 0.1 );
277  BOOST_REQUIRE_CLOSE( timer.occured[6].second, now+0.5, 0.1 );
278  BOOST_REQUIRE_CLOSE( timer.occured[7].second, now+0.5, 0.1 );
279  BOOST_REQUIRE_CLOSE( timer.occured[8].second, now+0.6, 0.1 );
280  BOOST_REQUIRE_CLOSE( timer.occured[9].second, now+0.6, 0.1 );
281  BOOST_REQUIRE_CLOSE( timer.occured[10].second, now+0.6, 0.1 );
282  BOOST_REQUIRE_CLOSE( timer.occured[11].second, now+0.7, 0.1 );
283  BOOST_REQUIRE_CLOSE( timer.occured[12].second, now+0.8, 0.1 );
284  BOOST_REQUIRE_CLOSE( timer.occured[13].second, now+0.8, 0.1 );
285  BOOST_REQUIRE_CLOSE( timer.occured[14].second, now+0.9, 0.1 );
286 
287  // Test wrong parameters.
288  BOOST_CHECK( timer.startTimer(4, -0.1) == false);
289  BOOST_CHECK( timer.startTimer(500, 0.1) == false);
290 
291  timer.occured.clear();
292 
293  // Test resize.
294  BOOST_CHECK( timer.startTimer(10, 0.5) );
295  timer.setMaxTimers( 5 ); // clears the timer
296  sleep(1);
297  BOOST_CHECK( timer.occured.size() == 0 );
298 }
299 
300 BOOST_AUTO_TEST_CASE( testTimerWaitFor )
301 {
302  TestTimer timer;
303  Seconds now = hbg->secondsSince( 0 );
304 
305  // Test waitFor
306  BOOST_CHECK( timer.arm(0, 1.0) );
307  BOOST_CHECK( timer.isArmed( 0 ) == true );
308  BOOST_CHECK( timer.waitFor( 0 ) == true );
309  BOOST_CHECK( timer.isArmed( 0 ) == false );
310  BOOST_REQUIRE_CLOSE( hbg->secondsSince(0), now + 1.0, 0.1 );
311 
312  // Test waitForUntil
313  now = hbg->secondsSince( 0 );
314  BOOST_CHECK( timer.arm(0, 1.0) );
315  BOOST_CHECK( timer.isArmed( 0 ) == true );
316  BOOST_CHECK( timer.waitForUntil(0, hbg->getNSecs() + RTT::Seconds_to_nsecs(0.5) ) == false );
317  BOOST_CHECK( timer.isArmed( 0 ) == true );
318  BOOST_REQUIRE_CLOSE( hbg->secondsSince( 0 ), now + 0.5, 0.1 );
319  sleep(1);
320  BOOST_CHECK( timer.isArmed( 0 ) == false );
321 
322  // Test killing of one timer
323  now = hbg->secondsSince( 0 );
324  BOOST_CHECK( timer.arm(0, 1.0) );
325  BOOST_CHECK( timer.isArmed( 0 ) );
326  // program timer 1 to kill timer 0 after 0.5 seconds
327  timer.mcallback = boost::bind(&Timer::killTimer, &timer, 0);
328  BOOST_CHECK( timer.arm(1, 0.5) );
329  BOOST_CHECK( timer.isArmed( 1 ) );
330  // wait for timer 0
331  BOOST_CHECK( timer.waitFor( 0 ) );
332  // callback killed timer 1
333  BOOST_CHECK( timer.isArmed( 0 ) == false );
334  BOOST_CHECK( timer.isArmed( 1 ) == false );
335  BOOST_REQUIRE_CLOSE( hbg->secondsSince(0), now + 0.5, 0.1 );
336 
337  // Test stopping the timer thread while another thread is waiting
338  now = hbg->secondsSince( 0 );
339  BOOST_CHECK( timer.arm(0, 1.0) );
340  BOOST_CHECK( timer.isArmed( 0 ) );
341  // program timer 1 to stop the timer activity after 0.5 seconds
342  timer.mcallback = boost::bind(&ActivityInterface::stop, timer.getActivity());
343  BOOST_CHECK( timer.arm(1, 0.5) );
344  BOOST_CHECK( timer.isArmed( 1 ) );
345  // wait for timer 0
346  BOOST_CHECK( timer.waitFor( 0 ) );
347  // callback stopped the timer activity and waitFor(0) should have returned
348  BOOST_CHECK( timer.isArmed( 0 ) == false );
349  BOOST_CHECK( timer.isArmed( 1 ) == false );
350  BOOST_REQUIRE_CLOSE( hbg->secondsSince(0), now + 0.5, 0.1 );
351 }
352 
void timeout(Timer::TimerId id)
Definition: time_test.cpp:71
#define BOOST_FIXTURE_TEST_SUITE(suite_name, F)
double Seconds
Definition: os/Time.hpp:53
boost::function< void(Timer::TimerId)> mcallback
Definition: time_test.cpp:64
Seconds nsecs_to_Seconds(const nsecs ns)
Definition: os/Time.hpp:108
#define BOOST_AUTO_TEST_SUITE_END()
Definition: mystd.hpp:163
int usleep(unsigned int us)
Definition: fosi.cpp:58
const int HighestPriority
Definition: ecosthreads.cpp:45
printstream cout
Definition: rtstreams.cpp:45
unsigned int sleep(unsigned int s)
Definition: fosi.cpp:51
BOOST_AUTO_TEST_CASE(testSecondsConversion)
Definition: time_test.cpp:91
nsecs Seconds_to_nsecs(const Seconds s)
Definition: os/Time.hpp:107
TimeService::Seconds mstart
Definition: time_test.cpp:63
#define EPSILON
Definition: time_test.cpp:27
#define ORO_SCHED_RT
Definition: ecos/fosi.h:61
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:53
std::vector< std::pair< Timer::TimerId, Seconds > > occured
Definition: time_test.cpp:62


rtt
Author(s): RTT Developers
autogenerated on Fri Oct 25 2019 03:59:44