1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci// Make sure SkUserConfig.h is included so #defines are available on 9cb93a386Sopenharmony_ci// Android. 10cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 11cb93a386Sopenharmony_ci#ifdef SK_ENABLE_ANDROID_UTILS 12cb93a386Sopenharmony_ci#include "client_utils/android/FrontBufferedStream.h" 13cb93a386Sopenharmony_ci#endif 14cb93a386Sopenharmony_ci#include "include/core/SkData.h" 15cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 16cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 17cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h" 18cb93a386Sopenharmony_ci#include "src/core/SkAutoMalloc.h" 19cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h" 20cb93a386Sopenharmony_ci#include "src/core/SkStreamPriv.h" 21cb93a386Sopenharmony_ci#include "src/utils/SkOSPath.h" 22cb93a386Sopenharmony_ci#include "tests/Test.h" 23cb93a386Sopenharmony_ci#include "tools/Resources.h" 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ci#include <functional> 26cb93a386Sopenharmony_ci#include <limits> 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ci#ifndef SK_BUILD_FOR_WIN 29cb93a386Sopenharmony_ci#include <unistd.h> 30cb93a386Sopenharmony_ci#include <fcntl.h> 31cb93a386Sopenharmony_ci#endif 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci#define MAX_SIZE (256 * 1024) 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_cistatic void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream, 36cb93a386Sopenharmony_ci const void* src, size_t len, int repeat) { 37cb93a386Sopenharmony_ci SkAutoSMalloc<256> storage(len); 38cb93a386Sopenharmony_ci void* tmp = storage.get(); 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci for (int i = 0; i < repeat; ++i) { 41cb93a386Sopenharmony_ci size_t bytes = stream->read(tmp, len); 42cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bytes == len); 43cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !memcmp(tmp, src, len)); 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci // expect EOF 47cb93a386Sopenharmony_ci size_t bytes = stream->read(tmp, 1); 48cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == bytes); 49cb93a386Sopenharmony_ci // isAtEnd might not return true until after the first failing read. 50cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, stream->isAtEnd()); 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_cistatic void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) { 54cb93a386Sopenharmony_ci SkString path = SkOSPath::Join(tmpDir, "wstream_test"); 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci const char s[] = "abcdefghijklmnopqrstuvwxyz"; 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci { 59cb93a386Sopenharmony_ci SkFILEWStream writer(path.c_str()); 60cb93a386Sopenharmony_ci if (!writer.isValid()) { 61cb93a386Sopenharmony_ci ERRORF(reporter, "Failed to create tmp file %s\n", path.c_str()); 62cb93a386Sopenharmony_ci return; 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci for (int i = 0; i < 100; ++i) { 66cb93a386Sopenharmony_ci writer.write(s, 26); 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci { 71cb93a386Sopenharmony_ci SkFILEStream stream(path.c_str()); 72cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, stream.isValid()); 73cb93a386Sopenharmony_ci test_loop_stream(reporter, &stream, s, 26, 100); 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream2(stream.duplicate()); 76cb93a386Sopenharmony_ci test_loop_stream(reporter, stream2.get(), s, 26, 100); 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci { 80cb93a386Sopenharmony_ci FILE* file = ::fopen(path.c_str(), "rb"); 81cb93a386Sopenharmony_ci SkFILEStream stream(file); 82cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, stream.isValid()); 83cb93a386Sopenharmony_ci test_loop_stream(reporter, &stream, s, 26, 100); 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream2(stream.duplicate()); 86cb93a386Sopenharmony_ci test_loop_stream(reporter, stream2.get(), s, 26, 100); 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci} 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_cistatic void TestWStream(skiatest::Reporter* reporter) { 91cb93a386Sopenharmony_ci SkDynamicMemoryWStream ds; 92cb93a386Sopenharmony_ci const char s[] = "abcdefghijklmnopqrstuvwxyz"; 93cb93a386Sopenharmony_ci int i; 94cb93a386Sopenharmony_ci for (i = 0; i < 100; i++) { 95cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, ds.write(s, 26)); 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26); 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci char* dst = new char[100 * 26 + 1]; 100cb93a386Sopenharmony_ci dst[100*26] = '*'; 101cb93a386Sopenharmony_ci ds.copyTo(dst); 102cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, dst[100*26] == '*'); 103cb93a386Sopenharmony_ci for (i = 0; i < 100; i++) { 104cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0); 105cb93a386Sopenharmony_ci } 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci { 108cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream()); 109cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength()); 110cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, ds.bytesWritten() == 0); 111cb93a386Sopenharmony_ci test_loop_stream(reporter, stream.get(), s, 26, 100); 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream2(stream->duplicate()); 114cb93a386Sopenharmony_ci test_loop_stream(reporter, stream2.get(), s, 26, 100); 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream3(stream->fork()); 117cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, stream3->isAtEnd()); 118cb93a386Sopenharmony_ci char tmp; 119cb93a386Sopenharmony_ci size_t bytes = stream->read(&tmp, 1); 120cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == bytes); 121cb93a386Sopenharmony_ci stream3->rewind(); 122cb93a386Sopenharmony_ci test_loop_stream(reporter, stream3.get(), s, 26, 100); 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci for (i = 0; i < 100; i++) { 126cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, ds.write(s, 26)); 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, ds.bytesWritten() == 100 * 26); 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci { 131cb93a386Sopenharmony_ci // Test that this works after a snapshot. 132cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream(ds.detachAsStream()); 133cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, ds.bytesWritten() == 0); 134cb93a386Sopenharmony_ci test_loop_stream(reporter, stream.get(), s, 26, 100); 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> stream2(stream->duplicate()); 137cb93a386Sopenharmony_ci test_loop_stream(reporter, stream2.get(), s, 26, 100); 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci delete[] dst; 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci SkString tmpDir = skiatest::GetTmpDir(); 142cb93a386Sopenharmony_ci if (!tmpDir.isEmpty()) { 143cb93a386Sopenharmony_ci test_filestreams(reporter, tmpDir.c_str()); 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci} 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_cistatic void TestPackedUInt(skiatest::Reporter* reporter) { 148cb93a386Sopenharmony_ci // we know that packeduint tries to write 1, 2 or 4 bytes for the length, 149cb93a386Sopenharmony_ci // so we test values around each of those transitions (and a few others) 150cb93a386Sopenharmony_ci const size_t sizes[] = { 151cb93a386Sopenharmony_ci 0, 1, 2, 0xFC, 0xFD, 0xFE, 0xFF, 0x100, 0x101, 32767, 32768, 32769, 152cb93a386Sopenharmony_ci 0xFFFD, 0xFFFE, 0xFFFF, 0x10000, 0x10001, 153cb93a386Sopenharmony_ci 0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0x1000000, 0x1000001, 154cb93a386Sopenharmony_ci 0x7FFFFFFE, 0x7FFFFFFF, 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF 155cb93a386Sopenharmony_ci }; 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ci size_t i; 159cb93a386Sopenharmony_ci SkDynamicMemoryWStream wstream; 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ci for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) { 162cb93a386Sopenharmony_ci bool success = wstream.writePackedUInt(sizes[i]); 163cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, success); 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> rstream(wstream.detachAsStream()); 167cb93a386Sopenharmony_ci for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) { 168cb93a386Sopenharmony_ci size_t n; 169cb93a386Sopenharmony_ci if (!rstream->readPackedUInt(&n)) { 170cb93a386Sopenharmony_ci ERRORF(reporter, "[%zu] sizes:%zx could not be read\n", i, sizes[i]); 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci if (sizes[i] != n) { 173cb93a386Sopenharmony_ci ERRORF(reporter, "[%zu] sizes:%zx != n:%zx\n", i, sizes[i], n); 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci } 176cb93a386Sopenharmony_ci} 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci// Test that setting an SkMemoryStream to a nullptr data does not result in a crash when calling 179cb93a386Sopenharmony_ci// methods that access fData. 180cb93a386Sopenharmony_cistatic void TestDereferencingData(SkMemoryStream* memStream) { 181cb93a386Sopenharmony_ci memStream->read(nullptr, 0); 182cb93a386Sopenharmony_ci memStream->getMemoryBase(); 183cb93a386Sopenharmony_ci (void)memStream->asData(); 184cb93a386Sopenharmony_ci} 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_cistatic void TestNullData() { 187cb93a386Sopenharmony_ci SkMemoryStream memStream(nullptr); 188cb93a386Sopenharmony_ci TestDereferencingData(&memStream); 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_ci memStream.setData(nullptr); 191cb93a386Sopenharmony_ci TestDereferencingData(&memStream); 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci} 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ciDEF_TEST(Stream, reporter) { 196cb93a386Sopenharmony_ci TestWStream(reporter); 197cb93a386Sopenharmony_ci TestPackedUInt(reporter); 198cb93a386Sopenharmony_ci TestNullData(); 199cb93a386Sopenharmony_ci} 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_ci#ifndef SK_BUILD_FOR_IOS 202cb93a386Sopenharmony_ci/** 203cb93a386Sopenharmony_ci * Tests peeking and then reading the same amount. The two should provide the 204cb93a386Sopenharmony_ci * same results. 205cb93a386Sopenharmony_ci * Returns the amount successfully read minus the amount successfully peeked. 206cb93a386Sopenharmony_ci */ 207cb93a386Sopenharmony_cistatic size_t compare_peek_to_read(skiatest::Reporter* reporter, 208cb93a386Sopenharmony_ci SkStream* stream, size_t bytesToPeek) { 209cb93a386Sopenharmony_ci // The rest of our tests won't be very interesting if bytesToPeek is zero. 210cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bytesToPeek > 0); 211cb93a386Sopenharmony_ci SkAutoMalloc peekStorage(bytesToPeek); 212cb93a386Sopenharmony_ci SkAutoMalloc readStorage(bytesToPeek); 213cb93a386Sopenharmony_ci void* peekPtr = peekStorage.get(); 214cb93a386Sopenharmony_ci void* readPtr = peekStorage.get(); 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci const size_t bytesPeeked = stream->peek(peekPtr, bytesToPeek); 217cb93a386Sopenharmony_ci const size_t bytesRead = stream->read(readPtr, bytesToPeek); 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci // bytesRead should only be less than attempted if the stream is at the 220cb93a386Sopenharmony_ci // end. 221cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bytesRead == bytesToPeek || stream->isAtEnd()); 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_ci // peek and read should behave the same, except peek returned to the 224cb93a386Sopenharmony_ci // original position, so they read the same data. 225cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !memcmp(peekPtr, readPtr, bytesPeeked)); 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci // A stream should never be able to peek more than it can read. 228cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bytesRead >= bytesPeeked); 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ci return bytesRead - bytesPeeked; 231cb93a386Sopenharmony_ci} 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_cistatic void test_fully_peekable_stream(skiatest::Reporter* r, SkStream* stream, size_t limit) { 234cb93a386Sopenharmony_ci for (size_t i = 1; !stream->isAtEnd(); i++) { 235cb93a386Sopenharmony_ci REPORTER_ASSERT(r, compare_peek_to_read(r, stream, i) == 0); 236cb93a386Sopenharmony_ci } 237cb93a386Sopenharmony_ci} 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_ci#ifdef SK_ENABLE_ANDROID_UTILS 240cb93a386Sopenharmony_cistatic void test_peeking_front_buffered_stream(skiatest::Reporter* r, 241cb93a386Sopenharmony_ci const SkStream& original, 242cb93a386Sopenharmony_ci size_t bufferSize) { 243cb93a386Sopenharmony_ci std::unique_ptr<SkStream> dupe(original.duplicate()); 244cb93a386Sopenharmony_ci REPORTER_ASSERT(r, dupe != nullptr); 245cb93a386Sopenharmony_ci auto bufferedStream = android::skia::FrontBufferedStream::Make( 246cb93a386Sopenharmony_ci std::move(dupe), bufferSize); 247cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bufferedStream != nullptr); 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_ci size_t peeked = 0; 250cb93a386Sopenharmony_ci for (size_t i = 1; !bufferedStream->isAtEnd(); i++) { 251cb93a386Sopenharmony_ci const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream.get(), i); 252cb93a386Sopenharmony_ci if (unpeekableBytes > 0) { 253cb93a386Sopenharmony_ci // This could not have returned a number greater than i. 254cb93a386Sopenharmony_ci REPORTER_ASSERT(r, unpeekableBytes <= i); 255cb93a386Sopenharmony_ci 256cb93a386Sopenharmony_ci // We have reached the end of the buffer. Verify that it was at least 257cb93a386Sopenharmony_ci // bufferSize. 258cb93a386Sopenharmony_ci REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize); 259cb93a386Sopenharmony_ci // No more peeking is supported. 260cb93a386Sopenharmony_ci break; 261cb93a386Sopenharmony_ci } 262cb93a386Sopenharmony_ci peeked += i; 263cb93a386Sopenharmony_ci } 264cb93a386Sopenharmony_ci 265cb93a386Sopenharmony_ci // Test that attempting to peek beyond the length of the buffer does not prevent rewinding. 266cb93a386Sopenharmony_ci bufferedStream = android::skia::FrontBufferedStream::Make(original.duplicate(), bufferSize); 267cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bufferedStream != nullptr); 268cb93a386Sopenharmony_ci 269cb93a386Sopenharmony_ci const size_t bytesToPeek = bufferSize + 1; 270cb93a386Sopenharmony_ci SkAutoMalloc peekStorage(bytesToPeek); 271cb93a386Sopenharmony_ci SkAutoMalloc readStorage(bytesToPeek); 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_ci for (size_t start = 0; start <= bufferSize; start++) { 274cb93a386Sopenharmony_ci // Skip to the starting point 275cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bufferedStream->skip(start) == start); 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek); 278cb93a386Sopenharmony_ci if (0 == bytesPeeked) { 279cb93a386Sopenharmony_ci // Peeking should only fail completely if we have read/skipped beyond the buffer. 280cb93a386Sopenharmony_ci REPORTER_ASSERT(r, start >= bufferSize); 281cb93a386Sopenharmony_ci break; 282cb93a386Sopenharmony_ci } 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_ci // Only read the amount that was successfully peeked. 285cb93a386Sopenharmony_ci const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked); 286cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bytesRead == bytesPeeked); 287cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked)); 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_ci // This should be safe to rewind. 290cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bufferedStream->rewind()); 291cb93a386Sopenharmony_ci } 292cb93a386Sopenharmony_ci} 293cb93a386Sopenharmony_ci#endif 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ci// This test uses file system operations that don't work out of the 296cb93a386Sopenharmony_ci// box on iOS. It's likely that we don't need them on iOS. Ignoring for now. 297cb93a386Sopenharmony_ci// TODO(stephana): Re-evaluate if we need this in the future. 298cb93a386Sopenharmony_ciDEF_TEST(StreamPeek, reporter) { 299cb93a386Sopenharmony_ci // Test a memory stream. 300cb93a386Sopenharmony_ci const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz"; 301cb93a386Sopenharmony_ci SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); 302cb93a386Sopenharmony_ci test_fully_peekable_stream(reporter, &memStream, memStream.getLength()); 303cb93a386Sopenharmony_ci 304cb93a386Sopenharmony_ci // Test an arbitrary file stream. file streams do not support peeking. 305cb93a386Sopenharmony_ci auto tmpdir = skiatest::GetTmpDir(); 306cb93a386Sopenharmony_ci if (tmpdir.isEmpty()) { 307cb93a386Sopenharmony_ci ERRORF(reporter, "no tmp dir!"); 308cb93a386Sopenharmony_ci return; 309cb93a386Sopenharmony_ci } 310cb93a386Sopenharmony_ci auto path = SkOSPath::Join(tmpdir.c_str(), "file"); 311cb93a386Sopenharmony_ci { 312cb93a386Sopenharmony_ci SkFILEWStream wStream(path.c_str()); 313cb93a386Sopenharmony_ci constexpr char filename[] = "images/baby_tux.webp"; 314cb93a386Sopenharmony_ci auto data = GetResourceAsData(filename); 315cb93a386Sopenharmony_ci if (!data || data->size() == 0) { 316cb93a386Sopenharmony_ci ERRORF(reporter, "resource missing: %s\n", filename); 317cb93a386Sopenharmony_ci return; 318cb93a386Sopenharmony_ci } 319cb93a386Sopenharmony_ci if (!wStream.isValid() || !wStream.write(data->data(), data->size())) { 320cb93a386Sopenharmony_ci ERRORF(reporter, "error wrtiting to file %s", path.c_str()); 321cb93a386Sopenharmony_ci return; 322cb93a386Sopenharmony_ci } 323cb93a386Sopenharmony_ci } 324cb93a386Sopenharmony_ci SkFILEStream fileStream(path.c_str()); 325cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, fileStream.isValid()); 326cb93a386Sopenharmony_ci if (!fileStream.isValid()) { 327cb93a386Sopenharmony_ci return; 328cb93a386Sopenharmony_ci } 329cb93a386Sopenharmony_ci SkAutoMalloc storage(fileStream.getLength()); 330cb93a386Sopenharmony_ci for (size_t i = 1; i < fileStream.getLength(); i++) { 331cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0); 332cb93a386Sopenharmony_ci } 333cb93a386Sopenharmony_ci 334cb93a386Sopenharmony_ci#ifdef SK_ENABLE_ANDROID_UTILS 335cb93a386Sopenharmony_ci // Now test some FrontBufferedStreams 336cb93a386Sopenharmony_ci for (size_t i = 1; i < memStream.getLength(); i++) { 337cb93a386Sopenharmony_ci test_peeking_front_buffered_stream(reporter, memStream, i); 338cb93a386Sopenharmony_ci } 339cb93a386Sopenharmony_ci#endif 340cb93a386Sopenharmony_ci} 341cb93a386Sopenharmony_ci#endif 342cb93a386Sopenharmony_ci 343cb93a386Sopenharmony_ci// Asserts that asset == expected and is peekable. 344cb93a386Sopenharmony_cistatic void stream_peek_test(skiatest::Reporter* rep, 345cb93a386Sopenharmony_ci SkStreamAsset* asset, 346cb93a386Sopenharmony_ci const SkData* expected) { 347cb93a386Sopenharmony_ci if (asset->getLength() != expected->size()) { 348cb93a386Sopenharmony_ci ERRORF(rep, "Unexpected length."); 349cb93a386Sopenharmony_ci return; 350cb93a386Sopenharmony_ci } 351cb93a386Sopenharmony_ci SkRandom rand; 352cb93a386Sopenharmony_ci uint8_t buffer[4096]; 353cb93a386Sopenharmony_ci const uint8_t* expect = expected->bytes(); 354cb93a386Sopenharmony_ci for (size_t i = 0; i < asset->getLength(); ++i) { 355cb93a386Sopenharmony_ci uint32_t maxSize = 356cb93a386Sopenharmony_ci SkToU32(std::min(sizeof(buffer), asset->getLength() - i)); 357cb93a386Sopenharmony_ci size_t size = rand.nextRangeU(1, maxSize); 358cb93a386Sopenharmony_ci SkASSERT(size >= 1); 359cb93a386Sopenharmony_ci SkASSERT(size <= sizeof(buffer)); 360cb93a386Sopenharmony_ci SkASSERT(size + i <= asset->getLength()); 361cb93a386Sopenharmony_ci if (asset->peek(buffer, size) < size) { 362cb93a386Sopenharmony_ci ERRORF(rep, "Peek Failed!"); 363cb93a386Sopenharmony_ci return; 364cb93a386Sopenharmony_ci } 365cb93a386Sopenharmony_ci if (0 != memcmp(buffer, &expect[i], size)) { 366cb93a386Sopenharmony_ci ERRORF(rep, "Peek returned wrong bytes!"); 367cb93a386Sopenharmony_ci return; 368cb93a386Sopenharmony_ci } 369cb93a386Sopenharmony_ci uint8_t value; 370cb93a386Sopenharmony_ci REPORTER_ASSERT(rep, 1 == asset->read(&value, 1)); 371cb93a386Sopenharmony_ci if (value != expect[i]) { 372cb93a386Sopenharmony_ci ERRORF(rep, "Read Failed!"); 373cb93a386Sopenharmony_ci return; 374cb93a386Sopenharmony_ci } 375cb93a386Sopenharmony_ci } 376cb93a386Sopenharmony_ci} 377cb93a386Sopenharmony_ci 378cb93a386Sopenharmony_ciDEF_TEST(StreamPeek_BlockMemoryStream, rep) { 379cb93a386Sopenharmony_ci const static int kSeed = 1234; 380cb93a386Sopenharmony_ci SkRandom valueSource(kSeed); 381cb93a386Sopenharmony_ci SkRandom rand(kSeed << 1); 382cb93a386Sopenharmony_ci uint8_t buffer[4096]; 383cb93a386Sopenharmony_ci SkDynamicMemoryWStream dynamicMemoryWStream; 384cb93a386Sopenharmony_ci size_t totalWritten = 0; 385cb93a386Sopenharmony_ci for (int i = 0; i < 32; ++i) { 386cb93a386Sopenharmony_ci // Randomize the length of the blocks. 387cb93a386Sopenharmony_ci size_t size = rand.nextRangeU(1, sizeof(buffer)); 388cb93a386Sopenharmony_ci for (size_t j = 0; j < size; ++j) { 389cb93a386Sopenharmony_ci buffer[j] = valueSource.nextU() & 0xFF; 390cb93a386Sopenharmony_ci } 391cb93a386Sopenharmony_ci dynamicMemoryWStream.write(buffer, size); 392cb93a386Sopenharmony_ci totalWritten += size; 393cb93a386Sopenharmony_ci REPORTER_ASSERT(rep, totalWritten == dynamicMemoryWStream.bytesWritten()); 394cb93a386Sopenharmony_ci } 395cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> asset(dynamicMemoryWStream.detachAsStream()); 396cb93a386Sopenharmony_ci sk_sp<SkData> expected(SkData::MakeUninitialized(asset->getLength())); 397cb93a386Sopenharmony_ci uint8_t* expectedPtr = static_cast<uint8_t*>(expected->writable_data()); 398cb93a386Sopenharmony_ci valueSource.setSeed(kSeed); // reseed. 399cb93a386Sopenharmony_ci // We want the exact same same "random" string of numbers to put 400cb93a386Sopenharmony_ci // in expected. i.e.: don't rely on SkDynamicMemoryStream to work 401cb93a386Sopenharmony_ci // correctly while we are testing SkDynamicMemoryStream. 402cb93a386Sopenharmony_ci for (size_t i = 0; i < asset->getLength(); ++i) { 403cb93a386Sopenharmony_ci expectedPtr[i] = valueSource.nextU() & 0xFF; 404cb93a386Sopenharmony_ci } 405cb93a386Sopenharmony_ci stream_peek_test(rep, asset.get(), expected.get()); 406cb93a386Sopenharmony_ci} 407cb93a386Sopenharmony_ci 408cb93a386Sopenharmony_cinamespace { 409cb93a386Sopenharmony_ciclass DumbStream : public SkStream { 410cb93a386Sopenharmony_cipublic: 411cb93a386Sopenharmony_ci DumbStream(const uint8_t* data, size_t n) 412cb93a386Sopenharmony_ci : fData(data), fCount(n), fIdx(0) {} 413cb93a386Sopenharmony_ci size_t read(void* buffer, size_t size) override { 414cb93a386Sopenharmony_ci size_t copyCount = std::min(fCount - fIdx, size); 415cb93a386Sopenharmony_ci if (copyCount) { 416cb93a386Sopenharmony_ci memcpy(buffer, &fData[fIdx], copyCount); 417cb93a386Sopenharmony_ci fIdx += copyCount; 418cb93a386Sopenharmony_ci } 419cb93a386Sopenharmony_ci return copyCount; 420cb93a386Sopenharmony_ci } 421cb93a386Sopenharmony_ci bool isAtEnd() const override { 422cb93a386Sopenharmony_ci return fCount == fIdx; 423cb93a386Sopenharmony_ci } 424cb93a386Sopenharmony_ci private: 425cb93a386Sopenharmony_ci const uint8_t* fData; 426cb93a386Sopenharmony_ci size_t fCount, fIdx; 427cb93a386Sopenharmony_ci}; 428cb93a386Sopenharmony_ci} // namespace 429cb93a386Sopenharmony_ci 430cb93a386Sopenharmony_cistatic void stream_copy_test(skiatest::Reporter* reporter, 431cb93a386Sopenharmony_ci const void* srcData, 432cb93a386Sopenharmony_ci size_t N, 433cb93a386Sopenharmony_ci SkStream* stream) { 434cb93a386Sopenharmony_ci SkDynamicMemoryWStream tgt; 435cb93a386Sopenharmony_ci if (!SkStreamCopy(&tgt, stream)) { 436cb93a386Sopenharmony_ci ERRORF(reporter, "SkStreamCopy failed"); 437cb93a386Sopenharmony_ci return; 438cb93a386Sopenharmony_ci } 439cb93a386Sopenharmony_ci sk_sp<SkData> data(tgt.detachAsData()); 440cb93a386Sopenharmony_ci if (data->size() != N) { 441cb93a386Sopenharmony_ci ERRORF(reporter, "SkStreamCopy incorrect size"); 442cb93a386Sopenharmony_ci return; 443cb93a386Sopenharmony_ci } 444cb93a386Sopenharmony_ci if (0 != memcmp(data->data(), srcData, N)) { 445cb93a386Sopenharmony_ci ERRORF(reporter, "SkStreamCopy bad copy"); 446cb93a386Sopenharmony_ci } 447cb93a386Sopenharmony_ci} 448cb93a386Sopenharmony_ci 449cb93a386Sopenharmony_ciDEF_TEST(DynamicMemoryWStream_detachAsData, r) { 450cb93a386Sopenharmony_ci const char az[] = "abcdefghijklmnopqrstuvwxyz"; 451cb93a386Sopenharmony_ci const unsigned N = 40000; 452cb93a386Sopenharmony_ci SkDynamicMemoryWStream dmws; 453cb93a386Sopenharmony_ci for (unsigned i = 0; i < N; ++i) { 454cb93a386Sopenharmony_ci dmws.writeText(az); 455cb93a386Sopenharmony_ci } 456cb93a386Sopenharmony_ci REPORTER_ASSERT(r, dmws.bytesWritten() == N * strlen(az)); 457cb93a386Sopenharmony_ci auto data = dmws.detachAsData(); 458cb93a386Sopenharmony_ci REPORTER_ASSERT(r, data->size() == N * strlen(az)); 459cb93a386Sopenharmony_ci const uint8_t* ptr = data->bytes(); 460cb93a386Sopenharmony_ci for (unsigned i = 0; i < N; ++i) { 461cb93a386Sopenharmony_ci if (0 != memcmp(ptr, az, strlen(az))) { 462cb93a386Sopenharmony_ci ERRORF(r, "detachAsData() memcmp failed"); 463cb93a386Sopenharmony_ci return; 464cb93a386Sopenharmony_ci } 465cb93a386Sopenharmony_ci ptr += strlen(az); 466cb93a386Sopenharmony_ci } 467cb93a386Sopenharmony_ci} 468cb93a386Sopenharmony_ci 469cb93a386Sopenharmony_ciDEF_TEST(StreamCopy, reporter) { 470cb93a386Sopenharmony_ci SkRandom random(123456); 471cb93a386Sopenharmony_ci static const int N = 10000; 472cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> src((size_t)N); 473cb93a386Sopenharmony_ci for (int j = 0; j < N; ++j) { 474cb93a386Sopenharmony_ci src[j] = random.nextU() & 0xff; 475cb93a386Sopenharmony_ci } 476cb93a386Sopenharmony_ci // SkStreamCopy had two code paths; this test both. 477cb93a386Sopenharmony_ci DumbStream dumbStream(src.get(), (size_t)N); 478cb93a386Sopenharmony_ci stream_copy_test(reporter, src, N, &dumbStream); 479cb93a386Sopenharmony_ci SkMemoryStream smartStream(src.get(), (size_t)N); 480cb93a386Sopenharmony_ci stream_copy_test(reporter, src, N, &smartStream); 481cb93a386Sopenharmony_ci} 482cb93a386Sopenharmony_ci 483cb93a386Sopenharmony_ciDEF_TEST(StreamEmptyStreamMemoryBase, r) { 484cb93a386Sopenharmony_ci SkDynamicMemoryWStream tmp; 485cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> asset(tmp.detachAsStream()); 486cb93a386Sopenharmony_ci REPORTER_ASSERT(r, nullptr == asset->getMemoryBase()); 487cb93a386Sopenharmony_ci} 488cb93a386Sopenharmony_ci 489cb93a386Sopenharmony_ciDEF_TEST(FILEStreamWithOffset, r) { 490cb93a386Sopenharmony_ci if (GetResourcePath().isEmpty()) { 491cb93a386Sopenharmony_ci return; 492cb93a386Sopenharmony_ci } 493cb93a386Sopenharmony_ci 494cb93a386Sopenharmony_ci SkString filename = GetResourcePath("images/baby_tux.png"); 495cb93a386Sopenharmony_ci SkFILEStream stream1(filename.c_str()); 496cb93a386Sopenharmony_ci if (!stream1.isValid()) { 497cb93a386Sopenharmony_ci ERRORF(r, "Could not create SkFILEStream from %s", filename.c_str()); 498cb93a386Sopenharmony_ci return; 499cb93a386Sopenharmony_ci } 500cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream1.hasLength()); 501cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream1.hasPosition()); 502cb93a386Sopenharmony_ci 503cb93a386Sopenharmony_ci // Seek halfway through the file. The second SkFILEStream will be created 504cb93a386Sopenharmony_ci // with the same filename and offset and therefore will treat that offset as 505cb93a386Sopenharmony_ci // the beginning. 506cb93a386Sopenharmony_ci const size_t size = stream1.getLength(); 507cb93a386Sopenharmony_ci const size_t middle = size / 2; 508cb93a386Sopenharmony_ci if (!stream1.seek(middle)) { 509cb93a386Sopenharmony_ci ERRORF(r, "Could not seek SkFILEStream to %lu out of %lu", middle, size); 510cb93a386Sopenharmony_ci return; 511cb93a386Sopenharmony_ci } 512cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream1.getPosition() == middle); 513cb93a386Sopenharmony_ci 514cb93a386Sopenharmony_ci FILE* file = sk_fopen(filename.c_str(), kRead_SkFILE_Flag); 515cb93a386Sopenharmony_ci if (!file) { 516cb93a386Sopenharmony_ci ERRORF(r, "Could not open %s as a FILE", filename.c_str()); 517cb93a386Sopenharmony_ci return; 518cb93a386Sopenharmony_ci } 519cb93a386Sopenharmony_ci 520cb93a386Sopenharmony_ci if (fseek(file, (long) middle, SEEK_SET) != 0) { 521cb93a386Sopenharmony_ci ERRORF(r, "Could not fseek FILE to %lu out of %lu", middle, size); 522cb93a386Sopenharmony_ci return; 523cb93a386Sopenharmony_ci } 524cb93a386Sopenharmony_ci SkFILEStream stream2(file); 525cb93a386Sopenharmony_ci 526cb93a386Sopenharmony_ci const size_t remaining = size - middle; 527cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> expected(remaining); 528cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream1.read(expected.get(), remaining) == remaining); 529cb93a386Sopenharmony_ci 530cb93a386Sopenharmony_ci auto test_full_read = [&r, &expected, remaining](SkStream* stream) { 531cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> actual(remaining); 532cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->read(actual.get(), remaining) == remaining); 533cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !memcmp(expected.get(), actual.get(), remaining)); 534cb93a386Sopenharmony_ci 535cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == stream->getLength()); 536cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->isAtEnd()); 537cb93a386Sopenharmony_ci }; 538cb93a386Sopenharmony_ci 539cb93a386Sopenharmony_ci auto test_rewind = [&r, &expected, remaining](SkStream* stream) { 540cb93a386Sopenharmony_ci // Rewind goes back to original offset. 541cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->rewind()); 542cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == 0); 543cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> actual(remaining); 544cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->read(actual.get(), remaining) == remaining); 545cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !memcmp(expected.get(), actual.get(), remaining)); 546cb93a386Sopenharmony_ci }; 547cb93a386Sopenharmony_ci 548cb93a386Sopenharmony_ci auto test_move = [&r, &expected, size, remaining](SkStream* stream) { 549cb93a386Sopenharmony_ci // Cannot move to before the original offset. 550cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->move(- (long) size)); 551cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == 0); 552cb93a386Sopenharmony_ci 553cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->move(std::numeric_limits<long>::min())); 554cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == 0); 555cb93a386Sopenharmony_ci 556cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> actual(remaining); 557cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->read(actual.get(), remaining) == remaining); 558cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !memcmp(expected.get(), actual.get(), remaining)); 559cb93a386Sopenharmony_ci 560cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->isAtEnd()); 561cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == remaining); 562cb93a386Sopenharmony_ci 563cb93a386Sopenharmony_ci // Cannot move beyond the end. 564cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->move(1)); 565cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->isAtEnd()); 566cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == remaining); 567cb93a386Sopenharmony_ci }; 568cb93a386Sopenharmony_ci 569cb93a386Sopenharmony_ci auto test_seek = [&r, &expected, middle, remaining](SkStream* stream) { 570cb93a386Sopenharmony_ci // Seek to an arbitrary position. 571cb93a386Sopenharmony_ci const size_t arbitrary = middle / 2; 572cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->seek(arbitrary)); 573cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == arbitrary); 574cb93a386Sopenharmony_ci const size_t miniRemaining = remaining - arbitrary; 575cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> actual(miniRemaining); 576cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->read(actual.get(), miniRemaining) == miniRemaining); 577cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !memcmp(expected.get() + arbitrary, actual.get(), miniRemaining)); 578cb93a386Sopenharmony_ci }; 579cb93a386Sopenharmony_ci 580cb93a386Sopenharmony_ci auto test_seek_beginning = [&r, &expected, remaining](SkStream* stream) { 581cb93a386Sopenharmony_ci // Seek to the beginning. 582cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->seek(0)); 583cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == 0); 584cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> actual(remaining); 585cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->read(actual.get(), remaining) == remaining); 586cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !memcmp(expected.get(), actual.get(), remaining)); 587cb93a386Sopenharmony_ci }; 588cb93a386Sopenharmony_ci 589cb93a386Sopenharmony_ci auto test_seek_end = [&r, remaining](SkStream* stream) { 590cb93a386Sopenharmony_ci // Cannot seek past the end. 591cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->isAtEnd()); 592cb93a386Sopenharmony_ci 593cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->seek(remaining + 1)); 594cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->isAtEnd()); 595cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == remaining); 596cb93a386Sopenharmony_ci 597cb93a386Sopenharmony_ci const size_t middle = remaining / 2; 598cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->seek(middle)); 599cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !stream->isAtEnd()); 600cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == middle); 601cb93a386Sopenharmony_ci 602cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->seek(remaining * 2)); 603cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->isAtEnd()); 604cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == remaining); 605cb93a386Sopenharmony_ci 606cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->seek(std::numeric_limits<long>::max())); 607cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->isAtEnd()); 608cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == remaining); 609cb93a386Sopenharmony_ci }; 610cb93a386Sopenharmony_ci 611cb93a386Sopenharmony_ci 612cb93a386Sopenharmony_ci std::function<void (SkStream* stream, bool recurse)> test_all; 613cb93a386Sopenharmony_ci test_all = [&](SkStream* stream, bool recurse) { 614cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getLength() == remaining); 615cb93a386Sopenharmony_ci REPORTER_ASSERT(r, stream->getPosition() == 0); 616cb93a386Sopenharmony_ci 617cb93a386Sopenharmony_ci test_full_read(stream); 618cb93a386Sopenharmony_ci test_rewind(stream); 619cb93a386Sopenharmony_ci test_move(stream); 620cb93a386Sopenharmony_ci test_seek(stream); 621cb93a386Sopenharmony_ci test_seek_beginning(stream); 622cb93a386Sopenharmony_ci test_seek_end(stream); 623cb93a386Sopenharmony_ci 624cb93a386Sopenharmony_ci if (recurse) { 625cb93a386Sopenharmony_ci // Duplicate shares the original offset. 626cb93a386Sopenharmony_ci auto duplicate = stream->duplicate(); 627cb93a386Sopenharmony_ci if (!duplicate) { 628cb93a386Sopenharmony_ci ERRORF(r, "Failed to duplicate the stream!"); 629cb93a386Sopenharmony_ci } else { 630cb93a386Sopenharmony_ci test_all(duplicate.get(), false); 631cb93a386Sopenharmony_ci } 632cb93a386Sopenharmony_ci 633cb93a386Sopenharmony_ci // Fork shares the original offset, too. 634cb93a386Sopenharmony_ci auto fork = stream->fork(); 635cb93a386Sopenharmony_ci if (!fork) { 636cb93a386Sopenharmony_ci ERRORF(r, "Failed to fork the stream!"); 637cb93a386Sopenharmony_ci } else { 638cb93a386Sopenharmony_ci REPORTER_ASSERT(r, fork->isAtEnd()); 639cb93a386Sopenharmony_ci REPORTER_ASSERT(r, fork->getLength() == remaining); 640cb93a386Sopenharmony_ci REPORTER_ASSERT(r, fork->rewind()); 641cb93a386Sopenharmony_ci 642cb93a386Sopenharmony_ci test_all(fork.get(), false); 643cb93a386Sopenharmony_ci } 644cb93a386Sopenharmony_ci } 645cb93a386Sopenharmony_ci }; 646cb93a386Sopenharmony_ci 647cb93a386Sopenharmony_ci test_all(&stream2, true); 648cb93a386Sopenharmony_ci} 649cb93a386Sopenharmony_ci 650cb93a386Sopenharmony_ci#include "src/core/SkBuffer.h" 651cb93a386Sopenharmony_ci 652cb93a386Sopenharmony_ciDEF_TEST(RBuffer, reporter) { 653cb93a386Sopenharmony_ci int32_t value = 0; 654cb93a386Sopenharmony_ci SkRBuffer buffer(&value, 4); 655cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, buffer.isValid()); 656cb93a386Sopenharmony_ci 657cb93a386Sopenharmony_ci int32_t tmp; 658cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, buffer.read(&tmp, 4)); 659cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, buffer.isValid()); 660cb93a386Sopenharmony_ci 661cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !buffer.read(&tmp, 4)); 662cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !buffer.isValid()); 663cb93a386Sopenharmony_ci} 664