blob: b99b0011934571d6e9da3a895cc78c9509bfaf52 [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
Ben Wagner145dbcd2016-11-03 14:40:50 -040064 std::unique_ptr<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
Ben Wagner145dbcd2016-11-03 14:40:50 -040074 std::unique_ptr<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 {
Ben Wagner145dbcd2016-11-03 14:40:50 -040097 std::unique_ptr<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
Ben Wagner145dbcd2016-11-03 14:40:50 -0400102 std::unique_ptr<SkStreamAsset> stream2(stream->duplicate());
bungeman@google.com88682b72013-07-19 13:55:41 +0000103 test_loop_stream(reporter, stream2.get(), s, 26, 100);
104
Ben Wagner145dbcd2016-11-03 14:40:50 -0400105 std::unique_ptr<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 {
reed42943c82016-09-12 12:01:44 -0700120 sk_sp<SkData> data = ds.snapshotAsData();
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 {
reed42943c82016-09-12 12:01:44 -0700126 // Test that this works after a snapshot.
Ben Wagner145dbcd2016-11-03 14:40:50 -0400127 std::unique_ptr<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
Ben Wagner145dbcd2016-11-03 14:40:50 -0400131 std::unique_ptr<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();
reed42943c82016-09-12 12:01:44 -0700177 (void)memStream->asData();
scroggo@google.come4904202013-01-09 22:02:58 +0000178}
179
180static void TestNullData() {
reed42943c82016-09-12 12:01:44 -0700181 SkMemoryStream memStream(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000182 TestDereferencingData(&memStream);
183
reed42943c82016-09-12 12:01:44 -0700184 memStream.setData(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000185 TestDereferencingData(&memStream);
186
187}
188
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000189DEF_TEST(Stream, reporter) {
reed@android.com5e5adfd2009-03-07 03:39:23 +0000190 TestWStream(reporter);
reed@google.com19f286b2011-10-18 11:49:52 +0000191 TestPackedUInt(reporter);
scroggo@google.come4904202013-01-09 22:02:58 +0000192 TestNullData();
reed@android.com5e5adfd2009-03-07 03:39:23 +0000193}
scroggo028a4132015-04-02 13:19:51 -0700194
Mike Klein7d302882016-11-03 14:06:31 -0400195#ifndef SK_BUILD_FOR_IOS
scroggo028a4132015-04-02 13:19:51 -0700196/**
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);
Ben Wagner145dbcd2016-11-03 14:40:50 -0400238 std::unique_ptr<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++) {
Ben Wagner145dbcd2016-11-03 14:40:50 -0400243 const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream.get(), i);
scroggod61c3842015-12-07 11:37:13 -0800244 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.
scroggo028a4132015-04-02 13:19:51 -0700289DEF_TEST(StreamPeek, reporter) {
290 // Test a memory stream.
291 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz";
292 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
scroggod61c3842015-12-07 11:37:13 -0800293 test_fully_peekable_stream(reporter, &memStream, memStream.getLength());
scroggo028a4132015-04-02 13:19:51 -0700294
295 // Test an arbitrary file stream. file streams do not support peeking.
296 SkFILEStream fileStream(GetResourcePath("baby_tux.webp").c_str());
297 REPORTER_ASSERT(reporter, fileStream.isValid());
caryclark30ac4642015-04-14 06:08:04 -0700298 if (!fileStream.isValid()) {
299 return;
300 }
scroggo028a4132015-04-02 13:19:51 -0700301 SkAutoMalloc storage(fileStream.getLength());
302 for (size_t i = 1; i < fileStream.getLength(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800303 REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700304 }
305
306 // Now test some FrontBufferedStreams
307 for (size_t i = 1; i < memStream.getLength(); i++) {
308 test_peeking_front_buffered_stream(reporter, memStream, i);
309 }
310}
halcanarye797d0d2015-05-21 08:13:27 -0700311#endif
312
313// Asserts that asset == expected and is peekable.
314static void stream_peek_test(skiatest::Reporter* rep,
315 SkStreamAsset* asset,
316 const SkData* expected) {
317 if (asset->getLength() != expected->size()) {
318 ERRORF(rep, "Unexpected length.");
319 return;
320 }
321 SkRandom rand;
322 uint8_t buffer[4096];
323 const uint8_t* expect = expected->bytes();
324 for (size_t i = 0; i < asset->getLength(); ++i) {
325 uint32_t maxSize =
326 SkToU32(SkTMin(sizeof(buffer), asset->getLength() - i));
327 size_t size = rand.nextRangeU(1, maxSize);
328 SkASSERT(size >= 1);
329 SkASSERT(size <= sizeof(buffer));
330 SkASSERT(size + i <= asset->getLength());
scroggod61c3842015-12-07 11:37:13 -0800331 if (asset->peek(buffer, size) < size) {
halcanarye797d0d2015-05-21 08:13:27 -0700332 ERRORF(rep, "Peek Failed!");
333 return;
334 }
335 if (0 != memcmp(buffer, &expect[i], size)) {
336 ERRORF(rep, "Peek returned wrong bytes!");
337 return;
338 }
339 uint8_t value;
340 REPORTER_ASSERT(rep, 1 == asset->read(&value, 1));
341 if (value != expect[i]) {
342 ERRORF(rep, "Read Failed!");
343 return;
344 }
345 }
346}
347
348DEF_TEST(StreamPeek_BlockMemoryStream, rep) {
349 const static int kSeed = 1234;
350 SkRandom valueSource(kSeed);
351 SkRandom rand(kSeed << 1);
352 uint8_t buffer[4096];
353 SkDynamicMemoryWStream dynamicMemoryWStream;
354 for (int i = 0; i < 32; ++i) {
355 // Randomize the length of the blocks.
356 size_t size = rand.nextRangeU(1, sizeof(buffer));
357 for (size_t j = 0; j < size; ++j) {
358 buffer[j] = valueSource.nextU() & 0xFF;
359 }
360 dynamicMemoryWStream.write(buffer, size);
361 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400362 std::unique_ptr<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream());
bungeman38d909e2016-08-02 14:40:46 -0700363 sk_sp<SkData> expected(SkData::MakeUninitialized(asset->getLength()));
halcanarye797d0d2015-05-21 08:13:27 -0700364 uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data());
365 valueSource.setSeed(kSeed); // reseed.
366 // We want the exact same same "random" string of numbers to put
367 // in expected. i.e.: don't rely on SkDynamicMemoryStream to work
368 // correctly while we are testing SkDynamicMemoryStream.
369 for (size_t i = 0; i < asset->getLength(); ++i) {
370 expectedPtr[i] = valueSource.nextU() & 0xFF;
371 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400372 stream_peek_test(rep, asset.get(), expected.get());
halcanarye797d0d2015-05-21 08:13:27 -0700373}
halcanary48305e82015-08-18 13:30:25 -0700374
375namespace {
376class DumbStream : public SkStream {
377public:
378 DumbStream(const uint8_t* data, size_t n)
379 : fData(data), fCount(n), fIdx(0) {}
380 size_t read(void* buffer, size_t size) override {
halcanaryd75e21d2015-08-19 07:22:04 -0700381 size_t copyCount = SkTMin(fCount - fIdx, size);
382 if (copyCount) {
383 memcpy(buffer, &fData[fIdx], copyCount);
384 fIdx += copyCount;
halcanary48305e82015-08-18 13:30:25 -0700385 }
halcanaryd75e21d2015-08-19 07:22:04 -0700386 return copyCount;
halcanary48305e82015-08-18 13:30:25 -0700387 }
388 bool isAtEnd() const override {
halcanaryd75e21d2015-08-19 07:22:04 -0700389 return fCount == fIdx;
halcanary48305e82015-08-18 13:30:25 -0700390 }
391 private:
392 const uint8_t* fData;
393 size_t fCount, fIdx;
394};
395} // namespace
396
397static void stream_copy_test(skiatest::Reporter* reporter,
398 const void* srcData,
399 size_t N,
400 SkStream* stream) {
401 SkDynamicMemoryWStream tgt;
402 if (!SkStreamCopy(&tgt, stream)) {
403 ERRORF(reporter, "SkStreamCopy failed");
404 return;
405 }
reed42943c82016-09-12 12:01:44 -0700406 sk_sp<SkData> data(tgt.detachAsData());
halcanary48305e82015-08-18 13:30:25 -0700407 if (data->size() != N) {
408 ERRORF(reporter, "SkStreamCopy incorrect size");
409 return;
410 }
411 if (0 != memcmp(data->data(), srcData, N)) {
412 ERRORF(reporter, "SkStreamCopy bad copy");
413 }
414}
415
416DEF_TEST(StreamCopy, reporter) {
417 SkRandom random(123456);
halcanarycb9241b2015-08-19 06:12:40 -0700418 static const int N = 10000;
419 SkAutoTMalloc<uint8_t> src((size_t)N);
420 for (int j = 0; j < N; ++j) {
halcanary48305e82015-08-18 13:30:25 -0700421 src[j] = random.nextU() & 0xff;
422 }
423 // SkStreamCopy had two code paths; this test both.
halcanarycb9241b2015-08-19 06:12:40 -0700424 DumbStream dumbStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700425 stream_copy_test(reporter, src, N, &dumbStream);
halcanarycb9241b2015-08-19 06:12:40 -0700426 SkMemoryStream smartStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700427 stream_copy_test(reporter, src, N, &smartStream);
halcanary48305e82015-08-18 13:30:25 -0700428}
halcanary209c1622015-09-28 07:29:39 -0700429
430DEF_TEST(StreamEmptyStreamMemoryBase, r) {
431 SkDynamicMemoryWStream tmp;
Ben Wagner145dbcd2016-11-03 14:40:50 -0400432 std::unique_ptr<SkStreamAsset> asset(tmp.detachAsStream());
halcanary209c1622015-09-28 07:29:39 -0700433 REPORTER_ASSERT(r, nullptr == asset->getMemoryBase());
434}