1/* 2 * Copyright 2011 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <vector> 18#include <algorithm> 19 20#include "gtest/gtest.h" 21#include "sfntly/port/type.h" 22#include "sfntly/data/writable_font_data.h" 23#include "sfntly/data/memory_byte_array.h" 24 25namespace sfntly { 26 27const int32_t BYTE_ARRAY_SIZES[] = 28 {1, 7, 127, 128, 129, 255, 256, 257, 666, 1023, 0x10000}; 29 30// array data for searching 31const int32_t LOWER_BYTE_ARRAY_FOR_SEARCHING[] = {2, 4, 7, 13, 127}; 32const int32_t UPPER_BYTE_ARRAY_FOR_SEARCHING[] = {2, 5, 12, 16, 256}; 33const int32_t kLowerByteArrayForSearchingLength = 5; 34const int32_t kUpperByteArrayForSearchingLength = 5; 35 36// search test result pairs - number to search for; index found at 37const int32_t SEARCH_TEST_PAIRS[][2] = { 38 {0, -1}, {1, -1}, {2, 0}, {3, -1}, {4, 1}, {5, 1}, {6, -1}, {12, 2}, 39 {13, 3}, {17, -1}, {126, -1}, {127, 4}, {256, 4}, {257, -1}, {0x1000, -1} 40}; 41const int32_t kSearchTestPairsLength = 15; 42 43// offset and start index data for searching data 44// array data size, lower_start_index, lower_offset, upper_start_index, 45// upper_offset 46const int32_t SEARCH_TEST_OFFSETS[][5] = { 47 // lower[], upper[] 48 { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) 49 * DataSize::kUSHORT, 50 0, 51 DataSize::kUSHORT, 52 kLowerByteArrayForSearchingLength * DataSize::kUSHORT, 53 DataSize::kUSHORT }, 54 55 // {lower, upper} [] 56 { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) 57 * DataSize::kUSHORT, 58 0, 59 2 * DataSize::kUSHORT, 60 DataSize::kUSHORT, 61 2 * DataSize::kUSHORT }, 62 63 // upper[], lower[] 64 { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) 65 * DataSize::kUSHORT, 66 kLowerByteArrayForSearchingLength * DataSize::kUSHORT, 67 DataSize::kUSHORT, 68 0, 69 DataSize::kUSHORT }, 70 71 // {upper, lower} [] 72 { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) 73 * DataSize::kUSHORT, 74 DataSize::kUSHORT, 75 2 * DataSize::kUSHORT, 76 0, 77 2 * DataSize::kUSHORT } 78}; 79const int32_t kSearchTestOffsetLength = 4; 80 81ReadableFontData* 82FillTestFontDataWithShortsForSearching(WritableFontData* wfd, 83 const int32_t* lower_data, 84 int32_t lower_start_index, 85 int32_t lower_offset, 86 const int32_t* upper_data, 87 int32_t upper_start_index, 88 int32_t upper_offset) { 89 // lower data 90 int offset = lower_start_index; 91 for (int32_t i = 0; i < kLowerByteArrayForSearchingLength; ++i) { 92 wfd->WriteUShort(offset, lower_data[i]); 93 offset += lower_offset; 94 } 95 96 // upper data 97 offset = upper_start_index; 98 for (int32_t i = 0; i < kUpperByteArrayForSearchingLength; ++i) { 99 wfd->WriteUShort(offset, upper_data[i]); 100 offset += upper_offset; 101 } 102 103 return wfd; 104} 105 106bool TestReadableFontDataSearching() { 107 for (int32_t i = 0; i < kSearchTestOffsetLength; ++i) { 108 const int32_t* array_setup_offset = SEARCH_TEST_OFFSETS[i]; 109 WritableFontDataPtr wfd; 110 wfd.Attach(WritableFontData::CreateWritableFontData(array_setup_offset[0])); 111 FillTestFontDataWithShortsForSearching(wfd, 112 LOWER_BYTE_ARRAY_FOR_SEARCHING, 113 array_setup_offset[1], 114 array_setup_offset[2], 115 UPPER_BYTE_ARRAY_FOR_SEARCHING, 116 array_setup_offset[3], 117 array_setup_offset[4]); 118 for (int32_t j = 0; j < kSearchTestPairsLength; ++j) { 119 const int32_t* test_case = SEARCH_TEST_PAIRS[j]; 120 int32_t found = wfd->SearchUShort(array_setup_offset[1], 121 array_setup_offset[2], 122 array_setup_offset[3], 123 array_setup_offset[4], 124 kLowerByteArrayForSearchingLength, 125 test_case[0]); 126#if defined (SFNTLY_DEBUG_FONTDATA) 127 fprintf(stderr, "Searching for %d; Got %d; Expected %d; " 128 "[test %d][offset %d]\n", 129 test_case[0], found, test_case[1], j, i); 130#endif 131 EXPECT_EQ(test_case[1], found); 132 } 133 } 134 return true; 135} 136 137void FillTestByteArray(ByteArray* ba, int32_t size) { 138 for (int32_t i = 0; i < size; ++i) { 139 ba->Put(i, (byte_t)(i % 256)); 140 } 141} 142 143void ReadFontDataWithSingleByte(ReadableFontData* rfd, ByteVector* buffer) { 144 buffer->resize(rfd->Length()); 145 for (int32_t index = 0; index < rfd->Length(); ++index) { 146 (*buffer)[index] = (byte_t)(rfd->ReadByte(index)); 147 } 148} 149 150void ReadFontDataWithBuffer(ReadableFontData* rfd, 151 int32_t buffer_size, 152 ByteVector* b) { 153 ByteVector buffer(buffer_size); 154 b->resize(rfd->Length()); 155 156 int32_t index = 0; 157 while (index < rfd->Length()) { 158 int32_t bytes_read = rfd->ReadBytes(index, &(buffer[0]), 0, buffer.size()); 159 EXPECT_GE(bytes_read, 0); 160 std::copy(buffer.begin(), buffer.begin() + bytes_read, b->begin() + index); 161 index += bytes_read; 162 } 163} 164 165void ReadFontDataWithSlidingWindow(ReadableFontData* rfd, int32_t window_size, 166 ByteVector* b) { 167 b->resize(rfd->Length()); 168 int32_t index = 0; 169 while (index < rfd->Length()) { 170 int32_t actual_window_size = 171 std::min<int32_t>(window_size, b->size() - index); 172 int32_t bytes_read = 173 rfd->ReadBytes(index, &((*b)[0]), index, actual_window_size); 174 EXPECT_GE(bytes_read, 0); 175 index += bytes_read; 176 } 177} 178 179void WriteFontDataWithSingleByte(ReadableFontData* rfd, WritableFontData* wfd) { 180 for (int32_t index = 0; index < rfd->Length(); ++index) { 181 byte_t b = (byte_t)(rfd->ReadByte(index)); 182 wfd->WriteByte(index, b); 183 } 184} 185 186void WriteFontDataWithBuffer(ReadableFontData* rfd, 187 WritableFontData* wfd, 188 int32_t buffer_size) { 189 ByteVector buffer(buffer_size); 190 int32_t index = 0; 191 while (index < rfd->Length()) { 192 int32_t bytesRead = rfd->ReadBytes(index, &(buffer[0]), 0, buffer.size()); 193 wfd->WriteBytes(index, &(buffer[0]), 0, buffer.size()); 194 index += bytesRead; 195 } 196} 197 198void WriteFontDataWithSlidingWindow(ReadableFontData* rfd, 199 WritableFontData* wfd, 200 int32_t window_size) { 201 ByteVector b(rfd->Length()); 202 int32_t index = 0; 203 while (index < rfd->Length()) { 204 int32_t sliding_size = std::min<int32_t>(window_size, b.size() - index); 205 int32_t bytes_read = rfd->ReadBytes(index, &(b[0]), index, sliding_size); 206 wfd->WriteBytes(index, &(b[0]), index, sliding_size); 207 index += bytes_read; 208 } 209} 210 211bool ReadComparison(int32_t offset, 212 int32_t length, 213 ReadableFontData* rfd1, 214 ReadableFontData* rfd2) { 215 EXPECT_TRUE(length == rfd2->Length()); 216 ByteVector b1, b2; 217 b1.resize(length); 218 b2.resize(length); 219 220 // single byte reads 221 ReadFontDataWithSingleByte(rfd1, &b1); 222 ReadFontDataWithSingleByte(rfd2, &b2); 223 EXPECT_EQ(memcmp(&(b1[offset]), &(b2[0]), length), 0); 224 225 // buffer reads 226 int32_t increments = std::max<int32_t>(length / 11, 1); 227 for (int32_t buffer_size = 1; buffer_size <= length; 228 buffer_size += increments) { 229 b1.clear(); 230 b2.clear(); 231 b1.resize(length); 232 b2.resize(length); 233 ReadFontDataWithBuffer(rfd1, buffer_size, &b1); 234 ReadFontDataWithBuffer(rfd2, buffer_size, &b2); 235 int result = memcmp(&(b1[offset]), &(b2[0]), length); 236 EXPECT_EQ(result, 0); 237 } 238 239 // sliding window reads 240 for (int32_t window_size = 1; window_size <= length; 241 window_size += increments) { 242 b1.clear(); 243 b2.clear(); 244 b1.resize(length); 245 b2.resize(length); 246 ReadFontDataWithSlidingWindow(rfd1, window_size, &b1); 247 ReadFontDataWithSlidingWindow(rfd2, window_size, &b2); 248 int result = memcmp(&(b1[offset]), &(b2[0]), length); 249 EXPECT_EQ(result, 0); 250 } 251 return true; 252} 253 254void SlicingReadTest(ReadableFontData* rfd) { 255 fprintf(stderr, "read - trim = "); 256 for (int32_t trim = 0; trim < (rfd->Length() / 2) + 1; 257 trim += (rfd->Length() / 21) + 1) { 258 fprintf(stderr, "%d ", trim); 259 int32_t length = rfd->Length() - 2 * trim; 260 ReadableFontDataPtr slice; 261 slice.Attach(down_cast<ReadableFontData*>(rfd->Slice(trim, length))); 262 EXPECT_TRUE(ReadComparison(trim, length, rfd, slice)); 263 } 264 fprintf(stderr, "\n"); 265} 266 267void SlicingWriteTest(ReadableFontData* rfd, WritableFontData* wfd) { 268 fprintf(stderr, "write - trim = "); 269 for (int32_t trim = 0; trim < (rfd->Length() / 2) + 1; 270 trim += (rfd->Length() / 21) + 1) { 271 fprintf(stderr, "%d ", trim); 272 int32_t length = rfd->Length() - 2 * trim; 273 WritableFontDataPtr w_slice; 274 ReadableFontDataPtr r_slice; 275 276 // single byte writes 277 w_slice.Attach(down_cast<WritableFontData*>(wfd->Slice(trim, length))); 278 r_slice.Attach(down_cast<ReadableFontData*>(rfd->Slice(trim, length))); 279 WriteFontDataWithSingleByte(r_slice, w_slice); 280 EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice)); 281 282 // buffer writes 283 int32_t increments = std::max<int32_t>(length / 11, 1); 284 for (int32_t buffer_size = 1; buffer_size < length; 285 buffer_size += increments) { 286 w_slice.Attach(down_cast<WritableFontData*>(wfd->Slice(trim, length))); 287 r_slice.Attach(down_cast<ReadableFontData*>(rfd->Slice(trim, length))); 288 WriteFontDataWithBuffer(r_slice, w_slice, buffer_size); 289 EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice)); 290 } 291 292 // sliding window writes 293 for (int window_size = 1; window_size < length; window_size += increments) { 294 w_slice.Attach(down_cast<WritableFontData*>(wfd->Slice(trim, length))); 295 r_slice.Attach(down_cast<ReadableFontData*>(rfd->Slice(trim, length))); 296 WriteFontDataWithSlidingWindow(r_slice, w_slice, window_size); 297 EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice)); 298 } 299 } 300 fprintf(stderr, "\n"); 301} 302 303bool TestReadableFontData() { 304 for (size_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { 305 int32_t size = BYTE_ARRAY_SIZES[i]; 306 ByteArrayPtr ba = new MemoryByteArray(size); 307 FillTestByteArray(ba, size); 308 ReadableFontDataPtr rfd = new ReadableFontData(ba); 309 SlicingReadTest(rfd); 310 } 311 return true; 312} 313 314bool TestWritableFontData() { 315 for (size_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { 316 int32_t size = BYTE_ARRAY_SIZES[i]; 317 ByteArrayPtr ba = new MemoryByteArray(size); 318 FillTestByteArray(ba, size); 319 WritableFontDataPtr wfd = new WritableFontData(ba); 320 SlicingReadTest(wfd); 321 ByteArrayPtr temp = new MemoryByteArray(size); 322 WritableFontDataPtr wfd_copy = new WritableFontData(temp); 323 SlicingWriteTest(wfd, wfd_copy); 324 } 325 return true; 326} 327 328} // namespace sfntly 329 330TEST(FontData, ReadableFontDataSearching) { 331 ASSERT_TRUE(sfntly::TestReadableFontDataSearching()); 332} 333 334TEST(FontData, All) { 335 ASSERT_TRUE(sfntly::TestReadableFontData()); 336 ASSERT_TRUE(sfntly::TestWritableFontData()); 337} 338