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/gdk-pixbuf.h"
28 #define PRETEND_MEM_SIZE (16 * 1024 * 1024)
29 #define REMAINING_MEM_SIZE 100000
32 static int current_allocation = 0;
33 static int max_allocation = 0;
35 #define HEADER_SPACE sizeof(void*)
38 record_bytes (gpointer mem, gsize bytes)
41 (current_allocation + bytes) > max_allocation)
49 *(void **)mem = GINT_TO_POINTER (bytes);
51 g_assert (GPOINTER_TO_INT (*(void**)mem) == bytes);
53 g_assert (current_allocation >= 0);
54 current_allocation += bytes;
55 g_assert (current_allocation >= 0);
57 g_assert ( mem == (void*) ((((char*)mem) + HEADER_SPACE) - HEADER_SPACE) );
58 return ((char*)mem) + HEADER_SPACE;
62 limited_try_malloc (gsize n_bytes)
64 return record_bytes (malloc (n_bytes + HEADER_SPACE), n_bytes);
68 limited_malloc (gsize n_bytes)
70 return limited_try_malloc (n_bytes);
74 limited_calloc (gsize n_blocks,
77 int bytes = n_blocks * n_block_bytes + HEADER_SPACE;
78 gpointer mem = malloc (bytes);
79 memset (mem, 0, bytes);
80 return record_bytes (mem, n_blocks * n_block_bytes);
84 limited_free (gpointer mem)
86 gpointer real = ((char*)mem) - HEADER_SPACE;
88 g_assert (current_allocation >= 0);
89 current_allocation -= GPOINTER_TO_INT (*(void**)real);
90 g_assert (current_allocation >= 0);
96 limited_try_realloc (gpointer mem,
101 return limited_try_malloc (n_bytes);
109 real = ((char*)mem) - HEADER_SPACE;
111 g_assert (current_allocation >= 0);
112 current_allocation -= GPOINTER_TO_INT (*(void**)real);
113 g_assert (current_allocation >= 0);
115 return record_bytes (realloc (real, n_bytes + HEADER_SPACE), n_bytes);
120 limited_realloc (gpointer mem,
123 return limited_try_realloc (mem, n_bytes);
126 static GMemVTable limited_table = {
136 mem_test (const gchar *bytes, gsize len)
138 gboolean did_fail = FALSE;
140 GdkPixbufLoader *loader;
141 GList *loaders = NULL;
145 loader = gdk_pixbuf_loader_new ();
146 gdk_pixbuf_loader_write (loader, (guchar *) bytes, len, &err);
153 gdk_pixbuf_loader_close (loader, NULL);
160 loaders = g_list_prepend (loaders, loader);
163 for (i = loaders; i != NULL; i = i->next)
164 g_object_unref (i->data);
165 g_list_free (loaders);
169 almost_exhaust_memory (void)
171 gpointer x = g_malloc (REMAINING_MEM_SIZE);
172 while (g_try_malloc (REMAINING_MEM_SIZE / 10))
180 g_print ("usage: pixbuf-lowmem <pretend_memory_size> <files>\n");
185 main (int argc, char **argv)
193 max_allocation = strtol (argv[1], &endptr, 10);
194 if (endptr == argv[1])
197 /* Set a malloc which emulates low mem */
198 g_mem_set_vtable (&limited_table);
201 g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
205 /* How do the loaders behave when memory is low?
206 It depends on the state the above tests left the
209 - Sometimes the png loader tries to report an
210 "out of memory", but then g_strdup_printf() calls
211 g_malloc(), which fails.
213 - There are unchecked realloc()s inside libtiff, which means it
214 will never work with low memory, unless something drastic is
215 done, like allocating a lot of memory upfront and release it
216 before entering libtiff. Also, some TIFFReadRGBAImage calls
217 returns successfully, even though they have called the error
218 handler with an 'out of memory' message.
221 almost_exhaust_memory ();
223 g_print ("Allocated %dK of %dK, %dK free during tests\n",
224 current_allocation / 1024, max_allocation / 1024,
225 (max_allocation - current_allocation) / 1024);
227 for (i = 2; i < argc; ++i)
233 if (!g_file_get_contents (argv[i], &contents, &size, &err))
235 g_print ("couldn't read %s: %s\n", argv[i], err->message);
240 g_print ("%-40s memory ", argv[i]);
242 mem_test (contents, size);
243 g_print ("\tpassed\n");