1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright © 2011  Google, Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci *  This is part of HarfBuzz, a text shaping library.
5cb93a386Sopenharmony_ci *
6cb93a386Sopenharmony_ci * Permission is hereby granted, without written agreement and without
7cb93a386Sopenharmony_ci * license or royalty fees, to use, copy, modify, and distribute this
8cb93a386Sopenharmony_ci * software and its documentation for any purpose, provided that the
9cb93a386Sopenharmony_ci * above copyright notice and the following two paragraphs appear in
10cb93a386Sopenharmony_ci * all copies of this software.
11cb93a386Sopenharmony_ci *
12cb93a386Sopenharmony_ci * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13cb93a386Sopenharmony_ci * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14cb93a386Sopenharmony_ci * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15cb93a386Sopenharmony_ci * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16cb93a386Sopenharmony_ci * DAMAGE.
17cb93a386Sopenharmony_ci *
18cb93a386Sopenharmony_ci * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19cb93a386Sopenharmony_ci * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20cb93a386Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21cb93a386Sopenharmony_ci * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22cb93a386Sopenharmony_ci * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23cb93a386Sopenharmony_ci *
24cb93a386Sopenharmony_ci * Google Author(s): Behdad Esfahbod
25cb93a386Sopenharmony_ci */
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ci#include "hb-test.h"
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci/* Unit tests for hb-buffer.h */
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_cistatic const char utf8[10] = "ab\360\240\200\200defg";
33cb93a386Sopenharmony_cistatic const uint16_t utf16[8] = {'a', 'b', 0xD840, 0xDC00, 'd', 'e', 'f', 'g'};
34cb93a386Sopenharmony_cistatic const uint32_t utf32[7] = {'a', 'b', 0x20000, 'd', 'e', 'f', 'g'};
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_citypedef enum {
38cb93a386Sopenharmony_ci  BUFFER_EMPTY,
39cb93a386Sopenharmony_ci  BUFFER_ONE_BY_ONE,
40cb93a386Sopenharmony_ci  BUFFER_UTF32,
41cb93a386Sopenharmony_ci  BUFFER_UTF16,
42cb93a386Sopenharmony_ci  BUFFER_UTF8,
43cb93a386Sopenharmony_ci  BUFFER_NUM_TYPES,
44cb93a386Sopenharmony_ci} buffer_type_t;
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_cistatic const char *buffer_names[] = {
47cb93a386Sopenharmony_ci  "empty",
48cb93a386Sopenharmony_ci  "one-by-one",
49cb93a386Sopenharmony_ci  "utf32",
50cb93a386Sopenharmony_ci  "utf16",
51cb93a386Sopenharmony_ci  "utf8"
52cb93a386Sopenharmony_ci};
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_citypedef struct
55cb93a386Sopenharmony_ci{
56cb93a386Sopenharmony_ci  hb_buffer_t *buffer;
57cb93a386Sopenharmony_ci} fixture_t;
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_cistatic void
60cb93a386Sopenharmony_cifixture_init (fixture_t *fixture, gconstpointer user_data)
61cb93a386Sopenharmony_ci{
62cb93a386Sopenharmony_ci  hb_buffer_t *b;
63cb93a386Sopenharmony_ci  unsigned int i;
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci  b = fixture->buffer = hb_buffer_create ();
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci  switch (GPOINTER_TO_INT (user_data))
68cb93a386Sopenharmony_ci  {
69cb93a386Sopenharmony_ci    case BUFFER_EMPTY:
70cb93a386Sopenharmony_ci      break;
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ci    case BUFFER_ONE_BY_ONE:
73cb93a386Sopenharmony_ci      for (i = 1; i < G_N_ELEMENTS (utf32) - 1; i++)
74cb93a386Sopenharmony_ci      hb_buffer_add (b, utf32[i], i);
75cb93a386Sopenharmony_ci      break;
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci    case BUFFER_UTF32:
78cb93a386Sopenharmony_ci      hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2);
79cb93a386Sopenharmony_ci      break;
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    case BUFFER_UTF16:
82cb93a386Sopenharmony_ci      hb_buffer_add_utf16 (b, utf16, G_N_ELEMENTS (utf16), 1, G_N_ELEMENTS (utf16) - 2);
83cb93a386Sopenharmony_ci      break;
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    case BUFFER_UTF8:
86cb93a386Sopenharmony_ci      hb_buffer_add_utf8  (b, utf8,  G_N_ELEMENTS (utf8),  1, G_N_ELEMENTS (utf8)  - 2);
87cb93a386Sopenharmony_ci      break;
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci    default:
90cb93a386Sopenharmony_ci      g_assert_not_reached ();
91cb93a386Sopenharmony_ci  }
92cb93a386Sopenharmony_ci}
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_cistatic void
95cb93a386Sopenharmony_cifixture_finish (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
96cb93a386Sopenharmony_ci{
97cb93a386Sopenharmony_ci  hb_buffer_destroy (fixture->buffer);
98cb93a386Sopenharmony_ci}
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_cistatic void
102cb93a386Sopenharmony_citest_buffer_properties (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
103cb93a386Sopenharmony_ci{
104cb93a386Sopenharmony_ci  hb_buffer_t *b = fixture->buffer;
105cb93a386Sopenharmony_ci  hb_unicode_funcs_t *ufuncs;
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ci  /* test default properties */
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ());
110cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
111cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
112cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_language (b) == NULL);
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ci  /* test property changes are retained */
116cb93a386Sopenharmony_ci  ufuncs = hb_unicode_funcs_create (NULL);
117cb93a386Sopenharmony_ci  hb_buffer_set_unicode_funcs (b, ufuncs);
118cb93a386Sopenharmony_ci  hb_unicode_funcs_destroy (ufuncs);
119cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs);
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci  hb_buffer_set_direction (b, HB_DIRECTION_RTL);
122cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL);
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci  hb_buffer_set_script (b, HB_SCRIPT_ARABIC);
125cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC);
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci  hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
128cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ci  hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
131cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci  hb_buffer_set_replacement_codepoint (b, (unsigned int) -1);
134cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_replacement_codepoint (b) == (unsigned int) -1);
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci  /* test clear_contents clears all these properties: */
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci  hb_buffer_clear_contents (b);
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs);
142cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
143cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
144cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_language (b) == NULL);
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci  /* but not these: */
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_flags (b) != HB_BUFFER_FLAGS_DEFAULT);
149cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_replacement_codepoint (b) != HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
150cb93a386Sopenharmony_ci
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci  /* test reset clears all properties */
153cb93a386Sopenharmony_ci
154cb93a386Sopenharmony_ci  hb_buffer_set_direction (b, HB_DIRECTION_RTL);
155cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL);
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci  hb_buffer_set_script (b, HB_SCRIPT_ARABIC);
158cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC);
159cb93a386Sopenharmony_ci
160cb93a386Sopenharmony_ci  hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
161cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci  hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
164cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci  hb_buffer_set_replacement_codepoint (b, (unsigned int) -1);
167cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_replacement_codepoint (b) == (unsigned int) -1);
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci  hb_buffer_reset (b);
170cb93a386Sopenharmony_ci
171cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ());
172cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
173cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
174cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_language (b) == NULL);
175cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT);
176cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_replacement_codepoint (b) == HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
177cb93a386Sopenharmony_ci}
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_cistatic void
180cb93a386Sopenharmony_citest_buffer_contents (fixture_t *fixture, gconstpointer user_data)
181cb93a386Sopenharmony_ci{
182cb93a386Sopenharmony_ci  hb_buffer_t *b = fixture->buffer;
183cb93a386Sopenharmony_ci  unsigned int i, len, len2;
184cb93a386Sopenharmony_ci  buffer_type_t buffer_type = GPOINTER_TO_INT (user_data);
185cb93a386Sopenharmony_ci  hb_glyph_info_t *glyphs;
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ci  if (buffer_type == BUFFER_EMPTY) {
188cb93a386Sopenharmony_ci    g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
189cb93a386Sopenharmony_ci    return;
190cb93a386Sopenharmony_ci  }
191cb93a386Sopenharmony_ci
192cb93a386Sopenharmony_ci  len = hb_buffer_get_length (b);
193cb93a386Sopenharmony_ci  hb_buffer_get_glyph_infos (b, NULL); /* test NULL */
194cb93a386Sopenharmony_ci  glyphs = hb_buffer_get_glyph_infos (b, &len2);
195cb93a386Sopenharmony_ci  g_assert_cmpint (len, ==, len2);
196cb93a386Sopenharmony_ci  g_assert_cmpint (len, ==, 5);
197cb93a386Sopenharmony_ci
198cb93a386Sopenharmony_ci  for (i = 0; i < len; i++) {
199cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].mask,      ==, 0);
200cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].var1.u32,  ==, 0);
201cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].var2.u32,  ==, 0);
202cb93a386Sopenharmony_ci  }
203cb93a386Sopenharmony_ci
204cb93a386Sopenharmony_ci  for (i = 0; i < len; i++) {
205cb93a386Sopenharmony_ci    unsigned int cluster;
206cb93a386Sopenharmony_ci    cluster = 1+i;
207cb93a386Sopenharmony_ci    if (i >= 2) {
208cb93a386Sopenharmony_ci      if (buffer_type == BUFFER_UTF16)
209cb93a386Sopenharmony_ci	cluster++;
210cb93a386Sopenharmony_ci      else if (buffer_type == BUFFER_UTF8)
211cb93a386Sopenharmony_ci	cluster += 3;
212cb93a386Sopenharmony_ci    }
213cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
214cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].cluster,   ==, cluster);
215cb93a386Sopenharmony_ci  }
216cb93a386Sopenharmony_ci
217cb93a386Sopenharmony_ci  /* reverse, test, and reverse back */
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_ci  hb_buffer_reverse (b);
220cb93a386Sopenharmony_ci  for (i = 0; i < len; i++)
221cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci  hb_buffer_reverse (b);
224cb93a386Sopenharmony_ci  for (i = 0; i < len; i++)
225cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci  /* reverse_clusters works same as reverse for now since each codepoint is
228cb93a386Sopenharmony_ci   * in its own cluster */
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_ci  hb_buffer_reverse_clusters (b);
231cb93a386Sopenharmony_ci  for (i = 0; i < len; i++)
232cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
233cb93a386Sopenharmony_ci
234cb93a386Sopenharmony_ci  hb_buffer_reverse_clusters (b);
235cb93a386Sopenharmony_ci  for (i = 0; i < len; i++)
236cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
237cb93a386Sopenharmony_ci
238cb93a386Sopenharmony_ci  /* now form a cluster and test again */
239cb93a386Sopenharmony_ci  glyphs[2].cluster = glyphs[1].cluster;
240cb93a386Sopenharmony_ci
241cb93a386Sopenharmony_ci  /* reverse, test, and reverse back */
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ci  hb_buffer_reverse (b);
244cb93a386Sopenharmony_ci  for (i = 0; i < len; i++)
245cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
246cb93a386Sopenharmony_ci
247cb93a386Sopenharmony_ci  hb_buffer_reverse (b);
248cb93a386Sopenharmony_ci  for (i = 0; i < len; i++)
249cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
250cb93a386Sopenharmony_ci
251cb93a386Sopenharmony_ci  /* reverse_clusters twice still should return the original string,
252cb93a386Sopenharmony_ci   * but when applied once, the 1-2 cluster should be retained. */
253cb93a386Sopenharmony_ci
254cb93a386Sopenharmony_ci  hb_buffer_reverse_clusters (b);
255cb93a386Sopenharmony_ci  for (i = 0; i < len; i++) {
256cb93a386Sopenharmony_ci    unsigned int j = len-1-i;
257cb93a386Sopenharmony_ci    if (j == 1)
258cb93a386Sopenharmony_ci      j = 2;
259cb93a386Sopenharmony_ci    else if (j == 2)
260cb93a386Sopenharmony_ci      j = 1;
261cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+j]);
262cb93a386Sopenharmony_ci  }
263cb93a386Sopenharmony_ci
264cb93a386Sopenharmony_ci  hb_buffer_reverse_clusters (b);
265cb93a386Sopenharmony_ci  for (i = 0; i < len; i++)
266cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
267cb93a386Sopenharmony_ci
268cb93a386Sopenharmony_ci
269cb93a386Sopenharmony_ci  /* test setting length */
270cb93a386Sopenharmony_ci
271cb93a386Sopenharmony_ci  /* enlarge */
272cb93a386Sopenharmony_ci  g_assert (hb_buffer_set_length (b, 10));
273cb93a386Sopenharmony_ci  glyphs = hb_buffer_get_glyph_infos (b, NULL);
274cb93a386Sopenharmony_ci  g_assert_cmpint (hb_buffer_get_length (b), ==, 10);
275cb93a386Sopenharmony_ci  for (i = 0; i < 5; i++)
276cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
277cb93a386Sopenharmony_ci  for (i = 5; i < 10; i++)
278cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, 0);
279cb93a386Sopenharmony_ci  /* shrink */
280cb93a386Sopenharmony_ci  g_assert (hb_buffer_set_length (b, 3));
281cb93a386Sopenharmony_ci  glyphs = hb_buffer_get_glyph_infos (b, NULL);
282cb93a386Sopenharmony_ci  g_assert_cmpint (hb_buffer_get_length (b), ==, 3);
283cb93a386Sopenharmony_ci  for (i = 0; i < 3; i++)
284cb93a386Sopenharmony_ci    g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
285cb93a386Sopenharmony_ci
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ci  g_assert (hb_buffer_allocation_successful (b));
288cb93a386Sopenharmony_ci
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci  /* test reset clears content */
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_ci  hb_buffer_reset (b);
293cb93a386Sopenharmony_ci  g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
294cb93a386Sopenharmony_ci}
295cb93a386Sopenharmony_ci
296cb93a386Sopenharmony_cistatic void
297cb93a386Sopenharmony_citest_buffer_positions (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
298cb93a386Sopenharmony_ci{
299cb93a386Sopenharmony_ci  hb_buffer_t *b = fixture->buffer;
300cb93a386Sopenharmony_ci  unsigned int i, len, len2;
301cb93a386Sopenharmony_ci  hb_glyph_position_t *positions;
302cb93a386Sopenharmony_ci
303cb93a386Sopenharmony_ci  /* Without shaping, positions should all be zero */
304cb93a386Sopenharmony_ci  len = hb_buffer_get_length (b);
305cb93a386Sopenharmony_ci  hb_buffer_get_glyph_positions (b, NULL); /* test NULL */
306cb93a386Sopenharmony_ci  positions = hb_buffer_get_glyph_positions (b, &len2);
307cb93a386Sopenharmony_ci  g_assert_cmpint (len, ==, len2);
308cb93a386Sopenharmony_ci  for (i = 0; i < len; i++) {
309cb93a386Sopenharmony_ci    g_assert_cmpint (0, ==, positions[i].x_advance);
310cb93a386Sopenharmony_ci    g_assert_cmpint (0, ==, positions[i].y_advance);
311cb93a386Sopenharmony_ci    g_assert_cmpint (0, ==, positions[i].x_offset);
312cb93a386Sopenharmony_ci    g_assert_cmpint (0, ==, positions[i].y_offset);
313cb93a386Sopenharmony_ci    g_assert_cmpint (0, ==, positions[i].var.i32);
314cb93a386Sopenharmony_ci  }
315cb93a386Sopenharmony_ci
316cb93a386Sopenharmony_ci  /* test reset clears content */
317cb93a386Sopenharmony_ci  hb_buffer_reset (b);
318cb93a386Sopenharmony_ci  g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
319cb93a386Sopenharmony_ci}
320cb93a386Sopenharmony_ci
321cb93a386Sopenharmony_cistatic void
322cb93a386Sopenharmony_citest_buffer_allocation (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
323cb93a386Sopenharmony_ci{
324cb93a386Sopenharmony_ci  hb_buffer_t *b = fixture->buffer;
325cb93a386Sopenharmony_ci
326cb93a386Sopenharmony_ci  g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ci  g_assert (hb_buffer_pre_allocate (b, 100));
329cb93a386Sopenharmony_ci  g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
330cb93a386Sopenharmony_ci  g_assert (hb_buffer_allocation_successful (b));
331cb93a386Sopenharmony_ci
332cb93a386Sopenharmony_ci  /* lets try a huge allocation, make sure it fails */
333cb93a386Sopenharmony_ci  g_assert (!hb_buffer_pre_allocate (b, (unsigned int) -1));
334cb93a386Sopenharmony_ci  g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
335cb93a386Sopenharmony_ci  g_assert (!hb_buffer_allocation_successful (b));
336cb93a386Sopenharmony_ci
337cb93a386Sopenharmony_ci  /* small one again */
338cb93a386Sopenharmony_ci  g_assert (hb_buffer_pre_allocate (b, 50));
339cb93a386Sopenharmony_ci  g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
340cb93a386Sopenharmony_ci  g_assert (!hb_buffer_allocation_successful (b));
341cb93a386Sopenharmony_ci
342cb93a386Sopenharmony_ci  hb_buffer_reset (b);
343cb93a386Sopenharmony_ci  g_assert (hb_buffer_allocation_successful (b));
344cb93a386Sopenharmony_ci
345cb93a386Sopenharmony_ci  /* all allocation and size  */
346cb93a386Sopenharmony_ci  g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 + 1));
347cb93a386Sopenharmony_ci  g_assert (!hb_buffer_allocation_successful (b));
348cb93a386Sopenharmony_ci
349cb93a386Sopenharmony_ci  hb_buffer_reset (b);
350cb93a386Sopenharmony_ci  g_assert (hb_buffer_allocation_successful (b));
351cb93a386Sopenharmony_ci
352cb93a386Sopenharmony_ci  /* technically, this one can actually pass on 64bit machines, but
353cb93a386Sopenharmony_ci   * I'm doubtful that any malloc allows 4GB allocations at a time.
354cb93a386Sopenharmony_ci   * But let's only enable it on a 32-bit machine. */
355cb93a386Sopenharmony_ci  if (sizeof (long) == 4) {
356cb93a386Sopenharmony_ci    g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 - 1));
357cb93a386Sopenharmony_ci    g_assert (!hb_buffer_allocation_successful (b));
358cb93a386Sopenharmony_ci  }
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci  hb_buffer_reset (b);
361cb93a386Sopenharmony_ci  g_assert (hb_buffer_allocation_successful (b));
362cb93a386Sopenharmony_ci}
363cb93a386Sopenharmony_ci
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_citypedef struct {
366cb93a386Sopenharmony_ci  const char utf8[8];
367cb93a386Sopenharmony_ci  const uint32_t codepoints[8];
368cb93a386Sopenharmony_ci} utf8_conversion_test_t;
369cb93a386Sopenharmony_ci
370cb93a386Sopenharmony_ci/* note: we skip the first and last byte when adding to buffer */
371cb93a386Sopenharmony_cistatic const utf8_conversion_test_t utf8_conversion_tests[] = {
372cb93a386Sopenharmony_ci  {"a\303\207", {(hb_codepoint_t) -1}},
373cb93a386Sopenharmony_ci  {"a\303\207b", {0xC7}},
374cb93a386Sopenharmony_ci  {"ab\303cd", {'b', (hb_codepoint_t) -1, 'c'}},
375cb93a386Sopenharmony_ci  {"ab\303\302\301cd", {'b', (hb_codepoint_t) -1, (hb_codepoint_t) -1, (hb_codepoint_t) -1, 'c'}}
376cb93a386Sopenharmony_ci};
377cb93a386Sopenharmony_ci
378cb93a386Sopenharmony_cistatic void
379cb93a386Sopenharmony_citest_buffer_utf8_conversion (void)
380cb93a386Sopenharmony_ci{
381cb93a386Sopenharmony_ci  hb_buffer_t *b;
382cb93a386Sopenharmony_ci  unsigned int chars, i, j, len;
383cb93a386Sopenharmony_ci
384cb93a386Sopenharmony_ci  b = hb_buffer_create ();
385cb93a386Sopenharmony_ci  hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1);
386cb93a386Sopenharmony_ci
387cb93a386Sopenharmony_ci  for (i = 0; i < G_N_ELEMENTS (utf8_conversion_tests); i++)
388cb93a386Sopenharmony_ci  {
389cb93a386Sopenharmony_ci    unsigned int bytes;
390cb93a386Sopenharmony_ci    hb_glyph_info_t *glyphs;
391cb93a386Sopenharmony_ci    const utf8_conversion_test_t *test = &utf8_conversion_tests[i];
392cb93a386Sopenharmony_ci    char *escaped;
393cb93a386Sopenharmony_ci
394cb93a386Sopenharmony_ci    escaped = g_strescape (test->utf8, NULL);
395cb93a386Sopenharmony_ci    g_test_message ("UTF-8 test #%d: %s", i, escaped);
396cb93a386Sopenharmony_ci    g_free (escaped);
397cb93a386Sopenharmony_ci
398cb93a386Sopenharmony_ci    bytes = strlen (test->utf8);
399cb93a386Sopenharmony_ci    for (chars = 0; test->codepoints[chars]; chars++)
400cb93a386Sopenharmony_ci      ;
401cb93a386Sopenharmony_ci
402cb93a386Sopenharmony_ci    hb_buffer_clear_contents (b);
403cb93a386Sopenharmony_ci    hb_buffer_add_utf8 (b, test->utf8, bytes,  1, bytes - 2);
404cb93a386Sopenharmony_ci
405cb93a386Sopenharmony_ci    glyphs = hb_buffer_get_glyph_infos (b, &len);
406cb93a386Sopenharmony_ci    g_assert_cmpint (len, ==, chars);
407cb93a386Sopenharmony_ci    for (j = 0; j < chars; j++)
408cb93a386Sopenharmony_ci      g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]);
409cb93a386Sopenharmony_ci  }
410cb93a386Sopenharmony_ci
411cb93a386Sopenharmony_ci  hb_buffer_destroy (b);
412cb93a386Sopenharmony_ci}
413cb93a386Sopenharmony_ci
414cb93a386Sopenharmony_ci
415cb93a386Sopenharmony_ci
416cb93a386Sopenharmony_ci/* Following test table is adapted from glib/glib/tests/utf8-validate.c
417cb93a386Sopenharmony_ci * with relicensing permission from Matthias Clasen. */
418cb93a386Sopenharmony_ci
419cb93a386Sopenharmony_citypedef struct {
420cb93a386Sopenharmony_ci  const char *utf8;
421cb93a386Sopenharmony_ci  int max_len;
422cb93a386Sopenharmony_ci  unsigned int offset;
423cb93a386Sopenharmony_ci  gboolean valid;
424cb93a386Sopenharmony_ci} utf8_validity_test_t;
425cb93a386Sopenharmony_ci
426cb93a386Sopenharmony_cistatic const utf8_validity_test_t utf8_validity_tests[] = {
427cb93a386Sopenharmony_ci  /* some tests to check max_len handling */
428cb93a386Sopenharmony_ci  /* length 1 */
429cb93a386Sopenharmony_ci  { "abcde", -1, 5, TRUE },
430cb93a386Sopenharmony_ci  { "abcde", 3, 3, TRUE },
431cb93a386Sopenharmony_ci  { "abcde", 5, 5, TRUE },
432cb93a386Sopenharmony_ci  /* length 2 */
433cb93a386Sopenharmony_ci  { "\xc2\xa9\xc2\xa9\xc2\xa9", -1, 6, TRUE },
434cb93a386Sopenharmony_ci  { "\xc2\xa9\xc2\xa9\xc2\xa9",  1, 0, FALSE },
435cb93a386Sopenharmony_ci  { "\xc2\xa9\xc2\xa9\xc2\xa9",  2, 2, TRUE },
436cb93a386Sopenharmony_ci  { "\xc2\xa9\xc2\xa9\xc2\xa9",  3, 2, FALSE },
437cb93a386Sopenharmony_ci  { "\xc2\xa9\xc2\xa9\xc2\xa9",  4, 4, TRUE },
438cb93a386Sopenharmony_ci  { "\xc2\xa9\xc2\xa9\xc2\xa9",  5, 4, FALSE },
439cb93a386Sopenharmony_ci  { "\xc2\xa9\xc2\xa9\xc2\xa9",  6, 6, TRUE },
440cb93a386Sopenharmony_ci  /* length 3 */
441cb93a386Sopenharmony_ci  { "\xe2\x89\xa0\xe2\x89\xa0", -1, 6, TRUE },
442cb93a386Sopenharmony_ci  { "\xe2\x89\xa0\xe2\x89\xa0",  1, 0, FALSE },
443cb93a386Sopenharmony_ci  { "\xe2\x89\xa0\xe2\x89\xa0",  2, 0, FALSE },
444cb93a386Sopenharmony_ci  { "\xe2\x89\xa0\xe2\x89\xa0",  3, 3, TRUE },
445cb93a386Sopenharmony_ci  { "\xe2\x89\xa0\xe2\x89\xa0",  4, 3, FALSE },
446cb93a386Sopenharmony_ci  { "\xe2\x89\xa0\xe2\x89\xa0",  5, 3, FALSE },
447cb93a386Sopenharmony_ci  { "\xe2\x89\xa0\xe2\x89\xa0",  6, 6, TRUE },
448cb93a386Sopenharmony_ci
449cb93a386Sopenharmony_ci  /* examples from https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt */
450cb93a386Sopenharmony_ci  /* greek 'kosme' */
451cb93a386Sopenharmony_ci  { "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5", -1, 11, TRUE },
452cb93a386Sopenharmony_ci  /* first sequence of each length */
453cb93a386Sopenharmony_ci  { "\x00", -1, 0, TRUE },
454cb93a386Sopenharmony_ci  { "\xc2\x80", -1, 2, TRUE },
455cb93a386Sopenharmony_ci  { "\xe0\xa0\x80", -1, 3, TRUE },
456cb93a386Sopenharmony_ci  { "\xf0\x90\x80\x80", -1, 4, TRUE },
457cb93a386Sopenharmony_ci  { "\xf8\x88\x80\x80\x80", -1, 0, FALSE },
458cb93a386Sopenharmony_ci  { "\xfc\x84\x80\x80\x80\x80", -1, 0, FALSE },
459cb93a386Sopenharmony_ci  /* last sequence of each length */
460cb93a386Sopenharmony_ci  { "\x7f", -1, 1, TRUE },
461cb93a386Sopenharmony_ci  { "\xdf\xbf", -1, 2, TRUE },
462cb93a386Sopenharmony_ci  { "\xef\xbf\xbf", -1, 0, TRUE },
463cb93a386Sopenharmony_ci  { "\xf4\x8f\xbf\xbf", -1, 0, TRUE },
464cb93a386Sopenharmony_ci  { "\xf4\x90\xbf\xbf", -1, 0, FALSE },
465cb93a386Sopenharmony_ci  { "\xf7\xbf\xbf\xbf", -1, 0, FALSE },
466cb93a386Sopenharmony_ci  { "\xfb\xbf\xbf\xbf\xbf", -1, 0, FALSE },
467cb93a386Sopenharmony_ci  { "\xfd\xbf\xbf\xbf\xbf\xbf", -1, 0, FALSE },
468cb93a386Sopenharmony_ci  /* other boundary conditions */
469cb93a386Sopenharmony_ci  { "\xed\x9f\xbf", -1, 3, TRUE },
470cb93a386Sopenharmony_ci  { "\xed\xa0\x80", -1, 0, FALSE },
471cb93a386Sopenharmony_ci  { "\xed\xbf\xbf", -1, 0, FALSE },
472cb93a386Sopenharmony_ci  { "\xee\x80\x80", -1, 3, TRUE },
473cb93a386Sopenharmony_ci  { "\xef\xbf\xbd", -1, 3, TRUE },
474cb93a386Sopenharmony_ci  { "\xf4\x8f\xbf\xbf", -1, 0, TRUE },
475cb93a386Sopenharmony_ci  /* malformed sequences */
476cb93a386Sopenharmony_ci  /* continuation bytes */
477cb93a386Sopenharmony_ci  { "\x80", -1, 0, FALSE },
478cb93a386Sopenharmony_ci  { "\xbf", -1, 0, FALSE },
479cb93a386Sopenharmony_ci  { "\x80\xbf", -1, 0, FALSE },
480cb93a386Sopenharmony_ci  { "\x80\xbf\x80", -1, 0, FALSE },
481cb93a386Sopenharmony_ci  { "\x80\xbf\x80\xbf", -1, 0, FALSE },
482cb93a386Sopenharmony_ci  { "\x80\xbf\x80\xbf\x80", -1, 0, FALSE },
483cb93a386Sopenharmony_ci  { "\x80\xbf\x80\xbf\x80\xbf", -1, 0, FALSE },
484cb93a386Sopenharmony_ci  { "\x80\xbf\x80\xbf\x80\xbf\x80", -1, 0, FALSE },
485cb93a386Sopenharmony_ci
486cb93a386Sopenharmony_ci  /* all possible continuation byte */
487cb93a386Sopenharmony_ci  { "\x80", -1, 0, FALSE },
488cb93a386Sopenharmony_ci  { "\x81", -1, 0, FALSE },
489cb93a386Sopenharmony_ci  { "\x82", -1, 0, FALSE },
490cb93a386Sopenharmony_ci  { "\x83", -1, 0, FALSE },
491cb93a386Sopenharmony_ci  { "\x84", -1, 0, FALSE },
492cb93a386Sopenharmony_ci  { "\x85", -1, 0, FALSE },
493cb93a386Sopenharmony_ci  { "\x86", -1, 0, FALSE },
494cb93a386Sopenharmony_ci  { "\x87", -1, 0, FALSE },
495cb93a386Sopenharmony_ci  { "\x88", -1, 0, FALSE },
496cb93a386Sopenharmony_ci  { "\x89", -1, 0, FALSE },
497cb93a386Sopenharmony_ci  { "\x8a", -1, 0, FALSE },
498cb93a386Sopenharmony_ci  { "\x8b", -1, 0, FALSE },
499cb93a386Sopenharmony_ci  { "\x8c", -1, 0, FALSE },
500cb93a386Sopenharmony_ci  { "\x8d", -1, 0, FALSE },
501cb93a386Sopenharmony_ci  { "\x8e", -1, 0, FALSE },
502cb93a386Sopenharmony_ci  { "\x8f", -1, 0, FALSE },
503cb93a386Sopenharmony_ci  { "\x90", -1, 0, FALSE },
504cb93a386Sopenharmony_ci  { "\x91", -1, 0, FALSE },
505cb93a386Sopenharmony_ci  { "\x92", -1, 0, FALSE },
506cb93a386Sopenharmony_ci  { "\x93", -1, 0, FALSE },
507cb93a386Sopenharmony_ci  { "\x94", -1, 0, FALSE },
508cb93a386Sopenharmony_ci  { "\x95", -1, 0, FALSE },
509cb93a386Sopenharmony_ci  { "\x96", -1, 0, FALSE },
510cb93a386Sopenharmony_ci  { "\x97", -1, 0, FALSE },
511cb93a386Sopenharmony_ci  { "\x98", -1, 0, FALSE },
512cb93a386Sopenharmony_ci  { "\x99", -1, 0, FALSE },
513cb93a386Sopenharmony_ci  { "\x9a", -1, 0, FALSE },
514cb93a386Sopenharmony_ci  { "\x9b", -1, 0, FALSE },
515cb93a386Sopenharmony_ci  { "\x9c", -1, 0, FALSE },
516cb93a386Sopenharmony_ci  { "\x9d", -1, 0, FALSE },
517cb93a386Sopenharmony_ci  { "\x9e", -1, 0, FALSE },
518cb93a386Sopenharmony_ci  { "\x9f", -1, 0, FALSE },
519cb93a386Sopenharmony_ci  { "\xa0", -1, 0, FALSE },
520cb93a386Sopenharmony_ci  { "\xa1", -1, 0, FALSE },
521cb93a386Sopenharmony_ci  { "\xa2", -1, 0, FALSE },
522cb93a386Sopenharmony_ci  { "\xa3", -1, 0, FALSE },
523cb93a386Sopenharmony_ci  { "\xa4", -1, 0, FALSE },
524cb93a386Sopenharmony_ci  { "\xa5", -1, 0, FALSE },
525cb93a386Sopenharmony_ci  { "\xa6", -1, 0, FALSE },
526cb93a386Sopenharmony_ci  { "\xa7", -1, 0, FALSE },
527cb93a386Sopenharmony_ci  { "\xa8", -1, 0, FALSE },
528cb93a386Sopenharmony_ci  { "\xa9", -1, 0, FALSE },
529cb93a386Sopenharmony_ci  { "\xaa", -1, 0, FALSE },
530cb93a386Sopenharmony_ci  { "\xab", -1, 0, FALSE },
531cb93a386Sopenharmony_ci  { "\xac", -1, 0, FALSE },
532cb93a386Sopenharmony_ci  { "\xad", -1, 0, FALSE },
533cb93a386Sopenharmony_ci  { "\xae", -1, 0, FALSE },
534cb93a386Sopenharmony_ci  { "\xaf", -1, 0, FALSE },
535cb93a386Sopenharmony_ci  { "\xb0", -1, 0, FALSE },
536cb93a386Sopenharmony_ci  { "\xb1", -1, 0, FALSE },
537cb93a386Sopenharmony_ci  { "\xb2", -1, 0, FALSE },
538cb93a386Sopenharmony_ci  { "\xb3", -1, 0, FALSE },
539cb93a386Sopenharmony_ci  { "\xb4", -1, 0, FALSE },
540cb93a386Sopenharmony_ci  { "\xb5", -1, 0, FALSE },
541cb93a386Sopenharmony_ci  { "\xb6", -1, 0, FALSE },
542cb93a386Sopenharmony_ci  { "\xb7", -1, 0, FALSE },
543cb93a386Sopenharmony_ci  { "\xb8", -1, 0, FALSE },
544cb93a386Sopenharmony_ci  { "\xb9", -1, 0, FALSE },
545cb93a386Sopenharmony_ci  { "\xba", -1, 0, FALSE },
546cb93a386Sopenharmony_ci  { "\xbb", -1, 0, FALSE },
547cb93a386Sopenharmony_ci  { "\xbc", -1, 0, FALSE },
548cb93a386Sopenharmony_ci  { "\xbd", -1, 0, FALSE },
549cb93a386Sopenharmony_ci  { "\xbe", -1, 0, FALSE },
550cb93a386Sopenharmony_ci  { "\xbf", -1, 0, FALSE },
551cb93a386Sopenharmony_ci  /* lone start characters */
552cb93a386Sopenharmony_ci  { "\xc0\x20", -1, 0, FALSE },
553cb93a386Sopenharmony_ci  { "\xc1\x20", -1, 0, FALSE },
554cb93a386Sopenharmony_ci  { "\xc2\x20", -1, 0, FALSE },
555cb93a386Sopenharmony_ci  { "\xc3\x20", -1, 0, FALSE },
556cb93a386Sopenharmony_ci  { "\xc4\x20", -1, 0, FALSE },
557cb93a386Sopenharmony_ci  { "\xc5\x20", -1, 0, FALSE },
558cb93a386Sopenharmony_ci  { "\xc6\x20", -1, 0, FALSE },
559cb93a386Sopenharmony_ci  { "\xc7\x20", -1, 0, FALSE },
560cb93a386Sopenharmony_ci  { "\xc8\x20", -1, 0, FALSE },
561cb93a386Sopenharmony_ci  { "\xc9\x20", -1, 0, FALSE },
562cb93a386Sopenharmony_ci  { "\xca\x20", -1, 0, FALSE },
563cb93a386Sopenharmony_ci  { "\xcb\x20", -1, 0, FALSE },
564cb93a386Sopenharmony_ci  { "\xcc\x20", -1, 0, FALSE },
565cb93a386Sopenharmony_ci  { "\xcd\x20", -1, 0, FALSE },
566cb93a386Sopenharmony_ci  { "\xce\x20", -1, 0, FALSE },
567cb93a386Sopenharmony_ci  { "\xcf\x20", -1, 0, FALSE },
568cb93a386Sopenharmony_ci  { "\xd0\x20", -1, 0, FALSE },
569cb93a386Sopenharmony_ci  { "\xd1\x20", -1, 0, FALSE },
570cb93a386Sopenharmony_ci  { "\xd2\x20", -1, 0, FALSE },
571cb93a386Sopenharmony_ci  { "\xd3\x20", -1, 0, FALSE },
572cb93a386Sopenharmony_ci  { "\xd4\x20", -1, 0, FALSE },
573cb93a386Sopenharmony_ci  { "\xd5\x20", -1, 0, FALSE },
574cb93a386Sopenharmony_ci  { "\xd6\x20", -1, 0, FALSE },
575cb93a386Sopenharmony_ci  { "\xd7\x20", -1, 0, FALSE },
576cb93a386Sopenharmony_ci  { "\xd8\x20", -1, 0, FALSE },
577cb93a386Sopenharmony_ci  { "\xd9\x20", -1, 0, FALSE },
578cb93a386Sopenharmony_ci  { "\xda\x20", -1, 0, FALSE },
579cb93a386Sopenharmony_ci  { "\xdb\x20", -1, 0, FALSE },
580cb93a386Sopenharmony_ci  { "\xdc\x20", -1, 0, FALSE },
581cb93a386Sopenharmony_ci  { "\xdd\x20", -1, 0, FALSE },
582cb93a386Sopenharmony_ci  { "\xde\x20", -1, 0, FALSE },
583cb93a386Sopenharmony_ci  { "\xdf\x20", -1, 0, FALSE },
584cb93a386Sopenharmony_ci  { "\xe0\x20", -1, 0, FALSE },
585cb93a386Sopenharmony_ci  { "\xe1\x20", -1, 0, FALSE },
586cb93a386Sopenharmony_ci  { "\xe2\x20", -1, 0, FALSE },
587cb93a386Sopenharmony_ci  { "\xe3\x20", -1, 0, FALSE },
588cb93a386Sopenharmony_ci  { "\xe4\x20", -1, 0, FALSE },
589cb93a386Sopenharmony_ci  { "\xe5\x20", -1, 0, FALSE },
590cb93a386Sopenharmony_ci  { "\xe6\x20", -1, 0, FALSE },
591cb93a386Sopenharmony_ci  { "\xe7\x20", -1, 0, FALSE },
592cb93a386Sopenharmony_ci  { "\xe8\x20", -1, 0, FALSE },
593cb93a386Sopenharmony_ci  { "\xe9\x20", -1, 0, FALSE },
594cb93a386Sopenharmony_ci  { "\xea\x20", -1, 0, FALSE },
595cb93a386Sopenharmony_ci  { "\xeb\x20", -1, 0, FALSE },
596cb93a386Sopenharmony_ci  { "\xec\x20", -1, 0, FALSE },
597cb93a386Sopenharmony_ci  { "\xed\x20", -1, 0, FALSE },
598cb93a386Sopenharmony_ci  { "\xee\x20", -1, 0, FALSE },
599cb93a386Sopenharmony_ci  { "\xef\x20", -1, 0, FALSE },
600cb93a386Sopenharmony_ci  { "\xf0\x20", -1, 0, FALSE },
601cb93a386Sopenharmony_ci  { "\xf1\x20", -1, 0, FALSE },
602cb93a386Sopenharmony_ci  { "\xf2\x20", -1, 0, FALSE },
603cb93a386Sopenharmony_ci  { "\xf3\x20", -1, 0, FALSE },
604cb93a386Sopenharmony_ci  { "\xf4\x20", -1, 0, FALSE },
605cb93a386Sopenharmony_ci  { "\xf5\x20", -1, 0, FALSE },
606cb93a386Sopenharmony_ci  { "\xf6\x20", -1, 0, FALSE },
607cb93a386Sopenharmony_ci  { "\xf7\x20", -1, 0, FALSE },
608cb93a386Sopenharmony_ci  { "\xf8\x20", -1, 0, FALSE },
609cb93a386Sopenharmony_ci  { "\xf9\x20", -1, 0, FALSE },
610cb93a386Sopenharmony_ci  { "\xfa\x20", -1, 0, FALSE },
611cb93a386Sopenharmony_ci  { "\xfb\x20", -1, 0, FALSE },
612cb93a386Sopenharmony_ci  { "\xfc\x20", -1, 0, FALSE },
613cb93a386Sopenharmony_ci  { "\xfd\x20", -1, 0, FALSE },
614cb93a386Sopenharmony_ci  /* missing continuation bytes */
615cb93a386Sopenharmony_ci  { "\x20\xc0", -1, 1, FALSE },
616cb93a386Sopenharmony_ci  { "\x20\xe0\x80", -1, 1, FALSE },
617cb93a386Sopenharmony_ci  { "\x20\xf0\x80\x80", -1, 1, FALSE },
618cb93a386Sopenharmony_ci  { "\x20\xf8\x80\x80\x80", -1, 1, FALSE },
619cb93a386Sopenharmony_ci  { "\x20\xfc\x80\x80\x80\x80", -1, 1, FALSE },
620cb93a386Sopenharmony_ci  { "\x20\xdf", -1, 1, FALSE },
621cb93a386Sopenharmony_ci  { "\x20\xef\xbf", -1, 1, FALSE },
622cb93a386Sopenharmony_ci  { "\x20\xf7\xbf\xbf", -1, 1, FALSE },
623cb93a386Sopenharmony_ci  { "\x20\xfb\xbf\xbf\xbf", -1, 1, FALSE },
624cb93a386Sopenharmony_ci  { "\x20\xfd\xbf\xbf\xbf\xbf", -1, 1, FALSE },
625cb93a386Sopenharmony_ci  /* impossible bytes */
626cb93a386Sopenharmony_ci  { "\x20\xfe\x20", -1, 1, FALSE },
627cb93a386Sopenharmony_ci  { "\x20\xff\x20", -1, 1, FALSE },
628cb93a386Sopenharmony_ci  /* overlong sequences */
629cb93a386Sopenharmony_ci  { "\x20\xc0\xaf\x20", -1, 1, FALSE },
630cb93a386Sopenharmony_ci  { "\x20\xe0\x80\xaf\x20", -1, 1, FALSE },
631cb93a386Sopenharmony_ci  { "\x20\xf0\x80\x80\xaf\x20", -1, 1, FALSE },
632cb93a386Sopenharmony_ci  { "\x20\xf8\x80\x80\x80\xaf\x20", -1, 1, FALSE },
633cb93a386Sopenharmony_ci  { "\x20\xfc\x80\x80\x80\x80\xaf\x20", -1, 1, FALSE },
634cb93a386Sopenharmony_ci  { "\x20\xc1\xbf\x20", -1, 1, FALSE },
635cb93a386Sopenharmony_ci  { "\x20\xe0\x9f\xbf\x20", -1, 1, FALSE },
636cb93a386Sopenharmony_ci  { "\x20\xf0\x8f\xbf\xbf\x20", -1, 1, FALSE },
637cb93a386Sopenharmony_ci  { "\x20\xf8\x87\xbf\xbf\xbf\x20", -1, 1, FALSE },
638cb93a386Sopenharmony_ci  { "\x20\xfc\x83\xbf\xbf\xbf\xbf\x20", -1, 1, FALSE },
639cb93a386Sopenharmony_ci  { "\x20\xc0\x80\x20", -1, 1, FALSE },
640cb93a386Sopenharmony_ci  { "\x20\xe0\x80\x80\x20", -1, 1, FALSE },
641cb93a386Sopenharmony_ci  { "\x20\xf0\x80\x80\x80\x20", -1, 1, FALSE },
642cb93a386Sopenharmony_ci  { "\x20\xf8\x80\x80\x80\x80\x20", -1, 1, FALSE },
643cb93a386Sopenharmony_ci  { "\x20\xfc\x80\x80\x80\x80\x80\x20", -1, 1, FALSE },
644cb93a386Sopenharmony_ci  /* illegal code positions */
645cb93a386Sopenharmony_ci  { "\x20\xed\xa0\x80\x20", -1, 1, FALSE },
646cb93a386Sopenharmony_ci  { "\x20\xed\xad\xbf\x20", -1, 1, FALSE },
647cb93a386Sopenharmony_ci  { "\x20\xed\xae\x80\x20", -1, 1, FALSE },
648cb93a386Sopenharmony_ci  { "\x20\xed\xaf\xbf\x20", -1, 1, FALSE },
649cb93a386Sopenharmony_ci  { "\x20\xed\xb0\x80\x20", -1, 1, FALSE },
650cb93a386Sopenharmony_ci  { "\x20\xed\xbe\x80\x20", -1, 1, FALSE },
651cb93a386Sopenharmony_ci  { "\x20\xed\xbf\xbf\x20", -1, 1, FALSE },
652cb93a386Sopenharmony_ci  { "\x20\xed\xa0\x80\xed\xb0\x80\x20", -1, 1, FALSE },
653cb93a386Sopenharmony_ci  { "\x20\xed\xa0\x80\xed\xbf\xbf\x20", -1, 1, FALSE },
654cb93a386Sopenharmony_ci  { "\x20\xed\xad\xbf\xed\xb0\x80\x20", -1, 1, FALSE },
655cb93a386Sopenharmony_ci  { "\x20\xed\xad\xbf\xed\xbf\xbf\x20", -1, 1, FALSE },
656cb93a386Sopenharmony_ci  { "\x20\xed\xae\x80\xed\xb0\x80\x20", -1, 1, FALSE },
657cb93a386Sopenharmony_ci  { "\x20\xed\xae\x80\xed\xbf\xbf\x20", -1, 1, FALSE },
658cb93a386Sopenharmony_ci  { "\x20\xed\xaf\xbf\xed\xb0\x80\x20", -1, 1, FALSE },
659cb93a386Sopenharmony_ci  { "\x20\xed\xaf\xbf\xed\xbf\xbf\x20", -1, 1, FALSE },
660cb93a386Sopenharmony_ci#if 0 /* We don't consider U+FFFE / U+FFFF and similar invalid. */
661cb93a386Sopenharmony_ci  { "\x20\xef\xbf\xbe\x20", -1, 1, FALSE },
662cb93a386Sopenharmony_ci  { "\x20\xef\xbf\xbf\x20", -1, 1, FALSE },
663cb93a386Sopenharmony_ci#endif
664cb93a386Sopenharmony_ci  { "", -1, 0, TRUE }
665cb93a386Sopenharmony_ci};
666cb93a386Sopenharmony_ci
667cb93a386Sopenharmony_cistatic void
668cb93a386Sopenharmony_citest_buffer_utf8_validity (void)
669cb93a386Sopenharmony_ci{
670cb93a386Sopenharmony_ci  hb_buffer_t *b;
671cb93a386Sopenharmony_ci  unsigned int i;
672cb93a386Sopenharmony_ci
673cb93a386Sopenharmony_ci  b = hb_buffer_create ();
674cb93a386Sopenharmony_ci  hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1);
675cb93a386Sopenharmony_ci
676cb93a386Sopenharmony_ci  for (i = 0; i < G_N_ELEMENTS (utf8_validity_tests); i++)
677cb93a386Sopenharmony_ci  {
678cb93a386Sopenharmony_ci    const utf8_validity_test_t *test = &utf8_validity_tests[i];
679cb93a386Sopenharmony_ci    unsigned int text_bytes, segment_bytes, j, len;
680cb93a386Sopenharmony_ci    hb_glyph_info_t *glyphs;
681cb93a386Sopenharmony_ci    char *escaped;
682cb93a386Sopenharmony_ci
683cb93a386Sopenharmony_ci    escaped = g_strescape (test->utf8, NULL);
684cb93a386Sopenharmony_ci    g_test_message ("UTF-8 test #%d: %s", i, escaped);
685cb93a386Sopenharmony_ci    g_free (escaped);
686cb93a386Sopenharmony_ci
687cb93a386Sopenharmony_ci    text_bytes = strlen (test->utf8);
688cb93a386Sopenharmony_ci    if (test->max_len == -1)
689cb93a386Sopenharmony_ci      segment_bytes = text_bytes;
690cb93a386Sopenharmony_ci    else
691cb93a386Sopenharmony_ci      segment_bytes = test->max_len;
692cb93a386Sopenharmony_ci
693cb93a386Sopenharmony_ci    hb_buffer_clear_contents (b);
694cb93a386Sopenharmony_ci    hb_buffer_add_utf8 (b, test->utf8, text_bytes,  0, segment_bytes);
695cb93a386Sopenharmony_ci
696cb93a386Sopenharmony_ci    glyphs = hb_buffer_get_glyph_infos (b, &len);
697cb93a386Sopenharmony_ci    for (j = 0; j < len; j++)
698cb93a386Sopenharmony_ci      if (glyphs[j].codepoint == (hb_codepoint_t) -1)
699cb93a386Sopenharmony_ci	break;
700cb93a386Sopenharmony_ci
701cb93a386Sopenharmony_ci    g_assert (test->valid ? j == len : j < len);
702cb93a386Sopenharmony_ci    if (!test->valid)
703cb93a386Sopenharmony_ci      g_assert (glyphs[j].cluster == test->offset);
704cb93a386Sopenharmony_ci  }
705cb93a386Sopenharmony_ci
706cb93a386Sopenharmony_ci  hb_buffer_destroy (b);
707cb93a386Sopenharmony_ci}
708cb93a386Sopenharmony_ci
709cb93a386Sopenharmony_ci
710cb93a386Sopenharmony_citypedef struct {
711cb93a386Sopenharmony_ci  const uint16_t utf16[8];
712cb93a386Sopenharmony_ci  const uint32_t codepoints[8];
713cb93a386Sopenharmony_ci} utf16_conversion_test_t;
714cb93a386Sopenharmony_ci
715cb93a386Sopenharmony_ci/* note: we skip the first and last item from utf16 when adding to buffer */
716cb93a386Sopenharmony_cistatic const utf16_conversion_test_t utf16_conversion_tests[] = {
717cb93a386Sopenharmony_ci  {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}},
718cb93a386Sopenharmony_ci  {{0x41, 0xD800, 0xDF02, 0x61}, {0x10302}},
719cb93a386Sopenharmony_ci  {{0x41, 0xD800, 0xDF02}, {(hb_codepoint_t) -1}},
720cb93a386Sopenharmony_ci  {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, (hb_codepoint_t) -1}},
721cb93a386Sopenharmony_ci  {{0x41, 0xD800, 0x61, 0xDF02}, {(hb_codepoint_t) -1, 0x61}},
722cb93a386Sopenharmony_ci  {{0x41, 0xDF00, 0x61}, {(hb_codepoint_t) -1}},
723cb93a386Sopenharmony_ci  {{0x41, 0x61}, {0}}
724cb93a386Sopenharmony_ci};
725cb93a386Sopenharmony_ci
726cb93a386Sopenharmony_cistatic void
727cb93a386Sopenharmony_citest_buffer_utf16_conversion (void)
728cb93a386Sopenharmony_ci{
729cb93a386Sopenharmony_ci  hb_buffer_t *b;
730cb93a386Sopenharmony_ci  unsigned int i;
731cb93a386Sopenharmony_ci
732cb93a386Sopenharmony_ci  b = hb_buffer_create ();
733cb93a386Sopenharmony_ci  hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1);
734cb93a386Sopenharmony_ci
735cb93a386Sopenharmony_ci  for (i = 0; i < G_N_ELEMENTS (utf16_conversion_tests); i++)
736cb93a386Sopenharmony_ci  {
737cb93a386Sopenharmony_ci    const utf16_conversion_test_t *test = &utf16_conversion_tests[i];
738cb93a386Sopenharmony_ci    unsigned int u_len, chars, j, len;
739cb93a386Sopenharmony_ci    hb_glyph_info_t *glyphs;
740cb93a386Sopenharmony_ci
741cb93a386Sopenharmony_ci    g_test_message ("UTF-16 test #%d", i);
742cb93a386Sopenharmony_ci
743cb93a386Sopenharmony_ci    for (u_len = 0; test->utf16[u_len]; u_len++)
744cb93a386Sopenharmony_ci      ;
745cb93a386Sopenharmony_ci    for (chars = 0; test->codepoints[chars]; chars++)
746cb93a386Sopenharmony_ci      ;
747cb93a386Sopenharmony_ci
748cb93a386Sopenharmony_ci    hb_buffer_clear_contents (b);
749cb93a386Sopenharmony_ci    hb_buffer_add_utf16 (b, test->utf16, u_len,  1, u_len - 2);
750cb93a386Sopenharmony_ci
751cb93a386Sopenharmony_ci    glyphs = hb_buffer_get_glyph_infos (b, &len);
752cb93a386Sopenharmony_ci    g_assert_cmpint (len, ==, chars);
753cb93a386Sopenharmony_ci    for (j = 0; j < chars; j++)
754cb93a386Sopenharmony_ci      g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]);
755cb93a386Sopenharmony_ci  }
756cb93a386Sopenharmony_ci
757cb93a386Sopenharmony_ci  hb_buffer_destroy (b);
758cb93a386Sopenharmony_ci}
759cb93a386Sopenharmony_ci
760cb93a386Sopenharmony_ci
761cb93a386Sopenharmony_citypedef struct {
762cb93a386Sopenharmony_ci  const uint32_t utf32[8];
763cb93a386Sopenharmony_ci  const uint32_t codepoints[8];
764cb93a386Sopenharmony_ci} utf32_conversion_test_t;
765cb93a386Sopenharmony_ci
766cb93a386Sopenharmony_ci/* note: we skip the first and last item from utf32 when adding to buffer */
767cb93a386Sopenharmony_cistatic const utf32_conversion_test_t utf32_conversion_tests[] = {
768cb93a386Sopenharmony_ci  {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, (hb_codepoint_t) -3, (hb_codepoint_t) -3}},
769cb93a386Sopenharmony_ci  {{0x41, 0x004D, 0x0430, 0x4E8C, 0x10302, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}},
770cb93a386Sopenharmony_ci  {{0x41, 0xD800, 0xDF02, 0x61}, {(hb_codepoint_t) -3, (hb_codepoint_t) -3}},
771cb93a386Sopenharmony_ci  {{0x41, 0xD800, 0xDF02}, {(hb_codepoint_t) -3}},
772cb93a386Sopenharmony_ci  {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, (hb_codepoint_t) -3}},
773cb93a386Sopenharmony_ci  {{0x41, 0xD800, 0x61, 0xDF02}, {(hb_codepoint_t) -3, 0x61}},
774cb93a386Sopenharmony_ci  {{0x41, 0xDF00, 0x61}, {(hb_codepoint_t) -3}},
775cb93a386Sopenharmony_ci  {{0x41, 0x10FFFF, 0x61}, {0x10FFFF}},
776cb93a386Sopenharmony_ci  {{0x41, 0x110000, 0x61}, {(hb_codepoint_t) -3}},
777cb93a386Sopenharmony_ci  {{0x41, 0x61}, {0}}
778cb93a386Sopenharmony_ci};
779cb93a386Sopenharmony_ci
780cb93a386Sopenharmony_cistatic void
781cb93a386Sopenharmony_citest_buffer_utf32_conversion (void)
782cb93a386Sopenharmony_ci{
783cb93a386Sopenharmony_ci  hb_buffer_t *b;
784cb93a386Sopenharmony_ci  unsigned int i;
785cb93a386Sopenharmony_ci
786cb93a386Sopenharmony_ci  b = hb_buffer_create ();
787cb93a386Sopenharmony_ci  hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -3);
788cb93a386Sopenharmony_ci
789cb93a386Sopenharmony_ci  for (i = 0; i < G_N_ELEMENTS (utf32_conversion_tests); i++)
790cb93a386Sopenharmony_ci  {
791cb93a386Sopenharmony_ci    const utf32_conversion_test_t *test = &utf32_conversion_tests[i];
792cb93a386Sopenharmony_ci    unsigned int u_len, chars, j, len;
793cb93a386Sopenharmony_ci    hb_glyph_info_t *glyphs;
794cb93a386Sopenharmony_ci
795cb93a386Sopenharmony_ci    g_test_message ("UTF-32 test #%d", i);
796cb93a386Sopenharmony_ci
797cb93a386Sopenharmony_ci    for (u_len = 0; test->utf32[u_len]; u_len++)
798cb93a386Sopenharmony_ci      ;
799cb93a386Sopenharmony_ci    for (chars = 0; test->codepoints[chars]; chars++)
800cb93a386Sopenharmony_ci      ;
801cb93a386Sopenharmony_ci
802cb93a386Sopenharmony_ci    hb_buffer_clear_contents (b);
803cb93a386Sopenharmony_ci    hb_buffer_add_utf32 (b, test->utf32, u_len,  1, u_len - 2);
804cb93a386Sopenharmony_ci
805cb93a386Sopenharmony_ci    glyphs = hb_buffer_get_glyph_infos (b, &len);
806cb93a386Sopenharmony_ci    g_assert_cmpint (len, ==, chars);
807cb93a386Sopenharmony_ci    for (j = 0; j < chars; j++)
808cb93a386Sopenharmony_ci      g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]);
809cb93a386Sopenharmony_ci  }
810cb93a386Sopenharmony_ci
811cb93a386Sopenharmony_ci  hb_buffer_destroy (b);
812cb93a386Sopenharmony_ci}
813cb93a386Sopenharmony_ci
814cb93a386Sopenharmony_ci
815cb93a386Sopenharmony_cistatic void
816cb93a386Sopenharmony_citest_empty (hb_buffer_t *b)
817cb93a386Sopenharmony_ci{
818cb93a386Sopenharmony_ci  g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
819cb93a386Sopenharmony_ci  g_assert (!hb_buffer_get_glyph_infos (b, NULL));
820cb93a386Sopenharmony_ci  g_assert (!hb_buffer_get_glyph_positions (b, NULL));
821cb93a386Sopenharmony_ci}
822cb93a386Sopenharmony_ci
823cb93a386Sopenharmony_cistatic void
824cb93a386Sopenharmony_citest_buffer_empty (void)
825cb93a386Sopenharmony_ci{
826cb93a386Sopenharmony_ci  hb_buffer_t *b = hb_buffer_get_empty ();
827cb93a386Sopenharmony_ci
828cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_empty ());
829cb93a386Sopenharmony_ci  g_assert (hb_buffer_get_empty () == b);
830cb93a386Sopenharmony_ci
831cb93a386Sopenharmony_ci  g_assert (!hb_buffer_allocation_successful (b));
832cb93a386Sopenharmony_ci
833cb93a386Sopenharmony_ci  test_empty (b);
834cb93a386Sopenharmony_ci
835cb93a386Sopenharmony_ci  hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2);
836cb93a386Sopenharmony_ci
837cb93a386Sopenharmony_ci  test_empty (b);
838cb93a386Sopenharmony_ci
839cb93a386Sopenharmony_ci  hb_buffer_reverse (b);
840cb93a386Sopenharmony_ci  hb_buffer_reverse_clusters (b);
841cb93a386Sopenharmony_ci
842cb93a386Sopenharmony_ci  g_assert (!hb_buffer_set_length (b, 10));
843cb93a386Sopenharmony_ci
844cb93a386Sopenharmony_ci  test_empty (b);
845cb93a386Sopenharmony_ci
846cb93a386Sopenharmony_ci  g_assert (hb_buffer_set_length (b, 0));
847cb93a386Sopenharmony_ci
848cb93a386Sopenharmony_ci  test_empty (b);
849cb93a386Sopenharmony_ci
850cb93a386Sopenharmony_ci  g_assert (!hb_buffer_allocation_successful (b));
851cb93a386Sopenharmony_ci
852cb93a386Sopenharmony_ci  hb_buffer_reset (b);
853cb93a386Sopenharmony_ci
854cb93a386Sopenharmony_ci  test_empty (b);
855cb93a386Sopenharmony_ci
856cb93a386Sopenharmony_ci  g_assert (!hb_buffer_allocation_successful (b));
857cb93a386Sopenharmony_ci}
858cb93a386Sopenharmony_ci
859cb93a386Sopenharmony_citypedef struct {
860cb93a386Sopenharmony_ci  const char *contents;
861cb93a386Sopenharmony_ci  hb_buffer_serialize_format_t format;
862cb93a386Sopenharmony_ci  unsigned int num_items;
863cb93a386Sopenharmony_ci  hb_bool_t success;
864cb93a386Sopenharmony_ci} serialization_test_t;
865cb93a386Sopenharmony_ci
866cb93a386Sopenharmony_cistatic const serialization_test_t serialization_tests[] = {
867cb93a386Sopenharmony_ci  { "<U+0640=0|U+0635=1>", HB_BUFFER_SERIALIZE_FORMAT_TEXT, 2, 1 },
868cb93a386Sopenharmony_ci  { "[{\"u\":1600,\"cl\":0},{\"u\":1589,\"cl\":1}]", HB_BUFFER_SERIALIZE_FORMAT_JSON, 2, 1 },
869cb93a386Sopenharmony_ci
870cb93a386Sopenharmony_ci  /* Mixed glyphs/Unicodes -> parse fail */
871cb93a386Sopenharmony_ci  { "[{\"u\":1600,\"cl\":0},{\"g\":1589,\"cl\":1}]", HB_BUFFER_SERIALIZE_FORMAT_JSON, 0, 0 },
872cb93a386Sopenharmony_ci  { "<U+0640=0|uni0635=1>", HB_BUFFER_SERIALIZE_FORMAT_TEXT, 0, 0 },
873cb93a386Sopenharmony_ci};
874cb93a386Sopenharmony_ci
875cb93a386Sopenharmony_cistatic void
876cb93a386Sopenharmony_citest_buffer_serialize_deserialize (void)
877cb93a386Sopenharmony_ci{
878cb93a386Sopenharmony_ci  hb_buffer_t *b;
879cb93a386Sopenharmony_ci  unsigned int i;
880cb93a386Sopenharmony_ci
881cb93a386Sopenharmony_ci  for (i = 0; i < G_N_ELEMENTS (serialization_tests); i++)
882cb93a386Sopenharmony_ci  {
883cb93a386Sopenharmony_ci    unsigned int consumed;
884cb93a386Sopenharmony_ci    char round_trip[1024];
885cb93a386Sopenharmony_ci
886cb93a386Sopenharmony_ci    b = hb_buffer_create ();
887cb93a386Sopenharmony_ci    hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1);
888cb93a386Sopenharmony_ci
889cb93a386Sopenharmony_ci    const serialization_test_t *test = &serialization_tests[i];
890cb93a386Sopenharmony_ci    g_test_message ("serialize test #%d", i);
891cb93a386Sopenharmony_ci
892cb93a386Sopenharmony_ci    (void) hb_buffer_deserialize_unicode (b, test->contents, -1, NULL, test->format);
893cb93a386Sopenharmony_ci
894cb93a386Sopenharmony_ci    // Expected parse failure, got one, don't round-trip
895cb93a386Sopenharmony_ci    if (test->success != 0)
896cb93a386Sopenharmony_ci    {
897cb93a386Sopenharmony_ci      unsigned int num_glyphs = hb_buffer_get_length (b);
898cb93a386Sopenharmony_ci      g_assert_cmpint (num_glyphs, ==, test->num_items);
899cb93a386Sopenharmony_ci
900cb93a386Sopenharmony_ci      hb_buffer_serialize_unicode (b, 0, num_glyphs, round_trip,
901cb93a386Sopenharmony_ci				   sizeof(round_trip), &consumed, test->format,
902cb93a386Sopenharmony_ci				   HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
903cb93a386Sopenharmony_ci      g_assert_cmpstr (round_trip, ==, test->contents);
904cb93a386Sopenharmony_ci    }
905cb93a386Sopenharmony_ci
906cb93a386Sopenharmony_ci    hb_buffer_destroy (b);
907cb93a386Sopenharmony_ci
908cb93a386Sopenharmony_ci  }
909cb93a386Sopenharmony_ci
910cb93a386Sopenharmony_ci  char test[1024];
911cb93a386Sopenharmony_ci  unsigned int consumed;
912cb93a386Sopenharmony_ci  hb_buffer_t *indeterminate = hb_buffer_get_empty ();
913cb93a386Sopenharmony_ci  hb_buffer_serialize (indeterminate, 0, (unsigned) -1,
914cb93a386Sopenharmony_ci		       test, sizeof(test), &consumed, NULL,
915cb93a386Sopenharmony_ci		       HB_BUFFER_SERIALIZE_FORMAT_JSON,
916cb93a386Sopenharmony_ci		       HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
917cb93a386Sopenharmony_ci  g_assert_cmpstr ( test, ==, "[]");
918cb93a386Sopenharmony_ci
919cb93a386Sopenharmony_ci  hb_buffer_serialize (indeterminate, 0, (unsigned) - 1,
920cb93a386Sopenharmony_ci		       test, sizeof(test), &consumed, NULL,
921cb93a386Sopenharmony_ci		       HB_BUFFER_SERIALIZE_FORMAT_TEXT,
922cb93a386Sopenharmony_ci		       HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
923cb93a386Sopenharmony_ci  g_assert_cmpstr ( test, ==, "!!");
924cb93a386Sopenharmony_ci
925cb93a386Sopenharmony_ci}
926cb93a386Sopenharmony_ci
927cb93a386Sopenharmony_ciint
928cb93a386Sopenharmony_cimain (int argc, char **argv)
929cb93a386Sopenharmony_ci{
930cb93a386Sopenharmony_ci  unsigned int i;
931cb93a386Sopenharmony_ci
932cb93a386Sopenharmony_ci  hb_test_init (&argc, &argv);
933cb93a386Sopenharmony_ci
934cb93a386Sopenharmony_ci  for (i = 0; i < BUFFER_NUM_TYPES; i++)
935cb93a386Sopenharmony_ci  {
936cb93a386Sopenharmony_ci    const void *buffer_type = GINT_TO_POINTER (i);
937cb93a386Sopenharmony_ci    const char *buffer_name = buffer_names[i];
938cb93a386Sopenharmony_ci
939cb93a386Sopenharmony_ci    hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_properties);
940cb93a386Sopenharmony_ci    hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_contents);
941cb93a386Sopenharmony_ci    hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_positions);
942cb93a386Sopenharmony_ci  }
943cb93a386Sopenharmony_ci
944cb93a386Sopenharmony_ci  hb_test_add_fixture (fixture, GINT_TO_POINTER (BUFFER_EMPTY), test_buffer_allocation);
945cb93a386Sopenharmony_ci
946cb93a386Sopenharmony_ci  hb_test_add (test_buffer_utf8_conversion);
947cb93a386Sopenharmony_ci  hb_test_add (test_buffer_utf8_validity);
948cb93a386Sopenharmony_ci  hb_test_add (test_buffer_utf16_conversion);
949cb93a386Sopenharmony_ci  hb_test_add (test_buffer_utf32_conversion);
950cb93a386Sopenharmony_ci  hb_test_add (test_buffer_empty);
951cb93a386Sopenharmony_ci  hb_test_add (test_buffer_serialize_deserialize);
952cb93a386Sopenharmony_ci
953cb93a386Sopenharmony_ci  return hb_test_run();
954cb93a386Sopenharmony_ci}
955