1 /* -*- Mode: C; c-basic-offset: 2; -*- */
2 /* GdkPixbuf library - test loaders
4 * Copyright (C) 2001 Søren Sandmann (sandmann@daimi.au.dk)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22 #include "gdk-pixbuf.h"
25 #include "test-images.h"
29 #define PRETEND_MEM_SIZE (16 * 1024 * 1024)
30 #define REMAINING_MEM_SIZE 5000
33 static int current_allocation = 0;
34 static int max_allocation = 0;
36 #define HEADER_SPACE sizeof(void*)
39 record_bytes (gpointer mem, gsize bytes)
42 (current_allocation + bytes) > max_allocation)
50 *(void **)mem = GINT_TO_POINTER (bytes);
52 g_assert (GPOINTER_TO_INT (*(void**)mem) == bytes);
54 g_assert (current_allocation >= 0);
55 current_allocation += bytes;
56 g_assert (current_allocation >= 0);
58 g_assert ( mem == (void*) ((((char*)mem) + HEADER_SPACE) - HEADER_SPACE) );
59 return ((char*)mem) + HEADER_SPACE;
63 limited_try_malloc (gsize n_bytes)
65 return record_bytes (malloc (n_bytes + HEADER_SPACE), n_bytes);
69 limited_malloc (gsize n_bytes)
71 return limited_try_malloc (n_bytes);
75 limited_calloc (gsize n_blocks,
78 int bytes = n_blocks * n_block_bytes + HEADER_SPACE;
79 gpointer mem = malloc (bytes);
80 memset (mem, 0, bytes);
81 return record_bytes (mem, n_blocks * n_block_bytes);
85 limited_free (gpointer mem)
87 gpointer real = ((char*)mem) - HEADER_SPACE;
89 g_assert (current_allocation >= 0);
90 current_allocation -= GPOINTER_TO_INT (*(void**)real);
91 g_assert (current_allocation >= 0);
97 limited_try_realloc (gpointer mem,
102 return limited_try_malloc (n_bytes);
110 real = ((char*)mem) - HEADER_SPACE;
112 g_assert (current_allocation >= 0);
113 current_allocation -= GPOINTER_TO_INT (*(void**)real);
114 g_assert (current_allocation >= 0);
116 return record_bytes (realloc (real, n_bytes + HEADER_SPACE), n_bytes);
121 limited_realloc (gpointer mem,
124 return limited_try_realloc (mem, n_bytes);
127 static GMemVTable limited_table = {
137 test_loader (const guchar *bytes, gsize len, gboolean data_is_ok)
139 GdkPixbufLoader *loader;
141 gboolean did_fail = FALSE;
143 loader = gdk_pixbuf_loader_new ();
144 gdk_pixbuf_loader_write (loader, bytes, len, &err);
151 gdk_pixbuf_loader_close (loader, &err);
158 g_object_unref (loader);
160 if (data_is_ok == did_fail)
167 mem_test (const guchar *bytes, gsize len)
169 gboolean did_fail = FALSE;
171 GdkPixbufLoader *loader;
172 GList *loaders = NULL;
176 loader = gdk_pixbuf_loader_new ();
177 gdk_pixbuf_loader_write (loader, bytes, len, &err);
184 gdk_pixbuf_loader_close (loader, NULL);
191 loaders = g_list_prepend (loaders, loader);
194 for (i = loaders; i != NULL; i = i->next)
195 g_object_unref (i->data);
196 g_list_free (loaders);
200 assault (const gchar *header, gsize header_size,
201 int n_images, gboolean verbose)
203 enum { N_CHARACTERS = 10000 };
205 for (j = 0; j < n_images; ++j)
209 GdkPixbufLoader *loader;
212 g_print ("'img' no: %d\n", j);
214 loader = gdk_pixbuf_loader_new ();
216 gdk_pixbuf_loader_write (loader, header, header_size, &err);
223 for (i = 0; i < N_CHARACTERS; ++i)
225 int r = g_random_int ();
230 for (j = 0; j < sizeof (r); j++)
231 g_print ("%u, ", ((guchar *)&r)[j]);
234 gdk_pixbuf_loader_write (loader, (guchar *)&r, sizeof (r), &err);
245 gdk_pixbuf_loader_close (loader, &err);
252 g_object_unref (loader);
257 randomly_modify (const guchar *image, guint size, gboolean verbose)
260 guchar *img_copy = g_malloc (size);
261 for (i = 0; i < size; i++)
262 img_copy [i] = image[i];
264 for (i = 0; i < size / 4; i++)
268 guint index = g_random_int_range (0, size);
269 guchar byte = g_random_int_range (0, 256);
271 img_copy[index] = byte;
275 g_print ("img no %d\n", i);
276 for (j = 0; j < size; j++)
277 g_print ("%u, ", img_copy[j]);
281 test_loader (img_copy, size, FALSE);
286 #define TEST(bytes, data_is_ok) \
288 g_print ("%-40s", " " #bytes " "); \
290 if (test_loader (bytes, sizeof (bytes), data_is_ok)) \
291 g_print ("\tpassed\n"); \
293 g_print ("\tFAILED\n"); \
296 #define LOWMEMTEST(bytes) \
298 g_print ("%-40s", "memory " #bytes " "); \
300 mem_test (bytes, sizeof (bytes)); \
301 g_print ("\tpassed\n"); \
304 #define TEST_RANDOM(header, n_img, verbose) \
306 static guchar h[] = { header }; \
307 g_print ("%-40s", "random " #header " "); \
309 assault (h, sizeof (h), n_img, verbose); \
310 g_print ("\tpassed\n"); \
313 #define TEST_RANDOMLY_MODIFIED(image, verbose) \
315 g_print ("%-40s", "randomly modified " #image " "); \
317 randomly_modify (image, sizeof (image), verbose); \
318 g_print ("\tpassed\n"); \
324 almost_exhaust_memory (void)
326 gpointer x = g_malloc (REMAINING_MEM_SIZE);
327 while (g_try_malloc (REMAINING_MEM_SIZE / 10))
333 write_seed (int seed)
336 /* write this so you can reproduce failed tests */
337 f = fopen ("test-loaders-seed", "w");
343 if (fprintf (f, "%d\n", seed) < 0)
353 g_print ("seed: %d\n", seed);
357 main (int argc, char **argv)
361 /* Set a malloc which emulates low mem */
362 max_allocation = G_MAXINT;
363 g_mem_set_vtable (&limited_table);
366 seed = atoi (argv[1]);
372 g_random_set_seed (seed);
375 g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
377 putenv ("GDK_PIXBUF_MODULEDIR="BUILT_MODULES_DIR);
379 TEST (valid_ppm_1, TRUE);
380 TEST (valid_ppm_2, TRUE);
381 TEST (valid_ppm_3, FALSE); /* image is valid, but we don't handle maxval > 255 */
382 TEST (valid_ppm_4, TRUE);
384 TEST (invalid_ppm_1, FALSE); /* this test fails to fail, because it's shorter than LOADER_HEADER_SIZE */
385 TEST (invalid_ppm_2, FALSE);
386 TEST (invalid_ppm_3, FALSE);
387 TEST (invalid_ppm_4, FALSE);
388 TEST (invalid_ppm_5, FALSE);
389 TEST (invalid_ppm_6, FALSE);
390 TEST (invalid_ppm_7, FALSE);
391 TEST (invalid_ppm_8, FALSE);
393 TEST (valid_gif_test, TRUE);
394 TEST (gif_test_1, FALSE);
395 TEST (gif_test_2, FALSE);
396 TEST (gif_test_3, FALSE);
397 TEST (gif_test_4, FALSE);
399 TEST (valid_png_test, TRUE);
400 TEST (png_test_1, FALSE);
401 TEST (png_test_2, FALSE);
404 TEST (valid_ico_test, TRUE);
405 TEST (ico_test_1, FALSE);
406 TEST (ico_test_2, FALSE);
408 TEST (valid_jpeg_test, TRUE);
410 TEST (valid_tiff1_test, TRUE);
411 TEST (tiff1_test_1, FALSE);
412 TEST (tiff1_test_2, FALSE);
414 TEST (tiff1_test_3, FALSE); /* Segfault in TIFFReadDirectory with libtiff 3.5.5, fixed in 3.5.7 */
417 TEST (valid_tga_test, TRUE);
418 TEST (tga_test_1, FALSE);
420 TEST (xpm_test_1, FALSE);
422 TEST (wbmp_test_1, FALSE);
423 TEST (wbmp_test_2, FALSE);
425 TEST_RANDOM (GIF_HEADER, 150, FALSE);
426 TEST_RANDOM (PNG_HEADER, 1100, FALSE);
427 TEST_RANDOM (JPEG_HEADER, 800, FALSE);
428 TEST_RANDOM (TIFF1_HEADER, 150, FALSE);
429 TEST_RANDOM (TIFF2_HEADER, 150, FALSE);
430 #define PNM_HEADER 'P', '6'
431 TEST_RANDOM (PNM_HEADER, 150, FALSE);
432 #define XBM_HEADER '#', 'd', 'e', 'f', 'i', 'n', 'e', ' '
433 TEST_RANDOM (XBM_HEADER, 150, FALSE);
434 #define BMP_HEADER 'B', 'M'
435 TEST_RANDOM (BMP_HEADER, 150, FALSE);
436 #define XPM_HEADER '/', '*', ' ', 'X', 'P', 'M', ' ', '*', '/'
437 TEST_RANDOM (XPM_HEADER, 150, FALSE);
440 TEST_RANDOMLY_MODIFIED (valid_tiff1_test, FALSE);
441 TEST_RANDOMLY_MODIFIED (valid_gif_test, FALSE);
442 TEST_RANDOMLY_MODIFIED (valid_png_test, FALSE);
443 TEST_RANDOMLY_MODIFIED (valid_tga_test, FALSE);
444 TEST_RANDOMLY_MODIFIED (valid_jpeg_test, FALSE);
445 TEST_RANDOMLY_MODIFIED (valid_ico_test, FALSE);
446 TEST_RANDOMLY_MODIFIED (valid_bmp_test, FALSE);
447 TEST_RANDOMLY_MODIFIED (valid_xpm_test, FALSE);
452 /* How do the loaders behave when memory is low?
453 It depends on the state the above tests left the
456 - Sometimes the png loader tries to report an
457 "out of memory", but then g_strdup_printf() calls
458 g_malloc(), which fails.
460 - There are unchecked realloc()s inside libtiff, which means it
461 will never work with low memory, unless something drastic is
462 done, like allocating a lot of memory upfront and release it
463 before entering libtiff. Also, some TIFFReadRGBAImage calls
464 returns successfully, even though they have called the error
465 handler with an 'out of memory' message.
468 max_allocation = PRETEND_MEM_SIZE;
469 almost_exhaust_memory ();
471 g_print ("Allocated %dK of %dK, %dK free during tests\n",
472 current_allocation / 1024, max_allocation / 1024,
473 (max_allocation - current_allocation) / 1024);
476 LOWMEMTEST (valid_tiff1_test);
478 LOWMEMTEST (valid_gif_test);
479 LOWMEMTEST (valid_png_test);
480 LOWMEMTEST (valid_jpeg_test);