blob: eea77452304926e89c95e29df1c08ad7b14f6634 [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"
Gian Marco Iodiced30ed112018-05-16 12:01:14 +010027#ifdef ARM_COMPUTE_CL
28#include "arm_compute/runtime/CL/CLScheduler.h"
29#endif /* ARM_COMPUTE_CL */
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010030
31#include <chrono>
32#include <iostream>
33#include <sstream>
34#include <type_traits>
35
36namespace arm_compute
37{
38namespace test
39{
40namespace framework
41{
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010042Framework::Framework()
43{
Giorgio Arenace58a9f2017-10-31 17:59:17 +000044 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::NONE), Instrument::make_instrument<WallClockTimer, ScaleFactor::NONE>);
45 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<WallClockTimer, ScaleFactor::TIME_MS>);
46 _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 +000047 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::NONE), Instrument::make_instrument<SchedulerTimer, ScaleFactor::NONE>);
48 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<SchedulerTimer, ScaleFactor::TIME_MS>);
49 _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 +010050#ifdef PMU_ENABLED
Giorgio Arenace58a9f2017-10-31 17:59:17 +000051 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::NONE), Instrument::make_instrument<PMUCounter, ScaleFactor::NONE>);
52 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::SCALE_1K), Instrument::make_instrument<PMUCounter, ScaleFactor::SCALE_1K>);
53 _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 +010054#endif /* PMU_ENABLED */
Moritz Pflanzer45634b42017-08-30 12:48:18 +010055#ifdef MALI_ENABLED
Giorgio Arenace58a9f2017-10-31 17:59:17 +000056 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::NONE), Instrument::make_instrument<MaliCounter, ScaleFactor::NONE>);
57 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::SCALE_1K), Instrument::make_instrument<MaliCounter, ScaleFactor::SCALE_1K>);
58 _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 +010059#endif /* MALI_ENABLED */
Anthony Barbiere8895f82017-11-23 16:58:52 +000060#ifdef ARM_COMPUTE_CL
Giorgio Arenace58a9f2017-10-31 17:59:17 +000061 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::NONE), Instrument::make_instrument<OpenCLTimer, ScaleFactor::NONE>);
62 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_US), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_US>);
63 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_MS>);
64 _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 +010065 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::NONE), Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::NONE>);
66 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1K),
67 Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1K>);
68 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1M),
69 Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1M>);
Anthony Barbiere8895f82017-11-23 16:58:52 +000070#endif /* ARM_COMPUTE_CL */
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010071}
72
Giorgio Arenace58a9f2017-10-31 17:59:17 +000073std::set<InstrumentsDescription> Framework::available_instruments() const
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010074{
Giorgio Arenace58a9f2017-10-31 17:59:17 +000075 std::set<InstrumentsDescription> types;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010076
77 for(const auto &instrument : _available_instruments)
78 {
79 types.emplace(instrument.first);
80 }
81
82 return types;
83}
84
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010085std::map<TestResult::Status, int> Framework::count_test_results() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010086{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010087 std::map<TestResult::Status, int> counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010088
89 for(const auto &test : _test_results)
90 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010091 ++counts[test.second.status];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010092 }
93
Moritz Pflanzerbf234e02017-07-24 15:04:14 +010094 return counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010095}
96
97Framework &Framework::get()
98{
99 static Framework instance;
100 return instance;
101}
102
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000103void Framework::init(const std::vector<framework::InstrumentsDescription> &instruments, int num_iterations, DatasetMode mode, const std::string &name_filter, const std::string &id_filter,
104 LogLevel log_level)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100105{
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100106 _test_filter = TestFilter(mode, name_filter, id_filter);
107 _num_iterations = num_iterations;
108 _log_level = log_level;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100109
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000110 _instruments = std::set<framework::InstrumentsDescription>(instruments.begin(), instruments.end());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100111}
112
113std::string Framework::current_suite_name() const
114{
115 return join(_test_suite_name.cbegin(), _test_suite_name.cend(), "/");
116}
117
118void Framework::push_suite(std::string name)
119{
120 _test_suite_name.emplace_back(std::move(name));
121}
122
123void Framework::pop_suite()
124{
125 _test_suite_name.pop_back();
126}
127
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100128void Framework::add_test_info(std::string info)
129{
130 _test_info.emplace_back(std::move(info));
131}
132
133void Framework::clear_test_info()
134{
135 _test_info.clear();
136}
137
138bool Framework::has_test_info() const
139{
140 return !_test_info.empty();
141}
142
143void Framework::print_test_info(std::ostream &os) const
144{
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100145 if(!_test_info.empty())
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100146 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100147 os << "CONTEXT:\n";
148
149 for(const auto &str : _test_info)
150 {
151 os << " " << str << "\n";
152 }
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100153 }
154}
155
Giorgio Arena2d099932017-10-25 15:47:08 +0100156template <typename F>
157void Framework::func_on_all_printers(F &&func)
158{
159 std::for_each(std::begin(_printers), std::end(_printers), func);
160}
161
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100162void Framework::log_test_start(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100163{
Giorgio Arena2d099932017-10-25 15:47:08 +0100164 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100165 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100166 func_on_all_printers([&](Printer * p)
167 {
168 p->print_test_header(info);
169 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100170 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100171}
172
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100173void Framework::log_test_skipped(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100174{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100175 static_cast<void>(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100176}
177
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100178void Framework::log_test_end(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100179{
Giorgio Arena2d099932017-10-25 15:47:08 +0100180 if(_log_level >= LogLevel::MEASUREMENTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100181 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100182 func_on_all_printers([&](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100183 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100184 p->print_measurements(_test_results.at(info).measurements);
185 });
186 }
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100187
Giorgio Arena2d099932017-10-25 15:47:08 +0100188 if(_log_level >= LogLevel::TESTS)
189 {
190 func_on_all_printers([](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100191 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100192 p->print_test_footer();
193 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100194 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100195}
196
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100197void Framework::log_failed_expectation(const TestError &error)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100198{
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100199 ARM_COMPUTE_ERROR_ON(_current_test_info == nullptr);
200 ARM_COMPUTE_ERROR_ON(_current_test_result == nullptr);
201
202 const bool is_expected_failure = _current_test_info->status == TestCaseFactory::Status::EXPECTED_FAILURE;
203
Giorgio Arena2d099932017-10-25 15:47:08 +0100204 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100205 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100206 func_on_all_printers([&](Printer * p)
207 {
208 p->print_error(error, is_expected_failure);
209 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100210 }
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100211
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100212 _current_test_result->status = TestResult::Status::FAILED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100213}
214
steniu01172c58d2017-08-31 13:49:08 +0100215void Framework::log_info(const std::string &info)
216{
Giorgio Arena2d099932017-10-25 15:47:08 +0100217 if(_log_level >= LogLevel::DEBUG)
steniu01172c58d2017-08-31 13:49:08 +0100218 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100219 func_on_all_printers([&](Printer * p)
220 {
221 p->print_info(info);
222 });
steniu01172c58d2017-08-31 13:49:08 +0100223 }
224}
225
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100226int Framework::num_iterations() const
227{
228 return _num_iterations;
229}
230
231void Framework::set_num_iterations(int num_iterations)
232{
233 _num_iterations = num_iterations;
234}
235
236void Framework::set_throw_errors(bool throw_errors)
237{
238 _throw_errors = throw_errors;
239}
240
241bool Framework::throw_errors() const
242{
243 return _throw_errors;
244}
245
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100246void Framework::set_stop_on_error(bool stop_on_error)
247{
248 _stop_on_error = stop_on_error;
249}
250
251bool Framework::stop_on_error() const
252{
253 return _stop_on_error;
254}
255
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100256void Framework::set_error_on_missing_assets(bool error_on_missing_assets)
257{
258 _error_on_missing_assets = error_on_missing_assets;
259}
260
261bool Framework::error_on_missing_assets() const
262{
263 return _error_on_missing_assets;
264}
265
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100266void Framework::run_test(const TestInfo &info, TestCaseFactory &test_factory)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100267{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100268 if(test_factory.status() == TestCaseFactory::Status::DISABLED)
269 {
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100270 log_test_skipped(info);
271 set_test_result(info, TestResult(TestResult::Status::DISABLED));
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100272 return;
273 }
274
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100275 log_test_start(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100276
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100277 Profiler profiler = get_profiler();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100278 TestResult result(TestResult::Status::NOT_RUN);
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100279
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100280 _current_test_info = &info;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100281 _current_test_result = &result;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100282
Giorgio Arena2d099932017-10-25 15:47:08 +0100283 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100284 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100285 func_on_all_printers([](Printer * p)
286 {
287 p->print_errors_header();
288 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100289 }
290
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100291 const bool is_expected_failure = info.status == TestCaseFactory::Status::EXPECTED_FAILURE;
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100292
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100293 try
294 {
295 std::unique_ptr<TestCase> test_case = test_factory.make();
296
297 try
298 {
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100299 profiler.test_start();
300
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100301 test_case->do_setup();
302
303 for(int i = 0; i < _num_iterations; ++i)
304 {
Anthony Barbier61941452017-11-21 17:49:07 +0000305 //Start the profiler if:
306 //- there is only one iteration
307 //- it's not the first iteration of a multi-iterations run.
308 //
309 //Reason: if the CLTuner is enabled then the first run will be really messy
310 //as each kernel will be executed several times, messing up the instruments like OpenCL timers.
311 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000312 {
313 profiler.start();
314 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100315 test_case->do_run();
Joel Liang1c5ffd62017-12-28 10:09:51 +0800316 test_case->do_sync();
Anthony Barbier61941452017-11-21 17:49:07 +0000317 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000318 {
319 profiler.stop();
320 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100321 }
322
323 test_case->do_teardown();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100324
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100325 profiler.test_stop();
326
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100327 // Change status to success if no error has happend
328 if(result.status == TestResult::Status::NOT_RUN)
329 {
330 result.status = TestResult::Status::SUCCESS;
331 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100332 }
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100333 catch(const FileNotFound &error)
334 {
335 if(_error_on_missing_assets)
336 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100337 if(_log_level >= LogLevel::ERRORS)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100338 {
339 TestError test_error(error.what(), LogLevel::ERRORS);
Giorgio Arena2d099932017-10-25 15:47:08 +0100340 func_on_all_printers([&](Printer * p)
341 {
342 p->print_error(test_error, is_expected_failure);
343 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100344 }
345
346 result.status = TestResult::Status::FAILED;
347
348 if(_throw_errors)
349 {
350 throw;
351 }
352 }
353 else
354 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100355 if(_log_level >= LogLevel::DEBUG)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100356 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100357 func_on_all_printers([&](Printer * p)
358 {
359 p->print_info(error.what());
360 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100361 }
362
363 result.status = TestResult::Status::NOT_RUN;
364 }
365 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100366 catch(const TestError &error)
367 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100368 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100369 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100370 func_on_all_printers([&](Printer * p)
371 {
372 p->print_error(error, is_expected_failure);
373 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100374 }
375
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100376 result.status = TestResult::Status::FAILED;
377
378 if(_throw_errors)
379 {
380 throw;
381 }
382 }
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100383#ifdef ARM_COMPUTE_CL
384 catch(const ::cl::Error &error)
385 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100386 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100387 {
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100388 std::stringstream stream;
389 stream << "Error code: " << error.err();
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100390 TestError test_error(error.what(), LogLevel::ERRORS, stream.str());
Giorgio Arena2d099932017-10-25 15:47:08 +0100391 func_on_all_printers([&](Printer * p)
392 {
393 p->print_error(test_error, is_expected_failure);
394 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100395 }
396
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100397 result.status = TestResult::Status::FAILED;
398
399 if(_throw_errors)
400 {
401 throw;
402 }
403 }
404#endif /* ARM_COMPUTE_CL */
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100405 catch(const std::exception &error)
406 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100407 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100408 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100409 func_on_all_printers([&](Printer * p)
410 {
411 p->print_error(error, is_expected_failure);
412 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100413 }
414
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100415 result.status = TestResult::Status::CRASHED;
416
417 if(_throw_errors)
418 {
419 throw;
420 }
421 }
422 catch(...)
423 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100424 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100425 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100426 func_on_all_printers([&](Printer * p)
427 {
428 p->print_error(TestError("Received unknown exception"), is_expected_failure);
429 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100430 }
431
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100432 result.status = TestResult::Status::CRASHED;
433
434 if(_throw_errors)
435 {
436 throw;
437 }
438 }
439 }
440 catch(const std::exception &error)
441 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100442 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100443 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100444 func_on_all_printers([&](Printer * p)
445 {
446 p->print_error(error, is_expected_failure);
447 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100448 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100449
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100450 result.status = TestResult::Status::CRASHED;
451
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100452 if(_throw_errors)
453 {
454 throw;
455 }
456 }
457 catch(...)
458 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100459 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100460 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100461 func_on_all_printers([&](Printer * p)
462 {
463 p->print_error(TestError("Received unknown exception"), is_expected_failure);
464 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100465 }
466
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100467 result.status = TestResult::Status::CRASHED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100468
469 if(_throw_errors)
470 {
471 throw;
472 }
473 }
474
Giorgio Arena2d099932017-10-25 15:47:08 +0100475 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100476 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100477 func_on_all_printers([](Printer * p)
478 {
479 p->print_errors_footer();
480 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100481 }
482
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100483 _current_test_info = nullptr;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100484 _current_test_result = nullptr;
485
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100486 if(result.status == TestResult::Status::FAILED)
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100487 {
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100488 if(info.status == TestCaseFactory::Status::EXPECTED_FAILURE)
489 {
490 result.status = TestResult::Status::EXPECTED_FAILURE;
491 }
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100492 }
493
494 if(result.status == TestResult::Status::FAILED || result.status == TestResult::Status::CRASHED)
495 {
496 if(_stop_on_error)
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100497 {
498 throw std::runtime_error("Abort on first error.");
499 }
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100500 }
501
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100502 result.measurements = profiler.measurements();
503
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100504 set_test_result(info, result);
505 log_test_end(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100506}
507
508bool Framework::run()
509{
510 // Clear old test results
511 _test_results.clear();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100512
Giorgio Arena2d099932017-10-25 15:47:08 +0100513 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100514 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100515 func_on_all_printers([](Printer * p)
516 {
517 p->print_run_header();
518 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100519 }
520
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100521 const std::chrono::time_point<std::chrono::high_resolution_clock> start = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100522
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100523 int id = 0;
524 int id_run_test = 0;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100525
526 for(auto &test_factory : _test_factories)
527 {
528 const std::string test_case_name = test_factory->name();
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100529 const TestInfo test_info{ id, test_case_name, test_factory->mode(), test_factory->status() };
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100530
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100531 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100532 {
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100533#ifdef ARM_COMPUTE_CL
534 // Every 5000 tests, reset the OpenCL context to release the allocated memory
Anthony Barbier80040bc2018-08-21 16:16:04 +0100535 if(opencl_is_available() && (id_run_test % 5000) == 0)
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100536 {
Georgios Pinitasdf473ea2018-05-31 18:53:52 +0100537 auto ctx_properties = CLScheduler::get().context().getInfo<CL_CONTEXT_PROPERTIES>(nullptr);
538 auto queue_properties = CLScheduler::get().queue().getInfo<CL_QUEUE_PROPERTIES>(nullptr);
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100539
Georgios Pinitasdf473ea2018-05-31 18:53:52 +0100540 cl::Context new_ctx = cl::Context(CL_DEVICE_TYPE_DEFAULT, ctx_properties.data());
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100541 cl::CommandQueue new_queue = cl::CommandQueue(new_ctx, CLKernelLibrary::get().get_device(), queue_properties);
Georgios Pinitasdf473ea2018-05-31 18:53:52 +0100542
543 CLKernelLibrary::get().clear_programs_cache();
544 CLScheduler::get().set_context(new_ctx);
545 CLScheduler::get().set_queue(new_queue);
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100546 }
547#endif // ARM_COMPUTE_CL
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100548 run_test(test_info, *test_factory);
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100549
550 ++id_run_test;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100551 }
552
553 ++id;
554 }
555
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100556 const std::chrono::time_point<std::chrono::high_resolution_clock> end = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100557
Giorgio Arena2d099932017-10-25 15:47:08 +0100558 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100559 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100560 func_on_all_printers([](Printer * p)
561 {
562 p->print_run_footer();
563 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100564 }
565
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100566 auto runtime = std::chrono::duration_cast<std::chrono::seconds>(end - start);
567 std::map<TestResult::Status, int> results = count_test_results();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100568
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100569 if(_log_level > LogLevel::NONE)
570 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100571 std::cout << "Executed " << _test_results.size() << " test(s) ("
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100572 << results[TestResult::Status::SUCCESS] << " passed, "
573 << results[TestResult::Status::EXPECTED_FAILURE] << " expected failures, "
574 << results[TestResult::Status::FAILED] << " failed, "
575 << results[TestResult::Status::CRASHED] << " crashed, "
576 << results[TestResult::Status::DISABLED] << " disabled) in " << runtime.count() << " second(s)\n";
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100577 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100578
steniu013e05e4e2017-08-25 17:18:01 +0100579 int num_successful_tests = results[TestResult::Status::SUCCESS] + results[TestResult::Status::EXPECTED_FAILURE] + results[TestResult::Status::DISABLED];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100580
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100581 return (static_cast<unsigned int>(num_successful_tests) == _test_results.size());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100582}
583
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100584void Framework::set_test_result(TestInfo info, TestResult result)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100585{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100586 _test_results.emplace(std::move(info), std::move(result));
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100587}
588
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100589void Framework::print_test_results(Printer &printer) const
590{
591 printer.print_run_header();
592
593 for(const auto &test : _test_results)
594 {
595 printer.print_test_header(test.first);
596 printer.print_measurements(test.second.measurements);
597 printer.print_test_footer();
598 }
599
600 printer.print_run_footer();
601}
602
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100603Profiler Framework::get_profiler() const
604{
605 Profiler profiler;
606
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100607 const bool all_instruments = std::any_of(
608 _instruments.begin(),
609 _instruments.end(),
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000610 [](InstrumentsDescription type) -> bool { return type.first == InstrumentType::ALL; });
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100611
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000612 auto is_selected = [&](InstrumentsDescription instrument) -> bool
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100613 {
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000614 return std::find_if(_instruments.begin(), _instruments.end(), [&](InstrumentsDescription type) -> bool {
615 const auto group = static_cast<InstrumentType>(static_cast<uint64_t>(type.first) & 0xFF00);
616 return (group == instrument.first) && (instrument.second == type.second);
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100617 })
618 != _instruments.end();
619 };
620
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100621 for(const auto &instrument : _available_instruments)
622 {
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100623 if(all_instruments || is_selected(instrument.first))
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100624 {
625 profiler.add(instrument.second());
626 }
627 }
628
629 return profiler;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100630}
631
Giorgio Arena2d099932017-10-25 15:47:08 +0100632void Framework::add_printer(Printer *printer)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100633{
Giorgio Arena2d099932017-10-25 15:47:08 +0100634 _printers.push_back(printer);
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100635}
636
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100637std::vector<TestInfo> Framework::test_infos() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100638{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100639 std::vector<TestInfo> ids;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100640
641 int id = 0;
642
643 for(const auto &factory : _test_factories)
644 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100645 TestInfo test_info{ id, factory->name(), factory->mode(), factory->status() };
646
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100647 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100648 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100649 ids.emplace_back(std::move(test_info));
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100650 }
651
652 ++id;
653 }
654
655 return ids;
656}
steniu01172c58d2017-08-31 13:49:08 +0100657
658LogLevel Framework::log_level() const
659{
660 return _log_level;
661}
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100662} // namespace framework
663} // namespace test
664} // namespace arm_compute