blob: ff23ca2341c88dd6dc91be7301ab410ba02f5feb [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;
Mike Reedff80c2a2017-01-07 11:16:28 -0500149 SkDynamicMemoryWStream wstream;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000150
reed@google.com19f286b2011-10-18 11:49:52 +0000151 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
152 bool success = wstream.writePackedUInt(sizes[i]);
153 REPORTER_ASSERT(reporter, success);
154 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000155
Mike Reedff80c2a2017-01-07 11:16:28 -0500156 std::unique_ptr<SkStreamAsset> rstream(wstream.detachAsStream());
reed@google.com19f286b2011-10-18 11:49:52 +0000157 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
Mike Reedff80c2a2017-01-07 11:16:28 -0500158 size_t n = rstream->readPackedUInt();
reed@google.com19f286b2011-10-18 11:49:52 +0000159 if (sizes[i] != n) {
halcanary7d571242016-02-24 17:59:16 -0800160 ERRORF(reporter, "sizes:%x != n:%x\n", i, sizes[i], n);
reed@google.com19f286b2011-10-18 11:49:52 +0000161 }
reed@google.com19f286b2011-10-18 11:49:52 +0000162 }
163}
164
halcanary96fcdcc2015-08-27 07:41:13 -0700165// 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 +0000166// methods that access fData.
167static void TestDereferencingData(SkMemoryStream* memStream) {
halcanary96fcdcc2015-08-27 07:41:13 -0700168 memStream->read(nullptr, 0);
scroggo@google.come4904202013-01-09 22:02:58 +0000169 memStream->getMemoryBase();
reed42943c82016-09-12 12:01:44 -0700170 (void)memStream->asData();
scroggo@google.come4904202013-01-09 22:02:58 +0000171}
172
173static void TestNullData() {
reed42943c82016-09-12 12:01:44 -0700174 SkMemoryStream memStream(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000175 TestDereferencingData(&memStream);
176
reed42943c82016-09-12 12:01:44 -0700177 memStream.setData(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000178 TestDereferencingData(&memStream);
179
180}
181
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000182DEF_TEST(Stream, reporter) {
reed@android.com5e5adfd2009-03-07 03:39:23 +0000183 TestWStream(reporter);
reed@google.com19f286b2011-10-18 11:49:52 +0000184 TestPackedUInt(reporter);
scroggo@google.come4904202013-01-09 22:02:58 +0000185 TestNullData();
reed@android.com5e5adfd2009-03-07 03:39:23 +0000186}
scroggo028a4132015-04-02 13:19:51 -0700187
Mike Klein7d302882016-11-03 14:06:31 -0400188#ifndef SK_BUILD_FOR_IOS
scroggo028a4132015-04-02 13:19:51 -0700189/**
190 * Tests peeking and then reading the same amount. The two should provide the
191 * same results.
scroggod61c3842015-12-07 11:37:13 -0800192 * Returns the amount successfully read minus the amount successfully peeked.
scroggo028a4132015-04-02 13:19:51 -0700193 */
scroggod61c3842015-12-07 11:37:13 -0800194static size_t compare_peek_to_read(skiatest::Reporter* reporter,
195 SkStream* stream, size_t bytesToPeek) {
scroggo028a4132015-04-02 13:19:51 -0700196 // The rest of our tests won't be very interesting if bytesToPeek is zero.
197 REPORTER_ASSERT(reporter, bytesToPeek > 0);
198 SkAutoMalloc peekStorage(bytesToPeek);
199 SkAutoMalloc readStorage(bytesToPeek);
200 void* peekPtr = peekStorage.get();
201 void* readPtr = peekStorage.get();
202
scroggod61c3842015-12-07 11:37:13 -0800203 const size_t bytesPeeked = stream->peek(peekPtr, bytesToPeek);
scroggo028a4132015-04-02 13:19:51 -0700204 const size_t bytesRead = stream->read(readPtr, bytesToPeek);
205
206 // bytesRead should only be less than attempted if the stream is at the
207 // end.
208 REPORTER_ASSERT(reporter, bytesRead == bytesToPeek || stream->isAtEnd());
209
210 // peek and read should behave the same, except peek returned to the
211 // original position, so they read the same data.
scroggod61c3842015-12-07 11:37:13 -0800212 REPORTER_ASSERT(reporter, !memcmp(peekPtr, readPtr, bytesPeeked));
scroggo028a4132015-04-02 13:19:51 -0700213
scroggod61c3842015-12-07 11:37:13 -0800214 // A stream should never be able to peek more than it can read.
215 REPORTER_ASSERT(reporter, bytesRead >= bytesPeeked);
216
217 return bytesRead - bytesPeeked;
scroggo028a4132015-04-02 13:19:51 -0700218}
219
scroggod61c3842015-12-07 11:37:13 -0800220static void test_fully_peekable_stream(skiatest::Reporter* r, SkStream* stream, size_t limit) {
scroggo028a4132015-04-02 13:19:51 -0700221 for (size_t i = 1; !stream->isAtEnd(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800222 REPORTER_ASSERT(r, compare_peek_to_read(r, stream, i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700223 }
224}
225
226static void test_peeking_front_buffered_stream(skiatest::Reporter* r,
227 const SkStream& original,
228 size_t bufferSize) {
229 SkStream* dupe = original.duplicate();
halcanary96fcdcc2015-08-27 07:41:13 -0700230 REPORTER_ASSERT(r, dupe != nullptr);
Ben Wagner145dbcd2016-11-03 14:40:50 -0400231 std::unique_ptr<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize));
halcanary96fcdcc2015-08-27 07:41:13 -0700232 REPORTER_ASSERT(r, bufferedStream != nullptr);
scroggod61c3842015-12-07 11:37:13 -0800233
234 size_t peeked = 0;
235 for (size_t i = 1; !bufferedStream->isAtEnd(); i++) {
Ben Wagner145dbcd2016-11-03 14:40:50 -0400236 const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream.get(), i);
scroggod61c3842015-12-07 11:37:13 -0800237 if (unpeekableBytes > 0) {
238 // This could not have returned a number greater than i.
239 REPORTER_ASSERT(r, unpeekableBytes <= i);
240
241 // We have reached the end of the buffer. Verify that it was at least
242 // bufferSize.
243 REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize);
244 // No more peeking is supported.
245 break;
246 }
247 peeked += i;
248 }
249
250 // Test that attempting to peek beyond the length of the buffer does not prevent rewinding.
251 bufferedStream.reset(SkFrontBufferedStream::Create(original.duplicate(), bufferSize));
252 REPORTER_ASSERT(r, bufferedStream != nullptr);
253
254 const size_t bytesToPeek = bufferSize + 1;
255 SkAutoMalloc peekStorage(bytesToPeek);
256 SkAutoMalloc readStorage(bytesToPeek);
257
258 for (size_t start = 0; start <= bufferSize; start++) {
259 // Skip to the starting point
260 REPORTER_ASSERT(r, bufferedStream->skip(start) == start);
scroggod61c3842015-12-07 11:37:13 -0800261
262 const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek);
263 if (0 == bytesPeeked) {
scroggoef0fed32016-02-18 05:59:25 -0800264 // Peeking should only fail completely if we have read/skipped beyond the buffer.
265 REPORTER_ASSERT(r, start >= bufferSize);
scroggod61c3842015-12-07 11:37:13 -0800266 break;
267 }
268
269 // Only read the amount that was successfully peeked.
270 const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked);
271 REPORTER_ASSERT(r, bytesRead == bytesPeeked);
272 REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked));
273
274 // This should be safe to rewind.
275 REPORTER_ASSERT(r, bufferedStream->rewind());
276 }
scroggo028a4132015-04-02 13:19:51 -0700277}
278
halcanary9d524f22016-03-29 09:03:52 -0700279// This test uses file system operations that don't work out of the
280// box on iOS. It's likely that we don't need them on iOS. Ignoring for now.
281// TODO(stephana): Re-evaluate if we need this in the future.
scroggo028a4132015-04-02 13:19:51 -0700282DEF_TEST(StreamPeek, reporter) {
283 // Test a memory stream.
284 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz";
285 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
scroggod61c3842015-12-07 11:37:13 -0800286 test_fully_peekable_stream(reporter, &memStream, memStream.getLength());
scroggo028a4132015-04-02 13:19:51 -0700287
288 // Test an arbitrary file stream. file streams do not support peeking.
289 SkFILEStream fileStream(GetResourcePath("baby_tux.webp").c_str());
290 REPORTER_ASSERT(reporter, fileStream.isValid());
caryclark30ac4642015-04-14 06:08:04 -0700291 if (!fileStream.isValid()) {
292 return;
293 }
scroggo028a4132015-04-02 13:19:51 -0700294 SkAutoMalloc storage(fileStream.getLength());
295 for (size_t i = 1; i < fileStream.getLength(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800296 REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700297 }
298
299 // Now test some FrontBufferedStreams
300 for (size_t i = 1; i < memStream.getLength(); i++) {
301 test_peeking_front_buffered_stream(reporter, memStream, i);
302 }
303}
halcanarye797d0d2015-05-21 08:13:27 -0700304#endif
305
306// Asserts that asset == expected and is peekable.
307static void stream_peek_test(skiatest::Reporter* rep,
308 SkStreamAsset* asset,
309 const SkData* expected) {
310 if (asset->getLength() != expected->size()) {
311 ERRORF(rep, "Unexpected length.");
312 return;
313 }
314 SkRandom rand;
315 uint8_t buffer[4096];
316 const uint8_t* expect = expected->bytes();
317 for (size_t i = 0; i < asset->getLength(); ++i) {
318 uint32_t maxSize =
319 SkToU32(SkTMin(sizeof(buffer), asset->getLength() - i));
320 size_t size = rand.nextRangeU(1, maxSize);
321 SkASSERT(size >= 1);
322 SkASSERT(size <= sizeof(buffer));
323 SkASSERT(size + i <= asset->getLength());
scroggod61c3842015-12-07 11:37:13 -0800324 if (asset->peek(buffer, size) < size) {
halcanarye797d0d2015-05-21 08:13:27 -0700325 ERRORF(rep, "Peek Failed!");
326 return;
327 }
328 if (0 != memcmp(buffer, &expect[i], size)) {
329 ERRORF(rep, "Peek returned wrong bytes!");
330 return;
331 }
332 uint8_t value;
333 REPORTER_ASSERT(rep, 1 == asset->read(&value, 1));
334 if (value != expect[i]) {
335 ERRORF(rep, "Read Failed!");
336 return;
337 }
338 }
339}
340
341DEF_TEST(StreamPeek_BlockMemoryStream, rep) {
342 const static int kSeed = 1234;
343 SkRandom valueSource(kSeed);
344 SkRandom rand(kSeed << 1);
345 uint8_t buffer[4096];
346 SkDynamicMemoryWStream dynamicMemoryWStream;
Mike Reed49282292016-12-14 12:34:06 -0500347 size_t totalWritten = 0;
halcanarye797d0d2015-05-21 08:13:27 -0700348 for (int i = 0; i < 32; ++i) {
349 // Randomize the length of the blocks.
350 size_t size = rand.nextRangeU(1, sizeof(buffer));
351 for (size_t j = 0; j < size; ++j) {
352 buffer[j] = valueSource.nextU() & 0xFF;
353 }
354 dynamicMemoryWStream.write(buffer, size);
Mike Reed49282292016-12-14 12:34:06 -0500355 totalWritten += size;
356 REPORTER_ASSERT(rep, totalWritten == dynamicMemoryWStream.bytesWritten());
halcanarye797d0d2015-05-21 08:13:27 -0700357 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400358 std::unique_ptr<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream());
bungeman38d909e2016-08-02 14:40:46 -0700359 sk_sp<SkData> expected(SkData::MakeUninitialized(asset->getLength()));
halcanarye797d0d2015-05-21 08:13:27 -0700360 uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data());
361 valueSource.setSeed(kSeed); // reseed.
362 // We want the exact same same "random" string of numbers to put
363 // in expected. i.e.: don't rely on SkDynamicMemoryStream to work
364 // correctly while we are testing SkDynamicMemoryStream.
365 for (size_t i = 0; i < asset->getLength(); ++i) {
366 expectedPtr[i] = valueSource.nextU() & 0xFF;
367 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400368 stream_peek_test(rep, asset.get(), expected.get());
halcanarye797d0d2015-05-21 08:13:27 -0700369}
halcanary48305e82015-08-18 13:30:25 -0700370
371namespace {
372class DumbStream : public SkStream {
373public:
374 DumbStream(const uint8_t* data, size_t n)
375 : fData(data), fCount(n), fIdx(0) {}
376 size_t read(void* buffer, size_t size) override {
halcanaryd75e21d2015-08-19 07:22:04 -0700377 size_t copyCount = SkTMin(fCount - fIdx, size);
378 if (copyCount) {
379 memcpy(buffer, &fData[fIdx], copyCount);
380 fIdx += copyCount;
halcanary48305e82015-08-18 13:30:25 -0700381 }
halcanaryd75e21d2015-08-19 07:22:04 -0700382 return copyCount;
halcanary48305e82015-08-18 13:30:25 -0700383 }
384 bool isAtEnd() const override {
halcanaryd75e21d2015-08-19 07:22:04 -0700385 return fCount == fIdx;
halcanary48305e82015-08-18 13:30:25 -0700386 }
387 private:
388 const uint8_t* fData;
389 size_t fCount, fIdx;
390};
391} // namespace
392
393static void stream_copy_test(skiatest::Reporter* reporter,
394 const void* srcData,
395 size_t N,
396 SkStream* stream) {
397 SkDynamicMemoryWStream tgt;
398 if (!SkStreamCopy(&tgt, stream)) {
399 ERRORF(reporter, "SkStreamCopy failed");
400 return;
401 }
reed42943c82016-09-12 12:01:44 -0700402 sk_sp<SkData> data(tgt.detachAsData());
halcanary48305e82015-08-18 13:30:25 -0700403 if (data->size() != N) {
404 ERRORF(reporter, "SkStreamCopy incorrect size");
405 return;
406 }
407 if (0 != memcmp(data->data(), srcData, N)) {
408 ERRORF(reporter, "SkStreamCopy bad copy");
409 }
410}
411
412DEF_TEST(StreamCopy, reporter) {
413 SkRandom random(123456);
halcanarycb9241b2015-08-19 06:12:40 -0700414 static const int N = 10000;
415 SkAutoTMalloc<uint8_t> src((size_t)N);
416 for (int j = 0; j < N; ++j) {
halcanary48305e82015-08-18 13:30:25 -0700417 src[j] = random.nextU() & 0xff;
418 }
419 // SkStreamCopy had two code paths; this test both.
halcanarycb9241b2015-08-19 06:12:40 -0700420 DumbStream dumbStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700421 stream_copy_test(reporter, src, N, &dumbStream);
halcanarycb9241b2015-08-19 06:12:40 -0700422 SkMemoryStream smartStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700423 stream_copy_test(reporter, src, N, &smartStream);
halcanary48305e82015-08-18 13:30:25 -0700424}
halcanary209c1622015-09-28 07:29:39 -0700425
426DEF_TEST(StreamEmptyStreamMemoryBase, r) {
427 SkDynamicMemoryWStream tmp;
Ben Wagner145dbcd2016-11-03 14:40:50 -0400428 std::unique_ptr<SkStreamAsset> asset(tmp.detachAsStream());
halcanary209c1622015-09-28 07:29:39 -0700429 REPORTER_ASSERT(r, nullptr == asset->getMemoryBase());
430}
Mike Reed1026ccf2017-01-08 14:35:29 -0500431
432#include "SkBuffer.h"
433
434DEF_TEST(RBuffer, reporter) {
435 int32_t value = 0;
436 SkRBuffer buffer(&value, 4);
437 REPORTER_ASSERT(reporter, buffer.isValid());
438
439 int32_t tmp;
440 REPORTER_ASSERT(reporter, buffer.read(&tmp, 4));
441 REPORTER_ASSERT(reporter, buffer.isValid());
442
443 REPORTER_ASSERT(reporter, !buffer.read(&tmp, 4));
444 REPORTER_ASSERT(reporter, !buffer.isValid());
445}