Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 : /*
10 : * Timers are evil beasties across platforms ...
11 : */
12 :
13 : #include <test/bootstrapfixture.hxx>
14 :
15 : #include <osl/thread.hxx>
16 : #include <salhelper/thread.hxx>
17 :
18 : #include <vcl/timer.hxx>
19 : #include <vcl/idle.hxx>
20 : #include <vcl/svapp.hxx>
21 : #include "svdata.hxx"
22 : #include "salinst.hxx"
23 :
24 : // #define TEST_WATCHDOG
25 :
26 : /// Avoid our timer tests just wedging the build if they fail.
27 0 : class WatchDog : public osl::Thread
28 : {
29 : sal_Int32 mnSeconds;
30 : public:
31 1 : explicit WatchDog(sal_Int32 nSeconds) :
32 : Thread(),
33 1 : mnSeconds( nSeconds )
34 : {
35 1 : create();
36 1 : }
37 1 : virtual void SAL_CALL run() SAL_OVERRIDE
38 : {
39 : TimeValue aWait;
40 1 : aWait.Seconds = mnSeconds;
41 1 : aWait.Nanosec = 1000000; // +1ms
42 1 : osl::Thread::wait( aWait );
43 0 : CPPUNIT_ASSERT_MESSAGE("watchdog triggered", false);
44 0 : }
45 : };
46 :
47 1 : static WatchDog aWatchDog( 10 /* 10 secs should be enough */);
48 :
49 12 : class TimerTest : public test::BootstrapFixture
50 : {
51 : public:
52 6 : TimerTest() : BootstrapFixture(true, false) {}
53 :
54 : void testIdleMainloop();
55 : void testIdle();
56 : #ifdef TEST_WATCHDOG
57 : void testWatchdog();
58 : #endif
59 : void testDurations();
60 : void testAutoTimer();
61 : void testRecursiveTimer();
62 : void testSlowTimerCallback();
63 :
64 2 : CPPUNIT_TEST_SUITE(TimerTest);
65 1 : CPPUNIT_TEST(testIdle);
66 1 : CPPUNIT_TEST(testIdleMainloop);
67 : #ifdef TEST_WATCHDOG
68 : CPPUNIT_TEST(testWatchdog);
69 : #endif
70 1 : CPPUNIT_TEST(testDurations);
71 1 : CPPUNIT_TEST(testAutoTimer);
72 1 : CPPUNIT_TEST(testRecursiveTimer);
73 1 : CPPUNIT_TEST(testSlowTimerCallback);
74 :
75 5 : CPPUNIT_TEST_SUITE_END();
76 : };
77 :
78 : #ifdef TEST_WATCHDOG
79 : void TimerTest::testWatchdog()
80 : {
81 : // out-wait the watchdog.
82 : TimeValue aWait;
83 : aWait.Seconds = 12;
84 : aWait.Nanosec = 0;
85 : osl::Thread::wait( aWait );
86 : }
87 : #endif
88 :
89 : // --------------------------------------------------------------------
90 :
91 2 : class IdleBool : public Idle
92 : {
93 : bool &mrBool;
94 : public:
95 2 : explicit IdleBool( bool &rBool ) :
96 2 : Idle(), mrBool( rBool )
97 : {
98 2 : SetPriority( SchedulerPriority::LOWEST );
99 2 : Start();
100 2 : mrBool = false;
101 2 : }
102 2 : virtual void Invoke() SAL_OVERRIDE
103 : {
104 2 : mrBool = true;
105 2 : Application::EndYield();
106 2 : }
107 : };
108 :
109 1 : void TimerTest::testIdle()
110 : {
111 1 : bool bTriggered = false;
112 1 : IdleBool aTest( bTriggered );
113 1 : Scheduler::ProcessTaskScheduling(false);
114 1 : CPPUNIT_ASSERT_MESSAGE("idle triggered", bTriggered);
115 1 : }
116 :
117 : // tdf#91727
118 1 : void TimerTest::testIdleMainloop()
119 : {
120 1 : bool bTriggered = false;
121 1 : IdleBool aTest( bTriggered );
122 6 : while (!bTriggered)
123 : {
124 4 : ImplSVData* pSVData = ImplGetSVData();
125 :
126 : // can't test this via Application::Yield since this
127 : // also processes all tasks directly via the scheduler.
128 4 : pSVData->maAppData.mnDispatchLevel++;
129 4 : pSVData->mpDefInst->Yield( true, false );
130 4 : pSVData->maAppData.mnDispatchLevel--;
131 : }
132 1 : CPPUNIT_ASSERT_MESSAGE("mainloop idle triggered", bTriggered);
133 1 : }
134 :
135 : // --------------------------------------------------------------------
136 :
137 4 : class TimerBool : public Timer
138 : {
139 : bool &mrBool;
140 : public:
141 4 : TimerBool( sal_uLong nMS, bool &rBool ) :
142 4 : Timer(), mrBool( rBool )
143 : {
144 4 : SetTimeout( nMS );
145 4 : Start();
146 4 : mrBool = false;
147 4 : }
148 4 : virtual void Invoke() SAL_OVERRIDE
149 : {
150 4 : mrBool = true;
151 4 : Application::EndYield();
152 4 : }
153 : };
154 :
155 1 : void TimerTest::testDurations()
156 : {
157 : static const sal_uLong aDurations[] = { 0, 1, 500, 1000 };
158 5 : for (size_t i = 0; i < SAL_N_ELEMENTS( aDurations ); i++)
159 : {
160 4 : bool bDone = false;
161 4 : TimerBool aTimer( aDurations[i], bDone );
162 : // coverity[loop_top] - Application::Yield allows the timer to fire and toggle bDone
163 19 : while( !bDone )
164 : {
165 11 : Application::Yield();
166 : }
167 4 : }
168 1 : }
169 :
170 : // --------------------------------------------------------------------
171 :
172 3 : class AutoTimerCount : public AutoTimer
173 : {
174 : sal_Int32 &mrCount;
175 : public:
176 3 : AutoTimerCount( sal_uLong nMS, sal_Int32 &rCount ) :
177 3 : AutoTimer(), mrCount( rCount )
178 : {
179 3 : SetTimeout( nMS );
180 3 : Start();
181 3 : mrCount = 0;
182 3 : }
183 374 : virtual void Invoke() SAL_OVERRIDE
184 : {
185 374 : mrCount++;
186 374 : }
187 : };
188 :
189 1 : void TimerTest::testAutoTimer()
190 : {
191 1 : sal_Int32 nCount = 0;
192 1 : AutoTimerCount aCount(1, nCount);
193 1071 : while (nCount < 100) {
194 1069 : Application::Yield();
195 1 : }
196 1 : }
197 :
198 : // --------------------------------------------------------------------
199 :
200 1 : class YieldTimer : public Timer
201 : {
202 : public:
203 1 : explicit YieldTimer( sal_uLong nMS ) : Timer()
204 : {
205 1 : SetTimeout( nMS );
206 1 : Start();
207 1 : }
208 1 : virtual void Invoke() SAL_OVERRIDE
209 : {
210 101 : for (int i = 0; i < 100; i++)
211 100 : Application::Yield();
212 1 : }
213 : };
214 :
215 1 : void TimerTest::testRecursiveTimer()
216 : {
217 1 : sal_Int32 nCount = 0;
218 1 : YieldTimer aCount(5);
219 2 : AutoTimerCount aCountUp( 3, nCount );
220 : // coverity[loop_top] - Application::Yield allows the timer to fire and increment nCount
221 5 : while (nCount < 20)
222 4 : Application::Yield();
223 1 : }
224 :
225 : // --------------------------------------------------------------------
226 :
227 1 : class SlowCallbackTimer : public Timer
228 : {
229 : bool &mbSlow;
230 : public:
231 1 : SlowCallbackTimer( sal_uLong nMS, bool &bBeenSlow ) :
232 1 : Timer(), mbSlow( bBeenSlow )
233 : {
234 1 : SetTimeout( nMS );
235 1 : Start();
236 1 : mbSlow = false;
237 1 : }
238 1 : virtual void Invoke() SAL_OVERRIDE
239 : {
240 : TimeValue aWait;
241 1 : aWait.Seconds = 1;
242 1 : aWait.Nanosec = 0;
243 1 : osl::Thread::wait( aWait );
244 1 : mbSlow = true;
245 1 : }
246 : };
247 :
248 1 : void TimerTest::testSlowTimerCallback()
249 : {
250 1 : bool bBeenSlow = false;
251 1 : sal_Int32 nCount = 0;
252 1 : AutoTimerCount aHighFreq(1, nCount);
253 2 : SlowCallbackTimer aSlow(250, bBeenSlow);
254 : // coverity[loop_top] - Application::Yield allows the timer to fire and toggle bBeenSlow
255 449 : while (!bBeenSlow)
256 447 : Application::Yield();
257 : // coverity[loop_top] - Application::Yield allows the timer to fire and increment nCount
258 2 : while (nCount < 200)
259 1 : Application::Yield();
260 1 : }
261 :
262 1 : CPPUNIT_TEST_SUITE_REGISTRATION(TimerTest);
263 :
264 4 : CPPUNIT_PLUGIN_IMPLEMENT();
265 :
266 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|