1 // Copyright (C) 2019-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7 #include <config.h>
8
9 #include <exceptions/exceptions.h>
10 #include <util/multi_threading_mgr.h>
11 #include <testutils/gtest_utils.h>
12
13 #include <gtest/gtest.h>
14
15 using namespace isc::util;
16 using namespace isc;
17
18 /// @brief Verifies that the default mode is false (MT disabled).
TEST(MultiThreadingMgrTest,defaultMode)19 TEST(MultiThreadingMgrTest, defaultMode) {
20 // MT should be disabled
21 EXPECT_FALSE(MultiThreadingMgr::instance().getMode());
22 }
23
24 /// @brief Verifies that the mode setter works.
TEST(MultiThreadingMgrTest,setMode)25 TEST(MultiThreadingMgrTest, setMode) {
26 // enable MT
27 EXPECT_NO_THROW(MultiThreadingMgr::instance().setMode(true));
28 // MT should be enabled
29 EXPECT_TRUE(MultiThreadingMgr::instance().getMode());
30 // disable MT
31 EXPECT_NO_THROW(MultiThreadingMgr::instance().setMode(false));
32 // MT should be disabled
33 EXPECT_FALSE(MultiThreadingMgr::instance().getMode());
34 }
35
36 /// @brief Verifies that accessing the thread pool works.
TEST(MultiThreadingMgrTest,threadPool)37 TEST(MultiThreadingMgrTest, threadPool) {
38 // get the thread pool
39 EXPECT_NO_THROW(MultiThreadingMgr::instance().getThreadPool());
40 }
41
42 /// @brief Verifies that the thread pool size setter works.
TEST(MultiThreadingMgrTest,threadPoolSize)43 TEST(MultiThreadingMgrTest, threadPoolSize) {
44 // default thread count is 0
45 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
46 // set thread count to 16
47 EXPECT_NO_THROW(MultiThreadingMgr::instance().setThreadPoolSize(16));
48 // thread count should be 16
49 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 16);
50 // set thread count to 0
51 EXPECT_NO_THROW(MultiThreadingMgr::instance().setThreadPoolSize(0));
52 // thread count should be 0
53 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
54 }
55
56 /// @brief Verifies that the packet queue size setter works.
TEST(MultiThreadingMgrTest,packetQueueSize)57 TEST(MultiThreadingMgrTest, packetQueueSize) {
58 // default queue size is 0
59 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
60 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPool().getMaxQueueSize(), 0);
61 // set queue size to 16
62 EXPECT_NO_THROW(MultiThreadingMgr::instance().setPacketQueueSize(16));
63 // queue size should be 16
64 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 16);
65 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPool().getMaxQueueSize(), 16);
66 // set queue size to 0
67 EXPECT_NO_THROW(MultiThreadingMgr::instance().setPacketQueueSize(0));
68 // queue size should be 0
69 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
70 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPool().getMaxQueueSize(), 0);
71 }
72
73 /// @brief Verifies that detecting thread count works.
TEST(MultiThreadingMgrTest,detectThreadCount)74 TEST(MultiThreadingMgrTest, detectThreadCount) {
75 // detecting thread count should work
76 EXPECT_NE(MultiThreadingMgr::detectThreadCount(), 0);
77 }
78
79 /// @brief Verifies that apply settings works.
TEST(MultiThreadingMgrTest,applyConfig)80 TEST(MultiThreadingMgrTest, applyConfig) {
81 // get the thread pool
82 auto& thread_pool = MultiThreadingMgr::instance().getThreadPool();
83 // MT should be disabled
84 EXPECT_FALSE(MultiThreadingMgr::instance().getMode());
85 // default thread count is 0
86 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
87 // thread pool should be stopped
88 EXPECT_EQ(thread_pool.size(), 0);
89 // enable MT with 16 threads and queue size 256
90 EXPECT_NO_THROW(MultiThreadingMgr::instance().apply(true, 16, 256));
91 // MT should be enabled
92 EXPECT_TRUE(MultiThreadingMgr::instance().getMode());
93 // thread count should be 16
94 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 16);
95 // queue size should be 256
96 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
97 // thread pool should be started
98 EXPECT_EQ(thread_pool.size(), 16);
99 // disable MT
100 EXPECT_NO_THROW(MultiThreadingMgr::instance().apply(false, 16, 256));
101 // MT should be disabled
102 EXPECT_FALSE(MultiThreadingMgr::instance().getMode());
103 // thread count should be 0
104 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
105 // queue size should be 0
106 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
107 // thread pool should be stopped
108 EXPECT_EQ(thread_pool.size(), 0);
109 // enable MT with auto scaling
110 EXPECT_NO_THROW(MultiThreadingMgr::instance().apply(true, 0, 0));
111 // MT should be enabled
112 EXPECT_TRUE(MultiThreadingMgr::instance().getMode());
113 // thread count should be detected automatically
114 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), MultiThreadingMgr::detectThreadCount());
115 // thread pool should be started
116 EXPECT_EQ(thread_pool.size(), MultiThreadingMgr::detectThreadCount());
117 // disable MT
118 EXPECT_NO_THROW(MultiThreadingMgr::instance().apply(false, 0, 0));
119 // MT should be disabled
120 EXPECT_FALSE(MultiThreadingMgr::instance().getMode());
121 // thread count should be 0
122 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
123 // thread pool should be stopped
124 EXPECT_EQ(thread_pool.size(), 0);
125 }
126
127 /// @brief Verifies that the critical section flag works.
TEST(MultiThreadingMgrTest,criticalSectionFlag)128 TEST(MultiThreadingMgrTest, criticalSectionFlag) {
129 // get the thread pool
130 auto& thread_pool = MultiThreadingMgr::instance().getThreadPool();
131 // MT should be disabled
132 EXPECT_FALSE(MultiThreadingMgr::instance().getMode());
133 // critical section should be disabled
134 EXPECT_FALSE(MultiThreadingMgr::instance().isInCriticalSection());
135 // thread count should be 0
136 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
137 // thread pool should be stopped
138 EXPECT_EQ(thread_pool.size(), 0);
139 // exit critical section
140 EXPECT_THROW(MultiThreadingMgr::instance().exitCriticalSection(), InvalidOperation);
141 // critical section should be disabled
142 EXPECT_FALSE(MultiThreadingMgr::instance().isInCriticalSection());
143 // enter critical section
144 EXPECT_NO_THROW(MultiThreadingMgr::instance().enterCriticalSection());
145 // critical section should be enabled
146 EXPECT_TRUE(MultiThreadingMgr::instance().isInCriticalSection());
147 // enable MT with 16 threads and queue size 256
148 EXPECT_NO_THROW(MultiThreadingMgr::instance().apply(true, 16, 256));
149 // MT should be enabled
150 EXPECT_TRUE(MultiThreadingMgr::instance().getMode());
151 // thread count should be 16
152 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 16);
153 // queue size should be 256
154 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
155 // thread pool should be stopped
156 EXPECT_EQ(thread_pool.size(), 0);
157 // exit critical section
158 EXPECT_NO_THROW(MultiThreadingMgr::instance().exitCriticalSection());
159 // critical section should be disabled
160 EXPECT_FALSE(MultiThreadingMgr::instance().isInCriticalSection());
161 // exit critical section
162 EXPECT_THROW(MultiThreadingMgr::instance().exitCriticalSection(), InvalidOperation);
163 // critical section should be disabled
164 EXPECT_FALSE(MultiThreadingMgr::instance().isInCriticalSection());
165 // disable MT
166 EXPECT_NO_THROW(MultiThreadingMgr::instance().apply(false, 0, 0));
167 // MT should be disabled
168 EXPECT_FALSE(MultiThreadingMgr::instance().getMode());
169 // thread count should be 0
170 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
171 // queue size should be 0
172 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
173 // thread pool should be stopped
174 EXPECT_EQ(thread_pool.size(), 0);
175 }
176
177 /// @brief Verifies that the critical section works.
TEST(MultiThreadingMgrTest,criticalSection)178 TEST(MultiThreadingMgrTest, criticalSection) {
179 // get the thread pool instance
180 auto& thread_pool = MultiThreadingMgr::instance().getThreadPool();
181 // thread pool should be stopped
182 EXPECT_EQ(thread_pool.size(), 0);
183 // apply multi-threading configuration with 16 threads and queue size 256
184 MultiThreadingMgr::instance().apply(true, 16, 256);
185 // thread count should match
186 EXPECT_EQ(thread_pool.size(), 16);
187 // thread count should be 16
188 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 16);
189 // queue size should be 256
190 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
191 // use scope to test constructor and destructor
192 {
193 MultiThreadingCriticalSection cs;
194 // thread pool should be stopped
195 EXPECT_EQ(thread_pool.size(), 0);
196 // thread count should be 16
197 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 16);
198 // queue size should be 256
199 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
200 // use scope to test constructor and destructor
201 {
202 MultiThreadingCriticalSection inner_cs;
203 // thread pool should be stopped
204 EXPECT_EQ(thread_pool.size(), 0);
205 // thread count should be 16
206 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 16);
207 // queue size should be 256
208 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
209 }
210 // thread pool should be stopped
211 EXPECT_EQ(thread_pool.size(), 0);
212 // thread count should be 16
213 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 16);
214 // queue size should be 256
215 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
216 }
217 // thread count should match
218 EXPECT_EQ(thread_pool.size(), 16);
219 // thread count should be 16
220 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 16);
221 // queue size should be 256
222 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
223 // use scope to test constructor and destructor
224 {
225 MultiThreadingCriticalSection cs;
226 // thread pool should be stopped
227 EXPECT_EQ(thread_pool.size(), 0);
228 // thread count should be 16
229 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 16);
230 // queue size should be 256
231 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
232 // apply multi-threading configuration with 64 threads and queue size 4
233 MultiThreadingMgr::instance().apply(true, 64, 4);
234 // thread pool should be stopped
235 EXPECT_EQ(thread_pool.size(), 0);
236 // thread count should be 64
237 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 64);
238 // queue size should be 4
239 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 4);
240 }
241 // thread count should match
242 EXPECT_EQ(thread_pool.size(), 64);
243 // thread count should be 64
244 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 64);
245 // queue size should be 4
246 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 4);
247 // use scope to test constructor and destructor
248 {
249 MultiThreadingCriticalSection cs;
250 // thread pool should be stopped
251 EXPECT_EQ(thread_pool.size(), 0);
252 // thread count should be 64
253 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 64);
254 // queue size should be 4
255 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 4);
256 // apply multi-threading configuration with 0 threads
257 MultiThreadingMgr::instance().apply(false, 64, 256);
258 // thread pool should be stopped
259 EXPECT_EQ(thread_pool.size(), 0);
260 // thread count should be 0
261 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
262 // queue size should be 0
263 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
264 }
265 // thread count should match
266 EXPECT_EQ(thread_pool.size(), 0);
267 // thread count should be 0
268 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
269 // queue size should be 0
270 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
271 // use scope to test constructor and destructor
272 {
273 MultiThreadingCriticalSection cs;
274 // thread pool should be stopped
275 EXPECT_EQ(thread_pool.size(), 0);
276 // thread count should be 0
277 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
278 // queue size should be 0
279 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
280 // use scope to test constructor and destructor
281 {
282 MultiThreadingCriticalSection inner_cs;
283 // thread pool should be stopped
284 EXPECT_EQ(thread_pool.size(), 0);
285 // thread count should be 0
286 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
287 // queue size should be 0
288 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
289 }
290 // thread pool should be stopped
291 EXPECT_EQ(thread_pool.size(), 0);
292 // thread count should be 0
293 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
294 // queue size should be 0
295 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
296 }
297 // thread count should match
298 EXPECT_EQ(thread_pool.size(), 0);
299 // thread count should be 0
300 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
301 // queue size should be 0
302 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 0);
303 // use scope to test constructor and destructor
304 {
305 MultiThreadingCriticalSection cs;
306 // thread pool should be stopped
307 EXPECT_EQ(thread_pool.size(), 0);
308 // apply multi-threading configuration with 64 threads
309 MultiThreadingMgr::instance().apply(true, 64, 256);
310 // thread pool should be stopped
311 EXPECT_EQ(thread_pool.size(), 0);
312 // thread count should be 64
313 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 64);
314 // queue size should be 256
315 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
316 }
317 // thread count should match
318 EXPECT_EQ(thread_pool.size(), 64);
319 // thread count should be 64
320 EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 64);
321 // queue size should be 256
322 EXPECT_EQ(MultiThreadingMgr::instance().getPacketQueueSize(), 256);
323 // apply multi-threading configuration with 0 threads
324 MultiThreadingMgr::instance().apply(false, 0, 0);
325 }
326
327 /// @brief Test fixture for exercised CriticalSection callbacks.
328 class CriticalSectionCallbackTest : public ::testing::Test {
329 public:
330 /// @brief Constructor.
CriticalSectionCallbackTest()331 CriticalSectionCallbackTest() {
332 MultiThreadingMgr::instance().apply(false, 0, 0);
333 }
334
335 /// @brief Destructor.
~CriticalSectionCallbackTest()336 ~CriticalSectionCallbackTest() {
337 MultiThreadingMgr::instance().apply(false, 0, 0);
338 }
339
340 /// @brief A callback that adds the value 1 to invocations lists.
one()341 void one() {
342 invocations_.push_back(1);
343 }
344
345 /// @brief A callback that adds the value 2 to invocations lists.
two()346 void two() {
347 invocations_.push_back(2);
348 }
349
350 /// @brief A callback that adds the value 3 to invocations lists.
three()351 void three() {
352 invocations_.push_back(3);
353 }
354
355 /// @brief A callback that adds the value 4 to invocations lists.
four()356 void four() {
357 invocations_.push_back(4);
358 }
359
360 /// @brief A callback that throws @ref isc::Exception which is ignored.
ignoredException()361 void ignoredException() {
362 isc_throw(isc::Exception, "ignored");
363 }
364
365 /// @brief A callback that throws @ref isc::MultiThreadingInvalidOperation
366 /// which is propagated to the scope of the
367 /// @ref MultiThreadingCriticalSection constructor.
observedException()368 void observedException() {
369 isc_throw(isc::MultiThreadingInvalidOperation, "observed");
370 }
371
372 /// @brief Indicates whether or not the DHCP thread pool is running.
373 ///
374 /// @return True if the pool is running, false otherwise.
isThreadPoolRunning()375 bool isThreadPoolRunning() {
376 return (MultiThreadingMgr::instance().getThreadPool().size());
377 }
378
379 /// @brief Checks callback invocations over a series of nested
380 /// CriticalSections.
381 ///
382 /// @param entries A vector of the invocation values that should
383 /// be present after entry into the outermost CriticalSection. The
384 /// expected values should be in the order the callbacks were added
385 /// to the MultiThreadingMgr's list of callbacks.
386 /// @param exits A vector of the invocation values that should
387 /// be present after exiting the outermost CriticalSection. The
388 /// expected values should be in the order the callbacks were added
389 /// to the MultiThreadingMgr's list of callbacks.
390 /// @param should_throw The flag indicating if the CriticalSection should
391 /// throw, simulating a dead-lock scenario when a processing thread tries
392 /// to stop the thread pool.
runCriticalSections(std::vector<int> entries,std::vector<int> exits,bool should_throw=false)393 void runCriticalSections(std::vector<int> entries, std::vector<int>exits,
394 bool should_throw = false) {
395 // Pool must be running.
396 ASSERT_TRUE(isThreadPoolRunning());
397
398 // Clear the invocations list.
399 invocations_.clear();
400
401 // Use scope to create nested CriticalSections.
402 if (!should_throw) {
403 // Enter a critical section.
404 MultiThreadingCriticalSection cs;
405
406 // Thread pool should be stopped.
407 ASSERT_FALSE(isThreadPoolRunning());
408
409 if (entries.size()) {
410 // We expect entry invocations.
411 ASSERT_EQ(invocations_.size(), entries.size());
412 ASSERT_EQ(invocations_, entries);
413 } else {
414 // We do not expect entry invocations.
415 ASSERT_FALSE(invocations_.size());
416 }
417
418 // Clear the invocations list.
419 invocations_.clear();
420
421 {
422 // Enter another CriticalSection.
423 MultiThreadingCriticalSection inner_cs;
424
425 // Thread pool should still be stopped.
426 ASSERT_FALSE(isThreadPoolRunning());
427
428 // We should not have had any callback invocations.
429 ASSERT_FALSE(invocations_.size());
430 }
431
432 // After exiting inner section, the thread pool should
433 // still be stopped.
434 ASSERT_FALSE(isThreadPoolRunning());
435
436 // We should not have had more callback invocations.
437 ASSERT_FALSE(invocations_.size());
438 } else {
439 ASSERT_THROW(MultiThreadingCriticalSection cs, MultiThreadingInvalidOperation);
440
441 if (entries.size()) {
442 // We expect entry invocations.
443 ASSERT_EQ(invocations_.size(), entries.size());
444 ASSERT_EQ(invocations_, entries);
445 } else {
446 // We do not expect entry invocations.
447 ASSERT_FALSE(invocations_.size());
448 }
449
450 // Clear the invocations list.
451 invocations_.clear();
452 }
453
454 // After exiting the outer section, the thread pool should
455 // match the thread count.
456 ASSERT_TRUE(isThreadPoolRunning());
457
458 if (exits.size()) {
459 // We expect exit invocations.
460 ASSERT_EQ(invocations_, exits);
461 } else {
462 // We do not expect exit invocations.
463 ASSERT_FALSE(invocations_.size());
464 }
465 }
466
467 /// @brief A list of values set by callback invocations.
468 std::vector<int> invocations_;
469 };
470
471 /// @brief Verifies critical section callback maintenance:
472 /// catch invalid pairs, add pairs, remove pairs.
TEST_F(CriticalSectionCallbackTest,addAndRemove)473 TEST_F(CriticalSectionCallbackTest, addAndRemove) {
474 auto& mgr = MultiThreadingMgr::instance();
475
476 // Cannot add with a blank name.
477 ASSERT_THROW_MSG(mgr.addCriticalSectionCallbacks("", [](){}, [](){}, [](){}),
478 BadValue, "CSCallbackSetList - name cannot be empty");
479
480 // Cannot add with an empty check callback.
481 ASSERT_THROW_MSG(mgr.addCriticalSectionCallbacks("bad", nullptr, [](){}, [](){}),
482 BadValue, "CSCallbackSetList - check callback for bad cannot be empty");
483
484 // Cannot add with an empty exit callback.
485 ASSERT_THROW_MSG(mgr.addCriticalSectionCallbacks("bad", [](){}, nullptr, [](){}),
486 BadValue, "CSCallbackSetList - entry callback for bad cannot be empty");
487
488 // Cannot add with an empty exit callback.
489 ASSERT_THROW_MSG(mgr.addCriticalSectionCallbacks("bad", [](){}, [](){}, nullptr),
490 BadValue, "CSCallbackSetList - exit callback for bad cannot be empty");
491
492 // Should be able to add foo.
493 ASSERT_NO_THROW_LOG(mgr.addCriticalSectionCallbacks("foo", [](){}, [](){}, [](){}));
494
495 // Should not be able to add foo twice.
496 ASSERT_THROW_MSG(mgr.addCriticalSectionCallbacks("foo", [](){}, [](){}, [](){}),
497 BadValue, "CSCallbackSetList - callbacks for foo already exist");
498
499 // Should be able to add bar.
500 ASSERT_NO_THROW_LOG(mgr.addCriticalSectionCallbacks("bar", [](){}, [](){}, [](){}));
501
502 // Should be able to remove foo.
503 ASSERT_NO_THROW_LOG(mgr.removeCriticalSectionCallbacks("foo"));
504
505 // Should be able to remove foo twice without issue.
506 ASSERT_NO_THROW_LOG(mgr.removeCriticalSectionCallbacks("foo"));
507
508 // Should be able to remove all without issue.
509 ASSERT_NO_THROW_LOG(mgr.removeAllCriticalSectionCallbacks());
510 }
511
512 /// @brief Verifies that the critical section callbacks work.
TEST_F(CriticalSectionCallbackTest,invocations)513 TEST_F(CriticalSectionCallbackTest, invocations) {
514 // get the thread pool instance
515 auto& thread_pool = MultiThreadingMgr::instance().getThreadPool();
516 // thread pool should be stopped
517 EXPECT_EQ(thread_pool.size(), 0);
518
519 // Add two sets of CriticalSection call backs.
520 MultiThreadingMgr::instance().addCriticalSectionCallbacks("oneAndTwo",
521 std::bind(&CriticalSectionCallbackTest::ignoredException, this),
522 std::bind(&CriticalSectionCallbackTest::one, this),
523 std::bind(&CriticalSectionCallbackTest::two, this));
524
525 MultiThreadingMgr::instance().addCriticalSectionCallbacks("threeAndFour",
526 std::bind(&CriticalSectionCallbackTest::ignoredException, this),
527 std::bind(&CriticalSectionCallbackTest::three, this),
528 std::bind(&CriticalSectionCallbackTest::four, this));
529
530 // Apply multi-threading configuration with 16 threads and queue size 256.
531 MultiThreadingMgr::instance().apply(true, 16, 256);
532
533 // Make three passes over nested CriticalSections to ensure
534 // callbacks execute at the appropriate times and we can do
535 // so repeatedly.
536 for (int i = 0; i < 3; ++i) {
537 runCriticalSections({1 ,3}, {4, 2});
538 }
539
540 // Now remove the first set of callbacks.
541 MultiThreadingMgr::instance().removeCriticalSectionCallbacks("oneAndTwo");
542
543 // Retest CriticalSections.
544 runCriticalSections({3}, {4});
545
546 // Now remove the remaining callbacks.
547 MultiThreadingMgr::instance().removeAllCriticalSectionCallbacks();
548
549 // Retest CriticalSections.
550 runCriticalSections({}, {});
551 }
552
553 /// @brief Verifies that the critical section callbacks work.
TEST_F(CriticalSectionCallbackTest,invocationsWithExceptions)554 TEST_F(CriticalSectionCallbackTest, invocationsWithExceptions) {
555 // get the thread pool instance
556 auto& thread_pool = MultiThreadingMgr::instance().getThreadPool();
557 // thread pool should be stopped
558 EXPECT_EQ(thread_pool.size(), 0);
559
560 // Apply multi-threading configuration with 16 threads and queue size 256.
561 MultiThreadingMgr::instance().apply(true, 16, 256);
562
563 // Add two sets of CriticalSection call backs.
564 MultiThreadingMgr::instance().addCriticalSectionCallbacks("observed",
565 std::bind(&CriticalSectionCallbackTest::observedException, this),
566 std::bind(&CriticalSectionCallbackTest::one, this),
567 std::bind(&CriticalSectionCallbackTest::two, this));
568
569 MultiThreadingMgr::instance().addCriticalSectionCallbacks("ignored",
570 std::bind(&CriticalSectionCallbackTest::ignoredException, this),
571 std::bind(&CriticalSectionCallbackTest::three, this),
572 std::bind(&CriticalSectionCallbackTest::four, this));
573
574 // Make three passes over nested CriticalSections to ensure
575 // callbacks execute at the appropriate times and we can do
576 // so repeatedly.
577 for (int i = 0; i < 3; ++i) {
578 runCriticalSections({}, {}, true);
579 }
580
581 // Now remove the first set of callbacks.
582 MultiThreadingMgr::instance().removeCriticalSectionCallbacks("observed");
583
584 // Retest CriticalSections.
585 runCriticalSections({3}, {4});
586
587 // Now remove the remaining callbacks.
588 MultiThreadingMgr::instance().removeAllCriticalSectionCallbacks();
589
590 // Retest CriticalSections.
591 runCriticalSections({}, {});
592 }
593