blob: cc7852906c8ed07c76333cacb01510d3795bb7d1 [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
Pablo Tello4e0ac6f2018-10-01 14:31:11 +010026#include "arm_compute/runtime/Scheduler.h"
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010027#include "support/ToolchainSupport.h"
Gian Marco Iodiced30ed112018-05-16 12:01:14 +010028#ifdef ARM_COMPUTE_CL
29#include "arm_compute/runtime/CL/CLScheduler.h"
30#endif /* ARM_COMPUTE_CL */
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010031
32#include <chrono>
33#include <iostream>
34#include <sstream>
35#include <type_traits>
36
37namespace arm_compute
38{
39namespace test
40{
41namespace framework
42{
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010043Framework::Framework()
44{
Anthony Barbier72f4ae52018-11-07 17:33:54 +000045 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<WallClockTimestamps, ScaleFactor::NONE>);
46 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::TIME_MS),
47 Instrument::make_instrument<WallClockTimestamps, ScaleFactor::TIME_MS>);
48 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::TIME_S),
49 Instrument::make_instrument<WallClockTimestamps, ScaleFactor::TIME_S>);
Giorgio Arenace58a9f2017-10-31 17:59:17 +000050 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::NONE), Instrument::make_instrument<WallClockTimer, ScaleFactor::NONE>);
51 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<WallClockTimer, ScaleFactor::TIME_MS>);
52 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::TIME_S), Instrument::make_instrument<WallClockTimer, ScaleFactor::TIME_S>);
Anthony Barbier72f4ae52018-11-07 17:33:54 +000053 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<SchedulerTimestamps, ScaleFactor::NONE>);
54 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMESTAMPS, ScaleFactor::TIME_MS),
55 Instrument::make_instrument<SchedulerTimestamps, ScaleFactor::TIME_MS>);
56 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMESTAMPS, ScaleFactor::TIME_S),
57 Instrument::make_instrument<SchedulerTimestamps, ScaleFactor::TIME_S>);
Anthony Barbiere8a49832018-01-18 10:04:05 +000058 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::NONE), Instrument::make_instrument<SchedulerTimer, ScaleFactor::NONE>);
59 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<SchedulerTimer, ScaleFactor::TIME_MS>);
60 _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 +010061#ifdef PMU_ENABLED
Giorgio Arenace58a9f2017-10-31 17:59:17 +000062 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::NONE), Instrument::make_instrument<PMUCounter, ScaleFactor::NONE>);
63 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::SCALE_1K), Instrument::make_instrument<PMUCounter, ScaleFactor::SCALE_1K>);
64 _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 +010065#endif /* PMU_ENABLED */
Moritz Pflanzer45634b42017-08-30 12:48:18 +010066#ifdef MALI_ENABLED
Giorgio Arenace58a9f2017-10-31 17:59:17 +000067 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::NONE), Instrument::make_instrument<MaliCounter, ScaleFactor::NONE>);
68 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::SCALE_1K), Instrument::make_instrument<MaliCounter, ScaleFactor::SCALE_1K>);
69 _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 +010070#endif /* MALI_ENABLED */
Anthony Barbiere8895f82017-11-23 16:58:52 +000071#ifdef ARM_COMPUTE_CL
Anthony Barbier72f4ae52018-11-07 17:33:54 +000072 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::NONE>);
73 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::TIME_US), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::TIME_US>);
74 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::TIME_MS), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::TIME_MS>);
75 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::TIME_S), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::TIME_S>);
Giorgio Arenace58a9f2017-10-31 17:59:17 +000076 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::NONE), Instrument::make_instrument<OpenCLTimer, ScaleFactor::NONE>);
77 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_US), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_US>);
78 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_MS>);
79 _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 +010080 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::NONE), Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::NONE>);
81 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1K),
82 Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1K>);
83 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1M),
84 Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1M>);
Anthony Barbiere8895f82017-11-23 16:58:52 +000085#endif /* ARM_COMPUTE_CL */
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010086}
87
Giorgio Arenace58a9f2017-10-31 17:59:17 +000088std::set<InstrumentsDescription> Framework::available_instruments() const
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010089{
Giorgio Arenace58a9f2017-10-31 17:59:17 +000090 std::set<InstrumentsDescription> types;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010091
92 for(const auto &instrument : _available_instruments)
93 {
94 types.emplace(instrument.first);
95 }
96
97 return types;
98}
99
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100100std::map<TestResult::Status, int> Framework::count_test_results() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100101{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100102 std::map<TestResult::Status, int> counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100103
104 for(const auto &test : _test_results)
105 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100106 ++counts[test.second.status];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100107 }
108
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100109 return counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100110}
111
112Framework &Framework::get()
113{
114 static Framework instance;
115 return instance;
116}
117
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000118void Framework::init(const std::vector<framework::InstrumentsDescription> &instruments, int num_iterations, DatasetMode mode, const std::string &name_filter, const std::string &id_filter,
119 LogLevel log_level)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100120{
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100121 _test_filter = TestFilter(mode, name_filter, id_filter);
122 _num_iterations = num_iterations;
123 _log_level = log_level;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100124
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000125 _instruments = std::set<framework::InstrumentsDescription>(instruments.begin(), instruments.end());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100126}
127
128std::string Framework::current_suite_name() const
129{
130 return join(_test_suite_name.cbegin(), _test_suite_name.cend(), "/");
131}
132
133void Framework::push_suite(std::string name)
134{
135 _test_suite_name.emplace_back(std::move(name));
136}
137
138void Framework::pop_suite()
139{
140 _test_suite_name.pop_back();
141}
142
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100143void Framework::add_test_info(std::string info)
144{
145 _test_info.emplace_back(std::move(info));
146}
147
148void Framework::clear_test_info()
149{
150 _test_info.clear();
151}
152
153bool Framework::has_test_info() const
154{
155 return !_test_info.empty();
156}
157
158void Framework::print_test_info(std::ostream &os) const
159{
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100160 if(!_test_info.empty())
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100161 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100162 os << "CONTEXT:\n";
163
164 for(const auto &str : _test_info)
165 {
166 os << " " << str << "\n";
167 }
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100168 }
169}
170
Giorgio Arena2d099932017-10-25 15:47:08 +0100171template <typename F>
172void Framework::func_on_all_printers(F &&func)
173{
174 std::for_each(std::begin(_printers), std::end(_printers), func);
175}
176
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100177void Framework::log_test_start(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100178{
Giorgio Arena2d099932017-10-25 15:47:08 +0100179 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100180 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100181 func_on_all_printers([&](Printer * p)
182 {
183 p->print_test_header(info);
184 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100185 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100186}
187
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100188void Framework::log_test_skipped(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100189{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100190 static_cast<void>(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100191}
192
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100193void Framework::log_test_end(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100194{
Giorgio Arena2d099932017-10-25 15:47:08 +0100195 if(_log_level >= LogLevel::MEASUREMENTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100196 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100197 func_on_all_printers([&](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100198 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100199 p->print_measurements(_test_results.at(info).measurements);
200 });
201 }
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100202
Giorgio Arena2d099932017-10-25 15:47:08 +0100203 if(_log_level >= LogLevel::TESTS)
204 {
205 func_on_all_printers([](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100206 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100207 p->print_test_footer();
208 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100209 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100210}
211
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100212void Framework::log_failed_expectation(const TestError &error)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100213{
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100214 ARM_COMPUTE_ERROR_ON(_current_test_info == nullptr);
215 ARM_COMPUTE_ERROR_ON(_current_test_result == nullptr);
216
217 const bool is_expected_failure = _current_test_info->status == TestCaseFactory::Status::EXPECTED_FAILURE;
218
Giorgio Arena2d099932017-10-25 15:47:08 +0100219 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100220 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100221 func_on_all_printers([&](Printer * p)
222 {
223 p->print_error(error, is_expected_failure);
224 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100225 }
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100226
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100227 _current_test_result->status = TestResult::Status::FAILED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100228}
229
steniu01172c58d2017-08-31 13:49:08 +0100230void Framework::log_info(const std::string &info)
231{
Giorgio Arena2d099932017-10-25 15:47:08 +0100232 if(_log_level >= LogLevel::DEBUG)
steniu01172c58d2017-08-31 13:49:08 +0100233 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100234 func_on_all_printers([&](Printer * p)
235 {
236 p->print_info(info);
237 });
steniu01172c58d2017-08-31 13:49:08 +0100238 }
239}
240
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100241int Framework::num_iterations() const
242{
243 return _num_iterations;
244}
245
246void Framework::set_num_iterations(int num_iterations)
247{
248 _num_iterations = num_iterations;
249}
250
251void Framework::set_throw_errors(bool throw_errors)
252{
253 _throw_errors = throw_errors;
254}
255
256bool Framework::throw_errors() const
257{
258 return _throw_errors;
259}
260
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100261void Framework::set_stop_on_error(bool stop_on_error)
262{
263 _stop_on_error = stop_on_error;
264}
265
266bool Framework::stop_on_error() const
267{
268 return _stop_on_error;
269}
270
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100271void Framework::set_error_on_missing_assets(bool error_on_missing_assets)
272{
273 _error_on_missing_assets = error_on_missing_assets;
274}
275
276bool Framework::error_on_missing_assets() const
277{
278 return _error_on_missing_assets;
279}
280
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100281void Framework::run_test(const TestInfo &info, TestCaseFactory &test_factory)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100282{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100283 if(test_factory.status() == TestCaseFactory::Status::DISABLED)
284 {
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100285 log_test_skipped(info);
286 set_test_result(info, TestResult(TestResult::Status::DISABLED));
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100287 return;
288 }
289
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100290 log_test_start(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100291
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100292 Profiler profiler = get_profiler();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100293 TestResult result(TestResult::Status::NOT_RUN);
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100294
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100295 _current_test_info = &info;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100296 _current_test_result = &result;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100297
Giorgio Arena2d099932017-10-25 15:47:08 +0100298 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100299 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100300 func_on_all_printers([](Printer * p)
301 {
302 p->print_errors_header();
303 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100304 }
305
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100306 const bool is_expected_failure = info.status == TestCaseFactory::Status::EXPECTED_FAILURE;
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100307
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100308 try
309 {
310 std::unique_ptr<TestCase> test_case = test_factory.make();
311
312 try
313 {
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100314 profiler.test_start();
315
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100316 test_case->do_setup();
317
318 for(int i = 0; i < _num_iterations; ++i)
319 {
Anthony Barbier61941452017-11-21 17:49:07 +0000320 //Start the profiler if:
321 //- there is only one iteration
322 //- it's not the first iteration of a multi-iterations run.
323 //
324 //Reason: if the CLTuner is enabled then the first run will be really messy
325 //as each kernel will be executed several times, messing up the instruments like OpenCL timers.
326 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000327 {
328 profiler.start();
329 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100330 test_case->do_run();
Joel Liang1c5ffd62017-12-28 10:09:51 +0800331 test_case->do_sync();
Anthony Barbier61941452017-11-21 17:49:07 +0000332 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000333 {
334 profiler.stop();
335 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100336 }
337
338 test_case->do_teardown();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100339
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100340 profiler.test_stop();
341
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100342 // Change status to success if no error has happend
343 if(result.status == TestResult::Status::NOT_RUN)
344 {
345 result.status = TestResult::Status::SUCCESS;
346 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100347 }
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100348 catch(const FileNotFound &error)
349 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100350 profiler.test_stop();
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100351 if(_error_on_missing_assets)
352 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100353 if(_log_level >= LogLevel::ERRORS)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100354 {
355 TestError test_error(error.what(), LogLevel::ERRORS);
Giorgio Arena2d099932017-10-25 15:47:08 +0100356 func_on_all_printers([&](Printer * p)
357 {
358 p->print_error(test_error, is_expected_failure);
359 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100360 }
361
362 result.status = TestResult::Status::FAILED;
363
364 if(_throw_errors)
365 {
366 throw;
367 }
368 }
369 else
370 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100371 if(_log_level >= LogLevel::DEBUG)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100372 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100373 func_on_all_printers([&](Printer * p)
374 {
375 p->print_info(error.what());
376 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100377 }
378
379 result.status = TestResult::Status::NOT_RUN;
380 }
381 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100382 catch(const TestError &error)
383 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100384 profiler.test_stop();
Giorgio Arena2d099932017-10-25 15:47:08 +0100385 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100386 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100387 func_on_all_printers([&](Printer * p)
388 {
389 p->print_error(error, is_expected_failure);
390 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100391 }
392
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100393 result.status = TestResult::Status::FAILED;
394
395 if(_throw_errors)
396 {
397 throw;
398 }
399 }
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100400#ifdef ARM_COMPUTE_CL
401 catch(const ::cl::Error &error)
402 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100403 profiler.test_stop();
Giorgio Arena2d099932017-10-25 15:47:08 +0100404 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100405 {
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100406 std::stringstream stream;
407 stream << "Error code: " << error.err();
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100408 TestError test_error(error.what(), LogLevel::ERRORS, stream.str());
Giorgio Arena2d099932017-10-25 15:47:08 +0100409 func_on_all_printers([&](Printer * p)
410 {
411 p->print_error(test_error, is_expected_failure);
412 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100413 }
414
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100415 result.status = TestResult::Status::FAILED;
416
417 if(_throw_errors)
418 {
419 throw;
420 }
421 }
422#endif /* ARM_COMPUTE_CL */
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100423 catch(const std::exception &error)
424 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100425 profiler.test_stop();
Giorgio Arena2d099932017-10-25 15:47:08 +0100426 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100427 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100428 func_on_all_printers([&](Printer * p)
429 {
430 p->print_error(error, is_expected_failure);
431 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100432 }
433
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100434 result.status = TestResult::Status::CRASHED;
435
436 if(_throw_errors)
437 {
438 throw;
439 }
440 }
441 catch(...)
442 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100443 profiler.test_stop();
Giorgio Arena2d099932017-10-25 15:47:08 +0100444 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100445 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100446 func_on_all_printers([&](Printer * p)
447 {
448 p->print_error(TestError("Received unknown exception"), is_expected_failure);
449 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100450 }
451
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100452 result.status = TestResult::Status::CRASHED;
453
454 if(_throw_errors)
455 {
456 throw;
457 }
458 }
459 }
460 catch(const std::exception &error)
461 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100462 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100463 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100464 func_on_all_printers([&](Printer * p)
465 {
466 p->print_error(error, is_expected_failure);
467 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100468 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100469
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100470 result.status = TestResult::Status::CRASHED;
471
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100472 if(_throw_errors)
473 {
474 throw;
475 }
476 }
477 catch(...)
478 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100479 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100480 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100481 func_on_all_printers([&](Printer * p)
482 {
483 p->print_error(TestError("Received unknown exception"), is_expected_failure);
484 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100485 }
486
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100487 result.status = TestResult::Status::CRASHED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100488
489 if(_throw_errors)
490 {
491 throw;
492 }
493 }
494
Giorgio Arena2d099932017-10-25 15:47:08 +0100495 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100496 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100497 func_on_all_printers([](Printer * p)
498 {
499 p->print_errors_footer();
500 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100501 }
502
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100503 _current_test_info = nullptr;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100504 _current_test_result = nullptr;
505
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100506 if(result.status == TestResult::Status::FAILED)
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100507 {
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100508 if(info.status == TestCaseFactory::Status::EXPECTED_FAILURE)
509 {
510 result.status = TestResult::Status::EXPECTED_FAILURE;
511 }
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100512 }
513
514 if(result.status == TestResult::Status::FAILED || result.status == TestResult::Status::CRASHED)
515 {
516 if(_stop_on_error)
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100517 {
518 throw std::runtime_error("Abort on first error.");
519 }
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100520 }
521
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100522 result.measurements = profiler.measurements();
523
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100524 set_test_result(info, result);
525 log_test_end(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100526}
527
528bool Framework::run()
529{
530 // Clear old test results
531 _test_results.clear();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100532
Giorgio Arena2d099932017-10-25 15:47:08 +0100533 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100534 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100535 func_on_all_printers([](Printer * p)
536 {
537 p->print_run_header();
538 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100539 }
540
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100541 const std::chrono::time_point<std::chrono::high_resolution_clock> start = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100542
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100543 int id = 0;
544 int id_run_test = 0;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100545
546 for(auto &test_factory : _test_factories)
547 {
548 const std::string test_case_name = test_factory->name();
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100549 const TestInfo test_info{ id, test_case_name, test_factory->mode(), test_factory->status() };
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100550
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100551 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100552 {
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100553#ifdef ARM_COMPUTE_CL
Georgios Pinitasf5ec9812018-10-26 14:07:56 +0100554 // Every 100 tests, reset the OpenCL context to release the allocated memory
555 if(opencl_is_available() && (id_run_test % 100) == 0)
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100556 {
Georgios Pinitasdf473ea2018-05-31 18:53:52 +0100557 auto ctx_properties = CLScheduler::get().context().getInfo<CL_CONTEXT_PROPERTIES>(nullptr);
558 auto queue_properties = CLScheduler::get().queue().getInfo<CL_QUEUE_PROPERTIES>(nullptr);
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100559
Georgios Pinitasdf473ea2018-05-31 18:53:52 +0100560 cl::Context new_ctx = cl::Context(CL_DEVICE_TYPE_DEFAULT, ctx_properties.data());
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100561 cl::CommandQueue new_queue = cl::CommandQueue(new_ctx, CLKernelLibrary::get().get_device(), queue_properties);
Georgios Pinitasdf473ea2018-05-31 18:53:52 +0100562
563 CLKernelLibrary::get().clear_programs_cache();
564 CLScheduler::get().set_context(new_ctx);
565 CLScheduler::get().set_queue(new_queue);
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100566 }
567#endif // ARM_COMPUTE_CL
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100568 run_test(test_info, *test_factory);
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100569
570 ++id_run_test;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100571 }
572
573 ++id;
574 }
575
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100576 const std::chrono::time_point<std::chrono::high_resolution_clock> end = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100577
Giorgio Arena2d099932017-10-25 15:47:08 +0100578 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100579 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100580 func_on_all_printers([](Printer * p)
581 {
582 p->print_run_footer();
583 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100584 }
585
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100586 auto runtime = std::chrono::duration_cast<std::chrono::seconds>(end - start);
587 std::map<TestResult::Status, int> results = count_test_results();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100588
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100589 if(_log_level > LogLevel::NONE)
590 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100591 std::cout << "Executed " << _test_results.size() << " test(s) ("
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100592 << results[TestResult::Status::SUCCESS] << " passed, "
593 << results[TestResult::Status::EXPECTED_FAILURE] << " expected failures, "
594 << results[TestResult::Status::FAILED] << " failed, "
595 << results[TestResult::Status::CRASHED] << " crashed, "
596 << results[TestResult::Status::DISABLED] << " disabled) in " << runtime.count() << " second(s)\n";
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100597 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100598
steniu013e05e4e2017-08-25 17:18:01 +0100599 int num_successful_tests = results[TestResult::Status::SUCCESS] + results[TestResult::Status::EXPECTED_FAILURE] + results[TestResult::Status::DISABLED];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100600
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100601 return (static_cast<unsigned int>(num_successful_tests) == _test_results.size());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100602}
603
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100604void Framework::set_test_result(TestInfo info, TestResult result)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100605{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100606 _test_results.emplace(std::move(info), std::move(result));
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100607}
608
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100609void Framework::print_test_results(Printer &printer) const
610{
611 printer.print_run_header();
612
613 for(const auto &test : _test_results)
614 {
615 printer.print_test_header(test.first);
616 printer.print_measurements(test.second.measurements);
617 printer.print_test_footer();
618 }
619
620 printer.print_run_footer();
621}
622
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100623Profiler Framework::get_profiler() const
624{
625 Profiler profiler;
626
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100627 const bool all_instruments = std::any_of(
628 _instruments.begin(),
629 _instruments.end(),
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000630 [](InstrumentsDescription type) -> bool { return type.first == InstrumentType::ALL; });
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100631
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000632 auto is_selected = [&](InstrumentsDescription instrument) -> bool
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100633 {
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000634 return std::find_if(_instruments.begin(), _instruments.end(), [&](InstrumentsDescription type) -> bool {
635 const auto group = static_cast<InstrumentType>(static_cast<uint64_t>(type.first) & 0xFF00);
636 return (group == instrument.first) && (instrument.second == type.second);
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100637 })
638 != _instruments.end();
639 };
640
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100641 for(const auto &instrument : _available_instruments)
642 {
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100643 if(all_instruments || is_selected(instrument.first))
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100644 {
645 profiler.add(instrument.second());
646 }
647 }
648
649 return profiler;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100650}
651
Giorgio Arena2d099932017-10-25 15:47:08 +0100652void Framework::add_printer(Printer *printer)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100653{
Giorgio Arena2d099932017-10-25 15:47:08 +0100654 _printers.push_back(printer);
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100655}
656
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100657std::vector<TestInfo> Framework::test_infos() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100658{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100659 std::vector<TestInfo> ids;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100660
661 int id = 0;
662
663 for(const auto &factory : _test_factories)
664 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100665 TestInfo test_info{ id, factory->name(), factory->mode(), factory->status() };
666
Moritz Pflanzerec2de0f2017-07-27 14:43:46 +0100667 if(_test_filter.is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100668 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100669 ids.emplace_back(std::move(test_info));
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100670 }
671
672 ++id;
673 }
674
675 return ids;
676}
steniu01172c58d2017-08-31 13:49:08 +0100677
678LogLevel Framework::log_level() const
679{
680 return _log_level;
681}
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100682} // namespace framework
683} // namespace test
684} // namespace arm_compute