blob: 3091b6677b1e1a74c861501139283d3e98a17e74 [file] [log] [blame]
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +01001/*
Anthony Barbiere8a49832018-01-18 10:04:05 +00002 * Copyright (c) 2017-2018 ARM Limited.
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "Framework.h"
25
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010026#include "support/ToolchainSupport.h"
27
28#include <chrono>
29#include <iostream>
30#include <sstream>
31#include <type_traits>
32
33namespace arm_compute
34{
35namespace test
36{
37namespace framework
38{
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010039Framework::Framework()
40{
Giorgio Arenace58a9f2017-10-31 17:59:17 +000041 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::NONE), Instrument::make_instrument<WallClockTimer, ScaleFactor::NONE>);
42 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<WallClockTimer, ScaleFactor::TIME_MS>);
43 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::TIME_S), Instrument::make_instrument<WallClockTimer, ScaleFactor::TIME_S>);
Anthony Barbiere8a49832018-01-18 10:04:05 +000044 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::NONE), Instrument::make_instrument<SchedulerTimer, ScaleFactor::NONE>);
45 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<SchedulerTimer, ScaleFactor::TIME_MS>);
46 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::TIME_S), Instrument::make_instrument<SchedulerTimer, ScaleFactor::TIME_S>);
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010047#ifdef PMU_ENABLED
Giorgio Arenace58a9f2017-10-31 17:59:17 +000048 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::NONE), Instrument::make_instrument<PMUCounter, ScaleFactor::NONE>);
49 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::SCALE_1K), Instrument::make_instrument<PMUCounter, ScaleFactor::SCALE_1K>);
50 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::SCALE_1M), Instrument::make_instrument<PMUCounter, ScaleFactor::SCALE_1M>);
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010051#endif /* PMU_ENABLED */
Moritz Pflanzer45634b42017-08-30 12:48:18 +010052#ifdef MALI_ENABLED
Giorgio Arenace58a9f2017-10-31 17:59:17 +000053 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::NONE), Instrument::make_instrument<MaliCounter, ScaleFactor::NONE>);
54 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::SCALE_1K), Instrument::make_instrument<MaliCounter, ScaleFactor::SCALE_1K>);
55 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::SCALE_1M), Instrument::make_instrument<MaliCounter, ScaleFactor::SCALE_1M>);
Moritz Pflanzer45634b42017-08-30 12:48:18 +010056#endif /* MALI_ENABLED */
Anthony Barbiere8895f82017-11-23 16:58:52 +000057#ifdef ARM_COMPUTE_CL
Giorgio Arenace58a9f2017-10-31 17:59:17 +000058 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::NONE), Instrument::make_instrument<OpenCLTimer, ScaleFactor::NONE>);
59 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_US), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_US>);
60 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_MS>);
61 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_S), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_S>);
Anthony Barbiere8895f82017-11-23 16:58:52 +000062#endif /* ARM_COMPUTE_CL */
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010063}
64
Giorgio Arenace58a9f2017-10-31 17:59:17 +000065std::set<InstrumentsDescription> Framework::available_instruments() const
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010066{
Giorgio Arenace58a9f2017-10-31 17:59:17 +000067 std::set<InstrumentsDescription> types;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010068
69 for(const auto &instrument : _available_instruments)
70 {
71 types.emplace(instrument.first);
72 }
73
74 return types;
75}
76
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010077std::map<TestResult::Status, int> Framework::count_test_results() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010078{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010079 std::map<TestResult::Status, int> counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010080
81 for(const auto &test : _test_results)
82 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010083 ++counts[test.second.status];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010084 }
85
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010086 return counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010087}
88
89Framework &Framework::get()
90{
91 static Framework instance;
92 return instance;
93}
94
Giorgio Arenace58a9f2017-10-31 17:59:17 +000095void Framework::init(const std::vector<framework::InstrumentsDescription> &instruments, int num_iterations, DatasetMode mode, const std::string &name_filter, const std::string &id_filter,
96 LogLevel log_level)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010097{
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +010098 _test_filter = TestFilter(mode, name_filter, id_filter);
99 _num_iterations = num_iterations;
100 _log_level = log_level;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100101
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000102 _instruments = std::set<framework::InstrumentsDescription>(instruments.begin(), instruments.end());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100103}
104
105std::string Framework::current_suite_name() const
106{
107 return join(_test_suite_name.cbegin(), _test_suite_name.cend(), "/");
108}
109
110void Framework::push_suite(std::string name)
111{
112 _test_suite_name.emplace_back(std::move(name));
113}
114
115void Framework::pop_suite()
116{
117 _test_suite_name.pop_back();
118}
119
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100120void Framework::add_test_info(std::string info)
121{
122 _test_info.emplace_back(std::move(info));
123}
124
125void Framework::clear_test_info()
126{
127 _test_info.clear();
128}
129
130bool Framework::has_test_info() const
131{
132 return !_test_info.empty();
133}
134
135void Framework::print_test_info(std::ostream &os) const
136{
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100137 if(!_test_info.empty())
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100138 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100139 os << "CONTEXT:\n";
140
141 for(const auto &str : _test_info)
142 {
143 os << " " << str << "\n";
144 }
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100145 }
146}
147
Giorgio Arena2d099932017-10-25 15:47:08 +0100148template <typename F>
149void Framework::func_on_all_printers(F &&func)
150{
151 std::for_each(std::begin(_printers), std::end(_printers), func);
152}
153
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100154void Framework::log_test_start(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100155{
Giorgio Arena2d099932017-10-25 15:47:08 +0100156 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100157 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100158 func_on_all_printers([&](Printer * p)
159 {
160 p->print_test_header(info);
161 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100162 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100163}
164
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100165void Framework::log_test_skipped(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100166{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100167 static_cast<void>(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100168}
169
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100170void Framework::log_test_end(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100171{
Giorgio Arena2d099932017-10-25 15:47:08 +0100172 if(_log_level >= LogLevel::MEASUREMENTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100173 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100174 func_on_all_printers([&](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100175 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100176 p->print_measurements(_test_results.at(info).measurements);
177 });
178 }
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100179
Giorgio Arena2d099932017-10-25 15:47:08 +0100180 if(_log_level >= LogLevel::TESTS)
181 {
182 func_on_all_printers([](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100183 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100184 p->print_test_footer();
185 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100186 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100187}
188
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100189void Framework::log_failed_expectation(const TestError &error)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100190{
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100191 ARM_COMPUTE_ERROR_ON(_current_test_info == nullptr);
192 ARM_COMPUTE_ERROR_ON(_current_test_result == nullptr);
193
194 const bool is_expected_failure = _current_test_info->status == TestCaseFactory::Status::EXPECTED_FAILURE;
195
Giorgio Arena2d099932017-10-25 15:47:08 +0100196 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100197 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100198 func_on_all_printers([&](Printer * p)
199 {
200 p->print_error(error, is_expected_failure);
201 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100202 }
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100203
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100204 _current_test_result->status = TestResult::Status::FAILED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100205}
206
steniu01172c58d2017-08-31 13:49:08 +0100207void Framework::log_info(const std::string &info)
208{
Giorgio Arena2d099932017-10-25 15:47:08 +0100209 if(_log_level >= LogLevel::DEBUG)
steniu01172c58d2017-08-31 13:49:08 +0100210 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100211 func_on_all_printers([&](Printer * p)
212 {
213 p->print_info(info);
214 });
steniu01172c58d2017-08-31 13:49:08 +0100215 }
216}
217
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100218int Framework::num_iterations() const
219{
220 return _num_iterations;
221}
222
223void Framework::set_num_iterations(int num_iterations)
224{
225 _num_iterations = num_iterations;
226}
227
228void Framework::set_throw_errors(bool throw_errors)
229{
230 _throw_errors = throw_errors;
231}
232
233bool Framework::throw_errors() const
234{
235 return _throw_errors;
236}
237
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100238void Framework::set_stop_on_error(bool stop_on_error)
239{
240 _stop_on_error = stop_on_error;
241}
242
243bool Framework::stop_on_error() const
244{
245 return _stop_on_error;
246}
247
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100248void Framework::set_error_on_missing_assets(bool error_on_missing_assets)
249{
250 _error_on_missing_assets = error_on_missing_assets;
251}
252
253bool Framework::error_on_missing_assets() const
254{
255 return _error_on_missing_assets;
256}
257
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100258void Framework::run_test(const TestInfo &info, TestCaseFactory &test_factory)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100259{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100260 if(test_factory.status() == TestCaseFactory::Status::DISABLED)
261 {
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100262 log_test_skipped(info);
263 set_test_result(info, TestResult(TestResult::Status::DISABLED));
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100264 return;
265 }
266
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100267 log_test_start(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100268
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100269 Profiler profiler = get_profiler();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100270 TestResult result(TestResult::Status::NOT_RUN);
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100271
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100272 _current_test_info = &info;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100273 _current_test_result = &result;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100274
Giorgio Arena2d099932017-10-25 15:47:08 +0100275 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100276 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100277 func_on_all_printers([](Printer * p)
278 {
279 p->print_errors_header();
280 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100281 }
282
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100283 const bool is_expected_failure = info.status == TestCaseFactory::Status::EXPECTED_FAILURE;
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100284
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100285 try
286 {
287 std::unique_ptr<TestCase> test_case = test_factory.make();
288
289 try
290 {
291 test_case->do_setup();
292
293 for(int i = 0; i < _num_iterations; ++i)
294 {
Anthony Barbier61941452017-11-21 17:49:07 +0000295 //Start the profiler if:
296 //- there is only one iteration
297 //- it's not the first iteration of a multi-iterations run.
298 //
299 //Reason: if the CLTuner is enabled then the first run will be really messy
300 //as each kernel will be executed several times, messing up the instruments like OpenCL timers.
301 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000302 {
303 profiler.start();
304 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100305 test_case->do_run();
Joel Liang1c5ffd62017-12-28 10:09:51 +0800306 test_case->do_sync();
Anthony Barbier61941452017-11-21 17:49:07 +0000307 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000308 {
309 profiler.stop();
310 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100311 }
312
313 test_case->do_teardown();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100314
315 // Change status to success if no error has happend
316 if(result.status == TestResult::Status::NOT_RUN)
317 {
318 result.status = TestResult::Status::SUCCESS;
319 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100320 }
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100321 catch(const FileNotFound &error)
322 {
323 if(_error_on_missing_assets)
324 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100325 if(_log_level >= LogLevel::ERRORS)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100326 {
327 TestError test_error(error.what(), LogLevel::ERRORS);
Giorgio Arena2d099932017-10-25 15:47:08 +0100328 func_on_all_printers([&](Printer * p)
329 {
330 p->print_error(test_error, is_expected_failure);
331 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100332 }
333
334 result.status = TestResult::Status::FAILED;
335
336 if(_throw_errors)
337 {
338 throw;
339 }
340 }
341 else
342 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100343 if(_log_level >= LogLevel::DEBUG)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100344 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100345 func_on_all_printers([&](Printer * p)
346 {
347 p->print_info(error.what());
348 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100349 }
350
351 result.status = TestResult::Status::NOT_RUN;
352 }
353 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100354 catch(const TestError &error)
355 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100356 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100357 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100358 func_on_all_printers([&](Printer * p)
359 {
360 p->print_error(error, is_expected_failure);
361 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100362 }
363
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100364 result.status = TestResult::Status::FAILED;
365
366 if(_throw_errors)
367 {
368 throw;
369 }
370 }
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100371#ifdef ARM_COMPUTE_CL
372 catch(const ::cl::Error &error)
373 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100374 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100375 {
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100376 std::stringstream stream;
377 stream << "Error code: " << error.err();
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100378 TestError test_error(error.what(), LogLevel::ERRORS, stream.str());
Giorgio Arena2d099932017-10-25 15:47:08 +0100379 func_on_all_printers([&](Printer * p)
380 {
381 p->print_error(test_error, is_expected_failure);
382 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100383 }
384
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100385 result.status = TestResult::Status::FAILED;
386
387 if(_throw_errors)
388 {
389 throw;
390 }
391 }
392#endif /* ARM_COMPUTE_CL */
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100393 catch(const std::exception &error)
394 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100395 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100396 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100397 func_on_all_printers([&](Printer * p)
398 {
399 p->print_error(error, is_expected_failure);
400 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100401 }
402
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100403 result.status = TestResult::Status::CRASHED;
404
405 if(_throw_errors)
406 {
407 throw;
408 }
409 }
410 catch(...)
411 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100412 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100413 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100414 func_on_all_printers([&](Printer * p)
415 {
416 p->print_error(TestError("Received unknown exception"), is_expected_failure);
417 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100418 }
419
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100420 result.status = TestResult::Status::CRASHED;
421
422 if(_throw_errors)
423 {
424 throw;
425 }
426 }
427 }
428 catch(const std::exception &error)
429 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100430 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100431 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100432 func_on_all_printers([&](Printer * p)
433 {
434 p->print_error(error, is_expected_failure);
435 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100436 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100437
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100438 result.status = TestResult::Status::CRASHED;
439
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100440 if(_throw_errors)
441 {
442 throw;
443 }
444 }
445 catch(...)
446 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100447 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100448 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100449 func_on_all_printers([&](Printer * p)
450 {
451 p->print_error(TestError("Received unknown exception"), is_expected_failure);
452 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100453 }
454
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100455 result.status = TestResult::Status::CRASHED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100456
457 if(_throw_errors)
458 {
459 throw;
460 }
461 }
462
Giorgio Arena2d099932017-10-25 15:47:08 +0100463 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100464 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100465 func_on_all_printers([](Printer * p)
466 {
467 p->print_errors_footer();
468 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100469 }
470
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100471 _current_test_info = nullptr;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100472 _current_test_result = nullptr;
473
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100474 if(result.status == TestResult::Status::FAILED)
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100475 {
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100476 if(info.status == TestCaseFactory::Status::EXPECTED_FAILURE)
477 {
478 result.status = TestResult::Status::EXPECTED_FAILURE;
479 }
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100480 }
481
482 if(result.status == TestResult::Status::FAILED || result.status == TestResult::Status::CRASHED)
483 {
484 if(_stop_on_error)
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100485 {
486 throw std::runtime_error("Abort on first error.");
487 }
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100488 }
489
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100490 result.measurements = profiler.measurements();
491
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100492 set_test_result(info, result);
493 log_test_end(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100494}
495
496bool Framework::run()
497{
498 // Clear old test results
499 _test_results.clear();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100500
Giorgio Arena2d099932017-10-25 15:47:08 +0100501 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100502 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100503 func_on_all_printers([](Printer * p)
504 {
505 p->print_run_header();
506 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100507 }
508
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100509 const std::chrono::time_point<std::chrono::high_resolution_clock> start = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100510
511 int id = 0;
512
513 for(auto &test_factory : _test_factories)
514 {
515 const std::string test_case_name = test_factory->name();
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100516 const TestInfo test_info{ id, test_case_name, test_factory->mode(), test_factory->status() };
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100517
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100518 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100519 {
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100520 run_test(test_info, *test_factory);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100521 }
522
523 ++id;
524 }
525
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100526 const std::chrono::time_point<std::chrono::high_resolution_clock> end = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100527
Giorgio Arena2d099932017-10-25 15:47:08 +0100528 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100529 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100530 func_on_all_printers([](Printer * p)
531 {
532 p->print_run_footer();
533 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100534 }
535
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100536 auto runtime = std::chrono::duration_cast<std::chrono::seconds>(end - start);
537 std::map<TestResult::Status, int> results = count_test_results();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100538
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100539 if(_log_level > LogLevel::NONE)
540 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100541 std::cout << "Executed " << _test_results.size() << " test(s) ("
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100542 << results[TestResult::Status::SUCCESS] << " passed, "
543 << results[TestResult::Status::EXPECTED_FAILURE] << " expected failures, "
544 << results[TestResult::Status::FAILED] << " failed, "
545 << results[TestResult::Status::CRASHED] << " crashed, "
546 << results[TestResult::Status::DISABLED] << " disabled) in " << runtime.count() << " second(s)\n";
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100547 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100548
steniu013e05e4e2017-08-25 17:18:01 +0100549 int num_successful_tests = results[TestResult::Status::SUCCESS] + results[TestResult::Status::EXPECTED_FAILURE] + results[TestResult::Status::DISABLED];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100550
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100551 return (static_cast<unsigned int>(num_successful_tests) == _test_results.size());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100552}
553
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100554void Framework::set_test_result(TestInfo info, TestResult result)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100555{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100556 _test_results.emplace(std::move(info), std::move(result));
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100557}
558
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100559void Framework::print_test_results(Printer &printer) const
560{
561 printer.print_run_header();
562
563 for(const auto &test : _test_results)
564 {
565 printer.print_test_header(test.first);
566 printer.print_measurements(test.second.measurements);
567 printer.print_test_footer();
568 }
569
570 printer.print_run_footer();
571}
572
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100573Profiler Framework::get_profiler() const
574{
575 Profiler profiler;
576
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100577 const bool all_instruments = std::any_of(
578 _instruments.begin(),
579 _instruments.end(),
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000580 [](InstrumentsDescription type) -> bool { return type.first == InstrumentType::ALL; });
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100581
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000582 auto is_selected = [&](InstrumentsDescription instrument) -> bool
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100583 {
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000584 return std::find_if(_instruments.begin(), _instruments.end(), [&](InstrumentsDescription type) -> bool {
585 const auto group = static_cast<InstrumentType>(static_cast<uint64_t>(type.first) & 0xFF00);
586 return (group == instrument.first) && (instrument.second == type.second);
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100587 })
588 != _instruments.end();
589 };
590
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100591 for(const auto &instrument : _available_instruments)
592 {
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100593 if(all_instruments || is_selected(instrument.first))
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100594 {
595 profiler.add(instrument.second());
596 }
597 }
598
599 return profiler;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100600}
601
Giorgio Arena2d099932017-10-25 15:47:08 +0100602void Framework::add_printer(Printer *printer)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100603{
Giorgio Arena2d099932017-10-25 15:47:08 +0100604 _printers.push_back(printer);
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100605}
606
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100607std::vector<TestInfo> Framework::test_infos() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100608{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100609 std::vector<TestInfo> ids;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100610
611 int id = 0;
612
613 for(const auto &factory : _test_factories)
614 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100615 TestInfo test_info{ id, factory->name(), factory->mode(), factory->status() };
616
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100617 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100618 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100619 ids.emplace_back(std::move(test_info));
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100620 }
621
622 ++id;
623 }
624
625 return ids;
626}
steniu01172c58d2017-08-31 13:49:08 +0100627
628LogLevel Framework::log_level() const
629{
630 return _log_level;
631}
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100632} // namespace framework
633} // namespace test
634} // namespace arm_compute