]> git.ipfire.org Git - thirdparty/squid.git/blob - src/tests/testEventLoop.cc
Import reconfigure cachemgr action from NT Devel branch
[thirdparty/squid.git] / src / tests / testEventLoop.cc
1 #if 0
2 #include "squid.h"
3 #endif
4
5 #include <cppunit/TestAssert.h>
6
7 #include "testEventLoop.h"
8 #include "EventLoop.h"
9 #include "Mem.h"
10
11 #if 0
12 #include "AsyncEngine.h"
13 #include "AsyncCallQueue.h"
14 #include "event.h"
15 #endif
16
17 CPPUNIT_TEST_SUITE_REGISTRATION( testEventLoop );
18
19 /* stub functions to link successfully */
20 void
21 shut_down(int)
22 {}
23
24 void
25 reconfigure(int)
26 {}
27
28 /* end stubs */
29
30 /* init legacy static-initialized modules */
31
32 void
33 testEventLoop::setUp()
34 {
35 Mem::Init();
36 statInit();
37 }
38
39 /*
40 * Test creating a EventLoop
41 */
42 void
43 testEventLoop::testCreate()
44 {
45 EventLoop();
46 }
47
48 #if POLISHED_MAIN_LOOP
49
50 /*
51 * Running the loop once is useful for integration with other loops, such as
52 * migrating to it in incrementally.
53 *
54 * This test works by having a custom dispatcher and engine which record how
55 * many times they are called.
56 */
57
58 class RecordDispatcher : public CompletionDispatcher
59 {
60
61 public:
62 int calls;
63 RecordDispatcher(): calls(0)
64 {}
65
66 bool dispatch()
67 {
68 ++calls;
69 /* claim we dispatched calls to be useful for the testStopOnIdle test.
70 */
71 return true;
72 }
73 };
74
75 #endif /* POLISHED_MAIN_LOOP */
76
77 class RecordingEngine : public AsyncEngine
78 {
79
80 public:
81 int calls;
82 int lasttimeout;
83 int return_timeout;
84 RecordingEngine(int return_timeout=0): calls(0), lasttimeout(0),
85 return_timeout(return_timeout)
86 {}
87
88 virtual int checkEvents(int timeout)
89 {
90 ++calls;
91 lasttimeout = timeout;
92 return return_timeout;
93 }
94 };
95
96 #if POLISHED_MAIN_LOOP
97
98 void
99 testEventLoop::testRunOnce()
100 {
101 EventLoop theLoop;
102 RecordDispatcher dispatcher;
103 theLoop.registerDispatcher(&dispatcher);
104 RecordingEngine engine;
105 theLoop.registerEngine(&engine);
106 theLoop.runOnce();
107 CPPUNIT_ASSERT_EQUAL(1, dispatcher.calls);
108 CPPUNIT_ASSERT_EQUAL(1, engine.calls);
109 }
110
111 /*
112 * completion dispatchers registered with the event loop are invoked by the
113 * event loop.
114 *
115 * This test works by having a customer dispatcher which shuts the loop down
116 * once its been invoked twice.
117 *
118 * It also tests that loop.run() and loop.stop() work, because if they dont
119 * work, this test will either hang, or fail.
120 */
121
122 class ShutdownDispatcher : public CompletionDispatcher
123 {
124
125 public:
126 EventLoop &theLoop;
127 int calls;
128 ShutdownDispatcher(EventLoop & theLoop):theLoop(theLoop), calls(0)
129 {}
130
131 bool dispatch()
132 {
133 if (++calls == 2)
134 theLoop.stop();
135
136 return true;
137 }
138 };
139
140 void
141 testEventLoop::testRegisterDispatcher()
142 {
143 EventLoop theLoop;
144 ShutdownDispatcher testDispatcher(theLoop);
145 theLoop.registerDispatcher(&testDispatcher);
146 theLoop.run();
147 /* we should get two calls because the test dispatched returns true from
148 * dispatch(), and calls stop on the second call.
149 */
150 CPPUNIT_ASSERT_EQUAL(2, testDispatcher.calls);
151 }
152
153 /* test that a registered async engine is invoked on each loop run
154 * we do this with an intstrumented async engine.
155 */
156 void
157 testEventLoop::testRegisterEngine()
158 {
159 EventLoop theLoop;
160 ShutdownDispatcher testDispatcher(theLoop);
161 theLoop.registerDispatcher(&testDispatcher);
162 RecordingEngine testEngine;
163 theLoop.registerEngine(&testEngine);
164 theLoop.run();
165 CPPUNIT_ASSERT_EQUAL(2, testEngine.calls);
166 }
167
168 /* each AsyncEngine needs to be given a timeout. We want one engine in each
169 * loop to be given the timeout value - and the rest to have a timeout of 0.
170 * The last registered engine should be given this timeout, which will mean
171 * that we dont block in the loop until the last engine. This will allow for
172 * dynamic introduction and removal of engines, as long as the last engine
173 * is one which can do a os call rather than busy waiting.
174 *
175 * So - we want the timeout hints returned from the earlier engines to be
176 * tracked, and the lowest non-negative value given to the last engine.
177 */
178 void
179 testEventLoop::testEngineTimeout()
180 {
181 EventLoop theLoop;
182 RecordingEngine engineOne(5);
183 RecordingEngine engineTwo;
184 theLoop.registerEngine(&engineOne);
185 theLoop.registerEngine(&engineTwo);
186 theLoop.runOnce();
187 CPPUNIT_ASSERT_EQUAL(0, engineOne.lasttimeout);
188 CPPUNIT_ASSERT_EQUAL(5, engineTwo.lasttimeout);
189 }
190
191 /* An event loop with all idle engines, and nothing dispatched in a run should
192 * automatically quit. The runOnce call should return True when the loop is
193 * entirely idle to make it easy for people running the loop by hand.
194 */
195 void
196 testEventLoop::testStopOnIdle()
197 {
198 EventLoop theLoop;
199 /* trivial case - no dispatchers or engines, should quit immediately */
200 CPPUNIT_ASSERT_EQUAL(true, theLoop.runOnce());
201 theLoop.run();
202 /* add a dispatcher with nothing to dispatch - use an EventDispatcher as its
203 * sufficient and handy
204 */
205 EventDispatcher dispatcher;
206 theLoop.registerDispatcher(&dispatcher);
207 CPPUNIT_ASSERT_EQUAL(true, theLoop.runOnce());
208 theLoop.run();
209 /* add an engine which is idle.
210 */
211 RecordingEngine engine(AsyncEngine::EVENT_IDLE);
212 theLoop.registerEngine(&engine);
213 CPPUNIT_ASSERT_EQUAL(true, theLoop.runOnce());
214 CPPUNIT_ASSERT_EQUAL(1, engine.calls);
215 theLoop.run();
216 CPPUNIT_ASSERT_EQUAL(2, engine.calls);
217 /* add an engine which is suffering errors. This should result in 10
218 * loops until the loop stops - because thats the error retry amount
219 */
220 RecordingEngine failing_engine(AsyncEngine::EVENT_ERROR);
221 theLoop.registerEngine(&failing_engine);
222 CPPUNIT_ASSERT_EQUAL(false, theLoop.runOnce());
223 CPPUNIT_ASSERT_EQUAL(1, failing_engine.calls);
224 theLoop.run();
225 /* run resets the error count ... */
226 CPPUNIT_ASSERT_EQUAL(11, failing_engine.calls);
227
228 /* an engine that asks for a timeout should not be detected as idle:
229 * use runOnce which should return false
230 */
231 theLoop = EventLoop();
232 RecordingEngine non_idle_engine(1000);
233 theLoop.registerEngine(&non_idle_engine);
234 CPPUNIT_ASSERT_EQUAL(false, theLoop.runOnce());
235 }
236
237 #endif /* POLISHED_MAIN_LOOP */
238
239 /* An event loop has a time service which is like an async engine but never
240 * generates events and there can only be one such service.
241 */
242
243 class StubTime : public TimeEngine
244 {
245
246 public:
247 StubTime() : calls(0) {}
248
249 int calls;
250 void tick()
251 {
252 ++calls;
253 }
254 };
255
256 void
257 testEventLoop::testSetTimeService()
258 {
259 EventLoop theLoop;
260 StubTime myTime;
261 /* the loop will not error without a time service */
262 theLoop.runOnce();
263 /* we can set the time service */
264 theLoop.setTimeService(&myTime);
265 /* it invokes our tick() call */
266 theLoop.runOnce();
267 CPPUNIT_ASSERT_EQUAL(1, myTime.calls);
268 /* it invokes our tick() call again */
269 theLoop.runOnce();
270 CPPUNIT_ASSERT_EQUAL(2, myTime.calls);
271 }
272
273 /* one async engine is the primary engine - the engine that is allowed to block.
274 * this defaults to the last added one, but can be explicitly nominated
275 */
276 void
277 testEventLoop::testSetPrimaryEngine()
278 {
279 EventLoop theLoop;
280 RecordingEngine first_engine(10);
281 RecordingEngine second_engine(10);
282 /* one engine - gets a timeout */
283 theLoop.registerEngine(&first_engine);
284 theLoop.runOnce();
285 CPPUNIT_ASSERT_EQUAL(EVENT_LOOP_TIMEOUT, first_engine.lasttimeout);
286 /* two engines - the second gets the timeout */
287 theLoop.registerEngine(&second_engine);
288 theLoop.runOnce();
289 CPPUNIT_ASSERT_EQUAL(0, first_engine.lasttimeout);
290 CPPUNIT_ASSERT_EQUAL(10, second_engine.lasttimeout);
291 /* set the first engine to be primary explicitly and now gets the timeout */
292 theLoop.setPrimaryEngine(&first_engine);
293 theLoop.runOnce();
294 CPPUNIT_ASSERT_EQUAL(10, first_engine.lasttimeout);
295 CPPUNIT_ASSERT_EQUAL(0, second_engine.lasttimeout);
296 }