Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/wave/test/testwave/testwave.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 11.5 KB
Line 
1/*=============================================================================
2    Boost.Wave: A Standard compliant C++ preprocessor library
3    http://www.boost.org/
4
5    Copyright (c) 2001-2006 Hartmut Kaiser. Distributed under the Boost
6    Software License, Version 1.0. (See accompanying file
7    LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9
10// system headers
11#include <string>
12#include <iostream>
13#include <vector>
14
15// include boost
16#include <boost/config.hpp>
17#include <boost/filesystem/path.hpp>
18#include <boost/filesystem/operations.hpp>
19
20//  test application related headers
21#include "cmd_line_utils.hpp"
22#include "testwave_app.hpp"
23
24namespace po = boost::program_options;
25namespace fs = boost::filesystem;
26
27///////////////////////////////////////////////////////////////////////////////
28//
29//  The debuglevel command line parameter is used to control the amount of text
30//  printed by the testwave application.
31//
32//  level 0:    prints nothing except serious failures preventing the testwave
33//              executable from running, the return value of the executable is
34//              equal to the number of failed tests
35//  level 1:    prints a short summary only
36//  level 2:    prints the names of the failed tests only
37//  level 3:    prints the expected and real result for failed tests
38//  level 4:    prints the outcome of every test
39//  level 5:    prints the real result even for succeeded tests
40//
41//  level 9:    prints information about almost everything
42//
43//  The default debug level is 1.
44//
45///////////////////////////////////////////////////////////////////////////////
46
47///////////////////////////////////////////////////////////////////////////////
48int 
49main(int argc, char *argv[])
50{
51    int error_count = 0;
52    int config_file_error_count = 0;
53    try {
54    // analyze the command line options and arguments
55        po::options_description desc_cmdline ("Options allowed on the command line");
56        desc_cmdline.add_options()
57            ("help,h", "print out program usage (this message)")
58            ("version,v", "print the version number")
59            ("copyright,c", "print out the copyright statement")
60            ("config-file", po::value<std::vector<std::string> >()->composing(), 
61                "specify a config file (alternatively: @arg)")
62            ("debug,d", po::value<int>(), "set the debug level (0...9)")
63        ;
64
65    // Hidden options, will be used in in config file analysis to allow to
66    // recognise positional arguments, will not be shown to the user.
67        po::options_description desc_hidden("Hidden options");
68        desc_hidden.add_options()
69            ("input", po::value<std::vector<std::string> >()->composing(), 
70                "inputfile")
71        ;       
72
73    // this is the test application object
74        po::variables_map vm;
75        testwave_app app(vm);
76
77    // all command line and config file options
78        po::options_description cmdline_options;
79        cmdline_options.add(desc_cmdline).add(app.common_options());
80
81    // parse command line
82        // (the (int) cast is to make the True64 compiler happy)
83        using namespace boost::program_options::command_line_style;
84        po::parsed_options opts(po::parse_command_line(argc, argv, 
85            cmdline_options, (int)unix_style, cmd_line_utils::at_option_parser));
86       
87        po::store(opts, vm);
88        po::notify(vm);
89
90    // ... act as required
91        if (vm.count("help")) {
92            po::options_description desc_help (
93                "Usage: testwave [options] [@config-file(s)] file(s)");
94            desc_help.add(desc_cmdline).add(app.common_options());
95            std::cout << desc_help << std::endl;
96            return 0;
97        }
98       
99    // debug flag
100        if (vm.count("debug")) {
101            int debug_level = vm["debug"].as<int>();
102            if (debug_level < 0 || debug_level > 9) {
103                std::cerr
104                    << "testwave: please use an integer in the range [0..9] "
105                    << "as the parameter to the debug option!" 
106                    << std::endl;
107            }
108            else {
109                app.set_debuglevel(debug_level);
110            }
111        }
112       
113        if (vm.count("version")) {
114            return app.print_version();
115        }
116
117        if (vm.count("copyright")) {
118            return app.print_copyright();
119        }
120       
121    // If there is specified at least one config file, parse it and add the
122    // options to the main variables_map
123    // Each of the config files is parsed into a separate variables_map to
124    // allow correct paths handling.
125        int input_count = 0;
126        if (vm.count("config-file")) {
127            std::vector<std::string> const &cfg_files = 
128                vm["config-file"].as<std::vector<std::string> >();
129
130            if (9 == app.get_debuglevel()) {
131                std::cerr << "found " << (unsigned)cfg_files.size() 
132                          << " config-file arguments" << std::endl;
133            }
134           
135            std::vector<std::string>::const_iterator end = cfg_files.end();
136            for (std::vector<std::string>::const_iterator cit = cfg_files.begin(); 
137                 cit != end; ++cit)
138            {
139                if (9 == app.get_debuglevel()) {
140                    std::cerr << "reading config_file: " << *cit << std::endl;
141                }
142               
143            // parse a single config file and store the results, config files
144            // may only contain --input and positional arguments
145                po::variables_map cvm;
146                if (!cmd_line_utils::read_config_file(app.get_debuglevel(), 
147                    *cit, desc_hidden, cvm)) 
148                {
149                    if (9 == app.get_debuglevel()) {
150                        std::cerr << "failed to read config_file: " << *cit
151                                  << std::endl;
152                    }
153                    ++config_file_error_count;
154                }
155               
156                if (9 == app.get_debuglevel()) {
157                    std::cerr << "succeeded to read config_file: " << *cit
158                              << std::endl;
159                }
160               
161            // correct the paths parsed into this variables_map
162                if (cvm.count("input")) {
163                    std::vector<std::string> const &infiles = 
164                        cvm["input"].as<std::vector<std::string> >();
165                   
166                    if (9 == app.get_debuglevel()) {
167                        std::cerr << "found " << (unsigned)infiles.size() 
168                                  << " entries" << std::endl;
169                    }
170                   
171                    std::vector<std::string>::const_iterator iend = infiles.end();
172                    for (std::vector<std::string>::const_iterator iit = infiles.begin(); 
173                         iit != iend; ++iit)
174                    {
175                    // correct the file name (prepend the cfg file path)
176                        fs::path cfgpath = fs::complete(
177                            fs::path(*cit, fs::native), fs::current_path());
178                        fs::path filepath = 
179                            cfgpath.branch_path() / fs::path(*iit, fs::native);
180                       
181                        if (9 == app.get_debuglevel()) {
182                            std::cerr << std::string(79, '-') << std::endl;
183                            std::cerr << "executing test: " 
184                                      << filepath.native_file_string()
185                                      << std::endl;
186                        }
187                   
188                    // execute this unit test case
189                        if (!app.test_a_file(filepath.native_file_string())) {
190                            if (9 == app.get_debuglevel()) {
191                                std::cerr << "failed to execute test: " 
192                                          << filepath.native_file_string()
193                                          << std::endl;
194                            }
195                            ++error_count;
196                        }
197                        else if (9 == app.get_debuglevel()) {
198                            std::cerr << "succeeded to execute test: " 
199                                      << filepath.native_file_string()
200                                      << std::endl;
201                        }
202                        ++input_count;
203                       
204                        if (9 == app.get_debuglevel()) {
205                            std::cerr << std::string(79, '-') << std::endl;
206                        }
207                    }
208                }
209                else if (9 == app.get_debuglevel()) {
210                    std::cerr << "no entries found" << std::endl;
211                }
212            }
213        }
214
215    // extract the arguments from the parsed command line
216        std::vector<po::option> arguments;
217        std::remove_copy_if(opts.options.begin(), opts.options.end(), 
218            std::back_inserter(arguments), cmd_line_utils::is_argument());
219
220        if (9 == app.get_debuglevel()) {
221            std::cerr << "found " << (unsigned)arguments.size() 
222                      << " arguments" << std::endl;
223        }
224       
225    // iterate over remaining arguments
226        std::vector<po::option>::const_iterator arg_end = arguments.end();
227        for (std::vector<po::option>::const_iterator arg = arguments.begin();
228             arg != arg_end; ++arg)
229        {
230            fs::path filepath((*arg).value[0], fs::native);
231
232            if (9 == app.get_debuglevel()) {
233                std::cerr << std::string(79, '-') << std::endl;
234                std::cerr << "executing test: " 
235                          << filepath.native_file_string()
236                          << std::endl;
237            }
238                   
239            if (!app.test_a_file(filepath.native_file_string())) {
240                if (9 == app.get_debuglevel()) {
241                    std::cerr << "failed to execute test: " 
242                              << filepath.native_file_string()
243                              << std::endl;
244                }
245                ++error_count;
246            }
247            else if (9 == app.get_debuglevel()) {
248                std::cerr << "succeeded to execute test: " 
249                          << filepath.native_file_string()
250                          << std::endl;
251            }
252
253            if (9 == app.get_debuglevel()) {
254                std::cerr << std::string(79, '-') << std::endl;
255            }
256            ++input_count;
257        }
258
259    // print a message if no input is given
260        if (0 == input_count) {
261            std::cerr
262                << "testwave: no input file specified, " 
263                << "try --help to get a hint." 
264                << std::endl;
265            return (std::numeric_limits<int>::max)() - 3;
266        }
267        else if (app.get_debuglevel() > 0) {
268            std::cout
269                << "testwave: " << input_count-error_count
270                << " of " << input_count << " test(s) succeeded";
271            if (0 != error_count) {
272                std::cout
273                    << " (" << error_count << " test(s) failed)";
274            }
275            std::cout << "." << std::endl;
276        }
277    }
278    catch (std::exception const& e) {
279        std::cerr << "testwave: exception caught: " << e.what() << std::endl;
280        return (std::numeric_limits<int>::max)() - 1;
281    }
282    catch (...) {
283        std::cerr << "testwave: unexpected exception caught." << std::endl;
284        return (std::numeric_limits<int>::max)() - 2;
285    }
286
287    return error_count + config_file_error_count;
288}
Note: See TracBrowser for help on using the repository browser.