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