2 * Copyright © 2011 Google, Inc.
4 * This is part of HarfBuzz, a text shaping library.
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 * Google Author(s): Behdad Esfahbod
29 /* This file tests types defined in hb-buffer.h */
32 static const char utf8[10] = "ab\360\240\200\200defg";
33 static const uint16_t utf16[8] = {'a', 'b', 0xD840, 0xDC00, 'd', 'e', 'f', 'g'};
34 static const uint32_t utf32[7] = {'a', 'b', 0x20000, 'd', 'e', 'f', 'g'};
46 static const char *buffer_names[] = {
60 fixture_init (fixture_t *fixture, gconstpointer user_data)
64 fixture->b = hb_buffer_create (0);
66 switch (GPOINTER_TO_INT (user_data)) {
70 case BUFFER_ONE_BY_ONE:
71 for (i = 1; i < G_N_ELEMENTS (utf32) - 1; i++)
72 hb_buffer_add (fixture->b, utf32[i], 1, i);
76 hb_buffer_add_utf32 (fixture->b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2);
80 hb_buffer_add_utf16 (fixture->b, utf16, G_N_ELEMENTS (utf16), 1, G_N_ELEMENTS (utf16) - 2);
84 hb_buffer_add_utf8 (fixture->b, utf8, G_N_ELEMENTS (utf8), 1, G_N_ELEMENTS (utf8) - 2);
88 g_assert_not_reached ();
93 fixture_finish (fixture_t *fixture, gconstpointer user_data)
95 hb_buffer_destroy (fixture->b);
100 test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
102 hb_unicode_funcs_t *ufuncs;
104 /* test default properties */
106 g_assert (hb_buffer_get_unicode_funcs (fixture->b) == hb_unicode_funcs_get_default ());
107 g_assert (hb_buffer_get_direction (fixture->b) == HB_DIRECTION_INVALID);
108 g_assert (hb_buffer_get_script (fixture->b) == HB_SCRIPT_INVALID);
109 g_assert (hb_buffer_get_language (fixture->b) == NULL);
112 /* test property changes are retained */
113 ufuncs = hb_unicode_funcs_create (NULL);
114 hb_buffer_set_unicode_funcs (fixture->b, ufuncs);
115 hb_unicode_funcs_destroy (ufuncs);
116 g_assert (hb_buffer_get_unicode_funcs (fixture->b) == ufuncs);
118 hb_buffer_set_direction (fixture->b, HB_DIRECTION_RTL);
119 g_assert (hb_buffer_get_direction (fixture->b) == HB_DIRECTION_RTL);
121 hb_buffer_set_script (fixture->b, HB_SCRIPT_ARABIC);
122 g_assert (hb_buffer_get_script (fixture->b) == HB_SCRIPT_ARABIC);
124 hb_buffer_set_language (fixture->b, hb_language_from_string ("fa"));
125 g_assert (hb_buffer_get_language (fixture->b) == hb_language_from_string ("Fa"));
128 /* test reset clears properties */
130 hb_buffer_reset (fixture->b);
132 g_assert (hb_buffer_get_unicode_funcs (fixture->b) == hb_unicode_funcs_get_default ());
133 g_assert (hb_buffer_get_direction (fixture->b) == HB_DIRECTION_INVALID);
134 g_assert (hb_buffer_get_script (fixture->b) == HB_SCRIPT_INVALID);
135 g_assert (hb_buffer_get_language (fixture->b) == NULL);
139 test_buffer_contents (fixture_t *fixture, gconstpointer user_data)
141 unsigned int i, len, len2;
142 buffer_type_t buffer_type = GPOINTER_TO_INT (user_data);
143 hb_glyph_info_t *glyphs;
145 if (buffer_type == BUFFER_EMPTY) {
146 g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
150 len = hb_buffer_get_length (fixture->b);
151 glyphs = hb_buffer_get_glyph_infos (fixture->b, NULL); /* test NULL */
152 glyphs = hb_buffer_get_glyph_infos (fixture->b, &len2);
153 g_assert_cmpint (len, ==, len2);
154 g_assert_cmpint (len, ==, 5);
156 for (i = 0; i < len; i++) {
157 g_assert_cmphex (glyphs[i].mask, ==, 1);
158 g_assert_cmphex (glyphs[i].var1.u32, ==, 0);
159 g_assert_cmphex (glyphs[i].var2.u32, ==, 0);
162 for (i = 0; i < len; i++) {
163 unsigned int cluster;
166 if (buffer_type == BUFFER_UTF16)
168 else if (buffer_type == BUFFER_UTF8)
171 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
172 g_assert_cmphex (glyphs[i].cluster, ==, cluster);
175 /* reverse, test, and reverse back */
177 hb_buffer_reverse (fixture->b);
178 for (i = 0; i < len; i++)
179 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
181 hb_buffer_reverse (fixture->b);
182 for (i = 0; i < len; i++)
183 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
185 /* reverse_clusters works same as reverse for now since each codepoint is
186 * in its own cluster */
188 hb_buffer_reverse_clusters (fixture->b);
189 for (i = 0; i < len; i++)
190 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
192 hb_buffer_reverse_clusters (fixture->b);
193 for (i = 0; i < len; i++)
194 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
196 /* now form a cluster and test again */
197 glyphs[2].cluster = glyphs[1].cluster;
199 /* reverse, test, and reverse back */
201 hb_buffer_reverse (fixture->b);
202 for (i = 0; i < len; i++)
203 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
205 hb_buffer_reverse (fixture->b);
206 for (i = 0; i < len; i++)
207 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
209 /* reverse_clusters twice still should return the original string,
210 * but when applied once, the 1-2 cluster should be retained. */
212 hb_buffer_reverse_clusters (fixture->b);
213 for (i = 0; i < len; i++) {
214 unsigned int j = len-1-i;
219 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+j]);
222 hb_buffer_reverse_clusters (fixture->b);
223 for (i = 0; i < len; i++)
224 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
227 /* test setting length */
230 g_assert (hb_buffer_set_length (fixture->b, 10));
231 glyphs = hb_buffer_get_glyph_infos (fixture->b, NULL);
232 g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 10);
233 for (i = 0; i < 5; i++)
234 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
235 for (i = 5; i < 10; i++)
236 g_assert_cmphex (glyphs[i].codepoint, ==, 0);
238 g_assert (hb_buffer_set_length (fixture->b, 3));
239 glyphs = hb_buffer_get_glyph_infos (fixture->b, NULL);
240 g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 3);
241 for (i = 0; i < 3; i++)
242 g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
245 g_assert (hb_buffer_allocation_successful (fixture->b));
248 /* test reset clears content */
250 hb_buffer_reset (fixture->b);
251 g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
255 test_buffer_positions (fixture_t *fixture, gconstpointer user_data)
257 unsigned int i, len, len2;
258 hb_glyph_position_t *positions;
260 /* Without shaping, positions should all be zero */
261 len = hb_buffer_get_length (fixture->b);
262 positions = hb_buffer_get_glyph_positions (fixture->b, NULL); /* test NULL */
263 positions = hb_buffer_get_glyph_positions (fixture->b, &len2);
264 g_assert_cmpint (len, ==, len2);
265 for (i = 0; i < len; i++) {
266 g_assert_cmpint (0, ==, positions[i].x_advance);
267 g_assert_cmpint (0, ==, positions[i].y_advance);
268 g_assert_cmpint (0, ==, positions[i].x_offset);
269 g_assert_cmpint (0, ==, positions[i].y_offset);
270 g_assert_cmpint (0, ==, positions[i].var.i32);
273 /* test reset clears content */
274 hb_buffer_reset (fixture->b);
275 g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
279 test_buffer_allocation (fixture_t *fixture, gconstpointer user_data)
281 g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
283 g_assert (hb_buffer_pre_allocate (fixture->b, 100));
284 g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
285 g_assert (hb_buffer_allocation_successful (fixture->b));
287 /* lets try a huge allocation, make sure it fails */
288 g_assert (!hb_buffer_pre_allocate (fixture->b, (unsigned int) -1));
289 g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
290 g_assert (!hb_buffer_allocation_successful (fixture->b));
292 /* small one again */
293 g_assert (hb_buffer_pre_allocate (fixture->b, 50));
294 g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
295 g_assert (!hb_buffer_allocation_successful (fixture->b));
297 hb_buffer_reset (fixture->b);
298 g_assert (hb_buffer_allocation_successful (fixture->b));
300 /* all allocation and size */
301 g_assert (!hb_buffer_pre_allocate (fixture->b, ((unsigned int) -1) / 20 + 1));
302 g_assert (!hb_buffer_allocation_successful (fixture->b));
304 hb_buffer_reset (fixture->b);
305 g_assert (hb_buffer_allocation_successful (fixture->b));
307 /* technically, this one can actually pass on 64bit machines, but
308 * I'm doubtful that any malloc allows 4GB allocations at a time.
309 * But let's only enable it on a 32-bit machine. */
310 if (sizeof (long) == 4) {
311 g_assert (!hb_buffer_pre_allocate (fixture->b, ((unsigned int) -1) / 20 - 1));
312 g_assert (!hb_buffer_allocation_successful (fixture->b));
315 hb_buffer_reset (fixture->b);
316 g_assert (hb_buffer_allocation_successful (fixture->b));
322 const uint32_t codepoints[8];
325 /* note: we skip the first and last byte when adding to buffer */
326 static const utf8_test_t utf8_tests[] = {
328 {"a\303\207b", {0xC7}},
329 {"ab\303cd", {'b', -1, 'c'}},
330 {"ab\303\302\301cd", {'b', -1, -1, -1, 'c'}}
334 test_buffer_utf8 (gconstpointer user_data)
336 const utf8_test_t *test = user_data;
338 hb_glyph_info_t *glyphs;
339 unsigned int bytes, chars, i, len;
341 bytes = strlen (test->utf8);
342 for (chars = 0; test->codepoints[chars]; chars++)
345 b = hb_buffer_create (0);
346 hb_buffer_add_utf8 (b, test->utf8, bytes, 1, bytes - 2);
348 glyphs = hb_buffer_get_glyph_infos (b, &len);
349 g_assert_cmpint (len, ==, chars);
350 for (i = 0; i < chars; i++)
351 g_assert_cmphex (glyphs[i].codepoint, ==, test->codepoints[i]);
353 hb_buffer_destroy (b);
358 /* Following test table is adapted from glib/glib/tests/utf8-validate.c
359 * with relicensing permission from Matthias Clasen. */
366 } utf8_validity_test_t;
368 static const utf8_validity_test_t utf8_validity_tests[] = {
369 /* some tests to check max_len handling */
371 { "abcde", -1, 5, TRUE },
372 { "abcde", 3, 3, TRUE },
373 { "abcde", 5, 5, TRUE },
375 { "\xc2\xa9\xc2\xa9\xc2\xa9", -1, 6, TRUE },
376 { "\xc2\xa9\xc2\xa9\xc2\xa9", 1, 0, FALSE },
377 { "\xc2\xa9\xc2\xa9\xc2\xa9", 2, 2, TRUE },
378 { "\xc2\xa9\xc2\xa9\xc2\xa9", 3, 2, FALSE },
379 { "\xc2\xa9\xc2\xa9\xc2\xa9", 4, 4, TRUE },
380 { "\xc2\xa9\xc2\xa9\xc2\xa9", 5, 4, FALSE },
381 { "\xc2\xa9\xc2\xa9\xc2\xa9", 6, 6, TRUE },
383 { "\xe2\x89\xa0\xe2\x89\xa0", -1, 6, TRUE },
384 { "\xe2\x89\xa0\xe2\x89\xa0", 1, 0, FALSE },
385 { "\xe2\x89\xa0\xe2\x89\xa0", 2, 0, FALSE },
386 { "\xe2\x89\xa0\xe2\x89\xa0", 3, 3, TRUE },
387 { "\xe2\x89\xa0\xe2\x89\xa0", 4, 3, FALSE },
388 { "\xe2\x89\xa0\xe2\x89\xa0", 5, 3, FALSE },
389 { "\xe2\x89\xa0\xe2\x89\xa0", 6, 6, TRUE },
391 /* examples from http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt */
393 { "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5", -1, 11, TRUE },
394 /* first sequence of each length */
395 { "\x00", -1, 0, TRUE },
396 { "\xc2\x80", -1, 2, TRUE },
397 { "\xe0\xa0\x80", -1, 3, TRUE },
398 { "\xf0\x90\x80\x80", -1, 4, TRUE },
399 { "\xf8\x88\x80\x80\x80", -1, 0, FALSE },
400 { "\xfc\x84\x80\x80\x80\x80", -1, 0, FALSE },
401 /* last sequence of each length */
402 { "\x7f", -1, 1, TRUE },
403 { "\xdf\xbf", -1, 2, TRUE },
404 { "\xef\xbf\xbf", -1, 0, TRUE },
405 { "\xf7\xbf\xbf\xbf", -1, 0, TRUE },
406 { "\xfb\xbf\xbf\xbf\xbf", -1, 0, FALSE },
407 { "\xfd\xbf\xbf\xbf\xbf\xbf", -1, 0, FALSE },
408 /* other boundary conditions */
409 { "\xed\x9f\xbf", -1, 3, TRUE },
410 { "\xee\x80\x80", -1, 3, TRUE },
411 { "\xef\xbf\xbd", -1, 3, TRUE },
412 { "\xf4\x8f\xbf\xbf", -1, 0, TRUE },
413 /* malformed sequences */
414 /* continuation bytes */
415 { "\x80", -1, 0, FALSE },
416 { "\xbf", -1, 0, FALSE },
417 { "\x80\xbf", -1, 0, FALSE },
418 { "\x80\xbf\x80", -1, 0, FALSE },
419 { "\x80\xbf\x80\xbf", -1, 0, FALSE },
420 { "\x80\xbf\x80\xbf\x80", -1, 0, FALSE },
421 { "\x80\xbf\x80\xbf\x80\xbf", -1, 0, FALSE },
422 { "\x80\xbf\x80\xbf\x80\xbf\x80", -1, 0, FALSE },
424 /* all possible continuation byte */
425 { "\x80", -1, 0, FALSE },
426 { "\x81", -1, 0, FALSE },
427 { "\x82", -1, 0, FALSE },
428 { "\x83", -1, 0, FALSE },
429 { "\x84", -1, 0, FALSE },
430 { "\x85", -1, 0, FALSE },
431 { "\x86", -1, 0, FALSE },
432 { "\x87", -1, 0, FALSE },
433 { "\x88", -1, 0, FALSE },
434 { "\x89", -1, 0, FALSE },
435 { "\x8a", -1, 0, FALSE },
436 { "\x8b", -1, 0, FALSE },
437 { "\x8c", -1, 0, FALSE },
438 { "\x8d", -1, 0, FALSE },
439 { "\x8e", -1, 0, FALSE },
440 { "\x8f", -1, 0, FALSE },
441 { "\x90", -1, 0, FALSE },
442 { "\x91", -1, 0, FALSE },
443 { "\x92", -1, 0, FALSE },
444 { "\x93", -1, 0, FALSE },
445 { "\x94", -1, 0, FALSE },
446 { "\x95", -1, 0, FALSE },
447 { "\x96", -1, 0, FALSE },
448 { "\x97", -1, 0, FALSE },
449 { "\x98", -1, 0, FALSE },
450 { "\x99", -1, 0, FALSE },
451 { "\x9a", -1, 0, FALSE },
452 { "\x9b", -1, 0, FALSE },
453 { "\x9c", -1, 0, FALSE },
454 { "\x9d", -1, 0, FALSE },
455 { "\x9e", -1, 0, FALSE },
456 { "\x9f", -1, 0, FALSE },
457 { "\xa0", -1, 0, FALSE },
458 { "\xa1", -1, 0, FALSE },
459 { "\xa2", -1, 0, FALSE },
460 { "\xa3", -1, 0, FALSE },
461 { "\xa4", -1, 0, FALSE },
462 { "\xa5", -1, 0, FALSE },
463 { "\xa6", -1, 0, FALSE },
464 { "\xa7", -1, 0, FALSE },
465 { "\xa8", -1, 0, FALSE },
466 { "\xa9", -1, 0, FALSE },
467 { "\xaa", -1, 0, FALSE },
468 { "\xab", -1, 0, FALSE },
469 { "\xac", -1, 0, FALSE },
470 { "\xad", -1, 0, FALSE },
471 { "\xae", -1, 0, FALSE },
472 { "\xaf", -1, 0, FALSE },
473 { "\xb0", -1, 0, FALSE },
474 { "\xb1", -1, 0, FALSE },
475 { "\xb2", -1, 0, FALSE },
476 { "\xb3", -1, 0, FALSE },
477 { "\xb4", -1, 0, FALSE },
478 { "\xb5", -1, 0, FALSE },
479 { "\xb6", -1, 0, FALSE },
480 { "\xb7", -1, 0, FALSE },
481 { "\xb8", -1, 0, FALSE },
482 { "\xb9", -1, 0, FALSE },
483 { "\xba", -1, 0, FALSE },
484 { "\xbb", -1, 0, FALSE },
485 { "\xbc", -1, 0, FALSE },
486 { "\xbd", -1, 0, FALSE },
487 { "\xbe", -1, 0, FALSE },
488 { "\xbf", -1, 0, FALSE },
489 /* lone start characters */
490 { "\xc0\x20", -1, 0, FALSE },
491 { "\xc1\x20", -1, 0, FALSE },
492 { "\xc2\x20", -1, 0, FALSE },
493 { "\xc3\x20", -1, 0, FALSE },
494 { "\xc4\x20", -1, 0, FALSE },
495 { "\xc5\x20", -1, 0, FALSE },
496 { "\xc6\x20", -1, 0, FALSE },
497 { "\xc7\x20", -1, 0, FALSE },
498 { "\xc8\x20", -1, 0, FALSE },
499 { "\xc9\x20", -1, 0, FALSE },
500 { "\xca\x20", -1, 0, FALSE },
501 { "\xcb\x20", -1, 0, FALSE },
502 { "\xcc\x20", -1, 0, FALSE },
503 { "\xcd\x20", -1, 0, FALSE },
504 { "\xce\x20", -1, 0, FALSE },
505 { "\xcf\x20", -1, 0, FALSE },
506 { "\xd0\x20", -1, 0, FALSE },
507 { "\xd1\x20", -1, 0, FALSE },
508 { "\xd2\x20", -1, 0, FALSE },
509 { "\xd3\x20", -1, 0, FALSE },
510 { "\xd4\x20", -1, 0, FALSE },
511 { "\xd5\x20", -1, 0, FALSE },
512 { "\xd6\x20", -1, 0, FALSE },
513 { "\xd7\x20", -1, 0, FALSE },
514 { "\xd8\x20", -1, 0, FALSE },
515 { "\xd9\x20", -1, 0, FALSE },
516 { "\xda\x20", -1, 0, FALSE },
517 { "\xdb\x20", -1, 0, FALSE },
518 { "\xdc\x20", -1, 0, FALSE },
519 { "\xdd\x20", -1, 0, FALSE },
520 { "\xde\x20", -1, 0, FALSE },
521 { "\xdf\x20", -1, 0, FALSE },
522 { "\xe0\x20", -1, 0, FALSE },
523 { "\xe1\x20", -1, 0, FALSE },
524 { "\xe2\x20", -1, 0, FALSE },
525 { "\xe3\x20", -1, 0, FALSE },
526 { "\xe4\x20", -1, 0, FALSE },
527 { "\xe5\x20", -1, 0, FALSE },
528 { "\xe6\x20", -1, 0, FALSE },
529 { "\xe7\x20", -1, 0, FALSE },
530 { "\xe8\x20", -1, 0, FALSE },
531 { "\xe9\x20", -1, 0, FALSE },
532 { "\xea\x20", -1, 0, FALSE },
533 { "\xeb\x20", -1, 0, FALSE },
534 { "\xec\x20", -1, 0, FALSE },
535 { "\xed\x20", -1, 0, FALSE },
536 { "\xee\x20", -1, 0, FALSE },
537 { "\xef\x20", -1, 0, FALSE },
538 { "\xf0\x20", -1, 0, FALSE },
539 { "\xf1\x20", -1, 0, FALSE },
540 { "\xf2\x20", -1, 0, FALSE },
541 { "\xf3\x20", -1, 0, FALSE },
542 { "\xf4\x20", -1, 0, FALSE },
543 { "\xf5\x20", -1, 0, FALSE },
544 { "\xf6\x20", -1, 0, FALSE },
545 { "\xf7\x20", -1, 0, FALSE },
546 { "\xf8\x20", -1, 0, FALSE },
547 { "\xf9\x20", -1, 0, FALSE },
548 { "\xfa\x20", -1, 0, FALSE },
549 { "\xfb\x20", -1, 0, FALSE },
550 { "\xfc\x20", -1, 0, FALSE },
551 { "\xfd\x20", -1, 0, FALSE },
552 /* missing continuation bytes */
553 { "\x20\xc0", -1, 1, FALSE },
554 { "\x20\xe0\x80", -1, 1, FALSE },
555 { "\x20\xf0\x80\x80", -1, 1, FALSE },
556 { "\x20\xf8\x80\x80\x80", -1, 1, FALSE },
557 { "\x20\xfc\x80\x80\x80\x80", -1, 1, FALSE },
558 { "\x20\xdf", -1, 1, FALSE },
559 { "\x20\xef\xbf", -1, 1, FALSE },
560 { "\x20\xf7\xbf\xbf", -1, 1, FALSE },
561 { "\x20\xfb\xbf\xbf\xbf", -1, 1, FALSE },
562 { "\x20\xfd\xbf\xbf\xbf\xbf", -1, 1, FALSE },
563 /* impossible bytes */
564 { "\x20\xfe\x20", -1, 1, FALSE },
565 { "\x20\xff\x20", -1, 1, FALSE },
567 /* XXX fix these, or document that we don't detect them? */
568 /* overlong sequences */
569 { "\x20\xc0\xaf\x20", -1, 1, FALSE },
570 { "\x20\xe0\x80\xaf\x20", -1, 1, FALSE },
571 { "\x20\xf0\x80\x80\xaf\x20", -1, 1, FALSE },
572 { "\x20\xf8\x80\x80\x80\xaf\x20", -1, 1, FALSE },
573 { "\x20\xfc\x80\x80\x80\x80\xaf\x20", -1, 1, FALSE },
574 { "\x20\xc1\xbf\x20", -1, 1, FALSE },
575 { "\x20\xe0\x9f\xbf\x20", -1, 1, FALSE },
576 { "\x20\xf0\x8f\xbf\xbf\x20", -1, 1, FALSE },
577 { "\x20\xf8\x87\xbf\xbf\xbf\x20", -1, 1, FALSE },
578 { "\x20\xfc\x83\xbf\xbf\xbf\xbf\x20", -1, 1, FALSE },
579 { "\x20\xc0\x80\x20", -1, 1, FALSE },
580 { "\x20\xe0\x80\x80\x20", -1, 1, FALSE },
581 { "\x20\xf0\x80\x80\x80\x20", -1, 1, FALSE },
582 { "\x20\xf8\x80\x80\x80\x80\x20", -1, 1, FALSE },
583 { "\x20\xfc\x80\x80\x80\x80\x80\x20", -1, 1, FALSE },
584 /* illegal code positions */
585 { "\x20\xed\xa0\x80\x20", -1, 1, FALSE },
586 { "\x20\xed\xad\xbf\x20", -1, 1, FALSE },
587 { "\x20\xed\xae\x80\x20", -1, 1, FALSE },
588 { "\x20\xed\xaf\xbf\x20", -1, 1, FALSE },
589 { "\x20\xed\xb0\x80\x20", -1, 1, FALSE },
590 { "\x20\xed\xbe\x80\x20", -1, 1, FALSE },
591 { "\x20\xed\xbf\xbf\x20", -1, 1, FALSE },
592 { "\x20\xed\xa0\x80\xed\xb0\x80\x20", -1, 1, FALSE },
593 { "\x20\xed\xa0\x80\xed\xbf\xbf\x20", -1, 1, FALSE },
594 { "\x20\xed\xad\xbf\xed\xb0\x80\x20", -1, 1, FALSE },
595 { "\x20\xed\xad\xbf\xed\xbf\xbf\x20", -1, 1, FALSE },
596 { "\x20\xed\xae\x80\xed\xb0\x80\x20", -1, 1, FALSE },
597 { "\x20\xed\xae\x80\xed\xbf\xbf\x20", -1, 1, FALSE },
598 { "\x20\xed\xaf\xbf\xed\xb0\x80\x20", -1, 1, FALSE },
599 { "\x20\xed\xaf\xbf\xed\xbf\xbf\x20", -1, 1, FALSE },
600 { "\x20\xef\xbf\xbe\x20", -1, 1, FALSE },
601 { "\x20\xef\xbf\xbf\x20", -1, 1, FALSE },
607 test_buffer_utf8_validity (gconstpointer user_data)
609 const utf8_validity_test_t *test = user_data;
611 hb_glyph_info_t *glyphs;
612 unsigned int text_bytes, segment_bytes, i, len;
614 text_bytes = strlen (test->text);
615 if (test->max_len == -1)
616 segment_bytes = text_bytes;
618 segment_bytes = test->max_len;
620 b = hb_buffer_create (0);
621 hb_buffer_add_utf8 (b, test->text, text_bytes, 0, segment_bytes);
623 glyphs = hb_buffer_get_glyph_infos (b, &len);
624 for (i = 0; i < len; i++)
625 if (glyphs[i].codepoint == (hb_codepoint_t) -1)
628 g_assert (test->valid ? i == len : i < len);
630 g_assert (glyphs[i].cluster == test->offset);
632 hb_buffer_destroy (b);
637 const uint16_t utf16[8];
638 const uint32_t codepoints[8];
641 /* note: we skip the first and last item from utf16 when adding to buffer */
642 static const utf16_test_t utf16_tests[] = {
643 {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}},
644 {{0x41, 0xD800, 0xDF02, 0x61}, {0x10302}},
645 {{0x41, 0xD800, 0xDF02}, {-1}},
646 {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, -1}},
647 {{0x41, 0xD800, 0x61, 0xDF02}, {-1, 0x61}},
652 test_buffer_utf16 (gconstpointer user_data)
654 const utf16_test_t *test = user_data;
656 hb_glyph_info_t *glyphs;
657 unsigned int u_len, chars, i, len;
659 for (u_len = 0; test->utf16[u_len]; u_len++)
661 for (chars = 0; test->codepoints[chars]; chars++)
664 b = hb_buffer_create (0);
665 hb_buffer_add_utf16 (b, test->utf16, u_len, 1, u_len - 2);
667 glyphs = hb_buffer_get_glyph_infos (b, &len);
668 g_assert_cmpint (len, ==, chars);
669 for (i = 0; i < chars; i++)
670 g_assert_cmphex (glyphs[i].codepoint, ==, test->codepoints[i]);
672 hb_buffer_destroy (b);
677 main (int argc, char **argv)
681 hb_test_init (&argc, &argv);
683 for (i = 0; i < BUFFER_NUM_TYPES; i++)
685 const void *buffer_type = GINT_TO_POINTER (i);
686 const char *buffer_name = buffer_names[i];
688 hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_properties);
689 hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_contents);
690 hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_positions);
693 hb_test_add_fixture (fixture, GINT_TO_POINTER (BUFFER_EMPTY), test_buffer_allocation);
695 for (i = 0; i < G_N_ELEMENTS (utf8_tests); i++)
697 char *flavor = g_strdup_printf ("%d", i);
698 hb_test_add_data_flavor (&utf8_tests[i], flavor, test_buffer_utf8);
701 for (i = 0; i < G_N_ELEMENTS (utf8_validity_tests); i++)
703 char *flavor = g_strdup_printf ("%d", i);
704 hb_test_add_data_flavor (&utf8_validity_tests[i], flavor, test_buffer_utf8_validity);
708 for (i = 0; i < G_N_ELEMENTS (utf16_tests); i++)
710 char *flavor = g_strdup_printf ("%d", i);
711 hb_test_add_data_flavor (&utf16_tests[i], flavor, test_buffer_utf16);
715 return hb_test_run();