blob: 4b8923f39900d34d470eaf24bd9578e9e4652b98 [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"
reed@google.com8d0b5772011-06-24 13:07:31 +00009#include "SkData.h"
scroggo028a4132015-04-02 13:19:51 -070010#include "SkFrontBufferedStream.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000011#include "SkOSFile.h"
Ben Wagnerbf111d72016-11-07 18:05:29 -050012#include "SkOSPath.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000013#include "SkRandom.h"
14#include "SkStream.h"
halcanary48305e82015-08-18 13:30:25 -070015#include "SkStreamPriv.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000016#include "Test.h"
reed@android.com5e5adfd2009-03-07 03:39:23 +000017
reed@google.com789c6f22013-02-25 20:24:24 +000018#ifndef SK_BUILD_FOR_WIN
19#include <unistd.h>
20#include <fcntl.h>
21#endif
22
reed@android.com5e5adfd2009-03-07 03:39:23 +000023#define MAX_SIZE (256 * 1024)
24
reed@google.com789c6f22013-02-25 20:24:24 +000025static void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream,
26 const void* src, size_t len, int repeat) {
27 SkAutoSMalloc<256> storage(len);
28 void* tmp = storage.get();
29
30 for (int i = 0; i < repeat; ++i) {
31 size_t bytes = stream->read(tmp, len);
32 REPORTER_ASSERT(reporter, bytes == len);
33 REPORTER_ASSERT(reporter, !memcmp(tmp, src, len));
34 }
35
36 // expect EOF
37 size_t bytes = stream->read(tmp, 1);
38 REPORTER_ASSERT(reporter, 0 == bytes);
bungeman@google.com88682b72013-07-19 13:55:41 +000039 // isAtEnd might not return true until after the first failing read.
40 REPORTER_ASSERT(reporter, stream->isAtEnd());
reed@google.com789c6f22013-02-25 20:24:24 +000041}
42
43static void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) {
tfarinaa8e2e152014-07-28 19:26:58 -070044 SkString path = SkOSPath::Join(tmpDir, "wstream_test");
reed@google.com789c6f22013-02-25 20:24:24 +000045
46 const char s[] = "abcdefghijklmnopqrstuvwxyz";
47
48 {
49 SkFILEWStream writer(path.c_str());
50 if (!writer.isValid()) {
halcanary@google.coma9325fa2014-01-10 14:58:10 +000051 ERRORF(reporter, "Failed to create tmp file %s\n", path.c_str());
reed@google.com789c6f22013-02-25 20:24:24 +000052 return;
53 }
54
55 for (int i = 0; i < 100; ++i) {
56 writer.write(s, 26);
57 }
58 }
59
60 {
61 SkFILEStream stream(path.c_str());
62 REPORTER_ASSERT(reporter, stream.isValid());
63 test_loop_stream(reporter, &stream, s, 26, 100);
bungeman@google.com6cab1a42013-05-29 13:43:31 +000064
Ben Wagner145dbcd2016-11-03 14:40:50 -040065 std::unique_ptr<SkStreamAsset> stream2(stream.duplicate());
bungeman@google.com6cab1a42013-05-29 13:43:31 +000066 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com789c6f22013-02-25 20:24:24 +000067 }
68
reed@google.com789c6f22013-02-25 20:24:24 +000069 {
bungeman@google.com6cab1a42013-05-29 13:43:31 +000070 FILE* file = ::fopen(path.c_str(), "rb");
71 SkFILEStream stream(file, SkFILEStream::kCallerPasses_Ownership);
reed@google.com789c6f22013-02-25 20:24:24 +000072 REPORTER_ASSERT(reporter, stream.isValid());
73 test_loop_stream(reporter, &stream, s, 26, 100);
bungeman@google.com6cab1a42013-05-29 13:43:31 +000074
Ben Wagner145dbcd2016-11-03 14:40:50 -040075 std::unique_ptr<SkStreamAsset> stream2(stream.duplicate());
bungeman@google.com6cab1a42013-05-29 13:43:31 +000076 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com789c6f22013-02-25 20:24:24 +000077 }
reed@google.com789c6f22013-02-25 20:24:24 +000078}
79
reed@android.com80e39a72009-04-02 16:59:40 +000080static void TestWStream(skiatest::Reporter* reporter) {
81 SkDynamicMemoryWStream ds;
82 const char s[] = "abcdefghijklmnopqrstuvwxyz";
83 int i;
84 for (i = 0; i < 100; i++) {
85 REPORTER_ASSERT(reporter, ds.write(s, 26));
reed@android.com5e5adfd2009-03-07 03:39:23 +000086 }
Ben Wagner884300d2016-12-16 16:51:41 +000087 REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26);
bungeman@google.com88682b72013-07-19 13:55:41 +000088
reed@android.com80e39a72009-04-02 16:59:40 +000089 char* dst = new char[100 * 26 + 1];
90 dst[100*26] = '*';
91 ds.copyTo(dst);
92 REPORTER_ASSERT(reporter, dst[100*26] == '*');
reed@android.com80e39a72009-04-02 16:59:40 +000093 for (i = 0; i < 100; i++) {
94 REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
reed@android.com5e5adfd2009-03-07 03:39:23 +000095 }
reed@google.com70442a62011-06-23 21:48:04 +000096
97 {
Ben Wagner145dbcd2016-11-03 14:40:50 -040098 std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream());
bungeman@google.com88682b72013-07-19 13:55:41 +000099 REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength());
Ben Wagner884300d2016-12-16 16:51:41 +0000100 REPORTER_ASSERT(reporter, ds.bytesWritten() == 0);
bungeman@google.com88682b72013-07-19 13:55:41 +0000101 test_loop_stream(reporter, stream.get(), s, 26, 100);
102
Ben Wagner145dbcd2016-11-03 14:40:50 -0400103 std::unique_ptr<SkStreamAsset> stream2(stream->duplicate());
bungeman@google.com88682b72013-07-19 13:55:41 +0000104 test_loop_stream(reporter, stream2.get(), s, 26, 100);
105
Ben Wagner145dbcd2016-11-03 14:40:50 -0400106 std::unique_ptr<SkStreamAsset> stream3(stream->fork());
bungeman@google.com88682b72013-07-19 13:55:41 +0000107 REPORTER_ASSERT(reporter, stream3->isAtEnd());
108 char tmp;
109 size_t bytes = stream->read(&tmp, 1);
110 REPORTER_ASSERT(reporter, 0 == bytes);
111 stream3->rewind();
112 test_loop_stream(reporter, stream3.get(), s, 26, 100);
113 }
114
115 for (i = 0; i < 100; i++) {
116 REPORTER_ASSERT(reporter, ds.write(s, 26));
117 }
Ben Wagner884300d2016-12-16 16:51:41 +0000118 REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26);
bungeman@google.com88682b72013-07-19 13:55:41 +0000119
120 {
reed42943c82016-09-12 12:01:44 -0700121 // Test that this works after a snapshot.
Ben Wagner145dbcd2016-11-03 14:40:50 -0400122 std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream());
Ben Wagner884300d2016-12-16 16:51:41 +0000123 REPORTER_ASSERT(reporter, ds.bytesWritten() == 0);
bungeman@google.com88682b72013-07-19 13:55:41 +0000124 test_loop_stream(reporter, stream.get(), s, 26, 100);
125
Ben Wagner145dbcd2016-11-03 14:40:50 -0400126 std::unique_ptr<SkStreamAsset> stream2(stream->duplicate());
bungeman@google.com88682b72013-07-19 13:55:41 +0000127 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com70442a62011-06-23 21:48:04 +0000128 }
reed@android.com80e39a72009-04-02 16:59:40 +0000129 delete[] dst;
reed@google.com789c6f22013-02-25 20:24:24 +0000130
halcanary87f3ba42015-01-20 09:30:20 -0800131 SkString tmpDir = skiatest::GetTmpDir();
scroggo@google.comc76218d2013-06-06 14:59:56 +0000132 if (!tmpDir.isEmpty()) {
133 test_filestreams(reporter, tmpDir.c_str());
reed@google.com789c6f22013-02-25 20:24:24 +0000134 }
reed@android.com5e5adfd2009-03-07 03:39:23 +0000135}
136
reed@google.com19f286b2011-10-18 11:49:52 +0000137static void TestPackedUInt(skiatest::Reporter* reporter) {
138 // we know that packeduint tries to write 1, 2 or 4 bytes for the length,
139 // so we test values around each of those transitions (and a few others)
140 const size_t sizes[] = {
141 0, 1, 2, 0xFC, 0xFD, 0xFE, 0xFF, 0x100, 0x101, 32767, 32768, 32769,
142 0xFFFD, 0xFFFE, 0xFFFF, 0x10000, 0x10001,
143 0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0x1000000, 0x1000001,
144 0x7FFFFFFE, 0x7FFFFFFF, 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF
145 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000146
147
reed@google.com19f286b2011-10-18 11:49:52 +0000148 size_t i;
149 char buffer[sizeof(sizes) * 4];
rmistry@google.comd6176b02012-08-23 18:14:13 +0000150
reed@google.com19f286b2011-10-18 11:49:52 +0000151 SkMemoryWStream wstream(buffer, sizeof(buffer));
152 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
153 bool success = wstream.writePackedUInt(sizes[i]);
154 REPORTER_ASSERT(reporter, success);
155 }
156 wstream.flush();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000157
reed@google.com19f286b2011-10-18 11:49:52 +0000158 SkMemoryStream rstream(buffer, sizeof(buffer));
159 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
160 size_t n = rstream.readPackedUInt();
161 if (sizes[i] != n) {
halcanary7d571242016-02-24 17:59:16 -0800162 ERRORF(reporter, "sizes:%x != n:%x\n", i, sizes[i], n);
reed@google.com19f286b2011-10-18 11:49:52 +0000163 }
reed@google.com19f286b2011-10-18 11:49:52 +0000164 }
165}
166
halcanary96fcdcc2015-08-27 07:41:13 -0700167// 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 +0000168// methods that access fData.
169static void TestDereferencingData(SkMemoryStream* memStream) {
halcanary96fcdcc2015-08-27 07:41:13 -0700170 memStream->read(nullptr, 0);
scroggo@google.come4904202013-01-09 22:02:58 +0000171 memStream->getMemoryBase();
reed42943c82016-09-12 12:01:44 -0700172 (void)memStream->asData();
scroggo@google.come4904202013-01-09 22:02:58 +0000173}
174
175static void TestNullData() {
reed42943c82016-09-12 12:01:44 -0700176 SkMemoryStream memStream(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000177 TestDereferencingData(&memStream);
178
reed42943c82016-09-12 12:01:44 -0700179 memStream.setData(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000180 TestDereferencingData(&memStream);
181
182}
183
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000184DEF_TEST(Stream, reporter) {
reed@android.com5e5adfd2009-03-07 03:39:23 +0000185 TestWStream(reporter);
reed@google.com19f286b2011-10-18 11:49:52 +0000186 TestPackedUInt(reporter);
scroggo@google.come4904202013-01-09 22:02:58 +0000187 TestNullData();
reed@android.com5e5adfd2009-03-07 03:39:23 +0000188}
scroggo028a4132015-04-02 13:19:51 -0700189
Mike Klein7d302882016-11-03 14:06:31 -0400190#ifndef SK_BUILD_FOR_IOS
scroggo028a4132015-04-02 13:19:51 -0700191/**
192 * Tests peeking and then reading the same amount. The two should provide the
193 * same results.
scroggod61c3842015-12-07 11:37:13 -0800194 * Returns the amount successfully read minus the amount successfully peeked.
scroggo028a4132015-04-02 13:19:51 -0700195 */
scroggod61c3842015-12-07 11:37:13 -0800196static size_t compare_peek_to_read(skiatest::Reporter* reporter,
197 SkStream* stream, size_t bytesToPeek) {
scroggo028a4132015-04-02 13:19:51 -0700198 // The rest of our tests won't be very interesting if bytesToPeek is zero.
199 REPORTER_ASSERT(reporter, bytesToPeek > 0);
200 SkAutoMalloc peekStorage(bytesToPeek);
201 SkAutoMalloc readStorage(bytesToPeek);
202 void* peekPtr = peekStorage.get();
203 void* readPtr = peekStorage.get();
204
scroggod61c3842015-12-07 11:37:13 -0800205 const size_t bytesPeeked = stream->peek(peekPtr, bytesToPeek);
scroggo028a4132015-04-02 13:19:51 -0700206 const size_t bytesRead = stream->read(readPtr, bytesToPeek);
207
208 // bytesRead should only be less than attempted if the stream is at the
209 // end.
210 REPORTER_ASSERT(reporter, bytesRead == bytesToPeek || stream->isAtEnd());
211
212 // peek and read should behave the same, except peek returned to the
213 // original position, so they read the same data.
scroggod61c3842015-12-07 11:37:13 -0800214 REPORTER_ASSERT(reporter, !memcmp(peekPtr, readPtr, bytesPeeked));
scroggo028a4132015-04-02 13:19:51 -0700215
scroggod61c3842015-12-07 11:37:13 -0800216 // A stream should never be able to peek more than it can read.
217 REPORTER_ASSERT(reporter, bytesRead >= bytesPeeked);
218
219 return bytesRead - bytesPeeked;
scroggo028a4132015-04-02 13:19:51 -0700220}
221
scroggod61c3842015-12-07 11:37:13 -0800222static void test_fully_peekable_stream(skiatest::Reporter* r, SkStream* stream, size_t limit) {
scroggo028a4132015-04-02 13:19:51 -0700223 for (size_t i = 1; !stream->isAtEnd(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800224 REPORTER_ASSERT(r, compare_peek_to_read(r, stream, i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700225 }
226}
227
228static void test_peeking_front_buffered_stream(skiatest::Reporter* r,
229 const SkStream& original,
230 size_t bufferSize) {
231 SkStream* dupe = original.duplicate();
halcanary96fcdcc2015-08-27 07:41:13 -0700232 REPORTER_ASSERT(r, dupe != nullptr);
Ben Wagner145dbcd2016-11-03 14:40:50 -0400233 std::unique_ptr<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize));
halcanary96fcdcc2015-08-27 07:41:13 -0700234 REPORTER_ASSERT(r, bufferedStream != nullptr);
scroggod61c3842015-12-07 11:37:13 -0800235
236 size_t peeked = 0;
237 for (size_t i = 1; !bufferedStream->isAtEnd(); i++) {
Ben Wagner145dbcd2016-11-03 14:40:50 -0400238 const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream.get(), i);
scroggod61c3842015-12-07 11:37:13 -0800239 if (unpeekableBytes > 0) {
240 // This could not have returned a number greater than i.
241 REPORTER_ASSERT(r, unpeekableBytes <= i);
242
243 // We have reached the end of the buffer. Verify that it was at least
244 // bufferSize.
245 REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize);
246 // No more peeking is supported.
247 break;
248 }
249 peeked += i;
250 }
251
252 // Test that attempting to peek beyond the length of the buffer does not prevent rewinding.
253 bufferedStream.reset(SkFrontBufferedStream::Create(original.duplicate(), bufferSize));
254 REPORTER_ASSERT(r, bufferedStream != nullptr);
255
256 const size_t bytesToPeek = bufferSize + 1;
257 SkAutoMalloc peekStorage(bytesToPeek);
258 SkAutoMalloc readStorage(bytesToPeek);
259
260 for (size_t start = 0; start <= bufferSize; start++) {
261 // Skip to the starting point
262 REPORTER_ASSERT(r, bufferedStream->skip(start) == start);
scroggod61c3842015-12-07 11:37:13 -0800263
264 const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek);
265 if (0 == bytesPeeked) {
scroggoef0fed32016-02-18 05:59:25 -0800266 // Peeking should only fail completely if we have read/skipped beyond the buffer.
267 REPORTER_ASSERT(r, start >= bufferSize);
scroggod61c3842015-12-07 11:37:13 -0800268 break;
269 }
270
271 // Only read the amount that was successfully peeked.
272 const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked);
273 REPORTER_ASSERT(r, bytesRead == bytesPeeked);
274 REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked));
275
276 // This should be safe to rewind.
277 REPORTER_ASSERT(r, bufferedStream->rewind());
278 }
scroggo028a4132015-04-02 13:19:51 -0700279}
280
halcanary9d524f22016-03-29 09:03:52 -0700281// This test uses file system operations that don't work out of the
282// box on iOS. It's likely that we don't need them on iOS. Ignoring for now.
283// TODO(stephana): Re-evaluate if we need this in the future.
scroggo028a4132015-04-02 13:19:51 -0700284DEF_TEST(StreamPeek, reporter) {
285 // Test a memory stream.
286 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz";
287 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
scroggod61c3842015-12-07 11:37:13 -0800288 test_fully_peekable_stream(reporter, &memStream, memStream.getLength());
scroggo028a4132015-04-02 13:19:51 -0700289
290 // Test an arbitrary file stream. file streams do not support peeking.
291 SkFILEStream fileStream(GetResourcePath("baby_tux.webp").c_str());
292 REPORTER_ASSERT(reporter, fileStream.isValid());
caryclark30ac4642015-04-14 06:08:04 -0700293 if (!fileStream.isValid()) {
294 return;
295 }
scroggo028a4132015-04-02 13:19:51 -0700296 SkAutoMalloc storage(fileStream.getLength());
297 for (size_t i = 1; i < fileStream.getLength(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800298 REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700299 }
300
301 // Now test some FrontBufferedStreams
302 for (size_t i = 1; i < memStream.getLength(); i++) {
303 test_peeking_front_buffered_stream(reporter, memStream, i);
304 }
305}
halcanarye797d0d2015-05-21 08:13:27 -0700306#endif
307
308// Asserts that asset == expected and is peekable.
309static void stream_peek_test(skiatest::Reporter* rep,
310 SkStreamAsset* asset,
311 const SkData* expected) {
312 if (asset->getLength() != expected->size()) {
313 ERRORF(rep, "Unexpected length.");
314 return;
315 }
316 SkRandom rand;
317 uint8_t buffer[4096];
318 const uint8_t* expect = expected->bytes();
319 for (size_t i = 0; i < asset->getLength(); ++i) {
320 uint32_t maxSize =
321 SkToU32(SkTMin(sizeof(buffer), asset->getLength() - i));
322 size_t size = rand.nextRangeU(1, maxSize);
323 SkASSERT(size >= 1);
324 SkASSERT(size <= sizeof(buffer));
325 SkASSERT(size + i <= asset->getLength());
scroggod61c3842015-12-07 11:37:13 -0800326 if (asset->peek(buffer, size) < size) {
halcanarye797d0d2015-05-21 08:13:27 -0700327 ERRORF(rep, "Peek Failed!");
328 return;
329 }
330 if (0 != memcmp(buffer, &expect[i], size)) {
331 ERRORF(rep, "Peek returned wrong bytes!");
332 return;
333 }
334 uint8_t value;
335 REPORTER_ASSERT(rep, 1 == asset->read(&value, 1));
336 if (value != expect[i]) {
337 ERRORF(rep, "Read Failed!");
338 return;
339 }
340 }
341}
342
343DEF_TEST(StreamPeek_BlockMemoryStream, rep) {
344 const static int kSeed = 1234;
345 SkRandom valueSource(kSeed);
346 SkRandom rand(kSeed << 1);
347 uint8_t buffer[4096];
348 SkDynamicMemoryWStream dynamicMemoryWStream;
Mike Reed49282292016-12-14 12:34:06 -0500349 size_t totalWritten = 0;
halcanarye797d0d2015-05-21 08:13:27 -0700350 for (int i = 0; i < 32; ++i) {
351 // Randomize the length of the blocks.
352 size_t size = rand.nextRangeU(1, sizeof(buffer));
353 for (size_t j = 0; j < size; ++j) {
354 buffer[j] = valueSource.nextU() & 0xFF;
355 }
356 dynamicMemoryWStream.write(buffer, size);
Mike Reed49282292016-12-14 12:34:06 -0500357 totalWritten += size;
358 REPORTER_ASSERT(rep, totalWritten == dynamicMemoryWStream.bytesWritten());
halcanarye797d0d2015-05-21 08:13:27 -0700359 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400360 std::unique_ptr<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream());
bungeman38d909e2016-08-02 14:40:46 -0700361 sk_sp<SkData> expected(SkData::MakeUninitialized(asset->getLength()));
halcanarye797d0d2015-05-21 08:13:27 -0700362 uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data());
363 valueSource.setSeed(kSeed); // reseed.
364 // We want the exact same same "random" string of numbers to put
365 // in expected. i.e.: don't rely on SkDynamicMemoryStream to work
366 // correctly while we are testing SkDynamicMemoryStream.
367 for (size_t i = 0; i < asset->getLength(); ++i) {
368 expectedPtr[i] = valueSource.nextU() & 0xFF;
369 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400370 stream_peek_test(rep, asset.get(), expected.get());
halcanarye797d0d2015-05-21 08:13:27 -0700371}
halcanary48305e82015-08-18 13:30:25 -0700372
373namespace {
374class DumbStream : public SkStream {
375public:
376 DumbStream(const uint8_t* data, size_t n)
377 : fData(data), fCount(n), fIdx(0) {}
378 size_t read(void* buffer, size_t size) override {
halcanaryd75e21d2015-08-19 07:22:04 -0700379 size_t copyCount = SkTMin(fCount - fIdx, size);
380 if (copyCount) {
381 memcpy(buffer, &fData[fIdx], copyCount);
382 fIdx += copyCount;
halcanary48305e82015-08-18 13:30:25 -0700383 }
halcanaryd75e21d2015-08-19 07:22:04 -0700384 return copyCount;
halcanary48305e82015-08-18 13:30:25 -0700385 }
386 bool isAtEnd() const override {
halcanaryd75e21d2015-08-19 07:22:04 -0700387 return fCount == fIdx;
halcanary48305e82015-08-18 13:30:25 -0700388 }
389 private:
390 const uint8_t* fData;
391 size_t fCount, fIdx;
392};
393} // namespace
394
395static void stream_copy_test(skiatest::Reporter* reporter,
396 const void* srcData,
397 size_t N,
398 SkStream* stream) {
399 SkDynamicMemoryWStream tgt;
400 if (!SkStreamCopy(&tgt, stream)) {
401 ERRORF(reporter, "SkStreamCopy failed");
402 return;
403 }
reed42943c82016-09-12 12:01:44 -0700404 sk_sp<SkData> data(tgt.detachAsData());
halcanary48305e82015-08-18 13:30:25 -0700405 if (data->size() != N) {
406 ERRORF(reporter, "SkStreamCopy incorrect size");
407 return;
408 }
409 if (0 != memcmp(data->data(), srcData, N)) {
410 ERRORF(reporter, "SkStreamCopy bad copy");
411 }
412}
413
414DEF_TEST(StreamCopy, reporter) {
415 SkRandom random(123456);
halcanarycb9241b2015-08-19 06:12:40 -0700416 static const int N = 10000;
417 SkAutoTMalloc<uint8_t> src((size_t)N);
418 for (int j = 0; j < N; ++j) {
halcanary48305e82015-08-18 13:30:25 -0700419 src[j] = random.nextU() & 0xff;
420 }
421 // SkStreamCopy had two code paths; this test both.
halcanarycb9241b2015-08-19 06:12:40 -0700422 DumbStream dumbStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700423 stream_copy_test(reporter, src, N, &dumbStream);
halcanarycb9241b2015-08-19 06:12:40 -0700424 SkMemoryStream smartStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700425 stream_copy_test(reporter, src, N, &smartStream);
halcanary48305e82015-08-18 13:30:25 -0700426}
halcanary209c1622015-09-28 07:29:39 -0700427
428DEF_TEST(StreamEmptyStreamMemoryBase, r) {
429 SkDynamicMemoryWStream tmp;
Ben Wagner145dbcd2016-11-03 14:40:50 -0400430 std::unique_ptr<SkStreamAsset> asset(tmp.detachAsStream());
halcanary209c1622015-09-28 07:29:39 -0700431 REPORTER_ASSERT(r, nullptr == asset->getMemoryBase());
432}