1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkData.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkOSFile.h" 10dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org#include "SkRandom.h" 11dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org#include "SkStream.h" 1229d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com#include "Test.h" 13dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SK_BUILD_FOR_WIN 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <unistd.h> 1629d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com#include <fcntl.h> 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MAX_SIZE (256 * 1024) 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void test_loop_stream(skiatest::Reporter* reporter, SkStream* stream, 22a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org const void* src, size_t len, int repeat) { 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoSMalloc<256> storage(len); 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void* tmp = storage.get(); 25d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < repeat; ++i) { 27a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org size_t bytes = stream->read(tmp, len); 28a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org REPORTER_ASSERT(reporter, bytes == len); 29a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org REPORTER_ASSERT(reporter, !memcmp(tmp, src, len)); 30a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org } 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // expect EOF 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t bytes = stream->read(tmp, 1); 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, 0 == bytes); 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // isAtEnd might not return true until after the first failing read. 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, stream->isAtEnd()); 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void test_filestreams(skiatest::Reporter* reporter, const char* tmpDir) { 4029d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com SkString path = SkOSPath::Join(tmpDir, "wstream_test"); 4129d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com 4229d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com const char s[] = "abcdefghijklmnopqrstuvwxyz"; 4329d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com 4429d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com { 4529d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com SkFILEWStream writer(path.c_str()); 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!writer.isValid()) { 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ERRORF(reporter, "Failed to create tmp file %s\n", path.c_str()); 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 100; ++i) { 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com writer.write(s, 26); 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFILEStream stream(path.c_str()); 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, stream.isValid()); 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_loop_stream(reporter, &stream, s, 26, 100); 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 61d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com SkAutoTUnref<SkStreamAsset> stream2(stream.duplicate()); 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_loop_stream(reporter, stream2.get(), s, 26, 100); 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FILE* file = ::fopen(path.c_str(), "rb"); 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFILEStream stream(file, SkFILEStream::kCallerPasses_Ownership); 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, stream.isValid()); 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_loop_stream(reporter, &stream, s, 26, 100); 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTUnref<SkStreamAsset> stream2(stream.duplicate()); 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_loop_stream(reporter, stream2.get(), s, 26, 100); 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void TestWStream(skiatest::Reporter* reporter) { 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDynamicMemoryWStream ds; 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char s[] = "abcdefghijklmnopqrstuvwxyz"; 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int i; 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (i = 0; i < 100; i++) { 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, ds.write(s, 26)); 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26); 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char* dst = new char[100 * 26 + 1]; 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[100*26] = '*'; 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ds.copyTo(dst); 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, dst[100*26] == '*'); 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (i = 0; i < 100; i++) { 90d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0); 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTUnref<SkStreamAsset> stream(ds.detachAsStream()); 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength()); 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, ds.getOffset() == 0); 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_loop_stream(reporter, stream.get(), s, 26, 100); 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTUnref<SkStreamAsset> stream2(stream->duplicate()); 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_loop_stream(reporter, stream2.get(), s, 26, 100); 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTUnref<SkStreamAsset> stream3(stream->fork()); 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, stream3->isAtEnd()); 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char tmp; 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t bytes = stream->read(&tmp, 1); 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, 0 == bytes); 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stream3->rewind(); 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_loop_stream(reporter, stream3.get(), s, 26, 100); 109bb89613380332065a2abf71b8b229eabcf2c0be8reed@google.com } 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 111bb89613380332065a2abf71b8b229eabcf2c0be8reed@google.com for (i = 0; i < 100; i++) { 112bb89613380332065a2abf71b8b229eabcf2c0be8reed@google.com REPORTER_ASSERT(reporter, ds.write(s, 26)); 113bb89613380332065a2abf71b8b229eabcf2c0be8reed@google.com } 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26); 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTUnref<SkData> data(ds.copyToData()); 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, 100 * 26 == data->size()); 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com REPORTER_ASSERT(reporter, memcmp(dst, data->data(), data->size()) == 0); 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 12357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com // Test that this works after a copyToData. 12457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com SkAutoTUnref<SkStreamAsset> stream(ds.detachAsStream()); 12557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com REPORTER_ASSERT(reporter, ds.getOffset() == 0); 12657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com test_loop_stream(reporter, stream.get(), s, 26, 100); 12757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTUnref<SkStreamAsset> stream2(stream->duplicate()); 129bc7d2fb5be746f6e0d9bd60c9e181eec20fe31eareed@android.com test_loop_stream(reporter, stream2.get(), s, 26, 100); 130bc7d2fb5be746f6e0d9bd60c9e181eec20fe31eareed@android.com } 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com delete[] dst; 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString tmpDir = skiatest::Test::GetTmpDir(); 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!tmpDir.isEmpty()) { 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com test_filestreams(reporter, tmpDir.c_str()); 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void TestPackedUInt(skiatest::Reporter* reporter) { 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we know that packeduint tries to write 1, 2 or 4 bytes for the length, 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // so we test values around each of those transitions (and a few others) 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const size_t sizes[] = { 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0, 1, 2, 0xFC, 0xFD, 0xFE, 0xFF, 0x100, 0x101, 32767, 32768, 32769, 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0xFFFD, 0xFFFE, 0xFFFF, 0x10000, 0x10001, 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0x1000000, 0x1000001, 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0x7FFFFFFE, 0x7FFFFFFF, 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t i; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char buffer[sizeof(sizes) * 4]; 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMemoryWStream wstream(buffer, sizeof(buffer)); 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) { 15529d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com bool success = wstream.writePackedUInt(sizes[i]); 15629d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com REPORTER_ASSERT(reporter, success); 15729d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com } 15829d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com wstream.flush(); 15929d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com 16029d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com SkMemoryStream rstream(buffer, sizeof(buffer)); 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (i = 0; i < SK_ARRAY_COUNT(sizes); ++i) { 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t n = rstream.readPackedUInt(); 16329d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com if (sizes[i] != n) { 16429d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com SkDebugf("-- %d: sizes:%x n:%x\n", i, sizes[i], n); 16529d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com } 16629d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com REPORTER_ASSERT(reporter, sizes[i] == n); 16729d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com } 16829d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com} 16929d4e638641d6d089a0361619ff2a583fd1a827fhalcanary@google.com 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Test that setting an SkMemoryStream to a NULL data does not result in a crash when calling 171dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org// methods that access fData. 172dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.orgstatic void TestDereferencingData(SkMemoryStream* memStream) { 173dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org memStream->read(NULL, 0); 174dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org memStream->getMemoryBase(); 175dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org SkAutoDataUnref data(memStream->copyToData()); 176dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org} 177dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org 178dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.orgstatic void TestNullData() { 179dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org SkData* nullData = NULL; 180dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org SkMemoryStream memStream(nullData); 181dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org TestDereferencingData(&memStream); 182dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org 183dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org memStream.setData(nullData); 184dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org TestDereferencingData(&memStream); 185dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org 186dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org} 187dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org 1883a8ebd9e71dab5c6640c40b8576dbe0d901c261bhalcanary@google.comDEF_TEST(Stream, reporter) { 1893a8ebd9e71dab5c6640c40b8576dbe0d901c261bhalcanary@google.com TestWStream(reporter); 1903a8ebd9e71dab5c6640c40b8576dbe0d901c261bhalcanary@google.com TestPackedUInt(reporter); 1913a8ebd9e71dab5c6640c40b8576dbe0d901c261bhalcanary@google.com TestNullData(); 1923a8ebd9e71dab5c6640c40b8576dbe0d901c261bhalcanary@google.com} 1933a8ebd9e71dab5c6640c40b8576dbe0d901c261bhalcanary@google.com