]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
17 | using namespace std; | |
18 | using namespace boost::iostreams; | |
19 | using namespace boost::iostreams::test; | |
20 | using boost::unit_test::test_suite; | |
21 | ||
22 | struct 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 | ||
31 | void 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(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(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(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(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(file_sink(dest1.name(), out_mode)); | |
109 | write_data_in_chars(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(file_sink(dest2.name(), out_mode)); | |
119 | write_data_in_chunks(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(file_sink(dest1.name(), out_mode)); | |
135 | write_data_in_chars(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(file_sink(dest2.name(), out_mode)); | |
145 | write_data_in_chunks(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(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 | #ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS | |
175 | ||
176 | void 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(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(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(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(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(wfile_sink(dest1.name(), out_mode)); | |
254 | write_data_in_chars(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(wfile_sink(dest2.name(), out_mode)); | |
264 | write_data_in_chunks(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(wfile_sink(dest1.name(), out_mode)); | |
280 | write_data_in_chars(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(wfile_sink(dest2.name(), out_mode)); | |
290 | write_data_in_chunks(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(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 | ||
321 | test_suite* init_unit_test_suite(int, char* []) | |
322 | { | |
323 | test_suite* test = BOOST_TEST_SUITE("regex_filter test"); | |
324 | test->add(BOOST_TEST_CASE(®ex_filter_test)); | |
325 | #ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS | |
326 | test->add(BOOST_TEST_CASE(&wregex_filter_test)); | |
327 | #endif | |
328 | return test; | |
329 | } |