xref: /aosp_15_r20/external/ComputeLibrary/docs/user_guide/tests.dox (revision c217d954acce2dbc11938adb493fc0abd69584f3)
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 Faustnamespace arm_compute
25*c217d954SCole Faust{
26*c217d954SCole Faustnamespace test
27*c217d954SCole Faust{
28*c217d954SCole Faust/**
29*c217d954SCole Faust@page tests Validation and Benchmarks
30*c217d954SCole Faust
31*c217d954SCole Faust@tableofcontents
32*c217d954SCole Faust
33*c217d954SCole Faust@section tests_overview Overview
34*c217d954SCole Faust
35*c217d954SCole FaustBenchmark and validation tests are based on the same framework to setup and run
36*c217d954SCole Faustthe tests. In addition to running simple, self-contained test functions the
37*c217d954SCole Faustframework supports fixtures and data test cases. The former allows to share
38*c217d954SCole Faustcommon setup routines between various backends thus reducing the amount of
39*c217d954SCole Faustduplicated code. The latter can be used to parameterize tests or fixtures with
40*c217d954SCole Faustdifferent inputs, e.g. different tensor shapes. One limitation is that
41*c217d954SCole Fausttests/fixtures cannot be parameterized based on the data type if static type
42*c217d954SCole Faustinformation is needed within the test (e.g. to validate the results).
43*c217d954SCole Faust
44*c217d954SCole Faust@note By default tests are not built. To enable them you need to add validation_tests=1 and / or benchmark_tests=1 to your SCons line.
45*c217d954SCole Faust
46*c217d954SCole Faust@note Tests are not included in the pre-built binary archive, you have to build them from sources.
47*c217d954SCole Faust
48*c217d954SCole Faust@subsection tests_overview_fixtures Fixtures
49*c217d954SCole Faust
50*c217d954SCole FaustFixtures can be used to share common setup, teardown or even run tasks among
51*c217d954SCole Faustmultiple test cases. For that purpose a fixture can define a `setup`,
52*c217d954SCole Faust`teardown` and `run` method. Additionally the constructor and destructor might
53*c217d954SCole Faustalso be customized.
54*c217d954SCole Faust
55*c217d954SCole FaustAn instance of the fixture is created immediately before the actual test is
56*c217d954SCole Faustexecuted. After construction the @ref framework::Fixture::setup method is called. Then the test
57*c217d954SCole Faustfunction or the fixtures `run` method is invoked. After test execution the
58*c217d954SCole Faust@ref framework::Fixture::teardown method is called and lastly the fixture is destructed.
59*c217d954SCole Faust
60*c217d954SCole Faust@subsubsection tests_overview_fixtures_fixture Fixture
61*c217d954SCole Faust
62*c217d954SCole FaustFixtures for non-parameterized test are straightforward. The custom fixture
63*c217d954SCole Faustclass has to inherit from @ref framework::Fixture and choose to implement any of the
64*c217d954SCole Faust`setup`, `teardown` or `run` methods. None of the methods takes any arguments
65*c217d954SCole Faustor returns anything.
66*c217d954SCole Faust
67*c217d954SCole Faust    class CustomFixture : public framework::Fixture
68*c217d954SCole Faust    {
69*c217d954SCole Faust        void setup()
70*c217d954SCole Faust        {
71*c217d954SCole Faust            _ptr = malloc(4000);
72*c217d954SCole Faust        }
73*c217d954SCole Faust
74*c217d954SCole Faust        void run()
75*c217d954SCole Faust        {
76*c217d954SCole Faust            ARM_COMPUTE_ASSERT(_ptr != nullptr);
77*c217d954SCole Faust        }
78*c217d954SCole Faust
79*c217d954SCole Faust        void teardown()
80*c217d954SCole Faust        {
81*c217d954SCole Faust            free(_ptr);
82*c217d954SCole Faust        }
83*c217d954SCole Faust
84*c217d954SCole Faust        void *_ptr;
85*c217d954SCole Faust    };
86*c217d954SCole Faust
87*c217d954SCole Faust@subsubsection tests_overview_fixtures_data_fixture Data fixture
88*c217d954SCole Faust
89*c217d954SCole FaustThe advantage of a parameterized fixture is that arguments can be passed to the setup method at runtime. To make this possible the setup method has to be a template with a type parameter for every argument (though the template parameter doesn't have to be used). All other methods remain the same.
90*c217d954SCole Faust
91*c217d954SCole Faust    class CustomFixture : public framework::Fixture
92*c217d954SCole Faust    {
93*c217d954SCole Faust    #ifdef ALTERNATIVE_DECLARATION
94*c217d954SCole Faust        template <typename ...>
95*c217d954SCole Faust        void setup(size_t size)
96*c217d954SCole Faust        {
97*c217d954SCole Faust            _ptr = malloc(size);
98*c217d954SCole Faust        }
99*c217d954SCole Faust    #else
100*c217d954SCole Faust        template <typename T>
101*c217d954SCole Faust        void setup(T size)
102*c217d954SCole Faust        {
103*c217d954SCole Faust            _ptr = malloc(size);
104*c217d954SCole Faust        }
105*c217d954SCole Faust    #endif
106*c217d954SCole Faust
107*c217d954SCole Faust        void run()
108*c217d954SCole Faust        {
109*c217d954SCole Faust            ARM_COMPUTE_ASSERT(_ptr != nullptr);
110*c217d954SCole Faust        }
111*c217d954SCole Faust
112*c217d954SCole Faust        void teardown()
113*c217d954SCole Faust        {
114*c217d954SCole Faust            free(_ptr);
115*c217d954SCole Faust        }
116*c217d954SCole Faust
117*c217d954SCole Faust        void *_ptr;
118*c217d954SCole Faust    };
119*c217d954SCole Faust
120*c217d954SCole Faust@subsection tests_overview_test_cases Test cases
121*c217d954SCole Faust
122*c217d954SCole FaustAll following commands can be optionally prefixed with `EXPECTED_FAILURE_` or
123*c217d954SCole Faust`DISABLED_`.
124*c217d954SCole Faust
125*c217d954SCole Faust@subsubsection tests_overview_test_cases_test_case Test case
126*c217d954SCole Faust
127*c217d954SCole FaustA simple test case function taking no inputs and having no (shared) state.
128*c217d954SCole Faust
129*c217d954SCole Faust- First argument is the name of the test case (has to be unique within the
130*c217d954SCole Faust  enclosing test suite).
131*c217d954SCole Faust- Second argument is the dataset mode in which the test will be active.
132*c217d954SCole Faust
133*c217d954SCole Faust
134*c217d954SCole Faust    TEST_CASE(TestCaseName, DatasetMode::PRECOMMIT)
135*c217d954SCole Faust    {
136*c217d954SCole Faust        ARM_COMPUTE_ASSERT_EQUAL(1 + 1, 2);
137*c217d954SCole Faust    }
138*c217d954SCole Faust
139*c217d954SCole Faust@subsubsection tests_overview_test_cases_fixture_fixture_test_case Fixture test case
140*c217d954SCole Faust
141*c217d954SCole FaustA simple test case function taking no inputs that inherits from a fixture. The
142*c217d954SCole Fausttest case will have access to all public and protected members of the fixture.
143*c217d954SCole FaustOnly the setup and teardown methods of the fixture will be used. The body of
144*c217d954SCole Faustthis function will be used as test function.
145*c217d954SCole Faust
146*c217d954SCole Faust- First argument is the name of the test case (has to be unique within the
147*c217d954SCole Faust  enclosing test suite).
148*c217d954SCole Faust- Second argument is the class name of the fixture.
149*c217d954SCole Faust- Third argument is the dataset mode in which the test will be active.
150*c217d954SCole Faust
151*c217d954SCole Faust
152*c217d954SCole Faust    class FixtureName : public framework::Fixture
153*c217d954SCole Faust    {
154*c217d954SCole Faust        public:
155*c217d954SCole Faust            void setup() override
156*c217d954SCole Faust            {
157*c217d954SCole Faust                _one = 1;
158*c217d954SCole Faust            }
159*c217d954SCole Faust
160*c217d954SCole Faust        protected:
161*c217d954SCole Faust            int _one;
162*c217d954SCole Faust    };
163*c217d954SCole Faust
164*c217d954SCole Faust    FIXTURE_TEST_CASE(TestCaseName, FixtureName, DatasetMode::PRECOMMIT)
165*c217d954SCole Faust    {
166*c217d954SCole Faust        ARM_COMPUTE_ASSERT_EQUAL(_one + 1, 2);
167*c217d954SCole Faust    }
168*c217d954SCole Faust
169*c217d954SCole Faust@subsubsection tests_overview_test_cases_fixture_register_fixture_test_case Registering a fixture as test case
170*c217d954SCole Faust
171*c217d954SCole FaustAllows to use a fixture directly as test case. Instead of defining a new test
172*c217d954SCole Faustfunction the run method of the fixture will be executed.
173*c217d954SCole Faust
174*c217d954SCole Faust- First argument is the name of the test case (has to be unique within the
175*c217d954SCole Faust  enclosing test suite).
176*c217d954SCole Faust- Second argument is the class name of the fixture.
177*c217d954SCole Faust- Third argument is the dataset mode in which the test will be active.
178*c217d954SCole Faust
179*c217d954SCole Faust
180*c217d954SCole Faust    class FixtureName : public framework::Fixture
181*c217d954SCole Faust    {
182*c217d954SCole Faust        public:
183*c217d954SCole Faust            void setup() override
184*c217d954SCole Faust            {
185*c217d954SCole Faust                _one = 1;
186*c217d954SCole Faust            }
187*c217d954SCole Faust
188*c217d954SCole Faust            void run() override
189*c217d954SCole Faust            {
190*c217d954SCole Faust                ARM_COMPUTE_ASSERT_EQUAL(_one + 1, 2);
191*c217d954SCole Faust            }
192*c217d954SCole Faust
193*c217d954SCole Faust        protected:
194*c217d954SCole Faust            int _one;
195*c217d954SCole Faust    };
196*c217d954SCole Faust
197*c217d954SCole Faust    REGISTER_FIXTURE_TEST_CASE(TestCaseName, FixtureName, DatasetMode::PRECOMMIT);
198*c217d954SCole Faust
199*c217d954SCole Faust
200*c217d954SCole Faust@subsubsection tests_overview_test_cases_data_test_case Data test case
201*c217d954SCole Faust
202*c217d954SCole FaustA parameterized test case function that has no (shared) state. The dataset will
203*c217d954SCole Faustbe used to generate versions of the test case with different inputs.
204*c217d954SCole Faust
205*c217d954SCole Faust- First argument is the name of the test case (has to be unique within the
206*c217d954SCole Faust  enclosing test suite).
207*c217d954SCole Faust- Second argument is the dataset mode in which the test will be active.
208*c217d954SCole Faust- Third argument is the dataset.
209*c217d954SCole Faust- Further arguments specify names of the arguments to the test function. The
210*c217d954SCole Faust  number must match the arity of the dataset.
211*c217d954SCole Faust
212*c217d954SCole Faust
213*c217d954SCole Faust    DATA_TEST_CASE(TestCaseName, DatasetMode::PRECOMMIT, framework::make("Numbers", {1, 2, 3}), num)
214*c217d954SCole Faust    {
215*c217d954SCole Faust        ARM_COMPUTE_ASSERT(num < 4);
216*c217d954SCole Faust    }
217*c217d954SCole Faust
218*c217d954SCole Faust@subsubsection tests_overview_test_cases_fixture_data_test_case Fixture data test case
219*c217d954SCole Faust
220*c217d954SCole FaustA parameterized test case that inherits from a fixture. The test case will have
221*c217d954SCole Faustaccess to all public and protected members of the fixture. Only the setup and
222*c217d954SCole Faustteardown methods of the fixture will be used. The setup method of the fixture
223*c217d954SCole Faustneeds to be a template and has to accept inputs from the dataset as arguments.
224*c217d954SCole FaustThe body of this function will be used as test function. The dataset will be
225*c217d954SCole Faustused to generate versions of the test case with different inputs.
226*c217d954SCole Faust
227*c217d954SCole Faust- First argument is the name of the test case (has to be unique within the
228*c217d954SCole Faust  enclosing test suite).
229*c217d954SCole Faust- Second argument is the class name of the fixture.
230*c217d954SCole Faust- Third argument is the dataset mode in which the test will be active.
231*c217d954SCole Faust- Fourth argument is the dataset.
232*c217d954SCole Faust
233*c217d954SCole Faust
234*c217d954SCole Faust    class FixtureName : public framework::Fixture
235*c217d954SCole Faust    {
236*c217d954SCole Faust        public:
237*c217d954SCole Faust            template <typename T>
238*c217d954SCole Faust            void setup(T num)
239*c217d954SCole Faust            {
240*c217d954SCole Faust                _num = num;
241*c217d954SCole Faust            }
242*c217d954SCole Faust
243*c217d954SCole Faust        protected:
244*c217d954SCole Faust            int _num;
245*c217d954SCole Faust    };
246*c217d954SCole Faust
247*c217d954SCole Faust    FIXTURE_DATA_TEST_CASE(TestCaseName, FixtureName, DatasetMode::PRECOMMIT, framework::make("Numbers", {1, 2, 3}))
248*c217d954SCole Faust    {
249*c217d954SCole Faust        ARM_COMPUTE_ASSERT(_num < 4);
250*c217d954SCole Faust    }
251*c217d954SCole Faust
252*c217d954SCole Faust@subsubsection tests_overview_test_cases_register_fixture_data_test_case Registering a fixture as data test case
253*c217d954SCole Faust
254*c217d954SCole FaustAllows to use a fixture directly as parameterized test case. Instead of
255*c217d954SCole Faustdefining a new test function the run method of the fixture will be executed.
256*c217d954SCole FaustThe setup method of the fixture needs to be a template and has to accept inputs
257*c217d954SCole Faustfrom the dataset as arguments. The dataset will be used to generate versions of
258*c217d954SCole Faustthe test case with different inputs.
259*c217d954SCole Faust
260*c217d954SCole Faust- First argument is the name of the test case (has to be unique within the
261*c217d954SCole Faust  enclosing test suite).
262*c217d954SCole Faust- Second argument is the class name of the fixture.
263*c217d954SCole Faust- Third argument is the dataset mode in which the test will be active.
264*c217d954SCole Faust- Fourth argument is the dataset.
265*c217d954SCole Faust
266*c217d954SCole Faust
267*c217d954SCole Faust    class FixtureName : public framework::Fixture
268*c217d954SCole Faust    {
269*c217d954SCole Faust        public:
270*c217d954SCole Faust            template <typename T>
271*c217d954SCole Faust            void setup(T num)
272*c217d954SCole Faust            {
273*c217d954SCole Faust                _num = num;
274*c217d954SCole Faust            }
275*c217d954SCole Faust
276*c217d954SCole Faust            void run() override
277*c217d954SCole Faust            {
278*c217d954SCole Faust                ARM_COMPUTE_ASSERT(_num < 4);
279*c217d954SCole Faust            }
280*c217d954SCole Faust
281*c217d954SCole Faust        protected:
282*c217d954SCole Faust            int _num;
283*c217d954SCole Faust    };
284*c217d954SCole Faust
285*c217d954SCole Faust    REGISTER_FIXTURE_DATA_TEST_CASE(TestCaseName, FixtureName, DatasetMode::PRECOMMIT, framework::make("Numbers", {1, 2, 3}));
286*c217d954SCole Faust
287*c217d954SCole Faust@section writing_tests Writing validation tests
288*c217d954SCole Faust
289*c217d954SCole FaustBefore starting a new test case have a look at the existing ones. They should
290*c217d954SCole Faustprovide a good overview how test cases are structured.
291*c217d954SCole Faust
292*c217d954SCole Faust- The C++ reference needs to be added to `tests/validation/CPP/`. The
293*c217d954SCole Faust  reference function is typically a template parameterized by the underlying
294*c217d954SCole Faust  value type of the `SimpleTensor`. This makes it easy to specialise for
295*c217d954SCole Faust  different data types.
296*c217d954SCole Faust- If all backends have a common interface it makes sense to share the setup
297*c217d954SCole Faust  code. This can be done by adding a fixture in
298*c217d954SCole Faust  `tests/validation/fixtures/`. Inside of the `setup` method of a fixture
299*c217d954SCole Faust  the tensors can be created and initialised and the function can be configured
300*c217d954SCole Faust  and run. The actual test will only have to validate the results. To be shared
301*c217d954SCole Faust  among multiple backends the fixture class is usually a template that accepts
302*c217d954SCole Faust  the specific types (data, tensor class, function class etc.) as parameters.
303*c217d954SCole Faust- The actual test cases need to be added for each backend individually.
304*c217d954SCole Faust  Typically the will be multiple tests for different data types and for
305*c217d954SCole Faust  different execution modes, e.g. precommit and nightly.
306*c217d954SCole Faust
307*c217d954SCole Faust@section tests_running_tests Running tests
308*c217d954SCole Faust@subsection tests_running_tests_benchmark_and_validation Benchmarking and validation suites
309*c217d954SCole Faust@subsubsection tests_running_tests_benchmarking_filter Filter tests
310*c217d954SCole FaustAll tests can be run by invoking
311*c217d954SCole Faust
312*c217d954SCole Faust    ./arm_compute_benchmark ./data
313*c217d954SCole Faust
314*c217d954SCole Faustwhere `./data` contains the assets needed by the tests.
315*c217d954SCole Faust
316*c217d954SCole FaustIf only a subset of the tests has to be executed the `--filter` option takes a
317*c217d954SCole Faustregular expression to select matching tests.
318*c217d954SCole Faust
319*c217d954SCole Faust    ./arm_compute_benchmark --filter='^NEON/.*AlexNet' ./data
320*c217d954SCole Faust
321*c217d954SCole Faust@note Filtering will be much faster if the regular expression starts from the start ("^") or end ("$") of the line.
322*c217d954SCole Faust
323*c217d954SCole FaustAdditionally each test has a test id which can be used as a filter, too.
324*c217d954SCole FaustHowever, the test id is not guaranteed to be stable when new tests are added.
325*c217d954SCole FaustOnly for a specific build the same the test will keep its id.
326*c217d954SCole Faust
327*c217d954SCole Faust    ./arm_compute_benchmark --filter-id=10 ./data
328*c217d954SCole Faust
329*c217d954SCole FaustAll available tests can be displayed with the `--list-tests` switch.
330*c217d954SCole Faust
331*c217d954SCole Faust    ./arm_compute_benchmark --list-tests
332*c217d954SCole Faust
333*c217d954SCole FaustMore options can be found in the `--help` message.
334*c217d954SCole Faust
335*c217d954SCole Faust@subsubsection tests_running_tests_benchmarking_runtime Runtime
336*c217d954SCole FaustBy default every test is run once on a single thread. The number of iterations
337*c217d954SCole Faustcan be controlled via the `--iterations` option and the number of threads via
338*c217d954SCole Faust`--threads`.
339*c217d954SCole Faust
340*c217d954SCole Faust@subsubsection tests_running_tests_benchmarking_output Output
341*c217d954SCole FaustBy default the benchmarking results are printed in a human readable format on
342*c217d954SCole Faustthe command line. The colored output can be disabled via `--no-color-output`.
343*c217d954SCole FaustAs an alternative output format JSON is supported and can be selected via
344*c217d954SCole Faust`--log-format=json`. To write the output to a file instead of stdout the
345*c217d954SCole Faust`--log-file` option can be used.
346*c217d954SCole Faust
347*c217d954SCole Faust@subsubsection tests_running_tests_benchmarking_mode Mode
348*c217d954SCole FaustTests contain different datasets of different sizes, some of which will take several hours to run.
349*c217d954SCole FaustYou can select which datasets to use by using the `--mode` option, we recommed you use `--mode=precommit` to start with.
350*c217d954SCole Faust
351*c217d954SCole Faust@subsubsection tests_running_tests_benchmarking_instruments Instruments
352*c217d954SCole FaustYou can use the `--instruments` option to select one or more instruments to measure the execution time of the benchmark tests.
353*c217d954SCole Faust
354*c217d954SCole Faust`PMU` will try to read the CPU PMU events from the kernel (They need to be enabled on your platform)
355*c217d954SCole Faust
356*c217d954SCole Faust`MALI` will try to collect Arm® Mali™ hardware performance counters. (You need to have a recent enough Arm® Mali™ driver)
357*c217d954SCole Faust
358*c217d954SCole Faust`WALL_CLOCK_TIMER` will measure time using `gettimeofday`: this should work on all platforms.
359*c217d954SCole Faust
360*c217d954SCole FaustYou can pass a combinations of these instruments: `--instruments=PMU,MALI,WALL_CLOCK_TIMER`
361*c217d954SCole Faust
362*c217d954SCole Faust@note You need to make sure the instruments have been selected at compile time using the `pmu=1` or `mali=1` scons options.
363*c217d954SCole Faust
364*c217d954SCole Faust@subsubsection tests_running_examples Examples
365*c217d954SCole Faust
366*c217d954SCole FaustTo run all the precommit validation tests:
367*c217d954SCole Faust
368*c217d954SCole Faust	LD_LIBRARY_PATH=. ./arm_compute_validation --mode=precommit
369*c217d954SCole Faust
370*c217d954SCole FaustTo run the OpenCL precommit validation tests:
371*c217d954SCole Faust
372*c217d954SCole Faust	LD_LIBRARY_PATH=. ./arm_compute_validation --mode=precommit --filter="^CL.*"
373*c217d954SCole Faust
374*c217d954SCole FaustTo run the Arm® Neon™ precommit benchmark tests with PMU and Wall Clock timer in miliseconds instruments enabled:
375*c217d954SCole Faust
376*c217d954SCole Faust	LD_LIBRARY_PATH=. ./arm_compute_benchmark --mode=precommit --filter="^NEON.*" --instruments="pmu,wall_clock_timer_ms" --iterations=10
377*c217d954SCole Faust
378*c217d954SCole FaustTo run the OpenCL precommit benchmark tests with OpenCL kernel timers in miliseconds enabled:
379*c217d954SCole Faust
380*c217d954SCole Faust	LD_LIBRARY_PATH=. ./arm_compute_benchmark --mode=precommit --filter="^CL.*" --instruments="opencl_timer_ms" --iterations=10
381*c217d954SCole Faust
382*c217d954SCole Faust@note You might need to export the path to OpenCL library as well in your LD_LIBRARY_PATH if Compute Library was built with OpenCL enabled.
383*c217d954SCole Faust*/
384*c217d954SCole Faust} // namespace test
385*c217d954SCole Faust} // namespace arm_compute
386