123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- /*
- *
- * 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 <boost/version.hpp>
- * DESCRIPTION: Error handling for test cases.
- */
- #ifndef BOOST_REGEX_REGRESS_INFO_HPP
- #define BOOST_REGEX_REGRESS_INFO_HPP
- #include <iostream>
- #include <string>
- #include <boost/regex.hpp>
- #ifdef TEST_THREADS
- #include <boost/thread/once.hpp>
- #include <boost/thread.hpp>
- #endif
- #ifdef GENERATE_CORPUS
- #include <boost/lexical_cast.hpp>
- #include <fstream>
- //
- // class de_fuzz_output
- // Generates de-fuzzing corpus files
- //
- template <class charT>
- class de_fuzz_output
- {
- public:
- de_fuzz_output() {}
- template <class U>
- void add(const U&, const U&) {}
- };
- template<>
- class de_fuzz_output<char>
- {
- std::set<std::pair<std::string, std::string> > 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<std::pair<std::string, std::string> >::const_iterator i = data.begin(); i != data.end(); ++i)
- {
- std::string filename = "corpus_" + boost::lexical_cast<std::string>(j);
- std::fstream ofs(filename.c_str(), std::ios_base::out | std::ios_base::binary);
- ofs.put(static_cast<char>(i->first.size() >> 8));
- ofs.put(static_cast<char>(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 charT>
- class test_info_base
- {
- public:
- typedef std::basic_string<charT> 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<data_type> 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<charT> 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 <class T>
- struct test_info
- : public test_info_base<wchar_t>
- {};
- template<>
- struct test_info<char>
- : public test_info_base<char>
- {};
- #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<wchar_t>::data_type & test_info_base<wchar_t>::data();
- template test_info_base<char>::data_type & test_info_base<char>::data();
- #endif
- template <class charT>
- std::ostream& operator<<(std::ostream& os, const test_info<charT>&)
- {
- if(test_info<charT>::need_to_print())
- {
- os << test_info<charT>::file() << ":" << test_info<charT>::line() << ": Error in test here:" << std::endl;
- test_info<charT>::clear();
- }
- return os;
- }
- //
- // define some test macros:
- //
- extern int error_count;
- #define BOOST_REGEX_TEST_ERROR(msg, charT)\
- ++error_count;\
- std::cerr << test_info<charT>();\
- std::cerr << " " << __FILE__ << ":" << __LINE__ << ":" << msg \
- << " (While testing " << test_info<charT>::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 << "<note>The above " << (error_count - m_saved_error_count) << " errors are treated as warnings only.</note>" << std::endl;
- error_count = m_saved_error_count;
- }
- }
- private:
- int m_saved_error_count;
- };
- #endif
|