μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
run_uhal_tests.cxx
Go to the documentation of this file.
1/*
2---------------------------------------------------------------------------
3
4 This file is part of uHAL.
5
6 uHAL is a hardware access library and programming framework
7 originally developed for upgrades of the Level-1 trigger of the CMS
8 experiment at CERN.
9
10 uHAL is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 uHAL is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with uHAL. If not, see <http://www.gnu.org/licenses/>.
22
23 Marc Magrans de Abril, CERN
24 email: marc.magrans.de.abril <AT> cern.ch
25
26 Andrew Rose, Imperial College, London
27 email: awr01 <AT> imperial.ac.uk
28
29 Tom Williams, Rutherford Appleton Laboratory, Oxfordshire
30 email: tom.williams <AT> cern.ch
31
32---------------------------------------------------------------------------
33*/
34
35
36/*
37 * File: run_uhal_tests.cxx
38 * Author: Tom Williams
39 * Date: September 2017
40 */
41
42
43
44#define BOOST_TEST_MODULE uhalTests
45
46// BOOST_TEST_NO_MAIN: Disable auto-generation of main function, in order to define our own, which parses some arguments
47#define BOOST_TEST_NO_MAIN
48
49
50#include <boost/program_options.hpp>
51#include <boost/test/unit_test.hpp>
52#if BOOST_VERSION >= 105900
53 #include <boost/test/tree/traverse.hpp>
54 #include <boost/test/tree/visitor.hpp>
55#endif
56
59#include "uhal/tests/tools.hpp"
60#include "uhal/log/log.hpp"
61
62
63#ifdef BOOST_TEST_DYN_LINK
64
65// Inspired by https://stackoverflow.com/questions/25385011/getting-all-boost-test-suites-test-cases
66struct ListWritingVisitor : boost::unit_test::test_tree_visitor
67{
68 size_t level;
69 size_t maxDepth;
70
71 ListWritingVisitor(const size_t aMaxDepth) :
72 level(0),
73 maxDepth(aMaxDepth == 0 ? std::numeric_limits<size_t>::max() : aMaxDepth)
74 {}
75
76 void visit( boost::unit_test::test_case const& test )
77 {
78 if ((level+1) <= maxDepth)
79 std::cout << std::string(2 * (level > 2 ? level - 2 : 0), ' ') << " └> " << test.p_name << std::endl;
80 }
81
82 bool test_suite_start( boost::unit_test::test_suite const& suite )
83 {
84 level += 1;
85
86 if (level <= maxDepth)
87 std::cout << std::string(2 * (level > 2 ? level - 2 : 0), ' ') << (level > 1 ? "└ " : "") << suite.p_name << std::endl;
88 return true;
89 }
90
91 void test_suite_finish( boost::unit_test::test_suite const& suite )
92 {
93 level -= 1;
94 }
95};
96
97
98using namespace uhal::tests;
99
100const std::string kOptionHelp = "help";
101const std::string kOptionList = "list";
102const std::string kOptionConnFile = "connection-file";
103const std::string kOptionHwTimeout = "timeout";
104const std::string kOptionQuickTest = "quick";
105const std::string kOptionVerbose = "verbose";
106const std::string kOptionVeryVerbose = "very-verbose";
107
108int BOOST_TEST_CALL_DECL
109main( int argc, char* argv[] )
110{
111 namespace po = boost::program_options;
112
113 size_t lListDepth = 0;
114
115 po::options_description lDesc ( "Allowed options" );
116 lDesc.add_options()
117 ( (kOptionHelp + ",h").c_str(), "produce help message" )
118 ( (kOptionList + ",l").c_str(), po::value<size_t>(&lListDepth)->implicit_value(0), "List all test suites and test cases (max depth can be specified if wanted; if not, all depths are shown)" )
119 ( (kOptionConnFile + ",c").c_str(), po::value<std::string>(&AbstractFixture::connectionFileURI), "Connection file URI" )
120 ( (kOptionHwTimeout + ",t").c_str(), po::value<size_t>(&AbstractFixture::timeout)->default_value(1000), "Timeout for Client/HwInterface (unit: ms)" )
121 ( kOptionQuickTest.c_str(), "Run brief tests (fewer iterations)" )
122 ( (kOptionVerbose + ",v").c_str(), "Verbose output" )
123 ( (kOptionVeryVerbose + ",V").c_str(), "Very verbose output" )
124 ;
125 po::variables_map vm;
126
127
128 std::vector<std::string> lOptionsForBoostUTF;
129 try
130 {
131 po::parsed_options lParsedOptions = po::command_line_parser(argc, argv).options(lDesc).allow_unregistered().run();
132 po::store ( lParsedOptions, vm );
133 po::notify ( vm );
134 lOptionsForBoostUTF = po::collect_unrecognized(lParsedOptions.options, po::include_positional);
135 }
136 catch ( std::exception& e )
137 {
138 std::cerr << "ERROR : " << e.what() << std::endl << std::endl;
139 std::cout << "Usage : " << argv[0] << " [OPTIONS]" << std::endl;
140 std::cout << lDesc << std::endl;
141 exit ( 1 );
142 }
143
144 if ( vm.count ( kOptionHelp ) )
145 {
146 std::cout << "Usage: " << argv[0] << " [OPTIONS]" << std::endl;
147 std::cout << lDesc << std::endl;
148 exit ( 0 );
149 }
150
151 if ( vm.count ( kOptionList ) )
152 {
153 ListWritingVisitor lVisitor(lListDepth);
154 boost::unit_test::traverse_test_tree( boost::unit_test::framework::master_test_suite(), lVisitor);
155 exit ( 0 );
156 }
157
158 if ( vm.count (kOptionConnFile) == 0)
159 {
160 std::cerr << " ERROR : Option '" << kOptionConnFile << "' must be specified under normal running mode." << std::endl << std::endl;
161 std::cout << "Usage: " << argv[0] << " [OPTIONS]" << std::endl;
162 std::cout << lDesc << std::endl;
163 exit ( 1 );
164 }
165 else if ( AbstractFixture::connectionFileURI.find("file://") != 0 )
166 AbstractFixture::connectionFileURI = "file://" + AbstractFixture::connectionFileURI;
167
168 AbstractFixture::quickTest = ( vm.count(kOptionQuickTest) > 0);
169
170 std::cout << "Supplied arguments ..." << std::endl;
171 std::cout << " connection file = " << AbstractFixture::connectionFileURI << std::endl;
172 std::cout << " timeout = " << AbstractFixture::timeout << " ms" << std::endl;
173 std::cout << " " << (AbstractFixture::quickTest ? "quick" : "full") << " test will be run" << std::endl;
174
175 std::cout << "Log level set to ";
176 if ( vm.count ( kOptionVeryVerbose ) ) {
178 std::cout << "DEBUG";
179 }
180 else if ( vm.count ( kOptionVerbose ) ) {
182 std::cout << "NOTICE";
183 }
184 else {
186 std::cout << "FATAL";
187 }
188 std::cout << std::endl << std::endl;
189
190
191 std::vector<const char*> lArgvForBoostUTF;
192 lArgvForBoostUTF.push_back(argv[0]);
193 if (lOptionsForBoostUTF.empty())
194 std::cout << "N.B. Didn't find any arguments/options to pass to boost UTF" << std::endl;
195 else {
196 std::cout << "Passing " << lOptionsForBoostUTF.size() << " arguments/options to boost UTF:" << std::endl << " ";
197 for (size_t i=0; i<lOptionsForBoostUTF.size(); i++) {
198 std::cout << " " << lOptionsForBoostUTF.at(i);
199 lArgvForBoostUTF.push_back(lOptionsForBoostUTF.at(i).c_str());
200 }
201 }
202 std::cout << std::endl << std::endl;
203
204 lArgvForBoostUTF.push_back(0);
205 return ::boost::unit_test::unit_test_main( &init_unit_test, lArgvForBoostUTF.size()-1, const_cast<char**>(lArgvForBoostUTF.data()) );
206}
207
208#endif
int main(int argc, char *argv[])
Definition: generator.cxx:423
Definition: test.py:1
DebugLevel Debug
Definition: LogLevels.cpp:133
void setLogLevelTo(const FatalLevel &)
Function to specify, at runtime, that only messages with a severity level above Fatal should be logge...
Definition: log.cpp:87
FatalLevel Fatal
Definition: LogLevels.cpp:43
NoticeLevel Notice
Definition: LogLevels.cpp:97
const char * c_str(Args &&...args)
Constructs a std::string with the given arguments, stores it in internals, and returns its c_str().
Definition: internals.h:534