c11 safe string handling support
[vpp.git] / src / vppinfra / test_heap.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16   Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 #include <unistd.h>
39 #include <stdlib.h>
40
41 #include <vppinfra/mem.h>
42 #include <vppinfra/heap.h>
43 #include <vppinfra/format.h>
44
45 static int verbose;
46 #define if_verbose(format,args...) \
47   if (verbose) { clib_warning(format, ## args); }
48
49 u32
50 vl (void *p)
51 {
52   return (vec_len (p));
53 }
54
55 int
56 main (int argc, char *argv[])
57 {
58   word i, j, k, n, check_mask;
59   u32 seed;
60   u32 *h = 0;
61   uword *objects = 0;
62   uword *handles = 0;
63   uword objects_used;
64   uword align, fixed_size;
65
66   clib_mem_init (0, 10 << 20);
67
68   n = 10;
69   seed = (u32) getpid ();
70   check_mask = 0;
71   fixed_size = 0;
72
73   if (argc > 1)
74     {
75       n = atoi (argv[1]);
76       verbose = 1;
77     }
78   if (argc > 2)
79     {
80       word i = atoi (argv[2]);
81       if (i)
82         seed = i;
83     }
84   if (argc > 3)
85     check_mask = atoi (argv[3]);
86
87   align = 0;
88   if (argc > 4)
89     align = 1 << atoi (argv[4]);
90
91   if_verbose ("testing %wd iterations seed %wd\n", n, seed);
92
93   if (verbose)
94     fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);
95
96   vec_resize (objects, 1000);
97   if (vec_bytes (objects) > 0)  /* stupid warning be gone */
98     clib_memset (objects, ~0, vec_bytes (objects));
99   vec_resize (handles, vec_len (objects));
100
101   objects_used = 0;
102
103   if (fixed_size)
104     {
105       uword max_len = 1024 * 1024;
106       void *memory = clib_mem_alloc (max_len * sizeof (h[0]));
107       h = heap_create_from_memory (memory, max_len, sizeof (h[0]));
108     }
109
110   for (i = 0; i < n; i++)
111     {
112       while (1)
113         {
114           j = random_u32 (&seed) % vec_len (objects);
115           if (objects[j] != ~0 || i + objects_used < n)
116             break;
117         }
118
119       if (objects[j] != ~0)
120         {
121           heap_dealloc (h, handles[j]);
122           objects_used--;
123           objects[j] = ~0;
124         }
125       else
126         {
127           u32 *data;
128           uword size;
129
130           size = 1 + (random_u32 (&seed) % 100);
131           objects[j] = heap_alloc_aligned (h, size, align, handles[j]);
132           objects_used++;
133
134           if (align)
135             ASSERT (0 == (objects[j] & (align - 1)));
136           ASSERT (objects[j] < vec_len (h));
137           ASSERT (size <= heap_len (h, handles[j]));
138
139           /* Set newly allocated object with test data. */
140           if (check_mask & 2)
141             {
142               data = h + objects[j];
143
144               for (k = 0; k < size; k++)
145                 data[k] = objects[j] + k;
146             }
147         }
148
149       if (check_mask & 1)
150         heap_validate (h);
151
152       if (check_mask & 4)
153         {
154           /* Duplicate heap at each iteration. */
155           u32 *h1 = heap_dup (h);
156           heap_free (h);
157           h = h1;
158         }
159
160       /* Verify that all used objects have correct test data. */
161       if (check_mask & 2)
162         {
163           for (j = 0; j < vec_len (objects); j++)
164             if (objects[j] != ~0)
165               {
166                 u32 *data = h + objects[j];
167                 for (k = 0; k < heap_len (h, handles[j]); k++)
168                   ASSERT (data[k] == objects[j] + k);
169               }
170         }
171     }
172
173   if (verbose)
174     fformat (stderr, "%U\n", format_heap, h, 1);
175
176   {
177     u32 *h1 = heap_dup (h);
178     if (verbose)
179       fformat (stderr, "%U\n", format_heap, h1, 1);
180     heap_free (h1);
181   }
182
183   heap_free (h);
184   if (verbose)
185     fformat (stderr, "%U\n", format_heap, h, 1);
186   // ASSERT (objects_used == 0);
187
188   vec_free (objects);
189   vec_free (handles);
190
191   if (fixed_size)
192     vec_free_h (h, sizeof (heap_header_t));
193
194   if (verbose)
195     fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);
196
197   return 0;
198 }
199
200 /*
201  * fd.io coding-style-patch-verification: ON
202  *
203  * Local Variables:
204  * eval: (c-set-style "gnu")
205  * End:
206  */