Branch data Line data Source code
# 1 : : // Copyright (c) 2012-2021 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : #include <fs.h>
# 6 : : #include <streams.h>
# 7 : : #include <test/util/setup_common.h>
# 8 : :
# 9 : : #include <boost/test/unit_test.hpp>
# 10 : :
# 11 : : using namespace std::string_literals;
# 12 : :
# 13 : : BOOST_FIXTURE_TEST_SUITE(streams_tests, BasicTestingSetup)
# 14 : :
# 15 : : BOOST_AUTO_TEST_CASE(streams_vector_writer)
# 16 : 2 : {
# 17 : 2 : unsigned char a(1);
# 18 : 2 : unsigned char b(2);
# 19 : 2 : unsigned char bytes[] = { 3, 4, 5, 6 };
# 20 : 2 : std::vector<unsigned char> vch;
# 21 : :
# 22 : : // Each test runs twice. Serializing a second time at the same starting
# 23 : : // point should yield the same results, even if the first test grew the
# 24 : : // vector.
# 25 : :
# 26 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, a, b);
# 27 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{1, 2}}));
# 28 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, a, b);
# 29 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{1, 2}}));
# 30 : 2 : vch.clear();
# 31 : :
# 32 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, b);
# 33 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2}}));
# 34 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, b);
# 35 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2}}));
# 36 : 2 : vch.clear();
# 37 : :
# 38 : 2 : vch.resize(5, 0);
# 39 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, b);
# 40 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2, 0}}));
# 41 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, b);
# 42 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2, 0}}));
# 43 : 2 : vch.clear();
# 44 : :
# 45 : 2 : vch.resize(4, 0);
# 46 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 3, a, b);
# 47 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 1, 2}}));
# 48 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 3, a, b);
# 49 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 1, 2}}));
# 50 : 2 : vch.clear();
# 51 : :
# 52 : 2 : vch.resize(4, 0);
# 53 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 4, a, b);
# 54 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
# 55 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 4, a, b);
# 56 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
# 57 : 2 : vch.clear();
# 58 : :
# 59 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
# 60 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
# 61 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
# 62 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
# 63 : 2 : vch.clear();
# 64 : :
# 65 : 2 : vch.resize(4, 8);
# 66 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
# 67 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
# 68 : 2 : CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
# 69 : 2 : BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
# 70 : 2 : vch.clear();
# 71 : 2 : }
# 72 : :
# 73 : : BOOST_AUTO_TEST_CASE(streams_vector_reader)
# 74 : 2 : {
# 75 : 2 : std::vector<unsigned char> vch = {1, 255, 3, 4, 5, 6};
# 76 : :
# 77 : 2 : SpanReader reader{SER_NETWORK, INIT_PROTO_VERSION, vch};
# 78 : 2 : BOOST_CHECK_EQUAL(reader.size(), 6U);
# 79 : 2 : BOOST_CHECK(!reader.empty());
# 80 : :
# 81 : : // Read a single byte as an unsigned char.
# 82 : 2 : unsigned char a;
# 83 : 2 : reader >> a;
# 84 : 2 : BOOST_CHECK_EQUAL(a, 1);
# 85 : 2 : BOOST_CHECK_EQUAL(reader.size(), 5U);
# 86 : 2 : BOOST_CHECK(!reader.empty());
# 87 : :
# 88 : : // Read a single byte as a signed char.
# 89 : 2 : signed char b;
# 90 : 2 : reader >> b;
# 91 : 2 : BOOST_CHECK_EQUAL(b, -1);
# 92 : 2 : BOOST_CHECK_EQUAL(reader.size(), 4U);
# 93 : 2 : BOOST_CHECK(!reader.empty());
# 94 : :
# 95 : : // Read a 4 bytes as an unsigned int.
# 96 : 2 : unsigned int c;
# 97 : 2 : reader >> c;
# 98 : 2 : BOOST_CHECK_EQUAL(c, 100992003U); // 3,4,5,6 in little-endian base-256
# 99 : 2 : BOOST_CHECK_EQUAL(reader.size(), 0U);
# 100 : 2 : BOOST_CHECK(reader.empty());
# 101 : :
# 102 : : // Reading after end of byte vector throws an error.
# 103 : 2 : signed int d;
# 104 : 2 : BOOST_CHECK_THROW(reader >> d, std::ios_base::failure);
# 105 : :
# 106 : : // Read a 4 bytes as a signed int from the beginning of the buffer.
# 107 : 2 : SpanReader new_reader{SER_NETWORK, INIT_PROTO_VERSION, vch};
# 108 : 2 : new_reader >> d;
# 109 : 2 : BOOST_CHECK_EQUAL(d, 67370753); // 1,255,3,4 in little-endian base-256
# 110 : 2 : BOOST_CHECK_EQUAL(new_reader.size(), 2U);
# 111 : 2 : BOOST_CHECK(!new_reader.empty());
# 112 : :
# 113 : : // Reading after end of byte vector throws an error even if the reader is
# 114 : : // not totally empty.
# 115 : 2 : BOOST_CHECK_THROW(new_reader >> d, std::ios_base::failure);
# 116 : 2 : }
# 117 : :
# 118 : : BOOST_AUTO_TEST_CASE(streams_vector_reader_rvalue)
# 119 : 2 : {
# 120 : 2 : std::vector<uint8_t> data{0x82, 0xa7, 0x31};
# 121 : 2 : SpanReader reader{SER_NETWORK, INIT_PROTO_VERSION, data};
# 122 : 2 : uint32_t varint = 0;
# 123 : : // Deserialize into r-value
# 124 : 2 : reader >> VARINT(varint);
# 125 : 2 : BOOST_CHECK_EQUAL(varint, 54321U);
# 126 : 2 : BOOST_CHECK(reader.empty());
# 127 : 2 : }
# 128 : :
# 129 : : BOOST_AUTO_TEST_CASE(bitstream_reader_writer)
# 130 : 2 : {
# 131 : 2 : CDataStream data(SER_NETWORK, INIT_PROTO_VERSION);
# 132 : :
# 133 : 2 : BitStreamWriter<CDataStream> bit_writer(data);
# 134 : 2 : bit_writer.Write(0, 1);
# 135 : 2 : bit_writer.Write(2, 2);
# 136 : 2 : bit_writer.Write(6, 3);
# 137 : 2 : bit_writer.Write(11, 4);
# 138 : 2 : bit_writer.Write(1, 5);
# 139 : 2 : bit_writer.Write(32, 6);
# 140 : 2 : bit_writer.Write(7, 7);
# 141 : 2 : bit_writer.Write(30497, 16);
# 142 : 2 : bit_writer.Flush();
# 143 : :
# 144 : 2 : CDataStream data_copy(data);
# 145 : 2 : uint32_t serialized_int1;
# 146 : 2 : data >> serialized_int1;
# 147 : 2 : BOOST_CHECK_EQUAL(serialized_int1, (uint32_t)0x7700C35A); // NOTE: Serialized as LE
# 148 : 2 : uint16_t serialized_int2;
# 149 : 2 : data >> serialized_int2;
# 150 : 2 : BOOST_CHECK_EQUAL(serialized_int2, (uint16_t)0x1072); // NOTE: Serialized as LE
# 151 : :
# 152 : 2 : BitStreamReader<CDataStream> bit_reader(data_copy);
# 153 : 2 : BOOST_CHECK_EQUAL(bit_reader.Read(1), 0U);
# 154 : 2 : BOOST_CHECK_EQUAL(bit_reader.Read(2), 2U);
# 155 : 2 : BOOST_CHECK_EQUAL(bit_reader.Read(3), 6U);
# 156 : 2 : BOOST_CHECK_EQUAL(bit_reader.Read(4), 11U);
# 157 : 2 : BOOST_CHECK_EQUAL(bit_reader.Read(5), 1U);
# 158 : 2 : BOOST_CHECK_EQUAL(bit_reader.Read(6), 32U);
# 159 : 2 : BOOST_CHECK_EQUAL(bit_reader.Read(7), 7U);
# 160 : 2 : BOOST_CHECK_EQUAL(bit_reader.Read(16), 30497U);
# 161 : 2 : BOOST_CHECK_THROW(bit_reader.Read(8), std::ios_base::failure);
# 162 : 2 : }
# 163 : :
# 164 : : BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
# 165 : 2 : {
# 166 : 2 : std::vector<std::byte> in;
# 167 : :
# 168 : : // Degenerate case
# 169 : 2 : {
# 170 : 2 : CDataStream ds{in, 0, 0};
# 171 : 2 : ds.Xor({0x00, 0x00});
# 172 : 2 : BOOST_CHECK_EQUAL(""s, ds.str());
# 173 : 2 : }
# 174 : :
# 175 : 2 : in.push_back(std::byte{0x0f});
# 176 : 2 : in.push_back(std::byte{0xf0});
# 177 : :
# 178 : : // Single character key
# 179 : 2 : {
# 180 : 2 : CDataStream ds{in, 0, 0};
# 181 : 2 : ds.Xor({0xff});
# 182 : 2 : BOOST_CHECK_EQUAL("\xf0\x0f"s, ds.str());
# 183 : 2 : }
# 184 : :
# 185 : : // Multi character key
# 186 : :
# 187 : 2 : in.clear();
# 188 : 2 : in.push_back(std::byte{0xf0});
# 189 : 2 : in.push_back(std::byte{0x0f});
# 190 : :
# 191 : 2 : {
# 192 : 2 : CDataStream ds{in, 0, 0};
# 193 : 2 : ds.Xor({0xff, 0x0f});
# 194 : 2 : BOOST_CHECK_EQUAL("\x0f\x00"s, ds.str());
# 195 : 2 : }
# 196 : 2 : }
# 197 : :
# 198 : : BOOST_AUTO_TEST_CASE(streams_buffered_file)
# 199 : 2 : {
# 200 : 2 : fs::path streams_test_filename = m_args.GetDataDirBase() / "streams_test_tmp";
# 201 : 2 : FILE* file = fsbridge::fopen(streams_test_filename, "w+b");
# 202 : :
# 203 : : // The value at each offset is the offset.
# 204 [ + + ]: 82 : for (uint8_t j = 0; j < 40; ++j) {
# 205 : 80 : fwrite(&j, 1, 1, file);
# 206 : 80 : }
# 207 : 2 : rewind(file);
# 208 : :
# 209 : : // The buffer size (second arg) must be greater than the rewind
# 210 : : // amount (third arg).
# 211 : 2 : try {
# 212 : 2 : CBufferedFile bfbad(file, 25, 25, 222, 333);
# 213 : 2 : BOOST_CHECK(false);
# 214 : 2 : } catch (const std::exception& e) {
# 215 : 2 : BOOST_CHECK(strstr(e.what(),
# 216 : 2 : "Rewind limit must be less than buffer size") != nullptr);
# 217 : 2 : }
# 218 : :
# 219 : : // The buffer is 25 bytes, allow rewinding 10 bytes.
# 220 : 2 : CBufferedFile bf(file, 25, 10, 222, 333);
# 221 : 2 : BOOST_CHECK(!bf.eof());
# 222 : :
# 223 : : // These two members have no functional effect.
# 224 : 2 : BOOST_CHECK_EQUAL(bf.GetType(), 222);
# 225 : 2 : BOOST_CHECK_EQUAL(bf.GetVersion(), 333);
# 226 : :
# 227 : 2 : uint8_t i;
# 228 : 2 : bf >> i;
# 229 : 2 : BOOST_CHECK_EQUAL(i, 0);
# 230 : 2 : bf >> i;
# 231 : 2 : BOOST_CHECK_EQUAL(i, 1);
# 232 : :
# 233 : : // After reading bytes 0 and 1, we're positioned at 2.
# 234 : 2 : BOOST_CHECK_EQUAL(bf.GetPos(), 2U);
# 235 : :
# 236 : : // Rewind to offset 0, ok (within the 10 byte window).
# 237 : 2 : BOOST_CHECK(bf.SetPos(0));
# 238 : 2 : bf >> i;
# 239 : 2 : BOOST_CHECK_EQUAL(i, 0);
# 240 : :
# 241 : : // We can go forward to where we've been, but beyond may fail.
# 242 : 2 : BOOST_CHECK(bf.SetPos(2));
# 243 : 2 : bf >> i;
# 244 : 2 : BOOST_CHECK_EQUAL(i, 2);
# 245 : :
# 246 : : // If you know the maximum number of bytes that should be
# 247 : : // read to deserialize the variable, you can limit the read
# 248 : : // extent. The current file offset is 3, so the following
# 249 : : // SetLimit() allows zero bytes to be read.
# 250 : 2 : BOOST_CHECK(bf.SetLimit(3));
# 251 : 2 : try {
# 252 : 2 : bf >> i;
# 253 : 2 : BOOST_CHECK(false);
# 254 : 2 : } catch (const std::exception& e) {
# 255 : 2 : BOOST_CHECK(strstr(e.what(),
# 256 : 2 : "Read attempted past buffer limit") != nullptr);
# 257 : 2 : }
# 258 : : // The default argument removes the limit completely.
# 259 : 2 : BOOST_CHECK(bf.SetLimit());
# 260 : : // The read position should still be at 3 (no change).
# 261 : 2 : BOOST_CHECK_EQUAL(bf.GetPos(), 3U);
# 262 : :
# 263 : : // Read from current offset, 3, forward until position 10.
# 264 [ + + ]: 16 : for (uint8_t j = 3; j < 10; ++j) {
# 265 : 14 : bf >> i;
# 266 : 14 : BOOST_CHECK_EQUAL(i, j);
# 267 : 14 : }
# 268 : 2 : BOOST_CHECK_EQUAL(bf.GetPos(), 10U);
# 269 : :
# 270 : : // We're guaranteed (just barely) to be able to rewind to zero.
# 271 : 2 : BOOST_CHECK(bf.SetPos(0));
# 272 : 2 : BOOST_CHECK_EQUAL(bf.GetPos(), 0U);
# 273 : 2 : bf >> i;
# 274 : 2 : BOOST_CHECK_EQUAL(i, 0);
# 275 : :
# 276 : : // We can set the position forward again up to the farthest
# 277 : : // into the stream we've been, but no farther. (Attempting
# 278 : : // to go farther may succeed, but it's not guaranteed.)
# 279 : 2 : BOOST_CHECK(bf.SetPos(10));
# 280 : 2 : bf >> i;
# 281 : 2 : BOOST_CHECK_EQUAL(i, 10);
# 282 : 2 : BOOST_CHECK_EQUAL(bf.GetPos(), 11U);
# 283 : :
# 284 : : // Now it's only guaranteed that we can rewind to offset 1
# 285 : : // (current read position, 11, minus rewind amount, 10).
# 286 : 2 : BOOST_CHECK(bf.SetPos(1));
# 287 : 2 : BOOST_CHECK_EQUAL(bf.GetPos(), 1U);
# 288 : 2 : bf >> i;
# 289 : 2 : BOOST_CHECK_EQUAL(i, 1);
# 290 : :
# 291 : : // We can stream into large variables, even larger than
# 292 : : // the buffer size.
# 293 : 2 : BOOST_CHECK(bf.SetPos(11));
# 294 : 2 : {
# 295 : 2 : uint8_t a[40 - 11];
# 296 : 2 : bf >> a;
# 297 [ + + ]: 60 : for (uint8_t j = 0; j < sizeof(a); ++j) {
# 298 : 58 : BOOST_CHECK_EQUAL(a[j], 11 + j);
# 299 : 58 : }
# 300 : 2 : }
# 301 : 2 : BOOST_CHECK_EQUAL(bf.GetPos(), 40U);
# 302 : :
# 303 : : // We've read the entire file, the next read should throw.
# 304 : 2 : try {
# 305 : 2 : bf >> i;
# 306 : 2 : BOOST_CHECK(false);
# 307 : 2 : } catch (const std::exception& e) {
# 308 : 2 : BOOST_CHECK(strstr(e.what(),
# 309 : 2 : "CBufferedFile::Fill: end of file") != nullptr);
# 310 : 2 : }
# 311 : : // Attempting to read beyond the end sets the EOF indicator.
# 312 : 2 : BOOST_CHECK(bf.eof());
# 313 : :
# 314 : : // Still at offset 40, we can go back 10, to 30.
# 315 : 2 : BOOST_CHECK_EQUAL(bf.GetPos(), 40U);
# 316 : 2 : BOOST_CHECK(bf.SetPos(30));
# 317 : 2 : bf >> i;
# 318 : 2 : BOOST_CHECK_EQUAL(i, 30);
# 319 : 2 : BOOST_CHECK_EQUAL(bf.GetPos(), 31U);
# 320 : :
# 321 : : // We're too far to rewind to position zero.
# 322 : 2 : BOOST_CHECK(!bf.SetPos(0));
# 323 : : // But we should now be positioned at least as far back as allowed
# 324 : : // by the rewind window (relative to our farthest read position, 40).
# 325 : 2 : BOOST_CHECK(bf.GetPos() <= 30);
# 326 : :
# 327 : : // We can explicitly close the file, or the destructor will do it.
# 328 : 2 : bf.fclose();
# 329 : :
# 330 : 2 : fs::remove(streams_test_filename);
# 331 : 2 : }
# 332 : :
# 333 : : BOOST_AUTO_TEST_CASE(streams_buffered_file_rand)
# 334 : 2 : {
# 335 : : // Make this test deterministic.
# 336 : 2 : SeedInsecureRand(SeedRand::ZEROS);
# 337 : :
# 338 : 2 : fs::path streams_test_filename = m_args.GetDataDirBase() / "streams_test_tmp";
# 339 [ + + ]: 102 : for (int rep = 0; rep < 50; ++rep) {
# 340 : 100 : FILE* file = fsbridge::fopen(streams_test_filename, "w+b");
# 341 : 100 : size_t fileSize = InsecureRandRange(256);
# 342 [ + + ]: 11592 : for (uint8_t i = 0; i < fileSize; ++i) {
# 343 : 11492 : fwrite(&i, 1, 1, file);
# 344 : 11492 : }
# 345 : 100 : rewind(file);
# 346 : :
# 347 : 100 : size_t bufSize = InsecureRandRange(300) + 1;
# 348 : 100 : size_t rewindSize = InsecureRandRange(bufSize);
# 349 : 100 : CBufferedFile bf(file, bufSize, rewindSize, 222, 333);
# 350 : 100 : size_t currentPos = 0;
# 351 : 100 : size_t maxPos = 0;
# 352 [ + + ]: 7444 : for (int step = 0; step < 100; ++step) {
# 353 [ + + ]: 7388 : if (currentPos >= fileSize)
# 354 : 44 : break;
# 355 : :
# 356 : : // We haven't read to the end of the file yet.
# 357 : 7344 : BOOST_CHECK(!bf.eof());
# 358 : 7344 : BOOST_CHECK_EQUAL(bf.GetPos(), currentPos);
# 359 : :
# 360 : : // Pretend the file consists of a series of objects of varying
# 361 : : // sizes; the boundaries of the objects can interact arbitrarily
# 362 : : // with the CBufferFile's internal buffer. These first three
# 363 : : // cases simulate objects of various sizes (1, 2, 5 bytes).
# 364 [ - + ]: 7344 : switch (InsecureRandRange(5)) {
# 365 [ + + ]: 1514 : case 0: {
# 366 : 1514 : uint8_t a[1];
# 367 [ - + ]: 1514 : if (currentPos + 1 > fileSize)
# 368 : 0 : continue;
# 369 : 1514 : bf.SetLimit(currentPos + 1);
# 370 : 1514 : bf >> a;
# 371 [ + + ]: 3028 : for (uint8_t i = 0; i < 1; ++i) {
# 372 : 1514 : BOOST_CHECK_EQUAL(a[i], currentPos);
# 373 : 1514 : currentPos++;
# 374 : 1514 : }
# 375 : 1514 : break;
# 376 : 1514 : }
# 377 [ + + ]: 1446 : case 1: {
# 378 : 1446 : uint8_t a[2];
# 379 [ + + ]: 1446 : if (currentPos + 2 > fileSize)
# 380 : 6 : continue;
# 381 : 1440 : bf.SetLimit(currentPos + 2);
# 382 : 1440 : bf >> a;
# 383 [ + + ]: 4320 : for (uint8_t i = 0; i < 2; ++i) {
# 384 : 2880 : BOOST_CHECK_EQUAL(a[i], currentPos);
# 385 : 2880 : currentPos++;
# 386 : 2880 : }
# 387 : 1440 : break;
# 388 : 1446 : }
# 389 [ + + ]: 1512 : case 2: {
# 390 : 1512 : uint8_t a[5];
# 391 [ + + ]: 1512 : if (currentPos + 5 > fileSize)
# 392 : 22 : continue;
# 393 : 1490 : bf.SetLimit(currentPos + 5);
# 394 : 1490 : bf >> a;
# 395 [ + + ]: 8940 : for (uint8_t i = 0; i < 5; ++i) {
# 396 : 7450 : BOOST_CHECK_EQUAL(a[i], currentPos);
# 397 : 7450 : currentPos++;
# 398 : 7450 : }
# 399 : 1490 : break;
# 400 : 1512 : }
# 401 [ + + ]: 1492 : case 3: {
# 402 : : // Find a byte value (that is at or ahead of the current position).
# 403 : 1492 : size_t find = currentPos + InsecureRandRange(8);
# 404 [ + + ]: 1492 : if (find >= fileSize)
# 405 : 10 : find = fileSize - 1;
# 406 : 1492 : bf.FindByte(uint8_t(find));
# 407 : : // The value at each offset is the offset.
# 408 : 1492 : BOOST_CHECK_EQUAL(bf.GetPos(), find);
# 409 : 1492 : currentPos = find;
# 410 : :
# 411 : 1492 : bf.SetLimit(currentPos + 1);
# 412 : 1492 : uint8_t i;
# 413 : 1492 : bf >> i;
# 414 : 1492 : BOOST_CHECK_EQUAL(i, currentPos);
# 415 : 1492 : currentPos++;
# 416 : 1492 : break;
# 417 : 1512 : }
# 418 [ + + ]: 1380 : case 4: {
# 419 : 1380 : size_t requestPos = InsecureRandRange(maxPos + 4);
# 420 : 1380 : bool okay = bf.SetPos(requestPos);
# 421 : : // The new position may differ from the requested position
# 422 : : // because we may not be able to rewind beyond the rewind
# 423 : : // window, and we may not be able to move forward beyond the
# 424 : : // farthest position we've reached so far.
# 425 : 1380 : currentPos = bf.GetPos();
# 426 : 1380 : BOOST_CHECK_EQUAL(okay, currentPos == requestPos);
# 427 : : // Check that we can position within the rewind window.
# 428 [ + + ]: 1380 : if (requestPos <= maxPos &&
# 429 [ + + ]: 1380 : maxPos > rewindSize &&
# 430 [ + + ]: 1380 : requestPos >= maxPos - rewindSize) {
# 431 : : // We requested a position within the rewind window.
# 432 : 220 : BOOST_CHECK(okay);
# 433 : 220 : }
# 434 : 1380 : break;
# 435 : 1512 : }
# 436 : 7344 : }
# 437 [ + + ]: 7316 : if (maxPos < currentPos)
# 438 : 2768 : maxPos = currentPos;
# 439 : 7316 : }
# 440 : 100 : }
# 441 : 2 : fs::remove(streams_test_filename);
# 442 : 2 : }
# 443 : :
# 444 : : BOOST_AUTO_TEST_SUITE_END()
|