Commits

Matt Oswald committed f8fc3d8

CommandLine didn't need to be a class

Comments (0)

Files changed (3)

xUnit++.console/CommandLine.cpp

 #include "CommandLine.h"
+#include <filesystem>
 #include <functional>
 #include <stack>
 #include <sstream>
     {
         if (arguments.empty())
         {
-            return opt + " expects at least one attribute argument.\n";
+            return opt + " expects at least one attribute argument.";
         }
 
         do
             auto pos = raw.find('=');
             if (pos == std::string::npos)
             {
-                return raw + " is not a valid format for " + opt + " (should be \"name=[value]\").\n";
+                return raw + " is not a valid format for " + opt + " (should be \"name=[value]\").";
             }
 
             auto key = raw.substr(0, pos);
 
 namespace xUnitpp { namespace Utilities {
 
-CommandLine::CommandLine(int argc, char **argv)
-    : mVerbose(false)
-    , mTimeLimit(0)
+namespace CommandLine
 {
-    std::stack<std::string> arguments;
-
-    for (int i = 1; i != argc; ++i)
+    Options::Options()
+        : verbose(false)
+        , timeLimit(0)
     {
-        arguments.emplace(argv[i]);
     }
 
-    while (!arguments.empty())
+    std::string Parse(int argc, char **argv, Options &options)
     {
-        auto opt = PopTop(arguments);
+        auto exe = [=]()
+        {
+            return std::tr2::sys::path(argv[0]).leaf();
+        };
 
-        if (opt[0] == '-')
+        std::stack<std::string> arguments;
+
+        for (int i = 1; i != argc; ++i)
         {
-            if (opt == "-v")
+            arguments.emplace(argv[i]);
+        }
+
+        while (!arguments.empty())
+        {
+            auto opt = PopTop(arguments);
+
+            if (opt[0] == '-')
             {
-                mVerbose = true;
-            }
-            else if (opt == "-i" || opt == "--include")
-            {
-                auto error = EatKeyValuePairs(opt, arguments, [&](std::tuple<std::string, std::string> &&kv) { mInclusiveAttributes.emplace_back(kv); });
+                if (opt == "-v")
+                {
+                    options.verbose = true;
+                }
+                else if (opt == "-i" || opt == "--include")
+                {
+                    auto error = EatKeyValuePairs(opt, arguments, [&](std::tuple<std::string, std::string> &&kv) { options.inclusiveAttributes.emplace_back(kv); });
 
-                if (!error.empty())
+                    if (!error.empty())
+                    {
+                        return error + Usage(exe());
+                    }
+                }
+                else if (opt == "-e" || opt == "--exclude")
                 {
-                    throw std::invalid_argument((error + Usage(argv[0])).c_str());
+                    auto error = EatKeyValuePairs(opt, arguments, [&](std::tuple<std::string, std::string> &&kv) { options.exclusiveAttributes.emplace_back(kv); });
+
+                    if (!error.empty())
+                    {
+                        return error + Usage(exe());
+                    }
                 }
-            }
-            else if (opt == "-e" || opt == "--exclude")
-            {
-                auto error = EatKeyValuePairs(opt, arguments, [&](std::tuple<std::string, std::string> &&kv) { mExclusiveAttributes.emplace_back(kv); });
+                else if (opt == "-x" || opt == "--xml")
+                {
+                    if (arguments.empty())
+                    {
+                        return opt + " expects a following filename argument." + Usage(exe());
+                    }
 
-                if (!error.empty())
+                    options.xmlOutput = PopTop(arguments);
+                }
+                else if (opt == "-t" || opt == "--timelimit")
                 {
-                    throw std::invalid_argument((error + Usage(argv[0])).c_str());
+                    if (arguments.empty() || Throws([&]() { std::istringstream(PopTop(arguments)) >> options.timeLimit; }))
+                    {
+                        return opt + " expects a following timelimit specified in milliseconds." + Usage(exe());
+                    }
                 }
-            }
-            else if (opt == "-x" || opt == "--xml")
-            {
-                if (arguments.empty())
+                else
                 {
-                    throw std::invalid_argument((opt + " expects a following filename argument." + Usage(argv[0])).c_str());
-                }
-
-                mXmlOutput = PopTop(arguments);
-            }
-            else if (opt == "-t" || opt == "--timelimit")
-            {
-                if (arguments.empty() || Throws([&]() { std::istringstream(PopTop(arguments)) >> mTimeLimit; }))
-                {
-                    throw std::invalid_argument((opt + " expects a following timelimit specified in milliseconds." + Usage(argv[0])).c_str());
+                    return "Unrecognized option " + opt + "." + Usage(exe());
                 }
             }
             else
             {
-                throw std::invalid_argument(("Unrecognized option " + opt + "." + Usage(argv[0])).c_str());
+                options.libraries.push_back(opt);
             }
         }
-        else
+
+        if (options.libraries.empty())
         {
-            mTestLibraries.push_back(opt);
+            return "At least one testLibrary must be specified." + Usage(exe());
         }
+
+        return "";
     }
 
-    if (mTestLibraries.empty())
+    std::string Usage(const std::string &exe)
     {
-        throw std::invalid_argument(("At least one testLibrary must be specified." + Usage(argv[0])).c_str());
+        static const std::string usage =
+            " <testLibrary>+ [option]+\n"
+            "\n"
+            "options:\n\n"
+            "  -v                             : Verbose mode: include successful test details\n"
+            "  -i --include <NAME=[VALUE]>+   : Include tests with a matching <name=value> attribute\n"
+            "  -e --exclude <NAME=[VALUE]>+   : Exclude tests with a matching <name=value> attribute\n"
+            "  -t --timelimit <MILLISECONDS>  : Set the default test time limit\n"
+            "  -x --xml <FILENAME>            : Output Xunit-style XML file\n"
+            "\n"
+            "Tests are selected with an OR operation for inclusive attributes.\n"
+            "Tests are excluded with an AND operation for exclusive attributes.\n"
+            "When VALUE is omitted, any attribute with name NAME is matched.\n";
+
+        return "\nusage: " + exe + usage;
     }
 }
 
-std::string CommandLine::Usage(const std::string &exe)
-{
-    static const std::string usage =
-        " <testLibrary>+ [option]+\n"
-        "\n"
-        "options:\n\n"
-        "  -v                             : Verbose mode: include successful test details\n"
-        "  -i --include <NAME=[VALUE]>+   : Include tests with a matching <name=value> attribute\n"
-        "  -e --exclude <NAME=[VALUE]>+   : Exclude tests with a matching <name=value> attribute\n"
-        "  -t --timelimit <MILLISECONDS>  : Set the default test time limit\n"
-        "  -x --xml <FILENAME>            : Output Xunit-style XML file\n"
-        "\n"
-        "Tests are selected with an OR operation for inclusive attributes.\n"
-        "Tests are excluded with an AND operation for exclusive attributes.\n"
-        "When VALUE is omitted, any attribute with name NAME is matched.\n";
-
-    return "\nusage: " + exe + usage;
-}
-
-const std::vector<std::string> &CommandLine::TestLibraries()
-{
-    return mTestLibraries;
-}
-
 }}

xUnit++.console/CommandLine.h

 #include <tuple>
 #include <vector>
 
-namespace xUnitpp
+namespace xUnitpp { namespace Utilities {
+
+namespace CommandLine
 {
+    struct Options
+    {
+        Options();
 
-namespace Utilities
-{
-    class CommandLine
-    {
-    public:
-        CommandLine(int argc, char **argv);
+        bool verbose;
+        std::vector<std::tuple<std::string, std::string>> inclusiveAttributes;
+        std::vector<std::tuple<std::string, std::string>> exclusiveAttributes;
+        std::vector<std::string> libraries;
+        std::string xmlOutput;
+        int timeLimit;
+    };
 
-        static std::string Usage(const std::string &exe);
-
-        const std::vector<std::string> &TestLibraries();
-
-    private:
-        bool mVerbose;
-        std::vector<std::tuple<std::string, std::string>> mInclusiveAttributes;
-        std::vector<std::tuple<std::string, std::string>> mExclusiveAttributes;
-        std::vector<std::string> mTestLibraries;
-        std::string mXmlOutput;
-        int mTimeLimit;
-    };
+    std::string Parse(int argc, char **argv, Options &options);
+    std::string Usage(const std::string &exe);
 }
 
-}
+}}
 
 #endif

xUnit++.console/main.cpp

 
 int main(int argc, char **argv)
 {
-    std::vector<std::string> libraries;
+    xUnitpp::Utilities::CommandLine::Options options;
 
-    try
     {
-        xUnitpp::Utilities::CommandLine commandLine(argc, argv);
-        libraries = commandLine.TestLibraries();
-    }
-    catch (std::invalid_argument &e)
-    {
-        std::cerr << e.what();
-        return -1;
+        auto result = xUnitpp::Utilities::CommandLine::Parse(argc, argv, options);
+        if (!result.empty())
+        {
+            std::cerr << result;
+            return -1;
+        }
     }
 
     int failures = 0;
 
-    for (const auto &lib : libraries)
+    for (const auto &lib : options.libraries)
     {
         auto testlib = LoadLibrary(lib.c_str());