First cut at new v5 regex version, doesn't really work yet, but all the infrastructure is in place...

[SVN r22489]
This commit is contained in:
John Maddock committed 2004-03-12 13:22:44 +00:00
1 parent 99d5760d2b
commit 4d2d3a1450
65 files changed
+5155 -7075

No files matched your search

+2 -3
View File
@@ -22,9 +22,8 @@ template test
#
template regression
: <template>test # sources
regress/parse.cpp
regress/regress.cpp
regress/tests.cpp
regress/main.cpp
regress/basic_tests.cpp
<lib>../../test/build/boost_prg_exec_monitor
;
+13 -3
View File
@@ -2,9 +2,19 @@
subproject libs/regex/test/captures ;
EX_SOURCES = c_regex_traits c_regex_traits_common cpp_regex_traits
cregex fileiter posix_api regex regex_debug
regex_synch w32_regex_traits wide_posix_api instances winstances ;
EX_SOURCES =
cpp_regex_traits.cpp
cregex.cpp
fileiter.cpp
instances.cpp
posix_api.cpp
regex.cpp
regex_debug.cpp
regex_raw_buffer.cpp
regex_traits_defaults.cpp
static_mutex.cpp
wide_posix_api.cpp
winstances.cpp ;
lib boost_regex_extra : ../../src/$(EX_SOURCES).cpp <template>../../build/regex-options
:
File diff suppressed because it is too large. Load diff
+126
View File
@@ -0,0 +1,126 @@
#ifndef BOOST_REGEX_REGRESS_INFO_HPP
#define BOOST_REGEX_REGRESS_INFO_HPP
#include <iostream>
#include <string>
#include <boost/regex.hpp>
//
// class test info,
// store information about the test we are about to conduct:
//
template <class charT>
class test_info
{
typedef std::basic_string<charT> string_type;
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;
};
static data_type& data()
{
static data_type d;
return d;
}
public:
test_info(){};
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;
}
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;
}
};
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 << std::endl
#endif
+45
View File
@@ -0,0 +1,45 @@
#include "test.hpp"
#include <stdarg.h>
int error_count = 0;
int cpp_main(int argc, char * argv[])
{
basic_tests();
return error_count;
}
const int* make_array(int first, ...)
{
//
// this function takes a variable number of arguments
// and packs them into an array that we can pass through
// our testing macros (ideally we would use an array literal
// but these can't apparently be used as macro arguments).
//
static int data[200];
va_list ap;
va_start(ap, first);
//
// keep packing args, until we get two successive -2 values:
//
int terminator_count;
int next_position = 1;
data[0] = first;
if(first == -2)
terminator_count = 1;
else
terminator_count = 0;
while(terminator_count < 2)
{
data[next_position] = va_arg(ap, int);
if(data[next_position] == -2)
++terminator_count;
else
terminator_count = 0;
++next_position;
}
va_end(ap);
return data;
}
-346
View File
@@ -1,346 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* Dr 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)
*
*/
/*
*
* FILE parse.cpp
* VERSION see <boost/version.hpp>
*
* Input parsing functions for regress.
*
*/
#include <boost/regex.hpp>
#include "regress.h"
#ifndef BOOST_REGEX_NO_TEST
#ifndef BOOST_RE_ALGO_INCLUDED
#include <algorithm>
#endif
using namespace boost;
#ifdef BOOST_REGEX_V3
#define regex_constants regbase
#endif
//
// start by defining all our flag types:
flag_info flag_data[] = {
{ BOOST_RE_STR("REG_BASIC"), 9, REG_BASIC, 0 },
{ BOOST_RE_STR("REG_EXTENDED"), 12, REG_EXTENDED, 0 },
{ BOOST_RE_STR("REG_ESCAPE_IN_LISTS"), 19, REG_ESCAPE_IN_LISTS, 0 },
{ BOOST_RE_STR("REG_ICASE"), 9, REG_ICASE, 0 },
{ BOOST_RE_STR("REG_NOSUB"), 9, REG_NOSUB, 0 },
{ BOOST_RE_STR("REG_NEWLINE"), 11, REG_NEWLINE, 0 },
{ BOOST_RE_STR("REG_NOCOLLATE"), 13, REG_NOCOLLATE, 0 },
{ BOOST_RE_STR("REG_NOSPEC"), 10, REG_NOSPEC, 0 },
{ BOOST_RE_STR("REG_NEWLINE_ALT"), 15, REG_NEWLINE_ALT , 0 },
{ BOOST_RE_STR("REG_PERL"), 8, REG_PERL, 0 },
{ BOOST_RE_STR("REG_AWK"), 7, REG_AWK, 0 },
{ BOOST_RE_STR("REG_EGREP"), 9, REG_EGREP, 0 },
{ BOOST_RE_STR("REG_NOTBOL"), 10, REG_NOTBOL, 1 },
{ BOOST_RE_STR("REG_NOTEOL"), 10, REG_NOTEOL, 1 },
{ BOOST_RE_STR("REG_STARTEND"), 12, REG_STARTEND, 1 },
{ BOOST_RE_STR("basic"), 5, regex_constants::basic, 2 },
{ BOOST_RE_STR("escape_in_lists"), 15, regex_constants::escape_in_lists, 2 },
{ BOOST_RE_STR("char_classes"), 12, regex_constants::char_classes, 2 },
{ BOOST_RE_STR("intervals"), 9, regex_constants::intervals, 2 },
{ BOOST_RE_STR("limited_ops"), 11, regex_constants::limited_ops, 2 },
{ BOOST_RE_STR("newline_alt"), 11, regex_constants::newline_alt, 2 },
{ BOOST_RE_STR("bk_plus_qm"), 10, regex_constants::bk_plus_qm, 2 },
{ BOOST_RE_STR("bk_braces"), 9, regex_constants::bk_braces, 2 },
{ BOOST_RE_STR("bk_parens"), 9, regex_constants::bk_parens, 2 },
{ BOOST_RE_STR("bk_refs"), 7, regex_constants::bk_refs, 2 },
{ BOOST_RE_STR("bk_vbar"), 7, regex_constants::bk_vbar, 2 },
{ BOOST_RE_STR("use_except"), 10, regex_constants::use_except, 2 },
{ BOOST_RE_STR("literal"), 7, regex_constants::literal, 2 },
#ifndef BOOST_REGEX_V3
{ BOOST_RE_STR("nosubs"), 6, regex_constants::nosubs, 2 },
{ BOOST_RE_STR("optimize"), 8, regex_constants::optimize, 2 },
{ BOOST_RE_STR("perlex"), 6, regex_constants::perlex, 2 },
#endif
{ BOOST_RE_STR("normal"), 6, regex_constants::normal, 2 },
{ BOOST_RE_STR("basic"), 5, regex_constants::basic, 2 },
{ BOOST_RE_STR("extended"), 8, regex_constants::extended, 2 },
{ BOOST_RE_STR("perl"), 6, regex_constants::perl, 2 },
{ BOOST_RE_STR("match_default"), 13, match_default, 3 },
{ BOOST_RE_STR("match_not_bol"), 13, match_not_bol, 3 },
{ BOOST_RE_STR("match_not_eol"), 13, match_not_eol, 3 },
{ BOOST_RE_STR("match_not_bob"), 13, match_not_bob, 3 },
{ BOOST_RE_STR("match_not_eob"), 13, match_not_eob, 3 },
{ BOOST_RE_STR("match_not_bow"), 13, match_not_bow, 3 },
{ BOOST_RE_STR("match_not_eow"), 13, match_not_eow, 3 },
{ BOOST_RE_STR("match_not_dot_newline"), 21, match_not_dot_newline, 3 },
{ BOOST_RE_STR("match_not_dot_null"), 18, match_not_dot_null, 3 },
{ BOOST_RE_STR("match_prev_avail"), 16, match_prev_avail, 3 },
{ BOOST_RE_STR("match_any"), 9, match_any, 3 },
{ BOOST_RE_STR("match_not_null"), 14, match_not_null, 3 },
{ BOOST_RE_STR("match_continuous"), 16, match_continuous, 3 },
{ BOOST_RE_STR("match_partial"), 13, match_partial, 3 },
#ifndef BOOST_REGEX_V3
{ BOOST_RE_STR("match_nosubs"), 12, match_nosubs, 3 },
{ BOOST_RE_STR("match_single_line"), 17, match_single_line, 3 },
#endif
{ BOOST_RE_STR("format_all"), 10, format_all, 3 },
{ BOOST_RE_STR("format_sed"), 10, format_sed, 3 },
{ BOOST_RE_STR("format_perl"), 11, format_perl, 3 },
{ BOOST_RE_STR("format_no_copy"), 14, format_no_copy, 3 },
{ BOOST_RE_STR("format_first_only"), 17, format_first_only, 3 },
{ BOOST_RE_STR("REG_NO_POSIX_TEST"), 17, REG_NO_POSIX_TEST, 4 },
{ BOOST_RE_STR("REG_UNICODE_ONLY"), 16, REG_UNICODE_ONLY, 4 },
{ BOOST_RE_STR("REG_GREP"), 8, REG_GREP, 4 },
{ BOOST_RE_STR("REG_MERGE"), 9, REG_MERGE, 4 },
{ BOOST_RE_STR("REG_MERGE_COPY"), 14, REG_MERGE_COPY, 4 },
{ BOOST_RE_STR("REG_PARTIAL_MATCH"), 17, REG_PARTIAL_MATCH, 4 },
{ BOOST_RE_STR(""), 0, 0, 0 },
};
// basically we create a simple token parser
// using regular expressions
const char_t* expression_text = BOOST_RE_STR("(;.*)|") // comment
BOOST_RE_STR("(^[[:blank:]]*-)|") // -
BOOST_RE_STR("([^\"[:space:]][^[:space:]]*)|") // token
BOOST_RE_STR("(\"((\\\\\"|[^\"])*)\")") // "token"
;
typedef basic_regex<char_t> re_parse_t;
typedef match_results<string_type::const_iterator> parse_grep;
typedef string_type::const_iterator parse_iterator;
re_parse_t parse_expression(expression_text, regex_constants::normal);
//
// now define our grep predicate function object:
class parse_function
{
int mode;
public:
parse_function() : mode(0) {}
parse_function(const parse_function& o) : mode(o.mode) {}
bool operator()(const parse_grep& i);
};
bool parse_function::operator()(const parse_grep& g)
{
parse_iterator i, j;
// determine what caused the match:
if(g[1].matched)
{
// we have a comment:
return true;
}
else if(g[2].matched)
{
// we have the start of a line of flags
mode = -1;
for(int i = 0; i < 5; ++i)
flags[i] = 0;
return true;
}
else if(g[3].matched)
{
// token:
i = g[3].first;
j = g[3].second;
}
else
{
// token delimited by ""
i = g[5].first;
j = g[5].second;
}
// now we need to switch depending upon what mode we are in:
switch(mode)
{
case -1:
{
// parse the flag:
unsigned int id = 0;
while(flag_data[id].len != 0)
{
if(static_cast<unsigned int>(j - i) != flag_data[id].len)
{
++id;
continue;
}
if(std::equal(i, j, flag_data[id].name) == true)
{
flags[flag_data[id].id] |= flag_data[id].value;
return true;
}
++id;
}
cout << "Warning: Unknown flag: ";
string_type t(i, j);
cout << make_narrow(t).c_str();
cout << endl;
return true;
}
case 0:
// set the expression text:
expression = string_type(i, j);
do_test = true;
break;
case 1:
// set the text to match:
search_text = string_type(i, j);
jm_trace("Initial search text: " << make_narrow(search_text).c_str());
expand_escapes(search_text);
jm_trace("Search text after escapes expanded: " << make_narrow(search_text).c_str());
break;
case 2:
// maybe set format string:
if(flags[4] & REG_MERGE)
{
format_string = string_type(i, j);
break;
}
else
{
matches[mode - 2] = to_int(i, j);
break;
}
case 3:
// maybe set format result:
if(flags[4] & REG_MERGE)
{
merge_string = string_type(i, j);
expand_escapes(merge_string);
break;
}
else
{
matches[mode - 2] = to_int(i, j);
break;
}
default:
jm_assert(mode >= 2);
// set the relevent int value:
matches[mode - 2] = to_int(i, j);
}
++mode;
return true;
}
void parse_input_line(const string_type& s)
{
// set matches back to starting values:
for(int i = 0; i < MAX_MATCHES; ++i)
{
matches[i] = -2;
}
parse_function op;
do_test = false;
regex_grep(op, s.begin(), s.end(), parse_expression);
jm_trace("expression: " << make_narrow(expression).c_str());
jm_trace("search string: " << make_narrow(search_text).c_str());
}
int to_int(string_type::const_iterator i, string_type::const_iterator j)
{
int val = 0;
bool neg = false;
if((i != j) && (*i == BOOST_RE_STR('-')))
{
neg = true;
++i;
}
while (i != j)
{
val *= 10;
val += *i - BOOST_RE_STR('0');
++i;
}
if(neg)
val *= -1;
return val;
}
void expand_escapes(string_type& s)
{
for(unsigned int i = 0; i < s.size(); ++i)
{
if(s[i] == BOOST_RE_STR('\\'))
{
switch(s[i+1])
{
case BOOST_RE_STR('a'):
s.erase(s.begin() + i);
s[i] = BOOST_RE_STR('\a');
break;
case BOOST_RE_STR('b'):
s.erase(s.begin() + i);
s[i] = BOOST_RE_STR('\b');
break;
case BOOST_RE_STR('f'):
s.erase(s.begin() + i);
s[i] = BOOST_RE_STR('\f');
break;
case BOOST_RE_STR('n'):
s.erase(s.begin() + i);
s[i] = BOOST_RE_STR('\n');
break;
case BOOST_RE_STR('r'):
s.erase(s.begin() + i);
s[i] = BOOST_RE_STR('\r');
break;
case BOOST_RE_STR('t'):
s.erase(s.begin() + i);
s[i] = BOOST_RE_STR('\t');
break;
case BOOST_RE_STR('v'):
s.erase(s.begin() + i);
s[i] = BOOST_RE_STR('\v');
break;
default:
if( (s[i + 1] >= BOOST_RE_STR('0')) && (s[i + 1] <= BOOST_RE_STR('9')) )
{
int val = 0;
unsigned int pos = i;
++i;
while((i < s.size()) && (s[i] >= BOOST_RE_STR('0')) && (s[i] <= BOOST_RE_STR('9')))
{
val *= 10;
val += s[i] - BOOST_RE_STR('0');
++i;
}
s.erase(s.begin() + pos, s.begin() + i);
if(0 == val)
{
s.insert(s.begin()+pos, ' ');
s[pos] = 0;
}
else
s.insert(s.begin() + pos, (string_type::value_type)val);
i = pos;
}
else
{
s.erase(s.begin() + i);
}
}
}
}
}
#endif
-194
View File
@@ -1,194 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* Dr 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 regex_test.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Builds regression test program with default
* locale and narrow character tests. Also
* instantiates all the templates in the library
* as a sanity check.
*/
// disable automatic selection of support library:
#define BOOST_REGEX_NO_LIB
#define BOOST_REGEX_STATIC_LINK
#define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#include <boost/regex.hpp>
#include <boost/regex/src.cpp>
#ifdef BOOST_MSVC
# pragma warning(disable: 4660)
#endif
//
// instantiate templates used:
//
namespace boost{
#if defined(__GNUC__) && defined(__BEOS__)
#define ra_it const char*
#define test_char_type char
#else
typedef const char* ra_it;
typedef char test_char_type;
#endif
typedef std::basic_string<test_char_type> test_string_type;
bool pred1(const match_results<ra_it>&)
{ return true; }
typedef bool (*pred1_type)(const match_results<ra_it>&);
typedef bool (*pred2_type)(const match_results<test_string_type::const_iterator>&);
//check that all the defined flags are available:
regex::flag_type f = regex::escape_in_lists | regex::char_classes | regex::intervals | regex::limited_ops
| regex::newline_alt | regex::bk_plus_qm | regex::bk_braces
| regex::bk_parens | regex::bk_refs | regex::bk_vbar | regex::use_except
| regex::failbit | regex::literal | regex::icase | regex::nocollate | regex::basic
| regex::extended | regex::normal | regex::emacs | regex::awk | regex::grep | regex::egrep | regex::sed;
template class reg_expression<test_char_type>;
template struct sub_match<ra_it>;
template class match_results<ra_it>;
#if 0
template bool regex_match(ra_it,
ra_it,
match_results<ra_it>& m,
const reg_expression<test_char_type>& e,
unsigned flags);
template bool regex_match(ra_it,
ra_it,
const reg_expression<test_char_type>& e,
unsigned flags);
template bool regex_search(ra_it,
ra_it,
match_results<ra_it>& m,
const reg_expression<test_char_type>& e,
unsigned flags);
template unsigned int regex_grep(pred1_type,
ra_it,
ra_it,
const reg_expression<test_char_type>& e,
unsigned flags);
template test_char_type* regex_format(test_char_type*,
const match_results<ra_it>& m,
const test_char_type* fmt,
unsigned flags);
template test_char_type* regex_format(test_char_type*,
const match_results<ra_it>& m,
const test_string_type& fmt,
unsigned flags);
template test_char_type* regex_replace(test_char_type*,
ra_it,
ra_it,
const reg_expression<test_char_type>&,
const test_char_type*,
unsigned int flags);
template test_char_type* regex_replace(test_char_type*,
ra_it,
ra_it,
const reg_expression<test_char_type>& e,
const test_string_type&,
unsigned int flags);
template std::size_t regex_split(test_string_type*,
test_string_type&,
const reg_expression<test_char_type>&,
unsigned flags,
std::size_t);
template std::size_t regex_split(test_string_type*,
test_string_type& s,
const reg_expression<test_char_type>& e,
unsigned flags);
template std::size_t regex_split(test_string_type*, test_string_type&);
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
//
// the following prototypes are only available if partial ordering
// of template functions is supported:
//
template bool regex_match(const test_char_type*,
match_results<const test_char_type*>& m,
const reg_expression<test_char_type>& e,
unsigned flags);
template bool regex_match(const test_string_type&,
match_results<test_string_type::const_iterator>&,
const reg_expression<test_char_type>&,
unsigned flags);
template bool regex_match(const test_char_type*,
const reg_expression<test_char_type>&,
unsigned flags);
template bool regex_match(const test_string_type&,
const reg_expression<test_char_type>&,
unsigned flags);
template bool regex_search(const test_char_type*,
match_results<const test_char_type*>&,
const reg_expression<test_char_type>&,
unsigned flags);
template bool regex_search(const test_string_type&,
match_results<test_string_type::const_iterator>&,
const reg_expression<test_char_type>&,
unsigned flags);
template unsigned int regex_grep(pred1_type,
const test_char_type*,
const reg_expression<test_char_type>&,
unsigned flags);
template unsigned int regex_grep(pred2_type,
const test_string_type&,
const reg_expression<test_char_type>&,
unsigned flags);
template test_string_type regex_format
(const match_results<test_string_type::const_iterator>& m,
const test_char_type*,
unsigned flags);
template test_string_type regex_format
(const match_results<test_string_type::const_iterator>&,
const test_string_type&,
unsigned flags);
template test_string_type regex_replace(const test_string_type&,
const reg_expression<test_char_type>&,
const test_char_type*,
unsigned int flags);
template test_string_type regex_replace(const test_string_type&,
const reg_expression<test_char_type>&,
const test_string_type&,
unsigned int flags);
#endif
#endif
} // namespace boost
//
// include regression test source files:
//
#ifdef BOOST_REGEX_USE_WIN32_LOCALE
#define BOOST_RE_TEST_LOCALE_W32
#elif !defined(BOOST_REGEX_USE_C_LOCALE)
#define BOOST_RE_TEST_LOCALE_CPP
#endif
#include "tests.cpp"
#include "parse.cpp"
#include "regress.cpp"
//
// Como goes into an infinite loop trying to link this,
// just have it fail for now:
//
#if defined(__COMO__) && defined(_MSC_VER)
#error "Comeau in VC6 mode goes into an infinite loop trying to link this program!!!"
#endif
-306
View File
@@ -1,306 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* Dr 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)
*
*/
/*
*
* FILE regress.cpp
* VERSION see <boost/version.hpp>
*
* main() and associated code for regress.
*
*/
#include <cstdlib>
#include <boost/regex.hpp>
#ifdef BOOST_RE_OLD_IOSTREAM
#include <fstream.h>
#else
#include <fstream>
using std::ifstream;
using std::ofstream;
//using std::cin;
//using std::cout;
using std::endl;
#endif
#ifdef __BORLANDC__
#pragma hrdstop
#endif
#include <boost/test/execution_monitor.hpp>
#include "regress.h"
#ifndef BOOST_REGEX_NO_TEST
#if defined(BOOST_MSVC) && defined(_DEBUG)
#include <CRTDBG.H>
#endif
#ifdef TIME_TEST
#include <boost/timer.hpp>
#endif
//
// declare all our globals here:
//
string_type expression;
string_type search_text;
string_type format_string;
string_type merge_string;
int matches[MAX_MATCHES];
char file[MAX_PATH];
int line;
bool do_test = false;
unsigned int flags[5];
unsigned error_count = 0;
void usage()
{
cout <<
"Usage: regress filename [filename2...]\n"
"see tests.txt for an example test script\n"
"and the script format.\n";
}
int cpp_main(int argc, char * argv[])
{
#if defined(BOOST_MSVC) && defined(_DEBUG)
// turn on heap reporting at program exit:
//int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
//tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
//tmpFlag &= ~_CRTDBG_CHECK_CRT_DF;
//_CrtSetDbgFlag( tmpFlag );
#endif
#ifdef TIME_TEST
boost::timer tim;
#endif
if(argc < 2)
usage();
int i;
for(i = 1; i < argc; ++i)
{
reset_error();
ifstream is(argv[i]);
if(is.good() == false)
{
cout << "Error unable to open file: " << argv[i] << endl << endl;
return -1;
}
std::strcpy(file, argv[i]);
line = 0;
unsigned int tests = 0;
while(is.good())
{
string_type s;
get_line(is, s);
++line;
jm_trace("Reading test script line " << line << " " << make_narrow(s).c_str());
parse_input_line(s);
if(do_test)
{
run_tests();
++tests;
}
}
cout << line << " lines, " << tests << " tests completed in file " << argv[i] << endl;
}
#ifdef TIME_TEST
double elapsed_time = tim.elapsed();
cout << "Elapsed time = " << elapsed_time << "s" << endl;
#endif
return error_count;
}
#ifdef TEST_UNICODE
std::string make_narrow(const wchar_t* ptr)
{
std::string result;
while(*ptr)
{
if(*ptr & ~0x7F)
{
char buf[10];
std::sprintf(buf, "\\x%.4x", (int)*ptr);
result.append(buf);
++ptr;
}
else
{
result.append(1, (char)*ptr);
++ptr;
}
}
return result;
}
istream& get_line(istream& is, nstring_type& s, char delim)
{
char c = (char)is.get();
s.erase(s.begin(), s.end());
while((c != delim) && is.good())
{
s.append(1, c);
c = (char)is.get();
}
return is;
}
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{ using ::mbtowc; }
#endif
istream& get_line(istream& is, string_type& s, char delim)
{
nstring_type t;
get_line(is, t, delim);
s.erase(s.begin(), s.end());
const char* i, *j;
i = t.c_str();
j = t.c_str() + t.size();
wchar_t* buf = new wchar_t[MB_CUR_MAX + 1];
int cchars;
while(i != j)
{
cchars = std::mbtowc(buf, i, j - i);
if(cchars == -1)
break;
if(cchars == 0)
break;
s.insert(s.end(), buf, buf + cchars);
i += cchars;
}
delete[] buf;
return is;
}
#else
istream& get_line(istream& is, string_type& s, char delim)
{
char c = (char)is.get();
s.erase(s.begin(), s.end());
while((c != delim) && is.good())
{
s.append(1, c);
c = (char)is.get();
}
return is;
}
#endif
jm_debug_alloc::jm_debug_alloc()
{
blocks = new int;
count = new int;
*blocks = 0;
*count = 1;
guard = this;
}
jm_debug_alloc::jm_debug_alloc(const jm_debug_alloc& d)
{
if(&d != this)
{
blocks = d.blocks;
count = d.count;
++(*count);
guard = this;
}
}
jm_debug_alloc& jm_debug_alloc::operator=(const jm_debug_alloc& d)
{
if(&d != this)
{
free_();
blocks = d.blocks;
count = d.count;
++(*count);
}
return *this;
}
jm_debug_alloc::~jm_debug_alloc()
{
if(guard != this)
{
cout << "Error: attempt to destroy object already destroyed" << endl;
}
else
{
free_();
guard = 0;
}
}
void jm_debug_alloc::free_()
{
if(--(*count) == 0)
{
if(*blocks)
{
begin_error();
cout << "Error: " << *blocks << " blocks not freed by allocator" << endl;
}
delete count;
delete blocks;
}
}
void* jm_debug_alloc::allocate(size_type n, void*)
{
pointer p = new char[n + maxi(sizeof(size_type), boost::re_detail::padding_size)];
*(size_type*)p = n;
++(*blocks);
return p + maxi(sizeof(size_type), boost::re_detail::padding_size);
}
void jm_debug_alloc::deallocate(void* pv, size_type n)
{
char* p = (char*)pv;
p -= maxi(sizeof(size_type), boost::re_detail::padding_size);
if(*(size_type*)p != n)
{
begin_error();
cout << "Error: size mismatch in allocate/deallocate calls" << endl;
}
--(*blocks);
delete[] p;
}
#else
#include <iostream>
int cpp_main(int argc, char * argv[])
{
std::cout <<
"\n<note>\n"
#if defined(BOOST_NO_WREGEX) && defined(TEST_UNICODE)
"This platform does not provide the needed wide character support for this test.\n"
#elif defined(BOOST_REGEX_DYN_LINK)
"Dynamic linking with this compiler is known not to work in this case - please complain to your compiler vendor.\n"
#else
"This test has been disabled due to a compiler bug - please complain to your compiler vendor.\n"
#endif
"</note>\n";
return 0;
}
#endif
+7 -3
View File
@@ -429,15 +429,19 @@ __iterator_category(const debug_iterator<T>&) {
#define BOOST_RE_TEST_LOCALE_W32
#endif
// TODO:
#define BOOST_RE_TEST_LOCALE_CPP
#undef BOOST_RE_TEST_LOCALE_W32
#ifdef BOOST_REGEX_V3
# define basic_regex reg_expression
#endif
#ifdef BOOST_RE_TEST_LOCALE_W32
typedef boost::basic_regex<char_t, boost::w32_regex_traits<char_t>, jm_debug_alloc> re_type;
typedef boost::basic_regex<char_t, boost::w32_regex_traits<char_t> > re_type;
#elif defined(BOOST_RE_TEST_LOCALE_CPP)
typedef boost::basic_regex<char_t, boost::cpp_regex_traits<char_t>, jm_debug_alloc> re_type;
typedef boost::basic_regex<char_t, boost::cpp_regex_traits<char_t> > re_type;
#else
typedef boost::basic_regex<char_t, boost::c_regex_traits<char_t>, jm_debug_alloc> re_type;
typedef boost::basic_regex<char_t, boost::c_regex_traits<char_t> > re_type;
#endif
#define REG_NO_POSIX_TEST 1
#define REG_UNICODE_ONLY 2
+90
View File
@@ -0,0 +1,90 @@
#ifndef BOOST_REGEX_REGRESS_TEST_HPP
#define BOOST_REGEX_REGRESS_TEST_HPP
#include "test_not_regex.hpp"
#include "test_regex_search.hpp"
//
// define test entry proc, this forwards on to the appropriate
// real test:
//
template <class charT, class tagT>
void test(charT, const tagT& tag)
{
boost::basic_regex<charT> e;
test(e, tag);
}
//
// define function to pack args into an array:
//
const int* make_array(int first, ...);
//
// define macros for testing invalid regexes:
//
#define TEST_INVALID_REGEX_N(s, f)\
do{\
const char e[] = { s };\
std::string se(e, sizeof(e) - 1);\
test_info<char>::set_info(__FILE__, __LINE__, se, f);\
test(char(0), test_invalid_regex_tag());\
}while(0)
#ifndef BOOST_NO_WREGEX
#define TEST_INVALID_REGEX_W(s, f)\
do{\
const wchar_t e[] = { s };\
std::wstring se(e, (sizeof(e) / sizeof(wchar_t)) - 1);\
test_info<wchar_t>::set_info(__FILE__, __LINE__, se, f);\
test(wchar_t(0), test_invalid_regex_tag());\
}while(0)
#else
#define TEST_INVALID_REGEX_W(s, f)
#endif
#define TEST_INVALID_REGEX(s, f)\
TEST_INVALID_REGEX_N(s, f);\
TEST_INVALID_REGEX_W(BOOST_JOIN(L, s), f)
//
// define macros for testing regex searches:
//
#define TEST_REGEX_SEARCH_N(s, f, t, m, a)\
do{\
const char e[] = { s };\
std::string se(e, sizeof(e) - 1);\
const char st[] = { t };\
std::string sst(st, sizeof(st) - 1);\
test_info<char>::set_info(__FILE__, __LINE__, se, f, sst, m, a);\
test(char(0), test_regex_search_tag());\
}while(0)
#ifndef BOOST_NO_WREGEX
#define TEST_REGEX_SEARCH_W(s, f, t, m, a)\
do{\
const wchar_t e[] = { s };\
std::wstring se(e, (sizeof(e) / sizeof(wchar_t)) - 1);\
const wchar_t st[] = { t };\
std::wstring sst(st, (sizeof(st) / sizeof(wchar_t)) - 1);\
test_info<wchar_t>::set_info(__FILE__, __LINE__, se, f, sst, m, a);\
test(wchar_t(0), test_regex_search_tag());\
}while(0)
#else
#define TEST_REGEX_SEARCH_W(s, f, t, m, a)
#endif
#define TEST_REGEX_SEARCH(s, f, t, m, a)\
TEST_REGEX_SEARCH_N(s, f, t, m, a);\
TEST_REGEX_SEARCH_W(BOOST_JOIN(L, s), f, BOOST_JOIN(L, t), m, a)
//
// define the test group proceedures:
//
void basic_tests();
#endif
+49
View File
@@ -0,0 +1,49 @@
#ifndef BOOST_REGEX_REGRESS_TEST_NOT_REGEX_HPP
#define BOOST_REGEX_REGRESS_TEST_NOT_REGEX_HPP
#include "info.hpp"
//
// this file implements a test for a regular expression that should not compile:
//
struct test_invalid_regex_tag{};
template<class charT, class traits>
void test(boost::basic_regex<charT, traits>& r, const test_invalid_regex_tag&)
{
const std::basic_string<charT>& expression = test_info<charT>::expression();
boost::regex_constants::syntax_option_type syntax_options = test_info<charT>::syntax_options();
bool have_catch = false;
try{
r.assign(expression, syntax_options);
}
catch(const boost::bad_expression&)
{
have_catch = true;
}
catch(const std::runtime_error& r)
{
have_catch = true;
BOOST_REGEX_TEST_ERROR("Expected a bad_expression exception, but a std::runtime_error instead: " << r.what(), charT);
}
catch(const std::exception& r)
{
have_catch = true;
BOOST_REGEX_TEST_ERROR("Expected a bad_expression exception, but a std::exception instead: " << r.what(), charT);
}
catch(...)
{
have_catch = true;
BOOST_REGEX_TEST_ERROR("Expected a bad_expression exception, but got an exception of unknown type instead", charT);
}
if(!have_catch)
{
// oops expected exception was not thrown:
BOOST_REGEX_TEST_ERROR("Expected an exception, but didn't find one.", charT);
}
}
#endif
+105
View File
@@ -0,0 +1,105 @@
#ifndef BOOST_REGEX_REGRESS_REGEX_SEARCH_HPP
#define BOOST_REGEX_REGRESS_REGEX_SEARCH_HPP
#include "info.hpp"
//
// this file implements a test for a regular expression that should compile,
// followed by a search for that expression:
//
struct test_regex_search_tag{};
template <class BidirectionalIterator>
void test_sub_match(const boost::sub_match<BidirectionalIterator>& sub, BidirectionalIterator base, const int* answer_table, int i)
{
typedef typename boost::sub_match<BidirectionalIterator>::value_type charT;
if(sub.matched == 0)
{
if(answer_table[2*i] >= 0)
{
BOOST_REGEX_TEST_ERROR(
"Sub-expression " << i
<< " was not matched when it should have been.", charT);
}
}
else
{
if(std::distance(base, sub.first) != answer_table[2*i])
{
BOOST_REGEX_TEST_ERROR(
"Error in start location of sub-expression "
<< i << ", found " << std::distance(base, sub.first)
<< ", expected " << answer_table[2*i] << ".", charT);
}
if(std::distance(base, sub.second) != answer_table[1+ 2*i])
{
BOOST_REGEX_TEST_ERROR(
"Error in end location of sub-expression "
<< i << ", found " << std::distance(base, sub.second)
<< ", expected " << answer_table[1 + 2*i] << ".", charT);
}
}
}
template <class BidirectionalIterator, class Allocator>
void test_result(const boost::match_results<BidirectionalIterator, Allocator>& what, BidirectionalIterator base, const int* answer_table)
{
for(unsigned i = 0; i < what.size(); ++i)
{
test_sub_match(what[i], base, answer_table, i);
}
}
template<class charT, class traits>
void test_simple_search(boost::basic_regex<charT, traits>& r)
{
const std::basic_string<charT>& search_text = test_info<charT>::search_text();
boost::regex_constants::match_flag_type opts = test_info<charT>::match_options();
const int* answer_table = test_info<charT>::answer_table();
boost::match_results<typename std::basic_string<charT>::const_iterator> what;
if(boost::regex_search(
search_text.begin(),
search_text.end(),
what,
r,
opts))
{
test_result(what, search_text.begin(), answer_table);
}
else if(answer_table[0] >= 0)
{
// we should have had a match but didn't:
BOOST_REGEX_TEST_ERROR("Expected match was not found.", charT);
}
}
template<class charT, class traits>
void test(boost::basic_regex<charT, traits>& r, const test_regex_search_tag&)
{
const std::basic_string<charT>& expression = test_info<charT>::expression();
boost::regex_constants::syntax_option_type syntax_options = test_info<charT>::syntax_options();
try{
r.assign(expression, syntax_options);
test_simple_search(r);
}
catch(const boost::bad_expression& e)
{
BOOST_REGEX_TEST_ERROR("Expression did not compile when it should have done: " << e.what(), charT);
}
catch(const std::runtime_error& r)
{
BOOST_REGEX_TEST_ERROR("Received an unexpected std::runtime_error: " << r.what(), charT);
}
catch(const std::exception& r)
{
BOOST_REGEX_TEST_ERROR("Received an unexpected std::exception: " << r.what(), charT);
}
catch(...)
{
BOOST_REGEX_TEST_ERROR("Received an unexpected exception of unknown type", charT);
}
}
#endif
-963
View File
@@ -1,963 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* Dr 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)
*
*/
/*
*
* FILE tests.cpp
* VERSION see <boost/version.hpp>
*
* the actual tests conducted by regress.
*
*/
#include <cassert>
#include <boost/regex.hpp>
#include "regress.h"
#ifndef BOOST_REGEX_NO_TEST
# ifdef BOOST_MSVC
# pragma warning(disable: 4244 4267)
#endif
using namespace boost;
template <class M1, class M2>
bool compare_result(const M1& sm, const M2& m)
{
if(sm.size() != m.size())
return false;
#ifdef BOOST_REGEX_V3
if(sm.line() != m.line())
return false;
#endif
for(unsigned int i = 0; i < sm.size(); ++i)
{
if(sm.position(i) != m.position(i))
return false;
if(sm.length(i) != m.length(i))
return false;
}
return true;
}
template <class M1>
bool compare_result(const M1& sm, const M1& m)
{
return sm == m;
}
template <class C, class T, class A>
void cpp_eh_tests(const basic_regex<C, T, A>& )
{
#ifndef __GNUC__
bool thrown = false;
// try set_expression form first:
#ifndef BOOST_NO_EXCEPTIONS
try
{
#endif
A a;
basic_regex<C, T, A> e(a);
e.set_expression(expression.c_str(), flags[2] | regex::use_except);
#ifndef BOOST_NO_EXCEPTIONS
}
catch(const boost::bad_expression&)
{
thrown = true;
}
catch(...){}
if(!thrown)
{
begin_error();
cout << "Error: expected exception not thrown" << endl;
}
#endif
// now try constructor form:
thrown = false;
#ifndef BOOST_NO_EXCEPTIONS
try
#endif
{
A a;
basic_regex<C, T, A> e(expression.c_str(), flags[2] | regex::use_except, a);
}
#ifndef BOOST_NO_EXCEPTIONS
catch(const boost::bad_expression&)
{
thrown = true;
}
catch(...){}
if(!thrown)
{
begin_error();
cout << "Error: expected exception not thrown" << endl;
}
#endif
#endif
}
template <class iterator>
iterator find_last_line(iterator start, iterator end)
{
iterator result = start;
while(start != end)
{
if(*start == '\n')
{
++start;
result = start;
}
else
++start;
}
return result;
}
template <class iterator>
unsigned int count_lines(iterator start, iterator end)
{
unsigned int result = 0;
while(start != end)
{
if(*start == '\n')
++result;
++start;
}
return result;
}
template <class iterator, class Alloc>
class grep_test_predicate
{
int match_id;
iterator base, term;
// rebind allocator to correct type:
#ifdef BOOST_REGEX_V3
typedef Alloc alloc_type;
#else
typedef typename detail::rebind_allocator<boost::sub_match<iterator>, Alloc>::type alloc_type;
#endif
public:
grep_test_predicate(iterator i, iterator j) : base(i), term(j) { match_id = 0; }
~grep_test_predicate(){}
bool operator()(const boost::match_results< iterator, alloc_type >& m);
};
template <class iterator, class Alloc>
bool grep_test_predicate<iterator, Alloc>::operator()(const boost::match_results< iterator, alloc_type >& m)
{
std::ptrdiff_t start, end;
start = m[0].first - base;
end = m[0].second - base;
if((matches[match_id] != start) || (matches[match_id + 1] != end))
{
begin_error();
cout << "regex++ grep match error: found [" << start << "," << end << "] expected [" << matches[match_id] << "," << matches[match_id+1] << "]" << endl;
}
//
// check $`:
start = m[-1].first - base;
end = m[-1].second - base;
if(match_id &&
( (end != matches[match_id]) || (start != matches[match_id - 1]) )
)
{
begin_error();
cout << "regex++ grep error in $`: found [" << start << "," << end << "] expected [" << matches[match_id-1] << "," << matches[match_id] << "]" << endl;
}
else if((!match_id) && ((start != 0) || (end != matches[0])))
{
begin_error();
cout << "regex++ grep error in $`: found [" << start << "," << end << "] expected [" << 0 << "," << matches[0] << "]" << endl;
}
//
// check $':
start = m[-2].first - base;
end = m[-2].second - base;
if((start != matches[match_id + 1]) || (end != (term-base)))
{
begin_error();
cout << "regex++ grep error in $': found [" << start << "," << end << "] expected [" << matches[match_id + 1] << "," << (term-base) << "]" << endl;
}
//
// now check line()
/* don't check this, it's not supported in the new algorithm....
start = m.line();
end = count_lines(base, iterator(m[0].first)) + 1;
if(start != end)
{
begin_error();
cout << "regex++ grep error in line(): found " << start << " expected " << end << endl;
}
*/
//
// now check line_start()
/* don't check this, it's not supported in the new algorithm....
start = m.line_start() - base;
end = find_last_line(base, iterator(m[0].first)) - base;
if(start != end)
{
begin_error();
cout << "regex++ grep error in line_start(): found " << start << " expected " << end << endl;
}
*/
match_id += 2;
return true;
}
template <class C, class T, class A>
void cpp_tests(const basic_regex<C, T, A>& e, bool recurse = true)
{
typedef typename basic_regex<C, T, A>::allocator_type base_allocator_type;
#ifdef BOOST_REGEX_V3
typedef base_allocator_type allocator_type;
#else
typedef typename detail::rebind_allocator<boost::sub_match<debug_iterator<string_type::iterator> >, base_allocator_type>::type allocator_type;
#endif
if(flags[4] & REG_MERGE)
{
//
// test merge code:
//
string_type s;
s = regex_merge(search_text, e, format_string.c_str(), static_cast<boost::match_flag_type>(flags[3]));
if(s != merge_string)
{
begin_error();
cout << "merge result mismatch: found \"" << make_narrow(s).c_str() << "\" expected \"" << make_narrow(merge_string.c_str()) << "\"" << endl;
}
return;
}
if(recurse)
{
// copy and assign test:
basic_regex<C, T, A> e2(e);
cpp_tests(e2, false);
e2 = e;
cpp_tests(e2, false);
basic_regex<C, T, A> e3;
#ifndef BOOST_REGEX_V3
e3.swap(e2);
cpp_tests(e3, false);
#endif
}
if(e.error_code())
{
// verify that we don't expect expression to compile
if(search_text != BOOST_RE_STR("!"))
{
begin_error();
cout << "Expression did not compile using regex++ API" << endl;
}
else if((recurse) && ((flags[3] & match_partial) == 0))
cpp_eh_tests(e);
}
else if(flags[4] & REG_GREP)
{
// try to do grep:
debug_iterator<string_type::iterator> x(search_text.begin(), search_text.begin(), search_text.end());
debug_iterator<string_type::iterator> y(search_text.end(), search_text.begin(), search_text.end());
grep_test_predicate<debug_iterator<string_type::iterator>, allocator_type> oi(x, y);
regex_grep(oi, x, y, e, static_cast<boost::match_flag_type>(flags[3]));
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
if(!recurse)
{
unsigned len = search_text.size();
const std::basic_string<char_t>& s = search_text;
grep_test_predicate<std::basic_string<char_t>::const_iterator, base_allocator_type> oi2(s.begin(), s.end());
regex_grep(oi2, s, e, static_cast<boost::match_flag_type>(flags[3]));
grep_test_predicate<const char_t*, base_allocator_type> oi3(s.c_str(), s.c_str()+s.size());
regex_grep(oi3, s.c_str(), e, static_cast<boost::match_flag_type>(flags[3]));
assert(s.size() == len);
assert(s.end() - s.begin() == (std::basic_string<char_t>::difference_type)len);
}
#endif
}
else
{
// try to find match
match_results< debug_iterator<string_type::iterator>, allocator_type> m;
debug_iterator<string_type::iterator> x(search_text.begin(), search_text.begin(), search_text.end());
debug_iterator<string_type::iterator> y(search_text.end(), search_text.begin(), search_text.end());
if(regex_search(x, y, m, e, static_cast<boost::match_flag_type>(flags[3])))
{
// special case for partial matches:
if(flags[4] & REG_PARTIAL_MATCH)
{
if(m[0].matched)
{
begin_error();
cout << "regex++ API result mismatch, found full match when partial match was expected: found ("
<< (m[0].first - x) << "," <<
(m[0].second - x) << ")" << endl;
}
else if(((m[0].first - x) != matches[0]) || ((m[0].second - x) != matches[1]))
{
begin_error();
cout << "regex++ API result mismatch in sub-expression " << 0 <<
", found (" << (m[0].first - x) << "," <<
(m[0].second - x) << ") expected (" <<
matches[0] << "," << matches[1] << ")" << endl;
}
return; // don't bother testing anything else for partial matches
}
// match found compare what matched with what we expect:
int j = 0;
for(unsigned int i = 0; i < m.size(); ++i, j += 2)
{
if(m[i].matched == false)
{
if(matches[j] != -1)
{
begin_error();
cout << "regex++ API result mismatch in sub-expression " << i <<
", found (" << (m[i].first - x) << "," <<
(m[i].second - x) << ") expected (" <<
matches[j] << "," << matches[j+1] << ")" << endl;
}
}
else if(((m[i].first - x) != matches[j]) || ((m[i].second - x) != matches[j+1]))
{
begin_error();
cout << "regex++ API result mismatch in sub-expression " << i <<
", found (" << (m[i].first - x) << "," <<
(m[i].second - x) << ") expected (" <<
matches[j] << "," << matches[j+1] << ")" << endl;
}
}
//
// now check $` and $':
//
if((m[-1].first != x) || (m[-1].second != m[0].first))
{
begin_error();
cout << "regex++ API result mismatch in $` (match -1), found (" <<
(m[-1].first - x) << "," << (m[-1].second - x) << ") expected (0" <<
"," << matches[0] << ")" << endl;
}
if(((flags[3] & match_partial) == 0) && ((m[-2].first != m[0].second) || (m[-2].second != y)))
{
begin_error();
cout << "regex++ API result mismatch in $' (match -2), found (" <<
(m[-2].first - x) << "," << (m[-2].second - x) << ") expected (" <<
matches[1] << "," << (y-x) << ")" << endl;
}
#if !(defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)) && !defined(BOOST_REGEX_V3)
//
// now try comparison operators:
string_type s(m[0]);
if((s != m[0]) || (m[0] != s)
|| !(s == m[0]) || !(m[0] == s)
|| (s < m[0]) || (m[0] < s)
|| (s > m[0]) || (m[0] > s)
|| !(s <= m[0]) || !(m[0] <= s)
|| !(s >= m[0]) || !(m[0] >= s))
{
begin_error();
cout << "string comparison failed for result" << std::endl;
}
if(s.find_first_of((string_type::value_type)0) == string_type::npos)
{
if((m[0] != s.c_str()) || (s.c_str() != m[0])
|| !(m[0] == s.c_str()) || !(s.c_str() == m[0])
|| (m[0] > s.c_str()) || (s.c_str() > m[0])
|| (m[0] < s.c_str()) || (s.c_str() < m[0])
|| !(m[0] >= s.c_str()) || !(s.c_str() >= m[0])
|| !(m[0] <= s.c_str()) || !(s.c_str() <= m[0]))
{
begin_error();
cout << "string comparison failed for result" << std::endl;
}
}
//
// now try addition operators:
string_type sa(1, (string_type::value_type)'a');
if(
((m[0] + sa) != (s + sa))
|| (sa + m[0]) != (sa + s)
|| ((m[0] + m[0]) != (s + s))
|| ((m[0] + m[0]) != (s + s))
|| ((m[0] + sa[0]) != (s + sa[0]))
|| ((sa[0] + m[0]) != (sa[0] + s))
)
{
begin_error();
cout << "string addition failed for result" << std::endl;
}
if(s.find_first_of((string_type::value_type)0) == string_type::npos)
{
if(
((m[0] + sa.c_str()) != (s + sa))
|| ((sa.c_str() + m[0]) != (sa + s))
)
{
begin_error();
cout << "string addition failed for result" << std::endl;
}
}
#endif
//
// now try alternative forms of regex_search if available:
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
if(!recurse)
{
std::basic_string<char_t> s2(search_text.begin(), search_text.end());
match_results<std::basic_string<char_t>::const_iterator> sm;
if(regex_search(s2, sm, e, static_cast<boost::match_flag_type>(flags[3])))
{
if(compare_result(sm, m) == false)
{
begin_error();
cout << "regex++ API result mismatch in regex_search(const std::string&, match_results&, const basic_regex&, int)" << endl;
}
}
else
{
begin_error();
cout << "regex++ API result mismatch in regex_search(const std::string&, match_results&, const basic_regex&, int)" << endl;
}
#ifndef BOOST_REGEX_V3
if(!regex_search(s2, e, static_cast<boost::match_flag_type>(flags[3]))
|| !regex_search(s2.begin(), s2.end(), e, static_cast<boost::match_flag_type>(flags[3])))
{
begin_error();
cout << "regex++ API result mismatch in regex_search(const std::string&, const basic_regex&, int)" << endl;
}
#endif
//
// partial match should give same result as full match
// provided a full match is expected:
//
if(matches[0] > 0)
{
if(regex_search(x, y, m, e, static_cast<boost::match_flag_type>(flags[3]) | boost::match_partial))
{
if(compare_result(sm, m) == false)
{
begin_error();
cout << "regex++ API result mismatch in regex_search when enabling match_partial" << endl;
}
}
else
{
begin_error();
cout << "regex++ API result: match not found when match_partial specified" << endl;
}
}
if(s2.find(char_t(0)) == std::basic_string<char_t>::npos)
{
match_results<const char_t*> ssm;
if(regex_search(search_text.c_str(), ssm, e, static_cast<boost::match_flag_type>(flags[3])))
{
if(compare_result(ssm, m) == false)
{
begin_error();
cout << "regex++ API result mismatch in regex_search(const char_t*, match_results&, const basic_regex&, int)" << endl;
}
}
else
{
begin_error();
cout << "regex++ API result mismatch in regex_search(const char_t*, match_results&, const basic_regex&, int)" << endl;
}
#ifndef BOOST_REGEX_V3
if(!regex_search(search_text.c_str(), e, static_cast<boost::match_flag_type>(flags[3])))
{
begin_error();
cout << "regex++ API result mismatch in regex_search(const char_t*, const basic_regex&, int)" << endl;
}
#endif
}
}
if((false == recurse) && (matches[0] == 0) && (matches[1] == static_cast<int>(search_text.size())))
{
//
// match expected on whole string, so all versions
// of regex_match should also succeed:
//
match_results< debug_iterator<string_type::iterator>, allocator_type> m1;
debug_iterator<string_type::iterator> x1(search_text.begin(), search_text.begin(), search_text.end());
debug_iterator<string_type::iterator> y1(search_text.end(), search_text.begin(), search_text.end());
if(regex_match(x1, y1, m1, e, static_cast<boost::match_flag_type>(flags[3])))
{
if(compare_result(m1, m) == false)
{
begin_error();
cout << "regex++ API result mismatch in regex_match(iterator, iterator, match_results&, const basic_regex&, int)" << endl;
}
}
else
{
begin_error();
cout << "regex++ API result mismatch in regex_match(iterator, iterator, match_results&, const basic_regex&, int)" << endl;
}
std::basic_string<char_t> s3(search_text.begin(), search_text.end());
match_results<std::basic_string<char_t>::const_iterator> sm;
if(regex_match(s3, sm, e, static_cast<boost::match_flag_type>(flags[3])))
{
if(compare_result(sm, m) == false)
{
begin_error();
cout << "regex++ API result mismatch in regex_match(const std::string&, match_results&, const basic_regex&, int)" << endl;
}
}
else
{
begin_error();
cout << "regex++ API result mismatch in regex_match(const std::string&, match_results&, const basic_regex&, int)" << endl;
}
if(s3.find(char_t(0)) == std::basic_string<char_t>::npos)
{
match_results<const char_t*> ssm;
if(regex_match(search_text.c_str(), ssm, e, static_cast<boost::match_flag_type>(flags[3])))
{
if(compare_result(ssm, m) == false)
{
begin_error();
cout << "regex++ API result mismatch in regex_match(const char_t*, match_results&, const basic_regex&, int)" << endl;
}
}
else
{
begin_error();
cout << "regex++ API result mismatch in regex_match(const char_t*, match_results&, const basic_regex&, int)" << endl;
}
}
}
#endif
}
else
{
// match not found
if(matches[0] != -1)
{
begin_error();
cout << "Match expected but not found using regex++ API" << endl;
}
}
}
}
#if !defined(TEST_UNICODE)
unsigned int hl_match_id;
bool
#if (defined(__BORLANDC__) || defined(BOOST_MSVC)) && !defined(BOOST_DISABLE_WIN32)
__cdecl
#endif
hl_grep_test_proc(const RegEx& e)
{
std::ptrdiff_t start, end;
start = e.Position(0);
end = start + e.Length();
if((matches[hl_match_id] != start) || (matches[hl_match_id + 1] != end))
{
begin_error();
cout << "class RegEx grep match error: found [" << start << "," << end << "] expected [" << matches[hl_match_id] << "," << matches[hl_match_id+1] << "]" << endl;
}
if(0 == (flags[4] & REG_GREP))
{
for(unsigned int sub = 1; sub < e.Marks(); ++sub)
{
start = e.Position(sub);
end = start + e.Length(sub);
if((matches[2*sub] != start) || (matches[2*sub + 1] != end))
{
begin_error();
cout << "class RegEx grep match error: found in sub " << sub << " [" << start << "," << end << "] expected [" << matches[2*sub] << "," << matches[2*sub+1] << "]" << endl;
}
}
}
//
// check $`:
start = e.Position(-1);
end = start + e.Length(-1);
if(start == -1)
{
if(hl_match_id &&
( matches[hl_match_id] != matches[hl_match_id - 1] )
)
{
begin_error();
cout << "class RegEx grep error in $`: found [" << start << "," << end << "] expected [" << matches[hl_match_id-1] << "," << matches[hl_match_id] << "]" << endl;
}
else if((!hl_match_id) && (0 != matches[0]))
{
begin_error();
cout << "class RegEx grep error in $`: found [" << start << "," << end << "] expected [" << 0 << "," << matches[0] << "]" << endl;
}
}
else
{
if(hl_match_id &&
( (end != matches[hl_match_id]) || (start != matches[hl_match_id - 1]) )
)
{
begin_error();
cout << "class RegEx grep error in $`: found [" << start << "," << end << "] expected [" << matches[hl_match_id-1] << "," << matches[hl_match_id] << "]" << endl;
}
else if((!hl_match_id) && ((start != 0) || (end != matches[0])))
{
begin_error();
cout << "class RegEx grep error in $`: found [" << start << "," << end << "] expected [" << 0 << "," << matches[0] << "]" << endl;
}
}
//
// check $':
start = e.Position(-2);
end = start + e.Length(-2);
if(start == -1)
{
if(matches[hl_match_id + 1] != (int)search_text.size())
{
begin_error();
cout << "class RegEx grep error in $': found [" << start << "," << end << "] expected [" << matches[hl_match_id + 1] << "," << (search_text.size()) << "]" << endl;
}
}
else if((start != matches[hl_match_id + 1]) || (end != (int)search_text.size()))
{
begin_error();
cout << "class RegEx grep error in $': found [" << start << "," << end << "] expected [" << matches[hl_match_id + 1] << "," << (search_text.size()) << "]" << endl;
}
hl_match_id += 2;
return true;
}
void cpp_hl_tests(RegEx& e, bool recurse = true)
{
if(flags[4] & REG_MERGE)
return;
if(e.error_code())
{
if(search_text != BOOST_RE_STR("!"))
{
begin_error();
cout << "Expression did not compile with class RegEx" << endl;
}
return;
}
if(recurse)
{
// copy and assign test:
RegEx e2(e);
cpp_hl_tests(e2, false);
e2 = e;
cpp_hl_tests(e2, false);
}
if(flags[4] & REG_GREP)
{
// try to do grep:
hl_match_id = 0;
GrepCallback cb = hl_grep_test_proc;
e.Grep(cb, search_text.c_str(), static_cast<boost::match_flag_type>(flags[3]));
}
else
{
if(e.Search(search_text.c_str(), static_cast<boost::match_flag_type>(flags[3])))
{
unsigned int i = 0;
unsigned int j = 0;
while(matches[j] != -2)
{
if( (matches[j] != (int)e.Position(i))
|| ((matches[j] != -1) && ((matches[j+1] - matches[j] != (int)e.Length(i)))) )
{
begin_error();
cout << "RegEx::Search error in subexpression " << i << ": found [" << e.Position(i) << "," << (e.Position(i) + e.Length(i)) << "] expected [" << matches[j] << "," << matches[j+1] << "]" << endl;
}
++i;
j += 2;
}
}
else
{
if(matches[0] != -1)
{
begin_error();
cout << "match expected but not found with RexEx::Search" << endl;
}
}
//
// test RegEx::Match only if we expect to match all of the input:
//
if((matches[0] == 0) && (matches[1] == (int)search_text.size()))
{
if(e.Match(search_text.c_str(), static_cast<boost::match_flag_type>(flags[3])))
{
unsigned int i = 0;
unsigned int j = 0;
while(matches[j] != -2)
{
if( (matches[j] != (int)e.Position(i))
|| ((matches[j] != -1) && ((matches[j+1] - matches[j] != (int)e.Length(i)))) )
{
begin_error();
cout << "RegEx::Match error in subexpression " << i << ": found [" << e.Position(i) << "," << (e.Position(i) + e.Length(i)) << "] expected [" << matches[j] << "," << matches[j+1] << "]" << endl;
}
++i;
j += 2;
}
}
else
{
begin_error();
cout << "Match expected but not found with RegEx::Match" << endl;
}
}
}
}
#endif
template <class iterator>
bool has_nulls(iterator i, iterator j)
{
while(i != j)
{
if(*i == 0)
return true;
++i;
}
return false;
}
#ifdef TEST_UNICODE
#undef regcomp
#undef regerror
#undef regexec
#undef regfree
#undef regex_t
#define regcomp regcompW
#define regerror regerrorW
#define regexec regexecW
#define regfree regfreeW
#define regex_t regex_tW
#endif
void run_tests()
{
#ifndef TEST_UNICODE
if(flags[4] & REG_UNICODE_ONLY)
return;
#endif
#ifndef NO_CPP_TEST
#ifndef BOOST_NO_EXCEPTIONS
try
{
#endif
unsigned int f = flags[2] & ~regex::use_except;
if(flags[0] & REG_ICASE)
f |= regex::icase;
re_type e(expression.c_str(), f);
cpp_tests(e, true);
#ifndef BOOST_NO_EXCEPTIONS
}
catch(const std::exception& e)
{
//
// this is only an error if the expression is expected to be valid:
if(search_text != BOOST_RE_STR("!"))
{
begin_error();
cout << "Unexpected exception thrown from C++ library: " << e.what() << endl;
}
}
catch(...)
{
begin_error();
cout << "Unexpected exception thrown from C++ library" << endl;
}
#endif // BOOST_NO_EXCEPTIONS
#endif
#if !defined(TEST_UNICODE)
#ifndef BOOST_NO_EXCEPTIONS
try
{
#endif
if(((flags[3] & match_partial) == 0) && (flags[2] == regex::normal) && (has_nulls(search_text.begin(), search_text.end()) == false))
{
RegEx e;
e.SetExpression(expression.c_str(), flags[0] & REG_ICASE);
cpp_hl_tests(e, true);
}
#ifndef BOOST_NO_EXCEPTIONS
}
catch(const std::exception& )
{
if(search_text != BOOST_RE_STR("!"))
{
begin_error();
cout << "Expression did not compile with class RegEx" << endl;
}
}
catch(...)
{
begin_error();
cout << "Unexpected exception thrown from RegEx::SetExpression" << endl;
}
#endif // BOOST_NO_EXCEPTIONS
#endif
if(flags[4] & (REG_NO_POSIX_TEST | REG_GREP | REG_MERGE | REG_MERGE_COPY))
return;
regex_t posix_expression;
regmatch_t m[MAX_MATCHES];
if(regcomp(&posix_expression, expression.c_str(), flags[0]) == 0)
{
if(flags[1] & REG_STARTEND)
{
m[0].rm_so = 0;
m[0].rm_eo = search_text.size();
}
if(regexec(&posix_expression, search_text.c_str(), MAX_MATCHES, m, flags[1]))
{
// match not found
if(matches[0] != -1)
{
begin_error();
cout << "Match expected but not found using POSIX API" << endl;
}
}
else
{
// match found compare what matched with what we expect:
int j = 0;
for(unsigned int i = 0; i <= posix_expression.re_nsub; ++i, j += 2)
{
if((m[i].rm_so != matches[j]) || (m[i].rm_eo != matches[j+1]))
{
begin_error();
cout << "POSIX API result mismatch in sub-expression " << i << ", found (" << m[i].rm_so << "," << m[i].rm_eo <<
") expected (" << matches[j] << "," << matches[j+1] << ")" << endl;
}
}
}
regfree(&posix_expression);
}
else
{
// expression did not compile
if(search_text != BOOST_RE_STR("!"))
{
begin_error();
cout << "Expression did not compile using POSIX API" << endl;
}
}
}
//
// error reporting:
int last_line = 0;
void begin_error()
{
if(line != last_line)
{
cout << "Error in line " << line << " of file " << file << endl;
cout << "Expression: " << make_narrow(expression).c_str() << endl;
cout << "Search text: " << make_narrow(search_text).c_str() << endl;
cout << "Flags: ";
bool started = false;
unsigned int id = 0;
while(flag_data[id].len != 0)
{
if(flags[flag_data[id].id] & flag_data[id].value)
{
if(started)
cout << " | ";
cout << make_narrow(flag_data[id].name).c_str();
started = true;
}
++id;
}
cout << endl;
last_line = line;
++error_count;
}
}
void reset_error()
{
last_line = 0;
}
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) && (__BORLANDC__ <= 0x551) && !defined(_RWSTD_COMPILE_INSTANTIATE)
//
// this is an ugly hack to work around an ugly problem:
// by default this file will produce unresolved externals during
// linking unless _RWSTD_COMPILE_INSTANTIATE is defined (Borland bug).
// However if _RWSTD_COMPILE_INSTANTIATE is defined then we get separate
// copies of basic_string's static data in the RTL and this DLL, this messes
// with basic_string's memory management and results in run-time crashes,
// Oh sweet joy of Catch 22....
//
namespace std{
template<> template<>
basic_string<string_type::value_type>&
basic_string<string_type::value_type>
::replace<debug_iterator<string_type::iterator> >(
string_type::iterator f1,
string_type::iterator f2,
debug_iterator<string_type::iterator> i1,
debug_iterator<string_type::iterator> i2)
{
unsigned insert_pos = f1 - begin();
unsigned remove_len = f2 - f1;
unsigned insert_len = i2 - i1;
unsigned org_size = size();
if(insert_len > remove_len)
{
append(insert_len-remove_len, ' ');
std::copy_backward(begin() + insert_pos + remove_len, begin() + org_size, end());
std::copy(i1, i2, begin() + insert_pos);
}
else
{
std::copy(begin() + insert_pos + remove_len, begin() + org_size, begin() + insert_pos + insert_len);
std::copy(i1, i2, begin() + insert_pos);
erase(size() + insert_len - remove_len);
}
return *this;
}
}
#endif
#endif
-201
View File
@@ -1,201 +0,0 @@
/*
*
* Copyright (c) 1998-2002
* Dr 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 regex_test.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Builds regression test program with default
* locale and wide character tests. Also
* instantiates all the templates in the library
* as a sanity check.
*/
// disable automatic selection of support library:
#define BOOST_REGEX_NO_LIB
#define BOOST_REGEX_STATIC_LINK
#define BOOST_REGEX_NO_EXTERNAL_TEMPLATES
#if defined(_MSC_VER) && defined(__STL_DEBUG) && defined(_DLL)
//
// Ugly hack:
// when this file is built with VC6 + STLPort 4 we get unresolved externals
// from std::wstring if __STL_DEBUG is defined. As a workaround disable
// STL debugging support in this case. This weakens the regression tests
// but is still better than not being able to run them at all. This should be
// removed once STLPort gets fixed.
//
#undef __STL_DEBUG
#endif
#include <boost/regex.hpp>
#include <boost/regex/src.cpp>
#ifdef BOOST_NO_WREGEX
#error The regex library is not configured for wide character support
#endif
//
// instantiate templates used:
//
namespace boost{
typedef const wchar_t* ra_it;
typedef wchar_t char_type;
typedef std::basic_string<char_type> test_string_type;
bool pred1(const match_results<ra_it>&)
{ return true; }
typedef bool (*pred1_type)(const match_results<ra_it>&);
typedef bool (*pred2_type)(const match_results<test_string_type::const_iterator>&);
//check that all the defined flags are available:
wregex::flag_type f = wregex::escape_in_lists | wregex::char_classes | wregex::intervals | wregex::limited_ops
| wregex::newline_alt | wregex::bk_plus_qm | wregex::bk_braces
| wregex::bk_parens | wregex::bk_refs | wregex::bk_vbar | wregex::use_except
| wregex::failbit | wregex::literal | wregex::icase | wregex::nocollate | wregex::basic
| wregex::extended | wregex::normal | wregex::emacs | wregex::awk | wregex::grep | wregex::egrep | wregex::sed;
template class reg_expression<char_type>;
template struct sub_match<ra_it>;
template class match_results<ra_it>;
template bool regex_match(ra_it,
ra_it,
match_results<ra_it>& m,
const reg_expression<char_type>& e,
unsigned flags);
template bool regex_match(ra_it,
ra_it,
const reg_expression<char_type>& e,
unsigned flags);
template bool regex_search(ra_it,
ra_it,
match_results<ra_it>& m,
const reg_expression<char_type>& e,
unsigned flags);
template unsigned int regex_grep(pred1_type,
ra_it,
ra_it,
const reg_expression<char_type>& e,
unsigned flags);
template char_type* regex_format(char_type*,
const match_results<ra_it>& m,
const char_type* fmt,
unsigned flags);
template char_type* regex_format(char_type*,
const match_results<ra_it>& m,
const test_string_type& fmt,
unsigned flags);
template char_type* regex_replace(char_type*,
ra_it,
ra_it,
const reg_expression<char_type>&,
const char_type*,
unsigned int flags);
template char_type* regex_replace(char_type*,
ra_it,
ra_it,
const reg_expression<char_type>& e,
const test_string_type&,
unsigned int flags);
template std::size_t regex_split(test_string_type*,
test_string_type&,
const reg_expression<char_type>&,
unsigned flags,
std::size_t);
template std::size_t regex_split(test_string_type*,
test_string_type& s,
const reg_expression<char_type>& e,
unsigned flags);
template std::size_t regex_split(test_string_type*, test_string_type&);
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
//
// the following prototypes are only available if partial ordering
// of template functions is supported:
//
template bool regex_match(const char_type*,
match_results<const char_type*>& m,
const reg_expression<char_type>& e,
unsigned flags);
template bool regex_match(const test_string_type&,
match_results<test_string_type::const_iterator>&,
const reg_expression<char_type>&,
unsigned flags);
template bool regex_match(const char_type*,
const reg_expression<char_type>&,
unsigned flags);
template bool regex_match(const test_string_type&,
const reg_expression<char_type>&,
unsigned flags);
template bool regex_search(const char_type*,
match_results<const char_type*>&,
const reg_expression<char_type>&,
unsigned flags);
template bool regex_search(const test_string_type&,
match_results<test_string_type::const_iterator>&,
const reg_expression<char_type>&,
unsigned flags);
template unsigned int regex_grep(pred1_type,
const char_type*,
const reg_expression<char_type>&,
unsigned flags);
template unsigned int regex_grep(pred2_type,
const test_string_type&,
const reg_expression<char_type>&,
unsigned flags);
template test_string_type regex_format
(const match_results<test_string_type::const_iterator>& m,
const char_type*,
unsigned flags);
template test_string_type regex_format
(const match_results<test_string_type::const_iterator>&,
const test_string_type&,
unsigned flags);
template test_string_type regex_replace(const test_string_type&,
const reg_expression<char_type>&,
const char_type*,
unsigned int flags);
template test_string_type regex_replace(const test_string_type&,
const reg_expression<char_type>&,
const test_string_type&,
unsigned int flags);
#endif
} // namespace boost
//
// include regression test source files:
//
#ifdef BOOST_REGEX_USE_WIN32_LOCALE
#define BOOST_RE_TEST_LOCALE_W32
#elif !defined(BOOST_REGEX_USE_C_LOCALE)
#define BOOST_RE_TEST_LOCALE_CPP
#endif
#define TEST_UNICODE
#include "tests.cpp"
#include "parse.cpp"
#include "regress.cpp"
//
// Como goes into an infinite loop trying to link this,
// just have it fail for now:
//
#if defined(__COMO__) && defined(_MSC_VER)
#error "Comeau in VC6 mode goes into an infinite loop trying to link this program!!!"
#endif
+181
View File
@@ -0,0 +1,181 @@
/*
*
* Copyright (c) 2004
* Dr 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 static_mutex_test.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: test program for boost::static_mutex.
*/
#include <iostream>
#include <boost/regex/static_mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/timer.hpp>
//
// we cannot use the regular Boost.Test in here: it is not thread safe
// and calls to BOOST_TEST will eventually crash on some compilers
// (Borland certainly) due to race conditions inside the Boost.Test lib.
//
#define BOOST_TEST(pred) if(!(pred)) failed_test(__FILE__, __LINE__, BOOST_STRINGIZE(pred));
int total_failures = 0;
void failed_test(const char* file, int line, const char* pred)
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
boost::static_mutex::scoped_lock guard(mut);
++total_failures;
std::cout << "Failed test in \"" << file << "\" at line " << line << ": " << pred << std::endl;
}
void print_cycles(int c)
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
boost::static_mutex::scoped_lock guard(mut);
std::cout << "Thread exited after " << c << " cycles." << std::endl;
}
bool sufficient_time()
{
// return true if enough time has passed since the tests began:
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
boost::static_mutex::scoped_lock guard(mut);
static boost::timer t;
// is 10 seconds enough?
return t.elapsed() >= 10.0;
}
// define three trivial test proceedures:
bool t1()
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
static int has_lock = 0;
static int data = 10000;
boost::static_mutex::scoped_lock guard(mut);
BOOST_TEST(++has_lock == 1);
BOOST_TEST(guard.locked());
BOOST_TEST(guard);
bool result = (--data > 0) ? true : false;
BOOST_TEST(--has_lock == 0);
return result;
}
bool t2()
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
static int has_lock = 0;
static int data = 10000;
boost::static_mutex::scoped_lock guard(mut, false);
BOOST_TEST(0 == guard.locked());
BOOST_TEST(!guard);
guard.lock();
BOOST_TEST(++has_lock == 1);
BOOST_TEST(guard.locked());
BOOST_TEST(guard);
bool result = (--data > 0) ? true : false;
BOOST_TEST(--has_lock == 0);
guard.unlock();
BOOST_TEST(0 == guard.locked());
BOOST_TEST(!guard);
return result;
}
bool t3()
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
static int has_lock = 0;
static int data = 10000;
boost::static_mutex::scoped_lock guard(mut);
BOOST_TEST(++has_lock == 1);
BOOST_TEST(guard.locked());
BOOST_TEST(guard);
bool result = (--data > 0) ? true : false;
BOOST_TEST(--has_lock == 0);
return result;
}
// define their thread procs:
void thread1_proc()
{
int cycles = 0;
while(!sufficient_time())
{
t1();
t2();
++cycles;
}
print_cycles(cycles);
}
void thread2_proc()
{
int cycles = 0;
while(!sufficient_time())
{
t2();
t3();
++cycles;
}
print_cycles(cycles);
}
void thread3_proc()
{
int cycles = 0;
while(!sufficient_time())
{
t1();
t3();
++cycles;
}
print_cycles(cycles);
}
// make sure that at least one of our test proceedures
// is called during program startup:
struct startup1
{
startup1()
{
t1();
}
~startup1()
{
t1();
}
};
startup1 up1;
int main()
{
BOOST_TEST(0 != &up1);
boost::thread thrd1(&thread1_proc);
boost::thread thrd2(&thread1_proc);
boost::thread thrd3(&thread2_proc);
boost::thread thrd4(&thread2_proc);
boost::thread thrd5(&thread3_proc);
boost::thread thrd6(&thread3_proc);
thrd1.join();
thrd2.join();
thrd3.join();
thrd4.join();
thrd5.join();
thrd6.join();
return total_failures;
}