Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
StreamTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
16#include "src/base/SkBuffer.h"
17#include "src/base/SkRandom.h"
18#include "src/core/SkOSFile.h"
20#include "src/utils/SkOSPath.h"
21#include "tests/Test.h"
22#include "tools/Resources.h"
23
24#include <algorithm>
25#include <climits>
26#include <cstdint>
27#include <cstdio>
28#include <cstring>
29#include <functional>
30#include <limits>
31#include <memory>
32#include <string>
33
34using namespace skia_private;
35
36#ifdef SK_ENABLE_ANDROID_UTILS
38#endif
39
40#ifndef SK_BUILD_FOR_WIN
41#include <fcntl.h>
42#endif
43
44#define MAX_SIZE (256 * 1024)
45
47 const void* src, size_t len, int repeat) {
48 SkAutoSMalloc<256> storage(len);
49 void* tmp = storage.get();
50
51 for (int i = 0; i < repeat; ++i) {
52 size_t bytes = stream->read(tmp, len);
53 REPORTER_ASSERT(reporter, bytes == len);
54 REPORTER_ASSERT(reporter, !memcmp(tmp, src, len));
55 }
56
57 // expect EOF
58 size_t bytes = stream->read(tmp, 1);
59 REPORTER_ASSERT(reporter, 0 == bytes);
60 // isAtEnd might not return true until after the first failing read.
61 REPORTER_ASSERT(reporter, stream->isAtEnd());
62}
63
64static void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) {
65 SkString path = SkOSPath::Join(tmpDir, "wstream_test");
66
67 const char s[] = "abcdefghijklmnopqrstuvwxyz";
68
69 {
70 SkFILEWStream writer(path.c_str());
71 if (!writer.isValid()) {
72 ERRORF(reporter, "Failed to create tmp file %s\n", path.c_str());
73 return;
74 }
75
76 for (int i = 0; i < 100; ++i) {
77 writer.write(s, 26);
78 }
79 }
80
81 {
82 SkFILEStream stream(path.c_str());
83 REPORTER_ASSERT(reporter, stream.isValid());
84 test_loop_stream(reporter, &stream, s, 26, 100);
85
86 std::unique_ptr<SkStreamAsset> stream2(stream.duplicate());
87 test_loop_stream(reporter, stream2.get(), s, 26, 100);
88 }
89
90 {
91 FILE* file = ::fopen(path.c_str(), "rb");
92 SkFILEStream stream(file);
93 REPORTER_ASSERT(reporter, stream.isValid());
94 test_loop_stream(reporter, &stream, s, 26, 100);
95
96 std::unique_ptr<SkStreamAsset> stream2(stream.duplicate());
97 test_loop_stream(reporter, stream2.get(), s, 26, 100);
98 }
99}
100
103 const char s[] = "abcdefghijklmnopqrstuvwxyz";
104 int i;
105 for (i = 0; i < 100; i++) {
107 }
108 REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26);
109
110 char* dst = new char[100 * 26 + 1];
111 dst[100*26] = '*';
112 ds.copyTo(dst);
113 REPORTER_ASSERT(reporter, dst[100*26] == '*');
114 for (i = 0; i < 100; i++) {
115 REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
116 }
117
118 {
119 std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream());
120 REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength());
122 test_loop_stream(reporter, stream.get(), s, 26, 100);
123
124 std::unique_ptr<SkStreamAsset> stream2(stream->duplicate());
125 test_loop_stream(reporter, stream2.get(), s, 26, 100);
126
127 std::unique_ptr<SkStreamAsset> stream3(stream->fork());
128 REPORTER_ASSERT(reporter, stream3->isAtEnd());
129 char tmp;
130 size_t bytes = stream->read(&tmp, 1);
131 REPORTER_ASSERT(reporter, 0 == bytes);
132 stream3->rewind();
133 test_loop_stream(reporter, stream3.get(), s, 26, 100);
134 }
135
136 for (i = 0; i < 100; i++) {
138 }
139 REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26);
140
141 {
142 // Test that this works after a snapshot.
143 std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream());
145 test_loop_stream(reporter, stream.get(), s, 26, 100);
146
147 std::unique_ptr<SkStreamAsset> stream2(stream->duplicate());
148 test_loop_stream(reporter, stream2.get(), s, 26, 100);
149 }
150 delete[] dst;
151
152 SkString tmpDir = skiatest::GetTmpDir();
153 if (!tmpDir.isEmpty()) {
155 }
156}
157
159 // we know that packeduint tries to write 1, 2 or 4 bytes for the length,
160 // so we test values around each of those transitions (and a few others)
161 const size_t sizes[] = {
162 0, 1, 2, 0xFC, 0xFD, 0xFE, 0xFF, 0x100, 0x101, 32767, 32768, 32769,
163 0xFFFD, 0xFFFE, 0xFFFF, 0x10000, 0x10001,
164 0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0x1000000, 0x1000001,
165 0x7FFFFFFE, 0x7FFFFFFF, 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF
166 };
167
168
169 size_t i;
171
172 for (i = 0; i < std::size(sizes); ++i) {
173 bool success = wstream.writePackedUInt(sizes[i]);
174 REPORTER_ASSERT(reporter, success);
175 }
176
177 std::unique_ptr<SkStreamAsset> rstream(wstream.detachAsStream());
178 for (i = 0; i < std::size(sizes); ++i) {
179 size_t n;
180 if (!rstream->readPackedUInt(&n)) {
181 ERRORF(reporter, "[%zu] sizes:%zx could not be read\n", i, sizes[i]);
182 }
183 if (sizes[i] != n) {
184 ERRORF(reporter, "[%zu] sizes:%zx != n:%zx\n", i, sizes[i], n);
185 }
186 }
187}
188
189// Test that setting an SkMemoryStream to a nullptr data does not result in a crash when calling
190// methods that access fData.
192 REPORTER_ASSERT(reporter, memStream->read(nullptr, 0) == 0);
193 // Reading non-zero bytes from an empty stream should cleanly read zero bytes.
194 char buf[1];
195 REPORTER_ASSERT(reporter, memStream->read(buf, sizeof(buf)) == 0);
196 memStream->getMemoryBase();
197 (void)memStream->getData();
198}
199
201 SkMemoryStream memStream(nullptr);
202 TestDereferencingData(reporter, &memStream);
203
204 memStream.setData(nullptr);
205 TestDereferencingData(reporter, &memStream);
206
207}
208
214
215#ifndef SK_BUILD_FOR_IOS
216/**
217 * Tests peeking and then reading the same amount. The two should provide the
218 * same results.
219 * Returns the amount successfully read minus the amount successfully peeked.
220 */
222 SkStream* stream, size_t bytesToPeek) {
223 // The rest of our tests won't be very interesting if bytesToPeek is zero.
224 REPORTER_ASSERT(reporter, bytesToPeek > 0);
225 SkAutoMalloc peekStorage(bytesToPeek);
226 SkAutoMalloc readStorage(bytesToPeek);
227 void* peekPtr = peekStorage.get();
228 void* readPtr = peekStorage.get();
229
230 const size_t bytesPeeked = stream->peek(peekPtr, bytesToPeek);
231 const size_t bytesRead = stream->read(readPtr, bytesToPeek);
232
233 // bytesRead should only be less than attempted if the stream is at the
234 // end.
235 REPORTER_ASSERT(reporter, bytesRead == bytesToPeek || stream->isAtEnd());
236
237 // peek and read should behave the same, except peek returned to the
238 // original position, so they read the same data.
239 REPORTER_ASSERT(reporter, !memcmp(peekPtr, readPtr, bytesPeeked));
240
241 // A stream should never be able to peek more than it can read.
242 REPORTER_ASSERT(reporter, bytesRead >= bytesPeeked);
243
244 return bytesRead - bytesPeeked;
245}
246
247static void test_fully_peekable_stream(skiatest::Reporter* r, SkStream* stream, size_t limit) {
248 for (size_t i = 1; !stream->isAtEnd(); i++) {
249 REPORTER_ASSERT(r, compare_peek_to_read(r, stream, i) == 0);
250 }
251}
252
253#ifdef SK_ENABLE_ANDROID_UTILS
254static void test_peeking_front_buffered_stream(skiatest::Reporter* r,
255 const SkStream& original,
256 size_t bufferSize) {
257 std::unique_ptr<SkStream> dupe(original.duplicate());
258 REPORTER_ASSERT(r, dupe != nullptr);
259 auto bufferedStream = android::skia::FrontBufferedStream::Make(
260 std::move(dupe), bufferSize);
261 REPORTER_ASSERT(r, bufferedStream != nullptr);
262
263 size_t peeked = 0;
264 for (size_t i = 1; !bufferedStream->isAtEnd(); i++) {
265 const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream.get(), i);
266 if (unpeekableBytes > 0) {
267 // This could not have returned a number greater than i.
268 REPORTER_ASSERT(r, unpeekableBytes <= i);
269
270 // We have reached the end of the buffer. Verify that it was at least
271 // bufferSize.
272 REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize);
273 // No more peeking is supported.
274 break;
275 }
276 peeked += i;
277 }
278
279 // Test that attempting to peek beyond the length of the buffer does not prevent rewinding.
280 bufferedStream = android::skia::FrontBufferedStream::Make(original.duplicate(), bufferSize);
281 REPORTER_ASSERT(r, bufferedStream != nullptr);
282
283 const size_t bytesToPeek = bufferSize + 1;
284 SkAutoMalloc peekStorage(bytesToPeek);
285 SkAutoMalloc readStorage(bytesToPeek);
286
287 for (size_t start = 0; start <= bufferSize; start++) {
288 // Skip to the starting point
289 REPORTER_ASSERT(r, bufferedStream->skip(start) == start);
290
291 const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek);
292 if (0 == bytesPeeked) {
293 // Peeking should only fail completely if we have read/skipped beyond the buffer.
294 REPORTER_ASSERT(r, start >= bufferSize);
295 break;
296 }
297
298 // Only read the amount that was successfully peeked.
299 const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked);
300 REPORTER_ASSERT(r, bytesRead == bytesPeeked);
301 REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked));
302
303 // This should be safe to rewind.
304 REPORTER_ASSERT(r, bufferedStream->rewind());
305 }
306}
307#endif
308
309// This test uses file system operations that don't work out of the
310// box on iOS. It's likely that we don't need them on iOS. Ignoring for now.
311// TODO(stephana): Re-evaluate if we need this in the future.
312DEF_TEST(StreamPeek, reporter) {
313 // Test a memory stream.
314 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz";
315 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
316 test_fully_peekable_stream(reporter, &memStream, memStream.getLength());
317
318 // Test an arbitrary file stream. file streams do not support peeking.
319 auto tmpdir = skiatest::GetTmpDir();
320 if (tmpdir.isEmpty()) {
321 ERRORF(reporter, "no tmp dir!");
322 return;
323 }
324 auto path = SkOSPath::Join(tmpdir.c_str(), "file");
325 {
326 SkFILEWStream wStream(path.c_str());
327 constexpr char filename[] = "images/baby_tux.webp";
328 auto data = GetResourceAsData(filename);
329 if (!data || data->size() == 0) {
330 ERRORF(reporter, "resource missing: %s\n", filename);
331 return;
332 }
333 if (!wStream.isValid() || !wStream.write(data->data(), data->size())) {
334 ERRORF(reporter, "error wrtiting to file %s", path.c_str());
335 return;
336 }
337 }
338 SkFILEStream fileStream(path.c_str());
339 REPORTER_ASSERT(reporter, fileStream.isValid());
340 if (!fileStream.isValid()) {
341 return;
342 }
343 SkAutoMalloc storage(fileStream.getLength());
344 for (size_t i = 1; i < fileStream.getLength(); i++) {
345 REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0);
346 }
347
348#ifdef SK_ENABLE_ANDROID_UTILS
349 // Now test some FrontBufferedStreams
350 for (size_t i = 1; i < memStream.getLength(); i++) {
351 test_peeking_front_buffered_stream(reporter, memStream, i);
352 }
353#endif
354}
355#endif
356
357// Asserts that asset == expected and is peekable.
359 SkStreamAsset* asset,
360 const SkData* expected) {
361 if (asset->getLength() != expected->size()) {
362 ERRORF(rep, "Unexpected length.");
363 return;
364 }
365 SkRandom rand;
366 uint8_t buffer[4096];
367 const uint8_t* expect = expected->bytes();
368 for (size_t i = 0; i < asset->getLength(); ++i) {
369 uint32_t maxSize =
370 SkToU32(std::min(sizeof(buffer), asset->getLength() - i));
371 size_t size = rand.nextRangeU(1, maxSize);
372 SkASSERT(size >= 1);
373 SkASSERT(size <= sizeof(buffer));
374 SkASSERT(size + i <= asset->getLength());
375 if (asset->peek(buffer, size) < size) {
376 ERRORF(rep, "Peek Failed!");
377 return;
378 }
379 if (0 != memcmp(buffer, &expect[i], size)) {
380 ERRORF(rep, "Peek returned wrong bytes!");
381 return;
382 }
383 uint8_t value;
384 REPORTER_ASSERT(rep, 1 == asset->read(&value, 1));
385 if (value != expect[i]) {
386 ERRORF(rep, "Read Failed!");
387 return;
388 }
389 }
390}
391
392DEF_TEST(StreamPeek_BlockMemoryStream, rep) {
393 const static int kSeed = 1234;
394 SkRandom valueSource(kSeed);
395 SkRandom rand(kSeed << 1);
396 uint8_t buffer[4096];
397 SkDynamicMemoryWStream dynamicMemoryWStream;
398 size_t totalWritten = 0;
399 for (int i = 0; i < 32; ++i) {
400 // Randomize the length of the blocks.
401 size_t size = rand.nextRangeU(1, sizeof(buffer));
402 for (size_t j = 0; j < size; ++j) {
403 buffer[j] = valueSource.nextU() & 0xFF;
404 }
405 dynamicMemoryWStream.write(buffer, size);
406 totalWritten += size;
407 REPORTER_ASSERT(rep, totalWritten == dynamicMemoryWStream.bytesWritten());
408 }
409 std::unique_ptr<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream());
410 sk_sp<SkData> expected(SkData::MakeUninitialized(asset->getLength()));
411 uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data());
412 valueSource.setSeed(kSeed); // reseed.
413 // We want the exact same same "random" string of numbers to put
414 // in expected. i.e.: don't rely on SkDynamicMemoryStream to work
415 // correctly while we are testing SkDynamicMemoryStream.
416 for (size_t i = 0; i < asset->getLength(); ++i) {
417 expectedPtr[i] = valueSource.nextU() & 0xFF;
418 }
419 stream_peek_test(rep, asset.get(), expected.get());
420}
421
422DEF_TEST(StreamRemainingLengthIsBelow_MemoryStream, rep) {
423 SkMemoryStream stream(100);
427
429 REPORTER_ASSERT(rep, StreamRemainingLengthIsBelow(&stream, ULONG_MAX));
430
431 uint8_t buff[75];
432 REPORTER_ASSERT(rep, stream.read(buff, 75) == 75);
433
437
440 REPORTER_ASSERT(rep, StreamRemainingLengthIsBelow(&stream, ULONG_MAX));
441}
442
443namespace {
444class DumbStream : public SkStream {
445public:
446 DumbStream(const uint8_t* data, size_t n)
447 : fData(data), fCount(n), fIdx(0) {}
448 size_t read(void* buffer, size_t size) override {
449 size_t copyCount = std::min(fCount - fIdx, size);
450 if (copyCount) {
451 memcpy(buffer, &fData[fIdx], copyCount);
452 fIdx += copyCount;
453 }
454 return copyCount;
455 }
456 bool isAtEnd() const override {
457 return fCount == fIdx;
458 }
459 private:
460 const uint8_t* fData;
461 size_t fCount, fIdx;
462};
463} // namespace
464
466 const void* srcData,
467 size_t N,
468 SkStream* stream) {
470 if (!SkStreamCopy(&tgt, stream)) {
471 ERRORF(reporter, "SkStreamCopy failed");
472 return;
473 }
474 sk_sp<SkData> data(tgt.detachAsData());
475 if (data->size() != N) {
476 ERRORF(reporter, "SkStreamCopy incorrect size");
477 return;
478 }
479 if (0 != memcmp(data->data(), srcData, N)) {
480 ERRORF(reporter, "SkStreamCopy bad copy");
481 }
482}
483
484DEF_TEST(DynamicMemoryWStream_detachAsData, r) {
485 const char az[] = "abcdefghijklmnopqrstuvwxyz";
486 const unsigned N = 40000;
488 for (unsigned i = 0; i < N; ++i) {
489 dmws.writeText(az);
490 }
491 REPORTER_ASSERT(r, dmws.bytesWritten() == N * strlen(az));
492 auto data = dmws.detachAsData();
493 REPORTER_ASSERT(r, data->size() == N * strlen(az));
494 const uint8_t* ptr = data->bytes();
495 for (unsigned i = 0; i < N; ++i) {
496 if (0 != memcmp(ptr, az, strlen(az))) {
497 ERRORF(r, "detachAsData() memcmp failed");
498 return;
499 }
500 ptr += strlen(az);
501 }
502}
503
504DEF_TEST(StreamCopy, reporter) {
505 SkRandom random(123456);
506 static const int N = 10000;
507 AutoTMalloc<uint8_t> src((size_t)N);
508 for (int j = 0; j < N; ++j) {
509 src[j] = random.nextU() & 0xff;
510 }
511 // SkStreamCopy had two code paths; this test both.
512 DumbStream dumbStream(src.get(), (size_t)N);
513 stream_copy_test(reporter, src, N, &dumbStream);
514 SkMemoryStream smartStream(src.get(), (size_t)N);
515 stream_copy_test(reporter, src, N, &smartStream);
516}
517
518DEF_TEST(StreamEmptyStreamMemoryBase, r) {
520 std::unique_ptr<SkStreamAsset> asset(tmp.detachAsStream());
521 REPORTER_ASSERT(r, nullptr == asset->getMemoryBase());
522}
523
524DEF_TEST(FILEStreamWithOffset, r) {
525 if (GetResourcePath().isEmpty()) {
526 return;
527 }
528
529 SkString filename = GetResourcePath("images/baby_tux.png");
530 SkFILEStream stream1(filename.c_str());
531 if (!stream1.isValid()) {
532 ERRORF(r, "Could not create SkFILEStream from %s", filename.c_str());
533 return;
534 }
535 REPORTER_ASSERT(r, stream1.hasLength());
536 REPORTER_ASSERT(r, stream1.hasPosition());
537
538 // Seek halfway through the file. The second SkFILEStream will be created
539 // with the same filename and offset and therefore will treat that offset as
540 // the beginning.
541 const size_t size = stream1.getLength();
542 const size_t middle = size / 2;
543 if (!stream1.seek(middle)) {
544 ERRORF(r, "Could not seek SkFILEStream to %zu out of %zu", middle, size);
545 return;
546 }
547 REPORTER_ASSERT(r, stream1.getPosition() == middle);
548
549 FILE* file = sk_fopen(filename.c_str(), kRead_SkFILE_Flag);
550 if (!file) {
551 ERRORF(r, "Could not open %s as a FILE", filename.c_str());
552 return;
553 }
554
555 if (fseek(file, (long) middle, SEEK_SET) != 0) {
556 ERRORF(r, "Could not fseek FILE to %zu out of %zu", middle, size);
557 return;
558 }
559 SkFILEStream stream2(file);
560
561 const size_t remaining = size - middle;
562 AutoTMalloc<uint8_t> expected(remaining);
563 REPORTER_ASSERT(r, stream1.read(expected.get(), remaining) == remaining);
564
565 auto test_full_read = [&r, &expected, remaining](SkStream* stream) {
566 AutoTMalloc<uint8_t> actual(remaining);
567 REPORTER_ASSERT(r, stream->read(actual.get(), remaining) == remaining);
568 REPORTER_ASSERT(r, !memcmp(expected.get(), actual.get(), remaining));
569
570 REPORTER_ASSERT(r, stream->getPosition() == stream->getLength());
571 REPORTER_ASSERT(r, stream->isAtEnd());
572 };
573
574 auto test_rewind = [&r, &expected, remaining](SkStream* stream) {
575 // Rewind goes back to original offset.
576 REPORTER_ASSERT(r, stream->rewind());
577 REPORTER_ASSERT(r, stream->getPosition() == 0);
578 AutoTMalloc<uint8_t> actual(remaining);
579 REPORTER_ASSERT(r, stream->read(actual.get(), remaining) == remaining);
580 REPORTER_ASSERT(r, !memcmp(expected.get(), actual.get(), remaining));
581 };
582
583 auto test_move = [&r, &expected, size, remaining](SkStream* stream) {
584 // Cannot move to before the original offset.
585 REPORTER_ASSERT(r, stream->move(- (long) size));
586 REPORTER_ASSERT(r, stream->getPosition() == 0);
587
588 REPORTER_ASSERT(r, stream->move(std::numeric_limits<long>::min()));
589 REPORTER_ASSERT(r, stream->getPosition() == 0);
590
591 AutoTMalloc<uint8_t> actual(remaining);
592 REPORTER_ASSERT(r, stream->read(actual.get(), remaining) == remaining);
593 REPORTER_ASSERT(r, !memcmp(expected.get(), actual.get(), remaining));
594
595 REPORTER_ASSERT(r, stream->isAtEnd());
596 REPORTER_ASSERT(r, stream->getPosition() == remaining);
597
598 // Cannot move beyond the end.
599 REPORTER_ASSERT(r, stream->move(1));
600 REPORTER_ASSERT(r, stream->isAtEnd());
601 REPORTER_ASSERT(r, stream->getPosition() == remaining);
602 };
603
604 auto test_seek = [&r, &expected, middle, remaining](SkStream* stream) {
605 // Seek to an arbitrary position.
606 const size_t arbitrary = middle / 2;
607 REPORTER_ASSERT(r, stream->seek(arbitrary));
608 REPORTER_ASSERT(r, stream->getPosition() == arbitrary);
609 const size_t miniRemaining = remaining - arbitrary;
610 AutoTMalloc<uint8_t> actual(miniRemaining);
611 REPORTER_ASSERT(r, stream->read(actual.get(), miniRemaining) == miniRemaining);
612 REPORTER_ASSERT(r, !memcmp(expected.get() + arbitrary, actual.get(), miniRemaining));
613 };
614
615 auto test_seek_beginning = [&r, &expected, remaining](SkStream* stream) {
616 // Seek to the beginning.
617 REPORTER_ASSERT(r, stream->seek(0));
618 REPORTER_ASSERT(r, stream->getPosition() == 0);
619 AutoTMalloc<uint8_t> actual(remaining);
620 REPORTER_ASSERT(r, stream->read(actual.get(), remaining) == remaining);
621 REPORTER_ASSERT(r, !memcmp(expected.get(), actual.get(), remaining));
622 };
623
624 auto test_seek_end = [&r, remaining](SkStream* stream) {
625 // Cannot seek past the end.
626 REPORTER_ASSERT(r, stream->isAtEnd());
627
628 REPORTER_ASSERT(r, stream->seek(remaining + 1));
629 REPORTER_ASSERT(r, stream->isAtEnd());
630 REPORTER_ASSERT(r, stream->getPosition() == remaining);
631
632 const size_t middle = remaining / 2;
633 REPORTER_ASSERT(r, stream->seek(middle));
634 REPORTER_ASSERT(r, !stream->isAtEnd());
635 REPORTER_ASSERT(r, stream->getPosition() == middle);
636
637 REPORTER_ASSERT(r, stream->seek(remaining * 2));
638 REPORTER_ASSERT(r, stream->isAtEnd());
639 REPORTER_ASSERT(r, stream->getPosition() == remaining);
640
641 REPORTER_ASSERT(r, stream->seek(std::numeric_limits<long>::max()));
642 REPORTER_ASSERT(r, stream->isAtEnd());
643 REPORTER_ASSERT(r, stream->getPosition() == remaining);
644 };
645
646
647 std::function<void (SkStream* stream, bool recurse)> test_all;
648 test_all = [&](SkStream* stream, bool recurse) {
649 REPORTER_ASSERT(r, stream->getLength() == remaining);
650 REPORTER_ASSERT(r, stream->getPosition() == 0);
651
652 test_full_read(stream);
653 test_rewind(stream);
654 test_move(stream);
655 test_seek(stream);
656 test_seek_beginning(stream);
657 test_seek_end(stream);
658
659 if (recurse) {
660 // Duplicate shares the original offset.
661 auto duplicate = stream->duplicate();
662 if (!duplicate) {
663 ERRORF(r, "Failed to duplicate the stream!");
664 } else {
665 test_all(duplicate.get(), false);
666 }
667
668 // Fork shares the original offset, too.
669 auto fork = stream->fork();
670 if (!fork) {
671 ERRORF(r, "Failed to fork the stream!");
672 } else {
673 REPORTER_ASSERT(r, fork->isAtEnd());
674 REPORTER_ASSERT(r, fork->getLength() == remaining);
675 REPORTER_ASSERT(r, fork->rewind());
676
677 test_all(fork.get(), false);
678 }
679 }
680 };
681
682 test_all(&stream2, true);
683}
684
686 int32_t value = 0;
688 REPORTER_ASSERT(reporter, buffer.isValid());
689
690 int32_t tmp;
691 REPORTER_ASSERT(reporter, buffer.read(&tmp, 4));
692 REPORTER_ASSERT(reporter, buffer.isValid());
693
694 REPORTER_ASSERT(reporter, !buffer.read(&tmp, 4));
695 REPORTER_ASSERT(reporter, !buffer.isValid());
696}
reporter
sk_sp< SkData > GetResourceAsData(const char *resource)
Definition Resources.cpp:42
SkString GetResourcePath(const char *resource)
Definition Resources.cpp:23
#define SkASSERT(cond)
Definition SkAssert.h:116
static unsigned repeat(SkFixed fx, int max)
FILE * sk_fopen(const char path[], SkFILE_Flags)
@ kRead_SkFILE_Flag
Definition SkOSFile.h:20
bool StreamRemainingLengthIsBelow(SkStream *stream, size_t len)
Definition SkStream.cpp:976
bool SkStreamCopy(SkWStream *out, SkStream *input)
Definition SkStream.cpp:954
constexpr uint32_t SkToU32(S x)
Definition SkTo.h:26
static void test_fully_peekable_stream(skiatest::Reporter *r, SkStream *stream, size_t limit)
static void TestWStream(skiatest::Reporter *reporter)
static void TestNullData(skiatest::Reporter *reporter)
static void TestDereferencingData(skiatest::Reporter *reporter, SkMemoryStream *memStream)
static void stream_peek_test(skiatest::Reporter *rep, SkStreamAsset *asset, const SkData *expected)
static size_t compare_peek_to_read(skiatest::Reporter *reporter, SkStream *stream, size_t bytesToPeek)
static void TestPackedUInt(skiatest::Reporter *reporter)
static void stream_copy_test(skiatest::Reporter *reporter, const void *srcData, size_t N, SkStream *stream)
static void test_loop_stream(skiatest::Reporter *reporter, SkStream *stream, const void *src, size_t len, int repeat)
static void test_filestreams(skiatest::Reporter *reporter, const char *tmpDir)
#define DEF_TEST(name, reporter)
Definition Test.h:312
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
#define ERRORF(r,...)
Definition Test.h:293
static void test_rewind(skiatest::Reporter *reporter)
#define N
Definition beziers.cpp:19
void * get()
void * get() const
const uint8_t * bytes() const
Definition SkData.h:43
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition SkData.cpp:116
size_t size() const
Definition SkData.h:30
size_t bytesWritten() const override
Definition SkStream.cpp:526
void copyTo(void *dst) const
Definition SkStream.cpp:631
std::unique_ptr< SkStreamAsset > detachAsStream()
Definition SkStream.cpp:876
bool write(const void *buffer, size_t size) override
Definition SkStream.cpp:535
sk_sp< SkData > detachAsData()
Definition SkStream.cpp:707
bool seek(size_t position) override
Definition SkStream.cpp:241
size_t read(void *buffer, size_t size) override
Definition SkStream.cpp:205
bool isValid() const
Definition SkStream.h:320
size_t getLength() const override
Definition SkStream.cpp:270
size_t getPosition() const override
Definition SkStream.cpp:236
bool write(const void *buffer, size_t size) override
Definition SkStream.cpp:426
bool isValid() const
Definition SkStream.h:442
sk_sp< SkData > getData() const override
Definition SkStream.h:395
size_t read(void *buffer, size_t size) override
Definition SkStream.cpp:337
size_t getLength() const override
Definition SkStream.cpp:395
const void * getMemoryBase() override
Definition SkStream.cpp:399
void setData(sk_sp< SkData > data)
Definition SkStream.cpp:328
static SkString Join(const char *rootPath, const char *relativePath)
Definition SkOSPath.cpp:14
uint32_t nextU()
Definition SkRandom.h:42
void setSeed(uint32_t seed)
Definition SkRandom.h:128
uint32_t nextRangeU(uint32_t min, uint32_t max)
Definition SkRandom.h:80
bool hasLength() const override
Definition SkStream.h:188
size_t getLength() const override=0
bool hasPosition() const override
Definition SkStream.h:172
std::unique_ptr< SkStream > duplicate() const
Definition SkStream.h:105
virtual size_t peek(void *, size_t) const
Definition SkStream.h:68
virtual bool isAtEnd() const =0
virtual size_t read(void *buffer, size_t size)=0
bool isEmpty() const
Definition SkString.h:130
const char * c_str() const
Definition SkString.h:133
bool writePackedUInt(size_t)
Definition SkStream.cpp:122
bool writeText(const char text[])
Definition SkStream.h:247
static std::unique_ptr< SkStreamRewindable > Make(std::unique_ptr< SkStream > stream, size_t minBufferSize)
T * get() const
Definition SkRefCnt.h:303
struct MyStruct s
static const uint8_t buffer[]
uint8_t value
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
SkString GetTmpDir()
Definition Test.cpp:53