Move sourcecode into 'senf/' directory
[senf.git] / senf / 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 << "diff:" << senf::ClockService::in_microseconds( senf::scheduler::now() - tm.timeout()) << '\n';
104         count ++;
105         delay += senf::ClockService::in_microseconds( 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 idleCb(senf::scheduler::TimerEvent & tm)
122     {
123         tm.timeout( senf::scheduler::now());
124     }
125
126     void jitterTest()
127     {
128         count = 0;
129         delay = 0;
130 //        senf::scheduler::EventHook pre ("jitterTest::preCb", &preCb,
131 //                                        senf::scheduler::EventHook::PRE);
132 //        senf::scheduler::EventHook post ("jitterTest::postCb", &postCb,
133 //                                         senf::scheduler::EventHook::POST);
134
135         senf::scheduler::TimerEvent tm1 (
136                 "jitterTest::tm1", boost::bind(&jitterCb, boost::ref(tm1)), randomDelay());
137         senf::scheduler::TimerEvent tm2 (
138                 "jitterTest::tm2", boost::bind(&jitterCb, boost::ref(tm2)), randomDelay());
139         senf::scheduler::TimerEvent tm3 (
140                 "jitterTest::tm3", boost::bind(&jitterCb, boost::ref(tm3)), randomDelay());
141         
142         // enabled "Idle"-Event will degrade scheduling delay
143         //senf::scheduler::TimerEvent idle (
144         //        "jitterTest::idle", boost::bind(&idleCb, boost::ref(idle)), senf::scheduler::now());
145
146         senf::scheduler::TimerEvent timeout("jitterTest::timeout", &senf::scheduler::terminate,
147                                             senf::scheduler::now() + senf::ClockService::seconds(5));
148
149         senf::scheduler::process();
150
151         std::cerr << "Average scheduling delay: " << delay/count << " microseconds\n";
152     }
153
154 }
155
156 BOOST_AUTO_UNIT_TEST(timerJitter)
157 {
158     senf::scheduler::watchdogTimeout(0);
159     std::cerr << "Epoll timers\n";
160     senf::scheduler::loresTimers();
161     jitterTest();
162     std::cerr << "Hires timers\n";
163     senf::scheduler::hiresTimers();
164     jitterTest();
165     senf::scheduler::loresTimers();
166     senf::scheduler::watchdogTimeout(1000);
167 }
168
169 ///////////////////////////////cc.e////////////////////////////////////////
170 #undef prefix_
171
172 \f
173 // Local Variables:
174 // mode: c++
175 // fill-column: 100
176 // comment-column: 40
177 // c-file-style: "senf"
178 // indent-tabs-mode: nil
179 // ispell-local-dictionary: "american"
180 // compile-command: "scons -u test"
181 // End: