| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- /*
- * Copyright © 2011 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
- #include "hb-test.h"
- /* Unit tests for hb-object-private.h */
- static void *
- create_blob (void)
- {
- static char data[] = "test data";
- return hb_blob_create (data, sizeof (data), HB_MEMORY_MODE_READONLY, NULL, NULL);
- }
- static void *
- create_blob_from_inert (void)
- {
- return hb_blob_create (NULL, 0, HB_MEMORY_MODE_DUPLICATE, NULL, NULL);
- }
- static void *
- create_buffer (void)
- {
- return hb_buffer_create ();
- }
- static void *
- create_buffer_from_inert (void)
- {
- return NULL;
- }
- static void *
- create_set (void)
- {
- return hb_set_create ();
- }
- static void *
- create_set_from_inert (void)
- {
- return NULL;
- }
- static void *
- create_face (void)
- {
- hb_blob_t *blob = (hb_blob_t *) create_blob ();
- hb_face_t *face = hb_face_create (blob, 0);
- hb_blob_destroy (blob);
- return face;
- }
- static void *
- create_face_from_inert (void)
- {
- return hb_face_create (hb_blob_get_empty (), 0);
- }
- static void *
- create_font (void)
- {
- hb_face_t *face = (hb_face_t *) create_face ();
- hb_font_t *font = hb_font_create (face);
- hb_face_destroy (face);
- return font;
- }
- static void *
- create_font_from_inert (void)
- {
- return hb_font_create (hb_face_get_empty ());
- }
- static void *
- create_font_funcs (void)
- {
- return hb_font_funcs_create ();
- }
- static void *
- create_font_funcs_from_inert (void)
- {
- return NULL;
- }
- static void *
- create_unicode_funcs (void)
- {
- return hb_unicode_funcs_create (NULL);
- }
- static void *
- create_unicode_funcs_from_inert (void)
- {
- return hb_unicode_funcs_create (hb_unicode_funcs_get_empty ());
- }
- typedef void *(*create_func_t) (void);
- typedef void *(*reference_func_t) (void *obj);
- typedef void (*destroy_func_t) (void *obj);
- 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);
- typedef void * (*get_user_data_func_t) (void *obj, hb_user_data_key_t *key);
- typedef void (*make_immutable_func_t) (void *obj);
- typedef hb_bool_t (*is_immutable_func_t) (void *obj);
- typedef struct {
- create_func_t create;
- create_func_t create_from_inert;
- create_func_t get_empty;
- reference_func_t reference;
- destroy_func_t destroy;
- set_user_data_func_t set_user_data;
- get_user_data_func_t get_user_data;
- make_immutable_func_t make_immutable;
- is_immutable_func_t is_immutable;
- const char *name;
- } object_t;
- #define OBJECT_WITHOUT_IMMUTABILITY(name) \
- { \
- (create_func_t) create_##name, \
- (create_func_t) create_##name##_from_inert, \
- (create_func_t) hb_##name##_get_empty, \
- (reference_func_t) hb_##name##_reference, \
- (destroy_func_t) hb_##name##_destroy, \
- (set_user_data_func_t) hb_##name##_set_user_data, \
- (get_user_data_func_t) hb_##name##_get_user_data, \
- (make_immutable_func_t) NULL, \
- (is_immutable_func_t) NULL, \
- #name, \
- }
- #define OBJECT_WITH_IMMUTABILITY(name) \
- { \
- (create_func_t) create_##name, \
- (create_func_t) create_##name##_from_inert, \
- (create_func_t) hb_##name##_get_empty, \
- (reference_func_t) hb_##name##_reference, \
- (destroy_func_t) hb_##name##_destroy, \
- (set_user_data_func_t) hb_##name##_set_user_data, \
- (get_user_data_func_t) hb_##name##_get_user_data, \
- (make_immutable_func_t) hb_##name##_make_immutable, \
- (is_immutable_func_t) hb_##name##_is_immutable, \
- #name, \
- }
- static const object_t objects[] =
- {
- OBJECT_WITHOUT_IMMUTABILITY (buffer),
- OBJECT_WITHOUT_IMMUTABILITY (set),
- OBJECT_WITH_IMMUTABILITY (blob),
- OBJECT_WITH_IMMUTABILITY (face),
- OBJECT_WITH_IMMUTABILITY (font),
- OBJECT_WITH_IMMUTABILITY (font_funcs),
- OBJECT_WITH_IMMUTABILITY (unicode_funcs)
- };
- #undef OBJECT
- #define MAGIC0 0x12345678
- #define MAGIC1 0x76543210
- typedef struct {
- int value;
- gboolean freed;
- } data_t;
- static int global_data;
- static void global_free_up (void *p G_GNUC_UNUSED)
- {
- global_data++;
- }
- static void free_up0 (void *p)
- {
- data_t *data = (data_t *) p;
- g_assert_cmphex (data->value, ==, MAGIC0);
- g_assert (!data->freed);
- data->freed = TRUE;
- }
- static void free_up1 (void *p)
- {
- data_t *data = (data_t *) p;
- g_assert_cmphex (data->value, ==, MAGIC1);
- g_assert (!data->freed);
- data->freed = TRUE;
- }
- typedef struct {
- const object_t *klass;
- void *object;
- hb_user_data_key_t key;
- } deadlock_test_t;
- static void free_deadlock_test (void *p)
- {
- deadlock_test_t *t = (deadlock_test_t *) p;
- g_assert (NULL == t->klass->get_user_data (t->object, &t->key));
- }
- static void
- test_object (void)
- {
- unsigned int i;
- for (i = 0; i < G_N_ELEMENTS (objects); i++) {
- const object_t *o = &objects[i];
- void *obj;
- hb_user_data_key_t key[1001];
- {
- unsigned int j;
- data_t data[1000] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
- deadlock_test_t deadlock_test;
- g_test_message ("Testing object %s", o->name);
- g_test_message ("->create()");
- obj = o->create ();
- g_assert (obj);
- g_assert (obj == o->reference (obj));
- o->destroy (obj);
- if (o->is_immutable)
- g_assert (!o->is_immutable (obj));
- g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
- g_assert (o->get_user_data (obj, &key[0]) == &data[0]);
- if (o->is_immutable) {
- o->make_immutable (obj);
- g_assert (o->is_immutable (obj));
- }
- /* Should still work even if object is made immutable */
- g_assert (o->set_user_data (obj, &key[1], &data[1], free_up1, TRUE));
- g_assert (o->get_user_data (obj, &key[1]) == &data[1]);
- g_assert (!o->set_user_data (obj, NULL, &data[0], free_up0, TRUE));
- g_assert (o->get_user_data (obj, &key[0]) == &data[0]);
- g_assert (o->set_user_data (obj, &key[0], &data[1], NULL, TRUE));
- g_assert (data[0].freed);
- g_assert (o->get_user_data (obj, &key[0]) == &data[1]);
- g_assert (!data[1].freed);
- data[0].freed = FALSE;
- g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
- g_assert (!data[0].freed);
- g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
- g_assert (data[0].freed);
- data[0].freed = FALSE;
- global_data = 0;
- g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
- g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, FALSE));
- g_assert_cmpuint (global_data, ==, 0);
- g_assert (o->set_user_data (obj, &key[0], NULL, global_free_up, TRUE));
- g_assert_cmpuint (global_data, ==, 0);
- g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
- g_assert_cmpuint (global_data, ==, 1);
- global_data = 0;
- for (j = 2; j < 1000; j++)
- g_assert (o->set_user_data (obj, &key[j], &data[j], global_free_up, TRUE));
- for (j = 2; j < 1000; j++)
- g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
- for (j = 100; j < 1000; j++)
- g_assert (o->set_user_data (obj, &key[j], NULL, NULL, TRUE));
- for (j = 2; j < 100; j++)
- g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
- for (j = 100; j < 1000; j++)
- g_assert (!o->get_user_data (obj, &key[j]));
- g_assert_cmpuint (global_data, ==, 900);
- /* Test set_user_data where the destroy() func calls user_data functions.
- * Make sure it doesn't deadlock or corrupt memory. */
- deadlock_test.klass = o;
- deadlock_test.object = obj;
- g_assert (o->set_user_data (obj, &deadlock_test.key, &deadlock_test, free_deadlock_test, TRUE));
- g_assert (o->set_user_data (obj, &deadlock_test.key, NULL, NULL, TRUE));
- g_assert (!data[1].freed);
- o->destroy (obj);
- g_assert (data[0].freed);
- g_assert (data[1].freed);
- g_assert_cmpuint (global_data, ==, 1000-2);
- }
- {
- data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
- g_test_message ("->get_empty()");
- obj = o->get_empty ();
- g_assert (obj);
- g_assert (obj == o->reference (obj));
- o->destroy (obj);
- if (o->is_immutable)
- g_assert (o->is_immutable (obj));
- g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
- g_assert (!o->get_user_data (obj, &key[0]));
- o->destroy (obj);
- o->destroy (obj);
- o->destroy (obj);
- o->destroy (obj);
- o->destroy (obj);
- g_assert (!data[0].freed);
- }
- {
- data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
- g_test_message ("->create_from_inert()");
- obj = o->create_from_inert ();
- if (!obj)
- continue;
- if (obj == o->get_empty ())
- continue; /* Tested already */
- g_assert (obj == o->reference (obj));
- o->destroy (obj);
- if (o->is_immutable)
- g_assert (!o->is_immutable (obj));
- g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
- g_assert (o->get_user_data (obj, &key[0]));
- o->destroy (obj);
- g_assert (data[0].freed);
- }
- }
- }
- int
- main (int argc, char **argv)
- {
- hb_test_init (&argc, &argv);
- hb_test_add (test_object);
- return hb_test_run ();
- }
|