Home | History | Annotate | Download | only in test
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <cmath>
      6 #include <vector>
      7 #include <gtest/gtest.h>
      8 
      9 #include "layout.h"
     10 #include "ots-memory-stream.h"
     11 
     12 namespace {
     13 
     14 const uint32_t kFakeTag = 0x00000000;
     15 const size_t kScriptRecordSize = 6;
     16 const size_t kLangSysRecordSize = 6;
     17 
     18 bool BuildFakeScriptListTable(ots::OTSStream *out, const uint16_t script_count,
     19                               const uint16_t langsys_count,
     20                               const uint16_t feature_count) {
     21   if (!out->WriteU16(script_count)) {
     22     return false;
     23   }
     24   const off_t script_record_end = out->Tell() +
     25       kScriptRecordSize * script_count;
     26   const size_t script_table_size = 4 + kLangSysRecordSize * langsys_count;
     27   for (unsigned i = 0; i < script_count; ++i) {
     28     if (!out->WriteU32(kFakeTag) ||
     29         !out->WriteU16(script_record_end + i * script_table_size)) {
     30       return false;
     31     }
     32   }
     33 
     34   // Offsets to LangSys tables are measured from the beginning of each
     35   // script table.
     36   const off_t langsys_record_end = 4 + kLangSysRecordSize * langsys_count;
     37   const size_t langsys_table_size = 6 + 2 * feature_count;
     38   // Write Fake Script tables.
     39   for (unsigned i = 0; i < script_count; ++i) {
     40     if (!out->WriteU16(0x0000) ||
     41         !out->WriteU16(langsys_count)) {
     42       return false;
     43     }
     44     for (unsigned j = 0; j < langsys_count; ++j) {
     45       if (!out->WriteU32(kFakeTag) ||
     46           !out->WriteU16(langsys_record_end + j * langsys_table_size)) {
     47         return false;
     48       }
     49     }
     50   }
     51 
     52   // Write Fake LangSys tables.
     53   for (unsigned i = 0; i < langsys_count; ++i) {
     54     if (!out->WriteU16(0x0000) ||
     55         !out->WriteU16(0xFFFF) ||
     56         !out->WriteU16(feature_count)) {
     57       return false;
     58     }
     59     for (unsigned j = 0; j < feature_count; ++j) {
     60       if (!out->WriteU16(j)) {
     61         return false;
     62       }
     63     }
     64   }
     65   return true;
     66 }
     67 
     68 const size_t kFeatureRecordSize = 6;
     69 
     70 bool BuildFakeFeatureListTable(ots::OTSStream *out,
     71                                const uint16_t feature_count,
     72                                const uint16_t lookup_count) {
     73   if (!out->WriteU16(feature_count)) {
     74     return false;
     75   }
     76   const off_t feature_record_end = out->Tell() +
     77       kFeatureRecordSize * feature_count;
     78   const size_t feature_table_size = 4 + 2 * lookup_count;
     79   for (unsigned i = 0; i < feature_count; ++i) {
     80     if (!out->WriteU32(kFakeTag) ||
     81         !out->WriteU16(feature_record_end + i * feature_table_size)) {
     82       return false;
     83     }
     84   }
     85 
     86   // Write FeatureTable
     87   for (unsigned i = 0; i < feature_count; ++i) {
     88     if (!out->WriteU16(0x0000) ||
     89         !out->WriteU16(lookup_count)) {
     90       return false;
     91     }
     92     for (uint16_t j = 0; j < lookup_count; ++j) {
     93       if (!out->WriteU16(j)) {
     94         return false;
     95       }
     96     }
     97   }
     98   return true;
     99 }
    100 
    101 bool BuildFakeLookupListTable(ots::OTSStream *out, const uint16_t lookup_count,
    102                               const uint16_t subtable_count) {
    103   if (!out->WriteU16(lookup_count)) {
    104     return false;
    105   }
    106   const off_t base_offset_lookup = out->Tell();
    107   if (!out->Pad(2 * lookup_count)) {
    108     return false;
    109   }
    110 
    111   std::vector<off_t> offsets_lookup(lookup_count, 0);
    112   for (uint16_t i = 0; i < lookup_count; ++i) {
    113     offsets_lookup[i] = out->Tell();
    114     if (!out->WriteU16(i + 1) ||
    115         !out->WriteU16(0) ||
    116         !out->WriteU16(subtable_count) ||
    117         !out->Pad(2 * subtable_count) ||
    118         !out->WriteU16(0)) {
    119       return false;
    120     }
    121   }
    122 
    123   const off_t offset_lookup_table_end = out->Tell();
    124   // Allocate 256 bytes for each subtable.
    125   if (!out->Pad(256 * lookup_count * subtable_count)) {
    126     return false;
    127   }
    128 
    129   if (!out->Seek(base_offset_lookup)) {
    130     return false;
    131   }
    132   for (unsigned i = 0; i < lookup_count; ++i) {
    133     if (!out->WriteU16(offsets_lookup[i])) {
    134       return false;
    135     }
    136   }
    137 
    138   for (unsigned i = 0; i < lookup_count; ++i) {
    139     if (!out->Seek(offsets_lookup[i] + 6)) {
    140       return false;
    141     }
    142     for (unsigned j = 0; j < subtable_count; ++j) {
    143       if (!out->WriteU16(offset_lookup_table_end +
    144                          256*i*subtable_count + 256*j)) {
    145         return false;
    146       }
    147     }
    148   }
    149   return true;
    150 }
    151 
    152 bool BuildFakeCoverageFormat1(ots::OTSStream *out, const uint16_t glyph_count) {
    153   if (!out->WriteU16(1) || !out->WriteU16(glyph_count)) {
    154     return false;
    155   }
    156   for (uint16_t glyph_id = 1; glyph_id <= glyph_count; ++glyph_id) {
    157     if (!out->WriteU16(glyph_id)) {
    158       return false;
    159     }
    160   }
    161   return true;
    162 }
    163 
    164 bool BuildFakeCoverageFormat2(ots::OTSStream *out, const uint16_t range_count) {
    165   if (!out->WriteU16(2) || !out->WriteU16(range_count)) {
    166     return false;
    167   }
    168   uint16_t glyph_id = 1;
    169   uint16_t start_coverage_index = 0;
    170   for (unsigned i = 0; i < range_count; ++i) {
    171     // Write consecutive ranges in which each range consists of two glyph id.
    172     if (!out->WriteU16(glyph_id) ||
    173         !out->WriteU16(glyph_id + 1) ||
    174         !out->WriteU16(start_coverage_index)) {
    175       return false;
    176     }
    177     glyph_id += 2;
    178     start_coverage_index += 2;
    179   }
    180   return true;
    181 }
    182 
    183 bool BuildFakeClassDefFormat1(ots::OTSStream *out, const uint16_t glyph_count) {
    184   if (!out->WriteU16(1) ||
    185       !out->WriteU16(1) ||
    186       !out->WriteU16(glyph_count)) {
    187     return false;
    188   }
    189   for (uint16_t class_value = 1; class_value <= glyph_count; ++class_value) {
    190     if (!out->WriteU16(class_value)) {
    191       return false;
    192     }
    193   }
    194   return true;
    195 }
    196 
    197 bool BuildFakeClassDefFormat2(ots::OTSStream *out, const uint16_t range_count) {
    198   if (!out->WriteU16(2) || !out->WriteU16(range_count)) {
    199     return false;
    200   }
    201   uint16_t glyph_id = 1;
    202   for (uint16_t class_value = 1; class_value <= range_count; ++class_value) {
    203     // Write consecutive ranges in which each range consists of one glyph id.
    204     if (!out->WriteU16(glyph_id) ||
    205         !out->WriteU16(glyph_id + 1) ||
    206         !out->WriteU16(class_value)) {
    207       return false;
    208     }
    209     glyph_id += 2;
    210   }
    211   return true;
    212 }
    213 
    214 bool BuildFakeDeviceTable(ots::OTSStream *out, const uint16_t start_size,
    215                           const uint16_t end_size, const uint16_t format) {
    216   if (!out->WriteU16(start_size) ||
    217       !out->WriteU16(end_size) ||
    218       !out->WriteU16(format)) {
    219     return false;
    220   }
    221 
    222   const unsigned num_values = std::abs(end_size - start_size) + 1;
    223   const unsigned num_bits = (1 << format) * num_values;
    224   const unsigned num_units = (num_bits - 1) / 16 + 1;
    225   if (!out->Pad(num_units * 2)) {
    226     return false;
    227   }
    228   return true;
    229 }
    230 
    231 class TestStream : public ots::MemoryStream {
    232  public:
    233   TestStream()
    234       : ots::MemoryStream(data_, sizeof(data_)), size_(0) {
    235     std::memset(reinterpret_cast<char*>(data_), 0, sizeof(data_));
    236   }
    237 
    238   uint8_t* data() { return data_; }
    239   size_t size() const { return size_; }
    240 
    241   virtual bool WriteRaw(const void *data, size_t length) {
    242     if (Tell() + length > size_) {
    243       size_ = Tell() + length;
    244     }
    245     return ots::MemoryStream::WriteRaw(data, length);
    246   }
    247 
    248  private:
    249   size_t size_;
    250   uint8_t data_[4096];
    251 };
    252 
    253 class ScriptListTableTest : public ::testing::Test {
    254  protected:
    255 
    256   TestStream out;
    257   ots::OpenTypeFile file;
    258 };
    259 
    260 class FeatureListTableTest : public ::testing::Test {
    261  protected:
    262 
    263   virtual void SetUp() {
    264     num_features = 0;
    265   }
    266 
    267   TestStream out;
    268   ots::OpenTypeFile file;
    269   uint16_t num_features;
    270 };
    271 
    272 bool fakeTypeParserReturnsTrue(const ots::OpenTypeFile*, const uint8_t *,
    273                                const size_t) {
    274   return true;
    275 }
    276 
    277 bool fakeTypeParserReturnsFalse(const ots::OpenTypeFile*, const uint8_t *,
    278                                 const size_t) {
    279   return false;
    280 }
    281 
    282 const ots::LookupSubtableParser::TypeParser TypeParsersReturnTrue[] = {
    283   {1, fakeTypeParserReturnsTrue},
    284   {2, fakeTypeParserReturnsTrue},
    285   {3, fakeTypeParserReturnsTrue},
    286   {4, fakeTypeParserReturnsTrue},
    287   {5, fakeTypeParserReturnsTrue}
    288 };
    289 
    290 // Fake lookup subtable parser which always returns true.
    291 const ots::LookupSubtableParser FakeLookupParserReturnsTrue = {
    292   5, 5, TypeParsersReturnTrue,
    293 };
    294 
    295 const ots::LookupSubtableParser::TypeParser TypeParsersReturnFalse[] = {
    296   {1, fakeTypeParserReturnsFalse}
    297 };
    298 
    299 // Fake lookup subtable parser which always returns false.
    300 const ots::LookupSubtableParser FakeLookupParserReturnsFalse = {
    301   1, 1, TypeParsersReturnFalse
    302 };
    303 
    304 class LookupListTableTest : public ::testing::Test {
    305  protected:
    306 
    307   virtual void SetUp() {
    308     num_lookups = 0;
    309   }
    310 
    311   bool Parse() {
    312     return ots::ParseLookupListTable(&file, out.data(), out.size(),
    313                                      &FakeLookupParserReturnsTrue,
    314                                      &num_lookups);
    315   }
    316 
    317   TestStream out;
    318   ots::OpenTypeFile file;
    319   uint16_t num_lookups;
    320 };
    321 
    322 }  // namespace
    323 
    324 TEST_F(ScriptListTableTest, TestSuccess) {
    325   BuildFakeScriptListTable(&out, 1, 1, 1);
    326   EXPECT_TRUE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    327 }
    328 
    329 TEST_F(ScriptListTableTest, TestBadScriptCount) {
    330   BuildFakeScriptListTable(&out, 1, 1, 1);
    331   // Set too large script count.
    332   out.Seek(0);
    333   out.WriteU16(2);
    334   EXPECT_FALSE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    335 }
    336 
    337 TEST_F(ScriptListTableTest, TestScriptRecordOffsetUnderflow) {
    338   BuildFakeScriptListTable(&out, 1, 1, 1);
    339   // Set bad offset to ScriptRecord[0].
    340   out.Seek(6);
    341   out.WriteU16(0);
    342   EXPECT_FALSE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    343 }
    344 
    345 TEST_F(ScriptListTableTest, TestScriptRecordOffsetOverflow) {
    346   BuildFakeScriptListTable(&out, 1, 1, 1);
    347   // Set bad offset to ScriptRecord[0].
    348   out.Seek(6);
    349   out.WriteU16(out.size());
    350   EXPECT_FALSE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    351 }
    352 
    353 TEST_F(ScriptListTableTest, TestBadLangSysCount) {
    354   BuildFakeScriptListTable(&out, 1, 1, 1);
    355   // Set too large langsys count.
    356   out.Seek(10);
    357   out.WriteU16(2);
    358   EXPECT_FALSE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    359 }
    360 
    361 TEST_F(ScriptListTableTest, TestLangSysRecordOffsetUnderflow) {
    362   BuildFakeScriptListTable(&out, 1, 1, 1);
    363   // Set bad offset to LangSysRecord[0].
    364   out.Seek(16);
    365   out.WriteU16(0);
    366   EXPECT_FALSE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    367 }
    368 
    369 TEST_F(ScriptListTableTest, TestLangSysRecordOffsetOverflow) {
    370   BuildFakeScriptListTable(&out, 1, 1, 1);
    371   // Set bad offset to LangSysRecord[0].
    372   out.Seek(16);
    373   out.WriteU16(out.size());
    374   EXPECT_FALSE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    375 }
    376 
    377 TEST_F(ScriptListTableTest, TestBadReqFeatureIndex) {
    378   BuildFakeScriptListTable(&out, 1, 1, 1);
    379   // Set too large feature index to ReqFeatureIndex of LangSysTable[0].
    380   out.Seek(20);
    381   out.WriteU16(2);
    382   EXPECT_FALSE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    383 }
    384 
    385 TEST_F(ScriptListTableTest, TestBadFeatureCount) {
    386   BuildFakeScriptListTable(&out, 1, 1, 1);
    387   // Set too large feature count to LangSysTable[0].
    388   out.Seek(22);
    389   out.WriteU16(2);
    390   EXPECT_FALSE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    391 }
    392 
    393 TEST_F(ScriptListTableTest, TestBadFeatureIndex) {
    394   BuildFakeScriptListTable(&out, 1, 1, 1);
    395   // Set too large feature index to ReatureIndex[0] of LangSysTable[0].
    396   out.Seek(24);
    397   out.WriteU16(2);
    398   EXPECT_FALSE(ots::ParseScriptListTable(out.data(), out.size(), 1));
    399 }
    400 
    401 TEST_F(FeatureListTableTest, TestSuccess) {
    402   BuildFakeFeatureListTable(&out, 1, 1);
    403   EXPECT_TRUE(ots::ParseFeatureListTable(out.data(), out.size(), 1,
    404                                          &num_features));
    405   EXPECT_EQ(num_features, 1);
    406 }
    407 
    408 TEST_F(FeatureListTableTest, TestSuccess2) {
    409   BuildFakeFeatureListTable(&out, 5, 1);
    410   EXPECT_TRUE(ots::ParseFeatureListTable(out.data(), out.size(), 1,
    411                                          &num_features));
    412   EXPECT_EQ(num_features, 5);
    413 }
    414 
    415 TEST_F(FeatureListTableTest, TestBadFeatureCount) {
    416   BuildFakeFeatureListTable(&out, 1, 1);
    417   // Set too large feature count.
    418   out.Seek(0);
    419   out.WriteU16(2);
    420   EXPECT_FALSE(ots::ParseFeatureListTable(out.data(), out.size(), 1,
    421                                           &num_features));
    422 }
    423 
    424 TEST_F(FeatureListTableTest, TestOffsetFeatureUnderflow) {
    425   BuildFakeFeatureListTable(&out, 1, 1);
    426   // Set bad offset to FeatureRecord[0].
    427   out.Seek(6);
    428   out.WriteU16(0);
    429   EXPECT_FALSE(ots::ParseFeatureListTable(out.data(), out.size(), 1,
    430                                           &num_features));
    431 }
    432 
    433 TEST_F(FeatureListTableTest, TestOffsetFeatureOverflow) {
    434   BuildFakeFeatureListTable(&out, 1, 1);
    435   // Set bad offset to FeatureRecord[0].
    436   out.Seek(6);
    437   out.WriteU16(out.size());
    438   EXPECT_FALSE(ots::ParseFeatureListTable(out.data(), out.size(), 1,
    439                                           &num_features));
    440 }
    441 
    442 TEST_F(FeatureListTableTest, TestBadLookupCount) {
    443   BuildFakeFeatureListTable(&out, 1, 1);
    444   // Set too large lookup count to FeatureTable[0].
    445   out.Seek(10);
    446   out.WriteU16(2);
    447   EXPECT_FALSE(ots::ParseFeatureListTable(out.data(), out.size(), 1,
    448                                           &num_features));
    449 }
    450 
    451 TEST_F(LookupListTableTest, TestSuccess) {
    452   BuildFakeLookupListTable(&out, 1, 1);
    453   EXPECT_TRUE(Parse());
    454   EXPECT_EQ(num_lookups, 1);
    455 }
    456 
    457 TEST_F(LookupListTableTest, TestSuccess2) {
    458   BuildFakeLookupListTable(&out, 5, 1);
    459   EXPECT_TRUE(Parse());
    460   EXPECT_EQ(num_lookups, 5);
    461 }
    462 
    463 TEST_F(LookupListTableTest, TestOffsetLookupTableUnderflow) {
    464   BuildFakeLookupListTable(&out, 1, 1);
    465   // Set bad offset to Lookup[0].
    466   out.Seek(2);
    467   out.WriteU16(0);
    468   EXPECT_FALSE(Parse());
    469 }
    470 
    471 TEST_F(LookupListTableTest, TestOffsetLookupTableOverflow) {
    472   BuildFakeLookupListTable(&out, 1, 1);
    473   // Set bad offset to Lookup[0].
    474   out.Seek(2);
    475   out.WriteU16(out.size());
    476   EXPECT_FALSE(Parse());
    477 }
    478 
    479 TEST_F(LookupListTableTest, TestOffsetSubtableUnderflow) {
    480   BuildFakeLookupListTable(&out, 1, 1);
    481   // Set bad offset to SubTable[0] of LookupTable[0].
    482   out.Seek(10);
    483   out.WriteU16(0);
    484   EXPECT_FALSE(Parse());
    485 }
    486 
    487 TEST_F(LookupListTableTest, TestOffsetSubtableOverflow) {
    488   BuildFakeLookupListTable(&out, 1, 1);
    489   // Set bad offset to SubTable[0] of LookupTable[0].
    490   out.Seek(10);
    491   out.WriteU16(out.size());
    492   EXPECT_FALSE(Parse());
    493 }
    494 
    495 TEST_F(LookupListTableTest, TesBadLookupCount) {
    496   BuildFakeLookupListTable(&out, 1, 1);
    497   // Set too large lookup count of LookupTable[0].
    498   out.Seek(0);
    499   out.WriteU16(2);
    500   EXPECT_FALSE(Parse());
    501 }
    502 
    503 TEST_F(LookupListTableTest, TesBadLookupType) {
    504   BuildFakeLookupListTable(&out, 1, 1);
    505   // Set too large lookup type of LookupTable[0].
    506   out.Seek(4);
    507   out.WriteU16(6);
    508   EXPECT_FALSE(Parse());
    509 }
    510 
    511 TEST_F(LookupListTableTest, TesBadLookupFlag) {
    512   BuildFakeLookupListTable(&out, 1, 1);
    513   // Set IgnoreBaseGlyphs(0x0002) to the lookup flag of LookupTable[0].
    514   out.Seek(6);
    515   out.WriteU16(0x0002);
    516   EXPECT_FALSE(Parse());
    517 }
    518 
    519 TEST_F(LookupListTableTest, TesBadSubtableCount) {
    520   BuildFakeLookupListTable(&out, 1, 1);
    521   // Set too large sutable count of LookupTable[0].
    522   out.Seek(8);
    523   out.WriteU16(2);
    524   EXPECT_FALSE(Parse());
    525 }
    526 
    527 TEST(CoverageTableTest, TestSuccessFormat1) {
    528   TestStream out;
    529   BuildFakeCoverageFormat1(&out, 1);
    530   EXPECT_TRUE(ots::ParseCoverageTable(out.data(), out.size(), 1));
    531 }
    532 
    533 TEST(CoverageTableTest, TestSuccessFormat2) {
    534   TestStream out;
    535   BuildFakeCoverageFormat2(&out, 1);
    536   EXPECT_TRUE(ots::ParseCoverageTable(out.data(), out.size(), 1));
    537 }
    538 
    539 TEST(CoverageTableTest, TestBadFormat) {
    540   TestStream out;
    541   BuildFakeCoverageFormat1(&out, 1);
    542   // Set bad format.
    543   out.Seek(0);
    544   out.WriteU16(3);
    545   EXPECT_FALSE(ots::ParseCoverageTable(out.data(), out.size(), 1));
    546 }
    547 
    548 TEST(CoverageFormat1Test, TestBadGlyphCount) {
    549   TestStream out;
    550   BuildFakeCoverageFormat1(&out, 1);
    551   // Set too large glyph count.
    552   out.Seek(2);
    553   out.WriteU16(2);
    554   EXPECT_FALSE(ots::ParseCoverageTable(out.data(), out.size(), 1));
    555 }
    556 
    557 TEST(CoverageFormat1Test, TestBadGlyphId) {
    558   TestStream out;
    559   BuildFakeCoverageFormat1(&out, 1);
    560   // Set too large glyph id.
    561   out.Seek(4);
    562   out.WriteU16(2);
    563   EXPECT_FALSE(ots::ParseCoverageTable(out.data(), out.size(), 1));
    564 }
    565 
    566 TEST(CoverageFormat2Test, TestBadRangeCount) {
    567   TestStream out;
    568   BuildFakeCoverageFormat2(&out, 1);
    569   // Set too large range count.
    570   out.Seek(2);
    571   out.WriteU16(2);
    572   EXPECT_FALSE(ots::ParseCoverageTable(out.data(), out.size(), 1));
    573 }
    574 
    575 TEST(CoverageFormat2Test, TestBadRange) {
    576   TestStream out;
    577   BuildFakeCoverageFormat2(&out, 1);
    578   // Set reverse order glyph id to start/end fields.
    579   out.Seek(4);
    580   out.WriteU16(2);
    581   out.WriteU16(1);
    582   EXPECT_FALSE(ots::ParseCoverageTable(out.data(), out.size(), 1));
    583 }
    584 
    585 TEST(CoverageFormat2Test, TestRangeOverlap) {
    586   TestStream out;
    587   BuildFakeCoverageFormat2(&out, 2);
    588   // Set overlapping glyph id to an end field.
    589   out.Seek(12);
    590   out.WriteU16(1);
    591   EXPECT_FALSE(ots::ParseCoverageTable(out.data(), out.size(), 2));
    592 }
    593 
    594 TEST(CoverageFormat2Test, TestRangeOverlap2) {
    595   TestStream out;
    596   BuildFakeCoverageFormat2(&out, 2);
    597   // Set overlapping range.
    598   out.Seek(10);
    599   out.WriteU16(1);
    600   out.WriteU16(2);
    601   EXPECT_FALSE(ots::ParseCoverageTable(out.data(), out.size(), 2));
    602 }
    603 
    604 TEST(ClassDefTableTest, TestSuccessFormat1) {
    605   TestStream out;
    606   BuildFakeClassDefFormat1(&out, 1);
    607   EXPECT_TRUE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
    608 }
    609 
    610 TEST(ClassDefTableTest, TestSuccessFormat2) {
    611   TestStream out;
    612   BuildFakeClassDefFormat2(&out, 1);
    613   EXPECT_TRUE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
    614 }
    615 
    616 TEST(ClassDefTableTest, TestBadFormat) {
    617   TestStream out;
    618   BuildFakeClassDefFormat1(&out, 1);
    619   // Set bad format.
    620   out.Seek(0);
    621   out.WriteU16(3);
    622   EXPECT_FALSE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
    623 }
    624 
    625 TEST(ClassDefFormat1Test, TestBadStartGlyph) {
    626   TestStream out;
    627   BuildFakeClassDefFormat1(&out, 1);
    628   // Set too large start glyph id.
    629   out.Seek(2);
    630   out.WriteU16(2);
    631   EXPECT_FALSE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
    632 }
    633 
    634 TEST(ClassDefFormat1Test, TestBadGlyphCount) {
    635   TestStream out;
    636   BuildFakeClassDefFormat1(&out, 1);
    637   // Set too large glyph count.
    638   out.Seek(4);
    639   out.WriteU16(2);
    640   EXPECT_FALSE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
    641 }
    642 
    643 TEST(ClassDefFormat1Test, TestBadClassValue) {
    644   TestStream out;
    645   BuildFakeClassDefFormat1(&out, 1);
    646   // Set too large class value.
    647   out.Seek(6);
    648   out.WriteU16(2);
    649   EXPECT_FALSE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
    650 }
    651 
    652 TEST(ClassDefFormat2Test, TestBadRangeCount) {
    653   TestStream out;
    654   BuildFakeClassDefFormat2(&out, 1);
    655   // Set too large range count.
    656   out.Seek(2);
    657   out.WriteU16(2);
    658   EXPECT_FALSE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
    659 }
    660 
    661 TEST(ClassDefFormat2Test, TestRangeOverlap) {
    662   TestStream out;
    663   BuildFakeClassDefFormat2(&out, 2);
    664   // Set overlapping glyph id to an end field.
    665   out.Seek(12);
    666   out.WriteU16(1);
    667   EXPECT_FALSE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
    668 }
    669 
    670 TEST(ClassDefFormat2Test, TestRangeOverlap2) {
    671   TestStream out;
    672   BuildFakeClassDefFormat2(&out, 2);
    673   // Set overlapping range.
    674   out.Seek(10);
    675   out.WriteU16(1);
    676   out.WriteU16(2);
    677   EXPECT_FALSE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
    678 }
    679 
    680 TEST(DeviceTableTest, TestDeltaFormat1Success) {
    681   {
    682     TestStream out;
    683     BuildFakeDeviceTable(&out, 1, 8, 1);
    684     EXPECT_TRUE(ots::ParseDeviceTable(out.data(), out.size()));
    685   }
    686   {
    687     TestStream out;
    688     BuildFakeDeviceTable(&out, 1, 9, 1);
    689     EXPECT_TRUE(ots::ParseDeviceTable(out.data(), out.size()));
    690   }
    691 }
    692 
    693 TEST(DeviceTableTest, TestDeltaFormat1Fail) {
    694   // Pass shorter length than expected.
    695   {
    696     TestStream out;
    697     BuildFakeDeviceTable(&out, 1, 8, 1);
    698     EXPECT_FALSE(ots::ParseDeviceTable(out.data(), out.size() - 1));
    699   }
    700   {
    701     TestStream out;
    702     BuildFakeDeviceTable(&out, 1, 9, 1);
    703     EXPECT_FALSE(ots::ParseDeviceTable(out.data(), out.size() - 1));
    704   }
    705 }
    706 
    707 TEST(DeviceTableTest, TestDeltaFormat2Success) {
    708   {
    709     TestStream out;
    710     BuildFakeDeviceTable(&out, 1, 1, 2);
    711     EXPECT_TRUE(ots::ParseDeviceTable(out.data(), out.size()));
    712   }
    713   {
    714     TestStream out;
    715     BuildFakeDeviceTable(&out, 1, 8, 2);
    716     EXPECT_TRUE(ots::ParseDeviceTable(out.data(), out.size()));
    717   }
    718 }
    719 
    720 TEST(DeviceTableTest, TestDeltaFormat2Fail) {
    721   // Pass shorter length than expected.
    722   {
    723     TestStream out;
    724     BuildFakeDeviceTable(&out, 1, 8, 2);
    725     EXPECT_FALSE(ots::ParseDeviceTable(out.data(), out.size() - 1));
    726   }
    727   {
    728     TestStream out;
    729     BuildFakeDeviceTable(&out, 1, 9, 2);
    730     EXPECT_FALSE(ots::ParseDeviceTable(out.data(), out.size() - 1));
    731   }
    732 }
    733 
    734 TEST(DeviceTableTest, TestDeltaFormat3Success) {
    735   {
    736     TestStream out;
    737     BuildFakeDeviceTable(&out, 1, 1, 3);
    738     EXPECT_TRUE(ots::ParseDeviceTable(out.data(), out.size()));
    739   }
    740   {
    741     TestStream out;
    742     BuildFakeDeviceTable(&out, 1, 8, 3);
    743     EXPECT_TRUE(ots::ParseDeviceTable(out.data(), out.size()));
    744   }
    745 }
    746 
    747 TEST(DeviceTableTest, TestDeltaFormat3Fail) {
    748   // Pass shorter length than expected.
    749   {
    750     TestStream out;
    751     BuildFakeDeviceTable(&out, 1, 8, 3);
    752     EXPECT_FALSE(ots::ParseDeviceTable(out.data(), out.size() - 1));
    753   }
    754   {
    755     TestStream out;
    756     BuildFakeDeviceTable(&out, 1, 9, 3);
    757     EXPECT_FALSE(ots::ParseDeviceTable(out.data(), out.size() - 1));
    758   }
    759 }
    760 
    761 TEST(LookupSubtableParserTest, TestSuccess) {
    762   {
    763     ots::OpenTypeFile file;
    764     EXPECT_TRUE(FakeLookupParserReturnsTrue.Parse(&file, 0, 0, 1));
    765   }
    766   {
    767     ots::OpenTypeFile file;
    768     EXPECT_TRUE(FakeLookupParserReturnsTrue.Parse(&file, 0, 0, 5));
    769   }
    770 }
    771 
    772 TEST(LookupSubtableParserTest, TestFail) {
    773   {
    774     ots::OpenTypeFile file;
    775     // Pass bad lookup type which less than the smallest type.
    776     EXPECT_FALSE(FakeLookupParserReturnsTrue.Parse(&file, 0, 0, 0));
    777   }
    778   {
    779     ots::OpenTypeFile file;
    780     // Pass bad lookup type which greater than the maximum type.
    781     EXPECT_FALSE(FakeLookupParserReturnsTrue.Parse(&file, 0, 0, 6));
    782   }
    783   {
    784     ots::OpenTypeFile file;
    785     // Check the type parser failure.
    786     EXPECT_FALSE(FakeLookupParserReturnsFalse.Parse(&file, 0, 0, 1));
    787   }
    788 }
    789