Initial commit of vpp code.
[vpp.git] / vppinfra / 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 int main (int argc, char * argv[])
50 {
51   word i, j, k, n, check_mask;
52   u32 seed;
53   u32 * h = 0;
54   uword * objects = 0;
55   uword * handles = 0;
56   uword objects_used;
57   uword align, fixed_size;
58
59   n = 10;
60   seed = (u32) getpid ();
61   check_mask = 0;
62   fixed_size = 0;
63
64   if (argc > 1)
65     {
66       n = atoi (argv[1]);
67       verbose = 1;
68     }
69   if (argc > 2)
70     {
71       word i = atoi (argv[2]);
72       if (i)
73         seed = i;
74     }
75   if (argc > 3)
76     check_mask = atoi (argv[3]);
77
78   align = 0;
79   if (argc > 4)
80     align = 1 << atoi (argv[4]);
81
82   if_verbose   ("testing %wd iterations seed %wd\n", n, seed);
83
84   if (verbose) fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);
85
86   vec_resize (objects, 1000);
87   if (vec_bytes(objects))       /* stupid warning be gone */
88     memset (objects, ~0, vec_bytes (objects));
89   vec_resize (handles, vec_len (objects));
90
91   objects_used = 0;
92
93   if (fixed_size)
94     {
95       uword max_len = 1024 * 1024;
96       void * memory = clib_mem_alloc (max_len * sizeof (h[0]));
97       h = heap_create_from_memory (memory, max_len, sizeof (h[0]));
98     }
99
100   for (i = 0; i < n; i++)
101     {
102       while (1)
103         {
104           j = random_u32 (&seed) % vec_len (objects);
105           if (objects[j] != ~0 || i + objects_used < n)
106             break;
107         }
108
109       if (objects[j] != ~0)
110         {
111           heap_dealloc (h, handles[j]);
112           objects_used--;
113           objects[j] = ~0;
114         }
115       else
116         {
117           u32 * data;
118           uword size;
119
120           size = 1 + (random_u32 (&seed) % 100);
121           objects[j] = heap_alloc_aligned (h, size, align, handles[j]);
122           objects_used++;
123
124           if (align)
125             ASSERT (0 == (objects[j] & (align - 1)));
126           ASSERT (objects[j] < vec_len (h));
127           ASSERT (size <= heap_len (h, handles[j]));
128
129           /* Set newly allocated object with test data. */
130           if (check_mask & 2)
131             {
132               data = h + objects[j];
133
134               for (k = 0; k < size; k++)
135                 data[k] = objects[j] + k;
136             }
137         }
138
139       if (check_mask & 1)
140         heap_validate (h);
141
142       if (check_mask & 4)
143         {
144           /* Duplicate heap at each iteration. */
145           u32 * h1 = heap_dup (h);
146           heap_free (h);
147           h = h1;
148         }
149
150       /* Verify that all used objects have correct test data. */
151       if (check_mask & 2)
152         {
153           for (j = 0; j < vec_len (objects); j++)
154             if (objects[j] != ~0)
155               {
156                 u32 * data = h + objects[j];
157                 for (k = 0; k < heap_len (h, handles[j]); k++)
158                   ASSERT(data[k] == objects[j] + k);
159               }
160         }
161     }
162
163   if (verbose) fformat (stderr, "%U\n", format_heap, h, 1);
164
165   {
166     u32 * h1 = heap_dup (h);
167     if (verbose) fformat (stderr, "%U\n", format_heap, h1, 1);
168     heap_free (h1);
169   }
170
171   heap_free (h);
172   if (verbose) fformat (stderr, "%U\n", format_heap, h, 1);
173   ASSERT (objects_used == 0);
174
175   vec_free (objects);
176   vec_free (handles);
177
178   if (fixed_size)
179     vec_free_h (h, sizeof (heap_header_t));
180
181   if (verbose) fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);
182
183   return 0;
184 }