Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include <sal/types.h>
11 : #include "cppunit/TestAssert.h"
12 : #include "cppunit/TestFixture.h"
13 : #include "cppunit/extensions/HelperMacros.h"
14 : #include "cppunit/plugin/TestPlugIn.h"
15 : #include <tools/stream.hxx>
16 : #include <sstream>
17 :
18 : //Tests for eofbit/badbit/goodbit/failbit
19 :
20 : namespace
21 : {
22 :
23 30 : class Test: public CppUnit::TestFixture
24 : {
25 : public:
26 : void test_stdstream();
27 : void test_fastostring();
28 : void test_read_cstring();
29 : void test_read_pstring();
30 : void test_readline();
31 :
32 4 : CPPUNIT_TEST_SUITE(Test);
33 2 : CPPUNIT_TEST(test_stdstream);
34 2 : CPPUNIT_TEST(test_fastostring);
35 2 : CPPUNIT_TEST(test_read_cstring);
36 2 : CPPUNIT_TEST(test_read_pstring);
37 2 : CPPUNIT_TEST(test_readline);
38 4 : CPPUNIT_TEST_SUITE_END();
39 : };
40 :
41 2 : void Test::test_stdstream()
42 : {
43 2 : char foo[] = "foo";
44 2 : std::istringstream iss(foo, std::istringstream::in);
45 4 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, STREAM_READ);
46 :
47 2 : char std_a(78);
48 2 : iss >> std_a;
49 2 : CPPUNIT_ASSERT(std_a == 'f');
50 :
51 2 : char tools_a(78);
52 2 : aMemStream.ReadChar( tools_a );
53 2 : CPPUNIT_ASSERT(tools_a == 'f');
54 :
55 2 : iss.seekg(0, std::ios_base::end);
56 : //seeking to end doesn't set eof, reading past eof does
57 2 : CPPUNIT_ASSERT(!iss.eof());
58 2 : CPPUNIT_ASSERT(iss.good());
59 :
60 2 : aMemStream.Seek(STREAM_SEEK_TO_END);
61 : //seeking to end doesn't set eof, reading past eof does
62 2 : CPPUNIT_ASSERT(!aMemStream.eof());
63 2 : CPPUNIT_ASSERT(aMemStream.good());
64 :
65 2 : std_a = 78;
66 2 : iss >> std_a;
67 : //so, now eof is set
68 2 : CPPUNIT_ASSERT(iss.eof());
69 : //a failed read doesn't change the data, it remains unchanged
70 2 : CPPUNIT_ASSERT(std_a == 78);
71 : //nothing wrong with the stream, so not bad
72 2 : CPPUNIT_ASSERT(!iss.bad());
73 : //yet, the read didn't succeed
74 2 : CPPUNIT_ASSERT(!iss.good());
75 2 : CPPUNIT_ASSERT(iss.rdstate() == (std::ios::failbit|std::ios::eofbit));
76 :
77 2 : tools_a = 78;
78 2 : aMemStream.ReadChar( tools_a );
79 : //so, now eof is set
80 2 : CPPUNIT_ASSERT(aMemStream.eof());
81 : //a failed read doesn't change the data, it remains unchanged
82 2 : CPPUNIT_ASSERT(tools_a == 78);
83 : //nothing wrong with the stream, so not bad
84 2 : CPPUNIT_ASSERT(!aMemStream.bad());
85 : //yet, the read didn't succeed
86 2 : CPPUNIT_ASSERT(!aMemStream.good());
87 :
88 : //set things up so that there is only one byte available on an attempt
89 : //to read a two-byte sal_uInt16. The byte should be consumed, but the
90 : //operation should fail, and tools_b should remain unchanged,
91 2 : sal_uInt16 tools_b = 0x1122;
92 2 : aMemStream.SeekRel(-1);
93 2 : CPPUNIT_ASSERT(!aMemStream.eof());
94 2 : CPPUNIT_ASSERT(aMemStream.good());
95 2 : aMemStream.ReadUInt16( tools_b );
96 2 : CPPUNIT_ASSERT(!aMemStream.good());
97 2 : CPPUNIT_ASSERT(aMemStream.eof());
98 2 : CPPUNIT_ASSERT(tools_b == 0x1122);
99 :
100 2 : iss.clear();
101 2 : iss.seekg(0);
102 2 : CPPUNIT_ASSERT(iss.good());
103 2 : iss >> std_a;
104 2 : CPPUNIT_ASSERT(std_a == 'f');
105 :
106 2 : aMemStream.Seek(0);
107 2 : CPPUNIT_ASSERT(aMemStream.good());
108 2 : aMemStream.ReadChar( tools_a );
109 2 : CPPUNIT_ASSERT(tools_a == 'f');
110 :
111 : //failbit is rather subtle wrt e.g seeks
112 :
113 : char buffer[1024];
114 :
115 2 : iss.clear();
116 2 : iss.seekg(0);
117 2 : CPPUNIT_ASSERT(iss.good());
118 2 : iss.read(buffer, sizeof(buffer));
119 2 : CPPUNIT_ASSERT(iss.gcount() == 3);
120 2 : CPPUNIT_ASSERT(!iss.good());
121 2 : CPPUNIT_ASSERT(!iss.bad());
122 2 : CPPUNIT_ASSERT(iss.eof());
123 :
124 2 : aMemStream.Seek(0);
125 2 : CPPUNIT_ASSERT(aMemStream.good());
126 2 : sal_Size nRet = aMemStream.Read(buffer, sizeof(buffer));
127 2 : CPPUNIT_ASSERT(nRet == 3);
128 2 : CPPUNIT_ASSERT(!aMemStream.good());
129 2 : CPPUNIT_ASSERT(!aMemStream.bad());
130 4 : CPPUNIT_ASSERT(aMemStream.eof());
131 2 : }
132 :
133 2 : void Test::test_fastostring()
134 : {
135 2 : char foo[] = "foobar";
136 2 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, STREAM_READ);
137 :
138 4 : OString aOne = read_uInt8s_ToOString(aMemStream, 3);
139 2 : CPPUNIT_ASSERT(aOne == "foo");
140 :
141 4 : OString aTwo = read_uInt8s_ToOString(aMemStream, 3);
142 2 : CPPUNIT_ASSERT(aTwo == "bar");
143 :
144 4 : OString aThree = read_uInt8s_ToOString(aMemStream, 3);
145 2 : CPPUNIT_ASSERT(aThree.isEmpty());
146 :
147 2 : aMemStream.Seek(0);
148 :
149 4 : OString aFour = read_uInt8s_ToOString(aMemStream, 100);
150 4 : CPPUNIT_ASSERT(aFour == foo);
151 2 : }
152 :
153 2 : void Test::test_read_cstring()
154 : {
155 2 : char foo[] = "foobar";
156 2 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, STREAM_READ);
157 :
158 4 : OString aOne = read_zeroTerminated_uInt8s_ToOString(aMemStream);
159 2 : CPPUNIT_ASSERT(aOne == "foobar");
160 2 : CPPUNIT_ASSERT(!aMemStream.good());
161 2 : CPPUNIT_ASSERT(!aMemStream.bad());
162 2 : CPPUNIT_ASSERT(aMemStream.eof());
163 :
164 2 : aMemStream.Seek(0);
165 2 : foo[3] = 0;
166 4 : OString aTwo = read_zeroTerminated_uInt8s_ToOString(aMemStream);
167 2 : CPPUNIT_ASSERT(aTwo == "foo");
168 4 : CPPUNIT_ASSERT(aMemStream.good());
169 2 : }
170 :
171 2 : void Test::test_read_pstring()
172 : {
173 2 : char foo[] = "\3foobar";
174 2 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, STREAM_READ);
175 :
176 4 : OString aFoo = read_uInt8_lenPrefixed_uInt8s_ToOString(aMemStream);
177 2 : CPPUNIT_ASSERT(aFoo == "foo");
178 2 : CPPUNIT_ASSERT(aMemStream.good());
179 2 : CPPUNIT_ASSERT(!aMemStream.bad());
180 2 : CPPUNIT_ASSERT(!aMemStream.eof());
181 :
182 2 : aMemStream.Seek(0);
183 2 : foo[0] = 10;
184 2 : aFoo = read_uInt8_lenPrefixed_uInt8s_ToOString(aMemStream);
185 2 : CPPUNIT_ASSERT(aFoo == "foobar");
186 2 : CPPUNIT_ASSERT(!aMemStream.good());
187 2 : CPPUNIT_ASSERT(!aMemStream.bad());
188 2 : CPPUNIT_ASSERT(aMemStream.eof());
189 :
190 2 : aMemStream.SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN);
191 2 : aMemStream.Seek(0);
192 2 : foo[0] = 0;
193 2 : foo[1] = 3;
194 2 : aFoo = read_uInt16_lenPrefixed_uInt8s_ToOString(aMemStream);
195 2 : CPPUNIT_ASSERT(aFoo == "oob");
196 2 : CPPUNIT_ASSERT(aMemStream.good());
197 2 : CPPUNIT_ASSERT(!aMemStream.bad());
198 2 : CPPUNIT_ASSERT(!aMemStream.eof());
199 :
200 2 : aMemStream.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
201 2 : aMemStream.Seek(0);
202 2 : foo[0] = 3;
203 2 : foo[1] = 0;
204 2 : foo[2] = 0;
205 2 : foo[3] = 0;
206 2 : aFoo = read_uInt32_lenPrefixed_uInt8s_ToOString(aMemStream);
207 2 : CPPUNIT_ASSERT(aFoo == "bar");
208 2 : CPPUNIT_ASSERT(aMemStream.good());
209 2 : CPPUNIT_ASSERT(!aMemStream.bad());
210 4 : CPPUNIT_ASSERT(!aMemStream.eof());
211 2 : }
212 :
213 2 : void Test::test_readline()
214 : {
215 2 : char foo[] = "foo\nbar\n\n";
216 2 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, STREAM_READ);
217 :
218 4 : OString aFoo;
219 : bool bRet;
220 :
221 2 : bRet = aMemStream.ReadLine(aFoo);
222 2 : CPPUNIT_ASSERT(bRet);
223 2 : CPPUNIT_ASSERT(aFoo == "foo");
224 2 : CPPUNIT_ASSERT(aMemStream.good());
225 :
226 2 : bRet = aMemStream.ReadLine(aFoo);
227 2 : CPPUNIT_ASSERT(bRet);
228 2 : CPPUNIT_ASSERT(aFoo == "bar");
229 2 : CPPUNIT_ASSERT(aMemStream.good());
230 :
231 2 : bRet = aMemStream.ReadLine(aFoo);
232 2 : CPPUNIT_ASSERT(bRet);
233 2 : CPPUNIT_ASSERT(aFoo.isEmpty());
234 2 : CPPUNIT_ASSERT(aMemStream.good());
235 :
236 2 : bRet = aMemStream.ReadLine(aFoo);
237 2 : CPPUNIT_ASSERT(!bRet);
238 2 : CPPUNIT_ASSERT(aFoo.isEmpty());
239 2 : CPPUNIT_ASSERT(aMemStream.eof());
240 :
241 2 : foo[3] = 0; //test reading embedded nulls
242 :
243 2 : aMemStream.Seek(0);
244 2 : bRet = aMemStream.ReadLine(aFoo);
245 2 : CPPUNIT_ASSERT(bRet);
246 2 : CPPUNIT_ASSERT(aFoo.getLength() == 7 && aFoo[3] == 0);
247 2 : CPPUNIT_ASSERT(aMemStream.good());
248 :
249 4 : std::string sStr(foo, RTL_CONSTASCII_LENGTH(foo));
250 4 : std::istringstream iss(sStr, std::istringstream::in);
251 2 : std::getline(iss, sStr, '\n');
252 : //embedded null read as expected
253 2 : CPPUNIT_ASSERT(sStr.size() == 7 && sStr[3] == 0);
254 2 : CPPUNIT_ASSERT(iss.good());
255 :
256 2 : bRet = aMemStream.ReadLine(aFoo);
257 2 : CPPUNIT_ASSERT(bRet);
258 2 : CPPUNIT_ASSERT(aFoo.isEmpty());
259 2 : CPPUNIT_ASSERT(aMemStream.good());
260 :
261 2 : std::getline(iss, sStr, '\n');
262 2 : CPPUNIT_ASSERT(sStr.empty());
263 2 : CPPUNIT_ASSERT(iss.good());
264 :
265 2 : bRet = aMemStream.ReadLine(aFoo);
266 2 : CPPUNIT_ASSERT(!bRet);
267 2 : CPPUNIT_ASSERT(aFoo.isEmpty());
268 2 : CPPUNIT_ASSERT(aMemStream.eof() && !aMemStream.bad());
269 :
270 2 : std::getline(iss, sStr, '\n');
271 2 : CPPUNIT_ASSERT(sStr.empty());
272 2 : CPPUNIT_ASSERT(iss.eof() && !iss.bad());
273 :
274 2 : char bar[] = "foo";
275 4 : SvMemoryStream aMemStreamB(bar, SAL_N_ELEMENTS(bar)-1, STREAM_READ);
276 2 : bRet = aMemStreamB.ReadLine(aFoo);
277 2 : CPPUNIT_ASSERT(bRet);
278 2 : CPPUNIT_ASSERT(aFoo == "foo");
279 2 : CPPUNIT_ASSERT(!aMemStreamB.eof()); //<-- diff A
280 :
281 4 : std::istringstream issB(bar, std::istringstream::in);
282 2 : std::getline(issB, sStr, '\n');
283 2 : CPPUNIT_ASSERT(sStr == "foo");
284 4 : CPPUNIT_ASSERT(issB.eof()); //<-- diff A
285 2 : }
286 :
287 2 : CPPUNIT_TEST_SUITE_REGISTRATION(Test);
288 6 : }
289 :
290 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|