1 // Copyright (c) 2011-2017 The OTS 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 
BuildFakeScriptListTable(ots::OTSStream * out,const uint16_t script_count,const uint16_t langsys_count,const uint16_t feature_count)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 
BuildFakeFeatureListTable(ots::OTSStream * out,const uint16_t feature_count,const uint16_t lookup_count)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 
BuildFakeLookupListTable(ots::OTSStream * out,const uint16_t lookup_count,const uint16_t subtable_count)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 
BuildFakeCoverageFormat1(ots::OTSStream * out,const uint16_t glyph_count)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 
BuildFakeCoverageFormat2(ots::OTSStream * out,const uint16_t range_count)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 
BuildFakeClassDefFormat1(ots::OTSStream * out,const uint16_t glyph_count)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 
BuildFakeClassDefFormat2(ots::OTSStream * out,const uint16_t range_count)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 
BuildFakeDeviceTable(ots::OTSStream * out,const uint16_t start_size,const uint16_t end_size,const uint16_t format)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:
TestStream()233   TestStream()
234       : ots::MemoryStream(data_, sizeof(data_)), size_(0) {
235     std::memset(reinterpret_cast<char*>(data_), 0, sizeof(data_));
236   }
237 
data()238   uint8_t* data() { return data_; }
size() const239   size_t size() const { return size_; }
240 
WriteRaw(const void * d,size_t length)241   virtual bool WriteRaw(const void *d, size_t length) {
242     if (Tell() + length > size_) {
243       size_ = Tell() + length;
244     }
245     return ots::MemoryStream::WriteRaw(d, length);
246   }
247 
248  private:
249   size_t size_;
250   uint8_t data_[4096];
251 };
252 
253 class TableTest : public ::testing::Test {
254  protected:
255 
SetUp()256   virtual void SetUp() {
257     ots::FontFile *file = new ots::FontFile();
258     file->context = new ots::OTSContext();
259     font = new ots::Font(file);
260   }
261 
TearDown()262   virtual void TearDown() {
263     delete font->file->context;
264     delete font->file;
265     delete font;
266   }
267 
268   TestStream out;
269   ots::Font *font;
270 };
271 
272 class ScriptListTableTest : public TableTest { };
273 class DeviceTableTest : public TableTest { };
274 class CoverageTableTest : public TableTest { };
275 class CoverageFormat1Test : public TableTest { };
276 class CoverageFormat2Test : public TableTest { };
277 class ClassDefTableTest : public TableTest { };
278 class ClassDefFormat1Test : public TableTest { };
279 class ClassDefFormat2Test : public TableTest { };
280 class LookupSubtableParserTest : public TableTest { };
281 
282 class FeatureListTableTest : public TableTest {
283  protected:
284 
SetUp()285   virtual void SetUp() {
286     TableTest::SetUp();
287     num_features = 0;
288   }
289 
290   uint16_t num_features;
291 };
292 
fakeTypeParserReturnsTrue(const ots::Font *,const uint8_t *,const size_t)293 bool fakeTypeParserReturnsTrue(const ots::Font*, const uint8_t *,
294                                const size_t) {
295   return true;
296 }
297 
fakeTypeParserReturnsFalse(const ots::Font *,const uint8_t *,const size_t)298 bool fakeTypeParserReturnsFalse(const ots::Font*, const uint8_t *,
299                                 const size_t) {
300   return false;
301 }
302 
303 const ots::LookupSubtableParser::TypeParser TypeParsersReturnTrue[] = {
304   {1, fakeTypeParserReturnsTrue},
305   {2, fakeTypeParserReturnsTrue},
306   {3, fakeTypeParserReturnsTrue},
307   {4, fakeTypeParserReturnsTrue},
308   {5, fakeTypeParserReturnsTrue}
309 };
310 
311 // Fake lookup subtable parser which always returns true.
312 const ots::LookupSubtableParser FakeLookupParserReturnsTrue = {
313   5, 5, TypeParsersReturnTrue,
314 };
315 
316 const ots::LookupSubtableParser::TypeParser TypeParsersReturnFalse[] = {
317   {1, fakeTypeParserReturnsFalse}
318 };
319 
320 // Fake lookup subtable parser which always returns false.
321 const ots::LookupSubtableParser FakeLookupParserReturnsFalse = {
322   1, 1, TypeParsersReturnFalse
323 };
324 
325 class LookupListTableTest : public TableTest {
326  protected:
327 
SetUp()328   virtual void SetUp() {
329     TableTest::SetUp();
330     num_lookups = 0;
331   }
332 
Parse()333   bool Parse() {
334     return ots::ParseLookupListTable(font, out.data(), out.size(),
335                                      &FakeLookupParserReturnsTrue,
336                                      &num_lookups);
337   }
338 
339   uint16_t num_lookups;
340 };
341 
342 }  // namespace
343 
TEST_F(ScriptListTableTest,TestSuccess)344 TEST_F(ScriptListTableTest, TestSuccess) {
345   BuildFakeScriptListTable(&out, 1, 1, 1);
346   EXPECT_TRUE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
347 }
348 
TEST_F(ScriptListTableTest,TestBadScriptCount)349 TEST_F(ScriptListTableTest, TestBadScriptCount) {
350   BuildFakeScriptListTable(&out, 1, 1, 1);
351   // Set too large script count.
352   out.Seek(0);
353   out.WriteU16(2);
354   EXPECT_FALSE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
355 }
356 
TEST_F(ScriptListTableTest,TestScriptRecordOffsetUnderflow)357 TEST_F(ScriptListTableTest, TestScriptRecordOffsetUnderflow) {
358   BuildFakeScriptListTable(&out, 1, 1, 1);
359   // Set bad offset to ScriptRecord[0].
360   out.Seek(6);
361   out.WriteU16(0);
362   EXPECT_FALSE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
363 }
364 
TEST_F(ScriptListTableTest,TestScriptRecordOffsetOverflow)365 TEST_F(ScriptListTableTest, TestScriptRecordOffsetOverflow) {
366   BuildFakeScriptListTable(&out, 1, 1, 1);
367   // Set bad offset to ScriptRecord[0].
368   out.Seek(6);
369   out.WriteU16(out.size());
370   EXPECT_FALSE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
371 }
372 
TEST_F(ScriptListTableTest,TestBadLangSysCount)373 TEST_F(ScriptListTableTest, TestBadLangSysCount) {
374   BuildFakeScriptListTable(&out, 1, 1, 1);
375   // Set too large langsys count.
376   out.Seek(10);
377   out.WriteU16(2);
378   EXPECT_FALSE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
379 }
380 
TEST_F(ScriptListTableTest,TestLangSysRecordOffsetUnderflow)381 TEST_F(ScriptListTableTest, TestLangSysRecordOffsetUnderflow) {
382   BuildFakeScriptListTable(&out, 1, 1, 1);
383   // Set bad offset to LangSysRecord[0].
384   out.Seek(16);
385   out.WriteU16(0);
386   EXPECT_FALSE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
387 }
388 
TEST_F(ScriptListTableTest,TestLangSysRecordOffsetOverflow)389 TEST_F(ScriptListTableTest, TestLangSysRecordOffsetOverflow) {
390   BuildFakeScriptListTable(&out, 1, 1, 1);
391   // Set bad offset to LangSysRecord[0].
392   out.Seek(16);
393   out.WriteU16(out.size());
394   EXPECT_FALSE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
395 }
396 
TEST_F(ScriptListTableTest,TestBadReqFeatureIndex)397 TEST_F(ScriptListTableTest, TestBadReqFeatureIndex) {
398   BuildFakeScriptListTable(&out, 1, 1, 1);
399   // Set too large feature index to ReqFeatureIndex of LangSysTable[0].
400   out.Seek(20);
401   out.WriteU16(2);
402   EXPECT_FALSE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
403 }
404 
TEST_F(ScriptListTableTest,TestBadFeatureCount)405 TEST_F(ScriptListTableTest, TestBadFeatureCount) {
406   BuildFakeScriptListTable(&out, 1, 1, 1);
407   // Set too large feature count to LangSysTable[0].
408   out.Seek(22);
409   out.WriteU16(2);
410   EXPECT_FALSE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
411 }
412 
TEST_F(ScriptListTableTest,TestBadFeatureIndex)413 TEST_F(ScriptListTableTest, TestBadFeatureIndex) {
414   BuildFakeScriptListTable(&out, 1, 1, 1);
415   // Set too large feature index to ReatureIndex[0] of LangSysTable[0].
416   out.Seek(24);
417   out.WriteU16(2);
418   EXPECT_FALSE(ots::ParseScriptListTable(font, out.data(), out.size(), 1));
419 }
420 
TEST_F(FeatureListTableTest,TestSuccess)421 TEST_F(FeatureListTableTest, TestSuccess) {
422   BuildFakeFeatureListTable(&out, 1, 1);
423   EXPECT_TRUE(ots::ParseFeatureListTable(font, out.data(), out.size(), 1,
424                                          &num_features));
425   EXPECT_EQ(num_features, 1);
426 }
427 
TEST_F(FeatureListTableTest,TestSuccess2)428 TEST_F(FeatureListTableTest, TestSuccess2) {
429   BuildFakeFeatureListTable(&out, 5, 1);
430   EXPECT_TRUE(ots::ParseFeatureListTable(font, out.data(), out.size(), 1,
431                                          &num_features));
432   EXPECT_EQ(num_features, 5);
433 }
434 
TEST_F(FeatureListTableTest,TestBadFeatureCount)435 TEST_F(FeatureListTableTest, TestBadFeatureCount) {
436   BuildFakeFeatureListTable(&out, 1, 1);
437   // Set too large feature count.
438   out.Seek(0);
439   out.WriteU16(2);
440   EXPECT_FALSE(ots::ParseFeatureListTable(font, out.data(), out.size(), 1,
441                                           &num_features));
442 }
443 
TEST_F(FeatureListTableTest,TestOffsetFeatureUnderflow)444 TEST_F(FeatureListTableTest, TestOffsetFeatureUnderflow) {
445   BuildFakeFeatureListTable(&out, 1, 1);
446   // Set bad offset to FeatureRecord[0].
447   out.Seek(6);
448   out.WriteU16(0);
449   EXPECT_FALSE(ots::ParseFeatureListTable(font, out.data(), out.size(), 1,
450                                           &num_features));
451 }
452 
TEST_F(FeatureListTableTest,TestOffsetFeatureOverflow)453 TEST_F(FeatureListTableTest, TestOffsetFeatureOverflow) {
454   BuildFakeFeatureListTable(&out, 1, 1);
455   // Set bad offset to FeatureRecord[0].
456   out.Seek(6);
457   out.WriteU16(out.size());
458   EXPECT_FALSE(ots::ParseFeatureListTable(font, out.data(), out.size(), 1,
459                                           &num_features));
460 }
461 
TEST_F(FeatureListTableTest,TestBadLookupCount)462 TEST_F(FeatureListTableTest, TestBadLookupCount) {
463   BuildFakeFeatureListTable(&out, 1, 1);
464   // Set too large lookup count to FeatureTable[0].
465   out.Seek(10);
466   out.WriteU16(2);
467   EXPECT_FALSE(ots::ParseFeatureListTable(font, out.data(), out.size(), 1,
468                                           &num_features));
469 }
470 
TEST_F(LookupListTableTest,TestSuccess)471 TEST_F(LookupListTableTest, TestSuccess) {
472   BuildFakeLookupListTable(&out, 1, 1);
473   EXPECT_TRUE(Parse());
474   EXPECT_EQ(num_lookups, 1);
475 }
476 
TEST_F(LookupListTableTest,TestSuccess2)477 TEST_F(LookupListTableTest, TestSuccess2) {
478   BuildFakeLookupListTable(&out, 5, 1);
479   EXPECT_TRUE(Parse());
480   EXPECT_EQ(num_lookups, 5);
481 }
482 
TEST_F(LookupListTableTest,TestOffsetLookupTableUnderflow)483 TEST_F(LookupListTableTest, TestOffsetLookupTableUnderflow) {
484   BuildFakeLookupListTable(&out, 1, 1);
485   // Set bad offset to Lookup[0].
486   out.Seek(2);
487   out.WriteU16(0);
488   EXPECT_FALSE(Parse());
489 }
490 
TEST_F(LookupListTableTest,TestOffsetLookupTableOverflow)491 TEST_F(LookupListTableTest, TestOffsetLookupTableOverflow) {
492   BuildFakeLookupListTable(&out, 1, 1);
493   // Set bad offset to Lookup[0].
494   out.Seek(2);
495   out.WriteU16(out.size());
496   EXPECT_FALSE(Parse());
497 }
498 
TEST_F(LookupListTableTest,TestOffsetSubtableUnderflow)499 TEST_F(LookupListTableTest, TestOffsetSubtableUnderflow) {
500   BuildFakeLookupListTable(&out, 1, 1);
501   // Set bad offset to SubTable[0] of LookupTable[0].
502   out.Seek(10);
503   out.WriteU16(0);
504   EXPECT_FALSE(Parse());
505 }
506 
TEST_F(LookupListTableTest,TestOffsetSubtableOverflow)507 TEST_F(LookupListTableTest, TestOffsetSubtableOverflow) {
508   BuildFakeLookupListTable(&out, 1, 1);
509   // Set bad offset to SubTable[0] of LookupTable[0].
510   out.Seek(10);
511   out.WriteU16(out.size());
512   EXPECT_FALSE(Parse());
513 }
514 
TEST_F(LookupListTableTest,TesBadLookupCount)515 TEST_F(LookupListTableTest, TesBadLookupCount) {
516   BuildFakeLookupListTable(&out, 1, 1);
517   // Set too large lookup count of LookupTable[0].
518   out.Seek(0);
519   out.WriteU16(2);
520   EXPECT_FALSE(Parse());
521 }
522 
TEST_F(LookupListTableTest,TesBadLookupType)523 TEST_F(LookupListTableTest, TesBadLookupType) {
524   BuildFakeLookupListTable(&out, 1, 1);
525   // Set too large lookup type of LookupTable[0].
526   out.Seek(4);
527   out.WriteU16(6);
528   EXPECT_FALSE(Parse());
529 }
530 
TEST_F(LookupListTableTest,TesBadLookupFlag)531 TEST_F(LookupListTableTest, TesBadLookupFlag) {
532   BuildFakeLookupListTable(&out, 1, 1);
533   // Set IgnoreBaseGlyphs(0x0002) to the lookup flag of LookupTable[0].
534   out.Seek(6);
535   out.WriteU16(0x0002);
536   EXPECT_TRUE(Parse());
537 }
538 
TEST_F(LookupListTableTest,TesBadSubtableCount)539 TEST_F(LookupListTableTest, TesBadSubtableCount) {
540   BuildFakeLookupListTable(&out, 1, 1);
541   // Set too large sutable count of LookupTable[0].
542   out.Seek(8);
543   out.WriteU16(2);
544   EXPECT_FALSE(Parse());
545 }
546 
TEST_F(CoverageTableTest,TestSuccessFormat1)547 TEST_F(CoverageTableTest, TestSuccessFormat1) {
548   BuildFakeCoverageFormat1(&out, 1);
549   EXPECT_TRUE(ots::ParseCoverageTable(font, out.data(), out.size(), 1));
550 }
551 
TEST_F(CoverageTableTest,TestSuccessFormat2)552 TEST_F(CoverageTableTest, TestSuccessFormat2) {
553   BuildFakeCoverageFormat2(&out, 1);
554   EXPECT_TRUE(ots::ParseCoverageTable(font, out.data(), out.size(), 1));
555 }
556 
TEST_F(CoverageTableTest,TestBadFormat)557 TEST_F(CoverageTableTest, TestBadFormat) {
558   BuildFakeCoverageFormat1(&out, 1);
559   // Set bad format.
560   out.Seek(0);
561   out.WriteU16(3);
562   EXPECT_FALSE(ots::ParseCoverageTable(font, out.data(), out.size(), 1));
563 }
564 
TEST_F(CoverageFormat1Test,TestBadGlyphCount)565 TEST_F(CoverageFormat1Test, TestBadGlyphCount) {
566   BuildFakeCoverageFormat1(&out, 1);
567   // Set too large glyph count.
568   out.Seek(2);
569   out.WriteU16(2);
570   EXPECT_FALSE(ots::ParseCoverageTable(font, out.data(), out.size(), 1));
571 }
572 
TEST_F(CoverageFormat1Test,TestBadGlyphId)573 TEST_F(CoverageFormat1Test, TestBadGlyphId) {
574   BuildFakeCoverageFormat1(&out, 1);
575   // Set too large glyph id.
576   out.Seek(4);
577   out.WriteU16(2);
578   EXPECT_FALSE(ots::ParseCoverageTable(font, out.data(), out.size(), 1));
579 }
580 
TEST_F(CoverageFormat2Test,TestBadRangeCount)581 TEST_F(CoverageFormat2Test, TestBadRangeCount) {
582   BuildFakeCoverageFormat2(&out, 1);
583   // Set too large range count.
584   out.Seek(2);
585   out.WriteU16(2);
586   EXPECT_FALSE(ots::ParseCoverageTable(font, out.data(), out.size(), 1));
587 }
588 
TEST_F(CoverageFormat2Test,TestBadRange)589 TEST_F(CoverageFormat2Test, TestBadRange) {
590   BuildFakeCoverageFormat2(&out, 1);
591   // Set reverse order glyph id to start/end fields.
592   out.Seek(4);
593   out.WriteU16(2);
594   out.WriteU16(1);
595   EXPECT_FALSE(ots::ParseCoverageTable(font, out.data(), out.size(), 1));
596 }
597 
TEST_F(CoverageFormat2Test,TestRangeOverlap)598 TEST_F(CoverageFormat2Test, TestRangeOverlap) {
599   BuildFakeCoverageFormat2(&out, 2);
600   // Set overlapping glyph id to an end field.
601   out.Seek(12);
602   out.WriteU16(1);
603   EXPECT_FALSE(ots::ParseCoverageTable(font, out.data(), out.size(), 2));
604 }
605 
TEST_F(CoverageFormat2Test,TestRangeOverlap2)606 TEST_F(CoverageFormat2Test, TestRangeOverlap2) {
607   BuildFakeCoverageFormat2(&out, 2);
608   // Set overlapping range.
609   out.Seek(10);
610   out.WriteU16(1);
611   out.WriteU16(2);
612   EXPECT_FALSE(ots::ParseCoverageTable(font, out.data(), out.size(), 2));
613 }
614 
TEST_F(ClassDefTableTest,TestSuccessFormat1)615 TEST_F(ClassDefTableTest, TestSuccessFormat1) {
616   BuildFakeClassDefFormat1(&out, 1);
617   EXPECT_TRUE(ots::ParseClassDefTable(font, out.data(), out.size(), 1, 1));
618 }
619 
TEST_F(ClassDefTableTest,TestSuccessFormat2)620 TEST_F(ClassDefTableTest, TestSuccessFormat2) {
621   BuildFakeClassDefFormat2(&out, 1);
622   EXPECT_TRUE(ots::ParseClassDefTable(font, out.data(), out.size(), 1, 1));
623 }
624 
TEST_F(ClassDefTableTest,TestBadFormat)625 TEST_F(ClassDefTableTest, TestBadFormat) {
626   BuildFakeClassDefFormat1(&out, 1);
627   // Set bad format.
628   out.Seek(0);
629   out.WriteU16(3);
630   EXPECT_FALSE(ots::ParseClassDefTable(font, out.data(), out.size(), 1, 1));
631 }
632 
TEST_F(ClassDefFormat1Test,TestBadStartGlyph)633 TEST_F(ClassDefFormat1Test, TestBadStartGlyph) {
634   BuildFakeClassDefFormat1(&out, 1);
635   // Set too large start glyph id.
636   out.Seek(2);
637   out.WriteU16(2);
638   EXPECT_FALSE(ots::ParseClassDefTable(font, out.data(), out.size(), 1, 1));
639 }
640 
TEST_F(ClassDefFormat1Test,TestBadGlyphCount)641 TEST_F(ClassDefFormat1Test, TestBadGlyphCount) {
642   BuildFakeClassDefFormat1(&out, 1);
643   // Set too large glyph count.
644   out.Seek(4);
645   out.WriteU16(2);
646   EXPECT_FALSE(ots::ParseClassDefTable(font, out.data(), out.size(), 1, 1));
647 }
648 
TEST_F(ClassDefFormat1Test,TestBadClassValue)649 TEST_F(ClassDefFormat1Test, TestBadClassValue) {
650   BuildFakeClassDefFormat1(&out, 1);
651   // Set too large class value.
652   out.Seek(6);
653   out.WriteU16(2);
654   EXPECT_FALSE(ots::ParseClassDefTable(font, out.data(), out.size(), 1, 1));
655 }
656 
TEST_F(ClassDefFormat2Test,TestBadRangeCount)657 TEST_F(ClassDefFormat2Test, TestBadRangeCount) {
658   BuildFakeClassDefFormat2(&out, 1);
659   // Set too large range count.
660   out.Seek(2);
661   out.WriteU16(2);
662   EXPECT_FALSE(ots::ParseClassDefTable(font, out.data(), out.size(), 1, 1));
663 }
664 
TEST_F(ClassDefFormat2Test,TestRangeOverlap)665 TEST_F(ClassDefFormat2Test, TestRangeOverlap) {
666   BuildFakeClassDefFormat2(&out, 2);
667   // Set overlapping glyph id to an end field.
668   out.Seek(12);
669   out.WriteU16(1);
670   EXPECT_FALSE(ots::ParseClassDefTable(font, out.data(), out.size(), 1, 1));
671 }
672 
TEST_F(ClassDefFormat2Test,TestRangeOverlap2)673 TEST_F(ClassDefFormat2Test, TestRangeOverlap2) {
674   BuildFakeClassDefFormat2(&out, 2);
675   // Set overlapping range.
676   out.Seek(10);
677   out.WriteU16(1);
678   out.WriteU16(2);
679   EXPECT_FALSE(ots::ParseClassDefTable(font, out.data(), out.size(), 1, 1));
680 }
681 
TEST_F(DeviceTableTest,TestDeltaFormat1Success)682 TEST_F(DeviceTableTest, TestDeltaFormat1Success) {
683   BuildFakeDeviceTable(&out, 1, 8, 1);
684   EXPECT_TRUE(ots::ParseDeviceTable(font, out.data(), out.size()));
685 }
686 
TEST_F(DeviceTableTest,TestDeltaFormat1Success2)687 TEST_F(DeviceTableTest, TestDeltaFormat1Success2) {
688   BuildFakeDeviceTable(&out, 1, 9, 1);
689   EXPECT_TRUE(ots::ParseDeviceTable(font, out.data(), out.size()));
690 }
691 
TEST_F(DeviceTableTest,TestDeltaFormat1Fail)692 TEST_F(DeviceTableTest, TestDeltaFormat1Fail) {
693   // Pass shorter length than expected.
694   BuildFakeDeviceTable(&out, 1, 8, 1);
695   EXPECT_FALSE(ots::ParseDeviceTable(font, out.data(), out.size() - 1));
696 }
697 
TEST_F(DeviceTableTest,TestDeltaFormat1Fail2)698 TEST_F(DeviceTableTest, TestDeltaFormat1Fail2) {
699   // Pass shorter length than expected.
700   BuildFakeDeviceTable(&out, 1, 9, 1);
701   EXPECT_FALSE(ots::ParseDeviceTable(font, out.data(), out.size() - 1));
702 }
703 
TEST_F(DeviceTableTest,TestDeltaFormat2Success)704 TEST_F(DeviceTableTest, TestDeltaFormat2Success) {
705   BuildFakeDeviceTable(&out, 1, 1, 2);
706   EXPECT_TRUE(ots::ParseDeviceTable(font, out.data(), out.size()));
707 }
708 
TEST_F(DeviceTableTest,TestDeltaFormat2Success2)709 TEST_F(DeviceTableTest, TestDeltaFormat2Success2) {
710   BuildFakeDeviceTable(&out, 1, 8, 2);
711   EXPECT_TRUE(ots::ParseDeviceTable(font, out.data(), out.size()));
712 }
713 
TEST_F(DeviceTableTest,TestDeltaFormat2Fail)714 TEST_F(DeviceTableTest, TestDeltaFormat2Fail) {
715   // Pass shorter length than expected.
716   BuildFakeDeviceTable(&out, 1, 8, 2);
717   EXPECT_FALSE(ots::ParseDeviceTable(font, out.data(), out.size() - 1));
718 }
719 
TEST_F(DeviceTableTest,TestDeltaFormat2Fail2)720 TEST_F(DeviceTableTest, TestDeltaFormat2Fail2) {
721   // Pass shorter length than expected.
722   BuildFakeDeviceTable(&out, 1, 9, 2);
723   EXPECT_FALSE(ots::ParseDeviceTable(font, out.data(), out.size() - 1));
724 }
725 
TEST_F(DeviceTableTest,TestDeltaFormat3Success)726 TEST_F(DeviceTableTest, TestDeltaFormat3Success) {
727   BuildFakeDeviceTable(&out, 1, 1, 3);
728   EXPECT_TRUE(ots::ParseDeviceTable(font, out.data(), out.size()));
729 }
730 
TEST_F(DeviceTableTest,TestDeltaFormat3Success2)731 TEST_F(DeviceTableTest, TestDeltaFormat3Success2) {
732   BuildFakeDeviceTable(&out, 1, 8, 3);
733   EXPECT_TRUE(ots::ParseDeviceTable(font, out.data(), out.size()));
734 }
735 
TEST_F(DeviceTableTest,TestDeltaFormat3Fail)736 TEST_F(DeviceTableTest, TestDeltaFormat3Fail) {
737   // Pass shorter length than expected.
738   BuildFakeDeviceTable(&out, 1, 8, 3);
739   EXPECT_FALSE(ots::ParseDeviceTable(font, out.data(), out.size() - 1));
740 }
741 
TEST_F(DeviceTableTest,TestDeltaFormat3Fail2)742 TEST_F(DeviceTableTest, TestDeltaFormat3Fail2) {
743   // Pass shorter length than expected.
744   BuildFakeDeviceTable(&out, 1, 9, 3);
745   EXPECT_FALSE(ots::ParseDeviceTable(font, out.data(), out.size() - 1));
746 }
747 
TEST_F(LookupSubtableParserTest,TestSuccess)748 TEST_F(LookupSubtableParserTest, TestSuccess) {
749   {
750     EXPECT_TRUE(FakeLookupParserReturnsTrue.Parse(font, 0, 0, 1));
751   }
752   {
753     EXPECT_TRUE(FakeLookupParserReturnsTrue.Parse(font, 0, 0, 5));
754   }
755 }
756 
TEST_F(LookupSubtableParserTest,TestFail)757 TEST_F(LookupSubtableParserTest, TestFail) {
758   {
759     // Pass bad lookup type which less than the smallest type.
760     EXPECT_FALSE(FakeLookupParserReturnsTrue.Parse(font, 0, 0, 0));
761   }
762   {
763     // Pass bad lookup type which greater than the maximum type.
764     EXPECT_FALSE(FakeLookupParserReturnsTrue.Parse(font, 0, 0, 6));
765   }
766   {
767     // Check the type parser failure.
768     EXPECT_FALSE(FakeLookupParserReturnsFalse.Parse(font, 0, 0, 1));
769   }
770 }
771