1// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2// (C) Copyright 2004-2007 Jonathan Turkanis
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5
6// See http://www.boost.org/libs/iostreams for documentation.
7
8#include <fstream>
9#include <boost/iostreams/device/file.hpp>
10#include <boost/iostreams/filtering_stream.hpp>
11#include <boost/iostreams/filter/regex.hpp>
12#include <boost/test/test_tools.hpp>
13#include <boost/test/unit_test.hpp>
14#include "detail/temp_file.hpp"
15#include "detail/verification.hpp"
16
17using namespace std;
18using namespace boost::iostreams;
19using namespace boost::iostreams::test;
20using boost::unit_test::test_suite;
21
22struct replace_lower {
23 std::string operator() (const boost::match_results<const char*>&)
24 { return "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
25#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS
26 std::wstring operator() (const boost::match_results<const wchar_t*>&)
27 { return L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
28#endif
29};
30
31void regex_filter_test()
32{
33 // Note: Given the basic stream and filter tests, two regex tests
34 // are probably sufficient: reading with a filter based on a function,
35 // and writing with a filter based on a format string.
36
37 test_file test;
38 uppercase_file upper;
39
40 boost::regex match_lower("[a-z]+");
41 std::string fmt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
42
43 {
44 // Note: the ifstream second is placed in a nested scope because
45 // closing and reopening a single ifstream failed for CW 9.4 on Windows.
46
47 // Test reading from a regex filter based on a function in chars.
48 filtering_istream
49 first(boost::iostreams::regex_filter(match_lower, replace_lower()));
50 first.push(t: file_source(test.name(), in_mode));
51 {
52 ifstream second(upper.name().c_str(), in_mode);
53 BOOST_CHECK_MESSAGE(
54 compare_streams_in_chars(first, second),
55 "failed reading from function-based regex_filter in chars"
56 );
57 }
58 first.pop();
59
60 // Test reading from a regex filter based on a function in chunks.
61 // (Also tests reusing the regex filter.)
62 first.push(t: file_source(test.name(), in_mode));
63 {
64 ifstream second(upper.name().c_str(), in_mode);
65 BOOST_CHECK_MESSAGE(
66 compare_streams_in_chunks(first, second),
67 "failed reading from function-based regex_filter in chunks"
68 );
69 }
70 }
71
72 {
73 // Note: the ifstream second is placed in a nested scope because
74 // closing and reopening a single ifstream failed for CW 9.4 on Windows.
75
76 // Test reading from a regex filter based on a format string in chars.
77 filtering_istream
78 first(boost::iostreams::regex_filter(match_lower, fmt));
79 first.push(t: file_source(test.name(), in_mode));
80 {
81 ifstream second(upper.name().c_str(), in_mode);
82 BOOST_CHECK_MESSAGE(
83 compare_streams_in_chars(first, second),
84 "failed reading from format-string-based regex_filter in chars"
85 );
86 }
87 first.pop();
88
89 // Test reading from a regex filter based on a format string in chunks.
90 // (Also tests reusing the regex filter.)
91 first.push(t: file_source(test.name(), in_mode));
92 {
93 ifstream second(upper.name().c_str(), in_mode);
94 BOOST_CHECK_MESSAGE(
95 compare_streams_in_chars(first, second),
96 "failed reading from format-string-based regex_filter in chunks"
97 );
98 }
99 }
100
101 {
102 test_file dest1;
103 test_file dest2;
104
105 // Test writing to a regex filter based on a function in chars.
106 filtering_ostream
107 out(boost::iostreams::regex_filter(match_lower, replace_lower()));
108 out.push(t: file_sink(dest1.name(), out_mode));
109 write_data_in_chars(os&: out);
110 out.pop();
111 BOOST_CHECK_MESSAGE(
112 compare_files(dest1.name(), upper.name()),
113 "failed writing to function-based regex_filter in chars"
114 );
115
116 // Test writing to a regex filter based on a function in chunks.
117 // (Also tests reusing the regex filter.)
118 out.push(t: file_sink(dest2.name(), out_mode));
119 write_data_in_chunks(os&: out);
120 out.pop();
121 BOOST_CHECK_MESSAGE(
122 compare_files(dest2.name(), upper.name()),
123 "failed writing to function-based regex_filter in chunks"
124 );
125 }
126
127 {
128 test_file dest1;
129 test_file dest2;
130
131 // Test writing to a regex filter based on a format string in chars.
132 filtering_ostream
133 out(boost::iostreams::regex_filter(match_lower, fmt));
134 out.push(t: file_sink(dest1.name(), out_mode));
135 write_data_in_chars(os&: out);
136 out.pop();
137 BOOST_CHECK_MESSAGE(
138 compare_files(dest1.name(), upper.name()),
139 "failed writing to format-string-based regex_filter in chars"
140 );
141
142 // Test writing to a regex filter based on a format string in chunks.
143 // (Also tests reusing the regex filter.)
144 out.push(t: file_sink(dest2.name(), out_mode));
145 write_data_in_chunks(os&: out);
146 out.pop();
147 BOOST_CHECK_MESSAGE(
148 compare_files(dest2.name(), upper.name()),
149 "failed writing to format-string-based regex_filter in chunks"
150 );
151 }
152
153 {
154 // Note: the ifstream second is placed in a nested scope because
155 // closing and reopening a single ifstream failed for CW 9.4 on Windows.
156
157 // Test reading from a regex filter with no matches; this checks that
158 // Ticket #1139 is fixed
159 boost::regex match_xxx("xxx");
160 test_file test2;
161 filtering_istream
162 first(boost::iostreams::regex_filter(match_xxx, replace_lower()));
163 first.push(t: file_source(test.name(), in_mode));
164 {
165 ifstream second(test2.name().c_str(), in_mode);
166 BOOST_CHECK_MESSAGE(
167 compare_streams_in_chars(first, second),
168 "failed reading from a regex filter with no matches"
169 );
170 }
171 }
172}
173
174#if !defined(BOOST_IOSTREAMS_NO_WIDE_STREAMS) && !defined(BOOST_NO_WREGEX)
175
176void wregex_filter_test()
177{
178 // Note: Given the basic stream and filter tests, two regex tests
179 // are probably sufficient: reading with a filter based on a function,
180 // and writing with a filter based on a format string.
181
182 test_file test;
183 uppercase_file upper;
184
185 boost::wregex match_lower(L"[a-z]+");
186 std::wstring fmt = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
187
188 {
189 // Note: the ifstream second is placed in a nested scope because
190 // closing and reopening a single ifstream failed for CW 9.4 on Windows.
191
192 // Test reading from a regex filter based on a function in chars.
193 filtering_wistream
194 first(boost::iostreams::wregex_filter(match_lower, replace_lower()));
195 first.push(t: wfile_source(test.name(), in_mode));
196 {
197 wifstream second(upper.name().c_str(), in_mode);
198 BOOST_CHECK_MESSAGE(
199 compare_streams_in_chars(first, second),
200 "failed reading from function-based regex_filter in chars"
201 );
202 }
203 first.pop();
204
205 // Test reading from a regex filter based on a function in chunks.
206 // (Also tests reusing the regex filter.)
207 first.push(t: wfile_source(test.name(), in_mode));
208 {
209 wifstream second(upper.name().c_str(), in_mode);
210 BOOST_CHECK_MESSAGE(
211 compare_streams_in_chunks(first, second),
212 "failed reading from function-based regex_filter in chunks"
213 );
214 }
215 }
216
217 {
218 // Note: the ifstream second is placed in a nested scope because
219 // closing and reopening a single ifstream failed for CW 9.4 on Windows.
220
221 // Test reading from a regex filter based on a format string in chars.
222 filtering_wistream
223 first(boost::iostreams::wregex_filter(match_lower, fmt));
224 first.push(t: wfile_source(test.name(), in_mode));
225 {
226 wifstream second(upper.name().c_str(), in_mode);
227 BOOST_CHECK_MESSAGE(
228 compare_streams_in_chars(first, second),
229 "failed reading from format-string-based regex_filter in chars"
230 );
231 }
232 first.pop();
233
234 // Test reading from a regex filter based on a format string in chunks.
235 // (Also tests reusing the regex filter.)
236 first.push(t: wfile_source(test.name(), in_mode));
237 {
238 wifstream second(upper.name().c_str(), in_mode);
239 BOOST_CHECK_MESSAGE(
240 compare_streams_in_chars(first, second),
241 "failed reading from format-string-based regex_filter in chunks"
242 );
243 }
244 }
245
246 {
247 test_file dest1;
248 test_file dest2;
249
250 // Test writing to a regex filter based on a function in chars.
251 filtering_wostream
252 out(boost::iostreams::wregex_filter(match_lower, replace_lower()));
253 out.push(t: wfile_sink(dest1.name(), out_mode));
254 write_data_in_chars(os&: out);
255 out.pop();
256 BOOST_CHECK_MESSAGE(
257 compare_files(dest1.name(), upper.name()),
258 "failed writing to function-based regex_filter in chars"
259 );
260
261 // Test writing to a regex filter based on a function in chunks.
262 // (Also tests reusing the regex filter.)
263 out.push(t: wfile_sink(dest2.name(), out_mode));
264 write_data_in_chunks(os&: out);
265 out.pop();
266 BOOST_CHECK_MESSAGE(
267 compare_files(dest2.name(), upper.name()),
268 "failed writing to function-based regex_filter in chunks"
269 );
270 }
271
272 {
273 test_file dest1;
274 test_file dest2;
275
276 // Test writing to a regex filter based on a format string in chars.
277 filtering_wostream
278 out(boost::iostreams::wregex_filter(match_lower, fmt));
279 out.push(t: wfile_sink(dest1.name(), out_mode));
280 write_data_in_chars(os&: out);
281 out.pop();
282 BOOST_CHECK_MESSAGE(
283 compare_files(dest1.name(), upper.name()),
284 "failed writing to format-string-based regex_filter in chars"
285 );
286
287 // Test writing to a regex filter based on a format string in chunks.
288 // (Also tests reusing the regex filter.)
289 out.push(t: wfile_sink(dest2.name(), out_mode));
290 write_data_in_chunks(os&: out);
291 out.pop();
292 BOOST_CHECK_MESSAGE(
293 compare_files(dest2.name(), upper.name()),
294 "failed writing to format-string-based regex_filter in chunks"
295 );
296 }
297
298 {
299 // Note: the ifstream second is placed in a nested scope because
300 // closing and reopening a single ifstream failed for CW 9.4 on Windows.
301
302 // Test reading from a regex filter with no matches; this checks that
303 // Ticket #1139 is fixed
304 boost::wregex match_xxx(L"xxx");
305 test_file test2;
306 filtering_wistream
307 first(boost::iostreams::wregex_filter(match_xxx, replace_lower()));
308 first.push(t: wfile_source(test.name(), in_mode));
309 {
310 wifstream second(test2.name().c_str(), in_mode);
311 BOOST_CHECK_MESSAGE(
312 compare_streams_in_chars(first, second),
313 "failed reading from a regex filter with no matches"
314 );
315 }
316 }
317}
318
319#endif
320
321test_suite* init_unit_test_suite(int, char* [])
322{
323 test_suite* test = BOOST_TEST_SUITE("regex_filter test");
324 test->add(BOOST_TEST_CASE(&regex_filter_test));
325#if !defined(BOOST_IOSTREAMS_NO_WIDE_STREAMS) && !defined(BOOST_NO_WREGEX)
326 test->add(BOOST_TEST_CASE(&wregex_filter_test));
327#endif
328 return test;
329}
330

source code of boost/libs/iostreams/test/regex_filter_test.cpp