blob: fe4da0f5fbcbdbb2560a94c549e34a6f18eb815e [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"
12#include "SkRandom.h"
13#include "SkStream.h"
halcanary48305e82015-08-18 13:30:25 -070014#include "SkStreamPriv.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000015#include "Test.h"
reed@android.com5e5adfd2009-03-07 03:39:23 +000016
reed@google.com789c6f22013-02-25 20:24:24 +000017#ifndef SK_BUILD_FOR_WIN
18#include <unistd.h>
19#include <fcntl.h>
20#endif
21
reed@android.com5e5adfd2009-03-07 03:39:23 +000022#define MAX_SIZE (256 * 1024)
23
reed@google.com789c6f22013-02-25 20:24:24 +000024static void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream,
25 const void* src, size_t len, int repeat) {
26 SkAutoSMalloc<256> storage(len);
27 void* tmp = storage.get();
28
29 for (int i = 0; i < repeat; ++i) {
30 size_t bytes = stream->read(tmp, len);
31 REPORTER_ASSERT(reporter, bytes == len);
32 REPORTER_ASSERT(reporter, !memcmp(tmp, src, len));
33 }
34
35 // expect EOF
36 size_t bytes = stream->read(tmp, 1);
37 REPORTER_ASSERT(reporter, 0 == bytes);
bungeman@google.com88682b72013-07-19 13:55:41 +000038 // isAtEnd might not return true until after the first failing read.
39 REPORTER_ASSERT(reporter, stream->isAtEnd());
reed@google.com789c6f22013-02-25 20:24:24 +000040}
41
42static void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) {
tfarinaa8e2e152014-07-28 19:26:58 -070043 SkString path = SkOSPath::Join(tmpDir, "wstream_test");
reed@google.com789c6f22013-02-25 20:24:24 +000044
45 const char s[] = "abcdefghijklmnopqrstuvwxyz";
46
47 {
48 SkFILEWStream writer(path.c_str());
49 if (!writer.isValid()) {
halcanary@google.coma9325fa2014-01-10 14:58:10 +000050 ERRORF(reporter, "Failed to create tmp file %s\n", path.c_str());
reed@google.com789c6f22013-02-25 20:24:24 +000051 return;
52 }
53
54 for (int i = 0; i < 100; ++i) {
55 writer.write(s, 26);
56 }
57 }
58
59 {
60 SkFILEStream stream(path.c_str());
61 REPORTER_ASSERT(reporter, stream.isValid());
62 test_loop_stream(reporter, &stream, s, 26, 100);
bungeman@google.com6cab1a42013-05-29 13:43:31 +000063
scroggoa1193e42015-01-21 12:09:53 -080064 SkAutoTDelete<SkStreamAsset> stream2(stream.duplicate());
bungeman@google.com6cab1a42013-05-29 13:43:31 +000065 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com789c6f22013-02-25 20:24:24 +000066 }
67
reed@google.com789c6f22013-02-25 20:24:24 +000068 {
bungeman@google.com6cab1a42013-05-29 13:43:31 +000069 FILE* file = ::fopen(path.c_str(), "rb");
70 SkFILEStream stream(file, SkFILEStream::kCallerPasses_Ownership);
reed@google.com789c6f22013-02-25 20:24:24 +000071 REPORTER_ASSERT(reporter, stream.isValid());
72 test_loop_stream(reporter, &stream, s, 26, 100);
bungeman@google.com6cab1a42013-05-29 13:43:31 +000073
scroggoa1193e42015-01-21 12:09:53 -080074 SkAutoTDelete<SkStreamAsset> stream2(stream.duplicate());
bungeman@google.com6cab1a42013-05-29 13:43:31 +000075 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com789c6f22013-02-25 20:24:24 +000076 }
reed@google.com789c6f22013-02-25 20:24:24 +000077}
78
reed@android.com80e39a72009-04-02 16:59:40 +000079static void TestWStream(skiatest::Reporter* reporter) {
80 SkDynamicMemoryWStream ds;
81 const char s[] = "abcdefghijklmnopqrstuvwxyz";
82 int i;
83 for (i = 0; i < 100; i++) {
84 REPORTER_ASSERT(reporter, ds.write(s, 26));
reed@android.com5e5adfd2009-03-07 03:39:23 +000085 }
reed@android.com80e39a72009-04-02 16:59:40 +000086 REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
bungeman@google.com88682b72013-07-19 13:55:41 +000087
reed@android.com80e39a72009-04-02 16:59:40 +000088 char* dst = new char[100 * 26 + 1];
89 dst[100*26] = '*';
90 ds.copyTo(dst);
91 REPORTER_ASSERT(reporter, dst[100*26] == '*');
reed@android.com80e39a72009-04-02 16:59:40 +000092 for (i = 0; i < 100; i++) {
93 REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
reed@android.com5e5adfd2009-03-07 03:39:23 +000094 }
reed@google.com70442a62011-06-23 21:48:04 +000095
96 {
scroggoa1193e42015-01-21 12:09:53 -080097 SkAutoTDelete<SkStreamAsset> stream(ds.detachAsStream());
bungeman@google.com88682b72013-07-19 13:55:41 +000098 REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength());
99 REPORTER_ASSERT(reporter, ds.getOffset() == 0);
100 test_loop_stream(reporter, stream.get(), s, 26, 100);
101
scroggoa1193e42015-01-21 12:09:53 -0800102 SkAutoTDelete<SkStreamAsset> stream2(stream->duplicate());
bungeman@google.com88682b72013-07-19 13:55:41 +0000103 test_loop_stream(reporter, stream2.get(), s, 26, 100);
104
scroggoa1193e42015-01-21 12:09:53 -0800105 SkAutoTDelete<SkStreamAsset> stream3(stream->fork());
bungeman@google.com88682b72013-07-19 13:55:41 +0000106 REPORTER_ASSERT(reporter, stream3->isAtEnd());
107 char tmp;
108 size_t bytes = stream->read(&tmp, 1);
109 REPORTER_ASSERT(reporter, 0 == bytes);
110 stream3->rewind();
111 test_loop_stream(reporter, stream3.get(), s, 26, 100);
112 }
113
114 for (i = 0; i < 100; i++) {
115 REPORTER_ASSERT(reporter, ds.write(s, 26));
116 }
117 REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
118
119 {
120 SkAutoTUnref<SkData> data(ds.copyToData());
reed@google.com70442a62011-06-23 21:48:04 +0000121 REPORTER_ASSERT(reporter, 100 * 26 == data->size());
122 REPORTER_ASSERT(reporter, memcmp(dst, data->data(), data->size()) == 0);
bungeman@google.com88682b72013-07-19 13:55:41 +0000123 }
124
125 {
126 // Test that this works after a copyToData.
scroggoa1193e42015-01-21 12:09:53 -0800127 SkAutoTDelete<SkStreamAsset> stream(ds.detachAsStream());
bungeman@google.com88682b72013-07-19 13:55:41 +0000128 REPORTER_ASSERT(reporter, ds.getOffset() == 0);
129 test_loop_stream(reporter, stream.get(), s, 26, 100);
130
scroggoa1193e42015-01-21 12:09:53 -0800131 SkAutoTDelete<SkStreamAsset> stream2(stream->duplicate());
bungeman@google.com88682b72013-07-19 13:55:41 +0000132 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com70442a62011-06-23 21:48:04 +0000133 }
reed@android.com80e39a72009-04-02 16:59:40 +0000134 delete[] dst;
reed@google.com789c6f22013-02-25 20:24:24 +0000135
halcanary87f3ba42015-01-20 09:30:20 -0800136 SkString tmpDir = skiatest::GetTmpDir();
scroggo@google.comc76218d2013-06-06 14:59:56 +0000137 if (!tmpDir.isEmpty()) {
138 test_filestreams(reporter, tmpDir.c_str());
reed@google.com789c6f22013-02-25 20:24:24 +0000139 }
reed@android.com5e5adfd2009-03-07 03:39:23 +0000140}
141
reed@google.com19f286b2011-10-18 11:49:52 +0000142static void TestPackedUInt(skiatest::Reporter* reporter) {
143 // we know that packeduint tries to write 1, 2 or 4 bytes for the length,
144 // so we test values around each of those transitions (and a few others)
145 const size_t sizes[] = {
146 0, 1, 2, 0xFC, 0xFD, 0xFE, 0xFF, 0x100, 0x101, 32767, 32768, 32769,
147 0xFFFD, 0xFFFE, 0xFFFF, 0x10000, 0x10001,
148 0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0x1000000, 0x1000001,
149 0x7FFFFFFE, 0x7FFFFFFF, 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF
150 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000151
152
reed@google.com19f286b2011-10-18 11:49:52 +0000153 size_t i;
154 char buffer[sizeof(sizes) * 4];
rmistry@google.comd6176b02012-08-23 18:14:13 +0000155
reed@google.com19f286b2011-10-18 11:49:52 +0000156 SkMemoryWStream wstream(buffer, sizeof(buffer));
157 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
158 bool success = wstream.writePackedUInt(sizes[i]);
159 REPORTER_ASSERT(reporter, success);
160 }
161 wstream.flush();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000162
reed@google.com19f286b2011-10-18 11:49:52 +0000163 SkMemoryStream rstream(buffer, sizeof(buffer));
164 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
165 size_t n = rstream.readPackedUInt();
166 if (sizes[i] != n) {
halcanary7d571242016-02-24 17:59:16 -0800167 ERRORF(reporter, "sizes:%x != n:%x\n", i, sizes[i], n);
reed@google.com19f286b2011-10-18 11:49:52 +0000168 }
reed@google.com19f286b2011-10-18 11:49:52 +0000169 }
170}
171
halcanary96fcdcc2015-08-27 07:41:13 -0700172// 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 +0000173// methods that access fData.
174static void TestDereferencingData(SkMemoryStream* memStream) {
halcanary96fcdcc2015-08-27 07:41:13 -0700175 memStream->read(nullptr, 0);
scroggo@google.come4904202013-01-09 22:02:58 +0000176 memStream->getMemoryBase();
177 SkAutoDataUnref data(memStream->copyToData());
178}
179
180static void TestNullData() {
halcanary96fcdcc2015-08-27 07:41:13 -0700181 SkData* nullData = nullptr;
scroggo@google.come4904202013-01-09 22:02:58 +0000182 SkMemoryStream memStream(nullData);
183 TestDereferencingData(&memStream);
184
185 memStream.setData(nullData);
186 TestDereferencingData(&memStream);
187
188}
189
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000190DEF_TEST(Stream, reporter) {
reed@android.com5e5adfd2009-03-07 03:39:23 +0000191 TestWStream(reporter);
reed@google.com19f286b2011-10-18 11:49:52 +0000192 TestPackedUInt(reporter);
scroggo@google.come4904202013-01-09 22:02:58 +0000193 TestNullData();
reed@android.com5e5adfd2009-03-07 03:39:23 +0000194}
scroggo028a4132015-04-02 13:19:51 -0700195
196/**
197 * Tests peeking and then reading the same amount. The two should provide the
198 * same results.
scroggod61c3842015-12-07 11:37:13 -0800199 * Returns the amount successfully read minus the amount successfully peeked.
scroggo028a4132015-04-02 13:19:51 -0700200 */
scroggod61c3842015-12-07 11:37:13 -0800201static size_t compare_peek_to_read(skiatest::Reporter* reporter,
202 SkStream* stream, size_t bytesToPeek) {
scroggo028a4132015-04-02 13:19:51 -0700203 // The rest of our tests won't be very interesting if bytesToPeek is zero.
204 REPORTER_ASSERT(reporter, bytesToPeek > 0);
205 SkAutoMalloc peekStorage(bytesToPeek);
206 SkAutoMalloc readStorage(bytesToPeek);
207 void* peekPtr = peekStorage.get();
208 void* readPtr = peekStorage.get();
209
scroggod61c3842015-12-07 11:37:13 -0800210 const size_t bytesPeeked = stream->peek(peekPtr, bytesToPeek);
scroggo028a4132015-04-02 13:19:51 -0700211 const size_t bytesRead = stream->read(readPtr, bytesToPeek);
212
213 // bytesRead should only be less than attempted if the stream is at the
214 // end.
215 REPORTER_ASSERT(reporter, bytesRead == bytesToPeek || stream->isAtEnd());
216
217 // peek and read should behave the same, except peek returned to the
218 // original position, so they read the same data.
scroggod61c3842015-12-07 11:37:13 -0800219 REPORTER_ASSERT(reporter, !memcmp(peekPtr, readPtr, bytesPeeked));
scroggo028a4132015-04-02 13:19:51 -0700220
scroggod61c3842015-12-07 11:37:13 -0800221 // A stream should never be able to peek more than it can read.
222 REPORTER_ASSERT(reporter, bytesRead >= bytesPeeked);
223
224 return bytesRead - bytesPeeked;
scroggo028a4132015-04-02 13:19:51 -0700225}
226
scroggod61c3842015-12-07 11:37:13 -0800227static void test_fully_peekable_stream(skiatest::Reporter* r, SkStream* stream, size_t limit) {
scroggo028a4132015-04-02 13:19:51 -0700228 for (size_t i = 1; !stream->isAtEnd(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800229 REPORTER_ASSERT(r, compare_peek_to_read(r, stream, i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700230 }
231}
232
233static void test_peeking_front_buffered_stream(skiatest::Reporter* r,
234 const SkStream& original,
235 size_t bufferSize) {
236 SkStream* dupe = original.duplicate();
halcanary96fcdcc2015-08-27 07:41:13 -0700237 REPORTER_ASSERT(r, dupe != nullptr);
scroggo028a4132015-04-02 13:19:51 -0700238 SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize));
halcanary96fcdcc2015-08-27 07:41:13 -0700239 REPORTER_ASSERT(r, bufferedStream != nullptr);
scroggod61c3842015-12-07 11:37:13 -0800240
241 size_t peeked = 0;
242 for (size_t i = 1; !bufferedStream->isAtEnd(); i++) {
243 const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream, i);
244 if (unpeekableBytes > 0) {
245 // This could not have returned a number greater than i.
246 REPORTER_ASSERT(r, unpeekableBytes <= i);
247
248 // We have reached the end of the buffer. Verify that it was at least
249 // bufferSize.
250 REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize);
251 // No more peeking is supported.
252 break;
253 }
254 peeked += i;
255 }
256
257 // Test that attempting to peek beyond the length of the buffer does not prevent rewinding.
258 bufferedStream.reset(SkFrontBufferedStream::Create(original.duplicate(), bufferSize));
259 REPORTER_ASSERT(r, bufferedStream != nullptr);
260
261 const size_t bytesToPeek = bufferSize + 1;
262 SkAutoMalloc peekStorage(bytesToPeek);
263 SkAutoMalloc readStorage(bytesToPeek);
264
265 for (size_t start = 0; start <= bufferSize; start++) {
266 // Skip to the starting point
267 REPORTER_ASSERT(r, bufferedStream->skip(start) == start);
scroggod61c3842015-12-07 11:37:13 -0800268
269 const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek);
270 if (0 == bytesPeeked) {
scroggoef0fed32016-02-18 05:59:25 -0800271 // Peeking should only fail completely if we have read/skipped beyond the buffer.
272 REPORTER_ASSERT(r, start >= bufferSize);
scroggod61c3842015-12-07 11:37:13 -0800273 break;
274 }
275
276 // Only read the amount that was successfully peeked.
277 const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked);
278 REPORTER_ASSERT(r, bytesRead == bytesPeeked);
279 REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked));
280
281 // This should be safe to rewind.
282 REPORTER_ASSERT(r, bufferedStream->rewind());
283 }
scroggo028a4132015-04-02 13:19:51 -0700284}
285
halcanary9d524f22016-03-29 09:03:52 -0700286// This test uses file system operations that don't work out of the
287// box on iOS. It's likely that we don't need them on iOS. Ignoring for now.
288// TODO(stephana): Re-evaluate if we need this in the future.
stephana195f62d2015-04-09 07:57:54 -0700289#ifndef SK_BUILD_FOR_IOS
scroggo028a4132015-04-02 13:19:51 -0700290DEF_TEST(StreamPeek, reporter) {
291 // Test a memory stream.
292 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz";
293 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
scroggod61c3842015-12-07 11:37:13 -0800294 test_fully_peekable_stream(reporter, &memStream, memStream.getLength());
scroggo028a4132015-04-02 13:19:51 -0700295
296 // Test an arbitrary file stream. file streams do not support peeking.
297 SkFILEStream fileStream(GetResourcePath("baby_tux.webp").c_str());
298 REPORTER_ASSERT(reporter, fileStream.isValid());
caryclark30ac4642015-04-14 06:08:04 -0700299 if (!fileStream.isValid()) {
300 return;
301 }
scroggo028a4132015-04-02 13:19:51 -0700302 SkAutoMalloc storage(fileStream.getLength());
303 for (size_t i = 1; i < fileStream.getLength(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800304 REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700305 }
306
307 // Now test some FrontBufferedStreams
308 for (size_t i = 1; i < memStream.getLength(); i++) {
309 test_peeking_front_buffered_stream(reporter, memStream, i);
310 }
311}
halcanarye797d0d2015-05-21 08:13:27 -0700312#endif
313
314// Asserts that asset == expected and is peekable.
315static void stream_peek_test(skiatest::Reporter* rep,
316 SkStreamAsset* asset,
317 const SkData* expected) {
318 if (asset->getLength() != expected->size()) {
319 ERRORF(rep, "Unexpected length.");
320 return;
321 }
322 SkRandom rand;
323 uint8_t buffer[4096];
324 const uint8_t* expect = expected->bytes();
325 for (size_t i = 0; i < asset->getLength(); ++i) {
326 uint32_t maxSize =
327 SkToU32(SkTMin(sizeof(buffer), asset->getLength() - i));
328 size_t size = rand.nextRangeU(1, maxSize);
329 SkASSERT(size >= 1);
330 SkASSERT(size <= sizeof(buffer));
331 SkASSERT(size + i <= asset->getLength());
scroggod61c3842015-12-07 11:37:13 -0800332 if (asset->peek(buffer, size) < size) {
halcanarye797d0d2015-05-21 08:13:27 -0700333 ERRORF(rep, "Peek Failed!");
334 return;
335 }
336 if (0 != memcmp(buffer, &expect[i], size)) {
337 ERRORF(rep, "Peek returned wrong bytes!");
338 return;
339 }
340 uint8_t value;
341 REPORTER_ASSERT(rep, 1 == asset->read(&value, 1));
342 if (value != expect[i]) {
343 ERRORF(rep, "Read Failed!");
344 return;
345 }
346 }
347}
348
349DEF_TEST(StreamPeek_BlockMemoryStream, rep) {
350 const static int kSeed = 1234;
351 SkRandom valueSource(kSeed);
352 SkRandom rand(kSeed << 1);
353 uint8_t buffer[4096];
354 SkDynamicMemoryWStream dynamicMemoryWStream;
355 for (int i = 0; i < 32; ++i) {
356 // Randomize the length of the blocks.
357 size_t size = rand.nextRangeU(1, sizeof(buffer));
358 for (size_t j = 0; j < size; ++j) {
359 buffer[j] = valueSource.nextU() & 0xFF;
360 }
361 dynamicMemoryWStream.write(buffer, size);
362 }
363 SkAutoTDelete<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream());
364 SkAutoTUnref<SkData> expected(SkData::NewUninitialized(asset->getLength()));
365 uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data());
366 valueSource.setSeed(kSeed); // reseed.
367 // We want the exact same same "random" string of numbers to put
368 // in expected. i.e.: don't rely on SkDynamicMemoryStream to work
369 // correctly while we are testing SkDynamicMemoryStream.
370 for (size_t i = 0; i < asset->getLength(); ++i) {
371 expectedPtr[i] = valueSource.nextU() & 0xFF;
372 }
373 stream_peek_test(rep, asset, expected);
374}
halcanary48305e82015-08-18 13:30:25 -0700375
376namespace {
377class DumbStream : public SkStream {
378public:
379 DumbStream(const uint8_t* data, size_t n)
380 : fData(data), fCount(n), fIdx(0) {}
381 size_t read(void* buffer, size_t size) override {
halcanaryd75e21d2015-08-19 07:22:04 -0700382 size_t copyCount = SkTMin(fCount - fIdx, size);
383 if (copyCount) {
384 memcpy(buffer, &fData[fIdx], copyCount);
385 fIdx += copyCount;
halcanary48305e82015-08-18 13:30:25 -0700386 }
halcanaryd75e21d2015-08-19 07:22:04 -0700387 return copyCount;
halcanary48305e82015-08-18 13:30:25 -0700388 }
389 bool isAtEnd() const override {
halcanaryd75e21d2015-08-19 07:22:04 -0700390 return fCount == fIdx;
halcanary48305e82015-08-18 13:30:25 -0700391 }
392 private:
393 const uint8_t* fData;
394 size_t fCount, fIdx;
395};
396} // namespace
397
398static void stream_copy_test(skiatest::Reporter* reporter,
399 const void* srcData,
400 size_t N,
401 SkStream* stream) {
402 SkDynamicMemoryWStream tgt;
403 if (!SkStreamCopy(&tgt, stream)) {
404 ERRORF(reporter, "SkStreamCopy failed");
405 return;
406 }
407 SkAutoTUnref<SkData> data(tgt.copyToData());
408 tgt.reset();
409 if (data->size() != N) {
410 ERRORF(reporter, "SkStreamCopy incorrect size");
411 return;
412 }
413 if (0 != memcmp(data->data(), srcData, N)) {
414 ERRORF(reporter, "SkStreamCopy bad copy");
415 }
416}
417
418DEF_TEST(StreamCopy, reporter) {
419 SkRandom random(123456);
halcanarycb9241b2015-08-19 06:12:40 -0700420 static const int N = 10000;
421 SkAutoTMalloc<uint8_t> src((size_t)N);
422 for (int j = 0; j < N; ++j) {
halcanary48305e82015-08-18 13:30:25 -0700423 src[j] = random.nextU() & 0xff;
424 }
425 // SkStreamCopy had two code paths; this test both.
halcanarycb9241b2015-08-19 06:12:40 -0700426 DumbStream dumbStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700427 stream_copy_test(reporter, src, N, &dumbStream);
halcanarycb9241b2015-08-19 06:12:40 -0700428 SkMemoryStream smartStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700429 stream_copy_test(reporter, src, N, &smartStream);
halcanary48305e82015-08-18 13:30:25 -0700430}
halcanary209c1622015-09-28 07:29:39 -0700431
432DEF_TEST(StreamEmptyStreamMemoryBase, r) {
433 SkDynamicMemoryWStream tmp;
434 SkAutoTDelete<SkStreamAsset> asset(tmp.detachAsStream());
435 REPORTER_ASSERT(r, nullptr == asset->getMemoryBase());
436}