1 ///////////////////////////////////////////////////////////////////////////////
2 // test_cycles.hpp
3 //
4 //  Copyright 2008 Eric Niebler. Distributed under the Boost
5 //  Software License, Version 1.0. (See accompanying file
6 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 // defining this causes regex_impl objects to be counted, allowing us to detect
9 // leaks portably.
10 #define BOOST_XPRESSIVE_DEBUG_CYCLE_TEST
11 
12 #include <iostream>
13 #include <boost/test/unit_test.hpp>
14 #include <boost/xpressive/xpressive.hpp>
15 
16 #if defined(_MSC_VER) && defined(_DEBUG)
17 # define _CRTDBG_MAP_ALLOC
18 # include <crtdbg.h>
19 #endif
20 
21 using namespace boost::unit_test;
22 using namespace boost::xpressive;
23 
24 ///////////////////////////////////////////////////////////////////////////////
25 // test_main
26 // regexes referred to by other regexes are kept alive via reference counting.
27 // but cycles are handled naturally. the following works as expected and doesn't leak.
test_main()28 void test_main()
29 {
30     {
31         sregex v;
32         {
33             sregex a,b,c;
34             a = 'a' >> !by_ref(b);
35             //std::cout << a << std::endl;
36             //std::cout << b << std::endl;
37             //std::cout << c << std::endl;
38 
39             // just for giggles
40             c = a;
41             c = epsilon >> 'a';
42 
43             b = epsilon >> by_ref(c);
44             //std::cout << a << std::endl;
45             //std::cout << b << std::endl;
46             //std::cout << c << std::endl;
47 
48             c = epsilon >> by_ref(a);
49             //std::cout << a << std::endl;
50             //std::cout << b << std::endl;
51             //std::cout << c << std::endl;
52 
53             v = a;
54         }
55         std::string const s("aaa");
56         smatch m;
57         if(!regex_match(s, m, v))
58         {
59             BOOST_ERROR("cycle test 1 failed");
60         }
61     }
62 
63     if(0 != detail::regex_impl<std::string::const_iterator>::instances)
64     {
65         BOOST_ERROR("leaks detected (cycle test 1)");
66         detail::regex_impl<std::string::const_iterator>::instances = 0;
67     }
68 
69     {
70         sregex v;
71         {
72             sregex a,b,c;
73             b = epsilon >> by_ref(c);
74             a = 'a' >> !by_ref(b);
75             c = epsilon >> by_ref(a);
76 
77             //std::cout << a << std::endl;
78             //std::cout << b << std::endl;
79             //std::cout << c << std::endl;
80 
81             v = a;
82         }
83         std::string const s("aaa");
84         smatch m;
85         if(!regex_match(s, m, v))
86         {
87             BOOST_ERROR("cycle test 2 failed");
88         }
89     }
90 
91     if(0 != detail::regex_impl<std::string::const_iterator>::instances)
92     {
93         BOOST_ERROR("leaks detected (cycle test 2)");
94         detail::regex_impl<std::string::const_iterator>::instances = 0;
95     }
96 
97     {
98         sregex v;
99         {
100             sregex a,b,c;
101 
102             b = epsilon >> by_ref(c);
103             c = epsilon >> by_ref(a);
104             a = 'a' >> !by_ref(b);
105 
106             //std::cout << a << std::endl;
107             //std::cout << b << std::endl;
108             //std::cout << c << std::endl;
109 
110             v = a;
111         }
112         std::string const s("aaa");
113         smatch m;
114         if(!regex_match(s, m, v))
115         {
116             BOOST_ERROR("cycle test 3 failed");
117         }
118     }
119 
120     if(0 != detail::regex_impl<std::string::const_iterator>::instances)
121     {
122         BOOST_ERROR("leaks detected (cycle test 3)");
123         detail::regex_impl<std::string::const_iterator>::instances = 0;
124     }
125 
126     {
127         sregex v;
128         {
129             sregex a,b,c;
130             c = epsilon >> by_ref(a);
131             b = epsilon >> by_ref(c);
132             a = 'a' >> !by_ref(b);
133 
134             //std::cout << a << std::endl;
135             //std::cout << b << std::endl;
136             //std::cout << c << std::endl;
137 
138             v = a;
139         }
140         std::string const s("aaa");
141         smatch m;
142         if(!regex_match(s, m, v))
143         {
144             BOOST_ERROR("cycle test 4 failed");
145         }
146     }
147 
148     if(0 != detail::regex_impl<std::string::const_iterator>::instances)
149     {
150         BOOST_ERROR("leaks detected (cycle test 4)");
151         detail::regex_impl<std::string::const_iterator>::instances = 0;
152     }
153 
154     {
155         sregex v;
156         {
157             sregex a,b,c;
158             a = 'a' >> !by_ref(b);
159             b = epsilon >> by_ref(c);
160             c = epsilon >> by_ref(a);
161 
162             sregex d,e;
163             d = epsilon >> by_ref(e);
164             e = epsilon >> "aa";
165 
166             c = d;
167 
168             //std::cout << a << std::endl;
169             //std::cout << b << std::endl;
170             //std::cout << c << std::endl;
171             //std::cout << e << std::endl;
172 
173             e = 'a' >> by_ref(c);
174 
175             //std::cout << "-new loop!\n";
176             //std::cout << a << std::endl;
177             //std::cout << b << std::endl;
178             //std::cout << c << std::endl;
179             //std::cout << e << std::endl;
180 
181             v = a;
182 
183             //std::cout << v << std::endl;
184 
185         }
186         std::string const s("aaa");
187         smatch m;
188         if(regex_match(s, m, v)) // OK, this shouldn't match
189         {
190             BOOST_ERROR("cycle test 5 failed");
191         }
192     }
193 
194     if(0 != detail::regex_impl<std::string::const_iterator>::instances)
195     {
196         BOOST_ERROR("leaks detected (cycle test 5)");
197         detail::regex_impl<std::string::const_iterator>::instances = 0;
198     }
199 }
200 
201 ///////////////////////////////////////////////////////////////////////////////
202 // init_unit_test_suite
203 //
init_unit_test_suite(int argc,char * argv[])204 test_suite* init_unit_test_suite( int argc, char* argv[] )
205 {
206     test_suite *test = BOOST_TEST_SUITE("test_cycles");
207     test->add(BOOST_TEST_CASE(&test_main));
208     return test;
209 }
210 
211 ///////////////////////////////////////////////////////////////////////////////
212 // Debug stuff
213 //
214 namespace
215 {
216     const struct debug_init
217     {
debug_init__anonee0579db0111::debug_init218         debug_init()
219         {
220             #ifdef _MSC_VER
221             // Send warnings, errors and asserts to STDERR
222             _CrtSetReportMode(_CRT_WARN,   _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
223             _CrtSetReportFile(_CRT_WARN,   _CRTDBG_FILE_STDERR);
224             _CrtSetReportMode(_CRT_ERROR,  _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
225             _CrtSetReportFile(_CRT_ERROR,  _CRTDBG_FILE_STDERR);
226             _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
227             _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
228 
229             // Check for leaks at program termination
230             _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
231 
232             //_CrtSetBreakAlloc(221);
233             #endif
234         }
235     } dbg;
236 }
237