blob: 01967b70b05cbba4bd8aa31b62e157b131767ea8 [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"
Hal Canary95e3c052017-01-11 12:44:43 -05009#include "SkAutoMalloc.h"
reed@google.com8d0b5772011-06-24 13:07:31 +000010#include "SkData.h"
scroggo028a4132015-04-02 13:19:51 -070011#include "SkFrontBufferedStream.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000012#include "SkOSFile.h"
Ben Wagnerbf111d72016-11-07 18:05:29 -050013#include "SkOSPath.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000014#include "SkRandom.h"
15#include "SkStream.h"
halcanary48305e82015-08-18 13:30:25 -070016#include "SkStreamPriv.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000017#include "Test.h"
reed@android.com5e5adfd2009-03-07 03:39:23 +000018
reed@google.com789c6f22013-02-25 20:24:24 +000019#ifndef SK_BUILD_FOR_WIN
20#include <unistd.h>
21#include <fcntl.h>
22#endif
23
reed@android.com5e5adfd2009-03-07 03:39:23 +000024#define MAX_SIZE (256 * 1024)
25
reed@google.com789c6f22013-02-25 20:24:24 +000026static void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream,
27 const void* src, size_t len, int repeat) {
28 SkAutoSMalloc<256> storage(len);
29 void* tmp = storage.get();
30
31 for (int i = 0; i < repeat; ++i) {
32 size_t bytes = stream->read(tmp, len);
33 REPORTER_ASSERT(reporter, bytes == len);
34 REPORTER_ASSERT(reporter, !memcmp(tmp, src, len));
35 }
36
37 // expect EOF
38 size_t bytes = stream->read(tmp, 1);
39 REPORTER_ASSERT(reporter, 0 == bytes);
bungeman@google.com88682b72013-07-19 13:55:41 +000040 // isAtEnd might not return true until after the first failing read.
41 REPORTER_ASSERT(reporter, stream->isAtEnd());
reed@google.com789c6f22013-02-25 20:24:24 +000042}
43
44static void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) {
tfarinaa8e2e152014-07-28 19:26:58 -070045 SkString path = SkOSPath::Join(tmpDir, "wstream_test");
reed@google.com789c6f22013-02-25 20:24:24 +000046
47 const char s[] = "abcdefghijklmnopqrstuvwxyz";
48
49 {
50 SkFILEWStream writer(path.c_str());
51 if (!writer.isValid()) {
halcanary@google.coma9325fa2014-01-10 14:58:10 +000052 ERRORF(reporter, "Failed to create tmp file %s\n", path.c_str());
reed@google.com789c6f22013-02-25 20:24:24 +000053 return;
54 }
55
56 for (int i = 0; i < 100; ++i) {
57 writer.write(s, 26);
58 }
59 }
60
61 {
62 SkFILEStream stream(path.c_str());
63 REPORTER_ASSERT(reporter, stream.isValid());
64 test_loop_stream(reporter, &stream, s, 26, 100);
bungeman@google.com6cab1a42013-05-29 13:43:31 +000065
Ben Wagner145dbcd2016-11-03 14:40:50 -040066 std::unique_ptr<SkStreamAsset> stream2(stream.duplicate());
bungeman@google.com6cab1a42013-05-29 13:43:31 +000067 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com789c6f22013-02-25 20:24:24 +000068 }
69
reed@google.com789c6f22013-02-25 20:24:24 +000070 {
bungeman@google.com6cab1a42013-05-29 13:43:31 +000071 FILE* file = ::fopen(path.c_str(), "rb");
Ben Wagner4d1955c2017-03-10 13:08:15 -050072 SkFILEStream stream(file);
reed@google.com789c6f22013-02-25 20:24:24 +000073 REPORTER_ASSERT(reporter, stream.isValid());
74 test_loop_stream(reporter, &stream, s, 26, 100);
bungeman@google.com6cab1a42013-05-29 13:43:31 +000075
Ben Wagner145dbcd2016-11-03 14:40:50 -040076 std::unique_ptr<SkStreamAsset> stream2(stream.duplicate());
bungeman@google.com6cab1a42013-05-29 13:43:31 +000077 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com789c6f22013-02-25 20:24:24 +000078 }
reed@google.com789c6f22013-02-25 20:24:24 +000079}
80
reed@android.com80e39a72009-04-02 16:59:40 +000081static void TestWStream(skiatest::Reporter* reporter) {
82 SkDynamicMemoryWStream ds;
83 const char s[] = "abcdefghijklmnopqrstuvwxyz";
84 int i;
85 for (i = 0; i < 100; i++) {
86 REPORTER_ASSERT(reporter, ds.write(s, 26));
reed@android.com5e5adfd2009-03-07 03:39:23 +000087 }
Ben Wagner884300d2016-12-16 16:51:41 +000088 REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26);
bungeman@google.com88682b72013-07-19 13:55:41 +000089
reed@android.com80e39a72009-04-02 16:59:40 +000090 char* dst = new char[100 * 26 + 1];
91 dst[100*26] = '*';
92 ds.copyTo(dst);
93 REPORTER_ASSERT(reporter, dst[100*26] == '*');
reed@android.com80e39a72009-04-02 16:59:40 +000094 for (i = 0; i < 100; i++) {
95 REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
reed@android.com5e5adfd2009-03-07 03:39:23 +000096 }
reed@google.com70442a62011-06-23 21:48:04 +000097
98 {
Ben Wagner145dbcd2016-11-03 14:40:50 -040099 std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream());
bungeman@google.com88682b72013-07-19 13:55:41 +0000100 REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength());
Ben Wagner884300d2016-12-16 16:51:41 +0000101 REPORTER_ASSERT(reporter, ds.bytesWritten() == 0);
bungeman@google.com88682b72013-07-19 13:55:41 +0000102 test_loop_stream(reporter, stream.get(), s, 26, 100);
103
Ben Wagner145dbcd2016-11-03 14:40:50 -0400104 std::unique_ptr<SkStreamAsset> stream2(stream->duplicate());
bungeman@google.com88682b72013-07-19 13:55:41 +0000105 test_loop_stream(reporter, stream2.get(), s, 26, 100);
106
Ben Wagner145dbcd2016-11-03 14:40:50 -0400107 std::unique_ptr<SkStreamAsset> stream3(stream->fork());
bungeman@google.com88682b72013-07-19 13:55:41 +0000108 REPORTER_ASSERT(reporter, stream3->isAtEnd());
109 char tmp;
110 size_t bytes = stream->read(&tmp, 1);
111 REPORTER_ASSERT(reporter, 0 == bytes);
112 stream3->rewind();
113 test_loop_stream(reporter, stream3.get(), s, 26, 100);
114 }
115
116 for (i = 0; i < 100; i++) {
117 REPORTER_ASSERT(reporter, ds.write(s, 26));
118 }
Ben Wagner884300d2016-12-16 16:51:41 +0000119 REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26);
bungeman@google.com88682b72013-07-19 13:55:41 +0000120
121 {
reed42943c82016-09-12 12:01:44 -0700122 // Test that this works after a snapshot.
Ben Wagner145dbcd2016-11-03 14:40:50 -0400123 std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream());
Ben Wagner884300d2016-12-16 16:51:41 +0000124 REPORTER_ASSERT(reporter, ds.bytesWritten() == 0);
bungeman@google.com88682b72013-07-19 13:55:41 +0000125 test_loop_stream(reporter, stream.get(), s, 26, 100);
126
Ben Wagner145dbcd2016-11-03 14:40:50 -0400127 std::unique_ptr<SkStreamAsset> stream2(stream->duplicate());
bungeman@google.com88682b72013-07-19 13:55:41 +0000128 test_loop_stream(reporter, stream2.get(), s, 26, 100);
reed@google.com70442a62011-06-23 21:48:04 +0000129 }
reed@android.com80e39a72009-04-02 16:59:40 +0000130 delete[] dst;
reed@google.com789c6f22013-02-25 20:24:24 +0000131
halcanary87f3ba42015-01-20 09:30:20 -0800132 SkString tmpDir = skiatest::GetTmpDir();
scroggo@google.comc76218d2013-06-06 14:59:56 +0000133 if (!tmpDir.isEmpty()) {
134 test_filestreams(reporter, tmpDir.c_str());
reed@google.com789c6f22013-02-25 20:24:24 +0000135 }
reed@android.com5e5adfd2009-03-07 03:39:23 +0000136}
137
reed@google.com19f286b2011-10-18 11:49:52 +0000138static void TestPackedUInt(skiatest::Reporter* reporter) {
139 // we know that packeduint tries to write 1, 2 or 4 bytes for the length,
140 // so we test values around each of those transitions (and a few others)
141 const size_t sizes[] = {
142 0, 1, 2, 0xFC, 0xFD, 0xFE, 0xFF, 0x100, 0x101, 32767, 32768, 32769,
143 0xFFFD, 0xFFFE, 0xFFFF, 0x10000, 0x10001,
144 0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0x1000000, 0x1000001,
145 0x7FFFFFFE, 0x7FFFFFFF, 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF
146 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000147
148
reed@google.com19f286b2011-10-18 11:49:52 +0000149 size_t i;
Mike Reedff80c2a2017-01-07 11:16:28 -0500150 SkDynamicMemoryWStream wstream;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000151
reed@google.com19f286b2011-10-18 11:49:52 +0000152 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
153 bool success = wstream.writePackedUInt(sizes[i]);
154 REPORTER_ASSERT(reporter, success);
155 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000156
Mike Reedff80c2a2017-01-07 11:16:28 -0500157 std::unique_ptr<SkStreamAsset> rstream(wstream.detachAsStream());
reed@google.com19f286b2011-10-18 11:49:52 +0000158 for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) {
Mike Reedff80c2a2017-01-07 11:16:28 -0500159 size_t n = rstream->readPackedUInt();
reed@google.com19f286b2011-10-18 11:49:52 +0000160 if (sizes[i] != n) {
halcanary7d571242016-02-24 17:59:16 -0800161 ERRORF(reporter, "sizes:%x != n:%x\n", i, sizes[i], n);
reed@google.com19f286b2011-10-18 11:49:52 +0000162 }
reed@google.com19f286b2011-10-18 11:49:52 +0000163 }
164}
165
halcanary96fcdcc2015-08-27 07:41:13 -0700166// 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 +0000167// methods that access fData.
168static void TestDereferencingData(SkMemoryStream* memStream) {
halcanary96fcdcc2015-08-27 07:41:13 -0700169 memStream->read(nullptr, 0);
scroggo@google.come4904202013-01-09 22:02:58 +0000170 memStream->getMemoryBase();
reed42943c82016-09-12 12:01:44 -0700171 (void)memStream->asData();
scroggo@google.come4904202013-01-09 22:02:58 +0000172}
173
174static void TestNullData() {
reed42943c82016-09-12 12:01:44 -0700175 SkMemoryStream memStream(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000176 TestDereferencingData(&memStream);
177
reed42943c82016-09-12 12:01:44 -0700178 memStream.setData(nullptr);
scroggo@google.come4904202013-01-09 22:02:58 +0000179 TestDereferencingData(&memStream);
180
181}
182
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000183DEF_TEST(Stream, reporter) {
reed@android.com5e5adfd2009-03-07 03:39:23 +0000184 TestWStream(reporter);
reed@google.com19f286b2011-10-18 11:49:52 +0000185 TestPackedUInt(reporter);
scroggo@google.come4904202013-01-09 22:02:58 +0000186 TestNullData();
reed@android.com5e5adfd2009-03-07 03:39:23 +0000187}
scroggo028a4132015-04-02 13:19:51 -0700188
Mike Klein7d302882016-11-03 14:06:31 -0400189#ifndef SK_BUILD_FOR_IOS
scroggo028a4132015-04-02 13:19:51 -0700190/**
191 * Tests peeking and then reading the same amount. The two should provide the
192 * same results.
scroggod61c3842015-12-07 11:37:13 -0800193 * Returns the amount successfully read minus the amount successfully peeked.
scroggo028a4132015-04-02 13:19:51 -0700194 */
scroggod61c3842015-12-07 11:37:13 -0800195static size_t compare_peek_to_read(skiatest::Reporter* reporter,
196 SkStream* stream, size_t bytesToPeek) {
scroggo028a4132015-04-02 13:19:51 -0700197 // The rest of our tests won't be very interesting if bytesToPeek is zero.
198 REPORTER_ASSERT(reporter, bytesToPeek > 0);
199 SkAutoMalloc peekStorage(bytesToPeek);
200 SkAutoMalloc readStorage(bytesToPeek);
201 void* peekPtr = peekStorage.get();
202 void* readPtr = peekStorage.get();
203
scroggod61c3842015-12-07 11:37:13 -0800204 const size_t bytesPeeked = stream->peek(peekPtr, bytesToPeek);
scroggo028a4132015-04-02 13:19:51 -0700205 const size_t bytesRead = stream->read(readPtr, bytesToPeek);
206
207 // bytesRead should only be less than attempted if the stream is at the
208 // end.
209 REPORTER_ASSERT(reporter, bytesRead == bytesToPeek || stream->isAtEnd());
210
211 // peek and read should behave the same, except peek returned to the
212 // original position, so they read the same data.
scroggod61c3842015-12-07 11:37:13 -0800213 REPORTER_ASSERT(reporter, !memcmp(peekPtr, readPtr, bytesPeeked));
scroggo028a4132015-04-02 13:19:51 -0700214
scroggod61c3842015-12-07 11:37:13 -0800215 // A stream should never be able to peek more than it can read.
216 REPORTER_ASSERT(reporter, bytesRead >= bytesPeeked);
217
218 return bytesRead - bytesPeeked;
scroggo028a4132015-04-02 13:19:51 -0700219}
220
scroggod61c3842015-12-07 11:37:13 -0800221static void test_fully_peekable_stream(skiatest::Reporter* r, SkStream* stream, size_t limit) {
scroggo028a4132015-04-02 13:19:51 -0700222 for (size_t i = 1; !stream->isAtEnd(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800223 REPORTER_ASSERT(r, compare_peek_to_read(r, stream, i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700224 }
225}
226
227static void test_peeking_front_buffered_stream(skiatest::Reporter* r,
228 const SkStream& original,
229 size_t bufferSize) {
Mike Reed98c5d922017-09-15 21:39:47 -0400230 std::unique_ptr<SkStream> dupe(original.duplicate());
halcanary96fcdcc2015-08-27 07:41:13 -0700231 REPORTER_ASSERT(r, dupe != nullptr);
Mike Reed98c5d922017-09-15 21:39:47 -0400232 auto bufferedStream = SkFrontBufferedStream::Make(std::move(dupe), bufferSize);
halcanary96fcdcc2015-08-27 07:41:13 -0700233 REPORTER_ASSERT(r, bufferedStream != nullptr);
scroggod61c3842015-12-07 11:37:13 -0800234
235 size_t peeked = 0;
236 for (size_t i = 1; !bufferedStream->isAtEnd(); i++) {
Ben Wagner145dbcd2016-11-03 14:40:50 -0400237 const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream.get(), i);
scroggod61c3842015-12-07 11:37:13 -0800238 if (unpeekableBytes > 0) {
239 // This could not have returned a number greater than i.
240 REPORTER_ASSERT(r, unpeekableBytes <= i);
241
242 // We have reached the end of the buffer. Verify that it was at least
243 // bufferSize.
244 REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize);
245 // No more peeking is supported.
246 break;
247 }
248 peeked += i;
249 }
250
251 // Test that attempting to peek beyond the length of the buffer does not prevent rewinding.
Mike Reed98c5d922017-09-15 21:39:47 -0400252 bufferedStream = SkFrontBufferedStream::Make(original.duplicate(), bufferSize);
scroggod61c3842015-12-07 11:37:13 -0800253 REPORTER_ASSERT(r, bufferedStream != nullptr);
254
255 const size_t bytesToPeek = bufferSize + 1;
256 SkAutoMalloc peekStorage(bytesToPeek);
257 SkAutoMalloc readStorage(bytesToPeek);
258
259 for (size_t start = 0; start <= bufferSize; start++) {
260 // Skip to the starting point
261 REPORTER_ASSERT(r, bufferedStream->skip(start) == start);
scroggod61c3842015-12-07 11:37:13 -0800262
263 const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek);
264 if (0 == bytesPeeked) {
scroggoef0fed32016-02-18 05:59:25 -0800265 // Peeking should only fail completely if we have read/skipped beyond the buffer.
266 REPORTER_ASSERT(r, start >= bufferSize);
scroggod61c3842015-12-07 11:37:13 -0800267 break;
268 }
269
270 // Only read the amount that was successfully peeked.
271 const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked);
272 REPORTER_ASSERT(r, bytesRead == bytesPeeked);
273 REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked));
274
275 // This should be safe to rewind.
276 REPORTER_ASSERT(r, bufferedStream->rewind());
277 }
scroggo028a4132015-04-02 13:19:51 -0700278}
279
halcanary9d524f22016-03-29 09:03:52 -0700280// This test uses file system operations that don't work out of the
281// box on iOS. It's likely that we don't need them on iOS. Ignoring for now.
282// TODO(stephana): Re-evaluate if we need this in the future.
scroggo028a4132015-04-02 13:19:51 -0700283DEF_TEST(StreamPeek, reporter) {
284 // Test a memory stream.
285 const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz";
286 SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
scroggod61c3842015-12-07 11:37:13 -0800287 test_fully_peekable_stream(reporter, &memStream, memStream.getLength());
scroggo028a4132015-04-02 13:19:51 -0700288
289 // Test an arbitrary file stream. file streams do not support peeking.
Hal Canary925e31e2017-12-11 14:42:58 -0500290 auto tmpdir = skiatest::GetTmpDir();
291 if (tmpdir.isEmpty()) {
292 ERRORF(reporter, "no tmp dir!");
Hal Canarya4935102017-12-08 13:35:47 -0500293 return;
294 }
Hal Canary925e31e2017-12-11 14:42:58 -0500295 auto path = SkOSPath::Join(tmpdir.c_str(), "file");
296 {
297 SkFILEWStream wStream(path.c_str());
298 constexpr char filename[] = "images/baby_tux.webp";
299 auto data = GetResourceAsData(filename);
300 if (!data || data->size() == 0) {
301 ERRORF(reporter, "resource missing: %s\n", filename);
302 return;
303 }
304 if (!wStream.isValid() || !wStream.write(data->data(), data->size())) {
305 ERRORF(reporter, "error wrtiting to file %s", path.c_str());
306 return;
307 }
308 }
Hal Canarya4935102017-12-08 13:35:47 -0500309 SkFILEStream fileStream(path.c_str());
scroggo028a4132015-04-02 13:19:51 -0700310 REPORTER_ASSERT(reporter, fileStream.isValid());
caryclark30ac4642015-04-14 06:08:04 -0700311 if (!fileStream.isValid()) {
312 return;
313 }
scroggo028a4132015-04-02 13:19:51 -0700314 SkAutoMalloc storage(fileStream.getLength());
315 for (size_t i = 1; i < fileStream.getLength(); i++) {
scroggod61c3842015-12-07 11:37:13 -0800316 REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0);
scroggo028a4132015-04-02 13:19:51 -0700317 }
318
319 // Now test some FrontBufferedStreams
320 for (size_t i = 1; i < memStream.getLength(); i++) {
321 test_peeking_front_buffered_stream(reporter, memStream, i);
322 }
323}
halcanarye797d0d2015-05-21 08:13:27 -0700324#endif
325
326// Asserts that asset == expected and is peekable.
327static void stream_peek_test(skiatest::Reporter* rep,
328 SkStreamAsset* asset,
329 const SkData* expected) {
330 if (asset->getLength() != expected->size()) {
331 ERRORF(rep, "Unexpected length.");
332 return;
333 }
334 SkRandom rand;
335 uint8_t buffer[4096];
336 const uint8_t* expect = expected->bytes();
337 for (size_t i = 0; i < asset->getLength(); ++i) {
338 uint32_t maxSize =
339 SkToU32(SkTMin(sizeof(buffer), asset->getLength() - i));
340 size_t size = rand.nextRangeU(1, maxSize);
341 SkASSERT(size >= 1);
342 SkASSERT(size <= sizeof(buffer));
343 SkASSERT(size + i <= asset->getLength());
scroggod61c3842015-12-07 11:37:13 -0800344 if (asset->peek(buffer, size) < size) {
halcanarye797d0d2015-05-21 08:13:27 -0700345 ERRORF(rep, "Peek Failed!");
346 return;
347 }
348 if (0 != memcmp(buffer, &expect[i], size)) {
349 ERRORF(rep, "Peek returned wrong bytes!");
350 return;
351 }
352 uint8_t value;
353 REPORTER_ASSERT(rep, 1 == asset->read(&value, 1));
354 if (value != expect[i]) {
355 ERRORF(rep, "Read Failed!");
356 return;
357 }
358 }
359}
360
361DEF_TEST(StreamPeek_BlockMemoryStream, rep) {
362 const static int kSeed = 1234;
363 SkRandom valueSource(kSeed);
364 SkRandom rand(kSeed << 1);
365 uint8_t buffer[4096];
366 SkDynamicMemoryWStream dynamicMemoryWStream;
Mike Reed49282292016-12-14 12:34:06 -0500367 size_t totalWritten = 0;
halcanarye797d0d2015-05-21 08:13:27 -0700368 for (int i = 0; i < 32; ++i) {
369 // Randomize the length of the blocks.
370 size_t size = rand.nextRangeU(1, sizeof(buffer));
371 for (size_t j = 0; j < size; ++j) {
372 buffer[j] = valueSource.nextU() & 0xFF;
373 }
374 dynamicMemoryWStream.write(buffer, size);
Mike Reed49282292016-12-14 12:34:06 -0500375 totalWritten += size;
376 REPORTER_ASSERT(rep, totalWritten == dynamicMemoryWStream.bytesWritten());
halcanarye797d0d2015-05-21 08:13:27 -0700377 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400378 std::unique_ptr<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream());
bungeman38d909e2016-08-02 14:40:46 -0700379 sk_sp<SkData> expected(SkData::MakeUninitialized(asset->getLength()));
halcanarye797d0d2015-05-21 08:13:27 -0700380 uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data());
381 valueSource.setSeed(kSeed); // reseed.
382 // We want the exact same same "random" string of numbers to put
383 // in expected. i.e.: don't rely on SkDynamicMemoryStream to work
384 // correctly while we are testing SkDynamicMemoryStream.
385 for (size_t i = 0; i < asset->getLength(); ++i) {
386 expectedPtr[i] = valueSource.nextU() & 0xFF;
387 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400388 stream_peek_test(rep, asset.get(), expected.get());
halcanarye797d0d2015-05-21 08:13:27 -0700389}
halcanary48305e82015-08-18 13:30:25 -0700390
391namespace {
392class DumbStream : public SkStream {
393public:
394 DumbStream(const uint8_t* data, size_t n)
395 : fData(data), fCount(n), fIdx(0) {}
396 size_t read(void* buffer, size_t size) override {
halcanaryd75e21d2015-08-19 07:22:04 -0700397 size_t copyCount = SkTMin(fCount - fIdx, size);
398 if (copyCount) {
399 memcpy(buffer, &fData[fIdx], copyCount);
400 fIdx += copyCount;
halcanary48305e82015-08-18 13:30:25 -0700401 }
halcanaryd75e21d2015-08-19 07:22:04 -0700402 return copyCount;
halcanary48305e82015-08-18 13:30:25 -0700403 }
404 bool isAtEnd() const override {
halcanaryd75e21d2015-08-19 07:22:04 -0700405 return fCount == fIdx;
halcanary48305e82015-08-18 13:30:25 -0700406 }
407 private:
408 const uint8_t* fData;
409 size_t fCount, fIdx;
410};
411} // namespace
412
413static void stream_copy_test(skiatest::Reporter* reporter,
414 const void* srcData,
415 size_t N,
416 SkStream* stream) {
417 SkDynamicMemoryWStream tgt;
418 if (!SkStreamCopy(&tgt, stream)) {
419 ERRORF(reporter, "SkStreamCopy failed");
420 return;
421 }
reed42943c82016-09-12 12:01:44 -0700422 sk_sp<SkData> data(tgt.detachAsData());
halcanary48305e82015-08-18 13:30:25 -0700423 if (data->size() != N) {
424 ERRORF(reporter, "SkStreamCopy incorrect size");
425 return;
426 }
427 if (0 != memcmp(data->data(), srcData, N)) {
428 ERRORF(reporter, "SkStreamCopy bad copy");
429 }
430}
431
Hal Canarydabe8ac2017-03-14 15:52:12 -0400432DEF_TEST(DynamicMemoryWStream_detachAsData, r) {
433 const char az[] = "abcdefghijklmnopqrstuvwxyz";
434 const unsigned N = 40000;
435 SkDynamicMemoryWStream dmws;
436 for (unsigned i = 0; i < N; ++i) {
437 dmws.writeText(az);
438 }
439 REPORTER_ASSERT(r, dmws.bytesWritten() == N * strlen(az));
440 auto data = dmws.detachAsData();
441 REPORTER_ASSERT(r, data->size() == N * strlen(az));
442 const uint8_t* ptr = data->bytes();
443 for (unsigned i = 0; i < N; ++i) {
444 if (0 != memcmp(ptr, az, strlen(az))) {
445 ERRORF(r, "detachAsData() memcmp failed");
446 return;
447 }
448 ptr += strlen(az);
449 }
450}
451
halcanary48305e82015-08-18 13:30:25 -0700452DEF_TEST(StreamCopy, reporter) {
453 SkRandom random(123456);
halcanarycb9241b2015-08-19 06:12:40 -0700454 static const int N = 10000;
455 SkAutoTMalloc<uint8_t> src((size_t)N);
456 for (int j = 0; j < N; ++j) {
halcanary48305e82015-08-18 13:30:25 -0700457 src[j] = random.nextU() & 0xff;
458 }
459 // SkStreamCopy had two code paths; this test both.
halcanarycb9241b2015-08-19 06:12:40 -0700460 DumbStream dumbStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700461 stream_copy_test(reporter, src, N, &dumbStream);
halcanarycb9241b2015-08-19 06:12:40 -0700462 SkMemoryStream smartStream(src.get(), (size_t)N);
halcanary48305e82015-08-18 13:30:25 -0700463 stream_copy_test(reporter, src, N, &smartStream);
halcanary48305e82015-08-18 13:30:25 -0700464}
halcanary209c1622015-09-28 07:29:39 -0700465
466DEF_TEST(StreamEmptyStreamMemoryBase, r) {
467 SkDynamicMemoryWStream tmp;
Ben Wagner145dbcd2016-11-03 14:40:50 -0400468 std::unique_ptr<SkStreamAsset> asset(tmp.detachAsStream());
halcanary209c1622015-09-28 07:29:39 -0700469 REPORTER_ASSERT(r, nullptr == asset->getMemoryBase());
470}
Mike Reed1026ccf2017-01-08 14:35:29 -0500471
472#include "SkBuffer.h"
473
474DEF_TEST(RBuffer, reporter) {
475 int32_t value = 0;
476 SkRBuffer buffer(&value, 4);
477 REPORTER_ASSERT(reporter, buffer.isValid());
478
479 int32_t tmp;
480 REPORTER_ASSERT(reporter, buffer.read(&tmp, 4));
481 REPORTER_ASSERT(reporter, buffer.isValid());
482
483 REPORTER_ASSERT(reporter, !buffer.read(&tmp, 4));
484 REPORTER_ASSERT(reporter, !buffer.isValid());
485}