blob: fba09c989a1ae2c6258f66b5fb691d61edd30a32 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +00007
scroggo028a4132015-04-02 13:19:51 -07008#include "Resources.h"
Hal Canary95e3c052017-01-11 12:44:43 -05009#include "SkAutoMalloc.h"
reed@google.com8d0b5772011-06-24 13:07:31 +000010#include "SkData.h"
scroggo028a4132015-04-02 13:19:51 -070011#include "SkFrontBufferedStream.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000012#include "SkOSFile.h"
Ben Wagnerbf111d72016-11-07 18:05:29 -050013#include "SkOSPath.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000014#include "SkRandom.h"
15#include "SkStream.h"
halcanary48305e82015-08-18 13:30:25 -070016#include "SkStreamPriv.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000017#include "Test.h"
reed@android.com5e5adfd2009-03-07 03:39:23 +000018
reed@google.com789c6f22013-02-25 20:24:24 +000019#ifndef SK_BUILD_FOR_WIN
20#include <unistd.h>
21#include <fcntl.h>
22#endif
23
reed@android.com5e5adfd2009-03-07 03:39:23 +000024#define MAX_SIZE (256 * 1024)
25
reed@google.com789c6f22013-02-25 20:24:24 +000026static void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream,
27 const void* src, size_t len, int repeat) {
28 SkAutoSMalloc<256> storage(len);
29 void* tmp = storage.get();
30
31 for (int i = 0; i < repeat; ++i) {
32 size_t bytes = stream->read(tmp, len);
33 REPORTER_ASSERT(reporter, bytes == len);
34 REPORTER_ASSERT(reporter, !memcmp(tmp, src, len));
35 }
36
37 // expect EOF
38 size_t bytes = stream->read(tmp, 1);
39 REPORTER_ASSERT(reporter, 0 == bytes);
bungeman@google.com88682b72013-07-19 13:55:41 +000040 // isAtEnd might not return true until after the first failing read.
41 REPORTER_ASSERT(reporter, stream->isAtEnd());
reed@google.com789c6f22013-02-25 20:24:24 +000042}
43
44static void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) {
tfarinaa8e2e152014-07-28 19:26:58 -070045 SkString path = SkOSPath::Join(tmpDir, "wstream_test");
reed@google.com789c6f22013-02-25 20:24:24 +000046
47 const char s[] = "abcdefghijklmnopqrstuvwxyz";
48
49 {
50 SkFILEWStream writer(path.c_str());
51 if (!writer.isValid()) {
halcanary@google.coma9325fa2014-01-10 14:58:10 +000052 ERRORF(reporter, "Failed to create tmp file %s\n", path.c_str());
reed@google.com789c6f22013-02-25 20:24:24 +000053 return;
54 }
55
56 for (int i = 0; i < 100; ++i) {
57 writer.write(s, 26);
58 }
59 }
60
61 {
62 SkFILEStream stream(path.c_str());
63 REPORTER_ASSERT(reporter, stream.isValid());
64 test_loop_stream(reporter, &stream, s, 26, 100);
bungeman@google.com6cab1a42013-05-29 13:43:31 +000065
Ben Wagner145dbcd2016-11-03 14:40:50 -040066 std::unique_ptr<SkStreamAsset> stream2(stream.duplicate());
bungeman@google.com6cab1a42013-05-29 13:43:31 +000067 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com789c6f22013-02-25 20:24:24 +000068 }
69
reed@google.com789c6f22013-02-25 20:24:24 +000070 {
bungeman@google.com6cab1a42013-05-29 13:43:31 +000071 FILE* file = ::fopen(path.c_str(), "rb");
72 SkFILEStream stream(file, SkFILEStream::kCallerPasses_Ownership);
reed@google.com789c6f22013-02-25 20:24:24 +000073 REPORTER_ASSERT(reporter, stream.isValid());
74 test_loop_stream(reporter, &stream, s, 26, 100);
bungeman@google.com6cab1a42013-05-29 13:43:31 +000075
Ben Wagner145dbcd2016-11-03 14:40:50 -040076 std::unique_ptr<SkStreamAsset> stream2(stream.duplicate());
bungeman@google.com6cab1a42013-05-29 13:43:31 +000077 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com789c6f22013-02-25 20:24:24 +000078 }
reed@google.com789c6f22013-02-25 20:24:24 +000079}
80
reed@android.com80e39a72009-04-02 16:59:40 +000081static void TestWStream(skiatest::Reporter* reporter) {
82 SkDynamicMemoryWStream ds;
83 const char s[] = "abcdefghijklmnopqrstuvwxyz";
84 int i;
85 for (i = 0; i < 100; i++) {
86 REPORTER_ASSERT(reporter, ds.write(s, 26));
reed@android.com5e5adfd2009-03-07 03:39:23 +000087 }
Ben Wagner884300d2016-12-16 16:51:41 +000088 REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26);
bungeman@google.com88682b72013-07-19 13:55:41 +000089
reed@android.com80e39a72009-04-02 16:59:40 +000090 char* dst = new char[100 * 26 + 1];
91 dst[100*26] = '*';
92 ds.copyTo(dst);
93 REPORTER_ASSERT(reporter, dst[100*26] == '*');
reed@android.com80e39a72009-04-02 16:59:40 +000094 for (i = 0; i < 100; i++) {
95 REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
reed@android.com5e5adfd2009-03-07 03:39:23 +000096 }
reed@google.com70442a62011-06-23 21:48:04 +000097
98 {
Ben Wagner145dbcd2016-11-03 14:40:50 -040099 std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream());
bungeman@google.com88682b72013-07-19 13:55:41 +0000100 REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength());
Ben Wagner884300d2016-12-16 16:51:41 +0000101 REPORTER_ASSERT(reporter, ds.bytesWritten() == 0);
bungeman@google.com88682b72013-07-19 13:55:41 +0000102 test_loop_stream(reporter, stream.get(), s, 26, 100);
103
Ben Wagner145dbcd2016-11-03 14:40:50 -0400104 std::unique_ptr<SkStreamAsset> stream2(stream->duplicate());
bungeman@google.com88682b72013-07-19 13:55:41 +0000105 test_loop_stream(reporter, stream2.get(), s, 26, 100);
106
Ben Wagner145dbcd2016-11-03 14:40:50 -0400107 std::unique_ptr<SkStreamAsset> stream3(stream->fork());
bungeman@google.com88682b72013-07-19 13:55:41 +0000108 REPORTER_ASSERT(reporter, stream3->isAtEnd());
109 char tmp;
110 size_t bytes = stream->read(&tmp, 1);
111 REPORTER_ASSERT(reporter, 0 == bytes);
112 stream3->rewind();
113 test_loop_stream(reporter, stream3.get(), s, 26, 100);
114 }
115
116 for (i = 0; i < 100; i++) {
117 REPORTER_ASSERT(reporter, ds.write(s, 26));
118 }
Ben Wagner884300d2016-12-16 16:51:41 +0000119 REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26);
bungeman@google.com88682b72013-07-19 13:55:41 +0000120
121 {
reed42943c82016-09-12 12:01:44 -0700122 // Test that this works after a snapshot.
Ben Wagner145dbcd2016-11-03 14:40:50 -0400123 std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream());
Ben Wagner884300d2016-12-16 16:51:41 +0000124 REPORTER_ASSERT(reporter, ds.bytesWritten() == 0);
bungeman@google.com88682b72013-07-19 13:55:41 +0000125 test_loop_stream(reporter, stream.get(), s, 26, 100);
126
Ben Wagner145dbcd2016-11-03 14:40:50 -0400127 std::unique_ptr<SkStreamAsset> stream2(stream->duplicate());
bungeman@google.com88682b72013-07-19 13:55:41 +0000128 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com70442a62011-06-23 21:48:04 +0000129 }
reed@android.com80e39a72009-04-02 16:59:40 +0000130 delete[] dst;
reed@google.com789c6f22013-02-25 20:24:24 +0000131
halcanary87f3ba42015-01-20 09:30:20 -0800132 SkString tmpDir = skiatest::GetTmpDir();
scroggo@google.comc76218d2013-06-06 14:59:56 +0000133 if (!tmpDir.isEmpty()) {
134 test_filestreams(reporter, tmpDir.c_str());
reed@google.com789c6f22013-02-25 20:24:24 +0000135 }
reed@android.com5e5adfd2009-03-07 03:39:23 +0000136}
137
reed@google.com19f286b2011-10-18 11:49:52 +0000138static void TestPackedUInt(skiatest::Reporter* reporter) {
139 // we know that packeduint tries to write 1, 2 or 4 bytes for the length,
140 // so we test values around each of those transitions (and a few others)
141 const size_t sizes[] = {
142 0, 1, 2, 0xFC, 0xFD, 0xFE, 0xFF, 0x100, 0x101, 32767, 32768, 32769,
143 0xFFFD, 0xFFFE, 0xFFFF, 0x10000, 0x10001,
144 0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0x1000000, 0x1000001,
145 0x7FFFFFFE, 0x7FFFFFFF, 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF
146 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000147
148
reed@google.com19f286b2011-10-18 11:49:52 +0000149 size_t i;
Mike Reedff80c2a2017-01-07 11:16:28 -0500150 SkDynamicMemoryWStream wstream;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000151
reed@google.com19f286b2011-10-18 11:49:52 +0000152 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
153 bool success = wstream.writePackedUInt(sizes[i]);
154 REPORTER_ASSERT(reporter, success);
155 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000156
Mike Reedff80c2a2017-01-07 11:16:28 -0500157 std::unique_ptr<SkStreamAsset> rstream(wstream.detachAsStream());
reed@google.com19f286b2011-10-18 11:49:52 +0000158 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
Mike Reedff80c2a2017-01-07 11:16:28 -0500159 size_t n = rstream->readPackedUInt();
reed@google.com19f286b2011-10-18 11:49:52 +0000160 if (sizes[i] != n) {
halcanary7d571242016-02-24 17:59:16 -0800161 ERRORF(reporter, "sizes:%x != n:%x\n", i, sizes[i], n);
reed@google.com19f286b2011-10-18 11:49:52 +0000162 }
reed@google.com19f286b2011-10-18 11:49:52 +0000163 }
164}
165
halcanary96fcdcc2015-08-27 07:41:13 -0700166// Test that setting an SkMemoryStream to a nullptr data does not result in a crash when calling
scroggo@google.come4904202013-01-09 22:02:58 +0000167// methods that access fData.
168static void TestDereferencingData(SkMemoryStream* memStream) {
halcanary96fcdcc2015-08-27 07:41:13 -0700169 memStream->read(nullptr, 0);
scroggo@google.come4904202013-01-09 22:02:58 +0000170 memStream->getMemoryBase();
reed42943c82016-09-12 12:01:44 -0700171 (void)memStream->asData();
scroggo@google.come4904202013-01-09 22:02:58 +0000172}
173
174static void TestNullData() {
reed42943c82016-09-12 12:01:44 -0700175 SkMemoryStream memStream(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000176 TestDereferencingData(&memStream);
177
reed42943c82016-09-12 12:01:44 -0700178 memStream.setData(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000179 TestDereferencingData(&memStream);
180
181}
182
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000183DEF_TEST(Stream, reporter) {
reed@android.com5e5adfd2009-03-07 03:39:23 +0000184 TestWStream(reporter);
reed@google.com19f286b2011-10-18 11:49:52 +0000185 TestPackedUInt(reporter);
scroggo@google.come4904202013-01-09 22:02:58 +0000186 TestNullData();
reed@android.com5e5adfd2009-03-07 03:39:23 +0000187}
scroggo028a4132015-04-02 13:19:51 -0700188
Mike Klein7d302882016-11-03 14:06:31 -0400189#ifndef SK_BUILD_FOR_IOS
scroggo028a4132015-04-02 13:19:51 -0700190/**
191 * Tests peeking and then reading the same amount. The two should provide the
192 * same results.
scroggod61c3842015-12-07 11:37:13 -0800193 * Returns the amount successfully read minus the amount successfully peeked.
scroggo028a4132015-04-02 13:19:51 -0700194 */
scroggod61c3842015-12-07 11:37:13 -0800195static size_t compare_peek_to_read(skiatest::Reporter* reporter,
196 SkStream* stream, size_t bytesToPeek) {
scroggo028a4132015-04-02 13:19:51 -0700197 // The rest of our tests won't be very interesting if bytesToPeek is zero.
198 REPORTER_ASSERT(reporter, bytesToPeek > 0);
199 SkAutoMalloc peekStorage(bytesToPeek);
200 SkAutoMalloc readStorage(bytesToPeek);
201 void* peekPtr = peekStorage.get();
202 void* readPtr = peekStorage.get();
203
scroggod61c3842015-12-07 11:37:13 -0800204 const size_t bytesPeeked = stream->peek(peekPtr, bytesToPeek);
scroggo028a4132015-04-02 13:19:51 -0700205 const size_t bytesRead = stream->read(readPtr, bytesToPeek);
206
207 // bytesRead should only be less than attempted if the stream is at the
208 // end.
209 REPORTER_ASSERT(reporter, bytesRead == bytesToPeek || stream->isAtEnd());
210
211 // peek and read should behave the same, except peek returned to the
212 // original position, so they read the same data.
scroggod61c3842015-12-07 11:37:13 -0800213 REPORTER_ASSERT(reporter, !memcmp(peekPtr, readPtr, bytesPeeked));
scroggo028a4132015-04-02 13:19:51 -0700214
scroggod61c3842015-12-07 11:37:13 -0800215 // A stream should never be able to peek more than it can read.
216 REPORTER_ASSERT(reporter, bytesRead >= bytesPeeked);
217
218 return bytesRead - bytesPeeked;
scroggo028a4132015-04-02 13:19:51 -0700219}
220
scroggod61c3842015-12-07 11:37:13 -0800221static void test_fully_peekable_stream(skiatest::Reporter* r, SkStream* stream, size_t limit) {
scroggo028a4132015-04-02 13:19:51 -0700222 for (size_t i = 1; !stream->isAtEnd(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800223 REPORTER_ASSERT(r, compare_peek_to_read(r, stream, i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700224 }
225}
226
227static void test_peeking_front_buffered_stream(skiatest::Reporter* r,
228 const SkStream& original,
229 size_t bufferSize) {
230 SkStream* dupe = original.duplicate();
halcanary96fcdcc2015-08-27 07:41:13 -0700231 REPORTER_ASSERT(r, dupe != nullptr);
Ben Wagner145dbcd2016-11-03 14:40:50 -0400232 std::unique_ptr<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize));
halcanary96fcdcc2015-08-27 07:41:13 -0700233 REPORTER_ASSERT(r, bufferedStream != nullptr);
scroggod61c3842015-12-07 11:37:13 -0800234
235 size_t peeked = 0;
236 for (size_t i = 1; !bufferedStream->isAtEnd(); i++) {
Ben Wagner145dbcd2016-11-03 14:40:50 -0400237 const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream.get(), i);
scroggod61c3842015-12-07 11:37:13 -0800238 if (unpeekableBytes > 0) {
239 // This could not have returned a number greater than i.
240 REPORTER_ASSERT(r, unpeekableBytes <= i);
241
242 // We have reached the end of the buffer. Verify that it was at least
243 // bufferSize.
244 REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize);
245 // No more peeking is supported.
246 break;
247 }
248 peeked += i;
249 }
250
251 // Test that attempting to peek beyond the length of the buffer does not prevent rewinding.
252 bufferedStream.reset(SkFrontBufferedStream::Create(original.duplicate(), bufferSize));
253 REPORTER_ASSERT(r, bufferedStream != nullptr);
254
255 const size_t bytesToPeek = bufferSize + 1;
256 SkAutoMalloc peekStorage(bytesToPeek);
257 SkAutoMalloc readStorage(bytesToPeek);
258
259 for (size_t start = 0; start <= bufferSize; start++) {
260 // Skip to the starting point
261 REPORTER_ASSERT(r, bufferedStream->skip(start) == start);
scroggod61c3842015-12-07 11:37:13 -0800262
263 const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek);
264 if (0 == bytesPeeked) {
scroggoef0fed32016-02-18 05:59:25 -0800265 // Peeking should only fail completely if we have read/skipped beyond the buffer.
266 REPORTER_ASSERT(r, start >= bufferSize);
scroggod61c3842015-12-07 11:37:13 -0800267 break;
268 }
269
270 // Only read the amount that was successfully peeked.
271 const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked);
272 REPORTER_ASSERT(r, bytesRead == bytesPeeked);
273 REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked));
274
275 // This should be safe to rewind.
276 REPORTER_ASSERT(r, bufferedStream->rewind());
277 }
scroggo028a4132015-04-02 13:19:51 -0700278}
279
halcanary9d524f22016-03-29 09:03:52 -0700280// This test uses file system operations that don't work out of the
281// box on iOS. It's likely that we don't need them on iOS. Ignoring for now.
282// TODO(stephana): Re-evaluate if we need this in the future.
scroggo028a4132015-04-02 13:19:51 -0700283DEF_TEST(StreamPeek, reporter) {
284 // Test a memory stream.
285 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz";
286 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
scroggod61c3842015-12-07 11:37:13 -0800287 test_fully_peekable_stream(reporter, &memStream, memStream.getLength());
scroggo028a4132015-04-02 13:19:51 -0700288
289 // Test an arbitrary file stream. file streams do not support peeking.
290 SkFILEStream fileStream(GetResourcePath("baby_tux.webp").c_str());
291 REPORTER_ASSERT(reporter, fileStream.isValid());
caryclark30ac4642015-04-14 06:08:04 -0700292 if (!fileStream.isValid()) {
293 return;
294 }
scroggo028a4132015-04-02 13:19:51 -0700295 SkAutoMalloc storage(fileStream.getLength());
296 for (size_t i = 1; i < fileStream.getLength(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800297 REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700298 }
299
300 // Now test some FrontBufferedStreams
301 for (size_t i = 1; i < memStream.getLength(); i++) {
302 test_peeking_front_buffered_stream(reporter, memStream, i);
303 }
304}
halcanarye797d0d2015-05-21 08:13:27 -0700305#endif
306
307// Asserts that asset == expected and is peekable.
308static void stream_peek_test(skiatest::Reporter* rep,
309 SkStreamAsset* asset,
310 const SkData* expected) {
311 if (asset->getLength() != expected->size()) {
312 ERRORF(rep, "Unexpected length.");
313 return;
314 }
315 SkRandom rand;
316 uint8_t buffer[4096];
317 const uint8_t* expect = expected->bytes();
318 for (size_t i = 0; i < asset->getLength(); ++i) {
319 uint32_t maxSize =
320 SkToU32(SkTMin(sizeof(buffer), asset->getLength() - i));
321 size_t size = rand.nextRangeU(1, maxSize);
322 SkASSERT(size >= 1);
323 SkASSERT(size <= sizeof(buffer));
324 SkASSERT(size + i <= asset->getLength());
scroggod61c3842015-12-07 11:37:13 -0800325 if (asset->peek(buffer, size) < size) {
halcanarye797d0d2015-05-21 08:13:27 -0700326 ERRORF(rep, "Peek Failed!");
327 return;
328 }
329 if (0 != memcmp(buffer, &expect[i], size)) {
330 ERRORF(rep, "Peek returned wrong bytes!");
331 return;
332 }
333 uint8_t value;
334 REPORTER_ASSERT(rep, 1 == asset->read(&value, 1));
335 if (value != expect[i]) {
336 ERRORF(rep, "Read Failed!");
337 return;
338 }
339 }
340}
341
342DEF_TEST(StreamPeek_BlockMemoryStream, rep) {
343 const static int kSeed = 1234;
344 SkRandom valueSource(kSeed);
345 SkRandom rand(kSeed << 1);
346 uint8_t buffer[4096];
347 SkDynamicMemoryWStream dynamicMemoryWStream;
Mike Reed49282292016-12-14 12:34:06 -0500348 size_t totalWritten = 0;
halcanarye797d0d2015-05-21 08:13:27 -0700349 for (int i = 0; i < 32; ++i) {
350 // Randomize the length of the blocks.
351 size_t size = rand.nextRangeU(1, sizeof(buffer));
352 for (size_t j = 0; j < size; ++j) {
353 buffer[j] = valueSource.nextU() & 0xFF;
354 }
355 dynamicMemoryWStream.write(buffer, size);
Mike Reed49282292016-12-14 12:34:06 -0500356 totalWritten += size;
357 REPORTER_ASSERT(rep, totalWritten == dynamicMemoryWStream.bytesWritten());
halcanarye797d0d2015-05-21 08:13:27 -0700358 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400359 std::unique_ptr<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream());
bungeman38d909e2016-08-02 14:40:46 -0700360 sk_sp<SkData> expected(SkData::MakeUninitialized(asset->getLength()));
halcanarye797d0d2015-05-21 08:13:27 -0700361 uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data());
362 valueSource.setSeed(kSeed); // reseed.
363 // We want the exact same same "random" string of numbers to put
364 // in expected. i.e.: don't rely on SkDynamicMemoryStream to work
365 // correctly while we are testing SkDynamicMemoryStream.
366 for (size_t i = 0; i < asset->getLength(); ++i) {
367 expectedPtr[i] = valueSource.nextU() & 0xFF;
368 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400369 stream_peek_test(rep, asset.get(), expected.get());
halcanarye797d0d2015-05-21 08:13:27 -0700370}
halcanary48305e82015-08-18 13:30:25 -0700371
372namespace {
373class DumbStream : public SkStream {
374public:
375 DumbStream(const uint8_t* data, size_t n)
376 : fData(data), fCount(n), fIdx(0) {}
377 size_t read(void* buffer, size_t size) override {
halcanaryd75e21d2015-08-19 07:22:04 -0700378 size_t copyCount = SkTMin(fCount - fIdx, size);
379 if (copyCount) {
380 memcpy(buffer, &fData[fIdx], copyCount);
381 fIdx += copyCount;
halcanary48305e82015-08-18 13:30:25 -0700382 }
halcanaryd75e21d2015-08-19 07:22:04 -0700383 return copyCount;
halcanary48305e82015-08-18 13:30:25 -0700384 }
385 bool isAtEnd() const override {
halcanaryd75e21d2015-08-19 07:22:04 -0700386 return fCount == fIdx;
halcanary48305e82015-08-18 13:30:25 -0700387 }
388 private:
389 const uint8_t* fData;
390 size_t fCount, fIdx;
391};
392} // namespace
393
394static void stream_copy_test(skiatest::Reporter* reporter,
395 const void* srcData,
396 size_t N,
397 SkStream* stream) {
398 SkDynamicMemoryWStream tgt;
399 if (!SkStreamCopy(&tgt, stream)) {
400 ERRORF(reporter, "SkStreamCopy failed");
401 return;
402 }
reed42943c82016-09-12 12:01:44 -0700403 sk_sp<SkData> data(tgt.detachAsData());
halcanary48305e82015-08-18 13:30:25 -0700404 if (data->size() != N) {
405 ERRORF(reporter, "SkStreamCopy incorrect size");
406 return;
407 }
408 if (0 != memcmp(data->data(), srcData, N)) {
409 ERRORF(reporter, "SkStreamCopy bad copy");
410 }
411}
412
413DEF_TEST(StreamCopy, reporter) {
414 SkRandom random(123456);
halcanarycb9241b2015-08-19 06:12:40 -0700415 static const int N = 10000;
416 SkAutoTMalloc<uint8_t> src((size_t)N);
417 for (int j = 0; j < N; ++j) {
halcanary48305e82015-08-18 13:30:25 -0700418 src[j] = random.nextU() & 0xff;
419 }
420 // SkStreamCopy had two code paths; this test both.
halcanarycb9241b2015-08-19 06:12:40 -0700421 DumbStream dumbStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700422 stream_copy_test(reporter, src, N, &dumbStream);
halcanarycb9241b2015-08-19 06:12:40 -0700423 SkMemoryStream smartStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700424 stream_copy_test(reporter, src, N, &smartStream);
halcanary48305e82015-08-18 13:30:25 -0700425}
halcanary209c1622015-09-28 07:29:39 -0700426
427DEF_TEST(StreamEmptyStreamMemoryBase, r) {
428 SkDynamicMemoryWStream tmp;
Ben Wagner145dbcd2016-11-03 14:40:50 -0400429 std::unique_ptr<SkStreamAsset> asset(tmp.detachAsStream());
halcanary209c1622015-09-28 07:29:39 -0700430 REPORTER_ASSERT(r, nullptr == asset->getMemoryBase());
431}
Mike Reed1026ccf2017-01-08 14:35:29 -0500432
433#include "SkBuffer.h"
434
435DEF_TEST(RBuffer, reporter) {
436 int32_t value = 0;
437 SkRBuffer buffer(&value, 4);
438 REPORTER_ASSERT(reporter, buffer.isValid());
439
440 int32_t tmp;
441 REPORTER_ASSERT(reporter, buffer.read(&tmp, 4));
442 REPORTER_ASSERT(reporter, buffer.isValid());
443
444 REPORTER_ASSERT(reporter, !buffer.read(&tmp, 4));
445 REPORTER_ASSERT(reporter, !buffer.isValid());
446}