Fix UPGRADE.txt Due To Merging From Branch 11
[asterisk/asterisk.git] / tests / test_stringfields.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009, Mark Michelson
5  *
6  * Mark Michelson <mmmichelson@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief String fields test
22  *
23  * \author\verbatim Mark Michelson <mmichelson@digium.com> \endverbatim
24  *
25  * Test module for string fields API
26  * \ingroup tests
27  * \todo need to test ast_calloc_with_stringfields
28  */
29
30 /*** MODULEINFO
31         <depend>TEST_FRAMEWORK</depend>
32         <support_level>core</support_level>
33  ***/
34
35 #include "asterisk.h"
36 #include "asterisk/module.h"
37 #include "asterisk/stringfields.h"
38 #include "asterisk/cli.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/test.h"
41
42 AST_TEST_DEFINE(string_field_test)
43 {
44         const char *address_holder;
45         struct ast_string_field_pool *field_pool1;
46         struct ast_string_field_pool *field_pool2;
47         struct ast_string_field_pool *field_pool3;
48         static const char LONG_STRING[] = "A professional panoramic photograph of the majestic elephant bathing itself and its young by the shores of the raging Mississippi River";
49
50         struct {
51                 AST_DECLARE_STRING_FIELDS (
52                         AST_STRING_FIELD(string1);
53                         AST_STRING_FIELD(string2);
54                 );
55         } test_struct;
56
57         struct {
58                 AST_DECLARE_STRING_FIELDS (
59                         AST_STRING_FIELD(string1);
60                         AST_STRING_FIELD(string2);
61                         AST_STRING_FIELD(string3);
62                 );
63         } test_struct2;
64
65         switch (cmd) {
66         case TEST_INIT:
67                 info->name = "string_field_test";
68                 info->category = "/main/utils/";
69                 info->summary = "Test stringfield operations";
70                 info->description =
71                         "This tests the stringfield API";
72                 return AST_TEST_NOT_RUN;
73         case TEST_EXECUTE:
74                 break;
75         }
76
77         ast_test_status_update(test, "First things first. Let's see if we can actually allocate string fields\n");
78
79         if (ast_string_field_init(&test_struct, 32)) {
80                 ast_test_status_update(test, "Failure to initialize string fields. They are totally messed up\n");
81                 return AST_TEST_FAIL;
82         } else {
83                 ast_test_status_update(test, "All right! Successfully allocated! Now let's get down to business\n");
84         }
85
86         ast_test_status_update(test,"We're going to set some string fields and perform some checks\n");
87
88         ast_string_field_set(&test_struct, string1, "elephant");
89         ast_string_field_set(&test_struct, string2, "hippopotamus");
90
91         ast_test_status_update(test, "First we're going to make sure that the strings are actually set to what we expect\n");
92
93         if (strcmp(test_struct.string1, "elephant")) {
94                 ast_test_status_update(test, "We were expecting test_struct.string1 to have 'elephant' but it has %s\n", test_struct.string1);
95                 goto error;
96         } else {
97                 ast_test_status_update(test, "test_struct.string1 appears to be all clear. It has '%s' and that's what we expect\n", test_struct.string1);
98         }
99
100         if (strcmp(test_struct.string2, "hippopotamus")) {
101                 ast_test_status_update(test, "We were expecting test_struct.string2 to have 'hippopotamus' but it has %s\n", test_struct.string2);
102                 goto error;
103         } else {
104                 ast_test_status_update(test, "test_struct.string2 appears to be all clear. It has '%s' and that's what we expect\n", test_struct.string2);
105         }
106
107         ast_test_status_update(test, "Now let's make sure that our recorded capacities for these strings is what we expect\n");
108
109         if (AST_STRING_FIELD_ALLOCATION(test_struct.string1) != strlen("elephant") + 1) {
110                 ast_test_status_update(test, "string1 has allocation area of %hu but we expect %lu\n",
111                                 AST_STRING_FIELD_ALLOCATION(test_struct.string1), (unsigned long) strlen("elephant") + 1);
112                 goto error;
113         } else {
114                 ast_test_status_update(test, "string1 has the allocation area we expect: %hu\n", AST_STRING_FIELD_ALLOCATION(test_struct.string1));
115         }
116
117         if (AST_STRING_FIELD_ALLOCATION(test_struct.string2) != strlen("hippopotamus") + 1) {
118                 ast_test_status_update(test, "string2 has allocation area of %hu but we expect %lu\n",
119                                 AST_STRING_FIELD_ALLOCATION(test_struct.string2), (unsigned long) strlen("hippopotamus") + 1);
120                 goto error;
121         } else {
122                 ast_test_status_update(test, "string2 has the allocation area we expect: %hu\n", AST_STRING_FIELD_ALLOCATION(test_struct.string2));
123         }
124
125         ast_test_status_update(test, "Now we're going to shrink string1 and see if it's in the same place in memory\n");
126
127         address_holder = test_struct.string1;
128         ast_string_field_set(&test_struct, string1, "rhino");
129
130         if (strcmp(test_struct.string1, "rhino")) {
131                 ast_test_status_update(test, "string1 has the wrong value in it. We want 'rhino' but it has '%s'\n", test_struct.string1);
132                 goto error;
133         } else {
134                 ast_test_status_update(test, "string1 successfully was changed to '%s'\n", test_struct.string1);
135         }
136
137         if (address_holder != test_struct.string1) {
138                 ast_test_status_update(test, "We shrunk string1, but it moved?!\n");
139                 goto error;
140         } else {
141                 ast_test_status_update(test, "Shrinking string1 allowed it to stay in the same place in memory\n");
142         }
143
144         if (AST_STRING_FIELD_ALLOCATION(test_struct.string1) != strlen("elephant") + 1) {
145                 ast_test_status_update(test, "The allocation amount changed when we shrunk the string...\n");
146                 goto error;
147         } else {
148                 ast_test_status_update(test, "Shrinking string1 did not change its allocation area (This is a good thing)\n");
149         }
150
151         ast_test_status_update(test, "Next, let's increase it a little but not all the way to its original size\n");
152
153         address_holder = test_struct.string1;
154         ast_string_field_set(&test_struct, string1, "mammoth");
155
156         if (strcmp(test_struct.string1, "mammoth")) {
157                 ast_test_status_update(test, "string1 has the wrong value in it. We want 'mammoth' but it has '%s'\n", test_struct.string1);
158                 goto error;
159         } else {
160                 ast_test_status_update(test, "string1 successfully was changed to '%s'\n", test_struct.string1);
161         }
162
163         if (address_holder != test_struct.string1) {
164                 ast_test_status_update(test, "We expanded string1, but it moved?!\n");
165                 goto error;
166         } else {
167                 ast_test_status_update(test, "Expanding string1 allowed it to stay in the same place in memory\n");
168         }
169
170         if (AST_STRING_FIELD_ALLOCATION(test_struct.string1) != strlen("elephant") + 1) {
171                 ast_test_status_update(test, "The allocation amount changed when we expanded the string...\n");
172                 goto error;
173         } else {
174                 ast_test_status_update(test, "Expanding string1 did not change its allocation area (This is a good thing)\n");
175         }
176
177         ast_test_status_update(test, "Cool, now let's bring it back to its original size and see what happens\n");
178
179         ast_string_field_set(&test_struct, string1, "elephant");
180
181         if (strcmp(test_struct.string1, "elephant")) {
182                 ast_test_status_update(test, "string1 has the wrong value in it. We want 'elephant' but it has '%s'\n", test_struct.string1);
183                 goto error;
184         } else {
185                 ast_test_status_update(test, "string1 successfully changed to '%s'\n", test_struct.string1);
186         }
187
188         if (address_holder != test_struct.string1) {
189                 ast_test_status_update(test, "We restored string1 to its original size, but it moved?!\n");
190                 goto error;
191         } else {
192                 ast_test_status_update(test, "Restoring string1 did not cause it to move (This is a good thing)\n");
193         }
194
195         if (AST_STRING_FIELD_ALLOCATION(test_struct.string1) != strlen("elephant") + 1) {
196                 ast_test_status_update(test, "The allocation amount changed when we re-expanded the string...\n");
197                 goto error;
198         } else {
199                 ast_test_status_update(test, "The allocation amount for string1 is still holding steady\n");
200         }
201
202         ast_test_status_update(test, "All right, now we're going to expand string 2. It should stay in place since it was the last string allocated in this pool\n");
203
204         address_holder = test_struct.string2;
205         ast_string_field_set(&test_struct, string2, "hippopotamus face");
206
207         if (strcmp(test_struct.string2, "hippopotamus face")) {
208                 ast_test_status_update(test, "string2 has the wrong value. We want 'hippopotamus face' but it has '%s'\n", test_struct.string2);
209                 goto error;
210         } else {
211                 ast_test_status_update(test, "string2 successfully changed to '%s'\n", test_struct.string2);
212         }
213
214         if (AST_STRING_FIELD_ALLOCATION(test_struct.string2) != strlen("hippopotamus face") + 1) {
215                 ast_test_status_update(test, "The allocation amount is incorrect for string2. We expect %lu but it has %hu\n",
216                                 (unsigned long) strlen("hippopotamus face"), AST_STRING_FIELD_ALLOCATION(test_struct.string2) + 1);
217                 goto error;
218         } else {
219                 ast_test_status_update(test, "The allocation amount successfully increased for string2 when it grew\n");
220         }
221
222         if (test_struct.string2 != address_holder) {
223                 ast_test_status_update(test, "string2 has moved, but it should not have since it had room to grow\n");
224                 goto error;
225         } else {
226                 ast_test_status_update(test, "string2 stayed in place when it grew. Good job!\n");
227         }
228
229         ast_test_status_update(test, "Now we're going to set string1 to a very long string so that a new string field pool must be allocated\n");
230
231         address_holder = test_struct.string1;
232         ast_string_field_set(&test_struct, string1, LONG_STRING);
233
234         if (strcmp(test_struct.string1, LONG_STRING)) {
235                 ast_test_status_update(test, "We were expecting string1 to be '%s'\nbut it was actually '%s'\n", LONG_STRING, test_struct.string1);
236                 goto error;
237         } else {
238                 ast_test_status_update(test, "string1 successfully changed to '%s'\n", test_struct.string1);
239         }
240
241         if (address_holder == test_struct.string1) {
242                 ast_test_status_update(test, "Uh oh, string1 didn't move when we set it to a long value\n");
243                 goto error;
244         } else {
245                 ast_test_status_update(test, "Good. Setting string1 to a long value caused it to change addresses\n");
246         }
247
248         if (AST_STRING_FIELD_ALLOCATION(test_struct.string1) != strlen(LONG_STRING) + 1) {
249                 ast_test_status_update(test, "The string field allocation for string1 indicates a length of %hu instead of the expected %lu\n",
250                                 AST_STRING_FIELD_ALLOCATION(test_struct.string1), (unsigned long) strlen(LONG_STRING) + 1);
251                 goto error;
252         } else {
253                 ast_test_status_update(test, "The stored allocation size of string1 is what we expect\n");
254         }
255
256         ast_string_field_init(&test_struct2, 32);
257         ast_test_status_update(test, "Now using a totally separate area of memory we're going to test a basic pool freeing scenario\n");
258
259         ast_string_field_set(&test_struct2, string1, "first");
260         ast_string_field_set(&test_struct2, string2, "second");
261         ast_string_field_set(&test_struct2, string3, "third");
262
263         /* This string is 208 characters long, which will surely exceed the initial pool size */
264         ast_string_field_set(&test_struct2, string1, "Expanded first string to create new pool-----------------------------------------------------------------------------------------------------------------------------------------------------------------------");
265         /* Pool size at this point is 976, so 1000 chars should do it */
266         ast_string_field_set(&test_struct2, string2, "Expanded second string to create new pool----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
267
268         field_pool3 = test_struct2.__field_mgr_pool;
269         field_pool2 = test_struct2.__field_mgr_pool->prev;
270         field_pool1 = test_struct2.__field_mgr_pool->prev->prev;
271
272         if(field_pool3->prev != field_pool2 || field_pool2->prev != field_pool1) {
273                 ast_test_status_update(test, "Pools are not linked properly!\n");
274                 goto error;
275         } else {
276                 ast_test_status_update(test, "Three different pools are linked as expected.\n");
277         }
278
279         ast_string_field_set(&test_struct2, string1, NULL);
280         if (test_struct2.string1 != __ast_string_field_empty || field_pool3->prev != field_pool1) {
281                 ast_test_status_update(test, "Things did not work out when removing the middle pool!\n");
282                 goto error;
283         } else {
284                 ast_test_status_update(test, "After removing a pool the remaining two are linked as expected.\n");
285         }
286
287         ast_string_field_free_memory(&test_struct2);
288         ast_string_field_free_memory(&test_struct);
289         return AST_TEST_PASS;
290
291 error:
292         ast_string_field_free_memory(&test_struct);
293         ast_string_field_free_memory(&test_struct2);
294         return AST_TEST_FAIL;
295 }
296
297 AST_TEST_DEFINE(string_field_aggregate_test)
298 {
299         struct test_struct {
300                 AST_DECLARE_STRING_FIELDS (
301                         AST_STRING_FIELD(string1);
302                         AST_STRING_FIELD(string2);
303                 );
304                 int foo;
305         } inst1, inst2, inst3, inst4;
306
307         switch (cmd) {
308         case TEST_INIT:
309                 info->name = "string_field_aggregate_test";
310                 info->category = "/main/utils/";
311                 info->summary = "Test stringfield aggregate operations";
312                 info->description =
313                         "This tests the structure comparison and copy macros of the stringfield API";
314                 return AST_TEST_NOT_RUN;
315         case TEST_EXECUTE:
316                 break;
317         }
318
319         ast_string_field_init(&inst1, 32);
320         ast_string_field_init(&inst2, 32);
321         ast_string_field_init(&inst3, 32);
322         ast_string_field_init(&inst4, 32);
323
324         ast_string_field_set(&inst1, string1, "foo");
325         ast_string_field_set(&inst1, string2, "bar");
326         inst1.foo = 1;
327
328         ast_string_field_set(&inst2, string2, "bar");
329         ast_string_field_set(&inst2, string1, "foo");
330         inst2.foo = 2;
331
332         ast_string_field_set(&inst3, string1, "foo");
333         ast_string_field_set(&inst3, string2, "baz");
334         inst3.foo = 3;
335
336         ast_string_field_set(&inst4, string1, "faz");
337         ast_string_field_set(&inst4, string2, "baz");
338         inst4.foo = 3;
339
340         if (ast_string_fields_cmp(&inst1, &inst2)) {
341                 ast_test_status_update(test, "Structures 1/2 should be equal!\n");
342                 goto error;
343         } else {
344                 ast_test_status_update(test, "Structures 1/2 are equal as expected.\n");
345         }
346
347         if (!ast_string_fields_cmp(&inst1, &inst3)) {
348                 ast_test_status_update(test, "Structures 1/3 should be different!\n");
349                 goto error;
350         } else {
351                 ast_test_status_update(test, "Structures 1/3 are different as expected.\n");
352         }
353
354         if (!ast_string_fields_cmp(&inst2, &inst3)) {
355                 ast_test_status_update(test, "Structures 2/3 should be different!\n");
356                 goto error;
357         } else {
358                 ast_test_status_update(test, "Structures 2/3 are different as expected.\n");
359         }
360
361         if (!ast_string_fields_cmp(&inst3, &inst4)) {
362                 ast_test_status_update(test, "Structures 3/4 should be different!\n");
363                 goto error;
364         } else {
365                 ast_test_status_update(test, "Structures 3/4 are different as expected.\n");
366         }
367
368         if (ast_string_fields_copy(&inst1, &inst3)) {
369                 ast_test_status_update(test, "Copying from structure 3 to structure 4 failed!\n");
370                 goto error;
371         } else {
372                 ast_test_status_update(test, "Copying from structure 3 to structure 4 succeeded!\n");
373         }
374
375         /* inst1 and inst3 should now be equal and inst1 should no longer be equal to inst2 */
376         if (ast_string_fields_cmp(&inst1, &inst3)) {
377                 ast_test_status_update(test, "Structures 1/3 should be equal!\n");
378                 goto error;
379         } else {
380                 ast_test_status_update(test, "Structures 1/3 are equal as expected.\n");
381         }
382
383         if (!ast_string_fields_cmp(&inst1, &inst2)) {
384                 ast_test_status_update(test, "Structures 1/2 should be different!\n");
385                 goto error;
386         } else {
387                 ast_test_status_update(test, "Structures 1/2 are different as expected.\n");
388         }
389
390         ast_string_field_free_memory(&inst1);
391         ast_string_field_free_memory(&inst2);
392         ast_string_field_free_memory(&inst3);
393         ast_string_field_free_memory(&inst4);
394         return AST_TEST_PASS;
395 error:
396         ast_string_field_free_memory(&inst1);
397         ast_string_field_free_memory(&inst2);
398         ast_string_field_free_memory(&inst3);
399         ast_string_field_free_memory(&inst4);
400         return AST_TEST_FAIL;
401 }
402
403 static int unload_module(void)
404 {
405         AST_TEST_UNREGISTER(string_field_aggregate_test);
406         AST_TEST_UNREGISTER(string_field_test);
407         return 0;
408 }
409
410 static int load_module(void)
411 {
412         AST_TEST_REGISTER(string_field_test);
413         AST_TEST_REGISTER(string_field_aggregate_test);
414         return AST_MODULE_LOAD_SUCCESS;
415 }
416
417 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "String Fields Test");