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 /* Unit tests for hb-object-private.h */
35 static char data[] = "test data";
36 return hb_blob_create (data, sizeof (data), HB_MEMORY_MODE_READONLY, NULL, NULL);
39 create_blob_inert (void)
41 return hb_blob_create (NULL, 0, HB_MEMORY_MODE_DUPLICATE, NULL, NULL);
47 return hb_buffer_create ();
50 create_buffer_inert (void)
58 hb_blob_t *blob = (hb_blob_t *) create_blob ();
59 hb_face_t *face = hb_face_create (blob, 0);
60 hb_blob_destroy (blob);
64 create_face_inert (void)
66 return hb_face_create (hb_blob_get_empty (), 0);
72 hb_face_t *face = (hb_face_t *) create_face ();
73 hb_font_t *font = hb_font_create (face);
74 hb_face_destroy (face);
78 create_font_inert (void)
80 return hb_font_create (hb_face_get_empty ());
84 create_font_funcs (void)
86 return hb_font_funcs_create ();
89 create_font_funcs_inert (void)
95 create_unicode_funcs (void)
97 return hb_unicode_funcs_create (NULL);
100 create_unicode_funcs_inert (void)
102 return hb_unicode_funcs_get_default ();
107 typedef void *(*create_func_t) (void);
108 typedef void *(*reference_func_t) (void *obj);
109 typedef void (*destroy_func_t) (void *obj);
110 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);
111 typedef void * (*get_user_data_func_t) (void *obj, hb_user_data_key_t *key);
112 typedef void (*make_immutable_func_t) (void *obj);
113 typedef hb_bool_t (*is_immutable_func_t) (void *obj);
116 create_func_t create;
117 create_func_t create_inert;
118 create_func_t get_empty;
119 reference_func_t reference;
120 destroy_func_t destroy;
121 set_user_data_func_t set_user_data;
122 get_user_data_func_t get_user_data;
123 make_immutable_func_t make_immutable;
124 is_immutable_func_t is_immutable;
128 #define OBJECT_WITHOUT_IMMUTABILITY(name) \
130 (create_func_t) create_##name, \
131 (create_func_t) create_##name##_inert, \
132 (create_func_t) hb_##name##_get_empty, \
133 (reference_func_t) hb_##name##_reference, \
134 (destroy_func_t) hb_##name##_destroy, \
135 (set_user_data_func_t) hb_##name##_set_user_data, \
136 (get_user_data_func_t) hb_##name##_get_user_data, \
137 (make_immutable_func_t) NULL, \
138 (is_immutable_func_t) NULL, \
141 #define OBJECT_WITH_IMMUTABILITY(name) \
143 (create_func_t) create_##name, \
144 (create_func_t) create_##name##_inert, \
145 (create_func_t) hb_##name##_get_empty, \
146 (reference_func_t) hb_##name##_reference, \
147 (destroy_func_t) hb_##name##_destroy, \
148 (set_user_data_func_t) hb_##name##_set_user_data, \
149 (get_user_data_func_t) hb_##name##_get_user_data, \
150 (make_immutable_func_t) hb_##name##_make_immutable, \
151 (is_immutable_func_t) hb_##name##_is_immutable, \
154 static const object_t objects[] =
156 OBJECT_WITHOUT_IMMUTABILITY (buffer),
157 OBJECT_WITH_IMMUTABILITY (blob),
158 OBJECT_WITH_IMMUTABILITY (face),
159 OBJECT_WITH_IMMUTABILITY (font),
160 OBJECT_WITH_IMMUTABILITY (font_funcs),
161 OBJECT_WITH_IMMUTABILITY (unicode_funcs)
166 #define MAGIC0 0x12345678
167 #define MAGIC1 0x76543210
174 static int global_data;
176 static void global_free_up (void *p G_GNUC_UNUSED)
181 static void free_up0 (void *p)
183 data_t *data = (data_t *) p;
185 g_assert_cmphex (data->value, ==, MAGIC0);
186 g_assert (!data->freed);
190 static void free_up1 (void *p)
192 data_t *data = (data_t *) p;
194 g_assert_cmphex (data->value, ==, MAGIC1);
195 g_assert (!data->freed);
201 const object_t *klass;
203 hb_user_data_key_t key;
206 static void free_deadlock_test (void *p)
208 deadlock_test_t *t = (deadlock_test_t *) p;
210 g_assert (NULL == t->klass->get_user_data (t->object, &t->key));
219 for (i = 0; i < G_N_ELEMENTS (objects); i++) {
220 const object_t *o = &objects[i];
222 hb_user_data_key_t key[2];
226 data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
227 deadlock_test_t deadlock_test;
229 g_test_message ("Testing object %s", o->name);
231 g_test_message ("->create()");
235 g_assert (obj == o->reference (obj));
239 g_assert (!o->is_immutable (obj));
241 g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
242 g_assert (o->get_user_data (obj, &key[0]) == &data[0]);
244 if (o->is_immutable) {
245 o->make_immutable (obj);
246 g_assert (o->is_immutable (obj));
249 /* Should still work even if object is made immutable */
250 g_assert (o->set_user_data (obj, &key[1], &data[1], free_up1, TRUE));
251 g_assert (o->get_user_data (obj, &key[1]) == &data[1]);
253 g_assert (!o->set_user_data (obj, NULL, &data[0], free_up0, TRUE));
254 g_assert (o->get_user_data (obj, &key[0]) == &data[0]);
255 g_assert (o->set_user_data (obj, &key[0], &data[1], NULL, TRUE));
256 g_assert (data[0].freed);
257 g_assert (o->get_user_data (obj, &key[0]) == &data[1]);
258 g_assert (!data[1].freed);
260 data[0].freed = FALSE;
261 g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
262 g_assert (!data[0].freed);
263 g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
264 g_assert (data[0].freed);
266 data[0].freed = FALSE;
268 g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
269 g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, FALSE));
270 g_assert_cmpuint (global_data, ==, 0);
271 g_assert (o->set_user_data (obj, &key[0], NULL, global_free_up, TRUE));
272 g_assert_cmpuint (global_data, ==, 0);
273 g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
274 g_assert_cmpuint (global_data, ==, 1);
277 for (j = 2; j < 1000; j++)
278 g_assert (o->set_user_data (obj, &key[j], &data[j], global_free_up, TRUE));
279 for (j = 2; j < 1000; j++)
280 g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
281 for (j = 100; j < 1000; j++)
282 g_assert (o->set_user_data (obj, &key[j], NULL, NULL, TRUE));
283 for (j = 2; j < 100; j++)
284 g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
285 for (j = 100; j < 1000; j++)
286 g_assert (!o->get_user_data (obj, &key[j]));
287 g_assert_cmpuint (global_data, ==, 900);
289 /* Test set_user_data where the destroy() func calls user_data functions.
290 * Make sure it doesn't deadlock or corrupt memory. */
291 deadlock_test.klass = o;
292 deadlock_test.object = obj;
293 g_assert (o->set_user_data (obj, &deadlock_test.key, &deadlock_test, free_deadlock_test, TRUE));
294 g_assert (o->set_user_data (obj, &deadlock_test.key, NULL, NULL, TRUE));
296 g_assert (!data[1].freed);
298 g_assert (data[0].freed);
299 g_assert (data[1].freed);
300 g_assert_cmpuint (global_data, ==, 1000-2);
304 data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
306 g_test_message ("->get_empty()");
307 obj = o->get_empty ();
310 g_assert (obj == o->reference (obj));
314 g_assert (o->is_immutable (obj));
316 g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
317 g_assert (!o->get_user_data (obj, &key[0]));
325 g_assert (!data[0].freed);
329 data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
331 g_test_message ("->create_inert()");
332 obj = o->create_inert ();
335 if (obj == o->get_empty ())
336 continue; /* Tested already */
338 g_assert (obj == o->reference (obj));
342 g_assert (o->is_immutable (obj));
344 g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
345 g_assert (!o->get_user_data (obj, &key[0]));
353 g_assert (!data[0].freed);
360 main (int argc, char **argv)
362 hb_test_init (&argc, &argv);
364 hb_test_add (test_object);
366 return hb_test_run ();