PPI: Missing commit
[senf.git] / Scheduler / TimerEvent.test.cc
1 // $Id$
2 //
3 // Copyright (C) 2008 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief TimerEvent unit tests */
25
26 //#include "TimerEvent.test.hh"
27 //#include "TimerEvent.test.ih"
28
29 // Custom includes
30 #include "TimerEvent.hh"
31 #include "Scheduler.hh"
32 #include <boost/bind.hpp>
33
34 #include "../Utils//auto_unit_test.hh"
35 #include <boost/test/test_tools.hpp>
36 #include <boost/random.hpp>
37
38 #define prefix_
39 ///////////////////////////////cc.p////////////////////////////////////////
40
41 namespace {
42
43     bool is_close(senf::ClockService::clock_type a, senf::ClockService::clock_type b)
44     {
45         return (a<b ? b-a : a-b) < senf::ClockService::milliseconds(100);
46     }
47     
48     bool called = false;
49     void handler()
50     {
51         called = true;
52     }
53
54 }
55
56 BOOST_AUTO_UNIT_TEST(timerDispatcher)
57 {
58     senf::scheduler::detail::FdManager::instance().timeout(1000);
59
60     senf::ClockService::clock_type t (senf::ClockService::now());
61     {
62         senf::scheduler::TimerEvent timer ("testTimer", &handler, 
63                                            t + senf::ClockService::milliseconds(500));
64         SENF_CHECK_NO_THROW( timer.disable() );
65         SENF_CHECK_NO_THROW( timer.enable() );
66         BOOST_CHECK( timer.enabled() );
67         SENF_CHECK_NO_THROW( senf::scheduler::process() );
68         senf::ClockService::clock_type t2 (senf::ClockService::now());
69         BOOST_CHECK( called );
70         BOOST_CHECK( ! timer.enabled() );
71         BOOST_CHECK_PREDICATE( is_close, (t2-t)(senf::ClockService::milliseconds(500)) );
72
73         called=false;
74         t = senf::ClockService::now();
75         SENF_CHECK_NO_THROW( timer.timeout(t) );
76         BOOST_CHECK( timer.enabled() );
77         SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().enable() );
78         SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().reschedule() );
79         SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
80         SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().prepareRun() );
81         SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
82         SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().disable() );
83         BOOST_CHECK_PREDICATE( is_close, (t) (senf::ClockService::now()) );
84         BOOST_CHECK( called );
85     }
86 }
87
88 namespace {
89
90     senf::ClockService::clock_type randomDelay()
91     {
92         static boost::uniform_smallint<> random (100,300);
93         static boost::mt19937 generator;
94         return senf::scheduler::now() + senf::ClockService::milliseconds(random(generator));
95     }
96
97     unsigned count (0);
98     senf::ClockService::clock_type delay (0);
99     bool haveCb (false);
100
101     void jitterCb(senf::scheduler::TimerEvent & tm)
102     {
103         std::cerr << senf::scheduler::now() << ' ' << tm.timeout() << '\n';
104         count ++;
105         delay += senf::scheduler::now() - tm.timeout();
106         haveCb = true;
107         tm.timeout(randomDelay());
108     }
109
110     void preCb()
111     {
112         haveCb = false;
113     }
114
115     void postCb()
116     {
117         if (! haveCb)
118             std::cerr << senf::scheduler::now() << '\n';
119     }
120
121     void jitterTest()
122     {
123         count = 0;
124         delay = 0;
125         senf::scheduler::EventHook pre ("jitterTest::preCb", &preCb,
126                                         senf::scheduler::EventHook::PRE);
127         senf::scheduler::EventHook post ("jitterTest::postCb", &postCb,
128                                          senf::scheduler::EventHook::POST);
129
130         senf::scheduler::TimerEvent tm1 ("jitterTest::tm1", boost::bind(&jitterCb, boost::ref(tm1)),
131                                          randomDelay());
132         senf::scheduler::TimerEvent tm2 ("jitterTest::tm2", boost::bind(&jitterCb, boost::ref(tm2)),
133                                          randomDelay());
134         senf::scheduler::TimerEvent tm3 ("jitterTest::tm3", boost::bind(&jitterCb, boost::ref(tm3)),
135                                          randomDelay());
136         
137         senf::scheduler::TimerEvent timeout("jitterTest::timeout", &senf::scheduler::terminate,
138                                             senf::scheduler::now() + senf::ClockService::seconds(5));
139
140         senf::scheduler::process();
141
142         std::cerr << "Average scheduling delay: " << delay/count << "\n";
143     }
144
145 }
146
147 BOOST_AUTO_UNIT_TEST(timerJitter)
148 {
149     senf::scheduler::watchdogTimeout(0);
150     std::cerr << "Epoll timers\n";
151     senf::scheduler::loresTimers();
152     jitterTest();
153     std::cerr << "Hires timers\n";
154     senf::scheduler::hiresTimers();
155     jitterTest();
156     senf::scheduler::watchdogTimeout(1000);
157 }
158
159 ///////////////////////////////cc.e////////////////////////////////////////
160 #undef prefix_
161
162 \f
163 // Local Variables:
164 // mode: c++
165 // fill-column: 100
166 // comment-column: 40
167 // c-file-style: "senf"
168 // indent-tabs-mode: nil
169 // ispell-local-dictionary: "american"
170 // compile-command: "scons -u test"
171 // End: