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