GCC Code Coverage Report


Directory: ./
File: openvdb_ax/openvdb_ax/test/main.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 47 98 48.0%
Functions: 4 7 57.1%
Branches: 45 170 26.5%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 #include <openvdb_ax/compiler/Compiler.h>
5
6 #include <openvdb/openvdb.h>
7 #include <openvdb/points/PointDataGrid.h>
8 #include <openvdb/util/CpuTimer.h>
9 #include <openvdb/util/logging.h>
10
11 #include <cppunit/CompilerOutputter.h>
12 #include <cppunit/TestFailure.h>
13 #include <cppunit/TestListener.h>
14 #include <cppunit/TestResult.h>
15 #include <cppunit/TestResultCollector.h>
16 #include <cppunit/TextTestProgressListener.h>
17 #include <cppunit/extensions/TestFactoryRegistry.h>
18 #include <cppunit/ui/text/TestRunner.h>
19
20 #include <algorithm> // for std::shuffle()
21 #include <cmath> // for std::round()
22 #include <cstdlib> // for EXIT_SUCCESS
23 #include <cstring> // for strrchr()
24 #include <exception>
25 #include <fstream>
26 #include <iostream>
27 #include <random>
28 #include <string>
29 #include <vector>
30
31
32 /// @note Global unit test flag enabled with -g which symbolises the integration
33 /// tests to auto-generate their AX tests. Any previous tests will be
34 /// overwritten.
35 int sGenerateAX = false;
36
37
38 namespace {
39
40 using StringVec = std::vector<std::string>;
41
42
43 void
44 usage(const char* progName, std::ostream& ostrm)
45 {
46 ostrm <<
47 "Usage: " << progName << " [options]\n" <<
48 "Which: runs OpenVDB AX library unit tests\n" <<
49 "Options:\n" <<
50 " -f file read whitespace-separated names of tests to be run\n" <<
51 " from the given file (\"#\" comments are supported)\n" <<
52 " -l list all available tests\n" <<
53 " -shuffle run tests in random order\n" <<
54 " -t test specific suite or test to run, e.g., \"-t TestGrid\"\n" <<
55 " or \"-t TestGrid::testGetGrid\" (default: run all tests)\n" <<
56 " -v verbose output\n" <<
57 " -g As well as testing, auto-generate any integration tests\n";
58 #ifdef OPENVDB_USE_LOG4CPLUS
59 ostrm <<
60 "\n" <<
61 " -error log fatal and non-fatal errors (default: log only fatal errors)\n" <<
62 " -warn log warnings and errors\n" <<
63 " -info log info messages, warnings and errors\n" <<
64 " -debug log debugging messages, info messages, warnings and errors\n";
65 #endif
66 }
67
68
69 void
70 getTestNames(StringVec& nameVec, const CppUnit::Test* test)
71 {
72 if (test) {
73 const int numChildren = test->getChildTestCount();
74 if (numChildren == 0) {
75 nameVec.push_back(test->getName());
76 } else {
77 for (int i = 0; i < test->getChildTestCount(); ++i) {
78 getTestNames(nameVec, test->getChildTestAt(i));
79 }
80 }
81 }
82 }
83
84
85 /// Listener that prints the name, elapsed time, and error status of each test
86 1 class TimedTestProgressListener: public CppUnit::TestListener
87 {
88 public:
89 246 void startTest(CppUnit::Test* test) override
90 {
91 246 mFailed = false;
92 492 std::cout << test->getName() << std::flush;
93 mTimer.start();
94 246 }
95
96 void addFailure(const CppUnit::TestFailure& failure) override
97 {
98 std::cout << " : " << (failure.isError() ? "error" : "assertion");
99 mFailed = true;
100 }
101
102 246 void endTest(CppUnit::Test*) override
103 {
104
1/2
✓ Branch 0 taken 246 times.
✗ Branch 1 not taken.
246 if (!mFailed) {
105 // Print elapsed time only for successful tests.
106 246 const double msec = std::round(mTimer.milliseconds());
107
2/2
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 82 times.
246 if (msec > 1.0) {
108
5/8
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 84 times.
✓ Branch 3 taken 164 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 164 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 164 times.
✗ Branch 10 not taken.
408 openvdb::util::printTime(std::cout, msec, " : OK (", ")",
109 /*width=*/0, /*precision=*/(msec > 1000.0 ? 1 : 0), /*verbose=*/0);
110 } else {
111 82 std::cout << " : OK (<1ms)";
112 }
113 }
114 std::cout << std::endl;
115 246 }
116
117 private:
118 openvdb::util::CpuTimer mTimer;
119 bool mFailed = false;
120 };
121
122
123 int
124 1 run(int argc, char* argv[])
125 {
126
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 const char* progName = argv[0];
127
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (const char* ptr = ::strrchr(progName, '/')) progName = ptr + 1;
128
129 bool shuffle = false, verbose = false;
130 1 StringVec tests;
131
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int i = 1; i < argc; ++i) {
132
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const std::string arg = argv[i];
133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (arg == "-l") {
134 StringVec allTests;
135 const CppUnit::Test* tests = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
136 getTestNames(allTests, tests);
137 delete tests;
138 for (const auto& name: allTests) { std::cout << name << "\n"; }
139 return EXIT_SUCCESS;
140
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (arg == "-shuffle") {
141 shuffle = true;
142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (arg == "-v") {
143 verbose = true;
144 } else if (arg == "-g") {
145 sGenerateAX = true;
146 } else if (arg == "-t") {
147 if (i + 1 < argc) {
148 ++i;
149 tests.push_back(argv[i]);
150 } else {
151 OPENVDB_LOG_FATAL("missing test name after \"-t\"");
152 usage(progName, std::cerr);
153 return EXIT_FAILURE;
154 }
155 } else if (arg == "-f") {
156 if (i + 1 < argc) {
157 ++i;
158 std::ifstream file{argv[i]};
159 if (file.fail()) {
160 OPENVDB_LOG_FATAL("unable to read file " << argv[i]);
161 return EXIT_FAILURE;
162 }
163 while (file) {
164 // Read a whitespace-separated string from the file.
165 std::string test;
166 file >> test;
167 if (!test.empty()) {
168 if (test[0] != '#') {
169 tests.push_back(test);
170 } else {
171 // If the string starts with a comment symbol ("#"),
172 // skip it and jump to the end of the line.
173 while (file) { if (file.get() == '\n') break; }
174 }
175 }
176 }
177 } else {
178 OPENVDB_LOG_FATAL("missing filename after \"-f\"");
179 usage(progName, std::cerr);
180 return EXIT_FAILURE;
181 }
182 } else if (arg == "-h" || arg == "-help" || arg == "--help") {
183 usage(progName, std::cout);
184 return EXIT_SUCCESS;
185 } else {
186 OPENVDB_LOG_FATAL("unrecognized option \"" << arg << "\"");
187 usage(progName, std::cerr);
188 return EXIT_FAILURE;
189 }
190 }
191
192 try {
193 CppUnit::TestFactoryRegistry& registry =
194
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 CppUnit::TestFactoryRegistry::getRegistry();
195
196
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto* root = registry.makeTest();
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!root) {
198 throw std::runtime_error(
199 "CppUnit test registry was not initialized properly");
200 }
201
202
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!shuffle) {
203
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 if (tests.empty()) tests.push_back("");
204 } else {
205 // Get the names of all selected tests and their children.
206 StringVec allTests;
207 if (tests.empty()) {
208 getTestNames(allTests, root);
209 } else {
210 for (const auto& name: tests) {
211 getTestNames(allTests, root->findTest(name));
212 }
213 }
214 // Randomly shuffle the list of names.
215 std::random_device randDev;
216 std::mt19937 generator(randDev());
217 std::shuffle(allTests.begin(), allTests.end(), generator);
218 tests.swap(allTests);
219 }
220
221
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CppUnit::TestRunner runner;
222
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 runner.addTest(root);
223
224
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CppUnit::TestResult controller;
225
226
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CppUnit::TestResultCollector result;
227
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 controller.addListener(&result);
228
229
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 CppUnit::TextTestProgressListener progress;
230 TimedTestProgressListener vProgress;
231
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (verbose) {
232
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 controller.addListener(&vProgress);
233 } else {
234 controller.addListener(&progress);
235 }
236
237
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (size_t i = 0; i < tests.size(); ++i) {
238
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 runner.run(controller, tests[i]);
239 }
240
241
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 CppUnit::CompilerOutputter outputter(&result, std::cerr);
242
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 outputter.write();
243
244
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 return result.wasSuccessful() ? EXIT_SUCCESS : EXIT_FAILURE;
245
246 } catch (std::exception& e) {
247 OPENVDB_LOG_FATAL(e.what());
248 return EXIT_FAILURE;
249 }
250 }
251
252 } // anonymous namespace
253
254 template <typename T>
255 static inline void registerType()
256 {
257
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
6 if (!openvdb::points::TypedAttributeArray<T>::isRegistered())
258 6 openvdb::points::TypedAttributeArray<T>::registerType();
259 }
260
261 int
262 1 main(int argc, char *argv[])
263 {
264 1 openvdb::initialize();
265 1 openvdb::ax::initialize();
266 openvdb::logging::initialize(argc, argv);
267
268 // Also intialize Vec2/4 point attributes
269
270 registerType<openvdb::math::Vec2<int32_t>>();
271 registerType<openvdb::math::Vec2<float>>();
272 registerType<openvdb::math::Vec2<double>>();
273 registerType<openvdb::math::Vec4<int32_t>>();
274 registerType<openvdb::math::Vec4<float>>();
275 registerType<openvdb::math::Vec4<double>>();
276
277 1 auto value = run(argc, argv);
278
279 1 openvdb::ax::uninitialize();
280 1 openvdb::uninitialize();
281
282 return value;
283 }
284
285