• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright (c) 2004
4  * John Maddock
5  *
6  * Use, modification and distribution are subject to the
7  * Boost Software License, Version 1.0. (See accompanying file
8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  */
11 
12  /*
13   *   LOCATION:    see http://www.boost.org for most recent version.
14   *   FILE         test_regex_search.hpp
15   *   VERSION      see <boost/version.hpp>
16   *   DESCRIPTION: Declares tests for regex search and iteration.
17   */
18 
19 #ifndef BOOST_REGEX_REGRESS_REGEX_PARTIAL_MATCH_HPP
20 #define BOOST_REGEX_REGRESS_REGEX_PARTIAL_MATCH_HPP
21 #include "info.hpp"
22 //
23 // this file implements a test for a regular expression that should compile,
24 // followed by a search for that expression:
25 //
26 struct test_regex_search_tag{};
27 
28 template <class BidirectionalIterator>
test_sub_match(const boost::sub_match<BidirectionalIterator> & sub,BidirectionalIterator base,const int * answer_table,int i)29 void test_sub_match(const boost::sub_match<BidirectionalIterator>& sub, BidirectionalIterator base, const int* answer_table, int i)
30 {
31 #ifdef BOOST_MSVC
32 #pragma warning(push)
33 #pragma warning(disable:4244)
34 #endif
35    typedef typename boost::sub_match<BidirectionalIterator>::value_type charT;
36    if((sub.matched == 0)
37       &&
38          !((i == 0)
39           && (test_info<charT>::match_options() & boost::match_partial)) )
40    {
41       if(answer_table[2*i] >= 0)
42       {
43          BOOST_REGEX_TEST_ERROR(
44             "Sub-expression " << i
45             << " was not matched when it should have been.", charT);
46       }
47    }
48    else
49    {
50       if(boost::BOOST_REGEX_DETAIL_NS::distance(base, sub.first) != answer_table[2*i])
51       {
52          BOOST_REGEX_TEST_ERROR(
53             "Error in start location of sub-expression "
54             << i << ", found " << boost::BOOST_REGEX_DETAIL_NS::distance(base, sub.first)
55             << ", expected " << answer_table[2*i] << ".", charT);
56       }
57       if(boost::BOOST_REGEX_DETAIL_NS::distance(base, sub.second) != answer_table[1+ 2*i])
58       {
59          BOOST_REGEX_TEST_ERROR(
60             "Error in end location of sub-expression "
61             << i << ", found " << boost::BOOST_REGEX_DETAIL_NS::distance(base, sub.second)
62             << ", expected " << answer_table[1 + 2*i] << ".", charT);
63       }
64    }
65 #ifdef BOOST_MSVC
66 #pragma warning(pop)
67 #endif
68 }
69 
70 template <class BidirectionalIterator, class Allocator>
test_result(const boost::match_results<BidirectionalIterator,Allocator> & what,BidirectionalIterator base,const int * answer_table)71 void test_result(const boost::match_results<BidirectionalIterator, Allocator>& what, BidirectionalIterator base, const int* answer_table)
72 {
73    for(unsigned i = 0; i < what.size(); ++i)
74    {
75       test_sub_match(what[i], base, answer_table, i);
76    }
77 }
78 
79 template<class charT, class traits>
test_simple_search(boost::basic_regex<charT,traits> & r)80 void test_simple_search(boost::basic_regex<charT, traits>& r)
81 {
82    typedef typename std::basic_string<charT>::const_iterator const_iterator;
83    const std::basic_string<charT>& search_text = test_info<charT>::search_text();
84    boost::regex_constants::match_flag_type opts = test_info<charT>::match_options();
85    const int* answer_table = test_info<charT>::answer_table();
86    boost::match_results<const_iterator> what;
87    if(boost::regex_search(
88       search_text.begin(),
89       search_text.end(),
90       what,
91       r,
92       opts))
93    {
94       test_result(what, search_text.begin(), answer_table);
95       // setting match_any should have no effect on the result returned:
96       if(!boost::regex_search(
97          search_text.begin(),
98          search_text.end(),
99          r,
100          opts|boost::regex_constants::match_any))
101       {
102          BOOST_REGEX_TEST_ERROR("Expected match was not found when using the match_any flag.", charT);
103       }
104    }
105    else
106    {
107       if(answer_table[0] >= 0)
108       {
109          // we should have had a match but didn't:
110          BOOST_REGEX_TEST_ERROR("Expected match was not found.", charT);
111       }
112       // setting match_any should have no effect on the result returned:
113       else if(boost::regex_search(
114          search_text.begin(),
115          search_text.end(),
116          r,
117          opts|boost::regex_constants::match_any))
118       {
119          BOOST_REGEX_TEST_ERROR("Unexpected match was found when using the match_any flag.", charT);
120       }
121    }
122 }
123 
124 template<class charT, class traits>
test_regex_iterator(boost::basic_regex<charT,traits> & r)125 void test_regex_iterator(boost::basic_regex<charT, traits>& r)
126 {
127    typedef typename std::basic_string<charT>::const_iterator const_iterator;
128    typedef boost::regex_iterator<const_iterator, charT, traits> test_iterator;
129    const std::basic_string<charT>& search_text = test_info<charT>::search_text();
130    boost::regex_constants::match_flag_type opts = test_info<charT>::match_options();
131    const int* answer_table = test_info<charT>::answer_table();
132    test_iterator start(search_text.begin(), search_text.end(), r, opts), end;
133    test_iterator copy(start);
134    const_iterator last_end = search_text.begin();
135    while(start != end)
136    {
137       if(start != copy)
138       {
139          BOOST_REGEX_TEST_ERROR("Failed iterator != comparison.", charT);
140       }
141       if(!(start == copy))
142       {
143          BOOST_REGEX_TEST_ERROR("Failed iterator == comparison.", charT);
144       }
145       test_result(*start, search_text.begin(), answer_table);
146       // test $` and $' :
147       if(start->prefix().first != last_end)
148       {
149          BOOST_REGEX_TEST_ERROR("Incorrect position for start of $`", charT);
150       }
151       if(start->prefix().second != (*start)[0].first)
152       {
153          BOOST_REGEX_TEST_ERROR("Incorrect position for end of $`", charT);
154       }
155       if(start->prefix().matched != (start->prefix().first != start->prefix().second))
156       {
157          BOOST_REGEX_TEST_ERROR("Incorrect position for matched member of $`", charT);
158       }
159       if(start->suffix().first != (*start)[0].second)
160       {
161          BOOST_REGEX_TEST_ERROR("Incorrect position for start of $'", charT);
162       }
163       if(start->suffix().second != search_text.end())
164       {
165          BOOST_REGEX_TEST_ERROR("Incorrect position for end of $'", charT);
166       }
167       if(start->suffix().matched != (start->suffix().first != start->suffix().second))
168       {
169          BOOST_REGEX_TEST_ERROR("Incorrect position for matched member of $'", charT);
170       }
171       last_end = (*start)[0].second;
172       ++start;
173       ++copy;
174       // move on the answer table to next set of answers;
175       if(*answer_table != -2)
176          while(*answer_table++ != -2){}
177    }
178    if(answer_table[0] >= 0)
179    {
180       // we should have had a match but didn't:
181       BOOST_REGEX_TEST_ERROR("Expected match was not found.", charT);
182    }
183 }
184 
185 template<class charT, class traits>
test_regex_token_iterator(boost::basic_regex<charT,traits> & r)186 void test_regex_token_iterator(boost::basic_regex<charT, traits>& r)
187 {
188    typedef typename std::basic_string<charT>::const_iterator const_iterator;
189    typedef boost::regex_token_iterator<const_iterator, charT, traits> test_iterator;
190    const std::basic_string<charT>& search_text = test_info<charT>::search_text();
191    boost::regex_constants::match_flag_type opts = test_info<charT>::match_options();
192    const int* answer_table = test_info<charT>::answer_table();
193    //
194    // we start by testing sub-expression 0:
195    //
196    test_iterator start(search_text.begin(), search_text.end(), r, 0, opts), end;
197    test_iterator copy(start);
198    while(start != end)
199    {
200       if(start != copy)
201       {
202          BOOST_REGEX_TEST_ERROR("Failed iterator != comparison.", charT);
203       }
204       if(!(start == copy))
205       {
206          BOOST_REGEX_TEST_ERROR("Failed iterator == comparison.", charT);
207       }
208       test_sub_match(*start, search_text.begin(), answer_table, 0);
209       ++start;
210       ++copy;
211       // move on the answer table to next set of answers;
212       if(*answer_table != -2)
213          while(*answer_table++ != -2){}
214    }
215    if(answer_table[0] >= 0)
216    {
217       // we should have had a match but didn't:
218       BOOST_REGEX_TEST_ERROR("Expected match was not found.", charT);
219    }
220    //
221    // and now field spitting:
222    //
223    test_iterator start2(search_text.begin(), search_text.end(), r, -1, opts), end2;
224    test_iterator copy2(start2);
225    int last_end2 = 0;
226    answer_table = test_info<charT>::answer_table();
227    while(start2 != end2)
228    {
229       if(start2 != copy2)
230       {
231          BOOST_REGEX_TEST_ERROR("Failed iterator != comparison.", charT);
232       }
233       if(!(start2 == copy2))
234       {
235          BOOST_REGEX_TEST_ERROR("Failed iterator == comparison.", charT);
236       }
237 #ifdef BOOST_MSVC
238 #pragma warning(push)
239 #pragma warning(disable:4244)
240 #endif
241       if(boost::BOOST_REGEX_DETAIL_NS::distance(search_text.begin(), start2->first) != last_end2)
242       {
243          BOOST_REGEX_TEST_ERROR(
244             "Error in location of start of field split, found: "
245             << boost::BOOST_REGEX_DETAIL_NS::distance(search_text.begin(), start2->first)
246             << ", expected: "
247             << last_end2
248             << ".", charT);
249       }
250       int expected_end = static_cast<int>(answer_table[0] < 0 ? search_text.size() : answer_table[0]);
251       if(boost::BOOST_REGEX_DETAIL_NS::distance(search_text.begin(), start2->second) != expected_end)
252       {
253          BOOST_REGEX_TEST_ERROR(
254             "Error in location of end2 of field split, found: "
255             << boost::BOOST_REGEX_DETAIL_NS::distance(search_text.begin(), start2->second)
256             << ", expected: "
257             << expected_end
258             << ".", charT);
259       }
260 #ifdef BOOST_MSVC
261 #pragma warning(pop)
262 #endif
263       last_end2 = answer_table[1];
264       ++start2;
265       ++copy2;
266       // move on the answer table to next set of answers;
267       if(*answer_table != -2)
268          while(*answer_table++ != -2){}
269    }
270    if(answer_table[0] >= 0)
271    {
272       // we should have had a match but didn't:
273       BOOST_REGEX_TEST_ERROR("Expected match was not found.", charT);
274    }
275 }
276 
277 template <class charT, class traits>
278 struct grep_test_predicate
279 {
280    typedef typename std::basic_string<charT>::const_iterator test_iter;
281 
grep_test_predicategrep_test_predicate282    grep_test_predicate(test_iter b, const int* a)
283       : m_base(b), m_table(a)
284    {}
operator ()grep_test_predicate285    bool operator()(const boost::match_results<test_iter>& what)
286    {
287       test_result(what, m_base, m_table);
288       // move on the answer table to next set of answers;
289       if(*m_table != -2)
290          while(*m_table++ != -2){}
291       return true;
292    }
293 private:
294    test_iter m_base;
295    const int* m_table;
296 };
297 
298 template<class charT, class traits>
test_regex_grep(boost::basic_regex<charT,traits> & r)299 void test_regex_grep(boost::basic_regex<charT, traits>& r)
300 {
301    typedef typename std::basic_string<charT>::const_iterator const_iterator;
302    const std::basic_string<charT>& search_text = test_info<charT>::search_text();
303    boost::regex_constants::match_flag_type opts = test_info<charT>::match_options();
304    const int* answer_table = test_info<charT>::answer_table();
305    grep_test_predicate<charT, traits> pred(search_text.begin(), answer_table);
306    boost::regex_grep(pred, search_text.begin(), search_text.end(), r, opts);
307 }
308 
309 template<class charT, class traits>
test_regex_match(boost::basic_regex<charT,traits> & r)310 void test_regex_match(boost::basic_regex<charT, traits>& r)
311 {
312    typedef typename std::basic_string<charT>::const_iterator const_iterator;
313    const std::basic_string<charT>& search_text = test_info<charT>::search_text();
314    boost::regex_constants::match_flag_type opts = test_info<charT>::match_options();
315    const int* answer_table = test_info<charT>::answer_table();
316    boost::match_results<const_iterator> what;
317    if(answer_table[0] < 0)
318    {
319       if(boost::regex_match(search_text, r, opts))
320       {
321          BOOST_REGEX_TEST_ERROR("boost::regex_match found a match when it should not have done so.", charT);
322       }
323    }
324    else
325    {
326       if((answer_table[0] > 0) && boost::regex_match(search_text, r, opts))
327       {
328          BOOST_REGEX_TEST_ERROR("boost::regex_match found a match when it should not have done so.", charT);
329       }
330       else if((answer_table[0] == 0) && (answer_table[1] == static_cast<int>(search_text.size())))
331       {
332          if(boost::regex_match(
333             search_text.begin(),
334             search_text.end(),
335             what,
336             r,
337             opts))
338          {
339             test_result(what, search_text.begin(), answer_table);
340          }
341          else if(answer_table[0] >= 0)
342          {
343             // we should have had a match but didn't:
344             BOOST_REGEX_TEST_ERROR("Expected match was not found.", charT);
345          }
346       }
347    }
348 }
349 
350 template<class charT, class traits>
test(boost::basic_regex<charT,traits> & r,const test_regex_search_tag &)351 void test(boost::basic_regex<charT, traits>& r, const test_regex_search_tag&)
352 {
353    const std::basic_string<charT>& expression = test_info<charT>::expression();
354    boost::regex_constants::syntax_option_type syntax_options = test_info<charT>::syntax_options();
355    try{
356       r.assign(expression, syntax_options);
357       if(r.status())
358       {
359          BOOST_REGEX_TEST_ERROR("Expression did not compile when it should have done, error code = " << r.status(), charT);
360       }
361       test_simple_search(r);
362       test_regex_iterator(r);
363       test_regex_token_iterator(r);
364       test_regex_grep(r);
365       test_regex_match(r);
366    }
367    catch(const boost::bad_expression& e)
368    {
369       BOOST_REGEX_TEST_ERROR("Expression did not compile when it should have done: " << e.what(), charT);
370    }
371    catch(const std::runtime_error& r)
372    {
373       BOOST_REGEX_TEST_ERROR("Received an unexpected std::runtime_error: " << r.what(), charT);
374    }
375    catch(const std::exception& r)
376    {
377       BOOST_REGEX_TEST_ERROR("Received an unexpected std::exception: " << r.what(), charT);
378    }
379    catch(...)
380    {
381       BOOST_REGEX_TEST_ERROR("Received an unexpected exception of unknown type", charT);
382    }
383 
384 }
385 
386 
387 
388 #endif
389 
390