~ubuntu-branches/ubuntu/precise/gdk-pixbuf/precise-proposed

« back to all changes in this revision

Viewing changes to tests/pixbuf-lowmem.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2010-07-23 11:26:25 UTC
  • mto: (4.1.1 sid) (33.1.2 sid) (1.2.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20100723112625-1ybus2sr4hyhmlku
Tags: upstream-2.21.6
Import upstream version 2.21.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; c-basic-offset: 2; -*- */
 
2
/* GdkPixbuf library - test loaders
 
3
 *
 
4
 * Copyright (C) 2001 S�ren Sandmann (sandmann@daimi.au.dk)
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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.
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
#include "gdk-pixbuf/gdk-pixbuf.h"
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <time.h>
 
26
#include <string.h>
 
27
 
 
28
#define PRETEND_MEM_SIZE (16 * 1024 * 1024)
 
29
#define REMAINING_MEM_SIZE 100000
 
30
 
 
31
 
 
32
static int current_allocation = 0;
 
33
static int max_allocation = 0;
 
34
 
 
35
#define HEADER_SPACE sizeof(void*)
 
36
 
 
37
static gpointer
 
38
record_bytes (gpointer mem, gsize bytes)
 
39
{
 
40
  if (mem == NULL ||
 
41
      (current_allocation + bytes) > max_allocation)
 
42
    {
 
43
      if (mem)
 
44
        free (mem);
 
45
      
 
46
      return NULL;
 
47
    }
 
48
  
 
49
  *(void **)mem = GINT_TO_POINTER (bytes);
 
50
 
 
51
  g_assert (GPOINTER_TO_INT (*(void**)mem) == bytes);
 
52
  
 
53
  g_assert (current_allocation >= 0);
 
54
  current_allocation += bytes;
 
55
  g_assert (current_allocation >= 0);
 
56
  
 
57
  g_assert ( mem == (void*) ((((char*)mem) + HEADER_SPACE) - HEADER_SPACE) );
 
58
  return ((char*)mem) + HEADER_SPACE;
 
59
}
 
60
 
 
61
static gpointer
 
62
limited_try_malloc (gsize n_bytes)
 
63
{
 
64
  return record_bytes (malloc (n_bytes + HEADER_SPACE), n_bytes);
 
65
}
 
66
 
 
67
static gpointer
 
68
limited_malloc (gsize n_bytes)
 
69
{
 
70
  return limited_try_malloc (n_bytes);
 
71
}
 
72
 
 
73
static gpointer
 
74
limited_calloc (gsize n_blocks,
 
75
                gsize n_block_bytes)
 
76
{
 
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);
 
81
}
 
82
 
 
83
static void
 
84
limited_free (gpointer mem)
 
85
{
 
86
  gpointer real = ((char*)mem) - HEADER_SPACE;
 
87
 
 
88
  g_assert (current_allocation >= 0);
 
89
  current_allocation -= GPOINTER_TO_INT (*(void**)real);
 
90
  g_assert (current_allocation >= 0);
 
91
  
 
92
  free (real);
 
93
}
 
94
 
 
95
static gpointer
 
96
limited_try_realloc (gpointer mem,
 
97
                     gsize    n_bytes)
 
98
{
 
99
  if (mem == NULL)
 
100
    {
 
101
      return limited_try_malloc (n_bytes);
 
102
    }
 
103
  else
 
104
    {
 
105
      gpointer real;
 
106
 
 
107
      g_assert (mem);
 
108
 
 
109
      real = ((char*)mem) - HEADER_SPACE;
 
110
      
 
111
      g_assert (current_allocation >= 0);
 
112
      current_allocation -= GPOINTER_TO_INT (*(void**)real);
 
113
      g_assert (current_allocation >= 0);
 
114
 
 
115
      return record_bytes (realloc (real, n_bytes + HEADER_SPACE), n_bytes);
 
116
    }
 
117
}
 
118
 
 
119
static gpointer
 
120
limited_realloc (gpointer mem,
 
121
                 gsize    n_bytes)
 
122
{
 
123
  return limited_try_realloc (mem, n_bytes);
 
124
}
 
125
 
 
126
static GMemVTable limited_table = {
 
127
  limited_malloc,
 
128
  limited_realloc,
 
129
  limited_free,
 
130
  limited_calloc,
 
131
  limited_try_malloc,
 
132
  limited_try_realloc
 
133
};
 
134
 
 
135
static void
 
136
mem_test (const gchar *bytes, gsize len)
 
137
{
 
138
  gboolean did_fail = FALSE;
 
139
  GError *err = NULL;
 
140
  GdkPixbufLoader *loader; 
 
141
  GList *loaders = NULL;
 
142
  GList *i;
 
143
  
 
144
  do {
 
145
    loader = gdk_pixbuf_loader_new ();
 
146
    gdk_pixbuf_loader_write (loader, (guchar *) bytes, len, &err);
 
147
    if (err)
 
148
      {
 
149
        g_error_free (err);
 
150
        err = NULL;
 
151
        did_fail = TRUE;
 
152
      }
 
153
    gdk_pixbuf_loader_close (loader, NULL);
 
154
    if (err)
 
155
      {
 
156
        g_error_free (err);
 
157
        err = NULL;
 
158
        did_fail = TRUE;
 
159
      }
 
160
    loaders = g_list_prepend (loaders, loader);
 
161
  } while (!did_fail);
 
162
  
 
163
  for (i = loaders; i != NULL; i = i->next)
 
164
    g_object_unref (i->data);
 
165
  g_list_free (loaders);
 
166
}
 
167
 
 
168
static void
 
169
almost_exhaust_memory (void)
 
170
{
 
171
  gpointer x = g_malloc (REMAINING_MEM_SIZE);
 
172
  while (g_try_malloc (REMAINING_MEM_SIZE / 10))
 
173
    ;
 
174
  g_free (x);
 
175
}
 
176
 
 
177
static void
 
178
usage (void)
 
179
{
 
180
  g_print ("usage: pixbuf-lowmem <pretend_memory_size> <files>\n");
 
181
  exit (EXIT_FAILURE);
 
182
}
 
183
 
 
184
int
 
185
main (int argc, char **argv)
 
186
{
 
187
  int i;
 
188
  char *endptr;
 
189
 
 
190
  if (argc <= 2)
 
191
    usage();
 
192
  
 
193
  max_allocation = strtol (argv[1], &endptr, 10);
 
194
  if (endptr == argv[1])
 
195
    usage();
 
196
 
 
197
  /* Set a malloc which emulates low mem */
 
198
  g_mem_set_vtable (&limited_table);
 
199
  
 
200
  g_type_init ();
 
201
  g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
 
202
  
 
203
  /* memory tests */
 
204
 
 
205
  /* How do the loaders behave when memory is low?
 
206
     It depends on the state the above tests left the 
 
207
     memory in.
 
208
 
 
209
     - Sometimes the png loader tries to report an 
 
210
       "out of memory", but then g_strdup_printf() calls
 
211
       g_malloc(), which fails.
 
212
       
 
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.
 
219
  */
 
220
 
 
221
  almost_exhaust_memory ();
 
222
 
 
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);
 
226
 
 
227
  for (i = 2; i < argc; ++i)
 
228
    {
 
229
      gchar *contents;
 
230
      gsize size;
 
231
      GError *err = NULL;
 
232
 
 
233
      if (!g_file_get_contents (argv[i], &contents, &size, &err))
 
234
        {
 
235
          g_print ("couldn't read %s: %s\n", argv[i], err->message);
 
236
          exit (EXIT_FAILURE);
 
237
        }
 
238
      else
 
239
        {
 
240
          g_print ("%-40s memory            ", argv[i]);
 
241
          fflush (stdout);
 
242
          mem_test (contents, size);
 
243
          g_print ("\tpassed\n");
 
244
          g_free (contents);
 
245
        }
 
246
    }
 
247
  
 
248
  return 0;
 
249
}