StreamTest.cpp 23 KB

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