μHAL (v2.6.5)
Part of the IPbus software repository
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_DYN_LINK
45 #define BOOST_TEST_MODULE uhalTests
46 
47 // BOOST_TEST_NO_MAIN: Disable auto-generation of main function, in order to define our own, which parses some arguments
48 #define BOOST_TEST_NO_MAIN
49 
50 
51 #include <boost/program_options.hpp>
52 #include <boost/test/unit_test.hpp>
53 #if BOOST_VERSION >= 105900
54  #include <boost/test/tree/traverse.hpp>
55  #include <boost/test/tree/visitor.hpp>
56 #endif
57 
59 #include "uhal/tests/fixtures.hpp"
60 #include "uhal/tests/tools.hpp"
61 #include "uhal/log/log.hpp"
62 
63 
64 // Inspired by https://stackoverflow.com/questions/25385011/getting-all-boost-test-suites-test-cases
65 struct ListWritingVisitor : boost::unit_test::test_tree_visitor
66 {
67  size_t level;
68  size_t maxDepth;
69 
70  ListWritingVisitor(const size_t aMaxDepth) :
71  level(0),
72  maxDepth(aMaxDepth == 0 ? std::numeric_limits<size_t>::max() : aMaxDepth)
73  {}
74 
75  void visit( boost::unit_test::test_case const& test )
76  {
77  if ((level+1) <= maxDepth)
78  std::cout << std::string(2 * (level > 2 ? level - 2 : 0), ' ') << " └> " << test.p_name << std::endl;
79  }
80 
81  bool test_suite_start( boost::unit_test::test_suite const& suite )
82  {
83  level += 1;
84 
85  if (level <= maxDepth)
86  std::cout << std::string(2 * (level > 2 ? level - 2 : 0), ' ') << (level > 1 ? "└ " : "") << suite.p_name << std::endl;
87  return true;
88  }
89 
90  void test_suite_finish( boost::unit_test::test_suite const& suite )
91  {
92  level -= 1;
93  }
94 };
95 
96 
97 using namespace uhal::tests;
98 
99 const std::string kOptionHelp = "help";
100 const std::string kOptionList = "list";
101 const std::string kOptionConnFile = "connection-file";
102 const std::string kOptionVerbose = "verbose";
103 const std::string kOptionVeryVerbose = "very-verbose";
104 
105 int BOOST_TEST_CALL_DECL
106 main( int argc, char* argv[] )
107 {
108  namespace po = boost::program_options;
109 
110  size_t lListDepth = 0;
111 
112  po::options_description lDesc ( "Allowed options" );
113  lDesc.add_options()
114  ( (kOptionHelp + ",h").c_str(), "produce help message" )
115  ( (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)" )
116  ( (kOptionConnFile + ",c").c_str(), po::value<std::string>(&AbstractFixture::connectionFileURI), "Connection file URI" )
117  ( (kOptionVerbose + ",v").c_str(), "Verbose output" )
118  ( (kOptionVeryVerbose + ",V").c_str(), "Very verbose output" )
119  ;
120  po::variables_map vm;
121 
122 
123  std::vector<std::string> lOptionsForBoostUTF;
124  try
125  {
126  po::parsed_options lParsedOptions = po::command_line_parser(argc, argv).options(lDesc).allow_unregistered().run();
127  po::store ( lParsedOptions, vm );
128  po::notify ( vm );
129  lOptionsForBoostUTF = po::collect_unrecognized(lParsedOptions.options, po::include_positional);
130  }
131  catch ( std::exception& e )
132  {
133  std::cerr << "ERROR : " << e.what() << std::endl << std::endl;
134  std::cout << "Usage : " << argv[0] << " [OPTIONS]" << std::endl;
135  std::cout << lDesc << std::endl;
136  exit ( 1 );
137  }
138 
139  if ( vm.count ( kOptionHelp ) )
140  {
141  std::cout << "Usage: " << argv[0] << " [OPTIONS]" << std::endl;
142  std::cout << lDesc << std::endl;
143  exit ( 0 );
144  }
145 
146  if ( vm.count ( kOptionList ) )
147  {
148  ListWritingVisitor lVisitor(lListDepth);
149  boost::unit_test::traverse_test_tree( boost::unit_test::framework::master_test_suite(), lVisitor);
150  exit ( 0 );
151  }
152  else if ( vm.count (kOptionConnFile) == 0)
153  {
154  std::cerr << " ERROR : Option '" << kOptionConnFile << "' must be specified under normal running mode." << std::endl << std::endl;
155  std::cout << "Usage: " << argv[0] << " [OPTIONS]" << std::endl;
156  std::cout << lDesc << std::endl;
157  exit ( 1 );
158  }
159 
160  std::cout << "Supplied arguments ..." << std::endl;
161  std::cout << " connection file = " << AbstractFixture::connectionFileURI << std::endl;
162 
163  std::cout << "Log level set to ";
164  if ( vm.count ( kOptionVeryVerbose ) ) {
165  uhal::setLogLevelTo ( uhal::Debug() );
166  std::cout << "DEBUG";
167  }
168  else if ( vm.count ( kOptionVerbose ) ) {
169  uhal::setLogLevelTo ( uhal::Notice() );
170  std::cout << "NOTICE";
171  }
172  else {
173  uhal::setLogLevelTo ( uhal::Fatal() );
174  std::cout << "FATAL";
175  }
176  std::cout << std::endl << std::endl;
177 
178 
179  std::vector<const char*> lArgvForBoostUTF;
180  lArgvForBoostUTF.push_back(argv[0]);
181  if (lOptionsForBoostUTF.empty())
182  std::cout << "N.B. Didn't find any arguments/options to pass to boost UTF" << std::endl;
183  else {
184  std::cout << "Passing " << lOptionsForBoostUTF.size() << " arguments/options to boost UTF:" << std::endl << " ";
185  for (size_t i=0; i<lOptionsForBoostUTF.size(); i++) {
186  std::cout << " " << lOptionsForBoostUTF.at(i);
187  lArgvForBoostUTF.push_back(lOptionsForBoostUTF.at(i).c_str());
188  }
189  }
190  std::cout << std::endl << std::endl;
191 
192  lArgvForBoostUTF.push_back(0);
193  return ::boost::unit_test::unit_test_main( &init_unit_test, lArgvForBoostUTF.size()-1, const_cast<char**>(lArgvForBoostUTF.data()) );
194 }
NoticeLevel Notice
Definition: LogLevels.cpp:96
bool test_suite_start(boost::unit_test::test_suite const &suite)
ListWritingVisitor(const size_t aMaxDepth)
const std::string kOptionVerbose
const std::string kOptionConnFile
const std::string kOptionHelp
void visit(boost::unit_test::test_case const &test)
int BOOST_TEST_CALL_DECL main(int argc, char *argv[])
FatalLevel Fatal
Definition: LogLevels.cpp:42
const std::string kOptionVeryVerbose
DebugLevel Debug
Definition: LogLevels.cpp:133
const std::string kOptionList
void test_suite_finish(boost::unit_test::test_suite const &suite)