1// Copyright (c) 2010 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 "cff_type2_charstring.h"
6
7#include <gtest/gtest.h>
8
9#include <climits>
10#include <vector>
11
12#include "cff.h"
13
14// Returns a biased number for callsubr and callgsubr operators.
15#define GET_SUBR_NUMBER(n) ((n) - 107)
16#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
17
18namespace {
19
20// A constant which is used in AddSubr function below.
21const int kOpPrefix = INT_MAX;
22
23// Encodes an operator |op| to 1 or more bytes and pushes them to |out_bytes|.
24// Returns true if the conversion succeeds.
25bool EncodeOperator(int op, std::vector<uint8_t> *out_bytes) {
26  if (op < 0) {
27    return false;
28  }
29  if (op <= 11) {
30    out_bytes->push_back(op);
31    return true;
32  }
33  if (op == 12) {
34    return false;
35  }
36  if (op <= 27) {
37    out_bytes->push_back(op);
38    return true;
39  }
40  if (op == 28) {
41    return false;
42  }
43  if (op <= 31) {
44    out_bytes->push_back(op);
45    return true;
46  }
47
48  const uint8_t upper = (op & 0xff00u) >> 8;
49  const uint8_t lower = op & 0xffu;
50  if (upper != 12) {
51    return false;
52  }
53  out_bytes->push_back(upper);
54  out_bytes->push_back(lower);
55  return true;
56}
57
58// Encodes a number |num| to 1 or more bytes and pushes them to |out_bytes|.
59// Returns true if the conversion succeeds. The function does not support 16.16
60// Fixed number.
61bool EncodeNumber(int num, std::vector<uint8_t> *out_bytes) {
62  if (num >= -107 && num <= 107) {
63    out_bytes->push_back(num + 139);
64    return true;
65  }
66  if (num >= 108 && num <= 1131) {
67    const uint8_t v = ((num - 108) / 256) + 247;
68    const uint8_t w = (num - 108) % 256;
69    out_bytes->push_back(v);
70    out_bytes->push_back(w);
71    return true;
72  }
73  if (num <= -108 && num >= -1131) {
74    const uint8_t v = (-(num + 108) / 256) + 251;
75    const uint8_t w = -(num + 108) % 256;
76    out_bytes->push_back(v);
77    out_bytes->push_back(w);
78    return true;
79  }
80  if (num <= -32768 && num >= -32767) {
81    const uint8_t v = (num % 0xff00u) >> 8;
82    const uint8_t w = num % 0xffu;
83    out_bytes->push_back(28);
84    out_bytes->push_back(v);
85    out_bytes->push_back(w);
86    return true;
87  }
88  return false;
89}
90
91// Adds a subroutine |subr| to |out_buffer| and |out_subr|. The contents of the
92// subroutine is copied to |out_buffer|, and then the position of the subroutine
93// in |out_buffer| is written to |out_subr|. Returns true on success.
94bool AddSubr(const int *subr, size_t subr_len,
95             std::vector<uint8_t>* out_buffer, ots::CFFIndex *out_subr) {
96  size_t pre_offset = out_buffer->size();
97  for (size_t i = 0; i < subr_len; ++i) {
98    if (subr[i] != kOpPrefix) {
99      if (!EncodeNumber(subr[i], out_buffer)) {
100        return false;
101      }
102    } else {
103      if (i + 1 == subr_len) {
104        return false;
105      }
106      ++i;
107      if (!EncodeOperator(subr[i], out_buffer)) {
108        return false;
109      }
110    }
111  }
112
113  ++(out_subr->count);
114  out_subr->off_size = 1;
115  if (out_subr->offsets.empty()) {
116    out_subr->offsets.push_back(pre_offset);
117  }
118  out_subr->offsets.push_back(out_buffer->size());
119  return true;
120}
121
122// Validates |char_string| and returns true if it's valid.
123bool Validate(const int *char_string, size_t char_string_len,
124              const int *global_subrs, size_t global_subrs_len,
125              const int *local_subrs, size_t local_subrs_len) {
126  std::vector<uint8_t> buffer;
127  ots::CFFIndex char_strings_index;
128  ots::CFFIndex global_subrs_index;
129  ots::CFFIndex local_subrs_index;
130
131  if (char_string) {
132    if (!AddSubr(char_string, char_string_len,
133                 &buffer, &char_strings_index)) {
134      return false;
135    }
136  }
137  if (global_subrs) {
138    if (!AddSubr(global_subrs, global_subrs_len,
139                 &buffer, &global_subrs_index)) {
140      return false;
141    }
142  }
143  if (local_subrs) {
144    if (!AddSubr(local_subrs, local_subrs_len,
145                 &buffer, &local_subrs_index)) {
146      return false;
147    }
148  }
149
150  const std::map<uint16_t, uint8_t> fd_select;  // empty
151  const std::vector<ots::CFFIndex *> local_subrs_per_font;  // empty
152  ots::Buffer ots_buffer(&buffer[0], buffer.size());
153
154  return ots::ValidateType2CharStringIndex(char_strings_index,
155                                           global_subrs_index,
156                                           fd_select,
157                                           local_subrs_per_font,
158                                           &local_subrs_index,
159                                           &ots_buffer);
160}
161
162// Validates |char_string| and returns true if it's valid.
163bool ValidateCharStrings(const int *char_string, size_t char_string_len) {
164  return Validate(char_string, char_string_len, NULL, 0, NULL, 0);
165}
166
167}  // namespace
168
169TEST(ValidateTest, TestRMoveTo) {
170  {
171    const int char_string[] = {
172      1, 2, kOpPrefix, ots::kRMoveTo,
173      kOpPrefix, ots::kEndChar,
174    };
175    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
176  }
177  {
178    const int char_string[] = {
179      1,  // width
180      1, 2, kOpPrefix, ots::kRMoveTo,
181      kOpPrefix, ots::kEndChar,
182    };
183    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
184  }
185  {
186    const int char_string[] = {
187      1, 2, kOpPrefix, ots::kRMoveTo,
188      1, 2, 3, kOpPrefix, ots::kRMoveTo,  // invalid number of args
189      kOpPrefix, ots::kEndChar,
190    };
191    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
192  }
193}
194
195TEST(ValidateTest, TestHMoveTo) {
196  {
197    const int char_string[] = {
198      1, kOpPrefix, ots::kHMoveTo,
199      kOpPrefix, ots::kEndChar,
200    };
201    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
202  }
203  {
204    const int char_string[] = {
205      1,  // width
206      1, kOpPrefix, ots::kHMoveTo,
207      kOpPrefix, ots::kEndChar,
208    };
209    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
210  }
211  {
212    const int char_string[] = {
213      1, kOpPrefix, ots::kHMoveTo,
214      1, 2, kOpPrefix, ots::kHMoveTo,  // invalid
215      kOpPrefix, ots::kEndChar,
216    };
217    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
218  }
219}
220
221TEST(ValidateTest, TestVMoveTo) {
222  {
223    const int char_string[] = {
224      1, kOpPrefix, ots::kVMoveTo,
225      kOpPrefix, ots::kEndChar,
226    };
227    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
228  }
229  {
230    const int char_string[] = {
231      1,  // width
232      1, kOpPrefix, ots::kVMoveTo,
233      kOpPrefix, ots::kEndChar,
234    };
235    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
236  }
237  {
238    const int char_string[] = {
239      1, kOpPrefix, ots::kVMoveTo,
240      1, 2, kOpPrefix, ots::kVMoveTo,  // invalid
241      kOpPrefix, ots::kEndChar,
242    };
243    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
244  }
245}
246
247TEST(ValidateTest, TestRLineTo) {
248  {
249    const int char_string[] = {
250      1, kOpPrefix, ots::kVMoveTo,
251      1, 2, kOpPrefix, ots::kRLineTo,
252      kOpPrefix, ots::kEndChar,
253    };
254    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
255  }
256  {
257    const int char_string[] = {
258      1, kOpPrefix, ots::kVMoveTo,
259      1, 2, 3, kOpPrefix, ots::kRLineTo,  // invalid
260      kOpPrefix, ots::kEndChar,
261    };
262    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
263  }
264  {
265    const int char_string[] = {
266      1, kOpPrefix, ots::kVMoveTo,
267      1, 2, 3, 4, kOpPrefix, ots::kRLineTo,
268      kOpPrefix, ots::kEndChar,
269    };
270    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
271  }
272  {
273    const int char_string[] = {
274      1, 2, kOpPrefix, ots::kRLineTo,  // can't be the first op.
275      kOpPrefix, ots::kEndChar,
276    };
277    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
278  }
279}
280
281TEST(ValidateTest, TestHLineTo) {
282  {
283    const int char_string[] = {
284      1, kOpPrefix, ots::kVMoveTo,
285      1, kOpPrefix, ots::kHLineTo,
286      1, 2, kOpPrefix, ots::kHLineTo,
287      1, 2, 3, kOpPrefix, ots::kHLineTo,
288      1, 2, 3, 4, kOpPrefix, ots::kHLineTo,
289      1, 2, 3, 4, 5, kOpPrefix, ots::kHLineTo,
290      kOpPrefix, ots::kEndChar,
291    };
292    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
293  }
294  {
295    const int char_string[] = {
296      1, kOpPrefix, ots::kVMoveTo,
297      kOpPrefix, ots::kHLineTo,  // invalid
298      kOpPrefix, ots::kEndChar,
299    };
300    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
301  }
302  {
303    const int char_string[] = {
304      1, kOpPrefix, ots::kHLineTo,  // can't be the first op.
305      kOpPrefix, ots::kEndChar,
306    };
307    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
308  }
309}
310
311TEST(ValidateTest, TestVLineTo) {
312  {
313    const int char_string[] = {
314      1, kOpPrefix, ots::kVMoveTo,
315      1, kOpPrefix, ots::kVLineTo,
316      1, 2, kOpPrefix, ots::kVLineTo,
317      1, 2, 3, kOpPrefix, ots::kVLineTo,
318      1, 2, 3, 4, kOpPrefix, ots::kVLineTo,
319      1, 2, 3, 4, 5, kOpPrefix, ots::kVLineTo,
320      kOpPrefix, ots::kEndChar,
321    };
322    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
323  }
324  {
325    const int char_string[] = {
326      1, kOpPrefix, ots::kVMoveTo,
327      kOpPrefix, ots::kVLineTo,  // invalid
328      kOpPrefix, ots::kEndChar,
329    };
330    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
331  }
332  {
333    const int char_string[] = {
334      1, kOpPrefix, ots::kVLineTo,  // can't be the first op.
335      kOpPrefix, ots::kEndChar,
336    };
337    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
338  }
339}
340
341TEST(ValidateTest, TestRRCurveTo) {
342  {
343    const int char_string[] = {
344      1, kOpPrefix, ots::kVMoveTo,
345      1, 2, 3, 4, 5, 6, kOpPrefix, ots::kRRCurveTo,
346      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, kOpPrefix, ots::kRRCurveTo,
347      kOpPrefix, ots::kEndChar,
348    };
349    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
350  }
351  {
352    const int char_string[] = {
353      1, kOpPrefix, ots::kVMoveTo,
354      kOpPrefix, ots::kRRCurveTo,  // invalid
355      kOpPrefix, ots::kEndChar,
356    };
357    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
358  }
359  {
360    const int char_string[] = {
361      1, 2, 3, 4, 5, 6, kOpPrefix, ots::kRRCurveTo,  // can't be the first op.
362      kOpPrefix, ots::kEndChar,
363    };
364    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
365  }
366}
367
368TEST(ValidateTest, TestHHCurveTo) {
369  {
370    const int char_string[] = {
371      1, kOpPrefix, ots::kVMoveTo,
372      1, 2, 3, 4, kOpPrefix, ots::kHHCurveTo,
373      1, 2, 3, 4, 5, kOpPrefix, ots::kHHCurveTo,
374      1, 2, 3, 4, 5, 6, 7, 8, 9, kOpPrefix, ots::kHHCurveTo,
375      kOpPrefix, ots::kEndChar,
376    };
377    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
378  }
379  {
380    const int char_string[] = {
381      1, kOpPrefix, ots::kVMoveTo,
382      1, kOpPrefix, ots::kHHCurveTo,  // invalid
383      kOpPrefix, ots::kEndChar,
384    };
385    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
386  }
387  {
388    const int char_string[] = {
389      1, kOpPrefix, ots::kVMoveTo,
390      1, 2, 3, kOpPrefix, ots::kHHCurveTo,  // invalid
391      kOpPrefix, ots::kEndChar,
392    };
393    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
394  }
395  {
396    const int char_string[] = {
397      1, 2, 3, 4, 5, kOpPrefix, ots::kHHCurveTo,  // can't be the first op.
398      kOpPrefix, ots::kEndChar,
399    };
400    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
401  }
402}
403
404TEST(ValidateTest, TestHVCurveTo) {
405  {
406    const int char_string[] = {
407      1, kOpPrefix, ots::kVMoveTo,
408      // The first form.
409      1, 2, 3, 4, kOpPrefix, ots::kHVCurveTo,
410      1, 2, 3, 4, 5, kOpPrefix, ots::kHVCurveTo,
411      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, kOpPrefix, ots::kHVCurveTo,
412      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
413      kOpPrefix, ots::kHVCurveTo,
414      // The second form.
415      1, 2, 3, 4, 5, 6, 7, 8, kOpPrefix, ots::kHVCurveTo,
416      1, 2, 3, 4, 5, 6, 7, 8, 9, kOpPrefix, ots::kHVCurveTo,
417      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
418      kOpPrefix, ots::kHVCurveTo,
419      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
420      22, 23, 24, 25, kOpPrefix, ots::kHVCurveTo,
421      kOpPrefix, ots::kEndChar,
422    };
423    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
424  }
425  {
426    const int char_string[] = {
427      1, kOpPrefix, ots::kVMoveTo,
428      1, kOpPrefix, ots::kHVCurveTo,  // invalid
429      kOpPrefix, ots::kEndChar,
430    };
431    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
432  }
433  {
434    const int char_string[] = {
435      1, kOpPrefix, ots::kVMoveTo,
436      1, 2, 3, kOpPrefix, ots::kHVCurveTo,  // invalid
437      kOpPrefix, ots::kEndChar,
438    };
439    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
440  }
441  {
442    const int char_string[] = {
443      1, 2, 3, 4, kOpPrefix, ots::kHVCurveTo,  // can't be the first op.
444      kOpPrefix, ots::kEndChar,
445    };
446    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
447  }
448}
449
450TEST(ValidateTest, TestRCurveLine) {
451  {
452    const int char_string[] = {
453      1, kOpPrefix, ots::kVMoveTo,
454      1, 2, 3, 4, 5, 6, 7, 8, kOpPrefix, ots::kRCurveLine,
455      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
456      kOpPrefix, ots::kRCurveLine,
457      kOpPrefix, ots::kEndChar,
458    };
459    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
460  }
461  {
462    const int char_string[] = {
463      1, kOpPrefix, ots::kVMoveTo,
464      1, 2, 3, 4, 5, 6, 7, kOpPrefix, ots::kRCurveLine,  // invalid
465      kOpPrefix, ots::kEndChar,
466    };
467    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
468  }
469  {
470    const int char_string[] = {
471      // can't be the first op.
472      1, 2, 3, 4, 5, 6, 7, 8, kOpPrefix, ots::kRCurveLine,
473      kOpPrefix, ots::kEndChar,
474    };
475    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
476  }
477}
478
479TEST(ValidateTest, TestRLineCurve) {
480  {
481    const int char_string[] = {
482      1, kOpPrefix, ots::kVMoveTo,
483      1, 2, 3, 4, 5, 6, 7, 8, kOpPrefix, ots::kRLineCurve,
484      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, kOpPrefix, ots::kRLineCurve,
485      kOpPrefix, ots::kEndChar,
486    };
487    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
488  }
489  {
490    const int char_string[] = {
491      1, kOpPrefix, ots::kVMoveTo,
492      1, 2, 3, 4, 5, 6, 7, kOpPrefix, ots::kRLineCurve,  // invalid
493      kOpPrefix, ots::kEndChar,
494    };
495    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
496  }
497  {
498    const int char_string[] = {
499      // can't be the first op.
500      1, 2, 3, 4, 5, 6, 7, 8, kOpPrefix, ots::kRLineCurve,
501      kOpPrefix, ots::kEndChar,
502    };
503    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
504  }
505}
506
507TEST(ValidateTest, TestVHCurveTo) {
508  {
509    const int char_string[] = {
510      1, kOpPrefix, ots::kVMoveTo,
511      // The first form.
512      1, 2, 3, 4, kOpPrefix, ots::kVHCurveTo,
513      1, 2, 3, 4, 5, kOpPrefix, ots::kVHCurveTo,
514      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, kOpPrefix, ots::kVHCurveTo,
515      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
516      kOpPrefix, ots::kVHCurveTo,
517      // The second form.
518      1, 2, 3, 4, 5, 6, 7, 8, kOpPrefix, ots::kVHCurveTo,
519      1, 2, 3, 4, 5, 6, 7, 8, 9, kOpPrefix, ots::kVHCurveTo,
520      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
521      kOpPrefix, ots::kVHCurveTo,
522      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
523      22, 23, 24, 25, kOpPrefix, ots::kVHCurveTo,
524      kOpPrefix, ots::kEndChar,
525    };
526    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
527  }
528  {
529    const int char_string[] = {
530      1, kOpPrefix, ots::kVMoveTo,
531      1, kOpPrefix, ots::kVHCurveTo,  // invalid
532      kOpPrefix, ots::kEndChar,
533    };
534    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
535  }
536  {
537    const int char_string[] = {
538      1, kOpPrefix, ots::kVMoveTo,
539      1, 2, 3, kOpPrefix, ots::kVHCurveTo,  // invalid
540      kOpPrefix, ots::kEndChar,
541    };
542    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
543  }
544  {
545    const int char_string[] = {
546      1, 2, 3, 4, kOpPrefix, ots::kVHCurveTo,  // can't be the first op.
547      kOpPrefix, ots::kEndChar,
548    };
549    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
550  }
551}
552
553TEST(ValidateTest, TestVVCurveTo) {
554  {
555    const int char_string[] = {
556      1, kOpPrefix, ots::kVMoveTo,
557      1, 2, 3, 4, kOpPrefix, ots::kVVCurveTo,
558      1, 2, 3, 4, 5, kOpPrefix, ots::kVVCurveTo,
559      1, 2, 3, 4, 5, 6, 7, 8, kOpPrefix, ots::kVVCurveTo,
560      1, 2, 3, 4, 5, 6, 7, 8, 9, kOpPrefix, ots::kVVCurveTo,
561      kOpPrefix, ots::kEndChar,
562    };
563    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
564  }
565  {
566    const int char_string[] = {
567      1, kOpPrefix, ots::kVMoveTo,
568      kOpPrefix, ots::kVVCurveTo,  // invalid
569      kOpPrefix, ots::kEndChar,
570    };
571    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
572  }
573  {
574    const int char_string[] = {
575      1, kOpPrefix, ots::kVMoveTo,
576      1, kOpPrefix, ots::kVVCurveTo,  // invalid
577      kOpPrefix, ots::kEndChar,
578    };
579    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
580  }
581  {
582    const int char_string[] = {
583      1, 2, 3, 4, kOpPrefix, ots::kVVCurveTo,  // can't be the first op.
584      kOpPrefix, ots::kEndChar,
585    };
586    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
587  }
588}
589
590TEST(ValidateTest, TestFlex) {
591  {
592    const int char_string[] = {
593      1, kOpPrefix, ots::kVMoveTo,
594      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, kOpPrefix, ots::kFlex,
595      kOpPrefix, ots::kEndChar,
596    };
597    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
598  }
599  {
600    const int char_string[] = {
601      1, kOpPrefix, ots::kVMoveTo,
602      kOpPrefix, ots::kFlex,  // invalid
603      kOpPrefix, ots::kEndChar,
604    };
605    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
606  }
607  {
608    const int char_string[] = {
609      1, kOpPrefix, ots::kVMoveTo,
610      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, kOpPrefix, ots::kFlex,  // invalid
611      kOpPrefix, ots::kEndChar,
612    };
613    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
614  }
615  {
616    const int char_string[] = {
617      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, kOpPrefix, ots::kFlex,
618      kOpPrefix, ots::kEndChar,
619    };
620    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
621  }
622}
623
624TEST(ValidateTest, TestHFlex) {
625  {
626    const int char_string[] = {
627      1, kOpPrefix, ots::kVMoveTo,
628      1, 2, 3, 4, 5, 6, 7, kOpPrefix, ots::kHFlex,
629      kOpPrefix, ots::kEndChar,
630    };
631    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
632  }
633  {
634    const int char_string[] = {
635      1, kOpPrefix, ots::kVMoveTo,
636      kOpPrefix, ots::kHFlex,  // invalid
637      kOpPrefix, ots::kEndChar,
638    };
639    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
640  }
641  {
642    const int char_string[] = {
643      1, kOpPrefix, ots::kVMoveTo,
644      1, 2, 3, 4, 5, 6, kOpPrefix, ots::kHFlex,  // invalid
645      kOpPrefix, ots::kEndChar,
646    };
647    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
648  }
649  {
650    const int char_string[] = {
651      1, 2, 3, 4, 5, 6, 7, kOpPrefix, ots::kHFlex,
652      kOpPrefix, ots::kEndChar,
653    };
654    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
655  }
656}
657
658TEST(ValidateTest, TestHFlex1) {
659  {
660    const int char_string[] = {
661      1, kOpPrefix, ots::kVMoveTo,
662      1, 2, 3, 4, 5, 6, 7, 8, 9, kOpPrefix, ots::kHFlex1,
663      kOpPrefix, ots::kEndChar,
664    };
665    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
666  }
667  {
668    const int char_string[] = {
669      1, kOpPrefix, ots::kVMoveTo,
670      kOpPrefix, ots::kHFlex1,  // invalid
671      kOpPrefix, ots::kEndChar,
672    };
673    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
674  }
675  {
676    const int char_string[] = {
677      1, kOpPrefix, ots::kVMoveTo,
678      1, 2, 3, 4, 5, 6, 7, 8, kOpPrefix, ots::kHFlex1,  // invalid
679      kOpPrefix, ots::kEndChar,
680    };
681    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
682  }
683  {
684    const int char_string[] = {
685      1, 2, 3, 4, 5, 6, 7, 8, 9, kOpPrefix, ots::kHFlex1,
686      kOpPrefix, ots::kEndChar,
687    };
688    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
689  }
690}
691
692TEST(ValidateTest, TestFlex1) {
693  {
694    const int char_string[] = {
695      1, kOpPrefix, ots::kVMoveTo,
696      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, kOpPrefix, ots::kFlex1,
697      kOpPrefix, ots::kEndChar,
698    };
699    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
700  }
701  {
702    const int char_string[] = {
703      1, kOpPrefix, ots::kVMoveTo,
704      kOpPrefix, ots::kFlex1,  // invalid
705      kOpPrefix, ots::kEndChar,
706    };
707    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
708  }
709  {
710    const int char_string[] = {
711      1, kOpPrefix, ots::kVMoveTo,
712      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, kOpPrefix, ots::kFlex1,  // invalid
713      kOpPrefix, ots::kEndChar,
714    };
715    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
716  }
717  {
718    const int char_string[] = {
719      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, kOpPrefix, ots::kFlex1,
720      kOpPrefix, ots::kEndChar,
721    };
722    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
723  }
724}
725
726TEST(ValidateTest, TestEndChar) {
727  {
728    const int char_string[] = {
729      kOpPrefix, ots::kEndChar,
730    };
731    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
732  }
733  {
734    const int char_string[] = {
735      1, kOpPrefix, ots::kVMoveTo,
736      kOpPrefix, ots::kEndChar,
737    };
738    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
739  }
740  {
741    const int char_string[] = {
742      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallSubr,
743    };
744    const int local_subrs[] = {
745      kOpPrefix, ots::kEndChar,
746    };
747    EXPECT_TRUE(Validate(char_string, ARRAYSIZE(char_string),
748                         NULL, 0,
749                         local_subrs, ARRAYSIZE(local_subrs)));
750  }
751  {
752    const int char_string[] = {
753      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallGSubr,
754    };
755    const int global_subrs[] = {
756      kOpPrefix, ots::kEndChar,
757    };
758    EXPECT_TRUE(Validate(char_string, ARRAYSIZE(char_string),
759                         global_subrs, ARRAYSIZE(global_subrs),
760                         NULL, 0));
761  }
762}
763
764TEST(ValidateTest, TestHStem) {
765  {
766    const int char_string[] = {
767      1, 2, kOpPrefix, ots::kHStem,
768      kOpPrefix, ots::kEndChar,
769    };
770    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
771  }
772  {
773    const int char_string[] = {
774      1, 2, 3, 4, kOpPrefix, ots::kHStem,
775      kOpPrefix, ots::kEndChar,
776    };
777    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
778  }
779  {
780    const int char_string[] = {
781      0,  // width
782      1, 2, kOpPrefix, ots::kHStem,
783      kOpPrefix, ots::kEndChar,
784    };
785    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
786  }
787  {
788    const int char_string[] = {
789      1, kOpPrefix, ots::kVMoveTo,
790      0, 1, 2, kOpPrefix, ots::kHStem,  // invalid
791      kOpPrefix, ots::kEndChar,
792    };
793    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
794  }
795  {
796    const int char_string[] = {
797      1, kOpPrefix, ots::kVMoveTo,
798      1, 2, 3, 4, 5, kOpPrefix, ots::kHStem,  // invalid
799      kOpPrefix, ots::kEndChar,
800    };
801    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
802  }
803}
804
805TEST(ValidateTest, TestVStem) {
806  {
807    const int char_string[] = {
808      1, 2, kOpPrefix, ots::kVStem,
809      kOpPrefix, ots::kEndChar,
810    };
811    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
812  }
813  {
814    const int char_string[] = {
815      1, 2, 3, 4, kOpPrefix, ots::kVStem,
816      kOpPrefix, ots::kEndChar,
817    };
818    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
819  }
820  {
821    const int char_string[] = {
822      0,  // width
823      1, 2, kOpPrefix, ots::kVStem,
824      kOpPrefix, ots::kEndChar,
825    };
826    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
827  }
828  {
829    const int char_string[] = {
830      1, kOpPrefix, ots::kVMoveTo,
831      0, 1, 2, kOpPrefix, ots::kVStem,  // invalid
832      kOpPrefix, ots::kEndChar,
833    };
834    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
835  }
836  {
837    const int char_string[] = {
838      1, kOpPrefix, ots::kVMoveTo,
839      1, 2, 3, 4, 5, kOpPrefix, ots::kVStem,  // invalid
840      kOpPrefix, ots::kEndChar,
841    };
842    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
843  }
844}
845
846TEST(ValidateTest, TestHStemHm) {
847  {
848    const int char_string[] = {
849      1, 2, kOpPrefix, ots::kHStemHm,
850      kOpPrefix, ots::kEndChar,
851    };
852    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
853  }
854  {
855    const int char_string[] = {
856      1, 2, 3, 4, kOpPrefix, ots::kHStemHm,
857      kOpPrefix, ots::kEndChar,
858    };
859    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
860  }
861  {
862    const int char_string[] = {
863      0,  // width
864      1, 2, kOpPrefix, ots::kHStemHm,
865      kOpPrefix, ots::kEndChar,
866    };
867    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
868  }
869  {
870    const int char_string[] = {
871      1, kOpPrefix, ots::kVMoveTo,
872      0, 1, 2, kOpPrefix, ots::kHStemHm,  // invalid
873      kOpPrefix, ots::kEndChar,
874    };
875    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
876  }
877  {
878    const int char_string[] = {
879      1, kOpPrefix, ots::kVMoveTo,
880      1, 2, 3, 4, 5, kOpPrefix, ots::kHStemHm,  // invalid
881      kOpPrefix, ots::kEndChar,
882    };
883    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
884  }
885}
886
887TEST(ValidateTest, TestVStemHm) {
888  {
889    const int char_string[] = {
890      1, 2, kOpPrefix, ots::kVStemHm,
891      kOpPrefix, ots::kEndChar,
892    };
893    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
894  }
895  {
896    const int char_string[] = {
897      1, 2, 3, 4, kOpPrefix, ots::kVStemHm,
898      kOpPrefix, ots::kEndChar,
899    };
900    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
901  }
902  {
903    const int char_string[] = {
904      0,  // width
905      1, 2, kOpPrefix, ots::kVStemHm,
906      kOpPrefix, ots::kEndChar,
907    };
908    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
909  }
910  {
911    const int char_string[] = {
912      1, kOpPrefix, ots::kVMoveTo,
913      0, 1, 2, kOpPrefix, ots::kVStemHm,  // invalid
914      kOpPrefix, ots::kEndChar,
915    };
916    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
917  }
918  {
919    const int char_string[] = {
920      1, kOpPrefix, ots::kVMoveTo,
921      1, 2, 3, 4, 5, kOpPrefix, ots::kVStemHm,  // invalid
922      kOpPrefix, ots::kEndChar,
923    };
924    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
925  }
926}
927
928TEST(ValidateTest, TestHintMask) {
929  {
930    const int char_string[] = {
931      1, 2, kOpPrefix, ots::kHStem,
932      kOpPrefix, ots::kHintMask, 0x00,
933      kOpPrefix, ots::kEndChar,
934    };
935    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
936  }
937  {
938    const int char_string[] = {
939      1, 2, kOpPrefix, ots::kHStem,
940      3, 4, 5, 6, kOpPrefix, ots::kHintMask, 0x00,  // vstem
941      kOpPrefix, ots::kEndChar,
942    };
943    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
944  }
945  {
946    const int char_string[] = {
947      kOpPrefix, ots::kHintMask, 0x00,  // no stems to mask
948      kOpPrefix, ots::kEndChar,
949    };
950    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
951  }
952  {
953    const int char_string[] = {
954      1, 2, kOpPrefix, ots::kHStem,
955      3, 4, 5, kOpPrefix, ots::kHintMask, 0x00,  // invalid vstem
956      kOpPrefix, ots::kEndChar,
957    };
958    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
959  }
960}
961
962TEST(ValidateTest, TestCntrMask) {
963  {
964    const int char_string[] = {
965      1, 2, kOpPrefix, ots::kHStem,
966      kOpPrefix, ots::kCntrMask, 0x00,
967      kOpPrefix, ots::kEndChar,
968    };
969    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
970  }
971  {
972    const int char_string[] = {
973      1, 2, kOpPrefix, ots::kHStem,
974      3, 4, 5, 6, kOpPrefix, ots::kCntrMask, 0x00,  // vstem
975      kOpPrefix, ots::kEndChar,
976    };
977    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
978  }
979  {
980    const int char_string[] = {
981      kOpPrefix, ots::kCntrMask, 0x00,  // no stems to mask
982      kOpPrefix, ots::kEndChar,
983    };
984    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
985  }
986  {
987    const int char_string[] = {
988      1, 2, kOpPrefix, ots::kHStem,
989      3, 4, 5, kOpPrefix, ots::kCntrMask, 0x00,  // invalid vstem
990      kOpPrefix, ots::kEndChar,
991    };
992    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
993  }
994}
995
996TEST(ValidateTest, TestAbs) {
997  {
998    const int char_string[] = {
999      -1, kOpPrefix, ots::kAbs,
1000      2, kOpPrefix, ots::kHStem,
1001      kOpPrefix, ots::kEndChar,
1002    };
1003    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1004  }
1005  {
1006    const int char_string[] = {
1007      kOpPrefix, ots::kAbs,  // invalid
1008      2, kOpPrefix, ots::kHStem,
1009      kOpPrefix, ots::kEndChar,
1010    };
1011    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1012  }
1013}
1014
1015TEST(ValidateTest, TestAdd) {
1016  {
1017    const int char_string[] = {
1018      0, 1, kOpPrefix, ots::kAdd,
1019      2, kOpPrefix, ots::kHStem,
1020      kOpPrefix, ots::kEndChar,
1021    };
1022    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1023  }
1024  {
1025    const int char_string[] = {
1026      1, kOpPrefix, ots::kAdd,  // invalid
1027      2, kOpPrefix, ots::kHStem,
1028      kOpPrefix, ots::kEndChar,
1029    };
1030    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1031  }
1032}
1033
1034TEST(ValidateTest, TestSub) {
1035  {
1036    const int char_string[] = {
1037      2, 1, kOpPrefix, ots::kSub,
1038      2, kOpPrefix, ots::kHStem,
1039      kOpPrefix, ots::kEndChar,
1040    };
1041    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1042  }
1043  {
1044    const int char_string[] = {
1045      1, kOpPrefix, ots::kSub,  // invalid
1046      2, kOpPrefix, ots::kHStem,
1047      kOpPrefix, ots::kEndChar,
1048    };
1049    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1050  }
1051}
1052
1053TEST(ValidateTest, TestDiv) {
1054  // TODO(yusukes): Test div-by-zero.
1055  {
1056    const int char_string[] = {
1057      2, 1, kOpPrefix, ots::kDiv,
1058      2, kOpPrefix, ots::kHStem,
1059      kOpPrefix, ots::kEndChar,
1060    };
1061    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1062  }
1063  {
1064    const int char_string[] = {
1065      1, kOpPrefix, ots::kDiv,  // invalid
1066      2, kOpPrefix, ots::kHStem,
1067      kOpPrefix, ots::kEndChar,
1068    };
1069    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1070  }
1071}
1072
1073TEST(ValidateTest, TestNeg) {
1074  {
1075    const int char_string[] = {
1076      -1, kOpPrefix, ots::kNeg,
1077      2, kOpPrefix, ots::kHStem,
1078      kOpPrefix, ots::kEndChar,
1079    };
1080    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1081  }
1082  {
1083    const int char_string[] = {
1084      kOpPrefix, ots::kNeg,  // invalid
1085      2, kOpPrefix, ots::kHStem,
1086      kOpPrefix, ots::kEndChar,
1087    };
1088    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1089  }
1090}
1091
1092TEST(ValidateTest, TestRandom) {
1093  {
1094    const int char_string[] = {
1095      kOpPrefix, ots::kRandom,  // OTS rejects the operator.
1096      2, kOpPrefix, ots::kHStem,
1097      kOpPrefix, ots::kEndChar,
1098    };
1099    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1100  }
1101}
1102
1103TEST(ValidateTest, TestMul) {
1104  {
1105    const int char_string[] = {
1106      2, 1, kOpPrefix, ots::kMul,
1107      2, kOpPrefix, ots::kHStem,
1108      kOpPrefix, ots::kEndChar,
1109    };
1110    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1111  }
1112  {
1113    const int char_string[] = {
1114      1, kOpPrefix, ots::kMul,  // invalid
1115      2, kOpPrefix, ots::kHStem,
1116      kOpPrefix, ots::kEndChar,
1117    };
1118    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1119  }
1120}
1121
1122TEST(ValidateTest, TestSqrt) {
1123  // TODO(yusukes): Test negative numbers.
1124  {
1125    const int char_string[] = {
1126      4, kOpPrefix, ots::kSqrt,
1127      2, kOpPrefix, ots::kHStem,
1128      kOpPrefix, ots::kEndChar,
1129    };
1130    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1131  }
1132  {
1133    const int char_string[] = {
1134      kOpPrefix, ots::kSqrt,  // invalid
1135      2, kOpPrefix, ots::kHStem,
1136      kOpPrefix, ots::kEndChar,
1137    };
1138    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1139  }
1140}
1141
1142TEST(ValidateTest, TestDrop) {
1143  {
1144    const int char_string[] = {
1145      1, 1, kOpPrefix, ots::kAdd,
1146      kOpPrefix, ots::kDrop,
1147      1, 2, kOpPrefix, ots::kHStem,
1148      kOpPrefix, ots::kEndChar,
1149    };
1150    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1151  }
1152  {
1153    const int char_string[] = {
1154      kOpPrefix, ots::kDrop,  // invalid
1155      1, 2, kOpPrefix, ots::kHStem,
1156      kOpPrefix, ots::kEndChar,
1157    };
1158    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1159  }
1160}
1161
1162TEST(ValidateTest, TestExch) {
1163  {
1164    const int char_string[] = {
1165      1, 1, kOpPrefix, ots::kAdd,
1166      kOpPrefix, ots::kDup,
1167      kOpPrefix, ots::kExch,
1168      kOpPrefix, ots::kHStem,
1169      kOpPrefix, ots::kEndChar,
1170    };
1171    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1172  }
1173  {
1174    const int char_string[] = {
1175      1, 1, kOpPrefix, ots::kAdd,
1176      kOpPrefix, ots::kExch,  // invalid
1177      2, kOpPrefix, ots::kHStem,
1178      kOpPrefix, ots::kEndChar,
1179    };
1180    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1181  }
1182}
1183
1184TEST(ValidateTest, TestIndex) {
1185  {
1186    const int char_string[] = {
1187      1, 2, 3, -1, kOpPrefix, ots::kIndex,  // OTS rejects the operator.
1188      kOpPrefix, ots::kHStem,
1189      kOpPrefix, ots::kEndChar,
1190    };
1191    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1192  }
1193}
1194
1195TEST(ValidateTest, TestRoll) {
1196  {
1197    const int char_string[] = {
1198      1, 2, 2, 1, kOpPrefix, ots::kRoll,  // OTS rejects the operator.
1199      kOpPrefix, ots::kHStem,
1200      kOpPrefix, ots::kEndChar,
1201    };
1202    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1203  }
1204}
1205
1206TEST(ValidateTest, TestDup) {
1207  {
1208    const int char_string[] = {
1209      1, 1, kOpPrefix, ots::kAdd,
1210      kOpPrefix, ots::kDup,
1211      kOpPrefix, ots::kHStem,
1212      kOpPrefix, ots::kEndChar,
1213    };
1214    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1215  }
1216  {
1217    const int char_string[] = {
1218      kOpPrefix, ots::kDup,  // invalid
1219      2, kOpPrefix, ots::kHStem,
1220      kOpPrefix, ots::kEndChar,
1221    };
1222    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1223  }
1224}
1225
1226TEST(ValidateTest, TestPut) {
1227  {
1228    const int char_string[] = {
1229      1, 10, kOpPrefix, ots::kPut,  // OTS rejects the operator.
1230      1, 2, kOpPrefix, ots::kHStem,
1231      kOpPrefix, ots::kEndChar,
1232    };
1233    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1234  }
1235}
1236
1237TEST(ValidateTest, TestGet) {
1238  {
1239    const int char_string[] = {
1240      1, 10, kOpPrefix, ots::kGet,  // OTS rejects the operator.
1241      1, 2, kOpPrefix, ots::kHStem,
1242      kOpPrefix, ots::kEndChar,
1243    };
1244    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1245  }
1246}
1247
1248TEST(ValidateTest, TestAnd) {
1249  {
1250    const int char_string[] = {
1251      2, 1, kOpPrefix, ots::kAnd,
1252      2, kOpPrefix, ots::kHStem,
1253      kOpPrefix, ots::kEndChar,
1254    };
1255    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1256  }
1257  {
1258    const int char_string[] = {
1259      1, kOpPrefix, ots::kAnd,  // invalid
1260      2, kOpPrefix, ots::kHStem,
1261      kOpPrefix, ots::kEndChar,
1262    };
1263    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1264  }
1265}
1266
1267TEST(ValidateTest, TestOr) {
1268  {
1269    const int char_string[] = {
1270      2, 1, kOpPrefix, ots::kOr,
1271      2, kOpPrefix, ots::kHStem,
1272      kOpPrefix, ots::kEndChar,
1273    };
1274    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1275  }
1276  {
1277    const int char_string[] = {
1278      1, kOpPrefix, ots::kOr,  // invalid
1279      2, kOpPrefix, ots::kHStem,
1280      kOpPrefix, ots::kEndChar,
1281    };
1282    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1283  }
1284}
1285
1286TEST(ValidateTest, TestNot) {
1287  {
1288    const int char_string[] = {
1289      1, kOpPrefix, ots::kNot,
1290      2, kOpPrefix, ots::kHStem,
1291      kOpPrefix, ots::kEndChar,
1292    };
1293    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1294  }
1295  {
1296    const int char_string[] = {
1297      kOpPrefix, ots::kNot,  // invalid
1298      2, kOpPrefix, ots::kHStem,
1299      kOpPrefix, ots::kEndChar,
1300    };
1301    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1302  }
1303}
1304
1305TEST(ValidateTest, TestEq) {
1306  {
1307    const int char_string[] = {
1308      2, 1, kOpPrefix, ots::kEq,
1309      2, kOpPrefix, ots::kHStem,
1310      kOpPrefix, ots::kEndChar,
1311    };
1312    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1313  }
1314  {
1315    const int char_string[] = {
1316      1, kOpPrefix, ots::kEq,  // invalid
1317      2, kOpPrefix, ots::kHStem,
1318      kOpPrefix, ots::kEndChar,
1319    };
1320    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1321  }
1322}
1323
1324TEST(ValidateTest, TestIfElse) {
1325  {
1326    const int char_string[] = {
1327      1, 2, 3, 4, kOpPrefix, ots::kIfElse,
1328      2, kOpPrefix, ots::kHStem,
1329      kOpPrefix, ots::kEndChar,
1330    };
1331    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1332  }
1333  {
1334    const int char_string[] = {
1335      1, 2, 3, kOpPrefix, ots::kIfElse,  // invalid
1336      2, kOpPrefix, ots::kHStem,
1337      kOpPrefix, ots::kEndChar,
1338    };
1339    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1340  }
1341}
1342
1343TEST(ValidateTest, TestCallSubr) {
1344  // Call valid subr.
1345  {
1346    const int char_string[] = {
1347      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallSubr,
1348    };
1349    const int local_subrs[] = {
1350      kOpPrefix, ots::kEndChar,
1351    };
1352    EXPECT_TRUE(Validate(char_string, ARRAYSIZE(char_string),
1353                         NULL, 0,
1354                         local_subrs, ARRAYSIZE(local_subrs)));
1355  }
1356  // Call undefined subr.
1357  {
1358    const int char_string[] = {
1359      GET_SUBR_NUMBER(-1), kOpPrefix, ots::kCallSubr,
1360    };
1361    const int local_subrs[] = {
1362      kOpPrefix, ots::kEndChar,
1363    };
1364    EXPECT_FALSE(Validate(char_string, ARRAYSIZE(char_string),
1365                          NULL, 0,
1366                          local_subrs, ARRAYSIZE(local_subrs)));
1367  }
1368  {
1369    const int char_string[] = {
1370      GET_SUBR_NUMBER(1), kOpPrefix, ots::kCallSubr,
1371    };
1372    const int local_subrs[] = {
1373      kOpPrefix, ots::kEndChar,
1374    };
1375    EXPECT_FALSE(Validate(char_string, ARRAYSIZE(char_string),
1376                          NULL, 0,
1377                          local_subrs, ARRAYSIZE(local_subrs)));
1378  }
1379  {
1380    const int char_string[] = {
1381      GET_SUBR_NUMBER(-1), kOpPrefix, ots::kCallSubr,
1382    };
1383    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1384  }
1385  {
1386    const int char_string[] = {
1387      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallSubr,
1388    };
1389    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1390  }
1391  {
1392    const int char_string[] = {
1393      GET_SUBR_NUMBER(1), kOpPrefix, ots::kCallSubr,
1394    };
1395    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1396  }
1397}
1398
1399TEST(ValidateTest, TestCallGSubr) {
1400  // Call valid subr.
1401  {
1402    const int char_string[] = {
1403      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallGSubr,
1404    };
1405    const int global_subrs[] = {
1406      kOpPrefix, ots::kEndChar,
1407    };
1408    EXPECT_TRUE(Validate(char_string, ARRAYSIZE(char_string),
1409                         global_subrs, ARRAYSIZE(global_subrs),
1410                         NULL, 0));
1411  }
1412  // Call undefined subr.
1413  {
1414    const int char_string[] = {
1415      GET_SUBR_NUMBER(-1), kOpPrefix, ots::kCallGSubr,
1416    };
1417    const int global_subrs[] = {
1418      kOpPrefix, ots::kEndChar,
1419    };
1420    EXPECT_FALSE(Validate(char_string, ARRAYSIZE(char_string),
1421                          global_subrs, ARRAYSIZE(global_subrs),
1422                          NULL, 0));
1423  }
1424  {
1425    const int char_string[] = {
1426      GET_SUBR_NUMBER(1), kOpPrefix, ots::kCallGSubr,
1427    };
1428    const int global_subrs[] = {
1429      kOpPrefix, ots::kEndChar,
1430    };
1431    EXPECT_FALSE(Validate(char_string, ARRAYSIZE(char_string),
1432                          global_subrs, ARRAYSIZE(global_subrs),
1433                          NULL, 0));
1434  }
1435  {
1436    const int char_string[] = {
1437      GET_SUBR_NUMBER(-1), kOpPrefix, ots::kCallGSubr,
1438    };
1439    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1440  }
1441  {
1442    const int char_string[] = {
1443      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallGSubr,
1444    };
1445    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1446  }
1447  {
1448    const int char_string[] = {
1449      GET_SUBR_NUMBER(1), kOpPrefix, ots::kCallGSubr,
1450    };
1451    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1452  }
1453}
1454
1455TEST(ValidateTest, TestCallGSubrWithComputedValues) {
1456  {
1457    // OTS does not allow to call(g)subr with a subroutine number which is
1458    // not a immediate value for safety.
1459    const int char_string[] = {
1460      0, 0, kOpPrefix, ots::kAdd,
1461      kOpPrefix, ots::kCallGSubr,
1462    };
1463    const int global_subrs[] = {
1464      kOpPrefix, ots::kEndChar,
1465    };
1466    EXPECT_FALSE(Validate(char_string, ARRAYSIZE(char_string),
1467                          global_subrs, ARRAYSIZE(global_subrs),
1468                          NULL, 0));
1469  }
1470}
1471
1472TEST(ValidateTest, TestInfiniteLoop) {
1473  {
1474    const int char_string[] = {
1475      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallSubr,
1476    };
1477    const int local_subrs[] = {
1478      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallSubr,
1479    };
1480    EXPECT_FALSE(Validate(char_string, ARRAYSIZE(char_string),
1481                          NULL, 0,
1482                          local_subrs, ARRAYSIZE(local_subrs)));
1483  }
1484  {
1485    const int char_string[] = {
1486      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallGSubr,
1487    };
1488    const int global_subrs[] = {
1489      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallGSubr,
1490    };
1491    EXPECT_FALSE(Validate(char_string, ARRAYSIZE(char_string),
1492                          global_subrs, ARRAYSIZE(global_subrs),
1493                          NULL, 0));
1494  }
1495  // mutual recursion which doesn't stop.
1496  {
1497    const int char_string[] = {
1498      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallSubr,
1499    };
1500    const int global_subrs[] = {
1501      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallSubr,
1502    };
1503    const int local_subrs[] = {
1504      GET_SUBR_NUMBER(0), kOpPrefix, ots::kCallGSubr,
1505    };
1506    EXPECT_FALSE(Validate(char_string, ARRAYSIZE(char_string),
1507                          global_subrs, ARRAYSIZE(global_subrs),
1508                          local_subrs, ARRAYSIZE(local_subrs)));
1509  }
1510}
1511
1512TEST(ValidateTest, TestStackOverflow) {
1513  {
1514    const int char_string[] = {
1515      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1516      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1517      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1518      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1519      1, 2, 3, 4, 5, 6, 7, 8,
1520      kOpPrefix, ots::kEndChar,
1521    };
1522    EXPECT_TRUE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1523  }
1524  {
1525    const int char_string[] = {
1526      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1527      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1528      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1529      1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1530      1, 2, 3, 4, 5, 6, 7, 8, 9,  // overflow
1531      kOpPrefix, ots::kEndChar,
1532    };
1533    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1534  }
1535}
1536
1537TEST(ValidateTest, TestDeprecatedOperators) {
1538  {
1539    const int char_string[] = {
1540      kOpPrefix, (12 << 8) + 0,  // dotsection operator, which is not supported.
1541      kOpPrefix, ots::kEndChar,
1542    };
1543    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1544  }
1545  {
1546    const int char_string[] = {
1547      kOpPrefix, 16,  // 'blend'.
1548      kOpPrefix, ots::kEndChar,
1549    };
1550    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1551  }
1552  {
1553    const int char_string[] = {
1554      kOpPrefix, (12 << 8) + 8,  // 'store'.
1555      kOpPrefix, ots::kEndChar,
1556    };
1557    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1558  }
1559  {
1560    const int char_string[] = {
1561      kOpPrefix, (12 << 8) + 13,  // 'load'.
1562      kOpPrefix, ots::kEndChar,
1563    };
1564    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1565  }
1566}
1567
1568TEST(ValidateTest, TestUnterminatedCharString) {
1569  // No endchar operator.
1570  {
1571    const int char_string[] = {
1572      123,
1573    };
1574    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1575  }
1576  {
1577    const int char_string[] = {
1578      123, 456,
1579    };
1580    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1581  }
1582  {
1583    const int char_string[] = {
1584      123, 456, kOpPrefix, ots::kReturn,
1585    };
1586    EXPECT_FALSE(ValidateCharStrings(char_string, ARRAYSIZE(char_string)));
1587  }
1588}
1589