Imported Upstream version 2.73.3
[platform/upstream/glib.git] / gio / tests / resources.c
1 /* GLib testing framework examples and tests
2  *
3  * Copyright (C) 2011 Red Hat, Inc.
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General
18  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <string.h>
22 #include <gio/gio.h>
23 #include <glibconfig.h>
24 #include "gconstructor.h"
25 #include "test_resources2.h"
26 #include "digit_test_resources.h"
27
28 #ifdef _MSC_VER
29 # define MODULE_FILENAME_PREFIX ""
30 #else
31 # define MODULE_FILENAME_PREFIX "lib"
32 #endif
33
34 static void
35 test_resource (GResource *resource)
36 {
37   GError *error = NULL;
38   gboolean found, success;
39   gsize size;
40   guint32 flags;
41   GBytes *data;
42   char **children;
43   GInputStream *in;
44   char buffer[128];
45   const gchar *not_found_paths[] =
46     {
47       "/not/there",
48       "/",
49       "",
50     };
51   gsize i;
52
53   for (i = 0; i < G_N_ELEMENTS (not_found_paths); i++)
54     {
55       found = g_resource_get_info (resource,
56                                    not_found_paths[i],
57                                    G_RESOURCE_LOOKUP_FLAGS_NONE,
58                                    &size, &flags, &error);
59       g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
60       g_clear_error (&error);
61       g_assert_false (found);
62     }
63
64   found = g_resource_get_info (resource,
65                                "/test1.txt",
66                                G_RESOURCE_LOOKUP_FLAGS_NONE,
67                                &size, &flags, &error);
68   g_assert_true (found);
69   g_assert_no_error (error);
70   g_assert_cmpint (size, ==, 6);
71   g_assert_cmpuint (flags, ==, G_RESOURCE_FLAGS_COMPRESSED);
72
73   found = g_resource_get_info (resource,
74                                "/empty.txt",
75                                G_RESOURCE_LOOKUP_FLAGS_NONE,
76                                &size, &flags, &error);
77   g_assert_true (found);
78   g_assert_no_error (error);
79   g_assert_cmpint (size, ==, 0);
80   g_assert_cmpuint (flags, ==, G_RESOURCE_FLAGS_COMPRESSED);
81
82   found = g_resource_get_info (resource,
83                                "/a_prefix/test2.txt",
84                                G_RESOURCE_LOOKUP_FLAGS_NONE,
85                                &size, &flags, &error);
86   g_assert_true (found);
87   g_assert_no_error (error);
88   g_assert_cmpint (size, ==, 6);
89   g_assert_cmpuint (flags, ==, 0);
90
91   found = g_resource_get_info (resource,
92                                "/a_prefix/test2-alias.txt",
93                                G_RESOURCE_LOOKUP_FLAGS_NONE,
94                                &size, &flags, &error);
95   g_assert_true (found);
96   g_assert_no_error (error);
97   g_assert_cmpint (size, ==, 6);
98   g_assert_cmpuint (flags, ==, 0);
99
100   for (i = 0; i < G_N_ELEMENTS (not_found_paths); i++)
101     {
102       data = g_resource_lookup_data (resource,
103                                      not_found_paths[i],
104                                      G_RESOURCE_LOOKUP_FLAGS_NONE,
105                                      &error);
106       g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
107       g_clear_error (&error);
108       g_assert_null (data);
109     }
110
111   data = g_resource_lookup_data (resource,
112                                  "/test1.txt",
113                                  G_RESOURCE_LOOKUP_FLAGS_NONE,
114                                  &error);
115   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test1\n");
116   g_assert_no_error (error);
117   g_bytes_unref (data);
118
119   data = g_resource_lookup_data (resource,
120                                  "/empty.txt",
121                                  G_RESOURCE_LOOKUP_FLAGS_NONE,
122                                  &error);
123   g_assert_cmpuint (g_bytes_get_size (data), ==, 0);
124   g_assert_no_error (error);
125   g_bytes_unref (data);
126
127   for (i = 0; i < G_N_ELEMENTS (not_found_paths); i++)
128     {
129       in = g_resource_open_stream (resource,
130                                    not_found_paths[i],
131                                    G_RESOURCE_LOOKUP_FLAGS_NONE,
132                                    &error);
133       g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
134       g_clear_error (&error);
135       g_assert_null (in);
136     }
137
138   in = g_resource_open_stream (resource,
139                                "/test1.txt",
140                                G_RESOURCE_LOOKUP_FLAGS_NONE,
141                                &error);
142   g_assert_nonnull (in);
143   g_assert_no_error (error);
144
145   success = g_input_stream_read_all (in, buffer, sizeof (buffer) - 1,
146                                      &size,
147                                      NULL, &error);
148   g_assert_true (success);
149   g_assert_no_error (error);
150   g_assert_cmpint (size, ==, 6);
151   buffer[size] = 0;
152   g_assert_cmpstr (buffer, ==, "test1\n");
153
154   g_input_stream_close (in, NULL, &error);
155   g_assert_no_error (error);
156   g_clear_object (&in);
157
158   in = g_resource_open_stream (resource,
159                                "/empty.txt",
160                                G_RESOURCE_LOOKUP_FLAGS_NONE,
161                                &error);
162   g_assert_no_error (error);
163   g_assert_nonnull (in);
164
165   success = g_input_stream_read_all (in, buffer, sizeof (buffer) - 1,
166                                      &size,
167                                      NULL, &error);
168   g_assert_no_error (error);
169   g_assert_true (success);
170   g_assert_cmpint (size, ==, 0);
171
172   g_input_stream_close (in, NULL, &error);
173   g_assert_no_error (error);
174   g_clear_object (&in);
175
176   data = g_resource_lookup_data (resource,
177                                  "/a_prefix/test2.txt",
178                                  G_RESOURCE_LOOKUP_FLAGS_NONE,
179                                  &error);
180   g_assert_nonnull (data);
181   g_assert_no_error (error);
182   size = g_bytes_get_size (data);
183   g_assert_cmpint (size, ==, 6);
184   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test2\n");
185   g_bytes_unref (data);
186
187   data = g_resource_lookup_data (resource,
188                                  "/a_prefix/test2-alias.txt",
189                                  G_RESOURCE_LOOKUP_FLAGS_NONE,
190                                  &error);
191   g_assert_nonnull (data);
192   g_assert_no_error (error);
193   size = g_bytes_get_size (data);
194   g_assert_cmpint (size, ==, 6);
195   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test2\n");
196   g_bytes_unref (data);
197
198   for (i = 0; i < G_N_ELEMENTS (not_found_paths); i++)
199     {
200       if (g_str_equal (not_found_paths[i], "/"))
201         continue;
202
203       children = g_resource_enumerate_children (resource,
204                                                 not_found_paths[i],
205                                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
206                                                 &error);
207       g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
208       g_clear_error (&error);
209       g_assert_null (children);
210     }
211
212   children = g_resource_enumerate_children  (resource,
213                                              "/a_prefix",
214                                              G_RESOURCE_LOOKUP_FLAGS_NONE,
215                                              &error);
216   g_assert_nonnull (children);
217   g_assert_no_error (error);
218   g_assert_cmpint (g_strv_length (children), ==, 2);
219   g_strfreev (children);
220
221   /* Test the preferred lookup where we have a trailing slash. */
222   children = g_resource_enumerate_children  (resource,
223                                              "/a_prefix/",
224                                              G_RESOURCE_LOOKUP_FLAGS_NONE,
225                                              &error);
226   g_assert_nonnull (children);
227   g_assert_no_error (error);
228   g_assert_cmpint (g_strv_length (children), ==, 2);
229   g_strfreev (children);
230
231   /* test with a path > 256 and no trailing slash to test the
232    * slow path of resources where we allocate a modified path.
233    */
234   children = g_resource_enumerate_children  (resource,
235                                              "/not/here/not/here/not/here/not/here/not/here/not/here/not/here"
236                                              "/not/here/not/here/not/here/not/here/not/here/not/here/not/here"
237                                              "/not/here/not/here/not/here/not/here/not/here/not/here/not/here"
238                                              "/not/here/not/here/not/here/not/here/not/here/not/here/not/here"
239                                              "/not/here/not/here/not/here/not/here/not/here/not/here/not/here"
240                                              "/with/no/trailing/slash",
241                                              G_RESOURCE_LOOKUP_FLAGS_NONE,
242                                              &error);
243   g_assert_null (children);
244   g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
245   g_clear_error (&error);
246 }
247
248 static void
249 test_resource_file (void)
250 {
251   GResource *resource;
252   GError *error = NULL;
253
254   resource = g_resource_load ("not-there", &error);
255   g_assert_null (resource);
256   g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
257   g_clear_error (&error);
258
259   resource = g_resource_load (g_test_get_filename (G_TEST_BUILT, "test.gresource", NULL), &error);
260   g_assert_nonnull (resource);
261   g_assert_no_error (error);
262
263   test_resource (resource);
264   g_resource_unref (resource);
265 }
266
267 static void
268 test_resource_file_path (void)
269 {
270   static const struct {
271     const gchar *input;
272     const gchar *expected;
273   } test_uris[] = {
274     { "resource://", "resource:///" },
275     { "resource:///", "resource:///" },
276     { "resource://////", "resource:///" },
277     { "resource:///../../../", "resource:///" },
278     { "resource:///../../..", "resource:///" },
279     { "resource://abc", "resource:///abc" },
280     { "resource:///abc/", "resource:///abc" },
281     { "resource:/a/b/../c/", "resource:///a/c" },
282     { "resource://../a/b/../c/../", "resource:///a" },
283     { "resource://a/b/cc//bb//a///", "resource:///a/b/cc/bb/a" },
284     { "resource://././././", "resource:///" },
285     { "resource://././././../", "resource:///" },
286     { "resource://a/b/c/d.png", "resource:///a/b/c/d.png" },
287     { "resource://a/b/c/..png", "resource:///a/b/c/..png" },
288     { "resource://a/b/c/./png", "resource:///a/b/c/png" },
289   };
290   guint i;
291
292   for (i = 0; i < G_N_ELEMENTS (test_uris); i++)
293     {
294       GFile *file;
295       gchar *uri;
296
297       file = g_file_new_for_uri (test_uris[i].input);
298       g_assert_nonnull (file);
299
300       uri = g_file_get_uri (file);
301       g_assert_nonnull (uri);
302
303       g_assert_cmpstr (uri, ==, test_uris[i].expected);
304
305       g_object_unref (file);
306       g_free (uri);
307     }
308 }
309
310 static void
311 test_resource_data (void)
312 {
313   GResource *resource;
314   GError *error = NULL;
315   gboolean loaded_file;
316   char *content;
317   gsize content_size;
318   GBytes *data;
319
320   loaded_file = g_file_get_contents (g_test_get_filename (G_TEST_BUILT, "test.gresource", NULL),
321                                      &content, &content_size, NULL);
322   g_assert_true (loaded_file);
323
324   data = g_bytes_new_take (content, content_size);
325   resource = g_resource_new_from_data (data, &error);
326   g_bytes_unref (data);
327   g_assert_nonnull (resource);
328   g_assert_no_error (error);
329
330   test_resource (resource);
331
332   g_resource_unref (resource);
333 }
334
335 static void
336 test_resource_data_unaligned (void)
337 {
338   GResource *resource;
339   GError *error = NULL;
340   gboolean loaded_file;
341   char *content, *content_copy;
342   gsize content_size;
343   GBytes *data;
344
345   loaded_file = g_file_get_contents (g_test_get_filename (G_TEST_BUILT, "test.gresource", NULL),
346                                      &content, &content_size, NULL);
347   g_assert_true (loaded_file);
348
349   content_copy = g_new (char, content_size + 1);
350   memcpy (content_copy + 1, content, content_size);
351
352   data = g_bytes_new_with_free_func (content_copy + 1, content_size,
353                                      (GDestroyNotify) g_free, content_copy);
354   g_free (content);
355   resource = g_resource_new_from_data (data, &error);
356   g_bytes_unref (data);
357   g_assert_nonnull (resource);
358   g_assert_no_error (error);
359
360   test_resource (resource);
361
362   g_resource_unref (resource);
363 }
364
365 /* Test error handling for corrupt GResource files (specifically, a corrupt
366  * GVDB header). */
367 static void
368 test_resource_data_corrupt (void)
369 {
370   /* A GVDB header is 6 guint32s, and requires a magic number in the first two
371    * guint32s. A set of zero bytes of a greater length is considered corrupt. */
372   static const guint8 data[sizeof (guint32) * 7] = { 0, };
373   GBytes *bytes = NULL;
374   GResource *resource = NULL;
375   GError *local_error = NULL;
376
377   bytes = g_bytes_new_static (data, sizeof (data));
378   resource = g_resource_new_from_data (bytes, &local_error);
379   g_bytes_unref (bytes);
380   g_assert_error (local_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_INTERNAL);
381   g_assert_null (resource);
382
383   g_clear_error (&local_error);
384 }
385
386 /* Test handling for empty GResource files. They should also be treated as
387  * corrupt. */
388 static void
389 test_resource_data_empty (void)
390 {
391   GBytes *bytes = NULL;
392   GResource *resource = NULL;
393   GError *local_error = NULL;
394
395   bytes = g_bytes_new_static (NULL, 0);
396   resource = g_resource_new_from_data (bytes, &local_error);
397   g_bytes_unref (bytes);
398   g_assert_error (local_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_INTERNAL);
399   g_assert_null (resource);
400
401   g_clear_error (&local_error);
402 }
403
404 static void
405 test_resource_registered (void)
406 {
407   GResource *resource;
408   GError *error = NULL;
409   gboolean found, success;
410   gsize size;
411   guint32 flags;
412   GBytes *data;
413   char **children;
414   GInputStream *in;
415   char buffer[128];
416
417   resource = g_resource_load (g_test_get_filename (G_TEST_BUILT, "test.gresource", NULL), &error);
418   g_assert_nonnull (resource);
419   g_assert_no_error (error);
420
421   found = g_resources_get_info ("/test1.txt",
422                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
423                                 &size, &flags, &error);
424   g_assert_false (found);
425   g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
426   g_clear_error (&error);
427
428   g_resources_register (resource);
429
430   found = g_resources_get_info ("/test1.txt",
431                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
432                                 &size, &flags, &error);
433   g_assert_true (found);
434   g_assert_no_error (error);
435   g_assert_cmpint (size, ==, 6);
436   g_assert_cmpint (flags, ==, G_RESOURCE_FLAGS_COMPRESSED);
437
438   found = g_resources_get_info ("/empty.txt",
439                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
440                                 &size, &flags, &error);
441   g_assert_no_error (error);
442   g_assert_true (found);
443   g_assert_cmpint (size, ==, 0);
444   g_assert_cmpint (flags, ==, G_RESOURCE_FLAGS_COMPRESSED);
445
446   found = g_resources_get_info ("/a_prefix/test2.txt",
447                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
448                                 &size, &flags, &error);
449   g_assert_true (found);
450   g_assert_no_error (error);
451   g_assert_cmpint (size, ==, 6);
452   g_assert_cmpint (flags, ==, 0);
453
454   found = g_resources_get_info ("/a_prefix/test2-alias.txt",
455                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
456                                 &size, &flags, &error);
457   g_assert_true (found);
458   g_assert_no_error (error);
459   g_assert_cmpint (size, ==, 6);
460   g_assert_cmpuint (flags, ==, 0);
461
462   data = g_resources_lookup_data ("/test1.txt",
463                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
464                                   &error);
465   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test1\n");
466   g_assert_no_error (error);
467   g_bytes_unref (data);
468
469   in = g_resources_open_stream ("/test1.txt",
470                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
471                                 &error);
472   g_assert_nonnull (in);
473   g_assert_no_error (error);
474
475   success = g_input_stream_read_all (in, buffer, sizeof (buffer) - 1,
476                                      &size,
477                                      NULL, &error);
478   g_assert_true (success);
479   g_assert_no_error (error);
480   g_assert_cmpint (size, ==, 6);
481   buffer[size] = 0;
482   g_assert_cmpstr (buffer, ==, "test1\n");
483
484   g_input_stream_close (in, NULL, &error);
485   g_assert_no_error (error);
486   g_clear_object (&in);
487
488   data = g_resources_lookup_data ("/empty.txt",
489                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
490                                   &error);
491   g_assert_no_error (error);
492   g_assert_cmpuint (g_bytes_get_size (data), ==, 0);
493   g_bytes_unref (data);
494
495   in = g_resources_open_stream ("/empty.txt",
496                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
497                                 &error);
498   g_assert_no_error (error);
499   g_assert_nonnull (in);
500
501   success = g_input_stream_read_all (in, buffer, sizeof (buffer) - 1,
502                                      &size,
503                                      NULL, &error);
504   g_assert_no_error (error);
505   g_assert_true (success);
506   g_assert_cmpint (size, ==, 0);
507
508   g_input_stream_close (in, NULL, &error);
509   g_assert_no_error (error);
510   g_clear_object (&in);
511
512   data = g_resources_lookup_data ("/a_prefix/test2.txt",
513                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
514                                   &error);
515   g_assert_nonnull (data);
516   g_assert_no_error (error);
517   size = g_bytes_get_size (data);
518   g_assert_cmpint (size, ==, 6);
519   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test2\n");
520   g_bytes_unref (data);
521
522   data = g_resources_lookup_data ("/a_prefix/test2-alias.txt",
523                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
524                                   &error);
525   g_assert_nonnull (data);
526   g_assert_no_error (error);
527   size = g_bytes_get_size (data);
528   g_assert_cmpint (size, ==, 6);
529   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test2\n");
530   g_bytes_unref (data);
531
532   children = g_resources_enumerate_children ("/not/here",
533                                              G_RESOURCE_LOOKUP_FLAGS_NONE,
534                                              &error);
535   g_assert_null (children);
536   g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
537   g_clear_error (&error);
538
539   children = g_resources_enumerate_children ("/a_prefix",
540                                              G_RESOURCE_LOOKUP_FLAGS_NONE,
541                                              &error);
542   g_assert_nonnull (children);
543   g_assert_no_error (error);
544   g_assert_cmpint (g_strv_length (children), ==, 2);
545   g_strfreev (children);
546
547   g_resources_unregister (resource);
548   g_resource_unref (resource);
549
550   found = g_resources_get_info ("/test1.txt",
551                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
552                                 &size, &flags, &error);
553   g_assert_false (found);
554   g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
555   g_clear_error (&error);
556 }
557
558 static void
559 test_resource_automatic (void)
560 {
561   GError *error = NULL;
562   gboolean found;
563   gsize size;
564   guint32 flags;
565   GBytes *data;
566
567   found = g_resources_get_info ("/auto_loaded/test1.txt",
568                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
569                                 &size, &flags, &error);
570   g_assert_true (found);
571   g_assert_no_error (error);
572   g_assert_cmpint (size, ==, 6);
573   g_assert_cmpint (flags, ==, 0);
574
575   data = g_resources_lookup_data ("/auto_loaded/test1.txt",
576                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
577                                   &error);
578   g_assert_nonnull (data);
579   g_assert_no_error (error);
580   size = g_bytes_get_size (data);
581   g_assert_cmpint (size, ==, 6);
582   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test1\n");
583   g_bytes_unref (data);
584 }
585
586 static void
587 test_resource_manual (void)
588 {
589   GError *error = NULL;
590   gboolean found;
591   gsize size;
592   guint32 flags;
593   GBytes *data;
594
595   found = g_resources_get_info ("/manual_loaded/test1.txt",
596                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
597                                 &size, &flags, &error);
598   g_assert_true (found);
599   g_assert_no_error (error);
600   g_assert_cmpint (size, ==, 6);
601   g_assert_cmpuint (flags, ==, 0);
602
603   data = g_resources_lookup_data ("/manual_loaded/test1.txt",
604                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
605                                   &error);
606   g_assert_nonnull (data);
607   g_assert_no_error (error);
608   size = g_bytes_get_size (data);
609   g_assert_cmpint (size, ==, 6);
610   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test1\n");
611   g_bytes_unref (data);
612 }
613
614 static void
615 test_resource_manual2 (void)
616 {
617   GResource *resource;
618   GBytes *data;
619   gsize size;
620   GError *error = NULL;
621
622   resource = _g_test2_get_resource ();
623
624   data = g_resource_lookup_data (resource,
625                                  "/manual_loaded/test1.txt",
626                                  G_RESOURCE_LOOKUP_FLAGS_NONE,
627                                  &error);
628   g_assert_nonnull (data);
629   g_assert_no_error (error);
630   size = g_bytes_get_size (data);
631   g_assert_cmpint (size, ==, 6);
632   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test1\n");
633   g_bytes_unref (data);
634
635   g_resource_unref (resource);
636 }
637
638 /* Test building resources with external data option,
639  * where data is linked in as binary instead of compiled in.
640  * Checks if resources are automatically registered and
641  * data can be found and read. */
642 static void
643 test_resource_binary_linked (void)
644 {
645   #ifndef __linux__
646   g_test_skip ("--external-data test only works on Linux");
647   return;
648   #else /* if __linux__ */
649   GError *error = NULL;
650   gboolean found;
651   gsize size;
652   guint32 flags;
653   GBytes *data;
654
655   found = g_resources_get_info ("/binary_linked/test1.txt",
656                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
657                                 &size, &flags, &error);
658   g_assert_true (found);
659   g_assert_no_error (error);
660   g_assert_cmpint (size, ==, 6);
661   g_assert_cmpuint (flags, ==, 0);
662
663   data = g_resources_lookup_data ("/binary_linked/test1.txt",
664                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
665                                   &error);
666   g_assert_nonnull (data);
667   g_assert_no_error (error);
668   size = g_bytes_get_size (data);
669   g_assert_cmpint (size, ==, 6);
670   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test1\n");
671   g_bytes_unref (data);
672   #endif /* if __linux__ */
673 }
674
675 /* Test resource whose xml file starts with more than one digit
676  * and where no explicit c-name is given
677  * Checks if resources are successfully registered and
678  * data can be found and read. */
679 static void
680 test_resource_digits (void)
681 {
682   GError *error = NULL;
683   gboolean found;
684   gsize size;
685   guint32 flags;
686   GBytes *data;
687
688   found = g_resources_get_info ("/digit_test/test1.txt",
689                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
690                                 &size, &flags, &error);
691   g_assert_true (found);
692   g_assert_no_error (error);
693   g_assert_cmpint (size, ==, 6);
694   g_assert_cmpuint (flags, ==, 0);
695
696   data = g_resources_lookup_data ("/digit_test/test1.txt",
697                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
698                                   &error);
699   g_assert_nonnull (data);
700   g_assert_no_error (error);
701   size = g_bytes_get_size (data);
702   g_assert_cmpint (size, ==, 6);
703   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test1\n");
704   g_bytes_unref (data);
705 }
706
707 static void
708 test_resource_module (void)
709 {
710   GIOModule *module;
711   gboolean found;
712   gsize size;
713   guint32 flags;
714   GBytes *data;
715   GError *error;
716
717 #ifdef GLIB_STATIC_COMPILATION
718   /* The resource module is statically linked with a separate copy
719    * of a GLib so g_static_resource_init won't work as expected. */
720   g_test_skip ("Resource modules aren't supported in static builds.");
721   return;
722 #endif
723
724   if (g_module_supported ())
725     {
726       module = g_io_module_new (g_test_get_filename (G_TEST_BUILT,
727                                                      MODULE_FILENAME_PREFIX "resourceplugin",
728                                                      NULL));
729
730       error = NULL;
731
732       found = g_resources_get_info ("/resourceplugin/test1.txt",
733                                     G_RESOURCE_LOOKUP_FLAGS_NONE,
734                                     &size, &flags, &error);
735       g_assert_false (found);
736       g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
737       g_clear_error (&error);
738
739       g_type_module_use (G_TYPE_MODULE (module));
740
741       found = g_resources_get_info ("/resourceplugin/test1.txt",
742                                     G_RESOURCE_LOOKUP_FLAGS_NONE,
743                                     &size, &flags, &error);
744       g_assert_true (found);
745       g_assert_no_error (error);
746       g_assert_cmpint (size, ==, 6);
747       g_assert_cmpuint (flags, ==, 0);
748
749       data = g_resources_lookup_data ("/resourceplugin/test1.txt",
750                                       G_RESOURCE_LOOKUP_FLAGS_NONE,
751                                       &error);
752       g_assert_nonnull (data);
753       g_assert_no_error (error);
754       size = g_bytes_get_size (data);
755       g_assert_cmpint (size, ==, 6);
756       g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test1\n");
757       g_bytes_unref (data);
758
759       g_type_module_unuse (G_TYPE_MODULE (module));
760
761       found = g_resources_get_info ("/resourceplugin/test1.txt",
762                                     G_RESOURCE_LOOKUP_FLAGS_NONE,
763                                     &size, &flags, &error);
764       g_assert_false (found);
765       g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
766       g_clear_error (&error);
767
768       g_clear_object (&module);
769     }
770 }
771
772 static void
773 test_uri_query_info (void)
774 {
775   GResource *resource;
776   GError *error = NULL;
777   gboolean loaded_file;
778   char *content;
779   gsize content_size;
780   GBytes *data;
781   GFile *file;
782   GFileInfo *info;
783   const char *content_type;
784   gchar *mime_type = NULL;
785   const char *fs_type;
786   gboolean readonly;
787
788   loaded_file = g_file_get_contents (g_test_get_filename (G_TEST_BUILT, "test.gresource", NULL),
789                                      &content, &content_size, NULL);
790   g_assert_true (loaded_file);
791
792   data = g_bytes_new_take (content, content_size);
793   resource = g_resource_new_from_data (data, &error);
794   g_bytes_unref (data);
795   g_assert_nonnull (resource);
796   g_assert_no_error (error);
797
798   g_resources_register (resource);
799
800   file = g_file_new_for_uri ("resource://" "/a_prefix/test2-alias.txt");
801   info = g_file_query_info (file, "*", 0, NULL, &error);
802   g_assert_no_error (error);
803
804   content_type = g_file_info_get_content_type (info);
805   g_assert_nonnull (content_type);
806   mime_type = g_content_type_get_mime_type (content_type);
807   g_assert_nonnull (mime_type);
808   g_assert_cmpstr (mime_type, ==, "text/plain");
809   g_free (mime_type);
810
811   g_object_unref (info);
812
813   info = g_file_query_filesystem_info (file, "*", NULL, &error);
814   g_assert_no_error (error);
815
816   fs_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE);
817   g_assert_cmpstr (fs_type, ==, "resource");
818   readonly = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY);
819   g_assert_true (readonly);
820
821   g_object_unref (info);
822
823   g_assert_cmpuint  (g_file_hash (file), !=, 0);
824
825   g_object_unref (file);
826
827   g_resources_unregister (resource);
828   g_resource_unref (resource);
829 }
830
831 static void
832 test_uri_file (void)
833 {
834   GResource *resource;
835   GError *error = NULL;
836   gboolean loaded_file;
837   char *content;
838   gsize content_size;
839   GBytes *data;
840   GFile *file;
841   GFileInfo *info;
842   gchar *name;
843   GFile *file2, *parent;
844   GFileEnumerator *enumerator;
845   gchar *scheme;
846   GFileAttributeInfoList *attrs;
847   GInputStream *stream;
848   gchar buf[1024];
849   gboolean ret;
850   gssize skipped;
851
852   loaded_file = g_file_get_contents (g_test_get_filename (G_TEST_BUILT, "test.gresource", NULL),
853                                      &content, &content_size, NULL);
854   g_assert_true (loaded_file);
855
856   data = g_bytes_new_take (content, content_size);
857   resource = g_resource_new_from_data (data, &error);
858   g_bytes_unref (data);
859   g_assert_nonnull (resource);
860   g_assert_no_error (error);
861
862   g_resources_register (resource);
863
864   file = g_file_new_for_uri ("resource://" "/a_prefix/test2-alias.txt");
865
866   g_assert_null (g_file_get_path (file));
867
868   name = g_file_get_parse_name (file);
869   g_assert_cmpstr (name, ==, "resource:///a_prefix/test2-alias.txt");
870   g_free (name);
871
872   name = g_file_get_uri (file);
873   g_assert_cmpstr (name, ==, "resource:///a_prefix/test2-alias.txt");
874   g_free (name);
875
876   g_assert_false (g_file_is_native (file));
877   g_assert_false (g_file_has_uri_scheme (file, "http"));
878   g_assert_true (g_file_has_uri_scheme (file, "resource"));
879   scheme = g_file_get_uri_scheme (file);
880   g_assert_cmpstr (scheme, ==, "resource");
881   g_free (scheme);
882
883   file2 = g_file_dup (file);
884   g_assert_true (g_file_equal (file, file2));
885   g_object_unref (file2);
886
887   parent = g_file_get_parent (file);
888   enumerator = g_file_enumerate_children (parent, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &error);
889   g_assert_no_error (error);
890
891   file2 = g_file_get_child_for_display_name (parent, "test2-alias.txt", &error);
892   g_assert_no_error (error);
893   g_assert_true (g_file_equal (file, file2));
894   g_object_unref (file2);
895
896   info = g_file_enumerator_next_file (enumerator, NULL, &error);
897   g_assert_no_error (error);
898   g_assert_nonnull (info);
899   g_object_unref (info);
900
901   info = g_file_enumerator_next_file (enumerator, NULL, &error);
902   g_assert_no_error (error);
903   g_assert_nonnull (info);
904   g_object_unref (info);
905
906   info = g_file_enumerator_next_file (enumerator, NULL, &error);
907   g_assert_no_error (error);
908   g_assert_null (info);
909
910   g_file_enumerator_close (enumerator, NULL, &error);
911   g_assert_no_error (error);
912   g_object_unref (enumerator);
913
914   file2 = g_file_new_for_uri ("resource://" "a_prefix/../a_prefix//test2-alias.txt");
915   g_assert_true (g_file_equal (file, file2));
916
917   g_assert_true (g_file_has_prefix (file, parent));
918
919   name = g_file_get_relative_path (parent, file);
920   g_assert_cmpstr (name, ==, "test2-alias.txt");
921   g_free (name);
922
923   g_object_unref (parent);
924
925   attrs = g_file_query_settable_attributes (file, NULL, &error);
926   g_assert_no_error (error);
927   g_file_attribute_info_list_unref (attrs);
928
929   attrs = g_file_query_writable_namespaces (file, NULL, &error);
930   g_assert_no_error (error);
931   g_file_attribute_info_list_unref (attrs);
932
933   stream = G_INPUT_STREAM (g_file_read (file, NULL, &error));
934   g_assert_no_error (error);
935   g_assert_cmpint (g_seekable_tell (G_SEEKABLE (stream)), ==, 0);
936   g_assert_true (g_seekable_can_seek (G_SEEKABLE (G_SEEKABLE (stream))));
937   ret = g_seekable_seek (G_SEEKABLE (stream), 1, G_SEEK_SET, NULL, &error);
938   g_assert_true (ret);
939   g_assert_no_error (error);
940   skipped = g_input_stream_skip (stream, 1, NULL, &error);
941   g_assert_cmpint (skipped, ==, 1);
942   g_assert_no_error (error);
943
944   memset (buf, 0, 1024);
945   ret = g_input_stream_read_all (stream, &buf, 1024, NULL, NULL, &error);
946   g_assert_true (ret);
947   g_assert_no_error (error);
948   g_assert_cmpstr (buf, ==, "st2\n");
949   info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (stream),
950                                          G_FILE_ATTRIBUTE_STANDARD_SIZE,
951                                          NULL,
952                                          &error);
953   g_assert_no_error (error);
954   g_assert_nonnull (info);
955   g_assert_cmpint (g_file_info_get_size (info), ==, 6);
956   g_object_unref (info);
957
958   ret = g_input_stream_close (stream, NULL, &error);
959   g_assert_true (ret);
960   g_assert_no_error (error);
961   g_object_unref (stream);
962
963   g_object_unref (file);
964   g_object_unref (file2);
965
966   g_resources_unregister (resource);
967   g_resource_unref (resource);
968 }
969
970 static void
971 test_resource_64k (void)
972 {
973   GError *error = NULL;
974   gboolean found;
975   gsize size;
976   guint32 flags;
977   GBytes *data;
978   gchar **tokens;
979
980   found = g_resources_get_info ("/big_prefix/gresource-big-test.txt",
981                                 G_RESOURCE_LOOKUP_FLAGS_NONE,
982                                 &size, &flags, &error);
983   g_assert_true (found);
984   g_assert_no_error (error);
985
986   /* Check size: 100 of all lower case letters + newline char +
987    *             100 all upper case letters + newline char +
988    *             100 of all numbers between 0 to 9 + newline char
989    *             (for 12 iterations)
990    */
991
992   g_assert_cmpint (size, ==, (26 + 26 + 10) * (100 + 1) * 12);
993   g_assert_cmpuint (flags, ==, 0);
994   data = g_resources_lookup_data ("/big_prefix/gresource-big-test.txt",
995                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
996                                   &error);
997   g_assert_nonnull (data);
998   g_assert_no_error (error);
999   size = g_bytes_get_size (data);
1000
1001   g_assert_cmpint (size, ==, (26 + 26 + 10) * (100 + 1) * 12);
1002   tokens = g_strsplit ((const gchar *) g_bytes_get_data (data, NULL), "\n", -1);
1003
1004   /* check tokens[x] == entry at gresource-big-test.txt's line, where x = line - 1 */
1005   g_assert_cmpstr (tokens[0], ==, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
1006   g_assert_cmpstr (tokens[27], ==, "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
1007   g_assert_cmpstr (tokens[183], ==, "7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777");
1008   g_assert_cmpstr (tokens[600], ==, "QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ");
1009   g_assert_cmpstr (tokens[742], ==, "8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888");
1010   g_strfreev (tokens);
1011   g_bytes_unref (data);
1012 }
1013
1014 /* Check that g_resources_get_info() respects G_RESOURCE_OVERLAYS */
1015 static void
1016 test_overlay (void)
1017 {
1018   if (g_test_subprocess ())
1019     {
1020        GError *error = NULL;
1021        gboolean res;
1022        gsize size;
1023        char *overlay;
1024        char *path;
1025
1026        path = g_test_build_filename (G_TEST_DIST, "test1.overlay", NULL);
1027        overlay = g_strconcat ("/auto_loaded/test1.txt=", path, NULL);
1028
1029        g_setenv ("G_RESOURCE_OVERLAYS", overlay, TRUE);
1030        res = g_resources_get_info ("/auto_loaded/test1.txt", 0, &size, NULL, &error);
1031        g_assert_true (res);
1032        g_assert_no_error (error);
1033        /* test1.txt is 6 bytes, test1.overlay is 23 */
1034        g_assert_cmpint (size, ==, 23);
1035
1036        g_free (overlay);
1037        g_free (path);
1038
1039        return;
1040     }
1041   g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDERR);
1042   g_test_trap_assert_passed ();
1043 }
1044
1045 int
1046 main (int   argc,
1047       char *argv[])
1048 {
1049   g_test_init (&argc, &argv, NULL);
1050
1051   _g_test2_register_resource ();
1052   _digit_test_register_resource ();
1053
1054   g_test_add_func ("/resource/file", test_resource_file);
1055   g_test_add_func ("/resource/file-path", test_resource_file_path);
1056   g_test_add_func ("/resource/data", test_resource_data);
1057   g_test_add_func ("/resource/data_unaligned", test_resource_data_unaligned);
1058   g_test_add_func ("/resource/data-corrupt", test_resource_data_corrupt);
1059   g_test_add_func ("/resource/data-empty", test_resource_data_empty);
1060   g_test_add_func ("/resource/registered", test_resource_registered);
1061   g_test_add_func ("/resource/manual", test_resource_manual);
1062   g_test_add_func ("/resource/manual2", test_resource_manual2);
1063 #ifdef G_HAS_CONSTRUCTORS
1064   g_test_add_func ("/resource/automatic", test_resource_automatic);
1065   /* This only uses automatic resources too, so it tests the constructors and destructors */
1066   g_test_add_func ("/resource/module", test_resource_module);
1067   g_test_add_func ("/resource/binary-linked", test_resource_binary_linked);
1068 #endif
1069   g_test_add_func ("/resource/uri/query-info", test_uri_query_info);
1070   g_test_add_func ("/resource/uri/file", test_uri_file);
1071   g_test_add_func ("/resource/64k", test_resource_64k);
1072   g_test_add_func ("/resource/overlay", test_overlay);
1073   g_test_add_func ("/resource/digits", test_resource_digits);
1074
1075   return g_test_run();
1076 }