testEventLoop.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #include "squid.h"
10 #include "AsyncEngine.h"
11 #include "EventLoop.h"
12 #include "tests/testEventLoop.h"
13 #include "time/Engine.h"
14 #include "unitTestMain.h"
15 
16 #include <cppunit/TestAssert.h>
17 
19 
20 void
22 {
23  EventLoop();
24 }
25 
27 {
28 public:
29  RecordingEngine(int aTimeout = 0) : return_timeout(aTimeout) {}
30 
31  virtual int checkEvents(int timeout) {
32  ++calls;
33  lasttimeout = timeout;
34  return return_timeout;
35  }
36 
37  int calls = 0;
38  int lasttimeout = 0;
39  int return_timeout = 0;
40 };
41 
42 /* test that a registered async engine is invoked on each loop run
43  * we do this with an instrumented async engine.
44  */
45 void
47 {
48  {
49  /* trivial case - no engine, should quit immediately */
50  EventLoop theLoop;
51  CPPUNIT_ASSERT_EQUAL(true, theLoop.runOnce());
52  }
53 
54  {
55  /* An event loop with all idle engines, and nothing dispatched in a run should
56  * automatically quit. The runOnce call should return True when the loop is
57  * entirely idle to make it easy for people running the loop by hand.
58  */
59  EventLoop theLoop;
61  theLoop.registerEngine(&engine);
62  CPPUNIT_ASSERT_EQUAL(true, theLoop.runOnce());
63  CPPUNIT_ASSERT_EQUAL(1, engine.calls);
64  theLoop.run();
65  CPPUNIT_ASSERT_EQUAL(2, engine.calls);
66  }
67 
68  {
69  /* an engine that asks for a timeout should not be detected as idle:
70  * use runOnce which should return false
71  */
72  EventLoop theLoop;
73  RecordingEngine engine;
74  theLoop.registerEngine(&engine);
75  CPPUNIT_ASSERT_EQUAL(false, theLoop.runOnce());
76  CPPUNIT_ASSERT_EQUAL(1, engine.calls);
77  CPPUNIT_ASSERT_EQUAL(EVENT_LOOP_TIMEOUT, engine.lasttimeout);
78  }
79 }
80 
81 /* each AsyncEngine needs to be given a timeout. We want one engine in each
82  * loop to be given the timeout value - and the rest to have a timeout of 0.
83  * The last registered engine should be given this timeout, which will mean
84  * that we do not block in the loop until the last engine. This will allow for
85  * dynamic introduction and removal of engines, as long as the last engine
86  * is one which can do a os call rather than busy waiting.
87  *
88  * So - we want the timeout hints returned from the earlier engines to be
89  * tracked, and the lowest non-negative value given to the last engine.
90  */
91 void
93 {
94  EventLoop theLoop;
95  RecordingEngine engineOne(5);
96  RecordingEngine engineTwo;
97  theLoop.registerEngine(&engineOne);
98  theLoop.registerEngine(&engineTwo);
99  theLoop.runOnce();
100  CPPUNIT_ASSERT_EQUAL(1, engineOne.calls);
101  CPPUNIT_ASSERT_EQUAL(0, engineOne.lasttimeout);
102  CPPUNIT_ASSERT_EQUAL(1, engineTwo.calls);
103  CPPUNIT_ASSERT_EQUAL(5, engineTwo.lasttimeout);
104 }
105 
106 /* An engine which is suffering errors. This should result in 10
107  * loops until the loop stops - because that's the error retry amount
108  * hard-coded into EventLoop::runOnce()
109  */
110 void
112 {
113  EventLoop theLoop;
115  theLoop.registerEngine(&failing_engine);
116  CPPUNIT_ASSERT_EQUAL(false, theLoop.runOnce());
117  CPPUNIT_ASSERT_EQUAL(1, failing_engine.calls);
118  CPPUNIT_ASSERT_EQUAL(1, theLoop.errcount);
119  theLoop.run();
120  /* run resets the error count ... */
121  CPPUNIT_ASSERT_EQUAL(10, theLoop.errcount);
122  CPPUNIT_ASSERT_EQUAL(11, failing_engine.calls);
123 }
124 
125 /* An event loop has a time service which is like an async engine but never
126  * generates events and there can only be one such service.
127  */
128 class StubTime : public Time::Engine
129 {
130 public:
131  StubTime() : calls(0) {}
132 
133  int calls;
134  void tick() {
135  ++calls;
136  }
137 };
138 
139 void
141 {
142  EventLoop theLoop;
143  StubTime myTime;
144  /* the loop will not error without a time service */
145  theLoop.runOnce();
146  /* we can set the time service */
147  theLoop.setTimeService(&myTime);
148  /* it invokes our tick() call */
149  theLoop.runOnce();
150  CPPUNIT_ASSERT_EQUAL(1, myTime.calls);
151  /* it invokes our tick() call again */
152  theLoop.runOnce();
153  CPPUNIT_ASSERT_EQUAL(2, myTime.calls);
154 }
155 
156 /* one async engine is the primary engine - the engine that is allowed to block.
157  * this defaults to the last added one, but can be explicitly nominated
158  */
159 void
161 {
162  EventLoop theLoop;
163  RecordingEngine first_engine(10);
164  RecordingEngine second_engine(10);
165  /* one engine - gets a timeout */
166  theLoop.registerEngine(&first_engine);
167  theLoop.runOnce();
168  CPPUNIT_ASSERT_EQUAL(EVENT_LOOP_TIMEOUT, first_engine.lasttimeout);
169  /* two engines - the second gets the timeout */
170  theLoop.registerEngine(&second_engine);
171  theLoop.runOnce();
172  CPPUNIT_ASSERT_EQUAL(0, first_engine.lasttimeout);
173  CPPUNIT_ASSERT_EQUAL(10, second_engine.lasttimeout);
174  /* set the first engine to be primary explicitly and now gets the timeout */
175  theLoop.setPrimaryEngine(&first_engine);
176  theLoop.runOnce();
177  CPPUNIT_ASSERT_EQUAL(10, first_engine.lasttimeout);
178  CPPUNIT_ASSERT_EQUAL(0, second_engine.lasttimeout);
179 }
180 
event class for doing synthetic time etc
Definition: Engine.h:16
CPPUNIT_TEST_SUITE_REGISTRATION(testEventLoop)
void run()
Definition: EventLoop.cc:76
virtual int checkEvents(int timeout)
void testEngineTimeout()
void testRunOnce()
void testSetTimeService()
RecordingEngine(int aTimeout=0)
bool runOnce()
Definition: EventLoop.cc:89
void testEngineErrors()
int errcount
Definition: EventLoop.h:69
void setTimeService(Time::Engine *)
Definition: EventLoop.cc:162
#define EVENT_LOOP_TIMEOUT
Definition: EventLoop.h:16
void setPrimaryEngine(AsyncEngine *engine)
Definition: EventLoop.cc:149
void registerEngine(AsyncEngine *engine)
Definition: EventLoop.cc:70
void testSetPrimaryEngine()
void tick()

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors