blob: 2a60a7b10f921dd6988e75cea280ff1a61ab06fa [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);
scroggod61c3842015-12-07 11:37:13 -0800269
270 const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek);
271 if (0 == bytesPeeked) {
scroggoef0fed32016-02-18 05:59:25 -0800272 // Peeking should only fail completely if we have read/skipped beyond the buffer.
273 REPORTER_ASSERT(r, start >= bufferSize);
scroggod61c3842015-12-07 11:37:13 -0800274 break;
275 }
276
277 // Only read the amount that was successfully peeked.
278 const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked);
279 REPORTER_ASSERT(r, bytesRead == bytesPeeked);
280 REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked));
281
282 // This should be safe to rewind.
283 REPORTER_ASSERT(r, bufferedStream->rewind());
284 }
scroggo028a4132015-04-02 13:19:51 -0700285}
286
stephana195f62d2015-04-09 07:57:54 -0700287// This test uses file system operations that don't work out of the
288// box on iOS. It's likely that we don't need them on iOS. Ignoring for now.
289// TODO(stephana): Re-evaluate if we need this in the future.
290#ifndef SK_BUILD_FOR_IOS
scroggo028a4132015-04-02 13:19:51 -0700291DEF_TEST(StreamPeek, reporter) {
292 // Test a memory stream.
293 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz";
294 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
scroggod61c3842015-12-07 11:37:13 -0800295 test_fully_peekable_stream(reporter, &memStream, memStream.getLength());
scroggo028a4132015-04-02 13:19:51 -0700296
297 // Test an arbitrary file stream. file streams do not support peeking.
298 SkFILEStream fileStream(GetResourcePath("baby_tux.webp").c_str());
299 REPORTER_ASSERT(reporter, fileStream.isValid());
caryclark30ac4642015-04-14 06:08:04 -0700300 if (!fileStream.isValid()) {
301 return;
302 }
scroggo028a4132015-04-02 13:19:51 -0700303 SkAutoMalloc storage(fileStream.getLength());
304 for (size_t i = 1; i < fileStream.getLength(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800305 REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700306 }
307
308 // Now test some FrontBufferedStreams
309 for (size_t i = 1; i < memStream.getLength(); i++) {
310 test_peeking_front_buffered_stream(reporter, memStream, i);
311 }
312}
halcanarye797d0d2015-05-21 08:13:27 -0700313#endif
314
315// Asserts that asset == expected and is peekable.
316static void stream_peek_test(skiatest::Reporter* rep,
317 SkStreamAsset* asset,
318 const SkData* expected) {
319 if (asset->getLength() != expected->size()) {
320 ERRORF(rep, "Unexpected length.");
321 return;
322 }
323 SkRandom rand;
324 uint8_t buffer[4096];
325 const uint8_t* expect = expected->bytes();
326 for (size_t i = 0; i < asset->getLength(); ++i) {
327 uint32_t maxSize =
328 SkToU32(SkTMin(sizeof(buffer), asset->getLength() - i));
329 size_t size = rand.nextRangeU(1, maxSize);
330 SkASSERT(size >= 1);
331 SkASSERT(size <= sizeof(buffer));
332 SkASSERT(size + i <= asset->getLength());
scroggod61c3842015-12-07 11:37:13 -0800333 if (asset->peek(buffer, size) < size) {
halcanarye797d0d2015-05-21 08:13:27 -0700334 ERRORF(rep, "Peek Failed!");
335 return;
336 }
337 if (0 != memcmp(buffer, &expect[i], size)) {
338 ERRORF(rep, "Peek returned wrong bytes!");
339 return;
340 }
341 uint8_t value;
342 REPORTER_ASSERT(rep, 1 == asset->read(&value, 1));
343 if (value != expect[i]) {
344 ERRORF(rep, "Read Failed!");
345 return;
346 }
347 }
348}
349
350DEF_TEST(StreamPeek_BlockMemoryStream, rep) {
351 const static int kSeed = 1234;
352 SkRandom valueSource(kSeed);
353 SkRandom rand(kSeed << 1);
354 uint8_t buffer[4096];
355 SkDynamicMemoryWStream dynamicMemoryWStream;
356 for (int i = 0; i < 32; ++i) {
357 // Randomize the length of the blocks.
358 size_t size = rand.nextRangeU(1, sizeof(buffer));
359 for (size_t j = 0; j < size; ++j) {
360 buffer[j] = valueSource.nextU() & 0xFF;
361 }
362 dynamicMemoryWStream.write(buffer, size);
363 }
364 SkAutoTDelete<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream());
365 SkAutoTUnref<SkData> expected(SkData::NewUninitialized(asset->getLength()));
366 uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data());
367 valueSource.setSeed(kSeed); // reseed.
368 // We want the exact same same "random" string of numbers to put
369 // in expected. i.e.: don't rely on SkDynamicMemoryStream to work
370 // correctly while we are testing SkDynamicMemoryStream.
371 for (size_t i = 0; i < asset->getLength(); ++i) {
372 expectedPtr[i] = valueSource.nextU() & 0xFF;
373 }
374 stream_peek_test(rep, asset, expected);
375}
halcanary48305e82015-08-18 13:30:25 -0700376
377namespace {
378class DumbStream : public SkStream {
379public:
380 DumbStream(const uint8_t* data, size_t n)
381 : fData(data), fCount(n), fIdx(0) {}
382 size_t read(void* buffer, size_t size) override {
halcanaryd75e21d2015-08-19 07:22:04 -0700383 size_t copyCount = SkTMin(fCount - fIdx, size);
384 if (copyCount) {
385 memcpy(buffer, &fData[fIdx], copyCount);
386 fIdx += copyCount;
halcanary48305e82015-08-18 13:30:25 -0700387 }
halcanaryd75e21d2015-08-19 07:22:04 -0700388 return copyCount;
halcanary48305e82015-08-18 13:30:25 -0700389 }
390 bool isAtEnd() const override {
halcanaryd75e21d2015-08-19 07:22:04 -0700391 return fCount == fIdx;
halcanary48305e82015-08-18 13:30:25 -0700392 }
393 private:
394 const uint8_t* fData;
395 size_t fCount, fIdx;
396};
397} // namespace
398
399static void stream_copy_test(skiatest::Reporter* reporter,
400 const void* srcData,
401 size_t N,
402 SkStream* stream) {
403 SkDynamicMemoryWStream tgt;
404 if (!SkStreamCopy(&tgt, stream)) {
405 ERRORF(reporter, "SkStreamCopy failed");
406 return;
407 }
408 SkAutoTUnref<SkData> data(tgt.copyToData());
409 tgt.reset();
410 if (data->size() != N) {
411 ERRORF(reporter, "SkStreamCopy incorrect size");
412 return;
413 }
414 if (0 != memcmp(data->data(), srcData, N)) {
415 ERRORF(reporter, "SkStreamCopy bad copy");
416 }
417}
418
419DEF_TEST(StreamCopy, reporter) {
420 SkRandom random(123456);
halcanarycb9241b2015-08-19 06:12:40 -0700421 static const int N = 10000;
422 SkAutoTMalloc<uint8_t> src((size_t)N);
423 for (int j = 0; j < N; ++j) {
halcanary48305e82015-08-18 13:30:25 -0700424 src[j] = random.nextU() & 0xff;
425 }
426 // SkStreamCopy had two code paths; this test both.
halcanarycb9241b2015-08-19 06:12:40 -0700427 DumbStream dumbStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700428 stream_copy_test(reporter, src, N, &dumbStream);
halcanarycb9241b2015-08-19 06:12:40 -0700429 SkMemoryStream smartStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700430 stream_copy_test(reporter, src, N, &smartStream);
halcanary48305e82015-08-18 13:30:25 -0700431}
halcanary209c1622015-09-28 07:29:39 -0700432
433DEF_TEST(StreamEmptyStreamMemoryBase, r) {
434 SkDynamicMemoryWStream tmp;
435 SkAutoTDelete<SkStreamAsset> asset(tmp.detachAsStream());
436 REPORTER_ASSERT(r, nullptr == asset->getMemoryBase());
437}
438