/* * * Copyright (c) 2004 * John Maddock * * Use, modification and distribution are subject to 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) * */ /* * LOCATION: see http://www.boost.org for most recent version. * FILE info.hpp * VERSION see * DESCRIPTION: Error handling for test cases. */ #ifndef BOOST_REGEX_REGRESS_INFO_HPP #define BOOST_REGEX_REGRESS_INFO_HPP #include #include #include #ifdef TEST_THREADS #include #include #endif #ifdef GENERATE_CORPUS #include #include // // class de_fuzz_output // Generates de-fuzzing corpus files // template class de_fuzz_output { public: de_fuzz_output() {} template void add(const U&, const U&) {} }; template<> class de_fuzz_output { std::set > data; public: de_fuzz_output() {} void add(const std::string& re, const std::string& text) { data.insert(std::make_pair(re, text)); } ~de_fuzz_output() { unsigned j = 0; for(typename std::set >::const_iterator i = data.begin(); i != data.end(); ++i) { std::string filename = "corpus_" + boost::lexical_cast(j); std::fstream ofs(filename.c_str(), std::ios_base::out | std::ios_base::binary); ofs.put(static_cast(i->first.size() >> 8)); ofs.put(static_cast(i->first.size() & 0xff)); ofs.write(i->first.c_str(), i->first.size()); ofs.write(i->second.c_str(), i->second.size()); ++j; } } }; #endif // // class test info, // store information about the test we are about to conduct: // template class test_info_base { public: typedef std::basic_string string_type; private: struct data_type { std::string file; int line; string_type expression; boost::regex_constants::syntax_option_type options; string_type search_text; boost::regex_constants::match_flag_type match_options; const int* answer_table; string_type format_string; string_type result_string; bool need_to_print; std::string expression_type_name; }; #ifdef TEST_THREADS static data_type& do_get_data() { static boost::thread_specific_ptr pd; if(pd.get() == 0) pd.reset(new data_type()); return *(pd.get()); } static void init_data() { do_get_data(); } #endif static data_type& data() { #ifdef TEST_THREADS static boost::once_flag f = BOOST_ONCE_INIT; boost::call_once(f,&init_data); return do_get_data(); #else static data_type d = {}; return d; #endif } public: test_info_base(){}; static void set_info( const char* file, int line, const string_type& ex, boost::regex_constants::syntax_option_type opt, const string_type& search_text = string_type(), boost::regex_constants::match_flag_type match_options = boost::match_default, const int* answer_table = 0, const string_type& format_string = string_type(), const string_type& result_string = string_type()) { data_type& dat = data(); dat.file = file; dat.line = line; dat.expression = ex; dat.options = opt; dat.search_text = search_text; dat.match_options = match_options; dat.answer_table = answer_table; dat.format_string = format_string; dat.result_string = result_string; dat.need_to_print = true; #ifdef GENERATE_CORPUS static de_fuzz_output corpus; corpus.add(ex, search_text); #endif } static void set_typename(const std::string& n) { data().expression_type_name = n; } static const string_type& expression() { return data().expression; } static boost::regex_constants::syntax_option_type syntax_options() { return data().options; } static const string_type& search_text() { return data().search_text; } static boost::regex_constants::match_flag_type match_options() { return data().match_options; } static const int* answer_table() { return data().answer_table; } static const string_type& format_string() { return data().format_string; } static const string_type& result_string() { return data().result_string; } static bool need_to_print() { return data().need_to_print; } static const std::string& file() { return data().file; } static int line() { return data().line; } static void clear() { data().need_to_print = false; } static std::string& expression_typename() { return data().expression_type_name; } }; template struct test_info : public test_info_base {}; template<> struct test_info : public test_info_base {}; #if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) // Some template instantiation modes (namely local, implicit local, and weak) of // this compiler need an explicit instantiation because otherwise we end up with // multiple copies of the static variable defined in this method. This explicit // instantiation generates the static variable with common linkage, which makes // the linker choose only one of the available definitions. For more details, // see "man ld". template test_info_base::data_type & test_info_base::data(); template test_info_base::data_type & test_info_base::data(); #endif template std::ostream& operator<<(std::ostream& os, const test_info&) { if(test_info::need_to_print()) { os << test_info::file() << ":" << test_info::line() << ": Error in test here:" << std::endl; test_info::clear(); } return os; } // // define some test macros: // extern int error_count; #define BOOST_REGEX_TEST_ERROR(msg, charT)\ ++error_count;\ std::cerr << test_info();\ std::cerr << " " << __FILE__ << ":" << __LINE__ << ":" << msg \ << " (While testing " << test_info::expression_typename() << ")" << std::endl class errors_as_warnings { public: errors_as_warnings() { m_saved_error_count = error_count; } ~errors_as_warnings() { if(m_saved_error_count != error_count) { std::cerr << "The above " << (error_count - m_saved_error_count) << " errors are treated as warnings only." << std::endl; error_count = m_saved_error_count; } } private: int m_saved_error_count; }; #endif