blob: 81e16c8fb7dded3d3c203c0e744709279ce3751e [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 Barbier35aa6a32018-04-23 16:12:12 +010062 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::NONE), Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::NONE>);
63 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1K),
64 Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1K>);
65 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1M),
66 Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1M>);
Anthony Barbiere8895f82017-11-23 16:58:52 +000067#endif /* ARM_COMPUTE_CL */
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010068}
69
Giorgio Arenace58a9f2017-10-31 17:59:17 +000070std::set<InstrumentsDescription> Framework::available_instruments() const
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010071{
Giorgio Arenace58a9f2017-10-31 17:59:17 +000072 std::set<InstrumentsDescription> types;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010073
74 for(const auto &instrument : _available_instruments)
75 {
76 types.emplace(instrument.first);
77 }
78
79 return types;
80}
81
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010082std::map<TestResult::Status, int> Framework::count_test_results() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010083{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010084 std::map<TestResult::Status, int> counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010085
86 for(const auto &test : _test_results)
87 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010088 ++counts[test.second.status];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010089 }
90
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010091 return counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010092}
93
94Framework &Framework::get()
95{
96 static Framework instance;
97 return instance;
98}
99
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000100void Framework::init(const std::vector<framework::InstrumentsDescription> &instruments, int num_iterations, DatasetMode mode, const std::string &name_filter, const std::string &id_filter,
101 LogLevel log_level)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100102{
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100103 _test_filter = TestFilter(mode, name_filter, id_filter);
104 _num_iterations = num_iterations;
105 _log_level = log_level;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100106
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000107 _instruments = std::set<framework::InstrumentsDescription>(instruments.begin(), instruments.end());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100108}
109
110std::string Framework::current_suite_name() const
111{
112 return join(_test_suite_name.cbegin(), _test_suite_name.cend(), "/");
113}
114
115void Framework::push_suite(std::string name)
116{
117 _test_suite_name.emplace_back(std::move(name));
118}
119
120void Framework::pop_suite()
121{
122 _test_suite_name.pop_back();
123}
124
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100125void Framework::add_test_info(std::string info)
126{
127 _test_info.emplace_back(std::move(info));
128}
129
130void Framework::clear_test_info()
131{
132 _test_info.clear();
133}
134
135bool Framework::has_test_info() const
136{
137 return !_test_info.empty();
138}
139
140void Framework::print_test_info(std::ostream &os) const
141{
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100142 if(!_test_info.empty())
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100143 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100144 os << "CONTEXT:\n";
145
146 for(const auto &str : _test_info)
147 {
148 os << " " << str << "\n";
149 }
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100150 }
151}
152
Giorgio Arena2d099932017-10-25 15:47:08 +0100153template <typename F>
154void Framework::func_on_all_printers(F &&func)
155{
156 std::for_each(std::begin(_printers), std::end(_printers), func);
157}
158
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100159void Framework::log_test_start(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100160{
Giorgio Arena2d099932017-10-25 15:47:08 +0100161 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100162 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100163 func_on_all_printers([&](Printer * p)
164 {
165 p->print_test_header(info);
166 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100167 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100168}
169
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100170void Framework::log_test_skipped(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100171{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100172 static_cast<void>(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100173}
174
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100175void Framework::log_test_end(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100176{
Giorgio Arena2d099932017-10-25 15:47:08 +0100177 if(_log_level >= LogLevel::MEASUREMENTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100178 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100179 func_on_all_printers([&](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100180 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100181 p->print_measurements(_test_results.at(info).measurements);
182 });
183 }
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100184
Giorgio Arena2d099932017-10-25 15:47:08 +0100185 if(_log_level >= LogLevel::TESTS)
186 {
187 func_on_all_printers([](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100188 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100189 p->print_test_footer();
190 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100191 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100192}
193
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100194void Framework::log_failed_expectation(const TestError &error)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100195{
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100196 ARM_COMPUTE_ERROR_ON(_current_test_info == nullptr);
197 ARM_COMPUTE_ERROR_ON(_current_test_result == nullptr);
198
199 const bool is_expected_failure = _current_test_info->status == TestCaseFactory::Status::EXPECTED_FAILURE;
200
Giorgio Arena2d099932017-10-25 15:47:08 +0100201 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100202 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100203 func_on_all_printers([&](Printer * p)
204 {
205 p->print_error(error, is_expected_failure);
206 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100207 }
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100208
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100209 _current_test_result->status = TestResult::Status::FAILED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100210}
211
steniu01172c58d2017-08-31 13:49:08 +0100212void Framework::log_info(const std::string &info)
213{
Giorgio Arena2d099932017-10-25 15:47:08 +0100214 if(_log_level >= LogLevel::DEBUG)
steniu01172c58d2017-08-31 13:49:08 +0100215 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100216 func_on_all_printers([&](Printer * p)
217 {
218 p->print_info(info);
219 });
steniu01172c58d2017-08-31 13:49:08 +0100220 }
221}
222
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100223int Framework::num_iterations() const
224{
225 return _num_iterations;
226}
227
228void Framework::set_num_iterations(int num_iterations)
229{
230 _num_iterations = num_iterations;
231}
232
233void Framework::set_throw_errors(bool throw_errors)
234{
235 _throw_errors = throw_errors;
236}
237
238bool Framework::throw_errors() const
239{
240 return _throw_errors;
241}
242
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100243void Framework::set_stop_on_error(bool stop_on_error)
244{
245 _stop_on_error = stop_on_error;
246}
247
248bool Framework::stop_on_error() const
249{
250 return _stop_on_error;
251}
252
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100253void Framework::set_error_on_missing_assets(bool error_on_missing_assets)
254{
255 _error_on_missing_assets = error_on_missing_assets;
256}
257
258bool Framework::error_on_missing_assets() const
259{
260 return _error_on_missing_assets;
261}
262
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100263void Framework::run_test(const TestInfo &info, TestCaseFactory &test_factory)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100264{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100265 if(test_factory.status() == TestCaseFactory::Status::DISABLED)
266 {
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100267 log_test_skipped(info);
268 set_test_result(info, TestResult(TestResult::Status::DISABLED));
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100269 return;
270 }
271
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100272 log_test_start(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100273
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100274 Profiler profiler = get_profiler();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100275 TestResult result(TestResult::Status::NOT_RUN);
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100276
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100277 _current_test_info = &info;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100278 _current_test_result = &result;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100279
Giorgio Arena2d099932017-10-25 15:47:08 +0100280 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100281 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100282 func_on_all_printers([](Printer * p)
283 {
284 p->print_errors_header();
285 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100286 }
287
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100288 const bool is_expected_failure = info.status == TestCaseFactory::Status::EXPECTED_FAILURE;
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100289
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100290 try
291 {
292 std::unique_ptr<TestCase> test_case = test_factory.make();
293
294 try
295 {
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100296 profiler.test_start();
297
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100298 test_case->do_setup();
299
300 for(int i = 0; i < _num_iterations; ++i)
301 {
Anthony Barbier61941452017-11-21 17:49:07 +0000302 //Start the profiler if:
303 //- there is only one iteration
304 //- it's not the first iteration of a multi-iterations run.
305 //
306 //Reason: if the CLTuner is enabled then the first run will be really messy
307 //as each kernel will be executed several times, messing up the instruments like OpenCL timers.
308 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000309 {
310 profiler.start();
311 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100312 test_case->do_run();
Joel Liang1c5ffd62017-12-28 10:09:51 +0800313 test_case->do_sync();
Anthony Barbier61941452017-11-21 17:49:07 +0000314 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000315 {
316 profiler.stop();
317 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100318 }
319
320 test_case->do_teardown();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100321
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100322 profiler.test_stop();
323
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100324 // Change status to success if no error has happend
325 if(result.status == TestResult::Status::NOT_RUN)
326 {
327 result.status = TestResult::Status::SUCCESS;
328 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100329 }
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100330 catch(const FileNotFound &error)
331 {
332 if(_error_on_missing_assets)
333 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100334 if(_log_level >= LogLevel::ERRORS)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100335 {
336 TestError test_error(error.what(), LogLevel::ERRORS);
Giorgio Arena2d099932017-10-25 15:47:08 +0100337 func_on_all_printers([&](Printer * p)
338 {
339 p->print_error(test_error, is_expected_failure);
340 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100341 }
342
343 result.status = TestResult::Status::FAILED;
344
345 if(_throw_errors)
346 {
347 throw;
348 }
349 }
350 else
351 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100352 if(_log_level >= LogLevel::DEBUG)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100353 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100354 func_on_all_printers([&](Printer * p)
355 {
356 p->print_info(error.what());
357 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100358 }
359
360 result.status = TestResult::Status::NOT_RUN;
361 }
362 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100363 catch(const TestError &error)
364 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100365 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100366 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100367 func_on_all_printers([&](Printer * p)
368 {
369 p->print_error(error, is_expected_failure);
370 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100371 }
372
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100373 result.status = TestResult::Status::FAILED;
374
375 if(_throw_errors)
376 {
377 throw;
378 }
379 }
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100380#ifdef ARM_COMPUTE_CL
381 catch(const ::cl::Error &error)
382 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100383 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100384 {
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100385 std::stringstream stream;
386 stream << "Error code: " << error.err();
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100387 TestError test_error(error.what(), LogLevel::ERRORS, stream.str());
Giorgio Arena2d099932017-10-25 15:47:08 +0100388 func_on_all_printers([&](Printer * p)
389 {
390 p->print_error(test_error, is_expected_failure);
391 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100392 }
393
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100394 result.status = TestResult::Status::FAILED;
395
396 if(_throw_errors)
397 {
398 throw;
399 }
400 }
401#endif /* ARM_COMPUTE_CL */
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100402 catch(const std::exception &error)
403 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100404 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100405 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100406 func_on_all_printers([&](Printer * p)
407 {
408 p->print_error(error, is_expected_failure);
409 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100410 }
411
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100412 result.status = TestResult::Status::CRASHED;
413
414 if(_throw_errors)
415 {
416 throw;
417 }
418 }
419 catch(...)
420 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100421 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100422 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100423 func_on_all_printers([&](Printer * p)
424 {
425 p->print_error(TestError("Received unknown exception"), is_expected_failure);
426 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100427 }
428
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100429 result.status = TestResult::Status::CRASHED;
430
431 if(_throw_errors)
432 {
433 throw;
434 }
435 }
436 }
437 catch(const std::exception &error)
438 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100439 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100440 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100441 func_on_all_printers([&](Printer * p)
442 {
443 p->print_error(error, is_expected_failure);
444 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100445 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100446
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100447 result.status = TestResult::Status::CRASHED;
448
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100449 if(_throw_errors)
450 {
451 throw;
452 }
453 }
454 catch(...)
455 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100456 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100457 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100458 func_on_all_printers([&](Printer * p)
459 {
460 p->print_error(TestError("Received unknown exception"), is_expected_failure);
461 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100462 }
463
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100464 result.status = TestResult::Status::CRASHED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100465
466 if(_throw_errors)
467 {
468 throw;
469 }
470 }
471
Giorgio Arena2d099932017-10-25 15:47:08 +0100472 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100473 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100474 func_on_all_printers([](Printer * p)
475 {
476 p->print_errors_footer();
477 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100478 }
479
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100480 _current_test_info = nullptr;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100481 _current_test_result = nullptr;
482
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100483 if(result.status == TestResult::Status::FAILED)
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100484 {
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100485 if(info.status == TestCaseFactory::Status::EXPECTED_FAILURE)
486 {
487 result.status = TestResult::Status::EXPECTED_FAILURE;
488 }
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100489 }
490
491 if(result.status == TestResult::Status::FAILED || result.status == TestResult::Status::CRASHED)
492 {
493 if(_stop_on_error)
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100494 {
495 throw std::runtime_error("Abort on first error.");
496 }
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100497 }
498
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100499 result.measurements = profiler.measurements();
500
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100501 set_test_result(info, result);
502 log_test_end(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100503}
504
505bool Framework::run()
506{
507 // Clear old test results
508 _test_results.clear();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100509
Giorgio Arena2d099932017-10-25 15:47:08 +0100510 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100511 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100512 func_on_all_printers([](Printer * p)
513 {
514 p->print_run_header();
515 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100516 }
517
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100518 const std::chrono::time_point<std::chrono::high_resolution_clock> start = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100519
520 int id = 0;
521
522 for(auto &test_factory : _test_factories)
523 {
524 const std::string test_case_name = test_factory->name();
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100525 const TestInfo test_info{ id, test_case_name, test_factory->mode(), test_factory->status() };
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100526
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100527 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100528 {
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100529 run_test(test_info, *test_factory);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100530 }
531
532 ++id;
533 }
534
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100535 const std::chrono::time_point<std::chrono::high_resolution_clock> end = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100536
Giorgio Arena2d099932017-10-25 15:47:08 +0100537 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100538 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100539 func_on_all_printers([](Printer * p)
540 {
541 p->print_run_footer();
542 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100543 }
544
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100545 auto runtime = std::chrono::duration_cast<std::chrono::seconds>(end - start);
546 std::map<TestResult::Status, int> results = count_test_results();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100547
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100548 if(_log_level > LogLevel::NONE)
549 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100550 std::cout << "Executed " << _test_results.size() << " test(s) ("
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100551 << results[TestResult::Status::SUCCESS] << " passed, "
552 << results[TestResult::Status::EXPECTED_FAILURE] << " expected failures, "
553 << results[TestResult::Status::FAILED] << " failed, "
554 << results[TestResult::Status::CRASHED] << " crashed, "
555 << results[TestResult::Status::DISABLED] << " disabled) in " << runtime.count() << " second(s)\n";
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100556 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100557
steniu013e05e4e2017-08-25 17:18:01 +0100558 int num_successful_tests = results[TestResult::Status::SUCCESS] + results[TestResult::Status::EXPECTED_FAILURE] + results[TestResult::Status::DISABLED];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100559
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100560 return (static_cast<unsigned int>(num_successful_tests) == _test_results.size());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100561}
562
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100563void Framework::set_test_result(TestInfo info, TestResult result)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100564{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100565 _test_results.emplace(std::move(info), std::move(result));
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100566}
567
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100568void Framework::print_test_results(Printer &printer) const
569{
570 printer.print_run_header();
571
572 for(const auto &test : _test_results)
573 {
574 printer.print_test_header(test.first);
575 printer.print_measurements(test.second.measurements);
576 printer.print_test_footer();
577 }
578
579 printer.print_run_footer();
580}
581
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100582Profiler Framework::get_profiler() const
583{
584 Profiler profiler;
585
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100586 const bool all_instruments = std::any_of(
587 _instruments.begin(),
588 _instruments.end(),
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000589 [](InstrumentsDescription type) -> bool { return type.first == InstrumentType::ALL; });
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100590
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000591 auto is_selected = [&](InstrumentsDescription instrument) -> bool
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100592 {
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000593 return std::find_if(_instruments.begin(), _instruments.end(), [&](InstrumentsDescription type) -> bool {
594 const auto group = static_cast<InstrumentType>(static_cast<uint64_t>(type.first) & 0xFF00);
595 return (group == instrument.first) && (instrument.second == type.second);
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100596 })
597 != _instruments.end();
598 };
599
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100600 for(const auto &instrument : _available_instruments)
601 {
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100602 if(all_instruments || is_selected(instrument.first))
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100603 {
604 profiler.add(instrument.second());
605 }
606 }
607
608 return profiler;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100609}
610
Giorgio Arena2d099932017-10-25 15:47:08 +0100611void Framework::add_printer(Printer *printer)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100612{
Giorgio Arena2d099932017-10-25 15:47:08 +0100613 _printers.push_back(printer);
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100614}
615
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100616std::vector<TestInfo> Framework::test_infos() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100617{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100618 std::vector<TestInfo> ids;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100619
620 int id = 0;
621
622 for(const auto &factory : _test_factories)
623 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100624 TestInfo test_info{ id, factory->name(), factory->mode(), factory->status() };
625
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100626 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100627 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100628 ids.emplace_back(std::move(test_info));
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100629 }
630
631 ++id;
632 }
633
634 return ids;
635}
steniu01172c58d2017-08-31 13:49:08 +0100636
637LogLevel Framework::log_level() const
638{
639 return _log_level;
640}
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100641} // namespace framework
642} // namespace test
643} // namespace arm_compute