blob: 15ebfcf07d63bc29345fbcac227fd3e803eb5091 [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) {
167 SkDebugf("-- %d: sizes:%x n:%x\n", i, sizes[i], n);
168 }
169 REPORTER_ASSERT(reporter, sizes[i] == n);
170 }
171}
172
halcanary96fcdcc2015-08-27 07:41:13 -0700173// 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 +0000174// methods that access fData.
175static void TestDereferencingData(SkMemoryStream* memStream) {
halcanary96fcdcc2015-08-27 07:41:13 -0700176 memStream->read(nullptr, 0);
scroggo@google.come4904202013-01-09 22:02:58 +0000177 memStream->getMemoryBase();
178 SkAutoDataUnref data(memStream->copyToData());
179}
180
181static void TestNullData() {
halcanary96fcdcc2015-08-27 07:41:13 -0700182 SkData* nullData = nullptr;
scroggo@google.come4904202013-01-09 22:02:58 +0000183 SkMemoryStream memStream(nullData);
184 TestDereferencingData(&memStream);
185
186 memStream.setData(nullData);
187 TestDereferencingData(&memStream);
188
189}
190
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000191DEF_TEST(Stream, reporter) {
reed@android.com5e5adfd2009-03-07 03:39:23 +0000192 TestWStream(reporter);
reed@google.com19f286b2011-10-18 11:49:52 +0000193 TestPackedUInt(reporter);
scroggo@google.come4904202013-01-09 22:02:58 +0000194 TestNullData();
reed@android.com5e5adfd2009-03-07 03:39:23 +0000195}
scroggo028a4132015-04-02 13:19:51 -0700196
197/**
198 * Tests peeking and then reading the same amount. The two should provide the
199 * same results.
scroggod61c3842015-12-07 11:37:13 -0800200 * Returns the amount successfully read minus the amount successfully peeked.
scroggo028a4132015-04-02 13:19:51 -0700201 */
scroggod61c3842015-12-07 11:37:13 -0800202static size_t compare_peek_to_read(skiatest::Reporter* reporter,
203 SkStream* stream, size_t bytesToPeek) {
scroggo028a4132015-04-02 13:19:51 -0700204 // The rest of our tests won't be very interesting if bytesToPeek is zero.
205 REPORTER_ASSERT(reporter, bytesToPeek > 0);
206 SkAutoMalloc peekStorage(bytesToPeek);
207 SkAutoMalloc readStorage(bytesToPeek);
208 void* peekPtr = peekStorage.get();
209 void* readPtr = peekStorage.get();
210
scroggod61c3842015-12-07 11:37:13 -0800211 const size_t bytesPeeked = stream->peek(peekPtr, bytesToPeek);
scroggo028a4132015-04-02 13:19:51 -0700212 const size_t bytesRead = stream->read(readPtr, bytesToPeek);
213
214 // bytesRead should only be less than attempted if the stream is at the
215 // end.
216 REPORTER_ASSERT(reporter, bytesRead == bytesToPeek || stream->isAtEnd());
217
218 // peek and read should behave the same, except peek returned to the
219 // original position, so they read the same data.
scroggod61c3842015-12-07 11:37:13 -0800220 REPORTER_ASSERT(reporter, !memcmp(peekPtr, readPtr, bytesPeeked));
scroggo028a4132015-04-02 13:19:51 -0700221
scroggod61c3842015-12-07 11:37:13 -0800222 // A stream should never be able to peek more than it can read.
223 REPORTER_ASSERT(reporter, bytesRead >= bytesPeeked);
224
225 return bytesRead - bytesPeeked;
scroggo028a4132015-04-02 13:19:51 -0700226}
227
scroggod61c3842015-12-07 11:37:13 -0800228static void test_fully_peekable_stream(skiatest::Reporter* r, SkStream* stream, size_t limit) {
scroggo028a4132015-04-02 13:19:51 -0700229 for (size_t i = 1; !stream->isAtEnd(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800230 REPORTER_ASSERT(r, compare_peek_to_read(r, stream, i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700231 }
232}
233
234static void test_peeking_front_buffered_stream(skiatest::Reporter* r,
235 const SkStream& original,
236 size_t bufferSize) {
237 SkStream* dupe = original.duplicate();
halcanary96fcdcc2015-08-27 07:41:13 -0700238 REPORTER_ASSERT(r, dupe != nullptr);
scroggo028a4132015-04-02 13:19:51 -0700239 SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize));
halcanary96fcdcc2015-08-27 07:41:13 -0700240 REPORTER_ASSERT(r, bufferedStream != nullptr);
scroggod61c3842015-12-07 11:37:13 -0800241
242 size_t peeked = 0;
243 for (size_t i = 1; !bufferedStream->isAtEnd(); i++) {
244 const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream, i);
245 if (unpeekableBytes > 0) {
246 // This could not have returned a number greater than i.
247 REPORTER_ASSERT(r, unpeekableBytes <= i);
248
249 // We have reached the end of the buffer. Verify that it was at least
250 // bufferSize.
251 REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize);
252 // No more peeking is supported.
253 break;
254 }
255 peeked += i;
256 }
257
258 // Test that attempting to peek beyond the length of the buffer does not prevent rewinding.
259 bufferedStream.reset(SkFrontBufferedStream::Create(original.duplicate(), bufferSize));
260 REPORTER_ASSERT(r, bufferedStream != nullptr);
261
262 const size_t bytesToPeek = bufferSize + 1;
263 SkAutoMalloc peekStorage(bytesToPeek);
264 SkAutoMalloc readStorage(bytesToPeek);
265
266 for (size_t start = 0; start <= bufferSize; start++) {
267 // Skip to the starting point
268 REPORTER_ASSERT(r, bufferedStream->skip(start) == start);
269 REPORTER_ASSERT(r, bufferedStream->getPosition() == start);
270
271 const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek);
272 if (0 == bytesPeeked) {
273 // Peeking should only fail completely if we have read beyond the buffer.
274 REPORTER_ASSERT(r, bufferedStream->getPosition() >= bufferSize);
275 break;
276 }
277
278 // Only read the amount that was successfully peeked.
279 const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked);
280 REPORTER_ASSERT(r, bytesRead == bytesPeeked);
281 REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked));
282
283 // This should be safe to rewind.
284 REPORTER_ASSERT(r, bufferedStream->rewind());
285 }
scroggo028a4132015-04-02 13:19:51 -0700286}
287
stephana195f62d2015-04-09 07:57:54 -0700288// This test uses file system operations that don't work out of the
289// box on iOS. It's likely that we don't need them on iOS. Ignoring for now.
290// TODO(stephana): Re-evaluate if we need this in the future.
291#ifndef SK_BUILD_FOR_IOS
scroggo028a4132015-04-02 13:19:51 -0700292DEF_TEST(StreamPeek, reporter) {
293 // Test a memory stream.
294 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz";
295 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
scroggod61c3842015-12-07 11:37:13 -0800296 test_fully_peekable_stream(reporter, &memStream, memStream.getLength());
scroggo028a4132015-04-02 13:19:51 -0700297
298 // Test an arbitrary file stream. file streams do not support peeking.
299 SkFILEStream fileStream(GetResourcePath("baby_tux.webp").c_str());
300 REPORTER_ASSERT(reporter, fileStream.isValid());
caryclark30ac4642015-04-14 06:08:04 -0700301 if (!fileStream.isValid()) {
302 return;
303 }
scroggo028a4132015-04-02 13:19:51 -0700304 SkAutoMalloc storage(fileStream.getLength());
305 for (size_t i = 1; i < fileStream.getLength(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800306 REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700307 }
308
309 // Now test some FrontBufferedStreams
310 for (size_t i = 1; i < memStream.getLength(); i++) {
311 test_peeking_front_buffered_stream(reporter, memStream, i);
312 }
313}
halcanarye797d0d2015-05-21 08:13:27 -0700314#endif
315
316// Asserts that asset == expected and is peekable.
317static void stream_peek_test(skiatest::Reporter* rep,
318 SkStreamAsset* asset,
319 const SkData* expected) {
320 if (asset->getLength() != expected->size()) {
321 ERRORF(rep, "Unexpected length.");
322 return;
323 }
324 SkRandom rand;
325 uint8_t buffer[4096];
326 const uint8_t* expect = expected->bytes();
327 for (size_t i = 0; i < asset->getLength(); ++i) {
328 uint32_t maxSize =
329 SkToU32(SkTMin(sizeof(buffer), asset->getLength() - i));
330 size_t size = rand.nextRangeU(1, maxSize);
331 SkASSERT(size >= 1);
332 SkASSERT(size <= sizeof(buffer));
333 SkASSERT(size + i <= asset->getLength());
scroggod61c3842015-12-07 11:37:13 -0800334 if (asset->peek(buffer, size) < size) {
halcanarye797d0d2015-05-21 08:13:27 -0700335 ERRORF(rep, "Peek Failed!");
336 return;
337 }
338 if (0 != memcmp(buffer, &expect[i], size)) {
339 ERRORF(rep, "Peek returned wrong bytes!");
340 return;
341 }
342 uint8_t value;
343 REPORTER_ASSERT(rep, 1 == asset->read(&value, 1));
344 if (value != expect[i]) {
345 ERRORF(rep, "Read Failed!");
346 return;
347 }
348 }
349}
350
351DEF_TEST(StreamPeek_BlockMemoryStream, rep) {
352 const static int kSeed = 1234;
353 SkRandom valueSource(kSeed);
354 SkRandom rand(kSeed << 1);
355 uint8_t buffer[4096];
356 SkDynamicMemoryWStream dynamicMemoryWStream;
357 for (int i = 0; i < 32; ++i) {
358 // Randomize the length of the blocks.
359 size_t size = rand.nextRangeU(1, sizeof(buffer));
360 for (size_t j = 0; j < size; ++j) {
361 buffer[j] = valueSource.nextU() & 0xFF;
362 }
363 dynamicMemoryWStream.write(buffer, size);
364 }
365 SkAutoTDelete<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream());
366 SkAutoTUnref<SkData> expected(SkData::NewUninitialized(asset->getLength()));
367 uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data());
368 valueSource.setSeed(kSeed); // reseed.
369 // We want the exact same same "random" string of numbers to put
370 // in expected. i.e.: don't rely on SkDynamicMemoryStream to work
371 // correctly while we are testing SkDynamicMemoryStream.
372 for (size_t i = 0; i < asset->getLength(); ++i) {
373 expectedPtr[i] = valueSource.nextU() & 0xFF;
374 }
375 stream_peek_test(rep, asset, expected);
376}
halcanary48305e82015-08-18 13:30:25 -0700377
378namespace {
379class DumbStream : public SkStream {
380public:
381 DumbStream(const uint8_t* data, size_t n)
382 : fData(data), fCount(n), fIdx(0) {}
383 size_t read(void* buffer, size_t size) override {
halcanaryd75e21d2015-08-19 07:22:04 -0700384 size_t copyCount = SkTMin(fCount - fIdx, size);
385 if (copyCount) {
386 memcpy(buffer, &fData[fIdx], copyCount);
387 fIdx += copyCount;
halcanary48305e82015-08-18 13:30:25 -0700388 }
halcanaryd75e21d2015-08-19 07:22:04 -0700389 return copyCount;
halcanary48305e82015-08-18 13:30:25 -0700390 }
391 bool isAtEnd() const override {
halcanaryd75e21d2015-08-19 07:22:04 -0700392 return fCount == fIdx;
halcanary48305e82015-08-18 13:30:25 -0700393 }
394 private:
395 const uint8_t* fData;
396 size_t fCount, fIdx;
397};
398} // namespace
399
400static void stream_copy_test(skiatest::Reporter* reporter,
401 const void* srcData,
402 size_t N,
403 SkStream* stream) {
404 SkDynamicMemoryWStream tgt;
405 if (!SkStreamCopy(&tgt, stream)) {
406 ERRORF(reporter, "SkStreamCopy failed");
407 return;
408 }
409 SkAutoTUnref<SkData> data(tgt.copyToData());
410 tgt.reset();
411 if (data->size() != N) {
412 ERRORF(reporter, "SkStreamCopy incorrect size");
413 return;
414 }
415 if (0 != memcmp(data->data(), srcData, N)) {
416 ERRORF(reporter, "SkStreamCopy bad copy");
417 }
418}
419
420DEF_TEST(StreamCopy, reporter) {
421 SkRandom random(123456);
halcanarycb9241b2015-08-19 06:12:40 -0700422 static const int N = 10000;
423 SkAutoTMalloc<uint8_t> src((size_t)N);
424 for (int j = 0; j < N; ++j) {
halcanary48305e82015-08-18 13:30:25 -0700425 src[j] = random.nextU() & 0xff;
426 }
427 // SkStreamCopy had two code paths; this test both.
halcanarycb9241b2015-08-19 06:12:40 -0700428 DumbStream dumbStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700429 stream_copy_test(reporter, src, N, &dumbStream);
halcanarycb9241b2015-08-19 06:12:40 -0700430 SkMemoryStream smartStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700431 stream_copy_test(reporter, src, N, &smartStream);
halcanary48305e82015-08-18 13:30:25 -0700432}
halcanary209c1622015-09-28 07:29:39 -0700433
434DEF_TEST(StreamEmptyStreamMemoryBase, r) {
435 SkDynamicMemoryWStream tmp;
436 SkAutoTDelete<SkStreamAsset> asset(tmp.detachAsStream());
437 REPORTER_ASSERT(r, nullptr == asset->getMemoryBase());
438}
439