VirtualBox

source: vbox/trunk/src/libs/libxml2-2.9.14/testOOMlib.c@ 103850

Last change on this file since 103850 was 95312, checked in by vboxsync, 2 years ago

libs/{curl,libxml2}: OSE export fixes, bugref:8515

  • Property svn:eol-style set to native
File size: 5.2 KB
Line 
1/*
2 * testOOM.c: Test out-of-memory handling
3 *
4 * See Copyright for the status of this software.
5 *
6 * Copyright 2003 Red Hat, Inc.
7 * Written by: [email protected]
8 */
9
10#include "testOOMlib.h"
11
12#ifdef HAVE_STDLIB_H
13#include <stdlib.h>
14#endif
15
16#include <string.h>
17
18#define _TEST_INT_MAX 2147483647
19#ifndef TRUE
20#define TRUE (1)
21#endif
22#ifndef FALSE
23#define FALSE (0)
24#endif
25#ifndef NULL
26#define NULL ((void*)0)
27#endif
28
29#include <libxml/xmlmemory.h>
30
31static int fail_alloc_counter = _TEST_INT_MAX;
32static int n_failures_per_failure = 1;
33static int n_failures_this_failure = 0;
34static int n_blocks_outstanding = 0;
35
36/**
37 * set_fail_alloc_counter:
38 * @until_next_fail: number of successful allocs before one fails
39 *
40 * Sets the number of allocations until we simulate a failed
41 * allocation. If set to 0, the next allocation to run
42 * fails; if set to 1, one succeeds then the next fails; etc.
43 * Set to _TEST_INT_MAX to not fail anything.
44 */
45static void
46set_fail_alloc_counter (int until_next_fail)
47{
48 fail_alloc_counter = until_next_fail;
49}
50
51/**
52 * get_fail_alloc_counter:
53 *
54 * Returns the number of successful allocs until we'll simulate
55 * a failed alloc.
56 */
57static int
58get_fail_alloc_counter (void)
59{
60 return fail_alloc_counter;
61}
62
63/**
64 * set_fail_alloc_failures:
65 * @failures_per_failure: number to fail
66 *
67 * Sets how many mallocs to fail when the fail alloc counter reaches
68 * 0.
69 *
70 */
71static void
72set_fail_alloc_failures (int failures_per_failure)
73{
74 n_failures_per_failure = failures_per_failure;
75}
76
77/**
78 * decrement_fail_alloc_counter:
79 *
80 * Called when about to alloc some memory; if
81 * it returns #TRUE, then the allocation should
82 * fail. If it returns #FALSE, then the allocation
83 * should not fail.
84 *
85 * returns #TRUE if this alloc should fail
86 */
87static int
88decrement_fail_alloc_counter (void)
89{
90 if (fail_alloc_counter <= 0)
91 {
92 n_failures_this_failure += 1;
93 if (n_failures_this_failure >= n_failures_per_failure)
94 {
95 fail_alloc_counter = _TEST_INT_MAX;
96
97 n_failures_this_failure = 0;
98 }
99
100 return TRUE;
101 }
102 else
103 {
104 fail_alloc_counter -= 1;
105 return FALSE;
106 }
107}
108
109/**
110 * test_get_malloc_blocks_outstanding:
111 *
112 * Get the number of outstanding malloc()'d blocks.
113 *
114 * Returns number of blocks
115 */
116int
117test_get_malloc_blocks_outstanding (void)
118{
119 return n_blocks_outstanding;
120}
121
122void*
123test_malloc (size_t bytes)
124{
125 if (decrement_fail_alloc_counter ())
126 {
127 /* FAIL the malloc */
128 return NULL;
129 }
130
131 if (bytes == 0) /* some system mallocs handle this, some don't */
132 return NULL;
133 else
134 {
135 void *mem;
136 mem = xmlMemMalloc (bytes);
137
138 if (mem)
139 n_blocks_outstanding += 1;
140
141 return mem;
142 }
143}
144
145void*
146test_realloc (void *memory,
147 size_t bytes)
148{
149 if (decrement_fail_alloc_counter ())
150 {
151 /* FAIL */
152 return NULL;
153 }
154
155 if (bytes == 0) /* guarantee this is safe */
156 {
157 test_free (memory);
158 return NULL;
159 }
160 else
161 {
162 void *mem;
163 mem = xmlMemRealloc (memory, bytes);
164
165 if (memory == NULL && mem != NULL)
166 n_blocks_outstanding += 1;
167
168 return mem;
169 }
170}
171
172void
173test_free (void *memory)
174{
175 if (memory) /* we guarantee it's safe to free (NULL) */
176 {
177 n_blocks_outstanding -= 1;
178
179 xmlMemFree (memory);
180 }
181}
182
183char*
184test_strdup (const char *str)
185{
186 int len;
187 char *copy;
188
189 if (str == NULL)
190 return NULL;
191
192 len = strlen (str);
193
194 copy = test_malloc (len + 1);
195 if (copy == NULL)
196 return NULL;
197
198 memcpy (copy, str, len + 1);
199
200 return copy;
201}
202
203static int
204run_failing_each_malloc (int n_mallocs,
205 TestMemoryFunction func,
206 void *data)
207{
208 n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
209
210 while (n_mallocs >= 0)
211 {
212 set_fail_alloc_counter (n_mallocs);
213
214 if (!(* func) (data))
215 return FALSE;
216
217 n_mallocs -= 1;
218 }
219
220 set_fail_alloc_counter (_TEST_INT_MAX);
221
222 return TRUE;
223}
224
225/**
226 * test_oom_handling:
227 * @func: function to call
228 * @data: data to pass to function
229 *
230 * Tests how well the given function responds to out-of-memory
231 * situations. Calls the function repeatedly, failing a different
232 * call to malloc() each time. If the function ever returns #FALSE,
233 * the test fails. The function should return #TRUE whenever something
234 * valid (such as returning an error, or succeeding) occurs, and #FALSE
235 * if it gets confused in some way.
236 *
237 * Returns #TRUE if the function never returns FALSE
238 */
239int
240test_oom_handling (TestMemoryFunction func,
241 void *data)
242{
243 int approx_mallocs;
244
245 /* Run once to see about how many mallocs are involved */
246
247 set_fail_alloc_counter (_TEST_INT_MAX);
248
249 if (!(* func) (data))
250 return FALSE;
251
252 approx_mallocs = _TEST_INT_MAX - get_fail_alloc_counter ();
253
254 set_fail_alloc_failures (1);
255 if (!run_failing_each_malloc (approx_mallocs, func, data))
256 return FALSE;
257
258 set_fail_alloc_failures (2);
259 if (!run_failing_each_malloc (approx_mallocs, func, data))
260 return FALSE;
261
262 set_fail_alloc_failures (3);
263 if (!run_failing_each_malloc (approx_mallocs, func, data))
264 return FALSE;
265
266 set_fail_alloc_counter (_TEST_INT_MAX);
267
268 return TRUE;
269}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette