[test/blob] Fix bug in test
[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 = malloc (sizeof (test_data));
161       memcpy ((char *) data, test_data, sizeof (test_data));
162       len = sizeof (test_data);
163       free_func = (hb_destroy_func_t) free_up_free;
164       break;
165
166 #if TEST_MMAP
167     case HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE:
168     {
169       uintptr_t pagesize = get_pagesize ();
170
171       data = mmap (NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
172       g_assert (data != (char *) -1);
173       memcpy ((char *) data, test_data, sizeof (test_data));
174       mprotect ((char *) data, pagesize, PROT_READ);
175       len = sizeof (test_data);
176       free_func = (hb_destroy_func_t) free_up_munmap;
177       break;
178     }
179 #endif
180
181     default:
182       g_assert_not_reached ();
183   }
184
185   fixture->freed = 0;
186   fixture->data = (char *) data;
187   fixture->len = len;
188   fixture->blob = hb_blob_create (data, len, mm, fixture, free_func);
189 }
190
191 static void
192 fixture_finish (fixture_t *fixture, gconstpointer user_data)
193 {
194   hb_blob_destroy (fixture->blob);
195   g_assert_cmpint (fixture->freed, ==, 1);
196 }
197
198
199 static void
200 test_blob (fixture_t *fixture, gconstpointer user_data)
201 {
202   hb_blob_t *b = fixture->blob;
203   hb_memory_mode_t mm = GPOINTER_TO_INT (user_data);
204   unsigned int len;
205   const char *data;
206   char *data_writable;
207   unsigned int i;
208
209   g_assert (b);
210
211   len = hb_blob_get_length (b);
212   g_assert_cmpint (len, ==, fixture->len);
213
214   data = hb_blob_get_data (b, &len);
215   g_assert_cmpint (len, ==, fixture->len);
216   if (mm == HB_MEMORY_MODE_DUPLICATE) {
217     g_assert (data != fixture->data);
218     g_assert_cmpint (fixture->freed, ==, 1);
219     mm = HB_MEMORY_MODE_WRITABLE;
220   } else {
221     g_assert (data == fixture->data);
222     g_assert_cmpint (fixture->freed, ==, 0);
223   }
224
225   data_writable = hb_blob_get_data_writable (b, &len);
226   g_assert_cmpint (len, ==, fixture->len);
227   g_assert (data_writable);
228   g_assert (0 == memcmp (data_writable, fixture->data, fixture->len));
229   if (mm == HB_MEMORY_MODE_READONLY) {
230     g_assert (data_writable != data);
231     g_assert_cmpint (fixture->freed, ==, 1);
232   } else {
233     g_assert (data_writable == data);
234   }
235
236   data = hb_blob_get_data (b, &len);
237   g_assert_cmpint (len, ==, fixture->len);
238   g_assert (data == data_writable);
239
240   memset (data_writable, 0, fixture->len);
241
242   /* Now, make it immutable and watch get_data_writable() fail */
243
244   g_assert (!hb_blob_is_immutable (b));
245   hb_blob_make_immutable (b);
246   g_assert (hb_blob_is_immutable (b));
247
248   data_writable = hb_blob_get_data_writable (b, &len);
249   g_assert (!data_writable);
250   g_assert_cmpint (len, ==, 0);
251
252   data = hb_blob_get_data (b, &len);
253   g_assert_cmpint (len, ==, fixture->len);
254   for (i = 0; i < len; i++)
255     g_assert ('\0' == data[i]);
256 }
257
258 static void
259 test_blob_subblob (fixture_t *fixture, gconstpointer user_data)
260 {
261   hb_blob_t *b = fixture->blob;
262
263   fixture->len -= 2;
264   fixture->data++;
265   fixture->blob = hb_blob_create_sub_blob (b, 1, fixture->len);
266   hb_blob_destroy (b);
267
268   test_blob (fixture, user_data);
269
270   fixture->data--;
271   fixture->len += 2;
272 }
273
274
275 int
276 main (int argc, char **argv)
277 {
278   unsigned int i;
279
280   hb_test_init (&argc, &argv);
281
282   hb_test_add (test_blob_empty);
283
284   for (i = 0; i < G_N_ELEMENTS (blob_names); i++)
285   {
286     const void *blob_type = GINT_TO_POINTER (i);
287     const char *blob_name = blob_names[i];
288
289     hb_test_add_fixture_flavor (fixture, blob_type, blob_name, test_blob);
290     hb_test_add_fixture_flavor (fixture, blob_type, blob_name, test_blob_subblob);
291   }
292
293   /*
294    * create_sub_blob
295    */
296
297   return hb_test_run ();
298 }