1 #include <string>
2 #include "math_aux.h"
3
4 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
5 # include <sstream>
6 # include <memory>
7
8 # include "full_streambuf.h"
9
10 # include "cppunit/cppunit_proxy.h"
11
12 # if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
13 using namespace std;
14 # endif
15
16 //
17 // TestCase class
18 //
19 class SstreamTest : public CPPUNIT_NS::TestCase
20 {
21 CPPUNIT_TEST_SUITE(SstreamTest);
22 CPPUNIT_TEST(output);
23 CPPUNIT_TEST(input);
24 CPPUNIT_TEST(input_char);
25 CPPUNIT_TEST(io);
26 CPPUNIT_TEST(err);
27 CPPUNIT_TEST(err_long);
28 CPPUNIT_TEST(maxint);
29 CPPUNIT_TEST(init_in);
30 CPPUNIT_TEST(init_out);
31 CPPUNIT_TEST(buf);
32 CPPUNIT_TEST(rdbuf);
33 CPPUNIT_TEST(streambuf_output);
34 CPPUNIT_TEST(seek);
35 CPPUNIT_TEST(seekp);
36 CPPUNIT_TEST(seek_gp);
37 CPPUNIT_TEST(tellp);
38 CPPUNIT_TEST(negative);
39 CPPUNIT_TEST_SUITE_END();
40
41 protected:
42 void output();
43 void input();
44 void input_char();
45 void io();
46 void err();
47 void err_long();
48 void maxint();
49 void init_in();
50 void init_out();
51 void buf();
52 void rdbuf();
53 void streambuf_output();
54 void seek();
55 void seekp();
56 void seek_gp();
57 void tellp();
58 void negative();
59 };
60
61 CPPUNIT_TEST_SUITE_REGISTRATION(SstreamTest);
62
63 //
64 // tests implementation
65 //
output()66 void SstreamTest::output()
67 {
68 {
69 ostringstream s;
70
71 s << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef";
72 CPPUNIT_ASSERT( s.good() );
73 CPPUNIT_ASSERT( s.str() == "1\n2\nabcd\nghk lm\nabcd ef" );
74 }
75
76 //Following tests are mostly used to reveal problem with the MSVC /Wp64 option
77 //used to track 64 bits portability issue:
78 {
79 ostringstream s;
80 size_t i = 0;
81 s << i;
82 CPPUNIT_ASSERT( s.good() );
83 CPPUNIT_ASSERT( s.str() == "0" );
84 }
85 {
86 ostringstream s;
87 ptrdiff_t i = 0;
88 s << i;
89 CPPUNIT_ASSERT( s.good() );
90 CPPUNIT_ASSERT( s.str() == "0" );
91 }
92 }
93
input()94 void SstreamTest::input()
95 {
96 {
97 istringstream s( "1\n2\nabcd\nghk lm\nabcd ef" );
98 int i = 0;
99 s >> i;
100 CPPUNIT_ASSERT( s.good() );
101 CPPUNIT_ASSERT( i == 1 );
102 double d = 0.0;
103 s >> d;
104 CPPUNIT_ASSERT( s.good() );
105 CPPUNIT_ASSERT( d == 2.0 );
106 string str;
107 s >> str;
108 CPPUNIT_ASSERT( s.good() );
109 CPPUNIT_ASSERT( str == "abcd" );
110 char c;
111 s.get(c); // extract newline, that not extracted by operator >>
112 CPPUNIT_ASSERT( s.good() );
113 CPPUNIT_ASSERT( c == '\n' );
114 getline( s, str );
115 CPPUNIT_ASSERT( s.good() );
116 CPPUNIT_ASSERT( str == "ghk lm" );
117 getline( s, str );
118 CPPUNIT_ASSERT( s.eof() );
119 CPPUNIT_ASSERT( str == "abcd ef" );
120 }
121 {
122 istringstream s("0");
123 size_t i = 1;
124 s >> i;
125 CPPUNIT_ASSERT( !s.fail() );
126 CPPUNIT_ASSERT( s.eof() );
127 CPPUNIT_ASSERT( i == 0 );
128 }
129 }
130
input_char()131 void SstreamTest::input_char()
132 {
133 char buf[16] = { 0, '1', '2', '3' };
134 istringstream s( "0" );
135 s >> buf;
136
137 CPPUNIT_ASSERT( buf[0] == '0' );
138 CPPUNIT_ASSERT( buf[1] == 0 );
139 CPPUNIT_ASSERT( buf[2] == '2' );
140 }
141
142
io()143 void SstreamTest::io()
144 {
145 stringstream s;
146 s << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef";
147 CPPUNIT_ASSERT( s.good() );
148
149 int i = 0;
150 s >> i;
151 CPPUNIT_ASSERT( i == 1 );
152 CPPUNIT_ASSERT( s.good() );
153 double d = 0.0;
154 s >> d;
155 CPPUNIT_ASSERT( d == 2.0 );
156 CPPUNIT_ASSERT( s.good() );
157 string str;
158 s >> str;
159 CPPUNIT_ASSERT( str == "abcd" );
160 CPPUNIT_ASSERT( s.good() );
161 char c;
162 s.get(c); // extract newline, that not extracted by operator >>
163 CPPUNIT_ASSERT( s.good() );
164 CPPUNIT_ASSERT( c == '\n' );
165 getline( s, str );
166 CPPUNIT_ASSERT( s.good() );
167 CPPUNIT_ASSERT( str == "ghk lm" );
168 getline( s, str );
169 CPPUNIT_ASSERT( str == "abcd ef" );
170 CPPUNIT_ASSERT( s.eof() );
171 }
172
err()173 void SstreamTest::err()
174 {
175 stringstream s( "9" );
176
177 int i = 0;
178 s >> i;
179 CPPUNIT_ASSERT( !s.fail() );
180 CPPUNIT_ASSERT( i == 9 );
181 s >> i;
182 CPPUNIT_ASSERT( s.fail() );
183 CPPUNIT_ASSERT( s.eof() );
184 CPPUNIT_ASSERT( i == 9 );
185 }
186
err_long()187 void SstreamTest::err_long()
188 {
189 stringstream s( "9" );
190
191 long i = 0;
192 s >> i;
193 CPPUNIT_ASSERT( !s.fail() );
194 CPPUNIT_ASSERT( i == 9 );
195 s >> i;
196 CPPUNIT_ASSERT( s.fail() );
197 CPPUNIT_ASSERT( s.eof() );
198 CPPUNIT_ASSERT( i == 9 );
199 }
200
maxint()201 void SstreamTest::maxint()
202 {
203 stringstream s;
204
205 s << INT_MAX << " " << UINT_MAX << " " << LONG_MAX << " " << ULONG_MAX << " "
206 << INT_MIN << " " << LONG_MIN;
207 CPPUNIT_ASSERT( s.good() );
208
209 int i = 0;
210 unsigned int u = 0;
211 long l = 0;
212 unsigned long ul = 0;
213
214 s >> i >> u >> l >> ul;
215 CPPUNIT_ASSERT( s.good() );
216 CPPUNIT_ASSERT( i == INT_MAX );
217 CPPUNIT_ASSERT( u == UINT_MAX );
218 CPPUNIT_ASSERT( l == LONG_MAX );
219 CPPUNIT_ASSERT( ul == ULONG_MAX );
220
221 s >> i >> l;
222 CPPUNIT_ASSERT( !s.fail() );
223 CPPUNIT_ASSERT( i == INT_MIN );
224 CPPUNIT_ASSERT( l == LONG_MIN );
225 }
226
init_in()227 void SstreamTest::init_in()
228 {
229 istringstream is( "12345" );
230 int n;
231
232 is >> n;
233 CPPUNIT_ASSERT( !is.fail() );
234 CPPUNIT_ASSERT( n == 12345 );
235
236 istringstream dis( "1.2345" );
237 double d;
238
239 dis >> d;
240 CPPUNIT_ASSERT( !dis.fail() );
241 CPPUNIT_ASSERT( are_equals(d, 1.2345) );
242
243 istringstream fis( "1.2345" );
244 float f;
245
246 fis >> f;
247 CPPUNIT_ASSERT( !fis.fail() );
248 CPPUNIT_ASSERT( are_equals(f, 1.2345f) );
249 }
250
init_out()251 void SstreamTest::init_out()
252 {
253 ostringstream os( "12345" );
254 CPPUNIT_ASSERT( os.str() == "12345" );
255
256 os << 67;
257 CPPUNIT_ASSERT( os.good() );
258
259 // This satisfy to the Standard:
260 // CPPUNIT_ASSERT( os.str() == "67345" );
261 // But we don't know the reason, why standard state that.
262
263 /*
264 * 27.7.1.1: ... then copies the content of str into the basic_sringbuf
265 * underlying character sequence and initializes the input and output
266 * sequences according to which. If which & ios_base::out is true, initializes
267 * the output sequence with underlying sequence. ...
268 *
269 * I can treat this as 'like output was performed', and then I should bump
270 * put pointer... Looks like more useful then my previous treatment.
271 *
272 * - ptr
273 */
274
275 CPPUNIT_ASSERT( os.str() == "1234567" );
276
277
278 os.str( "89ab" );
279 CPPUNIT_ASSERT( os.str() == "89ab" );
280
281 os << 10;
282 CPPUNIT_ASSERT( os.good() );
283 // CPPUNIT_ASSERT( os.str() == "10ab" );
284 CPPUNIT_ASSERT( os.str() == "89ab10" );
285 }
286
buf()287 void SstreamTest::buf()
288 {
289 stringstream ss;
290
291 ss << "1234567\n89\n";
292 char buf[10];
293 buf[7] = 'x';
294 ss.get( buf, 10 );
295 CPPUNIT_ASSERT( !ss.fail() );
296 CPPUNIT_ASSERT( buf[0] == '1' );
297 CPPUNIT_ASSERT( buf[1] == '2' );
298 CPPUNIT_ASSERT( buf[2] == '3' );
299 CPPUNIT_ASSERT( buf[3] == '4' );
300 CPPUNIT_ASSERT( buf[4] == '5' );
301 CPPUNIT_ASSERT( buf[5] == '6' );
302 CPPUNIT_ASSERT( buf[6] == '7' ); // 27.6.1.3 paragraph 10, paragraph 7
303 CPPUNIT_ASSERT( buf[7] == 0 ); // 27.6.1.3 paragraph 8
304 char c;
305 ss.get(c);
306 CPPUNIT_ASSERT( !ss.fail() );
307 CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 10, paragraph 7
308 ss.get(c);
309 CPPUNIT_ASSERT( !ss.fail() );
310 CPPUNIT_ASSERT( c == '8' );
311 }
312
rdbuf()313 void SstreamTest::rdbuf()
314 {
315 stringstream ss;
316
317 ss << "1234567\n89\n";
318
319 ostringstream os;
320 ss.get( *os.rdbuf(), '\n' );
321 CPPUNIT_ASSERT( !ss.fail() );
322 char c;
323 ss.get(c);
324 CPPUNIT_ASSERT( !ss.fail() );
325 CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 12
326 CPPUNIT_ASSERT( os.str() == "1234567" );
327 }
328
streambuf_output()329 void SstreamTest::streambuf_output()
330 {
331 {
332 istringstream in("01234567890123456789");
333 CPPUNIT_ASSERT( in );
334
335 full_streambuf full_buf(10);
336 ostream out(&full_buf);
337 CPPUNIT_ASSERT( out );
338
339 out << in.rdbuf();
340 CPPUNIT_ASSERT( out );
341 CPPUNIT_ASSERT( in );
342 //out is good we can check what has been extracted:
343 CPPUNIT_ASSERT( full_buf.str() == "0123456789" );
344
345 out << in.rdbuf();
346 CPPUNIT_ASSERT( out.fail() );
347 CPPUNIT_ASSERT( in );
348
349 ostringstream ostr;
350 ostr << in.rdbuf();
351 CPPUNIT_ASSERT( ostr );
352 CPPUNIT_ASSERT( in );
353 CPPUNIT_ASSERT( ostr.str() == "0123456789" );
354 }
355
356 # if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
357 {
358 //If the output stream buffer throws:
359 istringstream in("01234567890123456789");
360 CPPUNIT_ASSERT( in );
361
362 full_streambuf full_buf(10, true);
363 ostream out(&full_buf);
364 CPPUNIT_ASSERT( out );
365
366 out << in.rdbuf();
367 CPPUNIT_ASSERT( out.bad() );
368 CPPUNIT_ASSERT( in );
369 //out is bad we have no guaranty on what has been extracted:
370 //CPPUNIT_ASSERT( full_buf.str() == "0123456789" );
371
372 out.clear();
373 out << in.rdbuf();
374 CPPUNIT_ASSERT( out.fail() && out.bad() );
375 CPPUNIT_ASSERT( in );
376
377 ostringstream ostr;
378 ostr << in.rdbuf();
379 CPPUNIT_ASSERT( ostr );
380 CPPUNIT_ASSERT( in );
381 CPPUNIT_ASSERT( ostr.str() == "01234567890123456789" );
382 }
383 # endif
384 }
385
seek()386 void SstreamTest::seek()
387 {
388 stringstream s( "0123456789" );
389
390 CPPUNIT_ASSERT( s.tellg() == stringstream::pos_type(0) );
391 s.seekg( 6, ios::beg );
392 CPPUNIT_ASSERT( s.tellg() == stringstream::pos_type(6) );
393 s.seekg( -3, ios::cur );
394 CPPUNIT_ASSERT( s.tellg() == stringstream::pos_type(3) );
395
396 istringstream is( "0123456789" );
397 CPPUNIT_ASSERT( is.tellg() == stringstream::pos_type(0) );
398 is.seekg( 6, ios::beg );
399 CPPUNIT_ASSERT( is.tellg() == stringstream::pos_type(6) );
400 is.seekg( -3, ios::cur );
401 CPPUNIT_ASSERT( is.tellg() == stringstream::pos_type(3) );
402 }
403
seekp()404 void SstreamTest::seekp()
405 {
406 ostringstream s;
407
408 s << "1234567";
409 CPPUNIT_CHECK( s.tellp() == stringstream::pos_type(7) );
410 CPPUNIT_CHECK( s.str() == "1234567" );
411 s.seekp( 0 );
412 s << "X";
413 CPPUNIT_CHECK( s.str() == "X234567" );
414 s.seekp( 0, ios::beg );
415 s << "Y";
416 CPPUNIT_CHECK( s.str() == "Y234567" );
417 }
418
seek_gp()419 void SstreamTest::seek_gp()
420 {
421 stringstream ss( "1" );
422
423 /* ISO/IEC 14882 2003 (and 1998 too) assume change as get as put positions
424 with seekg and seekp (27.6.1.3, par 38; 27.6.2.4 par 2),
425 but this contradict to common practice and proposed draft N2588
426 (27.6.1.3, par 41; 27.6.2.5, par 4)
427
428 Now STLport implement (i.e. change behaviour ) the draft's point of view.
429 */
430
431 ss.seekg( 0, ios::beg );
432 ss.seekp( 0, ios::end );
433
434 ss << "2";
435
436 string str;
437
438 ss >> str;
439
440 /* CPPUNIT_CHECK( str == "2" ); --- according ISO/IEC 14882 2003 */
441 CPPUNIT_CHECK( str == "12" );
442 }
443
tellp()444 void SstreamTest::tellp()
445 {
446 {
447 ostringstream o( "1" );
448
449 o << "23456";
450
451 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == stringstream::pos_type(6) );
452 CPPUNIT_CHECK( o.tellp() == stringstream::pos_type(6) );
453 }
454 {
455 ostringstream o;
456
457 o << "123456";
458
459 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == stringstream::pos_type(6) );
460 CPPUNIT_CHECK( o.tellp() == stringstream::pos_type(6) );
461 }
462 {
463 ostringstream o( "1" );
464
465 o << "23456789";
466
467 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == stringstream::pos_type(9) );
468 CPPUNIT_CHECK( o.tellp() == stringstream::pos_type(9) );
469 }
470 }
471
472
473 template < class T >
to_string(const T & v)474 string to_string( const T& v )
475 {
476 ostringstream oss;
477 oss << v;
478 return oss.str();
479 }
480
negative()481 void SstreamTest::negative()
482 {
483 CPPUNIT_CHECK( to_string<int>(-1) == "-1" );
484 CPPUNIT_CHECK( to_string<long>(-1) == "-1" );
485 }
486
487 #endif
488