diff options
Diffstat (limited to 'src/boost/libs/wave/test/testwave/testwave.cpp')
-rw-r--r-- | src/boost/libs/wave/test/testwave/testwave.cpp | 301 |
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; +} |