summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/wave/test/testwave/testwave.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/wave/test/testwave/testwave.cpp')
-rw-r--r--src/boost/libs/wave/test/testwave/testwave.cpp301
1 files changed, 301 insertions, 0 deletions
diff --git a/src/boost/libs/wave/test/testwave/testwave.cpp b/src/boost/libs/wave/test/testwave/testwave.cpp
new file mode 100644
index 000000000..e5e481d0d
--- /dev/null
+++ b/src/boost/libs/wave/test/testwave/testwave.cpp
@@ -0,0 +1,301 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+ http://www.boost.org/
+
+ Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+// disable stupid compiler warnings
+#include <boost/config/warning_disable.hpp>
+
+// system headers
+#include <string>
+#include <iostream>
+#include <vector>
+
+// include boost
+#include <boost/config.hpp>
+#include <boost/wave.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+
+// test application related headers
+#include "cmd_line_utils.hpp"
+#include "testwave_app.hpp"
+
+namespace po = boost::program_options;
+namespace fs = boost::filesystem;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// The debuglevel command line parameter is used to control the amount of text
+// printed by the testwave application.
+//
+// level 0: prints nothing except serious failures preventing the testwave
+// executable from running, the return value of the executable is
+// equal to the number of failed tests
+// level 1: prints a short summary only
+// level 2: prints the names of the failed tests only
+// level 3: prints the expected and real result for failed tests
+// level 4: prints the outcome of every test
+// level 5: prints the real result even for succeeded tests
+// level 6: prints the real hooks information recorded, even for succeeded
+// tests
+//
+// level 9: prints information about almost everything
+//
+// The default debug level is 1.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main(int argc, char *argv[])
+{
+ int error_count = 0;
+ int config_file_error_count = 0;
+ try {
+ // analyze the command line options and arguments
+ po::options_description desc_cmdline ("Options allowed on the command line");
+ desc_cmdline.add_options()
+ ("help,h", "print out program usage (this message)")
+ ("version,v", "print the version number")
+ ("copyright,c", "print out the copyright statement")
+ ("config-file", po::value<std::vector<std::string> >()->composing(),
+ "specify a config file (alternatively: @arg)")
+ ("hooks", po::value<bool>()->default_value(true),
+ "test preprocessing hooks")
+ ("debug,d", po::value<int>(), "set the debug level (0...9)")
+ ;
+
+ // Hidden options, will be used in in config file analysis to allow to
+ // recognize positional arguments, will not be shown to the user.
+ po::options_description desc_hidden("Hidden options");
+ desc_hidden.add_options()
+ ("input", po::value<std::vector<std::string> >()->composing(),
+ "inputfile")
+ ;
+
+ // this is the test application object
+ po::variables_map vm;
+ testwave_app app(vm);
+
+ // all command line and config file options
+ po::options_description cmdline_options;
+ cmdline_options.add(desc_cmdline).add(app.common_options());
+
+ // parse command line
+ // (the (int) cast is to make the True64 compiler happy)
+ using namespace boost::program_options::command_line_style;
+ po::parsed_options opts(po::parse_command_line(argc, argv,
+ cmdline_options, (int)unix_style, cmd_line_utils::at_option_parser));
+
+ po::store(opts, vm);
+ po::notify(vm);
+
+ // ... act as required
+ if (vm.count("help")) {
+ po::options_description desc_help (
+ "Usage: testwave [options] [@config-file(s)] file(s)");
+ desc_help.add(desc_cmdline).add(app.common_options());
+ std::cout << desc_help << std::endl;
+ return 0;
+ }
+
+ // debug flag
+ if (vm.count("debug")) {
+ int debug_level = vm["debug"].as<int>();
+ if (debug_level < 0 || debug_level > 9) {
+ std::cerr
+ << "testwave: please use an integer in the range [0..9] "
+ << "as the parameter to the debug option!"
+ << std::endl;
+ }
+ else {
+ app.set_debuglevel(debug_level);
+ }
+ }
+
+ if (vm.count("version")) {
+ return app.print_version();
+ }
+
+ if (vm.count("copyright")) {
+ return app.print_copyright();
+ }
+
+ // If there is specified at least one config file, parse it and add the
+ // options to the main variables_map
+ // Each of the config files is parsed into a separate variables_map to
+ // allow correct paths handling.
+ int input_count = 0;
+ if (vm.count("config-file")) {
+ std::vector<std::string> const &cfg_files =
+ vm["config-file"].as<std::vector<std::string> >();
+
+ if (9 == app.get_debuglevel()) {
+ std::cerr << "found " << (unsigned)cfg_files.size()
+ << " config-file arguments" << std::endl;
+ }
+
+ std::vector<std::string>::const_iterator end = cfg_files.end();
+ for (std::vector<std::string>::const_iterator cit = cfg_files.begin();
+ cit != end; ++cit)
+ {
+ if (9 == app.get_debuglevel()) {
+ std::cerr << "reading config_file: " << *cit << std::endl;
+ }
+
+ // parse a single config file and store the results, config files
+ // may only contain --input and positional arguments
+ po::variables_map cvm;
+ if (!cmd_line_utils::read_config_file(app.get_debuglevel(),
+ *cit, desc_hidden, cvm))
+ {
+ if (9 == app.get_debuglevel()) {
+ std::cerr << "failed to read config_file: " << *cit
+ << std::endl;
+ }
+ ++config_file_error_count;
+ }
+
+ if (9 == app.get_debuglevel()) {
+ std::cerr << "succeeded to read config_file: " << *cit
+ << std::endl;
+ }
+
+ // correct the paths parsed into this variables_map
+ if (cvm.count("input")) {
+ std::vector<std::string> const &infiles =
+ cvm["input"].as<std::vector<std::string> >();
+
+ if (9 == app.get_debuglevel()) {
+ std::cerr << "found " << (unsigned)infiles.size()
+ << " entries" << std::endl;
+ }
+
+ std::vector<std::string>::const_iterator iend = infiles.end();
+ for (std::vector<std::string>::const_iterator iit = infiles.begin();
+ iit != iend; ++iit)
+ {
+ // correct the file name (pre-pend the config file path)
+ fs::path cfgpath = boost::wave::util::complete_path(
+ boost::wave::util::create_path(*cit),
+ boost::wave::util::current_path());
+ fs::path filepath =
+ boost::wave::util::branch_path(cfgpath) /
+ boost::wave::util::create_path(*iit);
+
+ if (9 == app.get_debuglevel()) {
+ std::cerr << std::string(79, '-') << std::endl;
+ std::cerr << "executing test: "
+ << boost::wave::util::native_file_string(filepath)
+ << std::endl;
+ }
+
+ // execute this unit test case
+ if (!app.test_a_file(
+ boost::wave::util::native_file_string(filepath)))
+ {
+ if (9 == app.get_debuglevel()) {
+ std::cerr << "failed to execute test: "
+ << boost::wave::util::native_file_string(filepath)
+ << std::endl;
+ }
+ ++error_count;
+ }
+ else if (9 == app.get_debuglevel()) {
+ std::cerr << "succeeded to execute test: "
+ << boost::wave::util::native_file_string(filepath)
+ << std::endl;
+ }
+ ++input_count;
+
+ if (9 == app.get_debuglevel()) {
+ std::cerr << std::string(79, '-') << std::endl;
+ }
+ }
+ }
+ else if (9 == app.get_debuglevel()) {
+ std::cerr << "no entries found" << std::endl;
+ }
+ }
+ }
+
+ // extract the arguments from the parsed command line
+ std::vector<po::option> arguments;
+ std::remove_copy_if(opts.options.begin(), opts.options.end(),
+ std::back_inserter(arguments), cmd_line_utils::is_argument());
+
+ if (9 == app.get_debuglevel()) {
+ std::cerr << "found " << (unsigned)arguments.size()
+ << " arguments" << std::endl;
+ }
+
+ // iterate over remaining arguments
+ std::vector<po::option>::const_iterator arg_end = arguments.end();
+ for (std::vector<po::option>::const_iterator arg = arguments.begin();
+ arg != arg_end; ++arg)
+ {
+ fs::path filepath(boost::wave::util::create_path((*arg).value[0]));
+
+ if (9 == app.get_debuglevel()) {
+ std::cerr << std::string(79, '-') << std::endl;
+ std::cerr << "executing test: "
+ << boost::wave::util::native_file_string(filepath)
+ << std::endl;
+ }
+
+ if (!app.test_a_file(boost::wave::util::native_file_string(filepath)))
+ {
+ if (9 == app.get_debuglevel()) {
+ std::cerr << "failed to execute test: "
+ << boost::wave::util::native_file_string(filepath)
+ << std::endl;
+ }
+ ++error_count;
+ }
+ else if (9 == app.get_debuglevel()) {
+ std::cerr << "succeeded to execute test: "
+ << boost::wave::util::native_file_string(filepath)
+ << std::endl;
+ }
+
+ if (9 == app.get_debuglevel()) {
+ std::cerr << std::string(79, '-') << std::endl;
+ }
+ ++input_count;
+ }
+
+ // print a message if no input is given
+ if (0 == input_count) {
+ std::cerr
+ << "testwave: no input file specified, "
+ << "try --help to get a hint."
+ << std::endl;
+ return (std::numeric_limits<int>::max)() - 3;
+ }
+ else if (app.get_debuglevel() > 0) {
+ std::cout
+ << "testwave: " << input_count-error_count
+ << " of " << input_count << " test(s) succeeded";
+ if (0 != error_count) {
+ std::cout
+ << " (" << error_count << " test(s) failed)";
+ }
+ std::cout << "." << std::endl;
+ }
+ }
+ catch (std::exception const& e) {
+ std::cerr << "testwave: exception caught: " << e.what() << std::endl;
+ return (std::numeric_limits<int>::max)() - 1;
+ }
+ catch (...) {
+ std::cerr << "testwave: unexpected exception caught." << std::endl;
+ return (std::numeric_limits<int>::max)() - 2;
+ }
+
+ return error_count + config_file_error_count;
+}