test-object.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. * Copyright © 2011 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): Behdad Esfahbod
  25. */
  26. #include "hb-test.h"
  27. /* Unit tests for hb-object-private.h */
  28. static void *
  29. create_blob (void)
  30. {
  31. static char data[] = "test data";
  32. return hb_blob_create (data, sizeof (data), HB_MEMORY_MODE_READONLY, NULL, NULL);
  33. }
  34. static void *
  35. create_blob_from_inert (void)
  36. {
  37. return hb_blob_create (NULL, 0, HB_MEMORY_MODE_DUPLICATE, NULL, NULL);
  38. }
  39. static void *
  40. create_buffer (void)
  41. {
  42. return hb_buffer_create ();
  43. }
  44. static void *
  45. create_buffer_from_inert (void)
  46. {
  47. return NULL;
  48. }
  49. static void *
  50. create_set (void)
  51. {
  52. return hb_set_create ();
  53. }
  54. static void *
  55. create_set_from_inert (void)
  56. {
  57. return NULL;
  58. }
  59. static void *
  60. create_face (void)
  61. {
  62. hb_blob_t *blob = (hb_blob_t *) create_blob ();
  63. hb_face_t *face = hb_face_create (blob, 0);
  64. hb_blob_destroy (blob);
  65. return face;
  66. }
  67. static void *
  68. create_face_from_inert (void)
  69. {
  70. return hb_face_create (hb_blob_get_empty (), 0);
  71. }
  72. static void *
  73. create_font (void)
  74. {
  75. hb_face_t *face = (hb_face_t *) create_face ();
  76. hb_font_t *font = hb_font_create (face);
  77. hb_face_destroy (face);
  78. return font;
  79. }
  80. static void *
  81. create_font_from_inert (void)
  82. {
  83. return hb_font_create (hb_face_get_empty ());
  84. }
  85. static void *
  86. create_font_funcs (void)
  87. {
  88. return hb_font_funcs_create ();
  89. }
  90. static void *
  91. create_font_funcs_from_inert (void)
  92. {
  93. return NULL;
  94. }
  95. static void *
  96. create_unicode_funcs (void)
  97. {
  98. return hb_unicode_funcs_create (NULL);
  99. }
  100. static void *
  101. create_unicode_funcs_from_inert (void)
  102. {
  103. return hb_unicode_funcs_create (hb_unicode_funcs_get_empty ());
  104. }
  105. typedef void *(*create_func_t) (void);
  106. typedef void *(*reference_func_t) (void *obj);
  107. typedef void (*destroy_func_t) (void *obj);
  108. typedef hb_bool_t (*set_user_data_func_t) (void *obj, hb_user_data_key_t *key, void *data, hb_destroy_func_t destroy, hb_bool_t replace);
  109. typedef void * (*get_user_data_func_t) (void *obj, hb_user_data_key_t *key);
  110. typedef void (*make_immutable_func_t) (void *obj);
  111. typedef hb_bool_t (*is_immutable_func_t) (void *obj);
  112. typedef struct {
  113. create_func_t create;
  114. create_func_t create_from_inert;
  115. create_func_t get_empty;
  116. reference_func_t reference;
  117. destroy_func_t destroy;
  118. set_user_data_func_t set_user_data;
  119. get_user_data_func_t get_user_data;
  120. make_immutable_func_t make_immutable;
  121. is_immutable_func_t is_immutable;
  122. const char *name;
  123. } object_t;
  124. #define OBJECT_WITHOUT_IMMUTABILITY(name) \
  125. { \
  126. (create_func_t) create_##name, \
  127. (create_func_t) create_##name##_from_inert, \
  128. (create_func_t) hb_##name##_get_empty, \
  129. (reference_func_t) hb_##name##_reference, \
  130. (destroy_func_t) hb_##name##_destroy, \
  131. (set_user_data_func_t) hb_##name##_set_user_data, \
  132. (get_user_data_func_t) hb_##name##_get_user_data, \
  133. (make_immutable_func_t) NULL, \
  134. (is_immutable_func_t) NULL, \
  135. #name, \
  136. }
  137. #define OBJECT_WITH_IMMUTABILITY(name) \
  138. { \
  139. (create_func_t) create_##name, \
  140. (create_func_t) create_##name##_from_inert, \
  141. (create_func_t) hb_##name##_get_empty, \
  142. (reference_func_t) hb_##name##_reference, \
  143. (destroy_func_t) hb_##name##_destroy, \
  144. (set_user_data_func_t) hb_##name##_set_user_data, \
  145. (get_user_data_func_t) hb_##name##_get_user_data, \
  146. (make_immutable_func_t) hb_##name##_make_immutable, \
  147. (is_immutable_func_t) hb_##name##_is_immutable, \
  148. #name, \
  149. }
  150. static const object_t objects[] =
  151. {
  152. OBJECT_WITHOUT_IMMUTABILITY (buffer),
  153. OBJECT_WITHOUT_IMMUTABILITY (set),
  154. OBJECT_WITH_IMMUTABILITY (blob),
  155. OBJECT_WITH_IMMUTABILITY (face),
  156. OBJECT_WITH_IMMUTABILITY (font),
  157. OBJECT_WITH_IMMUTABILITY (font_funcs),
  158. OBJECT_WITH_IMMUTABILITY (unicode_funcs)
  159. };
  160. #undef OBJECT
  161. #define MAGIC0 0x12345678
  162. #define MAGIC1 0x76543210
  163. typedef struct {
  164. int value;
  165. gboolean freed;
  166. } data_t;
  167. static int global_data;
  168. static void global_free_up (void *p G_GNUC_UNUSED)
  169. {
  170. global_data++;
  171. }
  172. static void free_up0 (void *p)
  173. {
  174. data_t *data = (data_t *) p;
  175. g_assert_cmphex (data->value, ==, MAGIC0);
  176. g_assert (!data->freed);
  177. data->freed = TRUE;
  178. }
  179. static void free_up1 (void *p)
  180. {
  181. data_t *data = (data_t *) p;
  182. g_assert_cmphex (data->value, ==, MAGIC1);
  183. g_assert (!data->freed);
  184. data->freed = TRUE;
  185. }
  186. typedef struct {
  187. const object_t *klass;
  188. void *object;
  189. hb_user_data_key_t key;
  190. } deadlock_test_t;
  191. static void free_deadlock_test (void *p)
  192. {
  193. deadlock_test_t *t = (deadlock_test_t *) p;
  194. g_assert (NULL == t->klass->get_user_data (t->object, &t->key));
  195. }
  196. static void
  197. test_object (void)
  198. {
  199. unsigned int i;
  200. for (i = 0; i < G_N_ELEMENTS (objects); i++) {
  201. const object_t *o = &objects[i];
  202. void *obj;
  203. hb_user_data_key_t key[1001];
  204. {
  205. unsigned int j;
  206. data_t data[1000] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
  207. deadlock_test_t deadlock_test;
  208. g_test_message ("Testing object %s", o->name);
  209. g_test_message ("->create()");
  210. obj = o->create ();
  211. g_assert (obj);
  212. g_assert (obj == o->reference (obj));
  213. o->destroy (obj);
  214. if (o->is_immutable)
  215. g_assert (!o->is_immutable (obj));
  216. g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
  217. g_assert (o->get_user_data (obj, &key[0]) == &data[0]);
  218. if (o->is_immutable) {
  219. o->make_immutable (obj);
  220. g_assert (o->is_immutable (obj));
  221. }
  222. /* Should still work even if object is made immutable */
  223. g_assert (o->set_user_data (obj, &key[1], &data[1], free_up1, TRUE));
  224. g_assert (o->get_user_data (obj, &key[1]) == &data[1]);
  225. g_assert (!o->set_user_data (obj, NULL, &data[0], free_up0, TRUE));
  226. g_assert (o->get_user_data (obj, &key[0]) == &data[0]);
  227. g_assert (o->set_user_data (obj, &key[0], &data[1], NULL, TRUE));
  228. g_assert (data[0].freed);
  229. g_assert (o->get_user_data (obj, &key[0]) == &data[1]);
  230. g_assert (!data[1].freed);
  231. data[0].freed = FALSE;
  232. g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
  233. g_assert (!data[0].freed);
  234. g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
  235. g_assert (data[0].freed);
  236. data[0].freed = FALSE;
  237. global_data = 0;
  238. g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
  239. g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, FALSE));
  240. g_assert_cmpuint (global_data, ==, 0);
  241. g_assert (o->set_user_data (obj, &key[0], NULL, global_free_up, TRUE));
  242. g_assert_cmpuint (global_data, ==, 0);
  243. g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
  244. g_assert_cmpuint (global_data, ==, 1);
  245. global_data = 0;
  246. for (j = 2; j < 1000; j++)
  247. g_assert (o->set_user_data (obj, &key[j], &data[j], global_free_up, TRUE));
  248. for (j = 2; j < 1000; j++)
  249. g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
  250. for (j = 100; j < 1000; j++)
  251. g_assert (o->set_user_data (obj, &key[j], NULL, NULL, TRUE));
  252. for (j = 2; j < 100; j++)
  253. g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
  254. for (j = 100; j < 1000; j++)
  255. g_assert (!o->get_user_data (obj, &key[j]));
  256. g_assert_cmpuint (global_data, ==, 900);
  257. /* Test set_user_data where the destroy() func calls user_data functions.
  258. * Make sure it doesn't deadlock or corrupt memory. */
  259. deadlock_test.klass = o;
  260. deadlock_test.object = obj;
  261. g_assert (o->set_user_data (obj, &deadlock_test.key, &deadlock_test, free_deadlock_test, TRUE));
  262. g_assert (o->set_user_data (obj, &deadlock_test.key, NULL, NULL, TRUE));
  263. g_assert (!data[1].freed);
  264. o->destroy (obj);
  265. g_assert (data[0].freed);
  266. g_assert (data[1].freed);
  267. g_assert_cmpuint (global_data, ==, 1000-2);
  268. }
  269. {
  270. data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
  271. g_test_message ("->get_empty()");
  272. obj = o->get_empty ();
  273. g_assert (obj);
  274. g_assert (obj == o->reference (obj));
  275. o->destroy (obj);
  276. if (o->is_immutable)
  277. g_assert (o->is_immutable (obj));
  278. g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
  279. g_assert (!o->get_user_data (obj, &key[0]));
  280. o->destroy (obj);
  281. o->destroy (obj);
  282. o->destroy (obj);
  283. o->destroy (obj);
  284. o->destroy (obj);
  285. g_assert (!data[0].freed);
  286. }
  287. {
  288. data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
  289. g_test_message ("->create_from_inert()");
  290. obj = o->create_from_inert ();
  291. if (!obj)
  292. continue;
  293. if (obj == o->get_empty ())
  294. continue; /* Tested already */
  295. g_assert (obj == o->reference (obj));
  296. o->destroy (obj);
  297. if (o->is_immutable)
  298. g_assert (!o->is_immutable (obj));
  299. g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
  300. g_assert (o->get_user_data (obj, &key[0]));
  301. o->destroy (obj);
  302. g_assert (data[0].freed);
  303. }
  304. }
  305. }
  306. int
  307. main (int argc, char **argv)
  308. {
  309. hb_test_init (&argc, &argv);
  310. hb_test_add (test_object);
  311. return hb_test_run ();
  312. }