blob: 238b5ab2c041f54c189377eccf77f50859320ee3 [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 {
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100291 profiler.test_start();
292
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100293 test_case->do_setup();
294
295 for(int i = 0; i < _num_iterations; ++i)
296 {
Anthony Barbier61941452017-11-21 17:49:07 +0000297 //Start the profiler if:
298 //- there is only one iteration
299 //- it's not the first iteration of a multi-iterations run.
300 //
301 //Reason: if the CLTuner is enabled then the first run will be really messy
302 //as each kernel will be executed several times, messing up the instruments like OpenCL timers.
303 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000304 {
305 profiler.start();
306 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100307 test_case->do_run();
Joel Liang1c5ffd62017-12-28 10:09:51 +0800308 test_case->do_sync();
Anthony Barbier61941452017-11-21 17:49:07 +0000309 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000310 {
311 profiler.stop();
312 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100313 }
314
315 test_case->do_teardown();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100316
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100317 profiler.test_stop();
318
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100319 // Change status to success if no error has happend
320 if(result.status == TestResult::Status::NOT_RUN)
321 {
322 result.status = TestResult::Status::SUCCESS;
323 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100324 }
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100325 catch(const FileNotFound &error)
326 {
327 if(_error_on_missing_assets)
328 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100329 if(_log_level >= LogLevel::ERRORS)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100330 {
331 TestError test_error(error.what(), LogLevel::ERRORS);
Giorgio Arena2d099932017-10-25 15:47:08 +0100332 func_on_all_printers([&](Printer * p)
333 {
334 p->print_error(test_error, is_expected_failure);
335 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100336 }
337
338 result.status = TestResult::Status::FAILED;
339
340 if(_throw_errors)
341 {
342 throw;
343 }
344 }
345 else
346 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100347 if(_log_level >= LogLevel::DEBUG)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100348 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100349 func_on_all_printers([&](Printer * p)
350 {
351 p->print_info(error.what());
352 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100353 }
354
355 result.status = TestResult::Status::NOT_RUN;
356 }
357 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100358 catch(const TestError &error)
359 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100360 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100361 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100362 func_on_all_printers([&](Printer * p)
363 {
364 p->print_error(error, is_expected_failure);
365 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100366 }
367
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100368 result.status = TestResult::Status::FAILED;
369
370 if(_throw_errors)
371 {
372 throw;
373 }
374 }
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100375#ifdef ARM_COMPUTE_CL
376 catch(const ::cl::Error &error)
377 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100378 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100379 {
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100380 std::stringstream stream;
381 stream << "Error code: " << error.err();
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100382 TestError test_error(error.what(), LogLevel::ERRORS, stream.str());
Giorgio Arena2d099932017-10-25 15:47:08 +0100383 func_on_all_printers([&](Printer * p)
384 {
385 p->print_error(test_error, is_expected_failure);
386 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100387 }
388
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100389 result.status = TestResult::Status::FAILED;
390
391 if(_throw_errors)
392 {
393 throw;
394 }
395 }
396#endif /* ARM_COMPUTE_CL */
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100397 catch(const std::exception &error)
398 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100399 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100400 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100401 func_on_all_printers([&](Printer * p)
402 {
403 p->print_error(error, is_expected_failure);
404 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100405 }
406
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100407 result.status = TestResult::Status::CRASHED;
408
409 if(_throw_errors)
410 {
411 throw;
412 }
413 }
414 catch(...)
415 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100416 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100417 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100418 func_on_all_printers([&](Printer * p)
419 {
420 p->print_error(TestError("Received unknown exception"), is_expected_failure);
421 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100422 }
423
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100424 result.status = TestResult::Status::CRASHED;
425
426 if(_throw_errors)
427 {
428 throw;
429 }
430 }
431 }
432 catch(const std::exception &error)
433 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100434 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100435 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100436 func_on_all_printers([&](Printer * p)
437 {
438 p->print_error(error, is_expected_failure);
439 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100440 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100441
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100442 result.status = TestResult::Status::CRASHED;
443
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100444 if(_throw_errors)
445 {
446 throw;
447 }
448 }
449 catch(...)
450 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100451 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100452 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100453 func_on_all_printers([&](Printer * p)
454 {
455 p->print_error(TestError("Received unknown exception"), is_expected_failure);
456 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100457 }
458
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100459 result.status = TestResult::Status::CRASHED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100460
461 if(_throw_errors)
462 {
463 throw;
464 }
465 }
466
Giorgio Arena2d099932017-10-25 15:47:08 +0100467 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100468 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100469 func_on_all_printers([](Printer * p)
470 {
471 p->print_errors_footer();
472 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100473 }
474
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100475 _current_test_info = nullptr;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100476 _current_test_result = nullptr;
477
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100478 if(result.status == TestResult::Status::FAILED)
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100479 {
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100480 if(info.status == TestCaseFactory::Status::EXPECTED_FAILURE)
481 {
482 result.status = TestResult::Status::EXPECTED_FAILURE;
483 }
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100484 }
485
486 if(result.status == TestResult::Status::FAILED || result.status == TestResult::Status::CRASHED)
487 {
488 if(_stop_on_error)
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100489 {
490 throw std::runtime_error("Abort on first error.");
491 }
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100492 }
493
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100494 result.measurements = profiler.measurements();
495
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100496 set_test_result(info, result);
497 log_test_end(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100498}
499
500bool Framework::run()
501{
502 // Clear old test results
503 _test_results.clear();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100504
Giorgio Arena2d099932017-10-25 15:47:08 +0100505 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100506 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100507 func_on_all_printers([](Printer * p)
508 {
509 p->print_run_header();
510 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100511 }
512
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100513 const std::chrono::time_point<std::chrono::high_resolution_clock> start = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100514
515 int id = 0;
516
517 for(auto &test_factory : _test_factories)
518 {
519 const std::string test_case_name = test_factory->name();
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100520 const TestInfo test_info{ id, test_case_name, test_factory->mode(), test_factory->status() };
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100521
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100522 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100523 {
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100524 run_test(test_info, *test_factory);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100525 }
526
527 ++id;
528 }
529
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100530 const std::chrono::time_point<std::chrono::high_resolution_clock> end = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100531
Giorgio Arena2d099932017-10-25 15:47:08 +0100532 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100533 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100534 func_on_all_printers([](Printer * p)
535 {
536 p->print_run_footer();
537 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100538 }
539
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100540 auto runtime = std::chrono::duration_cast<std::chrono::seconds>(end - start);
541 std::map<TestResult::Status, int> results = count_test_results();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100542
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100543 if(_log_level > LogLevel::NONE)
544 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100545 std::cout << "Executed " << _test_results.size() << " test(s) ("
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100546 << results[TestResult::Status::SUCCESS] << " passed, "
547 << results[TestResult::Status::EXPECTED_FAILURE] << " expected failures, "
548 << results[TestResult::Status::FAILED] << " failed, "
549 << results[TestResult::Status::CRASHED] << " crashed, "
550 << results[TestResult::Status::DISABLED] << " disabled) in " << runtime.count() << " second(s)\n";
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100551 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100552
steniu013e05e4e2017-08-25 17:18:01 +0100553 int num_successful_tests = results[TestResult::Status::SUCCESS] + results[TestResult::Status::EXPECTED_FAILURE] + results[TestResult::Status::DISABLED];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100554
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100555 return (static_cast<unsigned int>(num_successful_tests) == _test_results.size());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100556}
557
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100558void Framework::set_test_result(TestInfo info, TestResult result)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100559{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100560 _test_results.emplace(std::move(info), std::move(result));
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100561}
562
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100563void Framework::print_test_results(Printer &printer) const
564{
565 printer.print_run_header();
566
567 for(const auto &test : _test_results)
568 {
569 printer.print_test_header(test.first);
570 printer.print_measurements(test.second.measurements);
571 printer.print_test_footer();
572 }
573
574 printer.print_run_footer();
575}
576
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100577Profiler Framework::get_profiler() const
578{
579 Profiler profiler;
580
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100581 const bool all_instruments = std::any_of(
582 _instruments.begin(),
583 _instruments.end(),
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000584 [](InstrumentsDescription type) -> bool { return type.first == InstrumentType::ALL; });
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100585
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000586 auto is_selected = [&](InstrumentsDescription instrument) -> bool
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100587 {
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000588 return std::find_if(_instruments.begin(), _instruments.end(), [&](InstrumentsDescription type) -> bool {
589 const auto group = static_cast<InstrumentType>(static_cast<uint64_t>(type.first) & 0xFF00);
590 return (group == instrument.first) && (instrument.second == type.second);
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100591 })
592 != _instruments.end();
593 };
594
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100595 for(const auto &instrument : _available_instruments)
596 {
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100597 if(all_instruments || is_selected(instrument.first))
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100598 {
599 profiler.add(instrument.second());
600 }
601 }
602
603 return profiler;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100604}
605
Giorgio Arena2d099932017-10-25 15:47:08 +0100606void Framework::add_printer(Printer *printer)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100607{
Giorgio Arena2d099932017-10-25 15:47:08 +0100608 _printers.push_back(printer);
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100609}
610
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100611std::vector<TestInfo> Framework::test_infos() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100612{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100613 std::vector<TestInfo> ids;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100614
615 int id = 0;
616
617 for(const auto &factory : _test_factories)
618 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100619 TestInfo test_info{ id, factory->name(), factory->mode(), factory->status() };
620
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100621 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100622 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100623 ids.emplace_back(std::move(test_info));
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100624 }
625
626 ++id;
627 }
628
629 return ids;
630}
steniu01172c58d2017-08-31 13:49:08 +0100631
632LogLevel Framework::log_level() const
633{
634 return _log_level;
635}
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100636} // namespace framework
637} // namespace test
638} // namespace arm_compute