StreamBufferTest.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Copyright 2016 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 "src/codec/SkStreamBuffer.h"
  10. #include "src/core/SkMakeUnique.h"
  11. #include "src/utils/SkOSPath.h"
  12. #include "tests/FakeStreams.h"
  13. #include "tests/Test.h"
  14. static const char* gText = "Four score and seven years ago";
  15. static void test_get_data_at_position(skiatest::Reporter* r, SkStreamBuffer* buffer, size_t position,
  16. size_t length) {
  17. sk_sp<SkData> data = buffer->getDataAtPosition(position, length);
  18. REPORTER_ASSERT(r, data);
  19. if (data) {
  20. REPORTER_ASSERT(r, !memcmp(data->data(), gText + position, length));
  21. }
  22. }
  23. // Test buffering from the beginning, by different amounts.
  24. static void test_buffer_from_beginning(skiatest::Reporter* r, std::unique_ptr<SkStream> stream,
  25. size_t length) {
  26. if (!stream) {
  27. return;
  28. }
  29. SkStreamBuffer buffer(std::move(stream));
  30. // Buffer an arbitrary amount:
  31. size_t buffered = length / 2;
  32. REPORTER_ASSERT(r, buffer.buffer(buffered));
  33. REPORTER_ASSERT(r, !memcmp(buffer.get(), gText, buffered));
  34. // Buffering less is free:
  35. REPORTER_ASSERT(r, buffer.buffer(buffered / 2));
  36. // Buffer more should succeed:
  37. REPORTER_ASSERT(r, buffer.buffer(length));
  38. REPORTER_ASSERT(r, !memcmp(buffer.get(), gText, length));
  39. }
  40. // Test flushing the stream as we read.
  41. static void test_flushing(skiatest::Reporter* r, std::unique_ptr<SkStream> stream, size_t length,
  42. bool getDataAtPosition) {
  43. if (!stream) {
  44. return;
  45. }
  46. SkStreamBuffer buffer(std::move(stream));
  47. const size_t step = 5;
  48. for (size_t position = 0; position + step <= length; position += step) {
  49. REPORTER_ASSERT(r, buffer.buffer(step));
  50. REPORTER_ASSERT(r, buffer.markPosition() == position);
  51. if (!getDataAtPosition) {
  52. REPORTER_ASSERT(r, !memcmp(buffer.get(), gText + position, step));
  53. }
  54. buffer.flush();
  55. }
  56. REPORTER_ASSERT(r, !buffer.buffer(step));
  57. if (getDataAtPosition) {
  58. for (size_t position = 0; position + step <= length; position += step) {
  59. test_get_data_at_position(r, &buffer, position, step);
  60. }
  61. }
  62. }
  63. DEF_TEST(StreamBuffer, r) {
  64. const size_t size = strlen(gText);
  65. sk_sp<SkData> data(SkData::MakeWithoutCopy(gText, size));
  66. SkString tmpDir = skiatest::GetTmpDir();
  67. const char* subdir = "streamBuffer.txt";
  68. SkString path;
  69. if (!tmpDir.isEmpty()) {
  70. path = SkOSPath::Join(tmpDir.c_str(), subdir);
  71. SkFILEWStream writer(path.c_str());
  72. if (!writer.isValid()) {
  73. ERRORF(r, "unable to write to '%s'\n", path.c_str());
  74. return;
  75. }
  76. writer.write(gText, size);
  77. }
  78. struct {
  79. std::function<std::unique_ptr<SkStream>()> createStream;
  80. bool skipIfNoTmpDir;
  81. } factories[] = {
  82. { [&data]() { return skstd::make_unique<SkMemoryStream>(data); }, false },
  83. { [&data]() { return skstd::make_unique<NotAssetMemStream>(data); }, false },
  84. { [&path]() { return path.isEmpty()
  85. ? nullptr
  86. : skstd::make_unique<SkFILEStream>(path.c_str()); }, true },
  87. };
  88. for (auto f : factories) {
  89. if (tmpDir.isEmpty() && f.skipIfNoTmpDir) {
  90. continue;
  91. }
  92. test_buffer_from_beginning(r, f.createStream(), size);
  93. test_flushing(r, f.createStream(), size, false);
  94. test_flushing(r, f.createStream(), size, true);
  95. }
  96. // Stream that will receive more data. Will be owned by the SkStreamBuffer.
  97. auto halting = skstd::make_unique<HaltingStream>(data, 6);
  98. HaltingStream* peekHalting = halting.get();
  99. SkStreamBuffer buffer(std::move(halting));
  100. // Can only buffer less than what's available (6).
  101. REPORTER_ASSERT(r, !buffer.buffer(7));
  102. REPORTER_ASSERT(r, buffer.buffer(5));
  103. REPORTER_ASSERT(r, !memcmp(buffer.get(), gText, 5));
  104. // Add some more data. We can buffer and read all of it.
  105. peekHalting->addNewData(8);
  106. REPORTER_ASSERT(r, buffer.buffer(14));
  107. REPORTER_ASSERT(r, !memcmp(buffer.get(), gText, 14));
  108. // Flush the buffer, which moves the position.
  109. buffer.flush();
  110. // Add some data, and try to read more. Can only read what is
  111. // available.
  112. peekHalting->addNewData(9);
  113. REPORTER_ASSERT(r, !buffer.buffer(13));
  114. peekHalting->addNewData(4);
  115. REPORTER_ASSERT(r, buffer.buffer(13));
  116. // Do not call get on this data. We'll come back to this data after adding
  117. // more.
  118. buffer.flush();
  119. const size_t remaining = size - 27;
  120. REPORTER_ASSERT(r, remaining > 0);
  121. peekHalting->addNewData(remaining);
  122. REPORTER_ASSERT(r, buffer.buffer(remaining));
  123. REPORTER_ASSERT(r, !memcmp(buffer.get(), gText + 27, remaining));
  124. // Now go back to the data we skipped.
  125. test_get_data_at_position(r, &buffer, 14, 13);
  126. }