blob: bfb955c525061399493da0f9dd5a63acffab2da3 [file] [log] [blame]
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +01001/*
Ramy Elgammala8db6122023-05-08 03:33:43 +01002 * Copyright (c) 2017-2021, 2023 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"
Pablo Tellodb8485a2019-09-24 11:03:47 +010027#include "tests/framework/ParametersLibrary.h"
Matthew Bentham470bc1e2020-03-09 10:55:40 +000028#include "tests/framework/TestFilter.h"
Pablo Tellodb8485a2019-09-24 11:03:47 +010029
Gian Marco Iodiced30ed112018-05-16 12:01:14 +010030#ifdef ARM_COMPUTE_CL
Pablo Tellodb8485a2019-09-24 11:03:47 +010031#include "arm_compute/runtime/CL/CLRuntimeContext.h"
Gian Marco Iodiced30ed112018-05-16 12:01:14 +010032#include "arm_compute/runtime/CL/CLScheduler.h"
Pablo Tellodb8485a2019-09-24 11:03:47 +010033
Gian Marco Iodiced30ed112018-05-16 12:01:14 +010034#endif /* ARM_COMPUTE_CL */
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010035
36#include <chrono>
37#include <iostream>
Georgios Pinitas40f51a62020-11-21 03:04:18 +000038#include <memory>
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010039#include <sstream>
40#include <type_traits>
41
42namespace arm_compute
43{
44namespace test
45{
Pablo Tellodb8485a2019-09-24 11:03:47 +010046std::unique_ptr<ParametersLibrary> parameters;
47
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +010048namespace framework
49{
Georgios Pinitas12833d02019-07-25 13:31:10 +010050std::unique_ptr<InstrumentsInfo> instruments_info;
51
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010052Framework::Framework()
Matthew Bentham470bc1e2020-03-09 10:55:40 +000053 : _test_filter(nullptr)
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010054{
Anthony Barbier72f4ae52018-11-07 17:33:54 +000055 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<WallClockTimestamps, ScaleFactor::NONE>);
56 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::TIME_MS),
57 Instrument::make_instrument<WallClockTimestamps, ScaleFactor::TIME_MS>);
58 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::TIME_S),
59 Instrument::make_instrument<WallClockTimestamps, ScaleFactor::TIME_S>);
Giorgio Arenace58a9f2017-10-31 17:59:17 +000060 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::NONE), Instrument::make_instrument<WallClockTimer, ScaleFactor::NONE>);
61 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<WallClockTimer, ScaleFactor::TIME_MS>);
62 _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 +000063 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<SchedulerTimestamps, ScaleFactor::NONE>);
64 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMESTAMPS, ScaleFactor::TIME_MS),
65 Instrument::make_instrument<SchedulerTimestamps, ScaleFactor::TIME_MS>);
66 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMESTAMPS, ScaleFactor::TIME_S),
67 Instrument::make_instrument<SchedulerTimestamps, ScaleFactor::TIME_S>);
Anthony Barbiere8a49832018-01-18 10:04:05 +000068 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::NONE), Instrument::make_instrument<SchedulerTimer, ScaleFactor::NONE>);
69 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<SchedulerTimer, ScaleFactor::TIME_MS>);
70 _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 +010071#ifdef PMU_ENABLED
Giorgio Arenace58a9f2017-10-31 17:59:17 +000072 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::NONE), Instrument::make_instrument<PMUCounter, ScaleFactor::NONE>);
73 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::SCALE_1K), Instrument::make_instrument<PMUCounter, ScaleFactor::SCALE_1K>);
74 _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 +010075#endif /* PMU_ENABLED */
Moritz Pflanzer45634b42017-08-30 12:48:18 +010076#ifdef MALI_ENABLED
Giorgio Arenace58a9f2017-10-31 17:59:17 +000077 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::NONE), Instrument::make_instrument<MaliCounter, ScaleFactor::NONE>);
78 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::SCALE_1K), Instrument::make_instrument<MaliCounter, ScaleFactor::SCALE_1K>);
79 _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 +010080#endif /* MALI_ENABLED */
Anthony Barbiere8895f82017-11-23 16:58:52 +000081#ifdef ARM_COMPUTE_CL
Anthony Barbier72f4ae52018-11-07 17:33:54 +000082 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::NONE>);
83 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::TIME_US), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::TIME_US>);
84 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::TIME_MS), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::TIME_MS>);
85 _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 +000086 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::NONE), Instrument::make_instrument<OpenCLTimer, ScaleFactor::NONE>);
87 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_US), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_US>);
88 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_MS>);
89 _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 +010090 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::NONE), Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::NONE>);
91 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1K),
92 Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1K>);
93 _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1M),
94 Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1M>);
Anthony Barbiere8895f82017-11-23 16:58:52 +000095#endif /* ARM_COMPUTE_CL */
Georgios Pinitas12833d02019-07-25 13:31:10 +010096
Georgios Pinitas40f51a62020-11-21 03:04:18 +000097 instruments_info = std::make_unique<InstrumentsInfo>();
Moritz Pflanzera4f711b2017-07-05 11:02:23 +010098}
99
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000100std::set<InstrumentsDescription> Framework::available_instruments() const
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100101{
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000102 std::set<InstrumentsDescription> types;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100103
104 for(const auto &instrument : _available_instruments)
105 {
106 types.emplace(instrument.first);
107 }
108
109 return types;
110}
111
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100112std::map<TestResult::Status, int> Framework::count_test_results() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100113{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100114 std::map<TestResult::Status, int> counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100115
116 for(const auto &test : _test_results)
117 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100118 ++counts[test.second.status];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100119 }
120
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100121 return counts;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100122}
123
124Framework &Framework::get()
125{
126 static Framework instance;
127 return instance;
128}
129
Georgios Pinitas7f152512019-12-16 19:59:52 +0000130void Framework::init(const FrameworkConfig &config)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100131{
Matthew Bentham470bc1e2020-03-09 10:55:40 +0000132 _test_filter.reset(new TestFilter(config.mode, config.name_filter, config.id_filter));
Ramy Elgammal1355ec42023-05-15 13:50:46 +0100133 _num_iterations = config.num_iterations;
134 _log_level = config.log_level;
135 _cooldown_sec = config.cooldown_sec;
136 _configure_only = config.configure_only;
137 _print_rerun_cmd = config.print_rerun_cmd;
138 _seed = config.seed;
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100139
Georgios Pinitas7f152512019-12-16 19:59:52 +0000140 _instruments = std::set<framework::InstrumentsDescription>(std::begin(config.instruments), std::end(config.instruments));
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100141}
142
143std::string Framework::current_suite_name() const
144{
145 return join(_test_suite_name.cbegin(), _test_suite_name.cend(), "/");
146}
147
148void Framework::push_suite(std::string name)
149{
150 _test_suite_name.emplace_back(std::move(name));
151}
152
153void Framework::pop_suite()
154{
155 _test_suite_name.pop_back();
156}
157
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100158void Framework::add_test_info(std::string info)
159{
160 _test_info.emplace_back(std::move(info));
161}
162
163void Framework::clear_test_info()
164{
165 _test_info.clear();
166}
167
168bool Framework::has_test_info() const
169{
170 return !_test_info.empty();
171}
172
173void Framework::print_test_info(std::ostream &os) const
174{
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100175 if(!_test_info.empty())
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100176 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100177 os << "CONTEXT:\n";
178
179 for(const auto &str : _test_info)
180 {
181 os << " " << str << "\n";
182 }
Moritz Pflanzerc7d15032017-07-18 16:21:16 +0100183 }
184}
185
Giorgio Arena2d099932017-10-25 15:47:08 +0100186template <typename F>
187void Framework::func_on_all_printers(F &&func)
188{
189 std::for_each(std::begin(_printers), std::end(_printers), func);
190}
191
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100192void Framework::log_test_start(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100193{
Giorgio Arena2d099932017-10-25 15:47:08 +0100194 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100195 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100196 func_on_all_printers([&](Printer * p)
197 {
198 p->print_test_header(info);
199 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100200 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100201}
202
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100203void Framework::log_test_skipped(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100204{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100205 static_cast<void>(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100206}
207
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100208void Framework::log_test_end(const TestInfo &info)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100209{
Giorgio Arena2d099932017-10-25 15:47:08 +0100210 if(_log_level >= LogLevel::MEASUREMENTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100211 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100212 func_on_all_printers([&](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100213 {
Freddie Liardet59fd7a72021-06-17 13:30:11 +0100214 p->print_profiler_header(_test_results.at(info).header_data);
Giorgio Arena2d099932017-10-25 15:47:08 +0100215 p->print_measurements(_test_results.at(info).measurements);
216 });
217 }
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100218
Giorgio Arena2d099932017-10-25 15:47:08 +0100219 if(_log_level >= LogLevel::TESTS)
220 {
221 func_on_all_printers([](Printer * p)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100222 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100223 p->print_test_footer();
224 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100225 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100226}
227
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100228void Framework::log_failed_expectation(const TestError &error)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100229{
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100230 ARM_COMPUTE_ERROR_ON(_current_test_info == nullptr);
231 ARM_COMPUTE_ERROR_ON(_current_test_result == nullptr);
232
233 const bool is_expected_failure = _current_test_info->status == TestCaseFactory::Status::EXPECTED_FAILURE;
234
Giorgio Arena2d099932017-10-25 15:47:08 +0100235 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100236 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100237 func_on_all_printers([&](Printer * p)
238 {
239 p->print_error(error, is_expected_failure);
240 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100241 }
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100242
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100243 _current_test_result->status = TestResult::Status::FAILED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100244}
245
steniu01172c58d2017-08-31 13:49:08 +0100246void Framework::log_info(const std::string &info)
247{
Giorgio Arena2d099932017-10-25 15:47:08 +0100248 if(_log_level >= LogLevel::DEBUG)
steniu01172c58d2017-08-31 13:49:08 +0100249 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100250 func_on_all_printers([&](Printer * p)
251 {
252 p->print_info(info);
253 });
steniu01172c58d2017-08-31 13:49:08 +0100254 }
255}
256
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100257int Framework::num_iterations() const
258{
259 return _num_iterations;
260}
261
262void Framework::set_num_iterations(int num_iterations)
263{
264 _num_iterations = num_iterations;
265}
266
267void Framework::set_throw_errors(bool throw_errors)
268{
269 _throw_errors = throw_errors;
270}
271
272bool Framework::throw_errors() const
273{
274 return _throw_errors;
275}
276
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100277void Framework::set_stop_on_error(bool stop_on_error)
278{
279 _stop_on_error = stop_on_error;
280}
281
282bool Framework::stop_on_error() const
283{
284 return _stop_on_error;
285}
286
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100287void Framework::set_error_on_missing_assets(bool error_on_missing_assets)
288{
289 _error_on_missing_assets = error_on_missing_assets;
290}
291
292bool Framework::error_on_missing_assets() const
293{
294 return _error_on_missing_assets;
295}
296
Ramy Elgammal1355ec42023-05-15 13:50:46 +0100297TestResult::Status Framework::run_test(const TestInfo &info, TestCaseFactory &test_factory)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100298{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100299 if(test_factory.status() == TestCaseFactory::Status::DISABLED)
300 {
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100301 log_test_skipped(info);
302 set_test_result(info, TestResult(TestResult::Status::DISABLED));
Ramy Elgammal1355ec42023-05-15 13:50:46 +0100303 return TestResult::Status::DISABLED;
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100304 }
305
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100306 log_test_start(info);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100307
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100308 Profiler profiler = get_profiler();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100309 TestResult result(TestResult::Status::NOT_RUN);
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100310
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100311 _current_test_info = &info;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100312 _current_test_result = &result;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100313
Giorgio Arena2d099932017-10-25 15:47:08 +0100314 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100315 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100316 func_on_all_printers([](Printer * p)
317 {
318 p->print_errors_header();
319 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100320 }
321
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100322 const bool is_expected_failure = info.status == TestCaseFactory::Status::EXPECTED_FAILURE;
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100323
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100324 try
325 {
326 std::unique_ptr<TestCase> test_case = test_factory.make();
327
328 try
329 {
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100330 profiler.test_start();
331
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100332 test_case->do_setup();
333
334 for(int i = 0; i < _num_iterations; ++i)
335 {
Anthony Barbier61941452017-11-21 17:49:07 +0000336 //Start the profiler if:
337 //- there is only one iteration
338 //- it's not the first iteration of a multi-iterations run.
339 //
340 //Reason: if the CLTuner is enabled then the first run will be really messy
341 //as each kernel will be executed several times, messing up the instruments like OpenCL timers.
342 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000343 {
344 profiler.start();
345 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100346 test_case->do_run();
Joel Liang1c5ffd62017-12-28 10:09:51 +0800347 test_case->do_sync();
Anthony Barbier61941452017-11-21 17:49:07 +0000348 if(_num_iterations == 1 || i != 0)
Anthony Barbier2f8e0772017-11-15 13:06:46 +0000349 {
350 profiler.stop();
351 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100352 }
353
354 test_case->do_teardown();
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100355
Anthony Barbier9fb0cac2018-04-20 15:46:21 +0100356 profiler.test_stop();
357
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100358 // Change status to success if no error has happend
359 if(result.status == TestResult::Status::NOT_RUN)
360 {
361 result.status = TestResult::Status::SUCCESS;
362 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100363 }
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100364 catch(const FileNotFound &error)
365 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100366 profiler.test_stop();
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100367 if(_error_on_missing_assets)
368 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100369 if(_log_level >= LogLevel::ERRORS)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100370 {
371 TestError test_error(error.what(), LogLevel::ERRORS);
Giorgio Arena2d099932017-10-25 15:47:08 +0100372 func_on_all_printers([&](Printer * p)
373 {
374 p->print_error(test_error, is_expected_failure);
375 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100376 }
377
378 result.status = TestResult::Status::FAILED;
379
380 if(_throw_errors)
381 {
382 throw;
383 }
384 }
385 else
386 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100387 if(_log_level >= LogLevel::DEBUG)
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100388 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100389 func_on_all_printers([&](Printer * p)
390 {
391 p->print_info(error.what());
392 });
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100393 }
394
395 result.status = TestResult::Status::NOT_RUN;
396 }
397 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100398 catch(const TestError &error)
399 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100400 profiler.test_stop();
Giorgio Arena2d099932017-10-25 15:47:08 +0100401 if(_log_level >= error.level())
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100402 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100403 func_on_all_printers([&](Printer * p)
404 {
405 p->print_error(error, is_expected_failure);
406 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100407 }
408
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100409 result.status = TestResult::Status::FAILED;
410
411 if(_throw_errors)
412 {
413 throw;
414 }
415 }
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100416#ifdef ARM_COMPUTE_CL
417 catch(const ::cl::Error &error)
418 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100419 profiler.test_stop();
Giorgio Arena2d099932017-10-25 15:47:08 +0100420 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100421 {
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100422 std::stringstream stream;
423 stream << "Error code: " << error.err();
Moritz Pflanzer5b61fd32017-09-12 15:51:33 +0100424 TestError test_error(error.what(), LogLevel::ERRORS, stream.str());
Giorgio Arena2d099932017-10-25 15:47:08 +0100425 func_on_all_printers([&](Printer * p)
426 {
427 p->print_error(test_error, is_expected_failure);
428 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100429 }
430
Moritz Pflanzer47752c92017-07-18 13:38:47 +0100431 result.status = TestResult::Status::FAILED;
432
433 if(_throw_errors)
434 {
435 throw;
436 }
437 }
438#endif /* ARM_COMPUTE_CL */
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100439 catch(const std::exception &error)
440 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100441 profiler.test_stop();
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 }
449
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100450 result.status = TestResult::Status::CRASHED;
451
452 if(_throw_errors)
453 {
454 throw;
455 }
456 }
457 catch(...)
458 {
Pablo Tello21eaefe2018-10-10 14:38:35 +0100459 profiler.test_stop();
Giorgio Arena2d099932017-10-25 15:47:08 +0100460 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100461 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100462 func_on_all_printers([&](Printer * p)
463 {
464 p->print_error(TestError("Received unknown exception"), is_expected_failure);
465 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100466 }
467
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100468 result.status = TestResult::Status::CRASHED;
469
470 if(_throw_errors)
471 {
472 throw;
473 }
474 }
475 }
476 catch(const std::exception &error)
477 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100478 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100479 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100480 func_on_all_printers([&](Printer * p)
481 {
482 p->print_error(error, is_expected_failure);
483 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100484 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100485
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100486 result.status = TestResult::Status::CRASHED;
487
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100488 if(_throw_errors)
489 {
490 throw;
491 }
492 }
493 catch(...)
494 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100495 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100496 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100497 func_on_all_printers([&](Printer * p)
498 {
499 p->print_error(TestError("Received unknown exception"), is_expected_failure);
500 });
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100501 }
502
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100503 result.status = TestResult::Status::CRASHED;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100504
505 if(_throw_errors)
506 {
507 throw;
508 }
509 }
510
Giorgio Arena2d099932017-10-25 15:47:08 +0100511 if(_log_level >= LogLevel::ERRORS)
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100512 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100513 func_on_all_printers([](Printer * p)
514 {
515 p->print_errors_footer();
516 });
Moritz Pflanzer24a82462017-08-04 11:34:44 +0100517 }
518
Moritz Pflanzer0ce08442017-09-16 11:11:27 +0100519 _current_test_info = nullptr;
Moritz Pflanzere1103a82017-07-18 12:20:45 +0100520 _current_test_result = nullptr;
521
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100522 if(result.status == TestResult::Status::FAILED)
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100523 {
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100524 if(info.status == TestCaseFactory::Status::EXPECTED_FAILURE)
525 {
526 result.status = TestResult::Status::EXPECTED_FAILURE;
527 }
Moritz Pflanzere33eb642017-07-31 14:48:45 +0100528 }
529
530 if(result.status == TestResult::Status::FAILED || result.status == TestResult::Status::CRASHED)
531 {
532 if(_stop_on_error)
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100533 {
ramelg01b2eba7f2021-12-23 08:32:08 +0000534 throw std::runtime_error("Abandon on first error.");
Moritz Pflanzerfa811652017-07-26 17:00:37 +0100535 }
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100536 }
537
Freddie Liardet59fd7a72021-06-17 13:30:11 +0100538 result.header_data = profiler.header();
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100539 result.measurements = profiler.measurements();
540
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100541 set_test_result(info, result);
542 log_test_end(info);
Ramy Elgammal1355ec42023-05-15 13:50:46 +0100543 return result.status;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100544}
545
546bool Framework::run()
547{
548 // Clear old test results
549 _test_results.clear();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100550
Giorgio Arena2d099932017-10-25 15:47:08 +0100551 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100552 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100553 func_on_all_printers([](Printer * p)
554 {
555 p->print_run_header();
556 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100557 }
558
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100559 const std::chrono::time_point<std::chrono::high_resolution_clock> start = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100560
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100561 int id = 0;
562 int id_run_test = 0;
Ramy Elgammala8db6122023-05-08 03:33:43 +0100563 ARM_COMPUTE_UNUSED(id_run_test); // Not used if ARM_COMPUTE_CL is not defined
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100564
565 for(auto &test_factory : _test_factories)
566 {
567 const std::string test_case_name = test_factory->name();
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100568 const TestInfo test_info{ id, test_case_name, test_factory->mode(), test_factory->status() };
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100569
Matthew Bentham470bc1e2020-03-09 10:55:40 +0000570 if(_test_filter->is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100571 {
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100572#ifdef ARM_COMPUTE_CL
Georgios Pinitasf5ec9812018-10-26 14:07:56 +0100573 // Every 100 tests, reset the OpenCL context to release the allocated memory
574 if(opencl_is_available() && (id_run_test % 100) == 0)
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100575 {
Georgios Pinitasc9f163b2019-11-18 14:25:45 +0000576 auto ctx_properties = CLScheduler::get().context().getInfo<CL_CONTEXT_PROPERTIES>(nullptr);
577 auto queue_properties = CLScheduler::get().queue().getInfo<CL_QUEUE_PROPERTIES>(nullptr);
578
579 cl::Context new_ctx = cl::Context(CL_DEVICE_TYPE_DEFAULT, ctx_properties.data());
580 cl::CommandQueue new_queue = cl::CommandQueue(new_ctx, CLKernelLibrary::get().get_device(), queue_properties);
581
Georgios Pinitasdf473ea2018-05-31 18:53:52 +0100582 CLKernelLibrary::get().clear_programs_cache();
Georgios Pinitasc9f163b2019-11-18 14:25:45 +0000583 CLScheduler::get().set_context(new_ctx);
584 CLScheduler::get().set_queue(new_queue);
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100585 }
586#endif // ARM_COMPUTE_CL
Ramy Elgammal1355ec42023-05-15 13:50:46 +0100587 TestResult::Status result = run_test(test_info, *test_factory);
588 if((_print_rerun_cmd) && (result == TestResult::Status::CRASHED || result == TestResult::Status::FAILED))
589 {
590 std::cout << "Rerun command: ./arm_compute_validation --filter='^" << test_info.name << "$' --seed=" << _seed << std::endl;
591 }
Gian Marco Iodiced30ed112018-05-16 12:01:14 +0100592 ++id_run_test;
Georgios Pinitas7f152512019-12-16 19:59:52 +0000593
594 // Run test delay
595 sleep_in_seconds(_cooldown_sec);
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100596 }
597
598 ++id;
599 }
600
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100601 const std::chrono::time_point<std::chrono::high_resolution_clock> end = std::chrono::high_resolution_clock::now();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100602
Giorgio Arena2d099932017-10-25 15:47:08 +0100603 if(_log_level >= LogLevel::TESTS)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100604 {
Giorgio Arena2d099932017-10-25 15:47:08 +0100605 func_on_all_printers([](Printer * p)
606 {
607 p->print_run_footer();
608 });
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100609 }
610
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100611 auto runtime = std::chrono::duration_cast<std::chrono::seconds>(end - start);
612 std::map<TestResult::Status, int> results = count_test_results();
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100613
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100614 if(_log_level > LogLevel::NONE)
615 {
Moritz Pflanzer8df3faf2017-07-28 13:57:53 +0100616 std::cout << "Executed " << _test_results.size() << " test(s) ("
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100617 << results[TestResult::Status::SUCCESS] << " passed, "
618 << results[TestResult::Status::EXPECTED_FAILURE] << " expected failures, "
619 << results[TestResult::Status::FAILED] << " failed, "
620 << results[TestResult::Status::CRASHED] << " crashed, "
621 << results[TestResult::Status::DISABLED] << " disabled) in " << runtime.count() << " second(s)\n";
Moritz Pflanzer2ac50402017-07-24 15:52:54 +0100622 }
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100623
steniu013e05e4e2017-08-25 17:18:01 +0100624 int num_successful_tests = results[TestResult::Status::SUCCESS] + results[TestResult::Status::EXPECTED_FAILURE] + results[TestResult::Status::DISABLED];
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100625
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100626 return (static_cast<unsigned int>(num_successful_tests) == _test_results.size());
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100627}
628
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100629void Framework::set_test_result(TestInfo info, TestResult result)
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100630{
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100631 _test_results.emplace(std::move(info), std::move(result));
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100632}
633
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100634void Framework::print_test_results(Printer &printer) const
635{
636 printer.print_run_header();
637
638 for(const auto &test : _test_results)
639 {
640 printer.print_test_header(test.first);
Freddie Liardet59fd7a72021-06-17 13:30:11 +0100641 printer.print_profiler_header(test.second.header_data);
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100642 printer.print_measurements(test.second.measurements);
643 printer.print_test_footer();
644 }
645
646 printer.print_run_footer();
647}
648
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100649Profiler Framework::get_profiler() const
650{
651 Profiler profiler;
652
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100653 const bool all_instruments = std::any_of(
654 _instruments.begin(),
655 _instruments.end(),
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000656 [](InstrumentsDescription type) -> bool { return type.first == InstrumentType::ALL; });
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100657
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000658 auto is_selected = [&](InstrumentsDescription instrument) -> bool
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100659 {
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000660 return std::find_if(_instruments.begin(), _instruments.end(), [&](InstrumentsDescription type) -> bool {
661 const auto group = static_cast<InstrumentType>(static_cast<uint64_t>(type.first) & 0xFF00);
662 return (group == instrument.first) && (instrument.second == type.second);
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100663 })
664 != _instruments.end();
665 };
666
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100667 for(const auto &instrument : _available_instruments)
668 {
Moritz Pflanzer09e4f982017-08-30 12:47:06 +0100669 if(all_instruments || is_selected(instrument.first))
Moritz Pflanzera4f711b2017-07-05 11:02:23 +0100670 {
671 profiler.add(instrument.second());
672 }
673 }
674
675 return profiler;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100676}
677
Giorgio Arena2d099932017-10-25 15:47:08 +0100678void Framework::add_printer(Printer *printer)
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100679{
Giorgio Arena2d099932017-10-25 15:47:08 +0100680 _printers.push_back(printer);
Moritz Pflanzer80fffae2017-07-05 11:02:37 +0100681}
682
Moritz Pflanzer542002c2017-07-26 16:03:58 +0100683std::vector<TestInfo> Framework::test_infos() const
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100684{
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100685 std::vector<TestInfo> ids;
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100686
687 int id = 0;
688
689 for(const auto &factory : _test_factories)
690 {
Freddie Liardet59fd7a72021-06-17 13:30:11 +0100691 const TestInfo test_info{ id, factory->name(), factory->mode(), factory->status() };
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100692
Matthew Bentham470bc1e2020-03-09 10:55:40 +0000693 if(_test_filter->is_selected(test_info))
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100694 {
Moritz Pflanzerbf234e02017-07-24 15:04:14 +0100695 ids.emplace_back(std::move(test_info));
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100696 }
697
698 ++id;
699 }
700
701 return ids;
702}
steniu01172c58d2017-08-31 13:49:08 +0100703
704LogLevel Framework::log_level() const
705{
706 return _log_level;
707}
Georgios Pinitas12833d02019-07-25 13:31:10 +0100708
709void Framework::set_instruments_info(InstrumentsInfo instr_info)
710{
711 ARM_COMPUTE_ERROR_ON(instruments_info == nullptr);
712 *instruments_info = instr_info;
713}
Giorgio Arena68e29da2021-02-08 16:31:10 +0000714
715bool Framework::configure_only() const
716{
717 return _configure_only;
718}
719
720bool Framework::new_fixture_call() const
721{
722 return _new_fixture_call;
723}
724
725void Framework::set_new_fixture_call(bool val)
726{
727 _new_fixture_call = val;
728}
Moritz Pflanzerfc95ed22017-07-05 11:07:07 +0100729} // namespace framework
730} // namespace test
731} // namespace arm_compute