Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/harfbuzz/src/test-repacker.cc @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * Copyright © 2020 Google, Inc. | |
| 3 * | |
| 4 * This is part of HarfBuzz, a text shaping library. | |
| 5 * | |
| 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. | |
| 11 * | |
| 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 | |
| 16 * DAMAGE. | |
| 17 * | |
| 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. | |
| 23 * | |
| 24 * Google Author(s): Garret Rieger | |
| 25 */ | |
| 26 | |
| 27 #include <string> | |
| 28 | |
| 29 #include "hb-repacker.hh" | |
| 30 #include "hb-open-type.hh" | |
| 31 #include "graph/serialize.hh" | |
| 32 | |
| 33 static void extend (const char* value, | |
| 34 unsigned len, | |
| 35 hb_serialize_context_t* c) | |
| 36 { | |
| 37 char* obj = c->allocate_size<char> (len); | |
| 38 hb_memcpy (obj, value, len); | |
| 39 } | |
| 40 | |
| 41 static void start_object(const char* tag, | |
| 42 unsigned len, | |
| 43 hb_serialize_context_t* c) | |
| 44 { | |
| 45 c->push (); | |
| 46 extend (tag, len, c); | |
| 47 } | |
| 48 | |
| 49 static unsigned add_object(const char* tag, | |
| 50 unsigned len, | |
| 51 hb_serialize_context_t* c) | |
| 52 { | |
| 53 start_object (tag, len, c); | |
| 54 return c->pop_pack (false); | |
| 55 } | |
| 56 | |
| 57 | |
| 58 static void add_offset (unsigned id, | |
| 59 hb_serialize_context_t* c) | |
| 60 { | |
| 61 OT::Offset16* offset = c->start_embed<OT::Offset16> (); | |
| 62 c->extend_min (offset); | |
| 63 c->add_link (*offset, id); | |
| 64 } | |
| 65 | |
| 66 static void add_24_offset (unsigned id, | |
| 67 hb_serialize_context_t* c) | |
| 68 { | |
| 69 OT::Offset24* offset = c->start_embed<OT::Offset24> (); | |
| 70 c->extend_min (offset); | |
| 71 c->add_link (*offset, id); | |
| 72 } | |
| 73 | |
| 74 static void add_wide_offset (unsigned id, | |
| 75 hb_serialize_context_t* c) | |
| 76 { | |
| 77 OT::Offset32* offset = c->start_embed<OT::Offset32> (); | |
| 78 c->extend_min (offset); | |
| 79 c->add_link (*offset, id); | |
| 80 } | |
| 81 | |
| 82 static void add_gsubgpos_header (unsigned lookup_list, | |
| 83 hb_serialize_context_t* c) | |
| 84 { | |
| 85 char header[] = { | |
| 86 0, 1, // major | |
| 87 0, 0, // minor | |
| 88 0, 0, // script list | |
| 89 0, 0, // feature list | |
| 90 }; | |
| 91 | |
| 92 start_object (header, 8, c); | |
| 93 add_offset (lookup_list, c); | |
| 94 c->pop_pack (false); | |
| 95 } | |
| 96 | |
| 97 static unsigned add_lookup_list (const unsigned* lookups, | |
| 98 char count, | |
| 99 hb_serialize_context_t* c) | |
| 100 { | |
| 101 char lookup_count[] = {0, count}; | |
| 102 start_object ((char *) &lookup_count, 2, c); | |
| 103 | |
| 104 for (int i = 0; i < count; i++) | |
| 105 add_offset (lookups[i], c); | |
| 106 | |
| 107 return c->pop_pack (false); | |
| 108 } | |
| 109 | |
| 110 static void start_lookup (int8_t type, | |
| 111 int8_t num_subtables, | |
| 112 hb_serialize_context_t* c) | |
| 113 { | |
| 114 char lookup[] = { | |
| 115 0, (char)type, // type | |
| 116 0, 0, // flag | |
| 117 0, (char)num_subtables, // num subtables | |
| 118 }; | |
| 119 | |
| 120 start_object (lookup, 6, c); | |
| 121 } | |
| 122 | |
| 123 static unsigned finish_lookup (hb_serialize_context_t* c) | |
| 124 { | |
| 125 char filter[] = {0, 0}; | |
| 126 extend (filter, 2, c); | |
| 127 return c->pop_pack (false); | |
| 128 } | |
| 129 | |
| 130 static unsigned add_extension (unsigned child, | |
| 131 uint8_t type, | |
| 132 hb_serialize_context_t* c) | |
| 133 { | |
| 134 char ext[] = { | |
| 135 0, 1, | |
| 136 0, (char) type, | |
| 137 }; | |
| 138 | |
| 139 start_object (ext, 4, c); | |
| 140 add_wide_offset (child, c); | |
| 141 | |
| 142 return c->pop_pack (false); | |
| 143 | |
| 144 } | |
| 145 | |
| 146 // Adds coverage table fro [start, end] | |
| 147 static unsigned add_coverage (unsigned start, unsigned end, | |
| 148 hb_serialize_context_t* c) | |
| 149 { | |
| 150 if (end - start == 1) | |
| 151 { | |
| 152 uint8_t coverage[] = { | |
| 153 0, 1, // format | |
| 154 0, 2, // count | |
| 155 | |
| 156 (uint8_t) ((start >> 8) & 0xFF), | |
| 157 (uint8_t) (start & 0xFF), // glyph[0] | |
| 158 | |
| 159 (uint8_t) ((end >> 8) & 0xFF), | |
| 160 (uint8_t) (end & 0xFF), // glyph[1] | |
| 161 }; | |
| 162 return add_object ((char*) coverage, 8, c); | |
| 163 } | |
| 164 | |
| 165 uint8_t coverage[] = { | |
| 166 0, 2, // format | |
| 167 0, 1, // range count | |
| 168 | |
| 169 (uint8_t) ((start >> 8) & 0xFF), | |
| 170 (uint8_t) (start & 0xFF), // start | |
| 171 | |
| 172 (uint8_t) ((end >> 8) & 0xFF), | |
| 173 (uint8_t) (end & 0xFF), // end | |
| 174 | |
| 175 0, 0, | |
| 176 }; | |
| 177 return add_object ((char*) coverage, 10, c); | |
| 178 } | |
| 179 | |
| 180 | |
| 181 template<typename It> | |
| 182 static unsigned add_coverage (It it, | |
| 183 hb_serialize_context_t* c) | |
| 184 { | |
| 185 c->push (); | |
| 186 OT::Layout::Common::Coverage_serialize (c, it); | |
| 187 return c->pop_pack (false); | |
| 188 } | |
| 189 | |
| 190 // Adds a class that maps glyphs from [start_glyph, end_glyph) | |
| 191 // to classes 1...n | |
| 192 static unsigned add_class_def (uint16_t start_glyph, | |
| 193 uint16_t end_glyph, | |
| 194 hb_serialize_context_t* c) | |
| 195 { | |
| 196 unsigned count = end_glyph - start_glyph; | |
| 197 uint8_t header[] = { | |
| 198 0, 1, // format | |
| 199 | |
| 200 (uint8_t) ((start_glyph >> 8) & 0xFF), | |
| 201 (uint8_t) (start_glyph & 0xFF), // start_glyph | |
| 202 | |
| 203 (uint8_t) ((count >> 8) & 0xFF), | |
| 204 (uint8_t) (count & 0xFF), // count | |
| 205 }; | |
| 206 | |
| 207 start_object ((char*) header, 6, c); | |
| 208 for (uint16_t i = 1; i <= count; i++) | |
| 209 { | |
| 210 uint8_t class_value[] = { | |
| 211 (uint8_t) ((i >> 8) & 0xFF), | |
| 212 (uint8_t) (i & 0xFF), // count | |
| 213 }; | |
| 214 extend ((char*) class_value, 2, c); | |
| 215 } | |
| 216 | |
| 217 return c->pop_pack (false); | |
| 218 } | |
| 219 | |
| 220 static unsigned add_pair_pos_1 (unsigned* pair_sets, | |
| 221 char count, | |
| 222 unsigned coverage, | |
| 223 hb_serialize_context_t* c) | |
| 224 { | |
| 225 char format[] = { | |
| 226 0, 1 | |
| 227 }; | |
| 228 | |
| 229 start_object (format, 2, c); | |
| 230 add_offset (coverage, c); | |
| 231 | |
| 232 char value_format[] = { | |
| 233 0, 0, | |
| 234 0, 0, | |
| 235 0, count, | |
| 236 }; | |
| 237 extend (value_format, 6, c); | |
| 238 | |
| 239 for (char i = 0; i < count; i++) | |
| 240 add_offset (pair_sets[(unsigned) i], c); | |
| 241 | |
| 242 return c->pop_pack (false); | |
| 243 } | |
| 244 | |
| 245 static unsigned add_pair_pos_2 (unsigned starting_class, | |
| 246 unsigned coverage, | |
| 247 unsigned class_def_1, uint16_t class_def_1_count, | |
| 248 unsigned class_def_2, uint16_t class_def_2_count, | |
| 249 unsigned* device_tables, | |
| 250 hb_serialize_context_t* c) | |
| 251 { | |
| 252 uint8_t format[] = { | |
| 253 0, 2 | |
| 254 }; | |
| 255 | |
| 256 start_object ((char*) format, 2, c); | |
| 257 add_offset (coverage, c); | |
| 258 | |
| 259 unsigned num_values = 4; | |
| 260 uint8_t format1 = 0x01 | 0x02 | 0x08; | |
| 261 uint8_t format2 = 0x04; | |
| 262 if (device_tables) { | |
| 263 format2 |= 0x20; | |
| 264 num_values += 1; | |
| 265 } | |
| 266 uint8_t value_format[] = { | |
| 267 0, format1, | |
| 268 0, format2, | |
| 269 }; | |
| 270 | |
| 271 extend ((char*) value_format, 4, c); | |
| 272 | |
| 273 add_offset (class_def_1, c); | |
| 274 add_offset (class_def_2, c); | |
| 275 | |
| 276 uint8_t class_counts[] = { | |
| 277 (uint8_t) ((class_def_1_count >> 8) & 0xFF), | |
| 278 (uint8_t) (class_def_1_count & 0xFF), | |
| 279 (uint8_t) ((class_def_2_count >> 8) & 0xFF), | |
| 280 (uint8_t) (class_def_2_count & 0xFF), | |
| 281 }; | |
| 282 extend ((char*) class_counts, 4, c); | |
| 283 | |
| 284 unsigned num_bytes_per_record = class_def_2_count * num_values * 2; | |
| 285 uint8_t* record = (uint8_t*) calloc (1, num_bytes_per_record); | |
| 286 int device_index = 0; | |
| 287 for (uint16_t i = 0; i < class_def_1_count; i++) | |
| 288 { | |
| 289 | |
| 290 for (uint16_t j = 0; j < class_def_2_count; j++) | |
| 291 { | |
| 292 for (int k = 0; k < 4; k++) { | |
| 293 uint8_t value[] = { | |
| 294 (uint8_t) (i + starting_class), | |
| 295 (uint8_t) (i + starting_class), | |
| 296 }; | |
| 297 extend ((char*) value, 2, c); | |
| 298 } | |
| 299 | |
| 300 if (device_tables) { | |
| 301 add_offset (device_tables[device_index++], c); | |
| 302 } | |
| 303 } | |
| 304 } | |
| 305 free (record); | |
| 306 | |
| 307 return c->pop_pack (false); | |
| 308 } | |
| 309 | |
| 310 static unsigned add_mark_base_pos_1 (unsigned mark_coverage, | |
| 311 unsigned base_coverage, | |
| 312 unsigned mark_array, | |
| 313 unsigned base_array, | |
| 314 unsigned class_count, | |
| 315 hb_serialize_context_t* c) | |
| 316 { | |
| 317 uint8_t format[] = { | |
| 318 0, 1 | |
| 319 }; | |
| 320 | |
| 321 start_object ((char*) format, 2, c); | |
| 322 add_offset (mark_coverage, c); | |
| 323 add_offset (base_coverage, c); | |
| 324 | |
| 325 uint8_t count[] = { | |
| 326 (uint8_t) ((class_count >> 8) & 0xFF), | |
| 327 (uint8_t) (class_count & 0xFF), | |
| 328 }; | |
| 329 extend ((char*) count, 2, c); | |
| 330 | |
| 331 add_offset (mark_array, c); | |
| 332 add_offset (base_array, c); | |
| 333 | |
| 334 return c->pop_pack (false); | |
| 335 } | |
| 336 | |
| 337 template<int mark_count, | |
| 338 int class_count, | |
| 339 int base_count, | |
| 340 int table_count> | |
| 341 struct MarkBasePosBuffers | |
| 342 { | |
| 343 unsigned base_anchors[class_count * base_count]; | |
| 344 unsigned mark_anchors[mark_count]; | |
| 345 uint8_t anchor_buffers[class_count * base_count + 100]; | |
| 346 uint8_t class_buffer[class_count * 2]; | |
| 347 | |
| 348 MarkBasePosBuffers(hb_serialize_context_t* c) | |
| 349 { | |
| 350 for (unsigned i = 0; i < sizeof(anchor_buffers) / 2; i++) | |
| 351 { | |
| 352 OT::HBUINT16* value = (OT::HBUINT16*) (&anchor_buffers[2*i]); | |
| 353 *value = i; | |
| 354 } | |
| 355 | |
| 356 for (unsigned i = 0; i < class_count * base_count; i++) | |
| 357 { | |
| 358 base_anchors[i] = add_object ((char*) &anchor_buffers[i], 100, c); | |
| 359 if (i < class_count) { | |
| 360 class_buffer[i*2] = (uint8_t) ((i >> 8) & 0xFF); | |
| 361 class_buffer[i*2 + 1] = (uint8_t) (i & 0xFF); | |
| 362 } | |
| 363 } | |
| 364 | |
| 365 for (unsigned i = 0; i < mark_count; i++) | |
| 366 { | |
| 367 mark_anchors[i] = add_object ((char*) &anchor_buffers[i], 4, c); | |
| 368 } | |
| 369 } | |
| 370 | |
| 371 unsigned create_mark_base_pos_1 (unsigned table_index, hb_serialize_context_t* c) | |
| 372 { | |
| 373 unsigned class_per_table = class_count / table_count; | |
| 374 unsigned mark_per_class = mark_count / class_count; | |
| 375 unsigned start_class = class_per_table * table_index; | |
| 376 unsigned end_class = class_per_table * (table_index + 1) - 1; | |
| 377 | |
| 378 // baseArray | |
| 379 uint8_t base_count_buffer[] = { | |
| 380 (uint8_t) ((base_count >> 8) & 0xFF), | |
| 381 (uint8_t) (base_count & 0xFF), | |
| 382 | |
| 383 }; | |
| 384 start_object ((char*) base_count_buffer, 2, c); | |
| 385 for (unsigned base = 0; base < base_count; base++) | |
| 386 { | |
| 387 for (unsigned klass = start_class; klass <= end_class; klass++) | |
| 388 { | |
| 389 unsigned i = base * class_count + klass; | |
| 390 add_offset (base_anchors[i], c); | |
| 391 } | |
| 392 } | |
| 393 unsigned base_array = c->pop_pack (false); | |
| 394 | |
| 395 // markArray | |
| 396 unsigned num_marks = class_per_table * mark_per_class; | |
| 397 uint8_t mark_count_buffer[] = { | |
| 398 (uint8_t) ((num_marks >> 8) & 0xFF), | |
| 399 (uint8_t) (num_marks & 0xFF), | |
| 400 }; | |
| 401 start_object ((char*) mark_count_buffer, 2, c); | |
| 402 for (unsigned mark = 0; mark < mark_count; mark++) | |
| 403 { | |
| 404 unsigned klass = mark % class_count; | |
| 405 if (klass < start_class || klass > end_class) continue; | |
| 406 klass -= start_class; | |
| 407 | |
| 408 extend ((char*) &class_buffer[2 * klass], 2, c); | |
| 409 add_offset (mark_anchors[mark], c); | |
| 410 } | |
| 411 unsigned mark_array = c->pop_pack (false); | |
| 412 | |
| 413 // markCoverage | |
| 414 auto it = | |
| 415 + hb_range ((hb_codepoint_t) mark_count) | |
| 416 | hb_filter ([&] (hb_codepoint_t mark) { | |
| 417 unsigned klass = mark % class_count; | |
| 418 return klass >= class_per_table * table_index && | |
| 419 klass < class_per_table * (table_index + 1); | |
| 420 }) | |
| 421 ; | |
| 422 unsigned mark_coverage = add_coverage (it, c); | |
| 423 | |
| 424 // baseCoverage | |
| 425 unsigned base_coverage = add_coverage (10, 10 + base_count - 1, c); | |
| 426 | |
| 427 return add_mark_base_pos_1 (mark_coverage, | |
| 428 base_coverage, | |
| 429 mark_array, | |
| 430 base_array, | |
| 431 class_per_table, | |
| 432 c); | |
| 433 } | |
| 434 }; | |
| 435 | |
| 436 | |
| 437 | |
| 438 | |
| 439 | |
| 440 static void run_resolve_overflow_test (const char* name, | |
| 441 hb_serialize_context_t& overflowing, | |
| 442 hb_serialize_context_t& expected, | |
| 443 unsigned num_iterations = 0, | |
| 444 bool recalculate_extensions = false, | |
| 445 hb_tag_t tag = HB_TAG ('G', 'S', 'U', 'B')) | |
| 446 { | |
| 447 printf (">>> Testing overflowing resolution for %s\n", | |
| 448 name); | |
| 449 | |
| 450 graph_t graph (overflowing.object_graph ()); | |
| 451 graph_t expected_graph (expected.object_graph ()); | |
| 452 if (graph::will_overflow (expected_graph)) | |
| 453 { | |
| 454 expected_graph.assign_spaces (); | |
| 455 expected_graph.sort_shortest_distance (); | |
| 456 } | |
| 457 | |
| 458 // Check that overflow resolution succeeds | |
| 459 assert (overflowing.offset_overflow ()); | |
| 460 assert (hb_resolve_graph_overflows (tag, | |
| 461 num_iterations, | |
| 462 recalculate_extensions, | |
| 463 graph)); | |
| 464 | |
| 465 // Check the graphs can be serialized. | |
| 466 hb_blob_t* out = graph::serialize (graph); | |
| 467 assert (out); | |
| 468 hb_blob_destroy (out); | |
| 469 out = graph::serialize (expected_graph); | |
| 470 assert (out); | |
| 471 hb_blob_destroy (out); | |
| 472 | |
| 473 // Check the graphs are equivalent | |
| 474 graph.normalize (); | |
| 475 expected_graph.normalize (); | |
| 476 assert (graph == expected_graph); | |
| 477 } | |
| 478 | |
| 479 static void add_virtual_offset (unsigned id, | |
| 480 hb_serialize_context_t* c) | |
| 481 { | |
| 482 c->add_virtual_link (id); | |
| 483 } | |
| 484 | |
| 485 static void | |
| 486 populate_serializer_simple (hb_serialize_context_t* c) | |
| 487 { | |
| 488 c->start_serialize<char> (); | |
| 489 | |
| 490 unsigned obj_1 = add_object ("ghi", 3, c); | |
| 491 unsigned obj_2 = add_object ("def", 3, c); | |
| 492 | |
| 493 start_object ("abc", 3, c); | |
| 494 add_offset (obj_2, c); | |
| 495 add_offset (obj_1, c); | |
| 496 c->pop_pack (false); | |
| 497 | |
| 498 c->end_serialize(); | |
| 499 } | |
| 500 | |
| 501 static void | |
| 502 populate_serializer_with_overflow (hb_serialize_context_t* c) | |
| 503 { | |
| 504 std::string large_string(50000, 'a'); | |
| 505 c->start_serialize<char> (); | |
| 506 | |
| 507 unsigned obj_1 = add_object (large_string.c_str(), 10000, c); | |
| 508 unsigned obj_2 = add_object (large_string.c_str(), 20000, c); | |
| 509 unsigned obj_3 = add_object (large_string.c_str(), 50000, c); | |
| 510 | |
| 511 start_object ("abc", 3, c); | |
| 512 add_offset (obj_3, c); | |
| 513 add_offset (obj_2, c); | |
| 514 add_offset (obj_1, c); | |
| 515 c->pop_pack (false); | |
| 516 | |
| 517 c->end_serialize(); | |
| 518 } | |
| 519 | |
| 520 static void | |
| 521 populate_serializer_with_priority_overflow (hb_serialize_context_t* c) | |
| 522 { | |
| 523 std::string large_string(50000, 'a'); | |
| 524 c->start_serialize<char> (); | |
| 525 | |
| 526 unsigned obj_e = add_object ("e", 1, c); | |
| 527 unsigned obj_d = add_object ("d", 1, c); | |
| 528 | |
| 529 start_object (large_string.c_str (), 50000, c); | |
| 530 add_offset (obj_e, c); | |
| 531 unsigned obj_c = c->pop_pack (false); | |
| 532 | |
| 533 start_object (large_string.c_str (), 20000, c); | |
| 534 add_offset (obj_d, c); | |
| 535 unsigned obj_b = c->pop_pack (false); | |
| 536 | |
| 537 start_object ("a", 1, c); | |
| 538 add_offset (obj_b, c); | |
| 539 add_offset (obj_c, c); | |
| 540 c->pop_pack (false); | |
| 541 | |
| 542 c->end_serialize(); | |
| 543 } | |
| 544 | |
| 545 static void | |
| 546 populate_serializer_with_priority_overflow_expected (hb_serialize_context_t* c) | |
| 547 { | |
| 548 std::string large_string(50000, 'a'); | |
| 549 c->start_serialize<char> (); | |
| 550 | |
| 551 unsigned obj_e = add_object ("e", 1, c); | |
| 552 | |
| 553 start_object (large_string.c_str (), 50000, c); | |
| 554 add_offset (obj_e, c); | |
| 555 unsigned obj_c = c->pop_pack (false); | |
| 556 | |
| 557 unsigned obj_d = add_object ("d", 1, c); | |
| 558 | |
| 559 start_object (large_string.c_str (), 20000, c); | |
| 560 add_offset (obj_d, c); | |
| 561 unsigned obj_b = c->pop_pack (false); | |
| 562 | |
| 563 start_object ("a", 1, c); | |
| 564 add_offset (obj_b, c); | |
| 565 add_offset (obj_c, c); | |
| 566 c->pop_pack (false); | |
| 567 | |
| 568 c->end_serialize(); | |
| 569 } | |
| 570 | |
| 571 | |
| 572 static void | |
| 573 populate_serializer_with_dedup_overflow (hb_serialize_context_t* c) | |
| 574 { | |
| 575 std::string large_string(70000, 'a'); | |
| 576 c->start_serialize<char> (); | |
| 577 | |
| 578 unsigned obj_1 = add_object ("def", 3, c); | |
| 579 | |
| 580 start_object (large_string.c_str(), 60000, c); | |
| 581 add_offset (obj_1, c); | |
| 582 unsigned obj_2 = c->pop_pack (false); | |
| 583 | |
| 584 start_object (large_string.c_str(), 10000, c); | |
| 585 add_offset (obj_2, c); | |
| 586 add_offset (obj_1, c); | |
| 587 c->pop_pack (false); | |
| 588 | |
| 589 c->end_serialize(); | |
| 590 } | |
| 591 | |
| 592 static void | |
| 593 populate_serializer_with_isolation_overflow (hb_serialize_context_t* c) | |
| 594 { | |
| 595 std::string large_string(70000, 'a'); | |
| 596 c->start_serialize<char> (); | |
| 597 | |
| 598 unsigned obj_4 = add_object ("4", 1, c); | |
| 599 | |
| 600 start_object (large_string.c_str(), 60000, c); | |
| 601 add_offset (obj_4, c); | |
| 602 unsigned obj_3 = c->pop_pack (false); | |
| 603 | |
| 604 start_object (large_string.c_str(), 10000, c); | |
| 605 add_offset (obj_4, c); | |
| 606 unsigned obj_2 = c->pop_pack (false); | |
| 607 | |
| 608 start_object ("1", 1, c); | |
| 609 add_wide_offset (obj_3, c); | |
| 610 add_offset (obj_2, c); | |
| 611 c->pop_pack (false); | |
| 612 | |
| 613 c->end_serialize(); | |
| 614 } | |
| 615 | |
| 616 static void | |
| 617 populate_serializer_with_isolation_overflow_complex (hb_serialize_context_t* c) | |
| 618 { | |
| 619 std::string large_string(70000, 'a'); | |
| 620 c->start_serialize<char> (); | |
| 621 | |
| 622 unsigned obj_f = add_object ("f", 1, c); | |
| 623 | |
| 624 start_object ("e", 1, c); | |
| 625 add_offset (obj_f, c); | |
| 626 unsigned obj_e = c->pop_pack (false); | |
| 627 | |
| 628 start_object ("c", 1, c); | |
| 629 add_offset (obj_e, c); | |
| 630 unsigned obj_c = c->pop_pack (false); | |
| 631 | |
| 632 start_object ("d", 1, c); | |
| 633 add_offset (obj_e, c); | |
| 634 unsigned obj_d = c->pop_pack (false); | |
| 635 | |
| 636 start_object (large_string.c_str(), 60000, c); | |
| 637 add_offset (obj_d, c); | |
| 638 unsigned obj_h = c->pop_pack (false); | |
| 639 | |
| 640 start_object (large_string.c_str(), 60000, c); | |
| 641 add_offset (obj_c, c); | |
| 642 add_offset (obj_h, c); | |
| 643 unsigned obj_b = c->pop_pack (false); | |
| 644 | |
| 645 start_object (large_string.c_str(), 10000, c); | |
| 646 add_offset (obj_d, c); | |
| 647 unsigned obj_g = c->pop_pack (false); | |
| 648 | |
| 649 start_object (large_string.c_str(), 11000, c); | |
| 650 add_offset (obj_d, c); | |
| 651 unsigned obj_i = c->pop_pack (false); | |
| 652 | |
| 653 start_object ("a", 1, c); | |
| 654 add_wide_offset (obj_b, c); | |
| 655 add_offset (obj_g, c); | |
| 656 add_offset (obj_i, c); | |
| 657 c->pop_pack (false); | |
| 658 | |
| 659 c->end_serialize(); | |
| 660 } | |
| 661 | |
| 662 static void | |
| 663 populate_serializer_with_isolation_overflow_complex_expected (hb_serialize_context_t* c) | |
| 664 { | |
| 665 std::string large_string(70000, 'a'); | |
| 666 c->start_serialize<char> (); | |
| 667 | |
| 668 | |
| 669 // space 1 | |
| 670 | |
| 671 unsigned obj_f_prime = add_object ("f", 1, c); | |
| 672 | |
| 673 start_object ("e", 1, c); | |
| 674 add_offset (obj_f_prime, c); | |
| 675 unsigned obj_e_prime = c->pop_pack (false); | |
| 676 | |
| 677 start_object ("d", 1, c); | |
| 678 add_offset (obj_e_prime, c); | |
| 679 unsigned obj_d_prime = c->pop_pack (false); | |
| 680 | |
| 681 start_object (large_string.c_str(), 60000, c); | |
| 682 add_offset (obj_d_prime, c); | |
| 683 unsigned obj_h = c->pop_pack (false); | |
| 684 | |
| 685 start_object ("c", 1, c); | |
| 686 add_offset (obj_e_prime, c); | |
| 687 unsigned obj_c = c->pop_pack (false); | |
| 688 | |
| 689 start_object (large_string.c_str(), 60000, c); | |
| 690 add_offset (obj_c, c); | |
| 691 add_offset (obj_h, c); | |
| 692 unsigned obj_b = c->pop_pack (false); | |
| 693 | |
| 694 // space 0 | |
| 695 | |
| 696 unsigned obj_f = add_object ("f", 1, c); | |
| 697 | |
| 698 start_object ("e", 1, c); | |
| 699 add_offset (obj_f, c); | |
| 700 unsigned obj_e = c->pop_pack (false); | |
| 701 | |
| 702 | |
| 703 start_object ("d", 1, c); | |
| 704 add_offset (obj_e, c); | |
| 705 unsigned obj_d = c->pop_pack (false); | |
| 706 | |
| 707 start_object (large_string.c_str(), 11000, c); | |
| 708 add_offset (obj_d, c); | |
| 709 unsigned obj_i = c->pop_pack (false); | |
| 710 | |
| 711 start_object (large_string.c_str(), 10000, c); | |
| 712 add_offset (obj_d, c); | |
| 713 unsigned obj_g = c->pop_pack (false); | |
| 714 | |
| 715 start_object ("a", 1, c); | |
| 716 add_wide_offset (obj_b, c); | |
| 717 add_offset (obj_g, c); | |
| 718 add_offset (obj_i, c); | |
| 719 c->pop_pack (false); | |
| 720 | |
| 721 c->end_serialize(); | |
| 722 } | |
| 723 | |
| 724 static void | |
| 725 populate_serializer_with_isolation_overflow_spaces (hb_serialize_context_t* c) | |
| 726 { | |
| 727 std::string large_string(70000, 'a'); | |
| 728 c->start_serialize<char> (); | |
| 729 | |
| 730 unsigned obj_d = add_object ("f", 1, c); | |
| 731 unsigned obj_e = add_object ("f", 1, c); | |
| 732 | |
| 733 start_object (large_string.c_str(), 60000, c); | |
| 734 add_offset (obj_d, c); | |
| 735 unsigned obj_b = c->pop_pack (); | |
| 736 | |
| 737 start_object (large_string.c_str(), 60000, c); | |
| 738 add_offset (obj_e, c); | |
| 739 unsigned obj_c = c->pop_pack (); | |
| 740 | |
| 741 | |
| 742 start_object ("a", 1, c); | |
| 743 add_wide_offset (obj_b, c); | |
| 744 add_wide_offset (obj_c, c); | |
| 745 c->pop_pack (); | |
| 746 | |
| 747 c->end_serialize(); | |
| 748 } | |
| 749 | |
| 750 static void | |
| 751 populate_serializer_spaces (hb_serialize_context_t* c, bool with_overflow) | |
| 752 { | |
| 753 std::string large_string(70000, 'a'); | |
| 754 c->start_serialize<char> (); | |
| 755 | |
| 756 unsigned obj_i; | |
| 757 | |
| 758 if (with_overflow) | |
| 759 obj_i = add_object ("i", 1, c); | |
| 760 | |
| 761 // Space 2 | |
| 762 unsigned obj_h = add_object ("h", 1, c); | |
| 763 | |
| 764 start_object (large_string.c_str(), 30000, c); | |
| 765 add_offset (obj_h, c); | |
| 766 unsigned obj_e = c->pop_pack (false); | |
| 767 | |
| 768 start_object ("b", 1, c); | |
| 769 add_offset (obj_e, c); | |
| 770 unsigned obj_b = c->pop_pack (false); | |
| 771 | |
| 772 // Space 1 | |
| 773 if (!with_overflow) | |
| 774 obj_i = add_object ("i", 1, c); | |
| 775 | |
| 776 start_object (large_string.c_str(), 30000, c); | |
| 777 add_offset (obj_i, c); | |
| 778 unsigned obj_g = c->pop_pack (false); | |
| 779 | |
| 780 start_object (large_string.c_str(), 30000, c); | |
| 781 add_offset (obj_i, c); | |
| 782 unsigned obj_f = c->pop_pack (false); | |
| 783 | |
| 784 start_object ("d", 1, c); | |
| 785 add_offset (obj_g, c); | |
| 786 unsigned obj_d = c->pop_pack (false); | |
| 787 | |
| 788 start_object ("c", 1, c); | |
| 789 add_offset (obj_f, c); | |
| 790 unsigned obj_c = c->pop_pack (false); | |
| 791 | |
| 792 start_object ("a", 1, c); | |
| 793 add_wide_offset (obj_b, c); | |
| 794 add_wide_offset (obj_c, c); | |
| 795 add_wide_offset (obj_d, c); | |
| 796 c->pop_pack (false); | |
| 797 | |
| 798 c->end_serialize(); | |
| 799 } | |
| 800 | |
| 801 static void | |
| 802 populate_serializer_spaces_16bit_connection (hb_serialize_context_t* c) | |
| 803 { | |
| 804 std::string large_string(70000, 'a'); | |
| 805 c->start_serialize<char> (); | |
| 806 | |
| 807 unsigned obj_g = add_object ("g", 1, c); | |
| 808 unsigned obj_h = add_object ("h", 1, c); | |
| 809 | |
| 810 start_object (large_string.c_str (), 40000, c); | |
| 811 add_offset (obj_g, c); | |
| 812 unsigned obj_e = c->pop_pack (false); | |
| 813 | |
| 814 start_object (large_string.c_str (), 40000, c); | |
| 815 add_offset (obj_h, c); | |
| 816 unsigned obj_f = c->pop_pack (false); | |
| 817 | |
| 818 start_object ("c", 1, c); | |
| 819 add_offset (obj_e, c); | |
| 820 unsigned obj_c = c->pop_pack (false); | |
| 821 | |
| 822 start_object ("d", 1, c); | |
| 823 add_offset (obj_f, c); | |
| 824 unsigned obj_d = c->pop_pack (false); | |
| 825 | |
| 826 start_object ("b", 1, c); | |
| 827 add_offset (obj_e, c); | |
| 828 add_offset (obj_h, c); | |
| 829 unsigned obj_b = c->pop_pack (false); | |
| 830 | |
| 831 start_object ("a", 1, c); | |
| 832 add_offset (obj_b, c); | |
| 833 add_wide_offset (obj_c, c); | |
| 834 add_wide_offset (obj_d, c); | |
| 835 c->pop_pack (false); | |
| 836 | |
| 837 c->end_serialize(); | |
| 838 } | |
| 839 | |
| 840 static void | |
| 841 populate_serializer_spaces_16bit_connection_expected (hb_serialize_context_t* c) | |
| 842 { | |
| 843 std::string large_string(70000, 'a'); | |
| 844 c->start_serialize<char> (); | |
| 845 | |
| 846 unsigned obj_g_prime = add_object ("g", 1, c); | |
| 847 | |
| 848 start_object (large_string.c_str (), 40000, c); | |
| 849 add_offset (obj_g_prime, c); | |
| 850 unsigned obj_e_prime = c->pop_pack (false); | |
| 851 | |
| 852 start_object ("c", 1, c); | |
| 853 add_offset (obj_e_prime, c); | |
| 854 unsigned obj_c = c->pop_pack (false); | |
| 855 | |
| 856 unsigned obj_h_prime = add_object ("h", 1, c); | |
| 857 | |
| 858 start_object (large_string.c_str (), 40000, c); | |
| 859 add_offset (obj_h_prime, c); | |
| 860 unsigned obj_f = c->pop_pack (false); | |
| 861 | |
| 862 start_object ("d", 1, c); | |
| 863 add_offset (obj_f, c); | |
| 864 unsigned obj_d = c->pop_pack (false); | |
| 865 | |
| 866 unsigned obj_g = add_object ("g", 1, c); | |
| 867 | |
| 868 start_object (large_string.c_str (), 40000, c); | |
| 869 add_offset (obj_g, c); | |
| 870 unsigned obj_e = c->pop_pack (false); | |
| 871 | |
| 872 unsigned obj_h = add_object ("h", 1, c); | |
| 873 | |
| 874 start_object ("b", 1, c); | |
| 875 add_offset (obj_e, c); | |
| 876 add_offset (obj_h, c); | |
| 877 unsigned obj_b = c->pop_pack (false); | |
| 878 | |
| 879 start_object ("a", 1, c); | |
| 880 add_offset (obj_b, c); | |
| 881 add_wide_offset (obj_c, c); | |
| 882 add_wide_offset (obj_d, c); | |
| 883 c->pop_pack (false); | |
| 884 | |
| 885 c->end_serialize (); | |
| 886 } | |
| 887 | |
| 888 static void | |
| 889 populate_serializer_short_and_wide_subgraph_root (hb_serialize_context_t* c) | |
| 890 { | |
| 891 std::string large_string(70000, 'a'); | |
| 892 c->start_serialize<char> (); | |
| 893 | |
| 894 unsigned obj_e = add_object ("e", 1, c); | |
| 895 | |
| 896 start_object (large_string.c_str (), 40000, c); | |
| 897 add_offset (obj_e, c); | |
| 898 unsigned obj_c = c->pop_pack (false); | |
| 899 | |
| 900 start_object (large_string.c_str (), 40000, c); | |
| 901 add_offset (obj_c, c); | |
| 902 unsigned obj_d = c->pop_pack (false); | |
| 903 | |
| 904 start_object ("b", 1, c); | |
| 905 add_offset (obj_c, c); | |
| 906 add_offset (obj_e, c); | |
| 907 unsigned obj_b = c->pop_pack (false); | |
| 908 | |
| 909 start_object ("a", 1, c); | |
| 910 add_offset (obj_b, c); | |
| 911 add_wide_offset (obj_c, c); | |
| 912 add_wide_offset (obj_d, c); | |
| 913 c->pop_pack (false); | |
| 914 | |
| 915 c->end_serialize(); | |
| 916 } | |
| 917 | |
| 918 static void | |
| 919 populate_serializer_short_and_wide_subgraph_root_expected (hb_serialize_context_t* c) | |
| 920 { | |
| 921 std::string large_string(70000, 'a'); | |
| 922 c->start_serialize<char> (); | |
| 923 | |
| 924 unsigned obj_e_prime = add_object ("e", 1, c); | |
| 925 | |
| 926 start_object (large_string.c_str (), 40000, c); | |
| 927 add_offset (obj_e_prime, c); | |
| 928 unsigned obj_c_prime = c->pop_pack (false); | |
| 929 | |
| 930 start_object (large_string.c_str (), 40000, c); | |
| 931 add_offset (obj_c_prime, c); | |
| 932 unsigned obj_d = c->pop_pack (false); | |
| 933 | |
| 934 unsigned obj_e = add_object ("e", 1, c); | |
| 935 | |
| 936 start_object (large_string.c_str (), 40000, c); | |
| 937 add_offset (obj_e, c); | |
| 938 unsigned obj_c = c->pop_pack (false); | |
| 939 | |
| 940 | |
| 941 start_object ("b", 1, c); | |
| 942 add_offset (obj_c, c); | |
| 943 add_offset (obj_e, c); | |
| 944 unsigned obj_b = c->pop_pack (false); | |
| 945 | |
| 946 start_object ("a", 1, c); | |
| 947 add_offset (obj_b, c); | |
| 948 add_wide_offset (obj_c_prime, c); | |
| 949 add_wide_offset (obj_d, c); | |
| 950 c->pop_pack (false); | |
| 951 | |
| 952 c->end_serialize(); | |
| 953 } | |
| 954 | |
| 955 static void | |
| 956 populate_serializer_with_split_spaces (hb_serialize_context_t* c) | |
| 957 { | |
| 958 // Overflow needs to be resolved by splitting the single space | |
| 959 std::string large_string(70000, 'a'); | |
| 960 c->start_serialize<char> (); | |
| 961 | |
| 962 unsigned obj_f = add_object ("f", 1, c); | |
| 963 | |
| 964 start_object (large_string.c_str(), 40000, c); | |
| 965 add_offset (obj_f, c); | |
| 966 unsigned obj_d = c->pop_pack (false); | |
| 967 | |
| 968 start_object (large_string.c_str(), 40000, c); | |
| 969 add_offset (obj_f, c); | |
| 970 unsigned obj_e = c->pop_pack (false); | |
| 971 | |
| 972 start_object ("b", 1, c); | |
| 973 add_offset (obj_d, c); | |
| 974 unsigned obj_b = c->pop_pack (false); | |
| 975 | |
| 976 start_object ("c", 1, c); | |
| 977 add_offset (obj_e, c); | |
| 978 unsigned obj_c = c->pop_pack (false); | |
| 979 | |
| 980 start_object ("a", 1, c); | |
| 981 add_wide_offset (obj_b, c); | |
| 982 add_wide_offset (obj_c, c); | |
| 983 c->pop_pack (false); | |
| 984 | |
| 985 c->end_serialize(); | |
| 986 } | |
| 987 | |
| 988 static void | |
| 989 populate_serializer_with_split_spaces_2 (hb_serialize_context_t* c) | |
| 990 { | |
| 991 // Overflow needs to be resolved by splitting the single space | |
| 992 std::string large_string(70000, 'a'); | |
| 993 c->start_serialize<char> (); | |
| 994 | |
| 995 unsigned obj_f = add_object ("f", 1, c); | |
| 996 | |
| 997 start_object (large_string.c_str(), 40000, c); | |
| 998 add_offset (obj_f, c); | |
| 999 unsigned obj_d = c->pop_pack (false); | |
| 1000 | |
| 1001 start_object (large_string.c_str(), 40000, c); | |
| 1002 add_offset (obj_f, c); | |
| 1003 unsigned obj_e = c->pop_pack (false); | |
| 1004 | |
| 1005 start_object ("b", 1, c); | |
| 1006 add_offset (obj_d, c); | |
| 1007 unsigned obj_b = c->pop_pack (false); | |
| 1008 | |
| 1009 start_object ("c", 1, c); | |
| 1010 add_offset (obj_e, c); | |
| 1011 unsigned obj_c = c->pop_pack (false); | |
| 1012 | |
| 1013 start_object ("a", 1, c); | |
| 1014 add_offset (obj_b, c); | |
| 1015 add_wide_offset (obj_b, c); | |
| 1016 add_wide_offset (obj_c, c); | |
| 1017 c->pop_pack (false); | |
| 1018 | |
| 1019 c->end_serialize(); | |
| 1020 } | |
| 1021 | |
| 1022 static void | |
| 1023 populate_serializer_with_split_spaces_expected (hb_serialize_context_t* c) | |
| 1024 { | |
| 1025 // Overflow needs to be resolved by splitting the single space | |
| 1026 | |
| 1027 std::string large_string(70000, 'a'); | |
| 1028 c->start_serialize<char> (); | |
| 1029 | |
| 1030 unsigned obj_f_prime = add_object ("f", 1, c); | |
| 1031 | |
| 1032 start_object (large_string.c_str(), 40000, c); | |
| 1033 add_offset (obj_f_prime, c); | |
| 1034 unsigned obj_d = c->pop_pack (false); | |
| 1035 | |
| 1036 start_object ("b", 1, c); | |
| 1037 add_offset (obj_d, c); | |
| 1038 unsigned obj_b = c->pop_pack (false); | |
| 1039 | |
| 1040 unsigned obj_f = add_object ("f", 1, c); | |
| 1041 | |
| 1042 start_object (large_string.c_str(), 40000, c); | |
| 1043 add_offset (obj_f, c); | |
| 1044 unsigned obj_e = c->pop_pack (false); | |
| 1045 | |
| 1046 start_object ("c", 1, c); | |
| 1047 add_offset (obj_e, c); | |
| 1048 unsigned obj_c = c->pop_pack (false); | |
| 1049 | |
| 1050 start_object ("a", 1, c); | |
| 1051 add_wide_offset (obj_b, c); | |
| 1052 add_wide_offset (obj_c, c); | |
| 1053 c->pop_pack (false); | |
| 1054 | |
| 1055 c->end_serialize(); | |
| 1056 } | |
| 1057 | |
| 1058 static void | |
| 1059 populate_serializer_with_split_spaces_expected_2 (hb_serialize_context_t* c) | |
| 1060 { | |
| 1061 // Overflow needs to be resolved by splitting the single space | |
| 1062 | |
| 1063 std::string large_string(70000, 'a'); | |
| 1064 c->start_serialize<char> (); | |
| 1065 | |
| 1066 // Space 2 | |
| 1067 | |
| 1068 unsigned obj_f_double_prime = add_object ("f", 1, c); | |
| 1069 | |
| 1070 start_object (large_string.c_str(), 40000, c); | |
| 1071 add_offset (obj_f_double_prime, c); | |
| 1072 unsigned obj_d_prime = c->pop_pack (false); | |
| 1073 | |
| 1074 start_object ("b", 1, c); | |
| 1075 add_offset (obj_d_prime, c); | |
| 1076 unsigned obj_b_prime = c->pop_pack (false); | |
| 1077 | |
| 1078 // Space 1 | |
| 1079 | |
| 1080 unsigned obj_f_prime = add_object ("f", 1, c); | |
| 1081 | |
| 1082 start_object (large_string.c_str(), 40000, c); | |
| 1083 add_offset (obj_f_prime, c); | |
| 1084 unsigned obj_e = c->pop_pack (false); | |
| 1085 | |
| 1086 start_object ("c", 1, c); | |
| 1087 add_offset (obj_e, c); | |
| 1088 unsigned obj_c = c->pop_pack (false); | |
| 1089 | |
| 1090 // Space 0 | |
| 1091 | |
| 1092 unsigned obj_f = add_object ("f", 1, c); | |
| 1093 | |
| 1094 start_object (large_string.c_str(), 40000, c); | |
| 1095 add_offset (obj_f, c); | |
| 1096 unsigned obj_d = c->pop_pack (false); | |
| 1097 | |
| 1098 start_object ("b", 1, c); | |
| 1099 add_offset (obj_d, c); | |
| 1100 unsigned obj_b = c->pop_pack (false); | |
| 1101 | |
| 1102 // Root | |
| 1103 start_object ("a", 1, c); | |
| 1104 add_offset (obj_b, c); | |
| 1105 add_wide_offset (obj_b_prime, c); | |
| 1106 add_wide_offset (obj_c, c); | |
| 1107 c->pop_pack (false); | |
| 1108 | |
| 1109 c->end_serialize(); | |
| 1110 } | |
| 1111 | |
| 1112 static void | |
| 1113 populate_serializer_complex_2 (hb_serialize_context_t* c) | |
| 1114 { | |
| 1115 c->start_serialize<char> (); | |
| 1116 | |
| 1117 unsigned obj_5 = add_object ("mn", 2, c); | |
| 1118 | |
| 1119 unsigned obj_4 = add_object ("jkl", 3, c); | |
| 1120 | |
| 1121 start_object ("ghi", 3, c); | |
| 1122 add_offset (obj_4, c); | |
| 1123 unsigned obj_3 = c->pop_pack (false); | |
| 1124 | |
| 1125 start_object ("def", 3, c); | |
| 1126 add_offset (obj_3, c); | |
| 1127 unsigned obj_2 = c->pop_pack (false); | |
| 1128 | |
| 1129 start_object ("abc", 3, c); | |
| 1130 add_offset (obj_2, c); | |
| 1131 add_offset (obj_4, c); | |
| 1132 add_offset (obj_5, c); | |
| 1133 c->pop_pack (false); | |
| 1134 | |
| 1135 c->end_serialize(); | |
| 1136 } | |
| 1137 | |
| 1138 static void | |
| 1139 populate_serializer_complex_3 (hb_serialize_context_t* c) | |
| 1140 { | |
| 1141 c->start_serialize<char> (); | |
| 1142 | |
| 1143 unsigned obj_6 = add_object ("opqrst", 6, c); | |
| 1144 | |
| 1145 unsigned obj_5 = add_object ("mn", 2, c); | |
| 1146 | |
| 1147 start_object ("jkl", 3, c); | |
| 1148 add_offset (obj_6, c); | |
| 1149 unsigned obj_4 = c->pop_pack (false); | |
| 1150 | |
| 1151 start_object ("ghi", 3, c); | |
| 1152 add_offset (obj_4, c); | |
| 1153 unsigned obj_3 = c->pop_pack (false); | |
| 1154 | |
| 1155 start_object ("def", 3, c); | |
| 1156 add_offset (obj_3, c); | |
| 1157 unsigned obj_2 = c->pop_pack (false); | |
| 1158 | |
| 1159 start_object ("abc", 3, c); | |
| 1160 add_offset (obj_2, c); | |
| 1161 add_offset (obj_4, c); | |
| 1162 add_offset (obj_5, c); | |
| 1163 c->pop_pack (false); | |
| 1164 | |
| 1165 c->end_serialize(); | |
| 1166 } | |
| 1167 | |
| 1168 static void | |
| 1169 populate_serializer_virtual_link (hb_serialize_context_t* c) | |
| 1170 { | |
| 1171 c->start_serialize<char> (); | |
| 1172 | |
| 1173 unsigned obj_d = add_object ("d", 1, c); | |
| 1174 | |
| 1175 start_object ("b", 1, c); | |
| 1176 add_offset (obj_d, c); | |
| 1177 unsigned obj_b = c->pop_pack (false); | |
| 1178 | |
| 1179 start_object ("e", 1, c); | |
| 1180 add_virtual_offset (obj_b, c); | |
| 1181 unsigned obj_e = c->pop_pack (false); | |
| 1182 | |
| 1183 start_object ("c", 1, c); | |
| 1184 add_offset (obj_e, c); | |
| 1185 unsigned obj_c = c->pop_pack (false); | |
| 1186 | |
| 1187 start_object ("a", 1, c); | |
| 1188 add_offset (obj_b, c); | |
| 1189 add_offset (obj_c, c); | |
| 1190 c->pop_pack (false); | |
| 1191 | |
| 1192 c->end_serialize(); | |
| 1193 } | |
| 1194 | |
| 1195 static void | |
| 1196 populate_serializer_with_24_and_32_bit_offsets (hb_serialize_context_t* c) | |
| 1197 { | |
| 1198 std::string large_string(60000, 'a'); | |
| 1199 c->start_serialize<char> (); | |
| 1200 | |
| 1201 unsigned obj_f = add_object ("f", 1, c); | |
| 1202 unsigned obj_g = add_object ("g", 1, c); | |
| 1203 unsigned obj_j = add_object ("j", 1, c); | |
| 1204 unsigned obj_k = add_object ("k", 1, c); | |
| 1205 | |
| 1206 start_object (large_string.c_str (), 40000, c); | |
| 1207 add_offset (obj_f, c); | |
| 1208 unsigned obj_c = c->pop_pack (false); | |
| 1209 | |
| 1210 start_object (large_string.c_str (), 40000, c); | |
| 1211 add_offset (obj_g, c); | |
| 1212 unsigned obj_d = c->pop_pack (false); | |
| 1213 | |
| 1214 start_object (large_string.c_str (), 40000, c); | |
| 1215 add_offset (obj_j, c); | |
| 1216 unsigned obj_h = c->pop_pack (false); | |
| 1217 | |
| 1218 start_object (large_string.c_str (), 40000, c); | |
| 1219 add_offset (obj_k, c); | |
| 1220 unsigned obj_i = c->pop_pack (false); | |
| 1221 | |
| 1222 start_object ("e", 1, c); | |
| 1223 add_wide_offset (obj_h, c); | |
| 1224 add_wide_offset (obj_i, c); | |
| 1225 unsigned obj_e = c->pop_pack (false); | |
| 1226 | |
| 1227 start_object ("b", 1, c); | |
| 1228 add_24_offset (obj_c, c); | |
| 1229 add_24_offset (obj_d, c); | |
| 1230 add_24_offset (obj_e, c); | |
| 1231 unsigned obj_b = c->pop_pack (false); | |
| 1232 | |
| 1233 start_object ("a", 1, c); | |
| 1234 add_24_offset (obj_b, c); | |
| 1235 c->pop_pack (false); | |
| 1236 | |
| 1237 c->end_serialize(); | |
| 1238 } | |
| 1239 | |
| 1240 static void | |
| 1241 populate_serializer_with_extension_promotion (hb_serialize_context_t* c, | |
| 1242 int num_extensions = 0) | |
| 1243 { | |
| 1244 constexpr int num_lookups = 5; | |
| 1245 constexpr int num_subtables = num_lookups * 2; | |
| 1246 unsigned int lookups[num_lookups]; | |
| 1247 unsigned int subtables[num_subtables]; | |
| 1248 unsigned int extensions[num_subtables]; | |
| 1249 | |
| 1250 std::string large_string(60000, 'a'); | |
| 1251 c->start_serialize<char> (); | |
| 1252 | |
| 1253 | |
| 1254 for (int i = num_subtables - 1; i >= 0; i--) | |
| 1255 subtables[i] = add_object(large_string.c_str (), 15000, c); | |
| 1256 | |
| 1257 for (int i = num_subtables - 1; | |
| 1258 i >= (num_lookups - num_extensions) * 2; | |
| 1259 i--) | |
| 1260 { | |
| 1261 unsigned ext_index = i - (num_lookups - num_extensions) * 2; | |
| 1262 unsigned subtable_index = num_subtables - ext_index - 1; | |
| 1263 extensions[i] = add_extension (subtables[subtable_index], 5, c); | |
| 1264 } | |
| 1265 | |
| 1266 for (int i = num_lookups - 1; i >= 0; i--) | |
| 1267 { | |
| 1268 bool is_ext = (i >= (num_lookups - num_extensions)); | |
| 1269 | |
| 1270 start_lookup (is_ext ? (char) 7 : (char) 5, | |
| 1271 2, | |
| 1272 c); | |
| 1273 | |
| 1274 if (is_ext) { | |
| 1275 add_offset (extensions[i * 2], c); | |
| 1276 add_offset (extensions[i * 2 + 1], c); | |
| 1277 } else { | |
| 1278 add_offset (subtables[i * 2], c); | |
| 1279 add_offset (subtables[i * 2 + 1], c); | |
| 1280 } | |
| 1281 | |
| 1282 lookups[i] = finish_lookup (c); | |
| 1283 } | |
| 1284 | |
| 1285 unsigned lookup_list = add_lookup_list (lookups, num_lookups, c); | |
| 1286 | |
| 1287 add_gsubgpos_header (lookup_list, c); | |
| 1288 | |
| 1289 c->end_serialize(); | |
| 1290 } | |
| 1291 | |
| 1292 template<int num_pair_pos_1, int num_pair_set> | |
| 1293 static void | |
| 1294 populate_serializer_with_large_pair_pos_1 (hb_serialize_context_t* c, | |
| 1295 bool as_extension = false) | |
| 1296 { | |
| 1297 std::string large_string(60000, 'a'); | |
| 1298 c->start_serialize<char> (); | |
| 1299 | |
| 1300 constexpr int total_pair_set = num_pair_pos_1 * num_pair_set; | |
| 1301 unsigned pair_set[total_pair_set]; | |
| 1302 unsigned coverage[num_pair_pos_1]; | |
| 1303 unsigned pair_pos_1[num_pair_pos_1]; | |
| 1304 | |
| 1305 for (int i = num_pair_pos_1 - 1; i >= 0; i--) | |
| 1306 { | |
| 1307 for (int j = (i + 1) * num_pair_set - 1; j >= i * num_pair_set; j--) | |
| 1308 pair_set[j] = add_object (large_string.c_str (), 30000 + j, c); | |
| 1309 | |
| 1310 coverage[i] = add_coverage (i * num_pair_set, | |
| 1311 (i + 1) * num_pair_set - 1, c); | |
| 1312 | |
| 1313 pair_pos_1[i] = add_pair_pos_1 (&pair_set[i * num_pair_set], | |
| 1314 num_pair_set, | |
| 1315 coverage[i], | |
| 1316 c); | |
| 1317 } | |
| 1318 | |
| 1319 unsigned pair_pos_2 = add_object (large_string.c_str(), 200, c); | |
| 1320 | |
| 1321 if (as_extension) { | |
| 1322 pair_pos_2 = add_extension (pair_pos_2, 2, c); | |
| 1323 for (int i = num_pair_pos_1 - 1; i >= 0; i--) | |
| 1324 pair_pos_1[i] = add_extension (pair_pos_1[i], 2, c); | |
| 1325 } | |
| 1326 | |
| 1327 start_lookup (as_extension ? 9 : 2, 1 + num_pair_pos_1, c); | |
| 1328 | |
| 1329 for (int i = 0; i < num_pair_pos_1; i++) | |
| 1330 add_offset (pair_pos_1[i], c); | |
| 1331 add_offset (pair_pos_2, c); | |
| 1332 | |
| 1333 unsigned lookup = finish_lookup (c); | |
| 1334 | |
| 1335 unsigned lookup_list = add_lookup_list (&lookup, 1, c); | |
| 1336 | |
| 1337 add_gsubgpos_header (lookup_list, c); | |
| 1338 | |
| 1339 c->end_serialize(); | |
| 1340 } | |
| 1341 | |
| 1342 template<int num_pair_pos_2, int num_class_1, int num_class_2> | |
| 1343 static void | |
| 1344 populate_serializer_with_large_pair_pos_2 (hb_serialize_context_t* c, | |
| 1345 bool as_extension = false, | |
| 1346 bool with_device_tables = false, | |
| 1347 bool extra_table = true) | |
| 1348 { | |
| 1349 std::string large_string(100000, 'a'); | |
| 1350 c->start_serialize<char> (); | |
| 1351 | |
| 1352 unsigned coverage[num_pair_pos_2]; | |
| 1353 unsigned class_def_1[num_pair_pos_2]; | |
| 1354 unsigned class_def_2[num_pair_pos_2]; | |
| 1355 unsigned pair_pos_2[num_pair_pos_2]; | |
| 1356 | |
| 1357 unsigned* device_tables = (unsigned*) calloc (num_pair_pos_2 * num_class_1 * num_class_2, | |
| 1358 sizeof(unsigned)); | |
| 1359 | |
| 1360 // Total glyphs = num_class_1 * num_pair_pos_2 | |
| 1361 for (int i = num_pair_pos_2 - 1; i >= 0; i--) | |
| 1362 { | |
| 1363 unsigned start_glyph = 5 + i * num_class_1; | |
| 1364 if (num_class_2 >= num_class_1) | |
| 1365 { | |
| 1366 class_def_2[i] = add_class_def (11, | |
| 1367 10 + num_class_2, c); | |
| 1368 class_def_1[i] = add_class_def (start_glyph + 1, | |
| 1369 start_glyph + num_class_1, | |
| 1370 c); | |
| 1371 } else { | |
| 1372 class_def_1[i] = add_class_def (start_glyph + 1, | |
| 1373 start_glyph + num_class_1, | |
| 1374 c); | |
| 1375 class_def_2[i] = add_class_def (11, | |
| 1376 10 + num_class_2, c); | |
| 1377 } | |
| 1378 | |
| 1379 coverage[i] = add_coverage (start_glyph, | |
| 1380 start_glyph + num_class_1 - 1, | |
| 1381 c); | |
| 1382 | |
| 1383 if (with_device_tables) | |
| 1384 { | |
| 1385 for(int j = (i + 1) * num_class_1 * num_class_2 - 1; | |
| 1386 j >= i * num_class_1 * num_class_2; | |
| 1387 j--) | |
| 1388 { | |
| 1389 uint8_t table[] = { | |
| 1390 (uint8_t) ((j >> 8) & 0xFF), | |
| 1391 (uint8_t) (j & 0xFF), | |
| 1392 }; | |
| 1393 device_tables[j] = add_object ((char*) table, 2, c); | |
| 1394 } | |
| 1395 } | |
| 1396 | |
| 1397 pair_pos_2[i] = add_pair_pos_2 (1 + i * num_class_1, | |
| 1398 coverage[i], | |
| 1399 class_def_1[i], num_class_1, | |
| 1400 class_def_2[i], num_class_2, | |
| 1401 with_device_tables | |
| 1402 ? &device_tables[i * num_class_1 * num_class_2] | |
| 1403 : nullptr, | |
| 1404 c); | |
| 1405 } | |
| 1406 | |
| 1407 | |
| 1408 unsigned pair_pos_1 = 0; | |
| 1409 if (extra_table) pair_pos_1 = add_object (large_string.c_str(), 100000, c); | |
| 1410 | |
| 1411 if (as_extension) { | |
| 1412 for (int i = num_pair_pos_2 - 1; i >= 0; i--) | |
| 1413 pair_pos_2[i] = add_extension (pair_pos_2[i], 2, c); | |
| 1414 | |
| 1415 if (extra_table) | |
| 1416 pair_pos_1 = add_extension (pair_pos_1, 2, c); | |
| 1417 } | |
| 1418 | |
| 1419 start_lookup (as_extension ? 9 : 2, 1 + num_pair_pos_2, c); | |
| 1420 | |
| 1421 if (extra_table) | |
| 1422 add_offset (pair_pos_1, c); | |
| 1423 | |
| 1424 for (int i = 0; i < num_pair_pos_2; i++) | |
| 1425 add_offset (pair_pos_2[i], c); | |
| 1426 | |
| 1427 unsigned lookup = finish_lookup (c); | |
| 1428 | |
| 1429 unsigned lookup_list = add_lookup_list (&lookup, 1, c); | |
| 1430 | |
| 1431 add_gsubgpos_header (lookup_list, c); | |
| 1432 | |
| 1433 c->end_serialize(); | |
| 1434 | |
| 1435 free (device_tables); | |
| 1436 } | |
| 1437 | |
| 1438 template<int mark_count, | |
| 1439 int class_count, | |
| 1440 int base_count, | |
| 1441 int table_count> | |
| 1442 static void | |
| 1443 populate_serializer_with_large_mark_base_pos_1 (hb_serialize_context_t* c) | |
| 1444 { | |
| 1445 c->start_serialize<char> (); | |
| 1446 | |
| 1447 MarkBasePosBuffers<mark_count, class_count, base_count, table_count> buffers (c); | |
| 1448 | |
| 1449 unsigned mark_base_pos[table_count]; | |
| 1450 for (unsigned i = 0; i < table_count; i++) | |
| 1451 mark_base_pos[i] = buffers.create_mark_base_pos_1 (i, c); | |
| 1452 | |
| 1453 for (int i = 0; i < table_count; i++) | |
| 1454 mark_base_pos[i] = add_extension (mark_base_pos[i], 4, c); | |
| 1455 | |
| 1456 start_lookup (9, table_count, c); | |
| 1457 | |
| 1458 for (int i = 0; i < table_count; i++) | |
| 1459 add_offset (mark_base_pos[i], c); | |
| 1460 | |
| 1461 unsigned lookup = finish_lookup (c); | |
| 1462 | |
| 1463 unsigned lookup_list = add_lookup_list (&lookup, 1, c); | |
| 1464 | |
| 1465 add_gsubgpos_header (lookup_list, c); | |
| 1466 | |
| 1467 c->end_serialize(); | |
| 1468 } | |
| 1469 | |
| 1470 static void test_sort_shortest () | |
| 1471 { | |
| 1472 size_t buffer_size = 100; | |
| 1473 void* buffer = malloc (buffer_size); | |
| 1474 hb_serialize_context_t c (buffer, buffer_size); | |
| 1475 populate_serializer_complex_2 (&c); | |
| 1476 | |
| 1477 graph_t graph (c.object_graph ()); | |
| 1478 graph.sort_shortest_distance (); | |
| 1479 assert (!graph.in_error ()); | |
| 1480 | |
| 1481 assert(strncmp (graph.object (4).head, "abc", 3) == 0); | |
| 1482 assert(graph.object (4).real_links.length == 3); | |
| 1483 assert(graph.object (4).real_links[0].objidx == 2); | |
| 1484 assert(graph.object (4).real_links[1].objidx == 0); | |
| 1485 assert(graph.object (4).real_links[2].objidx == 3); | |
| 1486 | |
| 1487 assert(strncmp (graph.object (3).head, "mn", 2) == 0); | |
| 1488 assert(graph.object (3).real_links.length == 0); | |
| 1489 | |
| 1490 assert(strncmp (graph.object (2).head, "def", 3) == 0); | |
| 1491 assert(graph.object (2).real_links.length == 1); | |
| 1492 assert(graph.object (2).real_links[0].objidx == 1); | |
| 1493 | |
| 1494 assert(strncmp (graph.object (1).head, "ghi", 3) == 0); | |
| 1495 assert(graph.object (1).real_links.length == 1); | |
| 1496 assert(graph.object (1).real_links[0].objidx == 0); | |
| 1497 | |
| 1498 assert(strncmp (graph.object (0).head, "jkl", 3) == 0); | |
| 1499 assert(graph.object (0).real_links.length == 0); | |
| 1500 | |
| 1501 free (buffer); | |
| 1502 } | |
| 1503 | |
| 1504 static void test_duplicate_leaf () | |
| 1505 { | |
| 1506 size_t buffer_size = 100; | |
| 1507 void* buffer = malloc (buffer_size); | |
| 1508 hb_serialize_context_t c (buffer, buffer_size); | |
| 1509 populate_serializer_complex_2 (&c); | |
| 1510 | |
| 1511 graph_t graph (c.object_graph ()); | |
| 1512 graph.duplicate (4, 1); | |
| 1513 | |
| 1514 assert(strncmp (graph.object (5).head, "abc", 3) == 0); | |
| 1515 assert(graph.object (5).real_links.length == 3); | |
| 1516 assert(graph.object (5).real_links[0].objidx == 3); | |
| 1517 assert(graph.object (5).real_links[1].objidx == 4); | |
| 1518 assert(graph.object (5).real_links[2].objidx == 0); | |
| 1519 | |
| 1520 assert(strncmp (graph.object (4).head, "jkl", 3) == 0); | |
| 1521 assert(graph.object (4).real_links.length == 0); | |
| 1522 | |
| 1523 assert(strncmp (graph.object (3).head, "def", 3) == 0); | |
| 1524 assert(graph.object (3).real_links.length == 1); | |
| 1525 assert(graph.object (3).real_links[0].objidx == 2); | |
| 1526 | |
| 1527 assert(strncmp (graph.object (2).head, "ghi", 3) == 0); | |
| 1528 assert(graph.object (2).real_links.length == 1); | |
| 1529 assert(graph.object (2).real_links[0].objidx == 1); | |
| 1530 | |
| 1531 assert(strncmp (graph.object (1).head, "jkl", 3) == 0); | |
| 1532 assert(graph.object (1).real_links.length == 0); | |
| 1533 | |
| 1534 assert(strncmp (graph.object (0).head, "mn", 2) == 0); | |
| 1535 assert(graph.object (0).real_links.length == 0); | |
| 1536 | |
| 1537 free (buffer); | |
| 1538 } | |
| 1539 | |
| 1540 static void test_duplicate_interior () | |
| 1541 { | |
| 1542 size_t buffer_size = 100; | |
| 1543 void* buffer = malloc (buffer_size); | |
| 1544 hb_serialize_context_t c (buffer, buffer_size); | |
| 1545 populate_serializer_complex_3 (&c); | |
| 1546 | |
| 1547 graph_t graph (c.object_graph ()); | |
| 1548 graph.duplicate (3, 2); | |
| 1549 | |
| 1550 assert(strncmp (graph.object (6).head, "abc", 3) == 0); | |
| 1551 assert(graph.object (6).real_links.length == 3); | |
| 1552 assert(graph.object (6).real_links[0].objidx == 4); | |
| 1553 assert(graph.object (6).real_links[1].objidx == 2); | |
| 1554 assert(graph.object (6).real_links[2].objidx == 1); | |
| 1555 | |
| 1556 assert(strncmp (graph.object (5).head, "jkl", 3) == 0); | |
| 1557 assert(graph.object (5).real_links.length == 1); | |
| 1558 assert(graph.object (5).real_links[0].objidx == 0); | |
| 1559 | |
| 1560 assert(strncmp (graph.object (4).head, "def", 3) == 0); | |
| 1561 assert(graph.object (4).real_links.length == 1); | |
| 1562 assert(graph.object (4).real_links[0].objidx == 3); | |
| 1563 | |
| 1564 assert(strncmp (graph.object (3).head, "ghi", 3) == 0); | |
| 1565 assert(graph.object (3).real_links.length == 1); | |
| 1566 assert(graph.object (3).real_links[0].objidx == 5); | |
| 1567 | |
| 1568 assert(strncmp (graph.object (2).head, "jkl", 3) == 0); | |
| 1569 assert(graph.object (2).real_links.length == 1); | |
| 1570 assert(graph.object (2).real_links[0].objidx == 0); | |
| 1571 | |
| 1572 assert(strncmp (graph.object (1).head, "mn", 2) == 0); | |
| 1573 assert(graph.object (1).real_links.length == 0); | |
| 1574 | |
| 1575 assert(strncmp (graph.object (0).head, "opqrst", 6) == 0); | |
| 1576 assert(graph.object (0).real_links.length == 0); | |
| 1577 | |
| 1578 free (buffer); | |
| 1579 } | |
| 1580 | |
| 1581 static void | |
| 1582 test_serialize () | |
| 1583 { | |
| 1584 size_t buffer_size = 100; | |
| 1585 void* buffer_1 = malloc (buffer_size); | |
| 1586 hb_serialize_context_t c1 (buffer_1, buffer_size); | |
| 1587 populate_serializer_simple (&c1); | |
| 1588 hb_bytes_t expected = c1.copy_bytes (); | |
| 1589 | |
| 1590 graph_t graph (c1.object_graph ()); | |
| 1591 hb_blob_t* out = graph::serialize (graph); | |
| 1592 free (buffer_1); | |
| 1593 | |
| 1594 hb_bytes_t actual = out->as_bytes (); | |
| 1595 assert (actual == expected); | |
| 1596 expected.fini (); | |
| 1597 hb_blob_destroy (out); | |
| 1598 } | |
| 1599 | |
| 1600 static void test_will_overflow_1 () | |
| 1601 { | |
| 1602 size_t buffer_size = 100; | |
| 1603 void* buffer = malloc (buffer_size); | |
| 1604 hb_serialize_context_t c (buffer, buffer_size); | |
| 1605 populate_serializer_complex_2 (&c); | |
| 1606 graph_t graph (c.object_graph ()); | |
| 1607 | |
| 1608 assert (!graph::will_overflow (graph, nullptr)); | |
| 1609 | |
| 1610 free (buffer); | |
| 1611 } | |
| 1612 | |
| 1613 static void test_will_overflow_2 () | |
| 1614 { | |
| 1615 size_t buffer_size = 160000; | |
| 1616 void* buffer = malloc (buffer_size); | |
| 1617 hb_serialize_context_t c (buffer, buffer_size); | |
| 1618 populate_serializer_with_overflow (&c); | |
| 1619 graph_t graph (c.object_graph ()); | |
| 1620 | |
| 1621 assert (graph::will_overflow (graph, nullptr)); | |
| 1622 | |
| 1623 free (buffer); | |
| 1624 } | |
| 1625 | |
| 1626 static void test_will_overflow_3 () | |
| 1627 { | |
| 1628 size_t buffer_size = 160000; | |
| 1629 void* buffer = malloc (buffer_size); | |
| 1630 hb_serialize_context_t c (buffer, buffer_size); | |
| 1631 populate_serializer_with_dedup_overflow (&c); | |
| 1632 graph_t graph (c.object_graph ()); | |
| 1633 | |
| 1634 assert (graph::will_overflow (graph, nullptr)); | |
| 1635 | |
| 1636 free (buffer); | |
| 1637 } | |
| 1638 | |
| 1639 static void test_resolve_overflows_via_sort () | |
| 1640 { | |
| 1641 size_t buffer_size = 160000; | |
| 1642 void* buffer = malloc (buffer_size); | |
| 1643 hb_serialize_context_t c (buffer, buffer_size); | |
| 1644 populate_serializer_with_overflow (&c); | |
| 1645 graph_t graph (c.object_graph ()); | |
| 1646 | |
| 1647 hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE); | |
| 1648 assert (out); | |
| 1649 hb_bytes_t result = out->as_bytes (); | |
| 1650 assert (result.length == (80000 + 3 + 3 * 2)); | |
| 1651 | |
| 1652 free (buffer); | |
| 1653 hb_blob_destroy (out); | |
| 1654 } | |
| 1655 | |
| 1656 static void test_resolve_overflows_via_duplication () | |
| 1657 { | |
| 1658 size_t buffer_size = 160000; | |
| 1659 void* buffer = malloc (buffer_size); | |
| 1660 hb_serialize_context_t c (buffer, buffer_size); | |
| 1661 populate_serializer_with_dedup_overflow (&c); | |
| 1662 graph_t graph (c.object_graph ()); | |
| 1663 | |
| 1664 hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE); | |
| 1665 assert (out); | |
| 1666 hb_bytes_t result = out->as_bytes (); | |
| 1667 assert (result.length == (10000 + 2 * 2 + 60000 + 2 + 3 * 2)); | |
| 1668 | |
| 1669 free (buffer); | |
| 1670 hb_blob_destroy (out); | |
| 1671 } | |
| 1672 | |
| 1673 static void test_resolve_overflows_via_space_assignment () | |
| 1674 { | |
| 1675 size_t buffer_size = 160000; | |
| 1676 void* buffer = malloc (buffer_size); | |
| 1677 hb_serialize_context_t c (buffer, buffer_size); | |
| 1678 populate_serializer_spaces (&c, true); | |
| 1679 | |
| 1680 void* expected_buffer = malloc (buffer_size); | |
| 1681 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1682 populate_serializer_spaces (&e, false); | |
| 1683 | |
| 1684 run_resolve_overflow_test ("test_resolve_overflows_via_space_assignment", | |
| 1685 c, | |
| 1686 e); | |
| 1687 | |
| 1688 free (buffer); | |
| 1689 free (expected_buffer); | |
| 1690 } | |
| 1691 | |
| 1692 static void test_resolve_overflows_via_isolation () | |
| 1693 { | |
| 1694 size_t buffer_size = 160000; | |
| 1695 void* buffer = malloc (buffer_size); | |
| 1696 hb_serialize_context_t c (buffer, buffer_size); | |
| 1697 populate_serializer_with_isolation_overflow (&c); | |
| 1698 graph_t graph (c.object_graph ()); | |
| 1699 | |
| 1700 assert (c.offset_overflow ()); | |
| 1701 hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0); | |
| 1702 assert (out); | |
| 1703 hb_bytes_t result = out->as_bytes (); | |
| 1704 assert (result.length == (1 + 10000 + 60000 + 1 + 1 | |
| 1705 + 4 + 3 * 2)); | |
| 1706 | |
| 1707 free (buffer); | |
| 1708 hb_blob_destroy (out); | |
| 1709 } | |
| 1710 | |
| 1711 static void test_resolve_overflows_via_isolation_with_recursive_duplication () | |
| 1712 { | |
| 1713 size_t buffer_size = 160000; | |
| 1714 void* buffer = malloc (buffer_size); | |
| 1715 hb_serialize_context_t c (buffer, buffer_size); | |
| 1716 populate_serializer_with_isolation_overflow_complex (&c); | |
| 1717 | |
| 1718 void* expected_buffer = malloc (buffer_size); | |
| 1719 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1720 populate_serializer_with_isolation_overflow_complex_expected (&e); | |
| 1721 | |
| 1722 run_resolve_overflow_test ("test_resolve_overflows_via_isolation_with_recursive_duplication", | |
| 1723 c, | |
| 1724 e); | |
| 1725 free (buffer); | |
| 1726 free (expected_buffer); | |
| 1727 } | |
| 1728 | |
| 1729 static void test_resolve_overflows_via_isolating_16bit_space () | |
| 1730 { | |
| 1731 size_t buffer_size = 160000; | |
| 1732 void* buffer = malloc (buffer_size); | |
| 1733 hb_serialize_context_t c (buffer, buffer_size); | |
| 1734 populate_serializer_spaces_16bit_connection (&c); | |
| 1735 | |
| 1736 void* expected_buffer = malloc (buffer_size); | |
| 1737 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1738 populate_serializer_spaces_16bit_connection_expected (&e); | |
| 1739 | |
| 1740 run_resolve_overflow_test ("test_resolve_overflows_via_isolating_16bit_space", | |
| 1741 c, | |
| 1742 e); | |
| 1743 | |
| 1744 free (buffer); | |
| 1745 free (expected_buffer); | |
| 1746 } | |
| 1747 | |
| 1748 static void test_resolve_overflows_via_isolating_16bit_space_2 () | |
| 1749 { | |
| 1750 size_t buffer_size = 160000; | |
| 1751 void* buffer = malloc (buffer_size); | |
| 1752 hb_serialize_context_t c (buffer, buffer_size); | |
| 1753 populate_serializer_short_and_wide_subgraph_root (&c); | |
| 1754 | |
| 1755 void* expected_buffer = malloc (buffer_size); | |
| 1756 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1757 populate_serializer_short_and_wide_subgraph_root_expected (&e); | |
| 1758 | |
| 1759 run_resolve_overflow_test ("test_resolve_overflows_via_isolating_16bit_space_2", | |
| 1760 c, | |
| 1761 e); | |
| 1762 | |
| 1763 free (buffer); | |
| 1764 free (expected_buffer); | |
| 1765 } | |
| 1766 | |
| 1767 static void test_resolve_overflows_via_isolation_spaces () | |
| 1768 { | |
| 1769 size_t buffer_size = 160000; | |
| 1770 void* buffer = malloc (buffer_size); | |
| 1771 hb_serialize_context_t c (buffer, buffer_size); | |
| 1772 populate_serializer_with_isolation_overflow_spaces (&c); | |
| 1773 graph_t graph (c.object_graph ()); | |
| 1774 | |
| 1775 assert (c.offset_overflow ()); | |
| 1776 hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0); | |
| 1777 assert (out); | |
| 1778 hb_bytes_t result = out->as_bytes (); | |
| 1779 | |
| 1780 unsigned expected_length = 3 + 2 * 60000; // objects | |
| 1781 expected_length += 2 * 4 + 2 * 2; // links | |
| 1782 assert (result.length == expected_length); | |
| 1783 | |
| 1784 free (buffer); | |
| 1785 hb_blob_destroy (out); | |
| 1786 } | |
| 1787 | |
| 1788 static void test_resolve_mixed_overflows_via_isolation_spaces () | |
| 1789 { | |
| 1790 size_t buffer_size = 200000; | |
| 1791 void* buffer = malloc (buffer_size); | |
| 1792 hb_serialize_context_t c (buffer, buffer_size); | |
| 1793 populate_serializer_with_24_and_32_bit_offsets (&c); | |
| 1794 graph_t graph (c.object_graph ()); | |
| 1795 | |
| 1796 assert (c.offset_overflow ()); | |
| 1797 hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG ('G', 'S', 'U', 'B'), 0); | |
| 1798 assert (out); | |
| 1799 hb_bytes_t result = out->as_bytes (); | |
| 1800 | |
| 1801 unsigned expected_length = | |
| 1802 // Objects | |
| 1803 7 + | |
| 1804 4 * 40000; | |
| 1805 | |
| 1806 expected_length += | |
| 1807 // Links | |
| 1808 2 * 4 + // 32 | |
| 1809 4 * 3 + // 24 | |
| 1810 4 * 2; // 16 | |
| 1811 | |
| 1812 assert (result.length == expected_length); | |
| 1813 | |
| 1814 free (buffer); | |
| 1815 hb_blob_destroy (out); | |
| 1816 } | |
| 1817 | |
| 1818 static void test_resolve_with_extension_promotion () | |
| 1819 { | |
| 1820 size_t buffer_size = 200000; | |
| 1821 void* buffer = malloc (buffer_size); | |
| 1822 assert (buffer); | |
| 1823 hb_serialize_context_t c (buffer, buffer_size); | |
| 1824 populate_serializer_with_extension_promotion (&c); | |
| 1825 | |
| 1826 void* expected_buffer = malloc (buffer_size); | |
| 1827 assert (expected_buffer); | |
| 1828 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1829 populate_serializer_with_extension_promotion (&e, 3); | |
| 1830 | |
| 1831 run_resolve_overflow_test ("test_resolve_with_extension_promotion", | |
| 1832 c, | |
| 1833 e, | |
| 1834 20, | |
| 1835 true); | |
| 1836 free (buffer); | |
| 1837 free (expected_buffer); | |
| 1838 } | |
| 1839 | |
| 1840 static void test_resolve_with_basic_pair_pos_1_split () | |
| 1841 { | |
| 1842 size_t buffer_size = 200000; | |
| 1843 void* buffer = malloc (buffer_size); | |
| 1844 assert (buffer); | |
| 1845 hb_serialize_context_t c (buffer, buffer_size); | |
| 1846 populate_serializer_with_large_pair_pos_1 <1, 4>(&c); | |
| 1847 | |
| 1848 void* expected_buffer = malloc (buffer_size); | |
| 1849 assert (expected_buffer); | |
| 1850 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1851 populate_serializer_with_large_pair_pos_1 <2, 2>(&e, true); | |
| 1852 | |
| 1853 run_resolve_overflow_test ("test_resolve_with_basic_pair_pos_1_split", | |
| 1854 c, | |
| 1855 e, | |
| 1856 20, | |
| 1857 true, | |
| 1858 HB_TAG('G', 'P', 'O', 'S')); | |
| 1859 free (buffer); | |
| 1860 free (expected_buffer); | |
| 1861 } | |
| 1862 | |
| 1863 static void test_resolve_with_extension_pair_pos_1_split () | |
| 1864 { | |
| 1865 size_t buffer_size = 200000; | |
| 1866 void* buffer = malloc (buffer_size); | |
| 1867 assert (buffer); | |
| 1868 hb_serialize_context_t c (buffer, buffer_size); | |
| 1869 populate_serializer_with_large_pair_pos_1 <1, 4>(&c, true); | |
| 1870 | |
| 1871 void* expected_buffer = malloc (buffer_size); | |
| 1872 assert (expected_buffer); | |
| 1873 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1874 populate_serializer_with_large_pair_pos_1 <2, 2>(&e, true); | |
| 1875 | |
| 1876 run_resolve_overflow_test ("test_resolve_with_extension_pair_pos_1_split", | |
| 1877 c, | |
| 1878 e, | |
| 1879 20, | |
| 1880 true, | |
| 1881 HB_TAG('G', 'P', 'O', 'S')); | |
| 1882 free (buffer); | |
| 1883 free (expected_buffer); | |
| 1884 } | |
| 1885 | |
| 1886 static void test_resolve_with_basic_pair_pos_2_split () | |
| 1887 { | |
| 1888 size_t buffer_size = 300000; | |
| 1889 void* buffer = malloc (buffer_size); | |
| 1890 assert (buffer); | |
| 1891 hb_serialize_context_t c (buffer, buffer_size); | |
| 1892 populate_serializer_with_large_pair_pos_2 <1, 4, 3000>(&c); | |
| 1893 | |
| 1894 void* expected_buffer = malloc (buffer_size); | |
| 1895 assert (expected_buffer); | |
| 1896 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1897 populate_serializer_with_large_pair_pos_2 <2, 2, 3000>(&e, true); | |
| 1898 | |
| 1899 run_resolve_overflow_test ("test_resolve_with_basic_pair_pos_2_split", | |
| 1900 c, | |
| 1901 e, | |
| 1902 20, | |
| 1903 true, | |
| 1904 HB_TAG('G', 'P', 'O', 'S')); | |
| 1905 free (buffer); | |
| 1906 free (expected_buffer); | |
| 1907 } | |
| 1908 | |
| 1909 static void test_resolve_with_close_to_limit_pair_pos_2_split () | |
| 1910 { | |
| 1911 size_t buffer_size = 300000; | |
| 1912 void* buffer = malloc (buffer_size); | |
| 1913 assert (buffer); | |
| 1914 hb_serialize_context_t c (buffer, buffer_size); | |
| 1915 populate_serializer_with_large_pair_pos_2 <1, 1596, 10>(&c, true, false, false); | |
| 1916 | |
| 1917 void* expected_buffer = malloc (buffer_size); | |
| 1918 assert (expected_buffer); | |
| 1919 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1920 populate_serializer_with_large_pair_pos_2 <2, 798, 10>(&e, true, false, false); | |
| 1921 | |
| 1922 run_resolve_overflow_test ("test_resolve_with_close_to_limit_pair_pos_2_split", | |
| 1923 c, | |
| 1924 e, | |
| 1925 20, | |
| 1926 true, | |
| 1927 HB_TAG('G', 'P', 'O', 'S')); | |
| 1928 free (buffer); | |
| 1929 free (expected_buffer); | |
| 1930 } | |
| 1931 | |
| 1932 static void test_resolve_with_pair_pos_2_split_with_device_tables () | |
| 1933 { | |
| 1934 size_t buffer_size = 300000; | |
| 1935 void* buffer = malloc (buffer_size); | |
| 1936 assert (buffer); | |
| 1937 hb_serialize_context_t c (buffer, buffer_size); | |
| 1938 populate_serializer_with_large_pair_pos_2 <1, 4, 2000>(&c, false, true); | |
| 1939 | |
| 1940 void* expected_buffer = malloc (buffer_size); | |
| 1941 assert (expected_buffer); | |
| 1942 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1943 populate_serializer_with_large_pair_pos_2 <2, 2, 2000>(&e, true, true); | |
| 1944 | |
| 1945 run_resolve_overflow_test ("test_resolve_with_pair_pos_2_split_with_device_tables", | |
| 1946 c, | |
| 1947 e, | |
| 1948 20, | |
| 1949 true, | |
| 1950 HB_TAG('G', 'P', 'O', 'S')); | |
| 1951 free (buffer); | |
| 1952 free (expected_buffer); | |
| 1953 } | |
| 1954 | |
| 1955 static void test_resolve_with_basic_mark_base_pos_1_split () | |
| 1956 { | |
| 1957 size_t buffer_size = 200000; | |
| 1958 void* buffer = malloc (buffer_size); | |
| 1959 assert (buffer); | |
| 1960 hb_serialize_context_t c (buffer, buffer_size); | |
| 1961 populate_serializer_with_large_mark_base_pos_1 <40, 10, 110, 1>(&c); | |
| 1962 | |
| 1963 void* expected_buffer = malloc (buffer_size); | |
| 1964 assert (expected_buffer); | |
| 1965 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1966 populate_serializer_with_large_mark_base_pos_1 <40, 10, 110, 2>(&e); | |
| 1967 | |
| 1968 run_resolve_overflow_test ("test_resolve_with_basic_mark_base_pos_1_split", | |
| 1969 c, | |
| 1970 e, | |
| 1971 20, | |
| 1972 true, | |
| 1973 HB_TAG('G', 'P', 'O', 'S')); | |
| 1974 free (buffer); | |
| 1975 free (expected_buffer); | |
| 1976 } | |
| 1977 | |
| 1978 static void test_resolve_overflows_via_splitting_spaces () | |
| 1979 { | |
| 1980 size_t buffer_size = 160000; | |
| 1981 void* buffer = malloc (buffer_size); | |
| 1982 hb_serialize_context_t c (buffer, buffer_size); | |
| 1983 populate_serializer_with_split_spaces (&c); | |
| 1984 | |
| 1985 void* expected_buffer = malloc (buffer_size); | |
| 1986 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 1987 populate_serializer_with_split_spaces_expected (&e); | |
| 1988 | |
| 1989 run_resolve_overflow_test ("test_resolve_overflows_via_splitting_spaces", | |
| 1990 c, | |
| 1991 e, | |
| 1992 1); | |
| 1993 | |
| 1994 free (buffer); | |
| 1995 free (expected_buffer); | |
| 1996 | |
| 1997 } | |
| 1998 | |
| 1999 static void test_resolve_overflows_via_splitting_spaces_2 () | |
| 2000 { | |
| 2001 size_t buffer_size = 160000; | |
| 2002 void* buffer = malloc (buffer_size); | |
| 2003 hb_serialize_context_t c (buffer, buffer_size); | |
| 2004 populate_serializer_with_split_spaces_2 (&c); | |
| 2005 | |
| 2006 void* expected_buffer = malloc (buffer_size); | |
| 2007 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 2008 populate_serializer_with_split_spaces_expected_2 (&e); | |
| 2009 | |
| 2010 run_resolve_overflow_test ("test_resolve_overflows_via_splitting_spaces_2", | |
| 2011 c, | |
| 2012 e, | |
| 2013 1); | |
| 2014 free (buffer); | |
| 2015 free (expected_buffer); | |
| 2016 } | |
| 2017 | |
| 2018 static void test_resolve_overflows_via_priority () | |
| 2019 { | |
| 2020 size_t buffer_size = 160000; | |
| 2021 void* buffer = malloc (buffer_size); | |
| 2022 hb_serialize_context_t c (buffer, buffer_size); | |
| 2023 populate_serializer_with_priority_overflow (&c); | |
| 2024 | |
| 2025 void* expected_buffer = malloc (buffer_size); | |
| 2026 hb_serialize_context_t e (expected_buffer, buffer_size); | |
| 2027 populate_serializer_with_priority_overflow_expected (&e); | |
| 2028 | |
| 2029 run_resolve_overflow_test ("test_resolve_overflows_via_priority", | |
| 2030 c, | |
| 2031 e, | |
| 2032 3); | |
| 2033 free (buffer); | |
| 2034 free (expected_buffer); | |
| 2035 } | |
| 2036 | |
| 2037 | |
| 2038 static void test_virtual_link () | |
| 2039 { | |
| 2040 size_t buffer_size = 100; | |
| 2041 void* buffer = malloc (buffer_size); | |
| 2042 hb_serialize_context_t c (buffer, buffer_size); | |
| 2043 populate_serializer_virtual_link (&c); | |
| 2044 | |
| 2045 hb_blob_t* out = hb_resolve_overflows (c.object_graph (), HB_TAG_NONE); | |
| 2046 assert (out); | |
| 2047 | |
| 2048 hb_bytes_t result = out->as_bytes (); | |
| 2049 assert (result.length == 5 + 4 * 2); | |
| 2050 assert (result[0] == 'a'); | |
| 2051 assert (result[5] == 'c'); | |
| 2052 assert (result[8] == 'e'); | |
| 2053 assert (result[9] == 'b'); | |
| 2054 assert (result[12] == 'd'); | |
| 2055 | |
| 2056 free (buffer); | |
| 2057 hb_blob_destroy (out); | |
| 2058 } | |
| 2059 | |
| 2060 static void | |
| 2061 test_shared_node_with_virtual_links () | |
| 2062 { | |
| 2063 size_t buffer_size = 100; | |
| 2064 void* buffer = malloc (buffer_size); | |
| 2065 hb_serialize_context_t c (buffer, buffer_size); | |
| 2066 | |
| 2067 c.start_serialize<char> (); | |
| 2068 | |
| 2069 unsigned obj_b = add_object ("b", 1, &c); | |
| 2070 unsigned obj_c = add_object ("c", 1, &c); | |
| 2071 | |
| 2072 start_object ("d", 1, &c); | |
| 2073 add_virtual_offset (obj_b, &c); | |
| 2074 unsigned obj_d_1 = c.pop_pack (); | |
| 2075 | |
| 2076 start_object ("d", 1, &c); | |
| 2077 add_virtual_offset (obj_c, &c); | |
| 2078 unsigned obj_d_2 = c.pop_pack (); | |
| 2079 | |
| 2080 assert (obj_d_1 == obj_d_2); | |
| 2081 | |
| 2082 start_object ("a", 1, &c); | |
| 2083 add_offset (obj_b, &c); | |
| 2084 add_offset (obj_c, &c); | |
| 2085 add_offset (obj_d_1, &c); | |
| 2086 add_offset (obj_d_2, &c); | |
| 2087 c.pop_pack (); | |
| 2088 c.end_serialize (); | |
| 2089 | |
| 2090 assert(c.object_graph() [obj_d_1]->virtual_links.length == 2); | |
| 2091 assert(c.object_graph() [obj_d_1]->virtual_links[0].objidx == obj_b); | |
| 2092 assert(c.object_graph() [obj_d_1]->virtual_links[1].objidx == obj_c); | |
| 2093 free(buffer); | |
| 2094 } | |
| 2095 | |
| 2096 | |
| 2097 // TODO(garretrieger): update will_overflow tests to check the overflows array. | |
| 2098 // TODO(garretrieger): add tests for priority raising. | |
| 2099 | |
| 2100 int | |
| 2101 main (int argc, char **argv) | |
| 2102 { | |
| 2103 test_serialize (); | |
| 2104 test_sort_shortest (); | |
| 2105 test_will_overflow_1 (); | |
| 2106 test_will_overflow_2 (); | |
| 2107 test_will_overflow_3 (); | |
| 2108 test_resolve_overflows_via_sort (); | |
| 2109 test_resolve_overflows_via_duplication (); | |
| 2110 test_resolve_overflows_via_priority (); | |
| 2111 test_resolve_overflows_via_space_assignment (); | |
| 2112 test_resolve_overflows_via_isolation (); | |
| 2113 test_resolve_overflows_via_isolation_with_recursive_duplication (); | |
| 2114 test_resolve_overflows_via_isolation_spaces (); | |
| 2115 test_resolve_overflows_via_isolating_16bit_space (); | |
| 2116 test_resolve_overflows_via_isolating_16bit_space_2 (); | |
| 2117 test_resolve_overflows_via_splitting_spaces (); | |
| 2118 test_resolve_overflows_via_splitting_spaces_2 (); | |
| 2119 test_resolve_mixed_overflows_via_isolation_spaces (); | |
| 2120 test_duplicate_leaf (); | |
| 2121 test_duplicate_interior (); | |
| 2122 test_virtual_link (); | |
| 2123 test_shared_node_with_virtual_links (); | |
| 2124 test_resolve_with_extension_promotion (); | |
| 2125 test_resolve_with_basic_pair_pos_1_split (); | |
| 2126 test_resolve_with_extension_pair_pos_1_split (); | |
| 2127 test_resolve_with_basic_pair_pos_2_split (); | |
| 2128 test_resolve_with_pair_pos_2_split_with_device_tables (); | |
| 2129 test_resolve_with_close_to_limit_pair_pos_2_split (); | |
| 2130 test_resolve_with_basic_mark_base_pos_1_split (); | |
| 2131 | |
| 2132 // TODO(grieger): have run overflow tests compare graph equality not final packed binary. | |
| 2133 // TODO(grieger): split test where multiple subtables in one lookup are split to test link ordering. | |
| 2134 // TODO(grieger): split test where coverage table in subtable that is being split is shared. | |
| 2135 // TODO(grieger): test with extensions already mixed in as well. | |
| 2136 // TODO(grieger): test two layer ext promotion setup. | |
| 2137 // TODO(grieger): test sorting by subtables per byte in ext. promotion. | |
| 2138 } |
