1*c217d954SCole Faust /*
2*c217d954SCole Faust * Copyright (c) 2017-2021 Arm Limited.
3*c217d954SCole Faust *
4*c217d954SCole Faust * SPDX-License-Identifier: MIT
5*c217d954SCole Faust *
6*c217d954SCole Faust * Permission is hereby granted, free of charge, to any person obtaining a copy
7*c217d954SCole Faust * of this software and associated documentation files (the "Software"), to
8*c217d954SCole Faust * deal in the Software without restriction, including without limitation the
9*c217d954SCole Faust * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*c217d954SCole Faust * sell copies of the Software, and to permit persons to whom the Software is
11*c217d954SCole Faust * furnished to do so, subject to the following conditions:
12*c217d954SCole Faust *
13*c217d954SCole Faust * The above copyright notice and this permission notice shall be included in all
14*c217d954SCole Faust * copies or substantial portions of the Software.
15*c217d954SCole Faust *
16*c217d954SCole Faust * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*c217d954SCole Faust * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*c217d954SCole Faust * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*c217d954SCole Faust * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*c217d954SCole Faust * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*c217d954SCole Faust * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*c217d954SCole Faust * SOFTWARE.
23*c217d954SCole Faust */
24*c217d954SCole Faust #include "Framework.h"
25*c217d954SCole Faust
26*c217d954SCole Faust #include "arm_compute/runtime/Scheduler.h"
27*c217d954SCole Faust #include "tests/framework/ParametersLibrary.h"
28*c217d954SCole Faust #include "tests/framework/TestFilter.h"
29*c217d954SCole Faust
30*c217d954SCole Faust #ifdef ARM_COMPUTE_CL
31*c217d954SCole Faust #include "arm_compute/runtime/CL/CLRuntimeContext.h"
32*c217d954SCole Faust #include "arm_compute/runtime/CL/CLScheduler.h"
33*c217d954SCole Faust
34*c217d954SCole Faust #endif /* ARM_COMPUTE_CL */
35*c217d954SCole Faust
36*c217d954SCole Faust #include <chrono>
37*c217d954SCole Faust #include <iostream>
38*c217d954SCole Faust #include <memory>
39*c217d954SCole Faust #include <sstream>
40*c217d954SCole Faust #include <type_traits>
41*c217d954SCole Faust
42*c217d954SCole Faust namespace arm_compute
43*c217d954SCole Faust {
44*c217d954SCole Faust namespace test
45*c217d954SCole Faust {
46*c217d954SCole Faust std::unique_ptr<ParametersLibrary> parameters;
47*c217d954SCole Faust
48*c217d954SCole Faust namespace framework
49*c217d954SCole Faust {
50*c217d954SCole Faust std::unique_ptr<InstrumentsInfo> instruments_info;
51*c217d954SCole Faust
Framework()52*c217d954SCole Faust Framework::Framework()
53*c217d954SCole Faust : _test_filter(nullptr)
54*c217d954SCole Faust {
55*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<WallClockTimestamps, ScaleFactor::NONE>);
56*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::TIME_MS),
57*c217d954SCole Faust Instrument::make_instrument<WallClockTimestamps, ScaleFactor::TIME_MS>);
58*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::TIME_S),
59*c217d954SCole Faust Instrument::make_instrument<WallClockTimestamps, ScaleFactor::TIME_S>);
60*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::NONE), Instrument::make_instrument<WallClockTimer, ScaleFactor::NONE>);
61*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<WallClockTimer, ScaleFactor::TIME_MS>);
62*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::TIME_S), Instrument::make_instrument<WallClockTimer, ScaleFactor::TIME_S>);
63*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<SchedulerTimestamps, ScaleFactor::NONE>);
64*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMESTAMPS, ScaleFactor::TIME_MS),
65*c217d954SCole Faust Instrument::make_instrument<SchedulerTimestamps, ScaleFactor::TIME_MS>);
66*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMESTAMPS, ScaleFactor::TIME_S),
67*c217d954SCole Faust Instrument::make_instrument<SchedulerTimestamps, ScaleFactor::TIME_S>);
68*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::NONE), Instrument::make_instrument<SchedulerTimer, ScaleFactor::NONE>);
69*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<SchedulerTimer, ScaleFactor::TIME_MS>);
70*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::SCHEDULER_TIMER, ScaleFactor::TIME_S), Instrument::make_instrument<SchedulerTimer, ScaleFactor::TIME_S>);
71*c217d954SCole Faust #ifdef PMU_ENABLED
72*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::NONE), Instrument::make_instrument<PMUCounter, ScaleFactor::NONE>);
73*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::SCALE_1K), Instrument::make_instrument<PMUCounter, ScaleFactor::SCALE_1K>);
74*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::PMU, ScaleFactor::SCALE_1M), Instrument::make_instrument<PMUCounter, ScaleFactor::SCALE_1M>);
75*c217d954SCole Faust #endif /* PMU_ENABLED */
76*c217d954SCole Faust #ifdef MALI_ENABLED
77*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::NONE), Instrument::make_instrument<MaliCounter, ScaleFactor::NONE>);
78*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::SCALE_1K), Instrument::make_instrument<MaliCounter, ScaleFactor::SCALE_1K>);
79*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::MALI, ScaleFactor::SCALE_1M), Instrument::make_instrument<MaliCounter, ScaleFactor::SCALE_1M>);
80*c217d954SCole Faust #endif /* MALI_ENABLED */
81*c217d954SCole Faust #ifdef ARM_COMPUTE_CL
82*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::NONE>);
83*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::TIME_US), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::TIME_US>);
84*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::TIME_MS), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::TIME_MS>);
85*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMESTAMPS, ScaleFactor::TIME_S), Instrument::make_instrument<OpenCLTimestamps, ScaleFactor::TIME_S>);
86*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::NONE), Instrument::make_instrument<OpenCLTimer, ScaleFactor::NONE>);
87*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_US), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_US>);
88*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_MS), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_MS>);
89*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_TIMER, ScaleFactor::TIME_S), Instrument::make_instrument<OpenCLTimer, ScaleFactor::TIME_S>);
90*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::NONE), Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::NONE>);
91*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1K),
92*c217d954SCole Faust Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1K>);
93*c217d954SCole Faust _available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1M),
94*c217d954SCole Faust Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1M>);
95*c217d954SCole Faust #endif /* ARM_COMPUTE_CL */
96*c217d954SCole Faust
97*c217d954SCole Faust instruments_info = std::make_unique<InstrumentsInfo>();
98*c217d954SCole Faust }
99*c217d954SCole Faust
available_instruments() const100*c217d954SCole Faust std::set<InstrumentsDescription> Framework::available_instruments() const
101*c217d954SCole Faust {
102*c217d954SCole Faust std::set<InstrumentsDescription> types;
103*c217d954SCole Faust
104*c217d954SCole Faust for(const auto &instrument : _available_instruments)
105*c217d954SCole Faust {
106*c217d954SCole Faust types.emplace(instrument.first);
107*c217d954SCole Faust }
108*c217d954SCole Faust
109*c217d954SCole Faust return types;
110*c217d954SCole Faust }
111*c217d954SCole Faust
count_test_results() const112*c217d954SCole Faust std::map<TestResult::Status, int> Framework::count_test_results() const
113*c217d954SCole Faust {
114*c217d954SCole Faust std::map<TestResult::Status, int> counts;
115*c217d954SCole Faust
116*c217d954SCole Faust for(const auto &test : _test_results)
117*c217d954SCole Faust {
118*c217d954SCole Faust ++counts[test.second.status];
119*c217d954SCole Faust }
120*c217d954SCole Faust
121*c217d954SCole Faust return counts;
122*c217d954SCole Faust }
123*c217d954SCole Faust
get()124*c217d954SCole Faust Framework &Framework::get()
125*c217d954SCole Faust {
126*c217d954SCole Faust static Framework instance;
127*c217d954SCole Faust return instance;
128*c217d954SCole Faust }
129*c217d954SCole Faust
init(const FrameworkConfig & config)130*c217d954SCole Faust void Framework::init(const FrameworkConfig &config)
131*c217d954SCole Faust {
132*c217d954SCole Faust _test_filter.reset(new TestFilter(config.mode, config.name_filter, config.id_filter));
133*c217d954SCole Faust _num_iterations = config.num_iterations;
134*c217d954SCole Faust _log_level = config.log_level;
135*c217d954SCole Faust _cooldown_sec = config.cooldown_sec;
136*c217d954SCole Faust _configure_only = config.configure_only;
137*c217d954SCole Faust
138*c217d954SCole Faust _instruments = std::set<framework::InstrumentsDescription>(std::begin(config.instruments), std::end(config.instruments));
139*c217d954SCole Faust }
140*c217d954SCole Faust
current_suite_name() const141*c217d954SCole Faust std::string Framework::current_suite_name() const
142*c217d954SCole Faust {
143*c217d954SCole Faust return join(_test_suite_name.cbegin(), _test_suite_name.cend(), "/");
144*c217d954SCole Faust }
145*c217d954SCole Faust
push_suite(std::string name)146*c217d954SCole Faust void Framework::push_suite(std::string name)
147*c217d954SCole Faust {
148*c217d954SCole Faust _test_suite_name.emplace_back(std::move(name));
149*c217d954SCole Faust }
150*c217d954SCole Faust
pop_suite()151*c217d954SCole Faust void Framework::pop_suite()
152*c217d954SCole Faust {
153*c217d954SCole Faust _test_suite_name.pop_back();
154*c217d954SCole Faust }
155*c217d954SCole Faust
add_test_info(std::string info)156*c217d954SCole Faust void Framework::add_test_info(std::string info)
157*c217d954SCole Faust {
158*c217d954SCole Faust _test_info.emplace_back(std::move(info));
159*c217d954SCole Faust }
160*c217d954SCole Faust
clear_test_info()161*c217d954SCole Faust void Framework::clear_test_info()
162*c217d954SCole Faust {
163*c217d954SCole Faust _test_info.clear();
164*c217d954SCole Faust }
165*c217d954SCole Faust
has_test_info() const166*c217d954SCole Faust bool Framework::has_test_info() const
167*c217d954SCole Faust {
168*c217d954SCole Faust return !_test_info.empty();
169*c217d954SCole Faust }
170*c217d954SCole Faust
print_test_info(std::ostream & os) const171*c217d954SCole Faust void Framework::print_test_info(std::ostream &os) const
172*c217d954SCole Faust {
173*c217d954SCole Faust if(!_test_info.empty())
174*c217d954SCole Faust {
175*c217d954SCole Faust os << "CONTEXT:\n";
176*c217d954SCole Faust
177*c217d954SCole Faust for(const auto &str : _test_info)
178*c217d954SCole Faust {
179*c217d954SCole Faust os << " " << str << "\n";
180*c217d954SCole Faust }
181*c217d954SCole Faust }
182*c217d954SCole Faust }
183*c217d954SCole Faust
184*c217d954SCole Faust template <typename F>
func_on_all_printers(F && func)185*c217d954SCole Faust void Framework::func_on_all_printers(F &&func)
186*c217d954SCole Faust {
187*c217d954SCole Faust std::for_each(std::begin(_printers), std::end(_printers), func);
188*c217d954SCole Faust }
189*c217d954SCole Faust
log_test_start(const TestInfo & info)190*c217d954SCole Faust void Framework::log_test_start(const TestInfo &info)
191*c217d954SCole Faust {
192*c217d954SCole Faust if(_log_level >= LogLevel::TESTS)
193*c217d954SCole Faust {
194*c217d954SCole Faust func_on_all_printers([&](Printer * p)
195*c217d954SCole Faust {
196*c217d954SCole Faust p->print_test_header(info);
197*c217d954SCole Faust });
198*c217d954SCole Faust }
199*c217d954SCole Faust }
200*c217d954SCole Faust
log_test_skipped(const TestInfo & info)201*c217d954SCole Faust void Framework::log_test_skipped(const TestInfo &info)
202*c217d954SCole Faust {
203*c217d954SCole Faust static_cast<void>(info);
204*c217d954SCole Faust }
205*c217d954SCole Faust
log_test_end(const TestInfo & info)206*c217d954SCole Faust void Framework::log_test_end(const TestInfo &info)
207*c217d954SCole Faust {
208*c217d954SCole Faust if(_log_level >= LogLevel::MEASUREMENTS)
209*c217d954SCole Faust {
210*c217d954SCole Faust func_on_all_printers([&](Printer * p)
211*c217d954SCole Faust {
212*c217d954SCole Faust p->print_profiler_header(_test_results.at(info).header_data);
213*c217d954SCole Faust p->print_measurements(_test_results.at(info).measurements);
214*c217d954SCole Faust });
215*c217d954SCole Faust }
216*c217d954SCole Faust
217*c217d954SCole Faust if(_log_level >= LogLevel::TESTS)
218*c217d954SCole Faust {
219*c217d954SCole Faust func_on_all_printers([](Printer * p)
220*c217d954SCole Faust {
221*c217d954SCole Faust p->print_test_footer();
222*c217d954SCole Faust });
223*c217d954SCole Faust }
224*c217d954SCole Faust }
225*c217d954SCole Faust
log_failed_expectation(const TestError & error)226*c217d954SCole Faust void Framework::log_failed_expectation(const TestError &error)
227*c217d954SCole Faust {
228*c217d954SCole Faust ARM_COMPUTE_ERROR_ON(_current_test_info == nullptr);
229*c217d954SCole Faust ARM_COMPUTE_ERROR_ON(_current_test_result == nullptr);
230*c217d954SCole Faust
231*c217d954SCole Faust const bool is_expected_failure = _current_test_info->status == TestCaseFactory::Status::EXPECTED_FAILURE;
232*c217d954SCole Faust
233*c217d954SCole Faust if(_log_level >= error.level())
234*c217d954SCole Faust {
235*c217d954SCole Faust func_on_all_printers([&](Printer * p)
236*c217d954SCole Faust {
237*c217d954SCole Faust p->print_error(error, is_expected_failure);
238*c217d954SCole Faust });
239*c217d954SCole Faust }
240*c217d954SCole Faust
241*c217d954SCole Faust _current_test_result->status = TestResult::Status::FAILED;
242*c217d954SCole Faust }
243*c217d954SCole Faust
log_info(const std::string & info)244*c217d954SCole Faust void Framework::log_info(const std::string &info)
245*c217d954SCole Faust {
246*c217d954SCole Faust if(_log_level >= LogLevel::DEBUG)
247*c217d954SCole Faust {
248*c217d954SCole Faust func_on_all_printers([&](Printer * p)
249*c217d954SCole Faust {
250*c217d954SCole Faust p->print_info(info);
251*c217d954SCole Faust });
252*c217d954SCole Faust }
253*c217d954SCole Faust }
254*c217d954SCole Faust
num_iterations() const255*c217d954SCole Faust int Framework::num_iterations() const
256*c217d954SCole Faust {
257*c217d954SCole Faust return _num_iterations;
258*c217d954SCole Faust }
259*c217d954SCole Faust
set_num_iterations(int num_iterations)260*c217d954SCole Faust void Framework::set_num_iterations(int num_iterations)
261*c217d954SCole Faust {
262*c217d954SCole Faust _num_iterations = num_iterations;
263*c217d954SCole Faust }
264*c217d954SCole Faust
set_throw_errors(bool throw_errors)265*c217d954SCole Faust void Framework::set_throw_errors(bool throw_errors)
266*c217d954SCole Faust {
267*c217d954SCole Faust _throw_errors = throw_errors;
268*c217d954SCole Faust }
269*c217d954SCole Faust
throw_errors() const270*c217d954SCole Faust bool Framework::throw_errors() const
271*c217d954SCole Faust {
272*c217d954SCole Faust return _throw_errors;
273*c217d954SCole Faust }
274*c217d954SCole Faust
set_stop_on_error(bool stop_on_error)275*c217d954SCole Faust void Framework::set_stop_on_error(bool stop_on_error)
276*c217d954SCole Faust {
277*c217d954SCole Faust _stop_on_error = stop_on_error;
278*c217d954SCole Faust }
279*c217d954SCole Faust
stop_on_error() const280*c217d954SCole Faust bool Framework::stop_on_error() const
281*c217d954SCole Faust {
282*c217d954SCole Faust return _stop_on_error;
283*c217d954SCole Faust }
284*c217d954SCole Faust
set_error_on_missing_assets(bool error_on_missing_assets)285*c217d954SCole Faust void Framework::set_error_on_missing_assets(bool error_on_missing_assets)
286*c217d954SCole Faust {
287*c217d954SCole Faust _error_on_missing_assets = error_on_missing_assets;
288*c217d954SCole Faust }
289*c217d954SCole Faust
error_on_missing_assets() const290*c217d954SCole Faust bool Framework::error_on_missing_assets() const
291*c217d954SCole Faust {
292*c217d954SCole Faust return _error_on_missing_assets;
293*c217d954SCole Faust }
294*c217d954SCole Faust
run_test(const TestInfo & info,TestCaseFactory & test_factory)295*c217d954SCole Faust void Framework::run_test(const TestInfo &info, TestCaseFactory &test_factory)
296*c217d954SCole Faust {
297*c217d954SCole Faust if(test_factory.status() == TestCaseFactory::Status::DISABLED)
298*c217d954SCole Faust {
299*c217d954SCole Faust log_test_skipped(info);
300*c217d954SCole Faust set_test_result(info, TestResult(TestResult::Status::DISABLED));
301*c217d954SCole Faust return;
302*c217d954SCole Faust }
303*c217d954SCole Faust
304*c217d954SCole Faust log_test_start(info);
305*c217d954SCole Faust
306*c217d954SCole Faust Profiler profiler = get_profiler();
307*c217d954SCole Faust TestResult result(TestResult::Status::NOT_RUN);
308*c217d954SCole Faust
309*c217d954SCole Faust _current_test_info = &info;
310*c217d954SCole Faust _current_test_result = &result;
311*c217d954SCole Faust
312*c217d954SCole Faust if(_log_level >= LogLevel::ERRORS)
313*c217d954SCole Faust {
314*c217d954SCole Faust func_on_all_printers([](Printer * p)
315*c217d954SCole Faust {
316*c217d954SCole Faust p->print_errors_header();
317*c217d954SCole Faust });
318*c217d954SCole Faust }
319*c217d954SCole Faust
320*c217d954SCole Faust const bool is_expected_failure = info.status == TestCaseFactory::Status::EXPECTED_FAILURE;
321*c217d954SCole Faust
322*c217d954SCole Faust try
323*c217d954SCole Faust {
324*c217d954SCole Faust std::unique_ptr<TestCase> test_case = test_factory.make();
325*c217d954SCole Faust
326*c217d954SCole Faust try
327*c217d954SCole Faust {
328*c217d954SCole Faust profiler.test_start();
329*c217d954SCole Faust
330*c217d954SCole Faust test_case->do_setup();
331*c217d954SCole Faust
332*c217d954SCole Faust for(int i = 0; i < _num_iterations; ++i)
333*c217d954SCole Faust {
334*c217d954SCole Faust //Start the profiler if:
335*c217d954SCole Faust //- there is only one iteration
336*c217d954SCole Faust //- it's not the first iteration of a multi-iterations run.
337*c217d954SCole Faust //
338*c217d954SCole Faust //Reason: if the CLTuner is enabled then the first run will be really messy
339*c217d954SCole Faust //as each kernel will be executed several times, messing up the instruments like OpenCL timers.
340*c217d954SCole Faust if(_num_iterations == 1 || i != 0)
341*c217d954SCole Faust {
342*c217d954SCole Faust profiler.start();
343*c217d954SCole Faust }
344*c217d954SCole Faust test_case->do_run();
345*c217d954SCole Faust test_case->do_sync();
346*c217d954SCole Faust if(_num_iterations == 1 || i != 0)
347*c217d954SCole Faust {
348*c217d954SCole Faust profiler.stop();
349*c217d954SCole Faust }
350*c217d954SCole Faust }
351*c217d954SCole Faust
352*c217d954SCole Faust test_case->do_teardown();
353*c217d954SCole Faust
354*c217d954SCole Faust profiler.test_stop();
355*c217d954SCole Faust
356*c217d954SCole Faust // Change status to success if no error has happend
357*c217d954SCole Faust if(result.status == TestResult::Status::NOT_RUN)
358*c217d954SCole Faust {
359*c217d954SCole Faust result.status = TestResult::Status::SUCCESS;
360*c217d954SCole Faust }
361*c217d954SCole Faust }
362*c217d954SCole Faust catch(const FileNotFound &error)
363*c217d954SCole Faust {
364*c217d954SCole Faust profiler.test_stop();
365*c217d954SCole Faust if(_error_on_missing_assets)
366*c217d954SCole Faust {
367*c217d954SCole Faust if(_log_level >= LogLevel::ERRORS)
368*c217d954SCole Faust {
369*c217d954SCole Faust TestError test_error(error.what(), LogLevel::ERRORS);
370*c217d954SCole Faust func_on_all_printers([&](Printer * p)
371*c217d954SCole Faust {
372*c217d954SCole Faust p->print_error(test_error, is_expected_failure);
373*c217d954SCole Faust });
374*c217d954SCole Faust }
375*c217d954SCole Faust
376*c217d954SCole Faust result.status = TestResult::Status::FAILED;
377*c217d954SCole Faust
378*c217d954SCole Faust if(_throw_errors)
379*c217d954SCole Faust {
380*c217d954SCole Faust throw;
381*c217d954SCole Faust }
382*c217d954SCole Faust }
383*c217d954SCole Faust else
384*c217d954SCole Faust {
385*c217d954SCole Faust if(_log_level >= LogLevel::DEBUG)
386*c217d954SCole Faust {
387*c217d954SCole Faust func_on_all_printers([&](Printer * p)
388*c217d954SCole Faust {
389*c217d954SCole Faust p->print_info(error.what());
390*c217d954SCole Faust });
391*c217d954SCole Faust }
392*c217d954SCole Faust
393*c217d954SCole Faust result.status = TestResult::Status::NOT_RUN;
394*c217d954SCole Faust }
395*c217d954SCole Faust }
396*c217d954SCole Faust catch(const TestError &error)
397*c217d954SCole Faust {
398*c217d954SCole Faust profiler.test_stop();
399*c217d954SCole Faust if(_log_level >= error.level())
400*c217d954SCole Faust {
401*c217d954SCole Faust func_on_all_printers([&](Printer * p)
402*c217d954SCole Faust {
403*c217d954SCole Faust p->print_error(error, is_expected_failure);
404*c217d954SCole Faust });
405*c217d954SCole Faust }
406*c217d954SCole Faust
407*c217d954SCole Faust result.status = TestResult::Status::FAILED;
408*c217d954SCole Faust
409*c217d954SCole Faust if(_throw_errors)
410*c217d954SCole Faust {
411*c217d954SCole Faust throw;
412*c217d954SCole Faust }
413*c217d954SCole Faust }
414*c217d954SCole Faust #ifdef ARM_COMPUTE_CL
415*c217d954SCole Faust catch(const ::cl::Error &error)
416*c217d954SCole Faust {
417*c217d954SCole Faust profiler.test_stop();
418*c217d954SCole Faust if(_log_level >= LogLevel::ERRORS)
419*c217d954SCole Faust {
420*c217d954SCole Faust std::stringstream stream;
421*c217d954SCole Faust stream << "Error code: " << error.err();
422*c217d954SCole Faust TestError test_error(error.what(), LogLevel::ERRORS, stream.str());
423*c217d954SCole Faust func_on_all_printers([&](Printer * p)
424*c217d954SCole Faust {
425*c217d954SCole Faust p->print_error(test_error, is_expected_failure);
426*c217d954SCole Faust });
427*c217d954SCole Faust }
428*c217d954SCole Faust
429*c217d954SCole Faust result.status = TestResult::Status::FAILED;
430*c217d954SCole Faust
431*c217d954SCole Faust if(_throw_errors)
432*c217d954SCole Faust {
433*c217d954SCole Faust throw;
434*c217d954SCole Faust }
435*c217d954SCole Faust }
436*c217d954SCole Faust #endif /* ARM_COMPUTE_CL */
437*c217d954SCole Faust catch(const std::exception &error)
438*c217d954SCole Faust {
439*c217d954SCole Faust profiler.test_stop();
440*c217d954SCole Faust if(_log_level >= LogLevel::ERRORS)
441*c217d954SCole Faust {
442*c217d954SCole Faust func_on_all_printers([&](Printer * p)
443*c217d954SCole Faust {
444*c217d954SCole Faust p->print_error(error, is_expected_failure);
445*c217d954SCole Faust });
446*c217d954SCole Faust }
447*c217d954SCole Faust
448*c217d954SCole Faust result.status = TestResult::Status::CRASHED;
449*c217d954SCole Faust
450*c217d954SCole Faust if(_throw_errors)
451*c217d954SCole Faust {
452*c217d954SCole Faust throw;
453*c217d954SCole Faust }
454*c217d954SCole Faust }
455*c217d954SCole Faust catch(...)
456*c217d954SCole Faust {
457*c217d954SCole Faust profiler.test_stop();
458*c217d954SCole Faust if(_log_level >= LogLevel::ERRORS)
459*c217d954SCole Faust {
460*c217d954SCole Faust func_on_all_printers([&](Printer * p)
461*c217d954SCole Faust {
462*c217d954SCole Faust p->print_error(TestError("Received unknown exception"), is_expected_failure);
463*c217d954SCole Faust });
464*c217d954SCole Faust }
465*c217d954SCole Faust
466*c217d954SCole Faust result.status = TestResult::Status::CRASHED;
467*c217d954SCole Faust
468*c217d954SCole Faust if(_throw_errors)
469*c217d954SCole Faust {
470*c217d954SCole Faust throw;
471*c217d954SCole Faust }
472*c217d954SCole Faust }
473*c217d954SCole Faust }
474*c217d954SCole Faust catch(const std::exception &error)
475*c217d954SCole Faust {
476*c217d954SCole Faust if(_log_level >= LogLevel::ERRORS)
477*c217d954SCole Faust {
478*c217d954SCole Faust func_on_all_printers([&](Printer * p)
479*c217d954SCole Faust {
480*c217d954SCole Faust p->print_error(error, is_expected_failure);
481*c217d954SCole Faust });
482*c217d954SCole Faust }
483*c217d954SCole Faust
484*c217d954SCole Faust result.status = TestResult::Status::CRASHED;
485*c217d954SCole Faust
486*c217d954SCole Faust if(_throw_errors)
487*c217d954SCole Faust {
488*c217d954SCole Faust throw;
489*c217d954SCole Faust }
490*c217d954SCole Faust }
491*c217d954SCole Faust catch(...)
492*c217d954SCole Faust {
493*c217d954SCole Faust if(_log_level >= LogLevel::ERRORS)
494*c217d954SCole Faust {
495*c217d954SCole Faust func_on_all_printers([&](Printer * p)
496*c217d954SCole Faust {
497*c217d954SCole Faust p->print_error(TestError("Received unknown exception"), is_expected_failure);
498*c217d954SCole Faust });
499*c217d954SCole Faust }
500*c217d954SCole Faust
501*c217d954SCole Faust result.status = TestResult::Status::CRASHED;
502*c217d954SCole Faust
503*c217d954SCole Faust if(_throw_errors)
504*c217d954SCole Faust {
505*c217d954SCole Faust throw;
506*c217d954SCole Faust }
507*c217d954SCole Faust }
508*c217d954SCole Faust
509*c217d954SCole Faust if(_log_level >= LogLevel::ERRORS)
510*c217d954SCole Faust {
511*c217d954SCole Faust func_on_all_printers([](Printer * p)
512*c217d954SCole Faust {
513*c217d954SCole Faust p->print_errors_footer();
514*c217d954SCole Faust });
515*c217d954SCole Faust }
516*c217d954SCole Faust
517*c217d954SCole Faust _current_test_info = nullptr;
518*c217d954SCole Faust _current_test_result = nullptr;
519*c217d954SCole Faust
520*c217d954SCole Faust if(result.status == TestResult::Status::FAILED)
521*c217d954SCole Faust {
522*c217d954SCole Faust if(info.status == TestCaseFactory::Status::EXPECTED_FAILURE)
523*c217d954SCole Faust {
524*c217d954SCole Faust result.status = TestResult::Status::EXPECTED_FAILURE;
525*c217d954SCole Faust }
526*c217d954SCole Faust }
527*c217d954SCole Faust
528*c217d954SCole Faust if(result.status == TestResult::Status::FAILED || result.status == TestResult::Status::CRASHED)
529*c217d954SCole Faust {
530*c217d954SCole Faust if(_stop_on_error)
531*c217d954SCole Faust {
532*c217d954SCole Faust throw std::runtime_error("Abandon on first error.");
533*c217d954SCole Faust }
534*c217d954SCole Faust }
535*c217d954SCole Faust
536*c217d954SCole Faust result.header_data = profiler.header();
537*c217d954SCole Faust result.measurements = profiler.measurements();
538*c217d954SCole Faust
539*c217d954SCole Faust set_test_result(info, result);
540*c217d954SCole Faust log_test_end(info);
541*c217d954SCole Faust }
542*c217d954SCole Faust
run()543*c217d954SCole Faust bool Framework::run()
544*c217d954SCole Faust {
545*c217d954SCole Faust // Clear old test results
546*c217d954SCole Faust _test_results.clear();
547*c217d954SCole Faust
548*c217d954SCole Faust if(_log_level >= LogLevel::TESTS)
549*c217d954SCole Faust {
550*c217d954SCole Faust func_on_all_printers([](Printer * p)
551*c217d954SCole Faust {
552*c217d954SCole Faust p->print_run_header();
553*c217d954SCole Faust });
554*c217d954SCole Faust }
555*c217d954SCole Faust
556*c217d954SCole Faust const std::chrono::time_point<std::chrono::high_resolution_clock> start = std::chrono::high_resolution_clock::now();
557*c217d954SCole Faust
558*c217d954SCole Faust int id = 0;
559*c217d954SCole Faust int id_run_test = 0;
560*c217d954SCole Faust
561*c217d954SCole Faust for(auto &test_factory : _test_factories)
562*c217d954SCole Faust {
563*c217d954SCole Faust const std::string test_case_name = test_factory->name();
564*c217d954SCole Faust const TestInfo test_info{ id, test_case_name, test_factory->mode(), test_factory->status() };
565*c217d954SCole Faust
566*c217d954SCole Faust if(_test_filter->is_selected(test_info))
567*c217d954SCole Faust {
568*c217d954SCole Faust #ifdef ARM_COMPUTE_CL
569*c217d954SCole Faust // Every 100 tests, reset the OpenCL context to release the allocated memory
570*c217d954SCole Faust if(opencl_is_available() && (id_run_test % 100) == 0)
571*c217d954SCole Faust {
572*c217d954SCole Faust auto ctx_properties = CLScheduler::get().context().getInfo<CL_CONTEXT_PROPERTIES>(nullptr);
573*c217d954SCole Faust auto queue_properties = CLScheduler::get().queue().getInfo<CL_QUEUE_PROPERTIES>(nullptr);
574*c217d954SCole Faust
575*c217d954SCole Faust cl::Context new_ctx = cl::Context(CL_DEVICE_TYPE_DEFAULT, ctx_properties.data());
576*c217d954SCole Faust cl::CommandQueue new_queue = cl::CommandQueue(new_ctx, CLKernelLibrary::get().get_device(), queue_properties);
577*c217d954SCole Faust
578*c217d954SCole Faust CLKernelLibrary::get().clear_programs_cache();
579*c217d954SCole Faust CLScheduler::get().set_context(new_ctx);
580*c217d954SCole Faust CLScheduler::get().set_queue(new_queue);
581*c217d954SCole Faust }
582*c217d954SCole Faust #endif // ARM_COMPUTE_CL
583*c217d954SCole Faust
584*c217d954SCole Faust run_test(test_info, *test_factory);
585*c217d954SCole Faust
586*c217d954SCole Faust ++id_run_test;
587*c217d954SCole Faust
588*c217d954SCole Faust // Run test delay
589*c217d954SCole Faust sleep_in_seconds(_cooldown_sec);
590*c217d954SCole Faust }
591*c217d954SCole Faust
592*c217d954SCole Faust ++id;
593*c217d954SCole Faust }
594*c217d954SCole Faust
595*c217d954SCole Faust const std::chrono::time_point<std::chrono::high_resolution_clock> end = std::chrono::high_resolution_clock::now();
596*c217d954SCole Faust
597*c217d954SCole Faust if(_log_level >= LogLevel::TESTS)
598*c217d954SCole Faust {
599*c217d954SCole Faust func_on_all_printers([](Printer * p)
600*c217d954SCole Faust {
601*c217d954SCole Faust p->print_run_footer();
602*c217d954SCole Faust });
603*c217d954SCole Faust }
604*c217d954SCole Faust
605*c217d954SCole Faust auto runtime = std::chrono::duration_cast<std::chrono::seconds>(end - start);
606*c217d954SCole Faust std::map<TestResult::Status, int> results = count_test_results();
607*c217d954SCole Faust
608*c217d954SCole Faust if(_log_level > LogLevel::NONE)
609*c217d954SCole Faust {
610*c217d954SCole Faust std::cout << "Executed " << _test_results.size() << " test(s) ("
611*c217d954SCole Faust << results[TestResult::Status::SUCCESS] << " passed, "
612*c217d954SCole Faust << results[TestResult::Status::EXPECTED_FAILURE] << " expected failures, "
613*c217d954SCole Faust << results[TestResult::Status::FAILED] << " failed, "
614*c217d954SCole Faust << results[TestResult::Status::CRASHED] << " crashed, "
615*c217d954SCole Faust << results[TestResult::Status::DISABLED] << " disabled) in " << runtime.count() << " second(s)\n";
616*c217d954SCole Faust }
617*c217d954SCole Faust
618*c217d954SCole Faust int num_successful_tests = results[TestResult::Status::SUCCESS] + results[TestResult::Status::EXPECTED_FAILURE] + results[TestResult::Status::DISABLED];
619*c217d954SCole Faust
620*c217d954SCole Faust return (static_cast<unsigned int>(num_successful_tests) == _test_results.size());
621*c217d954SCole Faust }
622*c217d954SCole Faust
set_test_result(TestInfo info,TestResult result)623*c217d954SCole Faust void Framework::set_test_result(TestInfo info, TestResult result)
624*c217d954SCole Faust {
625*c217d954SCole Faust _test_results.emplace(std::move(info), std::move(result));
626*c217d954SCole Faust }
627*c217d954SCole Faust
print_test_results(Printer & printer) const628*c217d954SCole Faust void Framework::print_test_results(Printer &printer) const
629*c217d954SCole Faust {
630*c217d954SCole Faust printer.print_run_header();
631*c217d954SCole Faust
632*c217d954SCole Faust for(const auto &test : _test_results)
633*c217d954SCole Faust {
634*c217d954SCole Faust printer.print_test_header(test.first);
635*c217d954SCole Faust printer.print_profiler_header(test.second.header_data);
636*c217d954SCole Faust printer.print_measurements(test.second.measurements);
637*c217d954SCole Faust printer.print_test_footer();
638*c217d954SCole Faust }
639*c217d954SCole Faust
640*c217d954SCole Faust printer.print_run_footer();
641*c217d954SCole Faust }
642*c217d954SCole Faust
get_profiler() const643*c217d954SCole Faust Profiler Framework::get_profiler() const
644*c217d954SCole Faust {
645*c217d954SCole Faust Profiler profiler;
646*c217d954SCole Faust
647*c217d954SCole Faust const bool all_instruments = std::any_of(
648*c217d954SCole Faust _instruments.begin(),
649*c217d954SCole Faust _instruments.end(),
650*c217d954SCole Faust [](InstrumentsDescription type) -> bool { return type.first == InstrumentType::ALL; });
651*c217d954SCole Faust
652*c217d954SCole Faust auto is_selected = [&](InstrumentsDescription instrument) -> bool
653*c217d954SCole Faust {
654*c217d954SCole Faust return std::find_if(_instruments.begin(), _instruments.end(), [&](InstrumentsDescription type) -> bool {
655*c217d954SCole Faust const auto group = static_cast<InstrumentType>(static_cast<uint64_t>(type.first) & 0xFF00);
656*c217d954SCole Faust return (group == instrument.first) && (instrument.second == type.second);
657*c217d954SCole Faust })
658*c217d954SCole Faust != _instruments.end();
659*c217d954SCole Faust };
660*c217d954SCole Faust
661*c217d954SCole Faust for(const auto &instrument : _available_instruments)
662*c217d954SCole Faust {
663*c217d954SCole Faust if(all_instruments || is_selected(instrument.first))
664*c217d954SCole Faust {
665*c217d954SCole Faust profiler.add(instrument.second());
666*c217d954SCole Faust }
667*c217d954SCole Faust }
668*c217d954SCole Faust
669*c217d954SCole Faust return profiler;
670*c217d954SCole Faust }
671*c217d954SCole Faust
add_printer(Printer * printer)672*c217d954SCole Faust void Framework::add_printer(Printer *printer)
673*c217d954SCole Faust {
674*c217d954SCole Faust _printers.push_back(printer);
675*c217d954SCole Faust }
676*c217d954SCole Faust
test_infos() const677*c217d954SCole Faust std::vector<TestInfo> Framework::test_infos() const
678*c217d954SCole Faust {
679*c217d954SCole Faust std::vector<TestInfo> ids;
680*c217d954SCole Faust
681*c217d954SCole Faust int id = 0;
682*c217d954SCole Faust
683*c217d954SCole Faust for(const auto &factory : _test_factories)
684*c217d954SCole Faust {
685*c217d954SCole Faust const TestInfo test_info{ id, factory->name(), factory->mode(), factory->status() };
686*c217d954SCole Faust
687*c217d954SCole Faust if(_test_filter->is_selected(test_info))
688*c217d954SCole Faust {
689*c217d954SCole Faust ids.emplace_back(std::move(test_info));
690*c217d954SCole Faust }
691*c217d954SCole Faust
692*c217d954SCole Faust ++id;
693*c217d954SCole Faust }
694*c217d954SCole Faust
695*c217d954SCole Faust return ids;
696*c217d954SCole Faust }
697*c217d954SCole Faust
log_level() const698*c217d954SCole Faust LogLevel Framework::log_level() const
699*c217d954SCole Faust {
700*c217d954SCole Faust return _log_level;
701*c217d954SCole Faust }
702*c217d954SCole Faust
set_instruments_info(InstrumentsInfo instr_info)703*c217d954SCole Faust void Framework::set_instruments_info(InstrumentsInfo instr_info)
704*c217d954SCole Faust {
705*c217d954SCole Faust ARM_COMPUTE_ERROR_ON(instruments_info == nullptr);
706*c217d954SCole Faust *instruments_info = instr_info;
707*c217d954SCole Faust }
708*c217d954SCole Faust
configure_only() const709*c217d954SCole Faust bool Framework::configure_only() const
710*c217d954SCole Faust {
711*c217d954SCole Faust return _configure_only;
712*c217d954SCole Faust }
713*c217d954SCole Faust
new_fixture_call() const714*c217d954SCole Faust bool Framework::new_fixture_call() const
715*c217d954SCole Faust {
716*c217d954SCole Faust return _new_fixture_call;
717*c217d954SCole Faust }
718*c217d954SCole Faust
set_new_fixture_call(bool val)719*c217d954SCole Faust void Framework::set_new_fixture_call(bool val)
720*c217d954SCole Faust {
721*c217d954SCole Faust _new_fixture_call = val;
722*c217d954SCole Faust }
723*c217d954SCole Faust } // namespace framework
724*c217d954SCole Faust } // namespace test
725*c217d954SCole Faust } // namespace arm_compute
726