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
12namespace {
13
14const uint32_t kFakeTag = 0x00000000;
15const size_t kScriptRecordSize = 6;
16const size_t kLangSysRecordSize = 6;
17
18bool 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
68const size_t kFeatureRecordSize = 6;
69
70bool 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
101bool 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
152bool 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
164bool 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
183bool 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
197bool 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
214bool 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
231class 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
253class ScriptListTableTest : public ::testing::Test {
254 protected:
255
256  TestStream out;
257  ots::OpenTypeFile file;
258};
259
260class 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
272bool fakeTypeParserReturnsTrue(const ots::OpenTypeFile*, const uint8_t *,
273                               const size_t) {
274  return true;
275}
276
277bool fakeTypeParserReturnsFalse(const ots::OpenTypeFile*, const uint8_t *,
278                                const size_t) {
279  return false;
280}
281
282const 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.
291const ots::LookupSubtableParser FakeLookupParserReturnsTrue = {
292  5, 5, TypeParsersReturnTrue,
293};
294
295const ots::LookupSubtableParser::TypeParser TypeParsersReturnFalse[] = {
296  {1, fakeTypeParserReturnsFalse}
297};
298
299// Fake lookup subtable parser which always returns false.
300const ots::LookupSubtableParser FakeLookupParserReturnsFalse = {
301  1, 1, TypeParsersReturnFalse
302};
303
304class 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
324TEST_F(ScriptListTableTest, TestSuccess) {
325  BuildFakeScriptListTable(&out, 1, 1, 1);
326  EXPECT_TRUE(ots::ParseScriptListTable(out.data(), out.size(), 1));
327}
328
329TEST_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
337TEST_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
345TEST_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
353TEST_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
361TEST_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
369TEST_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
377TEST_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
385TEST_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
393TEST_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
401TEST_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
408TEST_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
415TEST_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
424TEST_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
433TEST_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
442TEST_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
451TEST_F(LookupListTableTest, TestSuccess) {
452  BuildFakeLookupListTable(&out, 1, 1);
453  EXPECT_TRUE(Parse());
454  EXPECT_EQ(num_lookups, 1);
455}
456
457TEST_F(LookupListTableTest, TestSuccess2) {
458  BuildFakeLookupListTable(&out, 5, 1);
459  EXPECT_TRUE(Parse());
460  EXPECT_EQ(num_lookups, 5);
461}
462
463TEST_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
471TEST_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
479TEST_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
487TEST_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
495TEST_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
503TEST_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
511TEST_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
519TEST_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
527TEST(CoverageTableTest, TestSuccessFormat1) {
528  TestStream out;
529  BuildFakeCoverageFormat1(&out, 1);
530  EXPECT_TRUE(ots::ParseCoverageTable(out.data(), out.size(), 1));
531}
532
533TEST(CoverageTableTest, TestSuccessFormat2) {
534  TestStream out;
535  BuildFakeCoverageFormat2(&out, 1);
536  EXPECT_TRUE(ots::ParseCoverageTable(out.data(), out.size(), 1));
537}
538
539TEST(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
548TEST(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
557TEST(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
566TEST(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
575TEST(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
585TEST(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
594TEST(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
604TEST(ClassDefTableTest, TestSuccessFormat1) {
605  TestStream out;
606  BuildFakeClassDefFormat1(&out, 1);
607  EXPECT_TRUE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
608}
609
610TEST(ClassDefTableTest, TestSuccessFormat2) {
611  TestStream out;
612  BuildFakeClassDefFormat2(&out, 1);
613  EXPECT_TRUE(ots::ParseClassDefTable(out.data(), out.size(), 1, 1));
614}
615
616TEST(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
625TEST(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
634TEST(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
643TEST(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
652TEST(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
661TEST(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
670TEST(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
680TEST(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
693TEST(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
707TEST(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
720TEST(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
734TEST(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
747TEST(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
761TEST(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
772TEST(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