| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2015 Google Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 */ | |
| 30 | |
| 31 #include "platform/image-decoders/FastSharedBufferReader.h" | |
| 32 #include "platform/image-decoders/SegmentReader.h" | |
| 33 | |
| 34 #include "testing/gtest/include/gtest/gtest.h" | |
| 35 | |
| 36 namespace blink { | |
| 37 | |
| 38 namespace { | |
| 39 | |
| 40 const unsigned kDefaultTestSize = 4 * SharedBuffer::kSegmentSize; | |
| 41 | |
| 42 void PrepareReferenceData(char* buffer, size_t size) { | |
| 43 for (size_t i = 0; i < size; ++i) | |
| 44 buffer[i] = static_cast<char>(i); | |
| 45 } | |
| 46 | |
| 47 PassRefPtr<SegmentReader> CopyToROBufferSegmentReader( | |
| 48 PassRefPtr<SegmentReader> input) { | |
| 49 SkRWBuffer rw_buffer; | |
| 50 const char* segment = 0; | |
| 51 size_t position = 0; | |
| 52 while (size_t length = input->GetSomeData(segment, position)) { | |
| 53 rw_buffer.append(segment, length); | |
| 54 position += length; | |
| 55 } | |
| 56 return SegmentReader::CreateFromSkROBuffer( | |
| 57 sk_sp<SkROBuffer>(rw_buffer.newRBufferSnapshot())); | |
| 58 } | |
| 59 | |
| 60 PassRefPtr<SegmentReader> CopyToDataSegmentReader( | |
| 61 PassRefPtr<SegmentReader> input) { | |
| 62 return SegmentReader::CreateFromSkData(input->GetAsSkData()); | |
| 63 } | |
| 64 | |
| 65 struct SegmentReaders { | |
| 66 RefPtr<SegmentReader> segment_readers[3]; | |
| 67 | |
| 68 SegmentReaders(PassRefPtr<SharedBuffer> input) { | |
| 69 segment_readers[0] = | |
| 70 SegmentReader::CreateFromSharedBuffer(std::move(input)); | |
| 71 segment_readers[1] = CopyToROBufferSegmentReader(segment_readers[0]); | |
| 72 segment_readers[2] = CopyToDataSegmentReader(segment_readers[0]); | |
| 73 } | |
| 74 }; | |
| 75 | |
| 76 } // namespace | |
| 77 | |
| 78 TEST(FastSharedBufferReaderTest, nonSequentialReads) { | |
| 79 char reference_data[kDefaultTestSize]; | |
| 80 PrepareReferenceData(reference_data, sizeof(reference_data)); | |
| 81 RefPtr<SharedBuffer> data = SharedBuffer::Create(); | |
| 82 data->Append(reference_data, sizeof(reference_data)); | |
| 83 | |
| 84 SegmentReaders reader_struct(data); | |
| 85 for (auto segment_reader : reader_struct.segment_readers) { | |
| 86 FastSharedBufferReader reader(segment_reader); | |
| 87 // Read size is prime such there will be a segment-spanning | |
| 88 // read eventually. | |
| 89 char temp_buffer[17]; | |
| 90 for (size_t data_position = 0; | |
| 91 data_position + sizeof(temp_buffer) < sizeof(reference_data); | |
| 92 data_position += sizeof(temp_buffer)) { | |
| 93 const char* block = reader.GetConsecutiveData( | |
| 94 data_position, sizeof(temp_buffer), temp_buffer); | |
| 95 ASSERT_FALSE( | |
| 96 memcmp(block, reference_data + data_position, sizeof(temp_buffer))); | |
| 97 } | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 TEST(FastSharedBufferReaderTest, readBackwards) { | |
| 102 char reference_data[kDefaultTestSize]; | |
| 103 PrepareReferenceData(reference_data, sizeof(reference_data)); | |
| 104 RefPtr<SharedBuffer> data = SharedBuffer::Create(); | |
| 105 data->Append(reference_data, sizeof(reference_data)); | |
| 106 | |
| 107 SegmentReaders reader_struct(data); | |
| 108 for (auto segment_reader : reader_struct.segment_readers) { | |
| 109 FastSharedBufferReader reader(segment_reader); | |
| 110 // Read size is prime such there will be a segment-spanning | |
| 111 // read eventually. | |
| 112 char temp_buffer[17]; | |
| 113 for (size_t data_offset = sizeof(temp_buffer); | |
| 114 data_offset < sizeof(reference_data); | |
| 115 data_offset += sizeof(temp_buffer)) { | |
| 116 const char* block = | |
| 117 reader.GetConsecutiveData(sizeof(reference_data) - data_offset, | |
| 118 sizeof(temp_buffer), temp_buffer); | |
| 119 ASSERT_FALSE(memcmp(block, | |
| 120 reference_data + sizeof(reference_data) - data_offset, | |
| 121 sizeof(temp_buffer))); | |
| 122 } | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 TEST(FastSharedBufferReaderTest, byteByByte) { | |
| 127 char reference_data[kDefaultTestSize]; | |
| 128 PrepareReferenceData(reference_data, sizeof(reference_data)); | |
| 129 RefPtr<SharedBuffer> data = SharedBuffer::Create(); | |
| 130 data->Append(reference_data, sizeof(reference_data)); | |
| 131 | |
| 132 SegmentReaders reader_struct(data); | |
| 133 for (auto segment_reader : reader_struct.segment_readers) { | |
| 134 FastSharedBufferReader reader(segment_reader); | |
| 135 for (size_t i = 0; i < sizeof(reference_data); ++i) { | |
| 136 ASSERT_EQ(reference_data[i], reader.GetOneByte(i)); | |
| 137 } | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 // Tests that a read from inside the penultimate segment to the very end of the | |
| 142 // buffer doesn't try to read off the end of the buffer. | |
| 143 TEST(FastSharedBufferReaderTest, readAllOverlappingLastSegmentBoundary) { | |
| 144 const unsigned kDataSize = 2 * SharedBuffer::kSegmentSize; | |
| 145 char reference_data[kDataSize]; | |
| 146 PrepareReferenceData(reference_data, kDataSize); | |
| 147 RefPtr<SharedBuffer> data = SharedBuffer::Create(); | |
| 148 data->Append(reference_data, kDataSize); | |
| 149 | |
| 150 SegmentReaders reader_struct(data); | |
| 151 for (auto segment_reader : reader_struct.segment_readers) { | |
| 152 FastSharedBufferReader reader(segment_reader); | |
| 153 char buffer[kDataSize]; | |
| 154 reader.GetConsecutiveData(0, kDataSize, buffer); | |
| 155 ASSERT_FALSE(memcmp(buffer, reference_data, kDataSize)); | |
| 156 } | |
| 157 } | |
| 158 | |
| 159 // Verify that reading past the end of the buffer does not break future reads. | |
| 160 TEST(SegmentReaderTest, readPastEndThenRead) { | |
| 161 const unsigned kDataSize = 2 * SharedBuffer::kSegmentSize; | |
| 162 char reference_data[kDataSize]; | |
| 163 PrepareReferenceData(reference_data, kDataSize); | |
| 164 RefPtr<SharedBuffer> data = SharedBuffer::Create(); | |
| 165 data->Append(reference_data, kDataSize); | |
| 166 | |
| 167 SegmentReaders reader_struct(data); | |
| 168 for (auto segment_reader : reader_struct.segment_readers) { | |
| 169 const char* contents; | |
| 170 size_t length = segment_reader->GetSomeData(contents, kDataSize); | |
| 171 EXPECT_EQ(0u, length); | |
| 172 | |
| 173 length = segment_reader->GetSomeData(contents, 0); | |
| 174 EXPECT_LE(SharedBuffer::kSegmentSize, length); | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 TEST(SegmentReaderTest, getAsSkData) { | |
| 179 const unsigned kDataSize = 4 * SharedBuffer::kSegmentSize; | |
| 180 char reference_data[kDataSize]; | |
| 181 PrepareReferenceData(reference_data, kDataSize); | |
| 182 RefPtr<SharedBuffer> data = SharedBuffer::Create(); | |
| 183 data->Append(reference_data, kDataSize); | |
| 184 | |
| 185 SegmentReaders reader_struct(data); | |
| 186 for (auto segment_reader : reader_struct.segment_readers) { | |
| 187 sk_sp<SkData> skdata = segment_reader->GetAsSkData(); | |
| 188 EXPECT_EQ(data->size(), skdata->size()); | |
| 189 | |
| 190 const char* segment; | |
| 191 size_t position = 0; | |
| 192 for (size_t length = segment_reader->GetSomeData(segment, position); length; | |
| 193 length = segment_reader->GetSomeData(segment, position)) { | |
| 194 ASSERT_FALSE(memcmp(segment, skdata->bytes() + position, length)); | |
| 195 position += length; | |
| 196 } | |
| 197 EXPECT_EQ(position, kDataSize); | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 TEST(SegmentReaderTest, variableSegments) { | |
| 202 const size_t kDataSize = 3.5 * SharedBuffer::kSegmentSize; | |
| 203 char reference_data[kDataSize]; | |
| 204 PrepareReferenceData(reference_data, kDataSize); | |
| 205 | |
| 206 RefPtr<SegmentReader> segment_reader; | |
| 207 { | |
| 208 // Create a SegmentReader with difference sized segments, to test that | |
| 209 // the SkROBuffer implementation works when two consecutive segments | |
| 210 // are not the same size. This test relies on knowledge of the | |
| 211 // internals of SkRWBuffer: it ensures that each segment is at least | |
| 212 // 4096 (though the actual data may be smaller, if it has not been | |
| 213 // written to yet), but when appending a larger amount it may create a | |
| 214 // larger segment. | |
| 215 SkRWBuffer rw_buffer; | |
| 216 rw_buffer.append(reference_data, SharedBuffer::kSegmentSize); | |
| 217 rw_buffer.append(reference_data + SharedBuffer::kSegmentSize, | |
| 218 2 * SharedBuffer::kSegmentSize); | |
| 219 rw_buffer.append(reference_data + 3 * SharedBuffer::kSegmentSize, | |
| 220 .5 * SharedBuffer::kSegmentSize); | |
| 221 | |
| 222 segment_reader = SegmentReader::CreateFromSkROBuffer( | |
| 223 sk_sp<SkROBuffer>(rw_buffer.newRBufferSnapshot())); | |
| 224 } | |
| 225 | |
| 226 const char* segment; | |
| 227 size_t position = 0; | |
| 228 size_t last_length = 0; | |
| 229 for (size_t length = segment_reader->GetSomeData(segment, position); length; | |
| 230 length = segment_reader->GetSomeData(segment, position)) { | |
| 231 // It is not a bug to have consecutive segments of the same length, but | |
| 232 // it does mean that the following test does not actually test what it | |
| 233 // is intended to test. | |
| 234 ASSERT_NE(length, last_length); | |
| 235 last_length = length; | |
| 236 | |
| 237 ASSERT_FALSE(memcmp(segment, reference_data + position, length)); | |
| 238 position += length; | |
| 239 } | |
| 240 EXPECT_EQ(position, kDataSize); | |
| 241 } | |
| 242 | |
| 243 } // namespace blink | |
| OLD | NEW |