Line data Source code
1 : /**
2 : *
3 : * @file WorkerThread_test.cxx WorkerThread class Unit Tests
4 : *
5 : * This is part of the DUNE DAQ Application Framework, copyright 2020.
6 : * Licensing/copyright details are in the COPYING file that you should have
7 : * received with this code.
8 : */
9 :
10 : #include "utilities/WorkerThread.hpp"
11 : #include "utilities/Issues.hpp"
12 :
13 : #define BOOST_TEST_MODULE WorkerThread_test // NOLINT
14 :
15 : #include "boost/asio/signal_set.hpp"
16 : #include "boost/test/unit_test.hpp"
17 :
18 : #include <chrono>
19 : #include <memory>
20 : #include <string>
21 :
22 : namespace {
23 :
24 : void
25 3 : do_something(std::atomic<bool>&)
26 : {
27 3 : int num_seconds = 5;
28 3 : BOOST_TEST_MESSAGE("This function will just sleep for " << num_seconds << " second(s) and then return");
29 3 : std::this_thread::sleep_for(std::chrono::seconds(num_seconds));
30 3 : }
31 :
32 : std::string test_thread_name;
33 : std::string actual_thread_name;
34 :
35 : void
36 2 : print_name(std::atomic<bool>&)
37 : {
38 : // Give WorkerThread time to set the name
39 2 : std::this_thread::sleep_for(std::chrono::milliseconds(1));
40 :
41 2 : char buffer[16]; // NOLINT
42 2 : int res = pthread_getname_np(pthread_self(), buffer, 16);
43 2 : BOOST_REQUIRE_EQUAL(res, 0);
44 2 : actual_thread_name = std::string(buffer);
45 2 : BOOST_TEST_MESSAGE("This function prints the current thread name, which is " + actual_thread_name);
46 2 : }
47 :
48 : } // namespace ""
49 :
50 2 : BOOST_AUTO_TEST_CASE(sanity_checks)
51 : {
52 :
53 1 : std::unique_ptr<dunedaq::utilities::WorkerThread> umth_ptr = nullptr;
54 :
55 1 : auto starttime = std::chrono::steady_clock::now();
56 1 : BOOST_REQUIRE_NO_THROW(umth_ptr = std::make_unique<dunedaq::utilities::WorkerThread>(do_something));
57 1 : auto construction_time_in_ms =
58 1 : std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - starttime).count();
59 1 : BOOST_TEST_MESSAGE("Construction time was " << construction_time_in_ms << " ms");
60 :
61 1 : starttime = std::chrono::steady_clock::now();
62 1 : BOOST_REQUIRE_NO_THROW(umth_ptr->start_working_thread());
63 1 : auto start_time_in_ms =
64 1 : std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - starttime).count();
65 1 : BOOST_TEST_MESSAGE("Time to call WorkerThread::start_working_thread() was " << start_time_in_ms << " ms");
66 :
67 1 : starttime = std::chrono::steady_clock::now();
68 1 : BOOST_REQUIRE_NO_THROW(umth_ptr->stop_working_thread());
69 1 : auto stop_time_in_ms =
70 1 : std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - starttime).count();
71 1 : BOOST_TEST_MESSAGE("Time to call WorkerThread::stop_working_thread() was " << stop_time_in_ms << " ms");
72 1 : }
73 :
74 2 : BOOST_AUTO_TEST_CASE(inappropriate_transitions, *boost::unit_test::depends_on("sanity_checks"))
75 : {
76 :
77 1 : dunedaq::utilities::WorkerThread umth(do_something);
78 2 : BOOST_REQUIRE_THROW(umth.stop_working_thread(), dunedaq::utilities::ThreadingIssue);
79 :
80 1 : umth.start_working_thread();
81 :
82 3 : BOOST_REQUIRE_THROW(umth.start_working_thread(), dunedaq::utilities::ThreadingIssue);
83 :
84 1 : umth.stop_working_thread();
85 1 : }
86 :
87 2 : BOOST_AUTO_TEST_CASE(thread_name)
88 : {
89 1 : dunedaq::utilities::WorkerThread umth(print_name);
90 1 : test_thread_name = "name test";
91 1 : umth.start_working_thread(test_thread_name);
92 1 : umth.stop_working_thread();
93 :
94 1 : BOOST_REQUIRE_EQUAL(test_thread_name, actual_thread_name);
95 :
96 1 : test_thread_name = "too long name test";
97 1 : umth.start_working_thread(test_thread_name);
98 1 : umth.stop_working_thread();
99 :
100 : // Name not changed
101 1 : BOOST_REQUIRE_EQUAL(actual_thread_name, "WorkerThread_te");
102 1 : }
103 :
104 : // You'll want this to test case to execute last, for reasons that are obvious
105 : // if you look at its checks
106 :
107 2 : BOOST_AUTO_TEST_CASE(abort_checks, *boost::unit_test::depends_on("inappropriate_transitions"))
108 : {
109 :
110 1 : {
111 1 : dunedaq::utilities::WorkerThread umth(do_something);
112 1 : }
113 1 : BOOST_TEST(true,
114 : "WorkerThread without having start_working_thread() thread "
115 : "called destructs without aborting the program, as expected");
116 :
117 1 : auto start_time = std::chrono::steady_clock::now();
118 1 : {
119 1 : dunedaq::utilities::WorkerThread umth(do_something);
120 1 : umth.start_working_thread();
121 1 : }
122 1 : BOOST_TEST(true,
123 : "WorkerThread having start_working_thread() thread "
124 : "called destructs without aborting the program, as expected");
125 1 : BOOST_REQUIRE(
126 : std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count() >=
127 : 5000);
128 1 : }
|