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 15 : 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 2 : CPPUNIT_TEST_SUITE(Test);
33 1 : CPPUNIT_TEST(test_stdstream);
34 1 : CPPUNIT_TEST(test_fastostring);
35 1 : CPPUNIT_TEST(test_read_cstring);
36 1 : CPPUNIT_TEST(test_read_pstring);
37 1 : CPPUNIT_TEST(test_readline);
38 5 : CPPUNIT_TEST_SUITE_END();
39 : };
40 :
41 1 : void Test::test_stdstream()
42 : {
43 1 : char foo[] = "foo";
44 1 : std::istringstream iss(foo, std::istringstream::in);
45 2 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, StreamMode::READ);
46 :
47 1 : char std_a(78);
48 1 : iss >> std_a;
49 1 : CPPUNIT_ASSERT(std_a == 'f');
50 :
51 1 : char tools_a(78);
52 1 : aMemStream.ReadChar( tools_a );
53 1 : CPPUNIT_ASSERT(tools_a == 'f');
54 :
55 1 : iss.seekg(0, std::ios_base::end);
56 : //seeking to end doesn't set eof, reading past eof does
57 1 : CPPUNIT_ASSERT(!iss.eof());
58 1 : CPPUNIT_ASSERT(iss.good());
59 :
60 1 : aMemStream.Seek(STREAM_SEEK_TO_END);
61 : //seeking to end doesn't set eof, reading past eof does
62 1 : CPPUNIT_ASSERT(!aMemStream.eof());
63 1 : CPPUNIT_ASSERT(aMemStream.good());
64 :
65 1 : std_a = 78;
66 1 : iss >> std_a;
67 : //so, now eof is set
68 1 : CPPUNIT_ASSERT(iss.eof());
69 : //a failed read doesn't change the data, it remains unchanged
70 1 : CPPUNIT_ASSERT(std_a == 78);
71 : //nothing wrong with the stream, so not bad
72 1 : CPPUNIT_ASSERT(!iss.bad());
73 : //yet, the read didn't succeed
74 1 : CPPUNIT_ASSERT(!iss.good());
75 1 : CPPUNIT_ASSERT(iss.rdstate() == (std::ios::failbit|std::ios::eofbit));
76 :
77 1 : tools_a = 78;
78 1 : aMemStream.ReadChar( tools_a );
79 : //so, now eof is set
80 1 : CPPUNIT_ASSERT(aMemStream.eof());
81 : //a failed read doesn't change the data, it remains unchanged
82 1 : CPPUNIT_ASSERT(tools_a == 78);
83 : //nothing wrong with the stream, so not bad
84 1 : CPPUNIT_ASSERT(!aMemStream.bad());
85 : //yet, the read didn't succeed
86 1 : 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 1 : sal_uInt16 tools_b = 0x1122;
92 1 : aMemStream.SeekRel(-1);
93 1 : CPPUNIT_ASSERT(!aMemStream.eof());
94 1 : CPPUNIT_ASSERT(aMemStream.good());
95 1 : aMemStream.ReadUInt16( tools_b );
96 1 : CPPUNIT_ASSERT(!aMemStream.good());
97 1 : CPPUNIT_ASSERT(aMemStream.eof());
98 1 : CPPUNIT_ASSERT(tools_b == 0x1122);
99 :
100 1 : iss.clear();
101 1 : iss.seekg(0);
102 1 : CPPUNIT_ASSERT(iss.good());
103 1 : iss >> std_a;
104 1 : CPPUNIT_ASSERT(std_a == 'f');
105 :
106 1 : aMemStream.Seek(0);
107 1 : CPPUNIT_ASSERT(aMemStream.good());
108 1 : aMemStream.ReadChar( tools_a );
109 1 : CPPUNIT_ASSERT(tools_a == 'f');
110 :
111 : //failbit is rather subtle wrt e.g seeks
112 :
113 : char buffer[1024];
114 :
115 1 : iss.clear();
116 1 : iss.seekg(0);
117 1 : CPPUNIT_ASSERT(iss.good());
118 1 : iss.read(buffer, sizeof(buffer));
119 1 : CPPUNIT_ASSERT(iss.gcount() == 3);
120 1 : CPPUNIT_ASSERT(!iss.good());
121 1 : CPPUNIT_ASSERT(!iss.bad());
122 1 : CPPUNIT_ASSERT(iss.eof());
123 :
124 1 : aMemStream.Seek(0);
125 1 : CPPUNIT_ASSERT(aMemStream.good());
126 1 : sal_Size nRet = aMemStream.Read(buffer, sizeof(buffer));
127 1 : CPPUNIT_ASSERT(nRet == 3);
128 1 : CPPUNIT_ASSERT(!aMemStream.good());
129 1 : CPPUNIT_ASSERT(!aMemStream.bad());
130 2 : CPPUNIT_ASSERT(aMemStream.eof());
131 1 : }
132 :
133 1 : void Test::test_fastostring()
134 : {
135 1 : char foo[] = "foobar";
136 1 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, StreamMode::READ);
137 :
138 2 : OString aOne = read_uInt8s_ToOString(aMemStream, 3);
139 1 : CPPUNIT_ASSERT(aOne == "foo");
140 :
141 2 : OString aTwo = read_uInt8s_ToOString(aMemStream, 3);
142 1 : CPPUNIT_ASSERT(aTwo == "bar");
143 :
144 2 : OString aThree = read_uInt8s_ToOString(aMemStream, 3);
145 1 : CPPUNIT_ASSERT(aThree.isEmpty());
146 :
147 1 : aMemStream.Seek(0);
148 :
149 2 : OString aFour = read_uInt8s_ToOString(aMemStream, 100);
150 2 : CPPUNIT_ASSERT(aFour == foo);
151 1 : }
152 :
153 1 : void Test::test_read_cstring()
154 : {
155 1 : char foo[] = "foobar";
156 1 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, StreamMode::READ);
157 :
158 2 : OString aOne = read_zeroTerminated_uInt8s_ToOString(aMemStream);
159 1 : CPPUNIT_ASSERT(aOne == "foobar");
160 1 : CPPUNIT_ASSERT(!aMemStream.good());
161 1 : CPPUNIT_ASSERT(!aMemStream.bad());
162 1 : CPPUNIT_ASSERT(aMemStream.eof());
163 :
164 1 : aMemStream.Seek(0);
165 1 : foo[3] = 0;
166 2 : OString aTwo = read_zeroTerminated_uInt8s_ToOString(aMemStream);
167 1 : CPPUNIT_ASSERT(aTwo == "foo");
168 2 : CPPUNIT_ASSERT(aMemStream.good());
169 1 : }
170 :
171 1 : void Test::test_read_pstring()
172 : {
173 1 : char foo[] = "\3foobar";
174 1 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, StreamMode::READ);
175 :
176 2 : OString aFoo = read_uInt8_lenPrefixed_uInt8s_ToOString(aMemStream);
177 1 : CPPUNIT_ASSERT(aFoo == "foo");
178 1 : CPPUNIT_ASSERT(aMemStream.good());
179 1 : CPPUNIT_ASSERT(!aMemStream.bad());
180 1 : CPPUNIT_ASSERT(!aMemStream.eof());
181 :
182 1 : aMemStream.Seek(0);
183 1 : foo[0] = 10;
184 1 : aFoo = read_uInt8_lenPrefixed_uInt8s_ToOString(aMemStream);
185 1 : CPPUNIT_ASSERT(aFoo == "foobar");
186 1 : CPPUNIT_ASSERT(!aMemStream.good());
187 1 : CPPUNIT_ASSERT(!aMemStream.bad());
188 1 : CPPUNIT_ASSERT(aMemStream.eof());
189 :
190 1 : aMemStream.SetEndian(SvStreamEndian::BIG);
191 1 : aMemStream.Seek(0);
192 1 : foo[0] = 0;
193 1 : foo[1] = 3;
194 1 : aFoo = read_uInt16_lenPrefixed_uInt8s_ToOString(aMemStream);
195 1 : CPPUNIT_ASSERT(aFoo == "oob");
196 1 : CPPUNIT_ASSERT(aMemStream.good());
197 1 : CPPUNIT_ASSERT(!aMemStream.bad());
198 1 : CPPUNIT_ASSERT(!aMemStream.eof());
199 :
200 1 : aMemStream.SetEndian(SvStreamEndian::LITTLE);
201 1 : aMemStream.Seek(0);
202 1 : foo[0] = 3;
203 1 : foo[1] = 0;
204 1 : foo[2] = 0;
205 1 : foo[3] = 0;
206 1 : aFoo = read_uInt32_lenPrefixed_uInt8s_ToOString(aMemStream);
207 1 : CPPUNIT_ASSERT(aFoo == "bar");
208 1 : CPPUNIT_ASSERT(aMemStream.good());
209 1 : CPPUNIT_ASSERT(!aMemStream.bad());
210 2 : CPPUNIT_ASSERT(!aMemStream.eof());
211 1 : }
212 :
213 1 : void Test::test_readline()
214 : {
215 1 : char foo[] = "foo\nbar\n\n";
216 1 : SvMemoryStream aMemStream(foo, SAL_N_ELEMENTS(foo)-1, StreamMode::READ);
217 :
218 2 : OString aFoo;
219 : bool bRet;
220 :
221 1 : bRet = aMemStream.ReadLine(aFoo);
222 1 : CPPUNIT_ASSERT(bRet);
223 1 : CPPUNIT_ASSERT(aFoo == "foo");
224 1 : CPPUNIT_ASSERT(aMemStream.good());
225 :
226 1 : bRet = aMemStream.ReadLine(aFoo);
227 1 : CPPUNIT_ASSERT(bRet);
228 1 : CPPUNIT_ASSERT(aFoo == "bar");
229 1 : CPPUNIT_ASSERT(aMemStream.good());
230 :
231 1 : bRet = aMemStream.ReadLine(aFoo);
232 1 : CPPUNIT_ASSERT(bRet);
233 1 : CPPUNIT_ASSERT(aFoo.isEmpty());
234 1 : CPPUNIT_ASSERT(aMemStream.good());
235 :
236 1 : bRet = aMemStream.ReadLine(aFoo);
237 1 : CPPUNIT_ASSERT(!bRet);
238 1 : CPPUNIT_ASSERT(aFoo.isEmpty());
239 1 : CPPUNIT_ASSERT(aMemStream.eof());
240 :
241 1 : foo[3] = 0; //test reading embedded nulls
242 :
243 1 : aMemStream.Seek(0);
244 1 : bRet = aMemStream.ReadLine(aFoo);
245 1 : CPPUNIT_ASSERT(bRet);
246 1 : CPPUNIT_ASSERT(aFoo.getLength() == 7 && aFoo[3] == 0);
247 1 : CPPUNIT_ASSERT(aMemStream.good());
248 :
249 2 : std::string sStr(foo, RTL_CONSTASCII_LENGTH(foo));
250 2 : std::istringstream iss(sStr, std::istringstream::in);
251 1 : std::getline(iss, sStr, '\n');
252 : //embedded null read as expected
253 1 : CPPUNIT_ASSERT(sStr.size() == 7 && sStr[3] == 0);
254 1 : CPPUNIT_ASSERT(iss.good());
255 :
256 1 : bRet = aMemStream.ReadLine(aFoo);
257 1 : CPPUNIT_ASSERT(bRet);
258 1 : CPPUNIT_ASSERT(aFoo.isEmpty());
259 1 : CPPUNIT_ASSERT(aMemStream.good());
260 :
261 1 : std::getline(iss, sStr, '\n');
262 1 : CPPUNIT_ASSERT(sStr.empty());
263 1 : CPPUNIT_ASSERT(iss.good());
264 :
265 1 : bRet = aMemStream.ReadLine(aFoo);
266 1 : CPPUNIT_ASSERT(!bRet);
267 1 : CPPUNIT_ASSERT(aFoo.isEmpty());
268 1 : CPPUNIT_ASSERT(aMemStream.eof() && !aMemStream.bad());
269 :
270 1 : std::getline(iss, sStr, '\n');
271 1 : CPPUNIT_ASSERT(sStr.empty());
272 1 : CPPUNIT_ASSERT(iss.eof() && !iss.bad());
273 :
274 1 : char bar[] = "foo";
275 2 : SvMemoryStream aMemStreamB(bar, SAL_N_ELEMENTS(bar)-1, StreamMode::READ);
276 1 : bRet = aMemStreamB.ReadLine(aFoo);
277 1 : CPPUNIT_ASSERT(bRet);
278 1 : CPPUNIT_ASSERT(aFoo == "foo");
279 1 : CPPUNIT_ASSERT(!aMemStreamB.eof()); //<-- diff A
280 :
281 2 : std::istringstream issB(bar, std::istringstream::in);
282 1 : std::getline(issB, sStr, '\n');
283 1 : CPPUNIT_ASSERT(sStr == "foo");
284 2 : CPPUNIT_ASSERT(issB.eof()); //<-- diff A
285 1 : }
286 :
287 1 : CPPUNIT_TEST_SUITE_REGISTRATION(Test);
288 3 : }
289 :
290 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|