91c11708d5a07a93db542842d894a6c3fa6d81b7
[apps/home/video-player.git] / test / test-blob.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-blob.h */
30
31 #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
32
33 # define TEST_MMAP 1
34
35 #ifdef HAVE_SYS_MMAN_H
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif /* HAVE_UNISTD_H */
39 #include <sys/mman.h>
40 #endif /* HAVE_SYS_MMAN_H */
41
42 #endif
43
44
45 static void
46 test_blob_empty (void)
47 {
48   hb_blob_t *blob;
49   unsigned int len;
50   const char *data;
51   char *data_writable;
52
53   g_assert (hb_blob_is_immutable (hb_blob_get_empty ()));
54   g_assert (hb_blob_get_empty () != NULL);
55
56   blob = hb_blob_get_empty ();
57   g_assert (blob == hb_blob_get_empty ());
58
59   len = hb_blob_get_length (blob);
60   g_assert_cmpint (len, ==, 0);
61
62   data = hb_blob_get_data (blob, NULL);
63   g_assert (data == NULL);
64
65   data = hb_blob_get_data (blob, &len);
66   g_assert (data == NULL);
67   g_assert_cmpint (len, ==, 0);
68
69   data_writable = hb_blob_get_data_writable (blob, NULL);
70   g_assert (data == NULL);
71
72   data_writable = hb_blob_get_data_writable (blob, &len);
73   g_assert (data_writable == NULL);
74   g_assert_cmpint (len, ==, 0);
75 }
76
77 static const char test_data[] = "test\0data";
78
79 static const char *blob_names[] = {
80   "duplicate",
81   "readonly",
82   "writable"
83 #ifdef TEST_MMAP
84    , "readonly-may-make-writable"
85 #endif
86 };
87
88 typedef struct
89 {
90   hb_blob_t *blob;
91   int freed;
92   char *data;
93   unsigned int len;
94 } fixture_t;
95
96 static void
97 free_up (fixture_t *fixture)
98 {
99   g_assert_cmpint (fixture->freed, ==, 0);
100   fixture->freed++;
101 }
102
103 static void
104 free_up_free (fixture_t *fixture)
105 {
106   free_up (fixture);
107   free (fixture->data);
108 }
109
110
111 static uintptr_t
112 get_pagesize (void)
113 {
114   uintptr_t pagesize = -1;
115
116 #if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
117   pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE);
118 #elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
119   pagesize = (uintptr_t) sysconf (_SC_PAGESIZE);
120 #elif defined(HAVE_GETPAGESIZE)
121   pagesize = (uintptr_t) getpagesize ();
122 #endif
123
124   g_assert (pagesize != (uintptr_t) -1);
125
126   return pagesize;
127 }
128
129 static void
130 free_up_munmap (fixture_t *fixture)
131 {
132   free_up (fixture);
133   munmap (fixture->data, get_pagesize ());
134 }
135
136 #include <errno.h>
137 static void
138 fixture_init (fixture_t *fixture, gconstpointer user_data)
139 {
140   hb_memory_mode_t mm = (hb_memory_mode_t) GPOINTER_TO_INT (user_data);
141   unsigned int len;
142   const char *data;
143   hb_destroy_func_t free_func;
144
145   switch (GPOINTER_TO_INT (user_data))
146   {
147     case HB_MEMORY_MODE_DUPLICATE:
148       data = test_data;
149       len = sizeof (test_data);
150       free_func = (hb_destroy_func_t) free_up;
151       break;
152
153     case HB_MEMORY_MODE_READONLY:
154       data = test_data;
155       len = sizeof (test_data);
156       free_func = (hb_destroy_func_t) free_up;
157       break;
158
159     case HB_MEMORY_MODE_WRITABLE:
160       data = strndup (test_data, sizeof (test_data));
161       len = sizeof (test_data);
162       free_func = (hb_destroy_func_t) free_up_free;
163       break;
164
165 #if TEST_MMAP
166     case HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE:
167     {
168       uintptr_t pagesize = get_pagesize ();
169
170       data = mmap (NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
171       g_assert (data != (char *) -1);
172       memcpy ((char *) data, test_data, sizeof (test_data));
173       mprotect ((char *) data, pagesize, PROT_READ);
174       len = sizeof (test_data);
175       free_func = (hb_destroy_func_t) free_up_munmap;
176       break;
177     }
178 #endif
179
180     default:
181       g_assert_not_reached ();
182   }
183
184   fixture->freed = 0;
185   fixture->data = (char *) data;
186   fixture->len = len;
187   fixture->blob = hb_blob_create (data, len, mm, fixture, free_func);
188 }
189
190 static void
191 fixture_finish (fixture_t *fixture, gconstpointer user_data)
192 {
193   hb_blob_destroy (fixture->blob);
194   g_assert_cmpint (fixture->freed, ==, 1);
195 }
196
197
198 static void
199 test_blob (fixture_t *fixture, gconstpointer user_data)
200 {
201   hb_blob_t *b = fixture->blob;
202   hb_memory_mode_t mm = GPOINTER_TO_INT (user_data);
203   unsigned int len;
204   const char *data;
205   char *data_writable;
206   unsigned int i;
207
208   g_assert (b);
209
210   len = hb_blob_get_length (b);
211   g_assert_cmpint (len, ==, fixture->len);
212
213   data = hb_blob_get_data (b, &len);
214   g_assert_cmpint (len, ==, fixture->len);
215   if (mm == HB_MEMORY_MODE_DUPLICATE) {
216     g_assert (data != fixture->data);
217     g_assert_cmpint (fixture->freed, ==, 1);
218     mm = HB_MEMORY_MODE_WRITABLE;
219   } else {
220     g_assert (data == fixture->data);
221     g_assert_cmpint (fixture->freed, ==, 0);
222   }
223
224   data_writable = hb_blob_get_data_writable (b, &len);
225   g_assert_cmpint (len, ==, fixture->len);
226   g_assert (data_writable);
227   g_assert (0 == memcmp (data_writable, fixture->data, fixture->len));
228   if (mm == HB_MEMORY_MODE_READONLY) {
229     g_assert (data_writable != data);
230     g_assert_cmpint (fixture->freed, ==, 1);
231   } else {
232     g_assert (data_writable == data);
233   }
234
235   data = hb_blob_get_data (b, &len);
236   g_assert_cmpint (len, ==, fixture->len);
237   g_assert (data == data_writable);
238
239   memset (data_writable, 0, fixture->len);
240
241   /* Now, make it immutable and watch get_data_writable() fail */
242
243   g_assert (!hb_blob_is_immutable (b));
244   hb_blob_make_immutable (b);
245   g_assert (hb_blob_is_immutable (b));
246
247   data_writable = hb_blob_get_data_writable (b, &len);
248   g_assert (!data_writable);
249   g_assert_cmpint (len, ==, 0);
250
251   data = hb_blob_get_data (b, &len);
252   g_assert_cmpint (len, ==, fixture->len);
253   for (i = 0; i < len; i++)
254     g_assert ('\0' == data[i]);
255 }
256
257 static void
258 test_blob_subblob (fixture_t *fixture, gconstpointer user_data)
259 {
260   hb_blob_t *b = fixture->blob;
261
262   fixture->len -= 2;
263   fixture->data++;
264   fixture->blob = hb_blob_create_sub_blob (b, 1, fixture->len);
265   hb_blob_destroy (b);
266
267   test_blob (fixture, user_data);
268
269   fixture->data--;
270   fixture->len += 2;
271 }
272
273
274 int
275 main (int argc, char **argv)
276 {
277   unsigned int i;
278
279   hb_test_init (&argc, &argv);
280
281   hb_test_add (test_blob_empty);
282
283   for (i = 0; i < G_N_ELEMENTS (blob_names); i++)
284   {
285     const void *blob_type = GINT_TO_POINTER (i);
286     const char *blob_name = blob_names[i];
287
288     hb_test_add_fixture_flavor (fixture, blob_type, blob_name, test_blob);
289     hb_test_add_fixture_flavor (fixture, blob_type, blob_name, test_blob_subblob);
290   }
291
292   /*
293    * create_sub_blob
294    */
295
296   return hb_test_run ();
297 }