aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoritz Pflanzer <moritz.pflanzer@arm.com>2017-07-05 11:07:07 +0100
committerAnthony Barbier <anthony.barbier@arm.com>2018-09-17 14:15:39 +0100
commitfc95ed2b9900471922d93c963b263f1f506da167 (patch)
tree765f6a94e965ed47b0c0215a725f869e0619a611
parent7d323a6adca97c130a0fc7c6299c75d581906edd (diff)
downloadComputeLibrary-fc95ed2b9900471922d93c963b263f1f506da167.tar.gz
COMPMID-415: New framework - base framework [1/5]
Change-Id: Icfbfb43321c3bbe6e2aa511dd03a613eed7734a5 Reviewed-on: http://mpd-gerrit.cambridge.arm.com/79760 Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com> Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
-rw-r--r--SConstruct1
-rw-r--r--docs/Doxyfile8
-rw-r--r--framework/Exceptions.h44
-rw-r--r--framework/Fixture.h63
-rw-r--r--framework/Framework.cpp286
-rw-r--r--framework/Framework.h240
-rw-r--r--framework/Macros.h188
-rw-r--r--framework/Registrars.h108
-rw-r--r--framework/SConscript68
-rw-r--r--framework/TestCase.h70
-rw-r--r--framework/TestCaseFactory.h139
-rw-r--r--framework/TestResult.h66
-rw-r--r--framework/Utils.h143
-rwxr-xr-xscripts/add_copyright.py12
-rwxr-xr-xscripts/check_bad_style.sh2
-rwxr-xr-xscripts/clang-tidy.sh8
-rw-r--r--scripts/copyright_mit.txt2
-rwxr-xr-xscripts/fix_code_formatting.sh2
-rwxr-xr-xscripts/format_doxygen.py2
-rw-r--r--support/ToolchainSupport.h6
-rw-r--r--tests/validation/system_tests/CL/AlexNet.cpp23
-rw-r--r--tests/validation/system_tests/CL/LeNet5.cpp23
-rw-r--r--tests/validation/system_tests/NEON/AlexNet.cpp23
-rw-r--r--tests/validation/system_tests/NEON/LeNet5.cpp23
24 files changed, 1531 insertions, 19 deletions
diff --git a/SConstruct b/SConstruct
index e23b2d239e..309e2eb880 100644
--- a/SConstruct
+++ b/SConstruct
@@ -210,4 +210,5 @@ if env['opencl']:
if env['examples']:
SConscript('./examples/SConscript', variant_dir='#build/%s/examples' % env['build_dir'], duplicate=0)
+SConscript('./framework/SConscript', variant_dir='#build/%s/framework' % env['build_dir'], duplicate=0)
SConscript('./tests/SConscript', variant_dir='#build/%s/tests' % env['build_dir'], duplicate=0)
diff --git a/docs/Doxyfile b/docs/Doxyfile
index 4a8815572b..31181364c8 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -776,8 +776,10 @@ INPUT = ./docs/00_introduction.dox \
./scripts/ \
./src/core/CL/cl_kernels/ \
./examples/ \
+ ./framework/ \
./tests/ \
- ./utils/
+ ./utils/ \
+ ./support/
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -1056,7 +1058,7 @@ VERBATIM_HEADERS = YES
# compiled with the --with-libclang option.
# The default value is: NO.
-#CLANG_ASSISTED_PARSING = NO
+CLANG_ASSISTED_PARSING = YES
# If clang assisted parsing is enabled you can provide the compiler with command
# line options that you would normally use when invoking the compiler. Note that
@@ -1064,7 +1066,7 @@ VERBATIM_HEADERS = YES
# specified with INPUT and INCLUDE_PATH.
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
-#CLANG_OPTIONS =
+CLANG_OPTIONS = -std=c++11
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
diff --git a/framework/Exceptions.h b/framework/Exceptions.h
new file mode 100644
index 0000000000..4e42971cd0
--- /dev/null
+++ b/framework/Exceptions.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_EXCEPTIONS
+#define ARM_COMPUTE_TEST_EXCEPTIONS
+
+#include <stdexcept>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Error class for failures during test execution. */
+class TestError : public std::runtime_error
+{
+public:
+ using std::runtime_error::runtime_error;
+};
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_EXCEPTIONS */
diff --git a/framework/Fixture.h b/framework/Fixture.h
new file mode 100644
index 0000000000..916dcc7fef
--- /dev/null
+++ b/framework/Fixture.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_FIXTURE
+#define ARM_COMPUTE_TEST_FIXTURE
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Abstract fixture class.
+ *
+ * All custom fixtures have to inherit from this class.
+ */
+class Fixture
+{
+public:
+ /** Setup function.
+ *
+ * This function is only invoked by non-data fixture test cases. Fixture
+ * data test cases implement a setup function with arguments matching the
+ * dataset.
+ *
+ * The function is called before the test case is executed.
+ */
+ void setup() {};
+
+ /** Teardown function.
+ *
+ * The function is called after the test case finished.
+ */
+ void teardown() {};
+
+protected:
+ Fixture() = default;
+ virtual ~Fixture() = default;
+};
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_FIXTURE */
diff --git a/framework/Framework.cpp b/framework/Framework.cpp
new file mode 100644
index 0000000000..b54c0c75b6
--- /dev/null
+++ b/framework/Framework.cpp
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Framework.h"
+
+#include "Exceptions.h"
+#include "support/ToolchainSupport.h"
+
+#include <chrono>
+#include <iostream>
+#include <sstream>
+#include <type_traits>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+std::tuple<int, int, int> Framework::count_test_results() const
+{
+ int passed = 0;
+ int failed = 0;
+ int crashed = 0;
+
+ for(const auto &test : _test_results)
+ {
+ switch(test.second.status)
+ {
+ case TestResult::Status::SUCCESS:
+ ++passed;
+ break;
+ case TestResult::Status::FAILED:
+ ++failed;
+ break;
+ case TestResult::Status::CRASHED:
+ ++crashed;
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+ }
+
+ return std::make_tuple(passed, failed, crashed);
+}
+
+Framework &Framework::get()
+{
+ static Framework instance;
+ return instance;
+}
+
+void Framework::init(int num_iterations, const std::string &name_filter, const std::string &id_filter)
+{
+ _test_name_filter = std::regex{ name_filter };
+ _test_id_filter = std::regex{ id_filter };
+ _num_iterations = num_iterations;
+}
+
+std::string Framework::current_suite_name() const
+{
+ return join(_test_suite_name.cbegin(), _test_suite_name.cend(), "/");
+}
+
+void Framework::push_suite(std::string name)
+{
+ _test_suite_name.emplace_back(std::move(name));
+}
+
+void Framework::pop_suite()
+{
+ _test_suite_name.pop_back();
+}
+
+void Framework::log_test_start(const std::string &test_name)
+{
+ static_cast<void>(test_name);
+}
+
+void Framework::log_test_skipped(const std::string &test_name)
+{
+ static_cast<void>(test_name);
+}
+
+void Framework::log_test_end(const std::string &test_name)
+{
+ static_cast<void>(test_name);
+}
+
+void Framework::log_failed_expectation(const std::string &msg)
+{
+ std::cerr << "ERROR: " << msg << "\n";
+}
+
+int Framework::num_iterations() const
+{
+ return _num_iterations;
+}
+
+void Framework::set_num_iterations(int num_iterations)
+{
+ _num_iterations = num_iterations;
+}
+
+void Framework::set_throw_errors(bool throw_errors)
+{
+ _throw_errors = throw_errors;
+}
+
+bool Framework::throw_errors() const
+{
+ return _throw_errors;
+}
+
+bool Framework::is_enabled(const TestId &id) const
+{
+ return (std::regex_search(support::cpp11::to_string(id.first), _test_id_filter) && std::regex_search(id.second, _test_name_filter));
+}
+
+void Framework::run_test(TestCaseFactory &test_factory)
+{
+ const std::string test_case_name = test_factory.name();
+
+ log_test_start(test_case_name);
+
+ TestResult result;
+
+ try
+ {
+ std::unique_ptr<TestCase> test_case = test_factory.make();
+
+ try
+ {
+ test_case->do_setup();
+
+ for(int i = 0; i < _num_iterations; ++i)
+ {
+ test_case->do_run();
+ }
+
+ test_case->do_teardown();
+
+ result.status = TestResult::Status::SUCCESS;
+ }
+ catch(const TestError &error)
+ {
+ std::cerr << "FATAL ERROR: " << error.what() << "\n";
+ result.status = TestResult::Status::FAILED;
+
+ if(_throw_errors)
+ {
+ throw;
+ }
+ }
+ catch(const std::exception &error)
+ {
+ std::cerr << "FATAL ERROR: Received unhandled error: '" << error.what() << "'\n";
+ result.status = TestResult::Status::CRASHED;
+
+ if(_throw_errors)
+ {
+ throw;
+ }
+ }
+ catch(...)
+ {
+ std::cerr << "FATAL ERROR: Received unhandled exception\n";
+ result.status = TestResult::Status::CRASHED;
+
+ if(_throw_errors)
+ {
+ throw;
+ }
+ }
+ }
+ catch(const std::exception &error)
+ {
+ std::cerr << "FATAL ERROR: Received unhandled error during fixture creation: '" << error.what() << "'\n";
+
+ if(_throw_errors)
+ {
+ throw;
+ }
+ }
+ catch(...)
+ {
+ std::cerr << "FATAL ERROR: Received unhandled exception during fixture creation\n";
+
+ if(_throw_errors)
+ {
+ throw;
+ }
+ }
+
+ set_test_result(test_case_name, result);
+ log_test_end(test_case_name);
+}
+
+bool Framework::run()
+{
+ // Clear old test results
+ _test_results.clear();
+ _runtime = std::chrono::seconds{ 0 };
+
+ const auto start = std::chrono::high_resolution_clock::now();
+
+ int id = 0;
+
+ for(auto &test_factory : _test_factories)
+ {
+ const std::string test_case_name = test_factory->name();
+
+ if(!is_enabled(TestId(id, test_case_name)))
+ {
+ log_test_skipped(test_case_name);
+ }
+ else
+ {
+ run_test(*test_factory);
+ }
+
+ ++id;
+ }
+
+ const auto end = std::chrono::high_resolution_clock::now();
+
+ _runtime = std::chrono::duration_cast<std::chrono::seconds>(end - start);
+
+ int passed = 0;
+ int failed = 0;
+ int crashed = 0;
+
+ std::tie(passed, failed, crashed) = count_test_results();
+
+ std::cout << "Executed " << _test_results.size() << " test(s) (" << passed << " passed, " << failed << " failed, " << crashed << " crashed) in " << _runtime.count() << " second(s)\n";
+
+ return (static_cast<unsigned int>(passed) == _test_results.size());
+}
+
+void Framework::set_test_result(std::string test_case_name, TestResult result)
+{
+ _test_results.emplace(std::move(test_case_name), result);
+}
+
+std::vector<Framework::TestId> Framework::test_ids() const
+{
+ std::vector<TestId> ids;
+
+ int id = 0;
+
+ for(const auto &factory : _test_factories)
+ {
+ if(is_enabled(TestId(id, factory->name())))
+ {
+ ids.emplace_back(id, factory->name());
+ }
+
+ ++id;
+ }
+
+ return ids;
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
diff --git a/framework/Framework.h b/framework/Framework.h
new file mode 100644
index 0000000000..e9beafd6eb
--- /dev/null
+++ b/framework/Framework.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_FRAMEWORK
+#define ARM_COMPUTE_TEST_FRAMEWORK
+
+#include "TestCase.h"
+#include "TestCaseFactory.h"
+#include "TestResult.h"
+#include "Utils.h"
+
+#include <algorithm>
+#include <chrono>
+#include <map>
+#include <memory>
+#include <numeric>
+#include <ostream>
+#include <regex>
+#include <set>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Main framework class.
+ *
+ * Keeps track of the global state, owns all test cases and collects results.
+ */
+class Framework final
+{
+public:
+ /** Type of a test identifier.
+ *
+ * A test can be identified either via its id or via its name.
+ *
+ * @note The mapping between test id and test name is not guaranteed to be
+ * stable. It is subject to change as new test are added.
+ */
+ using TestId = std::pair<int, std::string>;
+
+ /** Access to the singleton.
+ *
+ * @return Unique instance of the framework class.
+ */
+ static Framework &get();
+
+ /** Init the framework.
+ *
+ * @param[in] num_iterations Number of iterations per test.
+ * @param[in] name_filter Regular expression to filter tests by name. Only matching tests will be executed.
+ * @param[in] id_filter Regular expression to filter tests by id. Only matching tests will be executed.
+ */
+ void init(int num_iterations, const std::string &name_filter, const std::string &id_filter);
+
+ /** Add a new test suite.
+ *
+ * @warning Cannot be used at execution time. It can only be used for
+ * registering test cases.
+ *
+ * @param[in] name Name of the added test suite.
+ *
+ * @return Name of the current test suite.
+ */
+ void push_suite(std::string name);
+
+ /** Remove innermost test suite.
+ *
+ * @warning Cannot be used at execution time. It can only be used for
+ * registering test cases.
+ */
+ void pop_suite();
+
+ /** Add a test case to the framework.
+ *
+ * @param[in] test_name Name of the new test case.
+ */
+ template <typename T>
+ void add_test_case(std::string test_name);
+
+ /** Add a data test case to the framework.
+ *
+ * @param[in] test_name Name of the new test case.
+ * @param[in] description Description of @p data.
+ * @param[in] data Data that will be used as input to the test.
+ */
+ template <typename T, typename D>
+ void add_data_test_case(std::string test_name, std::string description, D &&data);
+
+ /** Tell the framework that execution of a test starts.
+ *
+ * @param[in] test_name Name of the started test case.
+ */
+ void log_test_start(const std::string &test_name);
+
+ /** Tell the framework that a test case is skipped.
+ *
+ * @param[in] test_name Name of the skipped test case.
+ */
+ void log_test_skipped(const std::string &test_name);
+
+ /** Tell the framework that a test case finished.
+ *
+ * @param[in] test_name Name of the finished test case.
+ */
+ void log_test_end(const std::string &test_name);
+
+ /** Tell the framework that the currently running test case failed a non-fatal expectation.
+ *
+ * @param[in] msg Description of the failure.
+ */
+ void log_failed_expectation(const std::string &msg);
+
+ /** Number of iterations per test case.
+ *
+ * @return Number of iterations per test case.
+ */
+ int num_iterations() const;
+
+ /** Set number of iterations per test case.
+ *
+ * @param[in] num_iterations Number of iterations per test case.
+ */
+ void set_num_iterations(int num_iterations);
+
+ /** Should errors be caught or thrown by the framework.
+ *
+ * @return True if errors are thrown.
+ */
+ bool throw_errors() const;
+
+ /** Set whether errors are caught or thrown by the framework.
+ *
+ * @param[in] throw_errors True if errors should be thrown.
+ */
+ void set_throw_errors(bool throw_errors);
+
+ /** Check if a test case would be executed.
+ *
+ * @param[in] id Id of the test case.
+ *
+ * @return True if the test case would be executed.
+ */
+ bool is_enabled(const TestId &id) const;
+
+ /** Run all enabled test cases.
+ *
+ * @return True if all test cases executed successful.
+ */
+ bool run();
+
+ /** Set the result for an executed test case.
+ *
+ * @param[in] test_case_name Name of the executed test case.
+ * @param[in] result Execution result.
+ */
+ void set_test_result(std::string test_case_name, TestResult result);
+
+ /** List of @ref TestId's.
+ *
+ * @return Vector with all test ids.
+ */
+ std::vector<Framework::TestId> test_ids() const;
+
+private:
+ Framework() = default;
+ ~Framework() = default;
+
+ Framework(const Framework &) = delete;
+ Framework &operator=(const Framework &) = delete;
+
+ void run_test(TestCaseFactory &test_factory);
+ std::tuple<int, int, int> count_test_results() const;
+
+ /** Returns the current test suite name.
+ *
+ * @warning Cannot be used at execution time to get the test suite of the
+ * currently executed test case. It can only be used for registering test
+ * cases.
+ *
+ * @return Name of the current test suite.
+ */
+ std::string current_suite_name() const;
+
+ std::vector<std::string> _test_suite_name{};
+ std::vector<std::unique_ptr<TestCaseFactory>> _test_factories{};
+ std::map<std::string, TestResult> _test_results{};
+ std::chrono::seconds _runtime{ 0 };
+ int _num_iterations{ 1 };
+ bool _throw_errors{ false };
+
+ std::regex _test_name_filter{ ".*" };
+ std::regex _test_id_filter{ ".*" };
+};
+
+template <typename T>
+inline void Framework::add_test_case(std::string test_name)
+{
+ _test_factories.emplace_back(support::cpp14::make_unique<SimpleTestCaseFactory<T>>(current_suite_name(), std::move(test_name)));
+}
+
+template <typename T, typename D>
+inline void Framework::add_data_test_case(std::string test_name, std::string description, D &&data)
+{
+ // WORKAROUND for GCC 4.9
+ // The function should get *it which is tuple but that seems to trigger a
+ // bug in the compiler.
+ auto tmp = std::unique_ptr<DataTestCaseFactory<T, decltype(*std::declval<D>())>>(new DataTestCaseFactory<T, decltype(*std::declval<D>())>(current_suite_name(), std::move(test_name),
+ std::move(description), *data));
+ _test_factories.emplace_back(std::move(tmp));
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_FRAMEWORK */
diff --git a/framework/Macros.h b/framework/Macros.h
new file mode 100644
index 0000000000..e3ef71ac56
--- /dev/null
+++ b/framework/Macros.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_FRAMEWORK_MACROS
+#define ARM_COMPUTE_TEST_FRAMEWORK_MACROS
+
+#include "Exceptions.h"
+#include "Framework.h"
+#include "Registrars.h"
+#include "TestCase.h"
+
+#include <sstream>
+
+//
+// TEST SUITE MACROS
+//
+#define TEST_SUITE(SUITE_NAME) \
+ namespace SUITE_NAME##Suite \
+ { \
+ static arm_compute::test::framework::detail::TestSuiteRegistrar SUITE_NAME##Suite_reg{ #SUITE_NAME };
+
+#define TEST_SUITE_END() \
+ static arm_compute::test::framework::detail::TestSuiteRegistrar Suite_end; \
+ }
+//
+// TEST SUITE MACROS END
+//
+
+//
+// TEST CASE MACROS
+//
+#define TEST_CASE_CONSTRUCTOR(TEST_NAME) \
+ TEST_NAME() = default;
+#define DATA_TEST_CASE_CONSTRUCTOR(TEST_NAME, DATASET) \
+ template <typename D> \
+ explicit TEST_NAME(D &&data) : DataTestCase{ std::forward<D>(data) } \
+ { \
+ }
+#define FIXTURE_SETUP(FIXTURE) \
+ void do_setup() override \
+ { \
+ FIXTURE::setup(); \
+ }
+#define FIXTURE_DATA_SETUP(FIXTURE) \
+ void do_setup() override \
+ { \
+ apply(this, &FIXTURE::setup, _data); \
+ }
+#define FIXTURE_RUN(FIXTURE) \
+ void do_run() override \
+ { \
+ FIXTURE::run(); \
+ }
+#define FIXTURE_TEARDOWN(FIXTURE) \
+ void do_teardown() override \
+ { \
+ FIXTURE::teardown(); \
+ }
+#define TEST_REGISTRAR(TEST_NAME) \
+ static arm_compute::test::framework::detail::TestCaseRegistrar<TEST_NAME> TEST_NAME##_reg \
+ { \
+ #TEST_NAME \
+ }
+#define DATA_TEST_REGISTRAR(TEST_NAME, DATASET) \
+ static arm_compute::test::framework::detail::TestCaseRegistrar<TEST_NAME> TEST_NAME##_reg \
+ { \
+ #TEST_NAME, DATASET \
+ }
+
+#define TEST_CASE(TEST_NAME) \
+ class TEST_NAME : public arm_compute::test::framework::TestCase \
+ { \
+ public: \
+ TEST_CASE_CONSTRUCTOR(TEST_NAME) \
+ void do_run() override; \
+ }; \
+ TEST_REGISTRAR(TEST_NAME); \
+ void TEST_NAME::do_run()
+
+#define DATA_TEST_CASE(TEST_NAME, DATASET, ...) \
+ class TEST_NAME : public arm_compute::test::framework::DataTestCase<decltype(DATASET)::type> \
+ { \
+ public: \
+ DATA_TEST_CASE_CONSTRUCTOR(TEST_NAME, DATASET) \
+ void do_run() override \
+ { \
+ arm_compute::test::framework::apply(this, &TEST_NAME::run, _data); \
+ } \
+ void run(__VA_ARGS__); \
+ }; \
+ DATA_TEST_REGISTRAR(TEST_NAME, DATASET); \
+ void TEST_NAME::run(__VA_ARGS__)
+
+#define FIXTURE_TEST_CASE(TEST_NAME, FIXTURE) \
+ class TEST_NAME : public arm_compute::test::framework::TestCase, public FIXTURE \
+ { \
+ public: \
+ TEST_CASE_CONSTRUCTOR(TEST_NAME) \
+ FIXTURE_SETUP(FIXTURE) \
+ void do_run() override; \
+ FIXTURE_TEARDOWN(FIXTURE) \
+ }; \
+ TEST_REGISTRAR(TEST_NAME); \
+ void TEST_NAME::do_run()
+
+#define FIXTURE_DATA_TEST_CASE(TEST_NAME, FIXTURE, DATASET) \
+ class TEST_NAME : public arm_compute::test::framework::DataTestCase<decltype(DATASET)::type>, public FIXTURE \
+ { \
+ public: \
+ DATA_TEST_CASE_CONSTRUCTOR(TEST_NAME, DATASET) \
+ FIXTURE_DATA_SETUP(FIXTURE) \
+ void do_run() override; \
+ FIXTURE_TEARDOWN(FIXTURE) \
+ }; \
+ DATA_TEST_REGISTRAR(TEST_NAME, DATASET); \
+ void TEST_NAME::do_run()
+
+#define REGISTER_FIXTURE_TEST_CASE(TEST_NAME, FIXTURE) \
+ class TEST_NAME : public arm_compute::test::framework::TestCase, public FIXTURE \
+ { \
+ public: \
+ TEST_CASE_CONSTRUCTOR(TEST_NAME) \
+ FIXTURE_SETUP(FIXTURE) \
+ FIXTURE_RUN(FIXTURE) \
+ FIXTURE_TEARDOWN(FIXTURE) \
+ }; \
+ TEST_REGISTRAR(TEST_NAME)
+
+#define REGISTER_FIXTURE_DATA_TEST_CASE(TEST_NAME, FIXTURE, DATASET) \
+ class TEST_NAME : public arm_compute::test::framework::DataTestCase<decltype(DATASET)::type>, public FIXTURE \
+ { \
+ public: \
+ DATA_TEST_CASE_CONSTRUCTOR(TEST_NAME, DATASET) \
+ FIXTURE_DATA_SETUP(FIXTURE) \
+ FIXTURE_RUN(FIXTURE) \
+ FIXTURE_TEARDOWN(FIXTURE) \
+ }; \
+ DATA_TEST_REGISTRAR(TEST_NAME, DATASET)
+//
+// TEST CASE MACROS END
+//
+
+#define ARM_COMPUTE_ASSERT_EQUAL(x, y) \
+ do \
+ { \
+ const auto &_x = (x); \
+ const auto &_y = (y); \
+ if(_x != _y) \
+ { \
+ std::stringstream msg; \
+ msg << "Assertion " << _x << " != " << _y << " failed."; \
+ throw arm_compute::test::framework::TestError(msg.str()); \
+ } \
+ } while(false)
+
+#define ARM_COMPUTE_EXPECT_EQUAL(x, y) \
+ do \
+ { \
+ const auto &_x = (x); \
+ const auto &_y = (y); \
+ if(_x != _y) \
+ { \
+ std::stringstream msg; \
+ msg << "Expectation " << _x << " != " << _y << " failed."; \
+ arm_compute::test::framework::Framework::get().log_failed_expectation(msg.str()); \
+ } \
+ } while(false)
+#endif /* ARM_COMPUTE_TEST_FRAMEWORK_MACROS */
diff --git a/framework/Registrars.h b/framework/Registrars.h
new file mode 100644
index 0000000000..19064c07f5
--- /dev/null
+++ b/framework/Registrars.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_FRAMEWORK_REGISTRARS
+#define ARM_COMPUTE_TEST_FRAMEWORK_REGISTRARS
+
+#include "Framework.h"
+
+#include <string>
+#include <utility>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+namespace detail
+{
+/** Helper class to statically register a test case. */
+template <typename T>
+class TestCaseRegistrar final
+{
+public:
+ /** Add a new test case with the given name to the framework.
+ *
+ * @param[in] test_name Name of the test case.
+ */
+ TestCaseRegistrar(std::string test_name);
+
+ /** Add a new data test case with the given name to the framework.
+ *
+ * @param[in] test_name Name of the test case.
+ * @param[in] dataset Dataset used as input for the test case.
+ */
+ template <typename D>
+ TestCaseRegistrar(std::string test_name, D &&dataset);
+};
+
+/** Helper class to statically begin and end a test suite. */
+class TestSuiteRegistrar final
+{
+public:
+ /** Remove the last added test suite from the framework. */
+ TestSuiteRegistrar();
+
+ /** Add a new test suite with the given name to the framework.
+ *
+ * @param[in] name Name of the test suite.
+ */
+ TestSuiteRegistrar(std::string name);
+};
+
+template <typename T>
+inline TestCaseRegistrar<T>::TestCaseRegistrar(std::string test_name)
+{
+ Framework::get().add_test_case<T>(std::move(test_name));
+}
+
+template <typename T>
+template <typename D>
+inline TestCaseRegistrar<T>::TestCaseRegistrar(std::string test_name, D &&dataset)
+{
+ auto it = dataset.begin();
+
+ for(int i = 0; i < dataset.size(); ++i, ++it)
+ {
+ // WORKAROUND for GCC 4.9
+ // The last argument should be *it to pass just the data and not the
+ // iterator.
+ Framework::get().add_data_test_case<T>(test_name, it.description(), it);
+ }
+}
+
+inline TestSuiteRegistrar::TestSuiteRegistrar()
+{
+ Framework::get().pop_suite();
+}
+
+inline TestSuiteRegistrar::TestSuiteRegistrar(std::string name)
+{
+ Framework::get().push_suite(std::move(name));
+}
+} // namespace detail
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_FRAMEWORK_REGISTRARS */
diff --git a/framework/SConscript b/framework/SConscript
new file mode 100644
index 0000000000..bf98241ca9
--- /dev/null
+++ b/framework/SConscript
@@ -0,0 +1,68 @@
+# Copyright (c) 2017 ARM Limited.
+#
+# SPDX-License-Identifier: MIT
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+import SCons
+import os.path
+
+Import('env')
+Import('vars')
+
+# vars is imported from arm_compute:
+variables = [
+ BoolVariable("pmu", "Enable PMU counters", False)
+]
+
+# We need a separate set of Variables for the Help message (Otherwise the global variables will get displayed twice)
+new_options = Variables('scons')
+
+for v in variables:
+ new_options.Add(v)
+ vars.Add(v)
+
+# Clone the environment to make sure we're not polluting the arm_compute one:
+framework_env = env.Clone()
+vars.Update(framework_env)
+
+Help(new_options.GenerateHelpText(framework_env))
+
+if env['os'] == 'android' and framework_env['pmu']:
+ print("pmu=1 is not supported for os=android")
+ Exit(1)
+
+framework_env.Append(CPPPATH = ["."])
+framework_env.Append(CPPFLAGS=['-Wno-overloaded-virtual'])
+
+files = Glob('*.cpp')
+files += Glob('command_line/*.cpp')
+files += Glob('printers/*.cpp')
+files += Glob('datasets/*.cpp')
+files += Glob('instruments/*.cpp')
+
+if not framework_env['pmu']:
+ # Remove PMU files
+ files = [f for f in files if "PMU" not in os.path.basename(str(f))]
+else:
+ framework_env.Append(CPPDEFINES = ['PMU_ENABLED'])
+
+arm_compute_test_framework = framework_env.StaticLibrary('arm_compute_test_framework', files)
+
+Default(arm_compute_test_framework)
+Export('arm_compute_test_framework')
diff --git a/framework/TestCase.h b/framework/TestCase.h
new file mode 100644
index 0000000000..43750b1d1b
--- /dev/null
+++ b/framework/TestCase.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_TESTCASE
+#define ARM_COMPUTE_TEST_TESTCASE
+
+#include <string>
+#include <utility>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Abstract test case class.
+ *
+ * All test cases have to inherit from this class.
+ */
+class TestCase
+{
+public:
+ virtual void do_setup() {};
+ virtual void do_run() {};
+ virtual void do_teardown() {};
+
+ /** Default destructor. */
+ virtual ~TestCase() = default;
+
+protected:
+ TestCase() = default;
+
+ friend class TestCaseFactory;
+};
+
+template <typename T>
+class DataTestCase : public TestCase
+{
+protected:
+ explicit DataTestCase(T data)
+ : _data{ data }
+ {
+ }
+
+ T _data;
+};
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_TESTCASE */
diff --git a/framework/TestCaseFactory.h b/framework/TestCaseFactory.h
new file mode 100644
index 0000000000..09e9d198d6
--- /dev/null
+++ b/framework/TestCaseFactory.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_TEST_CASE_FACTORY
+#define ARM_COMPUTE_TEST_TEST_CASE_FACTORY
+
+#include "TestCase.h"
+#include "support/ToolchainSupport.h"
+
+#include <memory>
+#include <string>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Abstract factory class to create test cases. */
+class TestCaseFactory
+{
+public:
+ /** Constructor.
+ *
+ * @param[in] suite_name Name of the test suite to which the test case has been added.
+ * @param[in] name Name of the test case.
+ * @param[in] description Description of data arguments.
+ */
+ TestCaseFactory(std::string suite_name, std::string name, std::string description = "");
+
+ /** Default destructor. */
+ virtual ~TestCaseFactory() = default;
+
+ /** Name of the test case.
+ *
+ * @return Name of the test case.
+ */
+ std::string name() const;
+
+ /** Factory function to create the test case
+ *
+ * @return Unique pointer to a newly created test case.
+ */
+ virtual std::unique_ptr<TestCase> make() const = 0;
+
+private:
+ const std::string _suite_name;
+ const std::string _test_name;
+ const std::string _data_description;
+};
+
+/** Implementation of a test case factory to create non-data test cases. */
+template <typename T>
+class SimpleTestCaseFactory final : public TestCaseFactory
+{
+public:
+ /** Default constructor. */
+ using TestCaseFactory::TestCaseFactory;
+
+ std::unique_ptr<TestCase> make() const override;
+};
+
+template <typename T, typename D>
+class DataTestCaseFactory final : public TestCaseFactory
+{
+public:
+ /** Constructor.
+ *
+ * @param[in] suite_name Name of the test suite to which the test case has been added.
+ * @param[in] test_name Name of the test case.
+ * @param[in] description Description of data arguments.
+ * @param[in] data Input data for the test case.
+ */
+ DataTestCaseFactory(std::string suite_name, std::string test_name, std::string description, const D &data);
+
+ std::unique_ptr<TestCase> make() const override;
+
+private:
+ D _data;
+};
+
+inline TestCaseFactory::TestCaseFactory(std::string suite_name, std::string test_name, std::string description)
+ : _suite_name{ std::move(suite_name) }, _test_name{ std::move(test_name) }, _data_description{ std::move(description) }
+{
+}
+
+inline std::string TestCaseFactory::name() const
+{
+ std::string name = _suite_name + "/" + _test_name;
+
+ if(!_data_description.empty())
+ {
+ name += "@" + _data_description;
+ }
+
+ return name;
+}
+
+template <typename T>
+inline std::unique_ptr<TestCase> SimpleTestCaseFactory<T>::make() const
+{
+ return support::cpp14::make_unique<T>();
+}
+
+template <typename T, typename D>
+inline DataTestCaseFactory<T, D>::DataTestCaseFactory(std::string suite_name, std::string test_name, std::string description, const D &data)
+ : TestCaseFactory{ std::move(suite_name), std::move(test_name), std::move(description) }, _data{ data }
+{
+}
+
+template <typename T, typename D>
+inline std::unique_ptr<TestCase> DataTestCaseFactory<T, D>::make() const
+{
+ return support::cpp14::make_unique<T>(_data);
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_TEST_CASE_FACTORY */
diff --git a/framework/TestResult.h b/framework/TestResult.h
new file mode 100644
index 0000000000..c860cbc22c
--- /dev/null
+++ b/framework/TestResult.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_TESTRESULT
+#define ARM_COMPUTE_TEST_TESTRESULT
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Class to store results of a test.
+ *
+ * Currently the execution status and profiling information are stored.
+ */
+struct TestResult
+{
+ /** Execution status of a test. */
+ enum class Status
+ {
+ NOT_RUN,
+ SUCCESS,
+ EXPECTED_FAILURE,
+ FAILED,
+ CRASHED
+ };
+
+ /** Default constructor. */
+ TestResult() = default;
+
+ /** Initialise the result with a status.
+ *
+ * @param[in] status Execution status.
+ */
+ TestResult(Status status)
+ : status{ status }
+ {
+ }
+
+ Status status{ Status::NOT_RUN }; //< Execution status
+};
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_TESTRESULT */
diff --git a/framework/Utils.h b/framework/Utils.h
new file mode 100644
index 0000000000..e9298618e8
--- /dev/null
+++ b/framework/Utils.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_UTILS
+#define ARM_COMPUTE_TEST_UTILS
+
+#include "support/ToolchainSupport.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstddef>
+#include <limits>
+#include <memory>
+#include <numeric>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** @cond */
+namespace detail
+{
+template <int...>
+struct sequence
+{
+};
+
+template <int N, int... Ns>
+struct sequence_generator;
+
+template <int... Ns>
+struct sequence_generator<0, Ns...>
+{
+ using type = sequence<Ns...>;
+};
+
+template <int N, int... Ns>
+struct sequence_generator : sequence_generator < N - 1, N - 1, Ns... >
+{
+};
+
+template <int N>
+using sequence_t = typename sequence_generator<N>::type;
+/** @endcond */
+
+template <typename O, typename F, typename... As, int... S>
+void apply_impl(O *obj, F &&func, const std::tuple<As...> &args, detail::sequence<S...>)
+{
+ (obj->*func)(std::get<S>(args)...);
+}
+} // namespace
+
+template <typename O, typename F, typename... As>
+void apply(O *obj, F &&func, const std::tuple<As...> &args)
+{
+ detail::apply_impl(obj, std::forward<F>(func), args, detail::sequence_t<sizeof...(As)>());
+}
+
+/** Helper function to concatenate multiple strings.
+ *
+ * @param[in] first Iterator pointing to the first element to be concatenated.
+ * @param[in] last Iterator pointing behind the last element to be concatenated.
+ * @param[in] separator String used to join the elements.
+ *
+ * @return String containing all elements joined by @p separator.
+ */
+template <typename T, typename std::enable_if<std::is_same<typename T::value_type, std::string>::value, int>::type = 0>
+std::string join(T first, T last, const std::string &separator)
+{
+ return std::accumulate(std::next(first), last, *first, [&separator](const std::string & base, const std::string & suffix)
+ {
+ return base + separator + suffix;
+ });
+}
+
+/** Helper function to concatenate multiple values.
+ *
+ * All values are converted to std::string using the provided operation before
+ * being joined.
+ *
+ * The signature of op has to be equivalent to
+ * std::string op(const T::value_type &val).
+ *
+ * @param[in] first Iterator pointing to the first element to be concatenated.
+ * @param[in] last Iterator pointing behind the last element to be concatenated.
+ * @param[in] separator String used to join the elements.
+ * @param[in] op Conversion function.
+ *
+ * @return String containing all elements joined by @p separator.
+ */
+template <typename T, typename UnaryOp>
+std::string join(T &&first, T &&last, const std::string &separator, UnaryOp &&op)
+{
+ return std::accumulate(std::next(first), last, op(*first), [&separator, &op](const std::string & base, const typename T::value_type & suffix)
+ {
+ return base + separator + op(suffix);
+ });
+}
+
+/** Helper function to concatenate multiple values.
+ *
+ * All values are converted to std::string using std::to_string before being joined.
+ *
+ * @param[in] first Iterator pointing to the first element to be concatenated.
+ * @param[in] last Iterator pointing behind the last element to be concatenated.
+ * @param[in] separator String used to join the elements.
+ *
+ * @return String containing all elements joined by @p separator.
+ */
+template <typename T, typename std::enable_if<std::is_arithmetic<typename T::value_type>::value, int>::type = 0>
+std::string join(T && first, T && last, const std::string &separator)
+{
+ return join(std::forward<T>(first), std::forward<T>(last), separator, support::cpp11::to_string);
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_UTILS */
diff --git a/scripts/add_copyright.py b/scripts/add_copyright.py
index 6142298828..4a86497155 100755
--- a/scripts/add_copyright.py
+++ b/scripts/add_copyright.py
@@ -3,13 +3,13 @@
import glob
import os.path
-eula_copyright = open("scripts/copyright_eula.txt",'r').read()
+mit_copyright = open("scripts/copyright_mit.txt",'r').read()
def add_cpp_copyright( f, content):
- global eula_copyright
+ global mit_copyright
out = open(f,'w')
out.write("/*\n")
- for line in eula_copyright.split('\n')[:-1]:
+ for line in mit_copyright.split('\n')[:-1]:
out.write(" *");
if line.strip() != "":
out.write(" %s" %line)
@@ -20,9 +20,9 @@ def add_cpp_copyright( f, content):
out.close()
def add_python_copyright( f, content):
- global eula_copyright
+ global mit_copyright
out = open(f,'w')
- for line in eula_copyright.split('\n')[:-1]:
+ for line in mit_copyright.split('\n')[:-1]:
out.write("#");
if line.strip() != "":
out.write(" %s" %line)
@@ -57,7 +57,7 @@ def remove_comment_python( content ):
out += line + "\n"
return out
-for top in ['./arm_compute', './tests','./src','./examples','./utils/']:
+for top in ['./arm_compute', './tests','./src','./examples','./utils/','./framework','./support']:
for root, _, files in os.walk(top):
for f in files:
path = os.path.join(root, f)
diff --git a/scripts/check_bad_style.sh b/scripts/check_bad_style.sh
index 29d14bdb4a..6a88b67cdc 100755
--- a/scripts/check_bad_style.sh
+++ b/scripts/check_bad_style.sh
@@ -2,7 +2,7 @@
set -e
-DIRECTORIES="./arm_compute ./src ./examples ./tests ./utils"
+DIRECTORIES="./arm_compute ./src ./examples ./tests ./utils ./framework ./support"
grep -HrnP "/\*\*$" $DIRECTORIES | tee bad_style.log
if (( `cat bad_style.log | wc -l` > 0 ))
diff --git a/scripts/clang-tidy.sh b/scripts/clang-tidy.sh
index 053e5783c2..3732e2ad46 100755
--- a/scripts/clang-tidy.sh
+++ b/scripts/clang-tidy.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-DIRECTORIES="./arm_compute ./src ./examples ./tests ./utils"
+DIRECTORIES="./arm_compute ./src ./examples ./tests ./utils ./framework ./support"
if [ $# -eq 0 ]
then
@@ -45,6 +45,8 @@ fi
ARMV7_GCC_PATH=$(dirname $ARMV7_GCC)/..
AARCH64_GCC_PATH=$(dirname $AARCH64_GCC)/..
+INCLUDE_PATHS="-Iinclude -I. -I3rdparty/include -Ikernels -Itests -Icomputer_vision -Iframework"
+
function armv7
{
USE_BOOST=""
@@ -60,7 +62,7 @@ function armv7
-target armv7a-none-linux-gnueabihf \
--gcc-toolchain=$ARMV7_GCC_PATH \
-std=c++11 \
- -Iinclude -I. -I3rdparty/include -Ikernels -Itests -Icomputer_vision \
+ $INCLUDE_PATHS \
-DARM_COMPUTE_CPP_SCHEDULER=1 $USE_BOOST
#read -rsp $'Press enter to continue...\n'
}
@@ -81,7 +83,7 @@ function aarch64
--gcc-toolchain=$AARCH64_GCC_PATH \
-std=c++11 \
-include $SCRIPT_PATH/clang-tidy.h \
- -Iinclude -I. -I3rdparty/include -Ikernels -Itests -Icomputer_vision \
+ $INCLUDE_PATHS \
-DARM_COMPUTE_ENABLE_FP16 -DARM_COMPUTE_CPP_SCHEDULER=1 $USE_BOOST
}
diff --git a/scripts/copyright_mit.txt b/scripts/copyright_mit.txt
index 0beacf8d93..18e83ec163 100644
--- a/scripts/copyright_mit.txt
+++ b/scripts/copyright_mit.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2016, 2017 ARM Limited.
+Copyright (c) 2017 ARM Limited.
SPDX-License-Identifier: MIT
diff --git a/scripts/fix_code_formatting.sh b/scripts/fix_code_formatting.sh
index 2ab3c1d532..5ceeb06794 100755
--- a/scripts/fix_code_formatting.sh
+++ b/scripts/fix_code_formatting.sh
@@ -17,7 +17,7 @@ ASTYLE_PARAMETERS=" --style=ansi \
--indent-preprocessor \
"
-DIRECTORIES="./arm_compute ./src ./examples ./tests ./utils"
+DIRECTORIES="./arm_compute ./src ./examples ./tests ./utils ./framework ./support"
if [ $# -eq 0 ]
then
diff --git a/scripts/format_doxygen.py b/scripts/format_doxygen.py
index 96adf52726..64fe7ecbce 100755
--- a/scripts/format_doxygen.py
+++ b/scripts/format_doxygen.py
@@ -74,7 +74,7 @@ if __name__ == "__main__":
if len(sys.argv) == 1:
paths = []
- for top_level in ["./arm_compute", "./src", "./examples", "./tests", "./utils"]:
+ for top_level in ["./arm_compute", "./src", "./examples", "./tests", "./utils", "./framework", "./support"]:
for root, _, files in os.walk(top_level):
paths.extend([os.path.join(root, f) for f in files])
else:
diff --git a/support/ToolchainSupport.h b/support/ToolchainSupport.h
index 36b08affb9..1a909d56db 100644
--- a/support/ToolchainSupport.h
+++ b/support/ToolchainSupport.h
@@ -154,7 +154,7 @@ inline T copysign(T x, T y)
{
return ::copysign(x, y);
}
-#else
+#else /* __ANDROID__ */
/** Convert integer and float values to string.
*
* @note This function acts as a convenience wrapper around std::to_string. The
@@ -260,7 +260,7 @@ inline T copysign(T x, T y)
{
return std::copysign(x, y);
}
-#endif
+#endif /* __ANDROID__ */
} // namespace cpp11
namespace cpp14
@@ -307,4 +307,4 @@ make_unique(Args &&...) = delete;
} // namespace cpp14
} // namespace support
} // namespace arm_compute
-#endif
+#endif /* ARM_COMPUTE_TEST_TOOLCHAINSUPPORT */
diff --git a/tests/validation/system_tests/CL/AlexNet.cpp b/tests/validation/system_tests/CL/AlexNet.cpp
index a7c6ea4640..15e16d3272 100644
--- a/tests/validation/system_tests/CL/AlexNet.cpp
+++ b/tests/validation/system_tests/CL/AlexNet.cpp
@@ -1,3 +1,26 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
#ifdef INTERNAL_ONLY //FIXME Delete this file before the release
/*
* Copyright (c) 2017 ARM Limited.
diff --git a/tests/validation/system_tests/CL/LeNet5.cpp b/tests/validation/system_tests/CL/LeNet5.cpp
index 42c5bd5a7b..bf3be10e13 100644
--- a/tests/validation/system_tests/CL/LeNet5.cpp
+++ b/tests/validation/system_tests/CL/LeNet5.cpp
@@ -1,3 +1,26 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
#ifdef INTERNAL_ONLY //FIXME Delete this file before the release
/*
* Copyright (c) 2017 ARM Limited.
diff --git a/tests/validation/system_tests/NEON/AlexNet.cpp b/tests/validation/system_tests/NEON/AlexNet.cpp
index 365689242b..3a3e983ade 100644
--- a/tests/validation/system_tests/NEON/AlexNet.cpp
+++ b/tests/validation/system_tests/NEON/AlexNet.cpp
@@ -1,3 +1,26 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
#ifdef INTERNAL_ONLY //FIXME Delete this file before the release
/*
* Copyright (c) 2017 ARM Limited.
diff --git a/tests/validation/system_tests/NEON/LeNet5.cpp b/tests/validation/system_tests/NEON/LeNet5.cpp
index fedc119cb3..ace8011d9b 100644
--- a/tests/validation/system_tests/NEON/LeNet5.cpp
+++ b/tests/validation/system_tests/NEON/LeNet5.cpp
@@ -1,3 +1,26 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
#ifdef INTERNAL_ONLY //FIXME Delete this file before the release
/*
* Copyright (c) 2017 ARM Limited.