aboutsummaryrefslogtreecommitdiff
path: root/deps/inja/third_party/include/hayai/hayai_main.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'deps/inja/third_party/include/hayai/hayai_main.hpp')
-rwxr-xr-xdeps/inja/third_party/include/hayai/hayai_main.hpp530
1 files changed, 530 insertions, 0 deletions
diff --git a/deps/inja/third_party/include/hayai/hayai_main.hpp b/deps/inja/third_party/include/hayai/hayai_main.hpp
new file mode 100755
index 0000000..d6d7cd3
--- /dev/null
+++ b/deps/inja/third_party/include/hayai/hayai_main.hpp
@@ -0,0 +1,530 @@
+#ifndef __HAYAI_MAIN
+#define __HAYAI_MAIN
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <errno.h>
+#include <fstream>
+#include <set>
+#include <vector>
+
+#include "hayai.hpp"
+
+
+#if defined(_WIN32)
+# define PATH_SEPARATOR '\\'
+#else
+# define PATH_SEPARATOR '/'
+#endif
+
+
+#define HAYAI_MAIN_FORMAT_FLAG(_desc) \
+ ::hayai::Console::TextGreen << _desc << ::hayai::Console::TextDefault
+#define HAYAI_MAIN_FORMAT_ARGUMENT(_desc) \
+ ::hayai::Console::TextYellow << _desc << ::hayai::Console::TextDefault
+#define HAYAI_MAIN_FORMAT_ERROR(_desc) \
+ ::hayai::Console::TextRed << "Error:" << \
+ ::hayai::Console::TextDefault << " " << _desc
+#define HAYAI_MAIN_USAGE_ERROR(_desc) \
+ { \
+ std::cerr << HAYAI_MAIN_FORMAT_ERROR(_desc) << std::endl \
+ << std::endl; \
+ ShowUsage(argv[0]); \
+ return EXIT_FAILURE; \
+ }
+
+
+namespace hayai
+{
+ /// Execution mode.
+ enum MainExecutionMode
+ {
+ /// Run benchmarks.
+ MainRunBenchmarks,
+
+
+ /// List benchmarks but do not execute them.
+ MainListBenchmarks
+ };
+
+
+ /// File outputter.
+ class FileOutputter
+ {
+ public:
+ /// File outputter.
+
+ /// @param path Output path. Expected to be available during the life
+ /// time of the outputter.
+ FileOutputter(const char* path)
+ : _path(path),
+ _outputter(NULL)
+ {
+
+ }
+
+
+ virtual ~FileOutputter()
+ {
+ if (_outputter)
+ delete _outputter;
+
+ _stream.close();
+ }
+
+
+ /// Set up.
+
+ /// Opens the output file for writing and initializes the outputter.
+ virtual void SetUp()
+ {
+ _stream.open(_path,
+ std::ios_base::out |
+ std::ios_base::trunc |
+ std::ios_base::binary);
+ if (_stream.bad())
+ {
+ std::stringstream error;
+ error << "failed to open " << _path << " for writing: "
+ << strerror(errno);
+ throw std::runtime_error(error.str());
+ }
+
+ _outputter = CreateOutputter(_stream);
+ }
+
+
+ /// Outputter.
+ virtual ::hayai::Outputter& Outputter()
+ {
+ if (!_outputter)
+ throw std::runtime_error("outputter has not been set up");
+
+ return *_outputter;
+ }
+ protected:
+ /// Create outputter from output stream.
+
+ /// @param stream Output stream for the outputter.
+ /// @returns the outputter for the given format.
+ virtual ::hayai::Outputter* CreateOutputter(std::ostream& stream) = 0;
+ private:
+ const char* _path;
+ std::ofstream _stream;
+ ::hayai::Outputter* _outputter;
+ };
+
+
+#define FILE_OUTPUTTER_IMPLEMENTATION(_prefix) \
+ class _prefix ## FileOutputter \
+ : public FileOutputter \
+ { \
+ public: \
+ _prefix ## FileOutputter(const char* path) \
+ : FileOutputter(path) \
+ {} \
+ protected: \
+ virtual ::hayai::Outputter* CreateOutputter(std::ostream& stream) \
+ { \
+ return new ::hayai::_prefix ## Outputter(stream); \
+ } \
+ }
+
+
+ FILE_OUTPUTTER_IMPLEMENTATION(Json);
+ FILE_OUTPUTTER_IMPLEMENTATION(Console);
+ FILE_OUTPUTTER_IMPLEMENTATION(JUnitXml);
+
+#undef FILE_OUTPUTTER_IMPLEMENTATION
+
+
+ /// Default main executable runner for Hayai.
+ class MainRunner
+ {
+ public:
+ MainRunner()
+ : ExecutionMode(MainRunBenchmarks),
+ ShuffleBenchmarks(false),
+ StdoutOutputter(NULL)
+ {
+
+ }
+
+
+ ~MainRunner()
+ {
+ // Clean up the outputters.
+ for (std::vector<FileOutputter*>::iterator it =
+ FileOutputters.begin();
+ it != FileOutputters.end();
+ ++it)
+ delete *it;
+
+ if (StdoutOutputter)
+ delete StdoutOutputter;
+ }
+
+
+ /// Execution mode.
+ MainExecutionMode ExecutionMode;
+
+
+ /// Shuffle benchmarks.
+ bool ShuffleBenchmarks;
+
+
+ /// File outputters.
+ ///
+ /// Outputter will be freed by the class on destruction.
+ std::vector<FileOutputter*> FileOutputters;
+
+
+ /// Standard output outputter.
+ ///
+ /// Will be freed by the class on destruction.
+ Outputter* StdoutOutputter;
+
+
+ /// Parse arguments.
+
+ /// @param argc Argument count including the executable name.
+ /// @param argv Arguments.
+ /// @param residualArgs Pointer to vector to hold residual arguments
+ /// after parsing. If not NULL, the parser will not fail upon
+ /// encounting an unknown argument but will instead add it to the list
+ /// of residual arguments and return a success code. Note: the parser
+ /// will still fail if an invalid value is provided to a known
+ /// argument.
+ /// @returns 0 on success, otherwise the exit status code to be
+ /// returned from the executable.
+ int ParseArgs(int argc,
+ char** argv,
+ std::vector<char*>* residualArgs = NULL)
+ {
+ int argI = 1;
+ while (argI < argc)
+ {
+ char* arg = argv[argI++];
+ bool argLast = (argI == argc);
+ std::size_t argLen = strlen(arg);
+
+ if (argLen == 0)
+ continue;
+
+ // List flag.
+ if ((!strcmp(arg, "-l")) || (!strcmp(arg, "--list")))
+ ExecutionMode = ::hayai::MainListBenchmarks;
+ // Shuffle flag.
+ else if ((!strcmp(arg, "-s")) || (!strcmp(arg, "--shuffle")))
+ ShuffleBenchmarks = true;
+ // Filter flag.
+ else if ((!strcmp(arg, "-f")) || (!strcmp(arg, "--filter")))
+ {
+ if ((argLast) || (*argv[argI] == 0))
+ HAYAI_MAIN_USAGE_ERROR(HAYAI_MAIN_FORMAT_FLAG(arg) <<
+ " requires a pattern to be specified");
+ char* pattern = argv[argI++];
+
+ ::hayai::Benchmarker::ApplyPatternFilter(pattern);
+ }
+ // Output flag.
+ else if ((!strcmp(arg, "-o")) || (!strcmp(arg, "--output")))
+ {
+ if (argLast)
+ HAYAI_MAIN_USAGE_ERROR(HAYAI_MAIN_FORMAT_FLAG(arg) <<
+ " requires a format to be specified");
+ char* formatSpecifier = argv[argI++];
+
+ char* format = formatSpecifier;
+ char* path = strchr(formatSpecifier, ':');
+ if (path)
+ {
+ *(path++) = 0;
+ if (!strlen(path))
+ path = NULL;
+ }
+
+#define ADD_OUTPUTTER(_prefix) \
+ { \
+ if (path) \
+ FileOutputters.push_back( \
+ new ::hayai::_prefix ## FileOutputter(path) \
+ ); \
+ else \
+ { \
+ if (StdoutOutputter) \
+ delete StdoutOutputter; \
+ StdoutOutputter = \
+ new ::hayai::_prefix ## Outputter(std::cout); \
+ } \
+ }
+
+ if (!strcmp(format, "console"))
+ ADD_OUTPUTTER(Console)
+ else if (!strcmp(format, "json"))
+ ADD_OUTPUTTER(Json)
+ else if (!strcmp(format, "junit"))
+ ADD_OUTPUTTER(JUnitXml)
+ else
+ HAYAI_MAIN_USAGE_ERROR("invalid format: " << format);
+
+#undef ADD_OUTPUTTER
+ }
+ // Console coloring flag.
+ else if ((!strcmp(arg, "-c")) || (!strcmp(arg, "--color")))
+ {
+ if (argLast)
+ HAYAI_MAIN_USAGE_ERROR(
+ HAYAI_MAIN_FORMAT_FLAG(arg) <<
+ " requires an argument " <<
+ "of either " << HAYAI_MAIN_FORMAT_FLAG("yes") <<
+ " or " << HAYAI_MAIN_FORMAT_FLAG("no")
+ );
+
+ char* choice = argv[argI++];
+ bool enabled;
+
+ if ((!strcmp(choice, "yes")) ||
+ (!strcmp(choice, "true")) ||
+ (!strcmp(choice, "on")) ||
+ (!strcmp(choice, "1")))
+ enabled = true;
+ else if ((!strcmp(choice, "no")) ||
+ (!strcmp(choice, "false")) ||
+ (!strcmp(choice, "off")) ||
+ (!strcmp(choice, "0")))
+ enabled = false;
+ else
+ HAYAI_MAIN_USAGE_ERROR(
+ "invalid argument to " <<
+ HAYAI_MAIN_FORMAT_FLAG(arg) <<
+ ": " << choice
+ );
+
+ ::hayai::Console::SetFormattingEnabled(enabled);
+ }
+ // Help.
+ else if ((!strcmp(arg, "-?")) ||
+ (!strcmp(arg, "-h")) ||
+ (!strcmp(arg, "--help")))
+ {
+ ShowUsage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ else if (residualArgs)
+ {
+ residualArgs->push_back(arg);
+ }
+ else
+ {
+ HAYAI_MAIN_USAGE_ERROR("unknown option: " << arg);
+ }
+ }
+
+ return EXIT_SUCCESS;
+ }
+
+
+ /// Run the selected execution mode.
+
+ /// @returns the exit status code to be returned from the executable.
+ int Run()
+ {
+ // Execute based on the selected mode.
+ switch (ExecutionMode)
+ {
+ case ::hayai::MainRunBenchmarks:
+ return RunBenchmarks();
+
+ case ::hayai::MainListBenchmarks:
+ return ListBenchmarks();
+
+ default:
+ std::cerr << HAYAI_MAIN_FORMAT_ERROR(
+ "invalid execution mode: " << ExecutionMode
+ ) << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+ private:
+ /// Run benchmarks.
+
+ /// @returns the exit status code to be returned from the executable.
+ int RunBenchmarks()
+ {
+ // Hook up the outputs.
+ if (StdoutOutputter)
+ ::hayai::Benchmarker::AddOutputter(*StdoutOutputter);
+
+ for (std::vector< ::hayai::FileOutputter*>::iterator it =
+ FileOutputters.begin();
+ it < FileOutputters.end();
+ ++it)
+ {
+ ::hayai::FileOutputter& fileOutputter = **it;
+
+ try
+ {
+ fileOutputter.SetUp();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << HAYAI_MAIN_FORMAT_ERROR(e.what()) << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ ::hayai::Benchmarker::AddOutputter(fileOutputter.Outputter());
+ }
+
+ // Run the benchmarks.
+ if (ShuffleBenchmarks)
+ {
+ std::srand(static_cast<unsigned>(std::time(0)));
+ ::hayai::Benchmarker::ShuffleTests();
+ }
+
+ ::hayai::Benchmarker::RunAllTests();
+
+ return EXIT_SUCCESS;
+ }
+
+
+ /// List benchmarks.
+
+ /// @returns the exit status code to be returned from the executable.
+ int ListBenchmarks()
+ {
+ // List out the unique benchmark names.
+ std::vector<const ::hayai::TestDescriptor*> tests =
+ ::hayai::Benchmarker::ListTests();
+ std::vector<std::string> testNames;
+ std::set<std::string> uniqueTestNames;
+
+ for (std::vector<const ::hayai::TestDescriptor*>::iterator it =
+ tests.begin();
+ it < tests.end();
+ ++it)
+ {
+ if (uniqueTestNames.find((*it)->CanonicalName) !=
+ uniqueTestNames.end())
+ continue;
+
+ testNames.push_back((*it)->CanonicalName);
+ uniqueTestNames.insert((*it)->CanonicalName);
+ }
+
+ // Sort the benchmark names.
+ std::sort(testNames.begin(), testNames.end());
+
+ // Dump the list.
+ for (std::vector<std::string>::iterator it = testNames.begin();
+ it < testNames.end();
+ ++it)
+ std::cout << *it << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+
+ /// Show usage.
+
+ /// @param execName Executable name.
+ void ShowUsage(const char* execName)
+ {
+ const char* baseName = strrchr(execName, PATH_SEPARATOR);
+
+ std::cerr << "Usage: " << (baseName ? baseName + 1 : execName)
+ << " " << HAYAI_MAIN_FORMAT_FLAG("[OPTIONS]") << std::endl
+ << std::endl
+
+ << " Runs the benchmarks for this project." << std::endl
+ << std::endl
+
+ << "Benchmark selection options:" << std::endl
+ << " " << HAYAI_MAIN_FORMAT_FLAG("-l") << ", "
+ << HAYAI_MAIN_FORMAT_FLAG("--list")
+ << std::endl
+ << " List the names of all benchmarks instead of "
+ << "running them." << std::endl
+ << " " << HAYAI_MAIN_FORMAT_FLAG("-f") << ", "
+ << HAYAI_MAIN_FORMAT_FLAG("--filter")
+ << " <" << HAYAI_MAIN_FORMAT_ARGUMENT("pattern") << ">"
+ << std::endl
+ << " Run only the tests whose name matches one of the "
+ << "positive patterns but" << std::endl
+ << " none of the negative patterns. '?' matches any "
+ << "single character; '*'" << std::endl
+ << " matches any substring; ':' separates two "
+ << "patterns."
+ << std::endl
+
+ << "Benchmark execution options:" << std::endl
+ << " " << HAYAI_MAIN_FORMAT_FLAG("-s") << ", "
+ << HAYAI_MAIN_FORMAT_FLAG("--shuffle")
+ << std::endl
+ << " Randomize benchmark execution order."
+ << std::endl
+ << std::endl
+
+ << "Benchmark output options:" << std::endl
+ << " " << HAYAI_MAIN_FORMAT_FLAG("-o") << ", "
+ << HAYAI_MAIN_FORMAT_FLAG("--output")
+ << " <" << HAYAI_MAIN_FORMAT_ARGUMENT("format") << ">[:"
+ << HAYAI_MAIN_FORMAT_ARGUMENT("<path>") << "]"
+ << std::endl
+ << " Output results in a specific format. If no "
+ << "path is specified, the output" << std::endl
+ << " will be presented on stdout. Can be specified "
+ << "multiple times to get output" << std::endl
+ << " in different formats. The supported formats are:"
+ << std::endl
+ << std::endl
+ << " " << HAYAI_MAIN_FORMAT_ARGUMENT("console")
+ << std::endl
+ << " Standard console output." << std::endl
+ << " " << HAYAI_MAIN_FORMAT_ARGUMENT("json")
+ << std::endl
+ << " JSON." << std::endl
+ << " " << HAYAI_MAIN_FORMAT_ARGUMENT("junit")
+ << std::endl
+ << " JUnit-compatible XML (very restrictive.)"
+ << std::endl
+ << std::endl
+ << " If multiple output formats are provided without "
+ << "a path, only the last" << std::endl
+ << " provided format will be output to stdout."
+ << std::endl
+ << " " << HAYAI_MAIN_FORMAT_FLAG("--c") << ", "
+ << HAYAI_MAIN_FORMAT_FLAG("--color") << " ("
+ << ::hayai::Console::TextGreen << "yes"
+ << ::hayai::Console::TextDefault << "|"
+ << ::hayai::Console::TextGreen << "no"
+ << ::hayai::Console::TextDefault << ")" << std::endl
+ << " Enable colored output when available. Default "
+ << ::hayai::Console::TextGreen << "yes"
+ << ::hayai::Console::TextDefault << "." << std::endl
+ << std::endl
+
+ << "Miscellaneous options:" << std::endl
+ << " " << HAYAI_MAIN_FORMAT_FLAG("-?") << ", "
+ << HAYAI_MAIN_FORMAT_FLAG("-h") << ", "
+ << HAYAI_MAIN_FORMAT_FLAG("--help") << std::endl
+ << " Show this help information." << std::endl
+ << std::endl
+
+ << "hayai version: " << HAYAI_VERSION << std::endl
+ << "Clock implementation: "
+ << ::hayai::Clock::Description()
+ << std::endl;
+ }
+ };
+}
+
+
+#undef HAYAI_MAIN_FORMAT_FLAG
+#undef HAYAI_MAIN_FORMAT_ARGUMENT
+#undef HAYAI_MAIN_FORMAT_ERROR
+#undef HAYAI_MAIN_USAGE_ERROR
+
+#endif