COMPMID-415: New framework - command line [5/5]

Change-Id: I4fb658c7fa24f40ef8f87239cc803d69ee89fd4d
Reviewed-on: http://mpd-gerrit.cambridge.arm.com/79759
Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com>
diff --git a/framework/command_line/CommandLineOptions.h b/framework/command_line/CommandLineOptions.h
new file mode 100644
index 0000000..cb4b794
--- /dev/null
+++ b/framework/command_line/CommandLineOptions.h
@@ -0,0 +1,33 @@
+/*
+ * 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_COMMANDLINEOPTIONS
+#define ARM_COMPUTE_TEST_COMMANDLINEOPTIONS
+
+#include "EnumListOption.h"
+#include "EnumOption.h"
+#include "ListOption.h"
+#include "Option.h"
+#include "ToggleOption.h"
+
+#endif /* ARM_COMPUTE_TEST_COMMANDLINEOPTIONS */
diff --git a/framework/command_line/CommandLineParser.cpp b/framework/command_line/CommandLineParser.cpp
new file mode 100644
index 0000000..228b18d
--- /dev/null
+++ b/framework/command_line/CommandLineParser.cpp
@@ -0,0 +1,149 @@
+/*
+ * 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 "CommandLineParser.h"
+
+#include <iostream>
+#include <regex>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+void CommandLineParser::parse(int argc, char **argv)
+{
+    const std::regex option_regex{ "--((?:no-)?)([^=]+)(?:=(.*))?" };
+
+    const auto set_option = [&](const std::string & option, const std::string & name, const std::string & value)
+    {
+        if(_options.find(name) == _options.end())
+        {
+            _unknown_options.push_back(option);
+            return;
+        }
+
+        const bool success = _options[name]->parse(value);
+
+        if(!success)
+        {
+            _invalid_options.push_back(option);
+        }
+    };
+
+    unsigned int positional_index = 0;
+
+    for(int i = 1; i < argc; ++i)
+    {
+        const std::string option{ argv[i] };
+        std::smatch       option_matches;
+
+        if(std::regex_match(option, option_matches, option_regex))
+        {
+            // Boolean option
+            if(option_matches.str(3).empty())
+            {
+                set_option(option, option_matches.str(2), option_matches.str(1).empty() ? "true" : "false");
+            }
+            else
+            {
+                // Can't have "no-" and a value
+                if(!option_matches.str(1).empty())
+                {
+                    _invalid_options.emplace_back(option);
+                }
+                else
+                {
+                    set_option(option, option_matches.str(2), option_matches.str(3));
+                }
+            }
+        }
+        else
+        {
+            if(positional_index >= _positional_options.size())
+            {
+                _invalid_options.push_back(option);
+            }
+            else
+            {
+                _positional_options[positional_index]->parse(option);
+                ++positional_index;
+            }
+        }
+    }
+}
+
+bool CommandLineParser::validate() const
+{
+    bool is_valid = true;
+
+    for(const auto &option : _options)
+    {
+        if(option.second->is_required() && !option.second->is_set())
+        {
+            is_valid = false;
+            std::cerr << "ERROR: Option '" << option.second->name() << "' is required but not given!\n";
+        }
+    }
+
+    for(const auto &option : _positional_options)
+    {
+        if(option->is_required() && !option->is_set())
+        {
+            is_valid = false;
+            std::cerr << "ERROR: Option '" << option->name() << "' is required but not given!\n";
+        }
+    }
+
+    for(const auto &option : _unknown_options)
+    {
+        std::cerr << "WARNING: Skipping unknown option '" << option << "'!\n";
+    }
+
+    for(const auto &option : _invalid_options)
+    {
+        std::cerr << "WARNING: Skipping invalid option '" << option << "'!\n";
+    }
+
+    return is_valid;
+}
+
+void CommandLineParser::print_help(const std::string &program_name) const
+{
+    std::cout << "usage: " << program_name << " \n";
+
+    for(const auto &option : _options)
+    {
+        std::cout << option.second->help() << "\n";
+    }
+
+    for(const auto &option : _positional_options)
+    {
+        //FIXME: Print help string as well
+        std::cout << option->name() << "\n";
+    }
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
diff --git a/framework/command_line/CommandLineParser.h b/framework/command_line/CommandLineParser.h
new file mode 100644
index 0000000..adb5214
--- /dev/null
+++ b/framework/command_line/CommandLineParser.h
@@ -0,0 +1,117 @@
+/*
+ * 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_COMMANDLINEPARSER
+#define ARM_COMPUTE_TEST_COMMANDLINEPARSER
+
+#include "../Utils.h"
+#include "Option.h"
+
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Class to parse command line arguments. */
+class CommandLineParser final
+{
+public:
+    /** Default constructor. */
+    CommandLineParser() = default;
+
+    /** Function to add a new option to the parser.
+     *
+     * @param[in] name Name of the option. Will be available under --name=VALUE.
+     * @param[in] args Option specific configuration arguments.
+     *
+     * @return Pointer to the option. The option is owned by the parser.
+     */
+    template <typename T, typename... As>
+    T *add_option(const std::string &name, As &&... args);
+
+    /** Function to add a new positional argument to the parser.
+     *
+     * @param[in] args Option specific configuration arguments.
+     *
+     * @return Pointer to the option. The option is owned by the parser.
+     */
+    template <typename T, typename... As>
+    T *add_positional_option(As &&... args);
+
+    /** Parses the command line arguments and updates the options accordingly.
+     *
+     * @param[in] argc Number of arguments.
+     * @param[in] argv Arguments.
+     */
+    void parse(int argc, char **argv);
+
+    /** Validates the previously parsed command line arguments.
+     *
+     * Validation fails if not all required options are provided. Additionally
+     * warnings are generated for options that have illegal values or unknown
+     * options.
+     *
+     * @return True if all required options have been provided.
+     */
+    bool validate() const;
+
+    /** Prints a help message for all configured options.
+     *
+     * @param[in] program_name Name of the program to be used in the help message.
+     */
+    void print_help(const std::string &program_name) const;
+
+private:
+    using OptionsMap              = std::map<std::string, std::unique_ptr<Option>>;
+    using PositionalOptionsVector = std::vector<std::unique_ptr<Option>>;
+
+    OptionsMap               _options{};
+    PositionalOptionsVector  _positional_options{};
+    std::vector<std::string> _unknown_options{};
+    std::vector<std::string> _invalid_options{};
+};
+
+template <typename T, typename... As>
+inline T *CommandLineParser::add_option(const std::string &name, As &&... args)
+{
+    auto result = _options.emplace(name, support::cpp14::make_unique<T>(name, std::forward<As>(args)...));
+    return static_cast<T *>(result.first->second.get());
+}
+
+template <typename T, typename... As>
+inline T *CommandLineParser::add_positional_option(As &&... args)
+{
+    _positional_options.emplace_back(support::cpp14::make_unique<T>(std::forward<As>(args)...));
+    return static_cast<T *>(_positional_options.back().get());
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_COMMANDLINEPARSER */
diff --git a/framework/command_line/EnumListOption.h b/framework/command_line/EnumListOption.h
new file mode 100644
index 0000000..41c5b6e
--- /dev/null
+++ b/framework/command_line/EnumListOption.h
@@ -0,0 +1,149 @@
+/*
+ * 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_ENUMLISTOPTION
+#define ARM_COMPUTE_TEST_ENUMLISTOPTION
+
+#include "Option.h"
+
+#include <initializer_list>
+#include <set>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Implementation of an option that accepts any number of values from a fixed set. */
+template <typename T>
+class EnumListOption : public Option
+{
+public:
+    /** Construct option with allowed values.
+     *
+     * @param[in] name           Name of the option.
+     * @param[in] allowed_values Set of allowed values for the option.
+     */
+    EnumListOption(std::string name, std::set<T> allowed_values);
+
+    /** Construct option with allowed values, a fixed number of accepted values and default values for the option.
+     *
+     * @param[in] name           Name of the option.
+     * @param[in] allowed_values Set of allowed values for the option.
+     * @param[in] default_values Default values.
+     */
+    EnumListOption(std::string name, std::set<T> allowed_values, std::initializer_list<T> &&default_values);
+
+    bool parse(std::string value) override;
+    std::string           help() const override;
+    const std::vector<T> &value() const;
+
+private:
+    std::vector<T> _values{};
+    std::set<T>    _allowed_values{};
+};
+
+template <typename T>
+inline EnumListOption<T>::EnumListOption(std::string name, std::set<T> allowed_values)
+    : Option{ std::move(name) }, _allowed_values{ std::move(allowed_values) }
+{
+}
+
+template <typename T>
+inline EnumListOption<T>::EnumListOption(std::string name, std::set<T> allowed_values, std::initializer_list<T> &&default_values)
+    : Option{ std::move(name), false, true }, _values{ std::forward<std::initializer_list<T>>(default_values) }, _allowed_values{ std::move(allowed_values) }
+{
+}
+
+template <typename T>
+bool EnumListOption<T>::parse(std::string value)
+{
+    // Remove default values
+    _values.clear();
+
+    try
+    {
+        std::stringstream stream{ value };
+        T                 typed_value{};
+
+        while(stream.good())
+        {
+            stream >> typed_value;
+
+            if(!stream.fail())
+            {
+                if(_allowed_values.count(typed_value) == 0)
+                {
+                    _values.clear();
+                    return false;
+                }
+
+                _values.emplace_back(typed_value);
+            }
+
+            if(!stream.eof())
+            {
+                stream.ignore(1, ',');
+            }
+        }
+
+        _is_set = !stream.fail();
+
+        return _is_set;
+    }
+    catch(const std::invalid_argument &)
+    {
+        return false;
+    }
+}
+
+template <typename T>
+std::string EnumListOption<T>::help() const
+{
+    std::stringstream msg;
+    msg << "--" + name() + "={";
+
+    for(const auto &value : _allowed_values)
+    {
+        msg << value << ",";
+    }
+
+    msg << "} - " << _help;
+
+    return msg.str();
+}
+
+template <typename T>
+inline const std::vector<T> &EnumListOption<T>::value() const
+{
+    return _values;
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_ENUMLISTOPTION */
diff --git a/framework/command_line/EnumOption.h b/framework/command_line/EnumOption.h
new file mode 100644
index 0000000..1abba77
--- /dev/null
+++ b/framework/command_line/EnumOption.h
@@ -0,0 +1,134 @@
+/*
+ * 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_ENUMOPTION
+#define ARM_COMPUTE_TEST_ENUMOPTION
+
+#include "SimpleOption.h"
+
+#include <set>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Implementation of a simple option that accepts a value from a fixed set. */
+template <typename T>
+class EnumOption : public SimpleOption<T>
+{
+public:
+    /** Construct option with allowed values.
+     *
+     * @param[in] name           Name of the option.
+     * @param[in] allowed_values Set of allowed values for the option.
+     */
+    EnumOption(std::string name, std::set<T> allowed_values);
+
+    /** Construct option with allowed values, a fixed number of accepted values and default values for the option.
+     *
+     * @param[in] name           Name of the option.
+     * @param[in] allowed_values Set of allowed values for the option.
+     * @param[in] default_value  Default value.
+     */
+    EnumOption(std::string name, std::set<T> allowed_values, T default_value);
+
+    bool parse(std::string value) override;
+    std::string help() const override;
+    const T    &value() const;
+
+private:
+    std::set<T> _allowed_values{};
+};
+
+template <typename T>
+inline EnumOption<T>::EnumOption(std::string name, std::set<T> allowed_values)
+    : SimpleOption<T>{ std::move(name) }, _allowed_values{ std::move(allowed_values) }
+{
+}
+
+template <typename T>
+inline EnumOption<T>::EnumOption(std::string name, std::set<T> allowed_values, T default_value)
+    : SimpleOption<T>{ std::move(name), std::move(default_value) }, _allowed_values{ std::move(allowed_values) }
+{
+}
+
+template <typename T>
+bool EnumOption<T>::parse(std::string value)
+{
+    try
+    {
+        std::stringstream stream{ value };
+        T                 typed_value{};
+
+        stream >> typed_value;
+
+        if(!stream.fail())
+        {
+            if(_allowed_values.count(typed_value) == 0)
+            {
+                return false;
+            }
+
+            this->_value  = std::move(typed_value);
+            this->_is_set = true;
+            return true;
+        }
+
+        return false;
+    }
+    catch(const std::invalid_argument &)
+    {
+        return false;
+    }
+}
+
+template <typename T>
+std::string EnumOption<T>::help() const
+{
+    std::stringstream msg;
+    msg << "--" + this->name() + "={";
+
+    for(const auto &value : _allowed_values)
+    {
+        msg << value << ",";
+    }
+
+    msg << "} - " << this->_help;
+
+    return msg.str();
+}
+
+template <typename T>
+inline const T &EnumOption<T>::value() const
+{
+    return this->_value;
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_ENUMOPTION */
diff --git a/framework/command_line/ListOption.h b/framework/command_line/ListOption.h
new file mode 100644
index 0000000..f867ef8
--- /dev/null
+++ b/framework/command_line/ListOption.h
@@ -0,0 +1,116 @@
+/*
+ * 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_LISTOPTION
+#define ARM_COMPUTE_TEST_LISTOPTION
+
+#include "Option.h"
+
+#include <initializer_list>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Implementation of an option that accepts any number of values. */
+template <typename T>
+class ListOption : public Option
+{
+public:
+    using Option::Option;
+
+    /** Construct the option with the given default values.
+     *
+     * @param[in] name           Name of the option.
+     * @param[in] default_values Default values.
+     */
+    ListOption(std::string name, std::initializer_list<T> &&default_values);
+
+    bool parse(std::string value) override;
+    std::string           help() const override;
+    const std::vector<T> &value() const;
+
+private:
+    std::vector<T> _values{};
+};
+
+template <typename T>
+inline ListOption<T>::ListOption(std::string name, std::initializer_list<T> &&default_values)
+    : Option{ std::move(name), false, true }, _values{ std::forward<std::initializer_list<T>>(default_values) }
+{
+}
+
+template <typename T>
+bool ListOption<T>::parse(std::string value)
+{
+    try
+    {
+        std::stringstream stream{ value };
+        T                 typed_value{};
+
+        while(stream.good())
+        {
+            stream >> typed_value;
+
+            if(!stream.fail())
+            {
+                _values.emplace_back(typed_value);
+            }
+
+            if(!stream.eof())
+            {
+                stream.ignore(1, ',');
+            }
+        }
+
+        _is_set = !stream.fail();
+
+        return _is_set;
+    }
+    catch(const std::invalid_argument &)
+    {
+        return false;
+    }
+}
+
+template <typename T>
+inline std::string ListOption<T>::help() const
+{
+    return "--" + name() + "=VALUE[,VALUE[,...]] - " + _help;
+}
+
+template <typename T>
+inline const std::vector<T> &ListOption<T>::value() const
+{
+    return _values;
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_LISTOPTION */
diff --git a/framework/command_line/Option.cpp b/framework/command_line/Option.cpp
new file mode 100644
index 0000000..d60c35a
--- /dev/null
+++ b/framework/command_line/Option.cpp
@@ -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.
+ */
+#include "Option.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+Option::Option(std::string name)
+    : _name{ std::move(name) }
+{
+}
+
+Option::Option(std::string name, bool is_required, bool is_set)
+    : _name{ std::move(name) }, _is_required{ is_required }, _is_set{ is_set }
+{
+}
+
+std::string Option::name() const
+{
+    return _name;
+}
+
+void Option::set_required(bool is_required)
+{
+    _is_required = is_required;
+}
+
+void Option::set_help(std::string help)
+{
+    _help = std::move(help);
+}
+
+bool Option::is_required() const
+{
+    return _is_required;
+}
+
+bool Option::is_set() const
+{
+    return _is_set;
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
diff --git a/framework/command_line/Option.h b/framework/command_line/Option.h
new file mode 100644
index 0000000..25cf492
--- /dev/null
+++ b/framework/command_line/Option.h
@@ -0,0 +1,109 @@
+/*
+ * 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_OPTIONBASE
+#define ARM_COMPUTE_TEST_OPTIONBASE
+
+#include <string>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Abstract base class for a command line option. */
+class Option
+{
+public:
+    /** Constructor.
+     *
+     * @param[in] name Name of the option.
+     */
+    Option(std::string name);
+
+    /** Constructor.
+     *
+     * @param[in] name        Name of the option.
+     * @param[in] is_required Is the option required?
+     * @param[in] is_set      Has a value been assigned to the option?
+     */
+    Option(std::string name, bool is_required, bool is_set);
+
+    /** Default destructor. */
+    virtual ~Option() = default;
+
+    /** Parses the given string.
+     *
+     * @param[in] value String representation as passed on the command line.
+     *
+     * @return True if the value could be parsed by the specific subclass.
+     */
+    virtual bool parse(std::string value) = 0;
+
+    /** Help message for the option.
+     *
+     * @return String representing the help message for the specific subclass.
+     */
+    virtual std::string help() const = 0;
+
+    /** Name of the option.
+     *
+     * @return Name of the option.
+     */
+    std::string name() const;
+
+    /** Set whether the option is required.
+     *
+     * @param[in] is_required Pass true if the option is required.
+     */
+    void set_required(bool is_required);
+
+    /** Set the help message for the option.
+     *
+     * @param[in] help Option specific help message.
+     */
+    void set_help(std::string help);
+
+    /** Is the option required?
+     *
+     * @return True if the option is required.
+     */
+    bool is_required() const;
+
+    /** Has a value been assigned to the option?
+     *
+     * @return True if a value has been set.
+     */
+    bool is_set() const;
+
+protected:
+    std::string _name;
+    bool        _is_required{ false };
+    bool        _is_set{ false };
+    std::string _help{};
+};
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_OPTIONBASE */
diff --git a/framework/command_line/SimpleOption.h b/framework/command_line/SimpleOption.h
new file mode 100644
index 0000000..e6e8045
--- /dev/null
+++ b/framework/command_line/SimpleOption.h
@@ -0,0 +1,105 @@
+/*
+ * 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_SIMPLEOPTION
+#define ARM_COMPUTE_TEST_SIMPLEOPTION
+
+#include "Option.h"
+
+#include <sstream>
+#include <stdexcept>
+#include <string>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Implementation of an option that accepts a single value. */
+template <typename T>
+class SimpleOption : public Option
+{
+public:
+    using Option::Option;
+
+    /** Construct the option with the given default value.
+     *
+     * @param[in] name          Name of the option.
+     * @param[in] default_value Default value.
+     */
+    SimpleOption(std::string name, T default_value);
+
+    bool parse(std::string value) override;
+    std::string help() const override;
+    const T    &value() const;
+
+protected:
+    T _value{};
+};
+
+template <typename T>
+inline SimpleOption<T>::SimpleOption(std::string name, T default_value)
+    : Option{ std::move(name), false, true }, _value{ std::move(default_value) }
+{
+}
+
+template <typename T>
+bool SimpleOption<T>::parse(std::string value)
+{
+    try
+    {
+        std::stringstream stream{ std::move(value) };
+        stream >> _value;
+        _is_set = !stream.fail();
+        return _is_set;
+    }
+    catch(const std::invalid_argument &)
+    {
+        return false;
+    }
+}
+
+template <>
+inline bool SimpleOption<std::string>::parse(std::string value)
+{
+    _value  = std::move(value);
+    _is_set = true;
+    return true;
+}
+
+template <typename T>
+inline std::string SimpleOption<T>::help() const
+{
+    return "--" + name() + "=VALUE - " + _help;
+}
+
+template <typename T>
+inline const T &SimpleOption<T>::value() const
+{
+    return _value;
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_SIMPLEOPTION */
diff --git a/framework/command_line/ToggleOption.cpp b/framework/command_line/ToggleOption.cpp
new file mode 100644
index 0000000..df5b1f8
--- /dev/null
+++ b/framework/command_line/ToggleOption.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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 "ToggleOption.h"
+
+#include <utility>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+ToggleOption::ToggleOption(std::string name, bool default_value)
+    : SimpleOption<bool>
+{
+    std::move(name), default_value
+}
+{
+}
+
+bool ToggleOption::parse(std::string value)
+{
+    if(value == "true")
+    {
+        _value  = true;
+        _is_set = true;
+    }
+    else if(value == "false")
+    {
+        _value  = false;
+        _is_set = true;
+    }
+
+    return _is_set;
+}
+
+std::string ToggleOption::help() const
+{
+    return "--" + name() + ", --no-" + name() + " - " + _help;
+}
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
diff --git a/framework/command_line/ToggleOption.h b/framework/command_line/ToggleOption.h
new file mode 100644
index 0000000..c440c0e
--- /dev/null
+++ b/framework/command_line/ToggleOption.h
@@ -0,0 +1,56 @@
+/*
+ * 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_TOGGLEOPTION
+#define ARM_COMPUTE_TEST_TOGGLEOPTION
+
+#include "SimpleOption.h"
+
+#include <string>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace framework
+{
+/** Implementation of an option that can be either true or false. */
+class ToggleOption : public SimpleOption<bool>
+{
+public:
+    using SimpleOption::SimpleOption;
+
+    /** Construct the option with the given default value.
+     *
+     * @param[in] name          Name of the option.
+     * @param[in] default_value Default value.
+     */
+    ToggleOption(std::string name, bool default_value);
+
+    bool parse(std::string value) override;
+    std::string help() const override;
+};
+} // namespace framework
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_TOGGLEOPTION */