8b311101fc8d1a32397f742756e818e17595691a
[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 <senf/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(50);
46     }
47
48     bool called = false;
49     void handler()
50     {
51         called = true;
52     }
53
54 }
55
56 SENF_AUTO_UNIT_TEST(timerDispatcher)
57 {
58     char const * enabled (getenv("SENF_TIMING_CRITICAL_TESTS"));
59     BOOST_WARN_MESSAGE(enabled, "Set SENF_TIMING_CRITICAL_TESTS to not skip timing critical tests");
60
61     senf::scheduler::detail::FdManager::instance().timeout(1000);
62
63     senf::ClockService::clock_type t (senf::ClockService::now());
64     {
65         senf::scheduler::TimerEvent timer ("testTimer", &handler,
66                                            t + senf::ClockService::milliseconds(500));
67         SENF_CHECK_NO_THROW( timer.disable() );
68         SENF_CHECK_NO_THROW( timer.enable() );
69         BOOST_CHECK( timer.enabled() );
70         SENF_CHECK_NO_THROW( senf::scheduler::process() );
71         senf::ClockService::clock_type t2 (senf::ClockService::now());
72         BOOST_CHECK( called );
73         BOOST_CHECK( ! timer.enabled() );
74         if (enabled)
75             BOOST_CHECK_PREDICATE( is_close, (t2-t)(senf::ClockService::milliseconds(500)) );
76
77         called=false;
78         t = senf::ClockService::now();
79         SENF_CHECK_NO_THROW( timer.timeout(t) );
80         BOOST_CHECK( timer.enabled() );
81         SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().enable() );
82         SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().reschedule() );
83         SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
84         SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().prepareRun() );
85         SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
86         SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().disable() );
87         if (enabled)
88             BOOST_CHECK_PREDICATE( is_close, (t) (senf::ClockService::now()) );
89         BOOST_CHECK( called );
90     }
91 }
92
93 namespace {
94
95     senf::ClockService::clock_type randomDelay()
96     {
97         static boost::uniform_smallint<> random (100,300);
98         static boost::mt19937 generator;
99         return senf::scheduler::now() + senf::ClockService::milliseconds(random(generator));
100     }
101
102     unsigned count (0);
103     senf::ClockService::clock_type delay (0);
104     bool haveCb (false);
105
106     void jitterCb(senf::scheduler::TimerEvent & tm)
107     {
108         //std::cerr << "diff:" << senf::ClockService::in_microseconds( senf::scheduler::now() - tm.timeout()) << '\n';
109         count ++;
110         delay += senf::ClockService::in_microseconds( senf::scheduler::now() - tm.timeout());
111         haveCb = true;
112         tm.timeout(randomDelay());
113     }
114
115     void preCb()
116     {
117         haveCb = false;
118     }
119
120     void postCb()
121     {
122         if (! haveCb)
123             std::cerr << senf::scheduler::now() << '\n';
124     }
125
126     void idleCb(senf::scheduler::TimerEvent & tm)
127     {
128         tm.timeout( senf::scheduler::now());
129     }
130
131     void jitterTest()
132     {
133         count = 0;
134         delay = 0;
135 //        senf::scheduler::EventHook pre ("jitterTest::preCb", &preCb,
136 //                                        senf::scheduler::EventHook::PRE);
137 //        senf::scheduler::EventHook post ("jitterTest::postCb", &postCb,
138 //                                         senf::scheduler::EventHook::POST);
139
140         senf::scheduler::TimerEvent tm1 (
141                 "jitterTest::tm1", boost::bind(&jitterCb, boost::ref(tm1)), randomDelay());
142         senf::scheduler::TimerEvent tm2 (
143                 "jitterTest::tm2", boost::bind(&jitterCb, boost::ref(tm2)), randomDelay());
144         senf::scheduler::TimerEvent tm3 (
145                 "jitterTest::tm3", boost::bind(&jitterCb, boost::ref(tm3)), randomDelay());
146
147         // enabled "Idle"-Event will degrade scheduling delay
148         //senf::scheduler::TimerEvent idle (
149         //        "jitterTest::idle", boost::bind(&idleCb, boost::ref(idle)), senf::scheduler::now());
150
151         senf::scheduler::TimerEvent timeout("jitterTest::timeout", &senf::scheduler::terminate,
152                                             senf::scheduler::now() + senf::ClockService::seconds(5));
153
154         senf::scheduler::process();
155
156         std::cerr << "Average scheduling delay: " << delay/count << " microseconds\n";
157     }
158
159 }
160
161 SENF_AUTO_UNIT_TEST(timerJitter)
162 {
163     senf::scheduler::watchdogTimeout(0);
164     std::cerr << "Epoll timers\n";
165     senf::scheduler::loresTimers();
166     jitterTest();
167     std::cerr << "Hires timers\n";
168     senf::scheduler::hiresTimers();
169     jitterTest();
170     senf::scheduler::loresTimers();
171     senf::scheduler::watchdogTimeout(1000);
172     BOOST_CHECK( true );
173 }
174
175 ///////////////////////////////cc.e////////////////////////////////////////
176 #undef prefix_
177
178 \f
179 // Local Variables:
180 // mode: c++
181 // fill-column: 100
182 // comment-column: 40
183 // c-file-style: "senf"
184 // indent-tabs-mode: nil
185 // ispell-local-dictionary: "american"
186 // compile-command: "scons -u test"
187 // End: