Unit test for ast_str API.
[asterisk/asterisk.git] / tests / test_strings.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * Mark Michelson <mmichelson@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 Dynamic string tests
22  *
23  * \author Mark Michelson <mmichelson@digium.com>
24  *
25  * This module will run some dyanmic string tests.
26  * \ingroup tests
27  */
28
29 /*** MODULEINFO
30         <depend>TEST_FRAMEWORK</depend>
31  ***/
32
33 #include "asterisk.h"
34 #include "asterisk/test.h"
35 #include "asterisk/utils.h"
36 #include "asterisk/strings.h"
37 #include "asterisk/module.h"
38
39 AST_TEST_DEFINE(str_test)
40 {
41         struct ast_str *stack_str;
42         struct ast_str *heap_str;
43         const char short_string1[] = "apple";
44         const char short_string2[] = "banana";
45         char short_string_cat[30];
46         const char long_string1[] = "applebananapeachmangocherrypeargrapeplumlimetangerinepomegranategravel";
47         const char long_string2[] = "passionuglinectarinepineapplekiwilemonpaintthinner";
48         char long_string_cat[200];
49         char string_limit_cat[11];
50         const int string_limit = 5;
51         int current_size;
52         enum ast_test_result_state res = AST_TEST_PASS;
53
54         switch (cmd) {
55         case TEST_INIT:
56                 info->name = "str_test";
57                 info->category = "main/strings/";
58                 info->summary = "Test dynamic string operations";
59                 info->description = "Test setting and appending stack and heap-allocated strings";
60                 return AST_TEST_NOT_RUN;
61         case TEST_EXECUTE:
62                 break;
63         }
64         snprintf(short_string_cat, sizeof(short_string_cat), "%s%s", short_string1, short_string2);
65         snprintf(long_string_cat, sizeof(long_string_cat), "%s%s", long_string1, long_string2);
66         snprintf(string_limit_cat, string_limit, "%s", long_string1);
67         strncat(string_limit_cat, long_string2, string_limit);
68
69         if (!(stack_str = ast_str_alloca(15))) {
70                 ast_test_status_update(test, "Failed to allocate an ast_str on the stack\n");
71                 return AST_TEST_FAIL;
72         }
73
74         if (!(heap_str = ast_str_create(15))) {
75                 ast_test_status_update(test, "Failed to allocate an ast_str on the heap\n");
76         }
77
78         /* Stack string tests:
79          * Part 1: Basic tests
80          * a. set a small string
81          * b. append a small string
82          * c. clear a string
83          * Part 2: Advanced tests
84          * a. Set a string that is larger than our allocation
85          * b. Append a string that is larger than our allocation
86          */
87
88         /* Part 1a */
89         if (ast_str_set(&stack_str, 0, "%s", short_string1) < 0) {
90                 ast_test_status_update(test, "Error setting stack string\n");
91                 res = AST_TEST_FAIL;
92                 goto cleanup;
93         }
94         if (strcmp(ast_str_buffer(stack_str), short_string1)) {
95                 ast_test_status_update(test, "ast_str_set failed for stack string. Expected '%s' but"
96                                 "instead got %s\n", short_string1, ast_str_buffer(stack_str));
97                 res = AST_TEST_FAIL;
98                 goto cleanup;
99         }
100         /* Part 1b */
101         if (ast_str_append(&stack_str, 0, "%s", short_string2) < 0) {
102                 ast_test_status_update(test, "Error appending to stack string\n");
103                 res = AST_TEST_FAIL;
104                 goto cleanup;
105         }
106         if (strcmp(ast_str_buffer(stack_str), short_string_cat)) {
107                 ast_test_status_update(test, "ast_str_set failed for stack string. Expected '%s'"
108                                 "but instead got %s\n", short_string_cat, ast_str_buffer(stack_str));
109                 res = AST_TEST_FAIL;
110                 goto cleanup;
111         }
112         /* Part 1c */
113         ast_str_reset(stack_str);
114         if (ast_str_strlen(stack_str) != 0) {
115                 ast_test_status_update(test, "ast_str_reset resulted in non-zero length for stack_str\n");
116                 res = AST_TEST_FAIL;
117                 goto cleanup;
118         }
119
120         /* Part 2a */
121         if (ast_str_set(&stack_str, -1, "%s", long_string1) < 0) {
122                 ast_test_status_update(test, "Error setting stack string with long input\n");
123                 res = AST_TEST_FAIL;
124                 goto cleanup;
125         }
126         if (strncmp(ast_str_buffer(stack_str), long_string1, ast_str_strlen(stack_str))) {
127                 ast_test_status_update(test, "Stack string not set to what is expected.\n");
128                 res = AST_TEST_FAIL;
129                 goto cleanup;
130         }
131         /* Part 2b */
132         if (ast_str_append(&stack_str, -1, "%s", long_string2) < 0) {
133                 ast_test_status_update(test, "Error appending long string to full stack string buffer\n");
134                 res = AST_TEST_FAIL;
135                 goto cleanup;
136         }
137         if (strncmp(ast_str_buffer(stack_str), long_string_cat, ast_str_strlen(stack_str))) {
138                 ast_test_status_update(test, "Stack string not set to what is expected.\n");
139                 res = AST_TEST_FAIL;
140                 goto cleanup;
141         }
142
143         /* Heap string tests
144          *
145          * All stack string tests from part 1.
146          * All stack string tests 2a and 2b.
147          * Tests 2a and 2b from stack string tests, passing 0 as max_len
148          * instead of -1. This allows for the buffer to grow.
149          */
150         /* Part 1a */
151         if (ast_str_set(&heap_str, 0, "%s", short_string1) < 0) {
152                 ast_test_status_update(test, "Error setting heap string\n");
153                 res = AST_TEST_FAIL;
154                 goto cleanup;
155         }
156         if (strcmp(ast_str_buffer(heap_str), short_string1)) {
157                 ast_test_status_update(test, "ast_str_set failed for heap string. Expected '%s' but"
158                                 "instead got %s\n", short_string1, ast_str_buffer(heap_str));
159                 res = AST_TEST_FAIL;
160                 goto cleanup;
161         }
162         /* Part 1b */
163         if (ast_str_append(&heap_str, 0, "%s", short_string2) < 0) {
164                 ast_test_status_update(test, "Error appending to heap string\n");
165                 res = AST_TEST_FAIL;
166                 goto cleanup;
167         }
168         if (strcmp(ast_str_buffer(heap_str), short_string_cat)) {
169                 ast_test_status_update(test, "ast_str_set failed for stack string. Expected '%s'"
170                                 "but instead got %s\n", short_string_cat, ast_str_buffer(stack_str));
171                 res = AST_TEST_FAIL;
172                 goto cleanup;
173         }
174         /* Part 1c */
175         ast_str_reset(heap_str);
176         if (ast_str_strlen(heap_str) != 0) {
177                 ast_test_status_update(test, "ast_str_reset resulted in non-zero length for stack_str\n");
178                 res = AST_TEST_FAIL;
179                 goto cleanup;
180         }
181         /* Part 2a with -1 arg */
182         current_size = ast_str_size(heap_str);
183         if (ast_str_set(&heap_str, -1, "%s", long_string1) < 0) {
184                 ast_test_status_update(test, "Error setting heap string with long input\n");
185                 res = AST_TEST_FAIL;
186                 goto cleanup;
187         }
188         if (current_size != ast_str_size(heap_str)) {
189                 ast_test_status_update(test, "Heap string changed size during ast_str_set when it was"
190                                 "instructed not to. Was %d and now is %d\n", current_size, (int) ast_str_size(heap_str));
191                 res = AST_TEST_FAIL;
192                 goto cleanup;
193         }
194         if (strncmp(ast_str_buffer(heap_str), long_string1, ast_str_strlen(heap_str))) {
195                 ast_test_status_update(test, "Heap string not set to what is expected.\n");
196                 res = AST_TEST_FAIL;
197                 goto cleanup;
198         }
199         /* Part 2b with -1 arg */
200         current_size = ast_str_size(heap_str);
201         if (ast_str_append(&heap_str, -1, "%s", long_string2) < 0) {
202                 ast_test_status_update(test, "Error appending long string to full heap string buffer\n");
203                 res = AST_TEST_FAIL;
204                 goto cleanup;
205         }
206         if (current_size != ast_str_size(heap_str)) {
207                 ast_test_status_update(test, "Heap string changed size during ast_str_append when it was"
208                                 "instructed not to. Was %d and now is %d\n", current_size, (int) ast_str_size(heap_str));
209                 res = AST_TEST_FAIL;
210                 goto cleanup;
211         }
212         if (strncmp(ast_str_buffer(heap_str), long_string_cat, ast_str_strlen(heap_str))) {
213                 ast_test_status_update(test, "Heap string not set to what is expected.\n");
214                 res = AST_TEST_FAIL;
215                 goto cleanup;
216         }
217         /* reset string before continuing */
218         ast_str_reset(heap_str);
219         /* Part 2a with 0 arg */
220         if (ast_str_set(&heap_str, 0, "%s", long_string1) < 0) {
221                 ast_test_status_update(test, "Error setting heap string with long input\n");
222                 res = AST_TEST_FAIL;
223                 goto cleanup;
224         }
225         if (strcmp(ast_str_buffer(heap_str), long_string1)) {
226                 ast_test_status_update(test, "Heap string does not contain what was expected. Expected %s"
227                                 "but have %s instead\n", long_string1, ast_str_buffer(heap_str));
228                 res = AST_TEST_FAIL;
229                 goto cleanup;
230         }
231         /* Part 2b with 0 arg */
232         if (ast_str_append(&heap_str, 0, "%s", long_string2) < 0) {
233                 ast_test_status_update(test, "Error setting heap string with long input\n");
234                 res = AST_TEST_FAIL;
235                 goto cleanup;
236         }
237         if (strcmp(ast_str_buffer(heap_str), long_string_cat)) {
238                 ast_test_status_update(test, "Heap string does not contain what was expected. Expected %s"
239                                 "but have %s instead\n", long_string_cat, ast_str_buffer(heap_str));
240                 res = AST_TEST_FAIL;
241                 goto cleanup;
242         }
243
244 cleanup:
245         ast_free(heap_str);
246         return res;
247 }
248
249 static int unload_module(void)
250 {
251         AST_TEST_UNREGISTER(str_test);
252         return 0;
253 }
254
255 static int load_module(void)
256 {
257         AST_TEST_REGISTER(str_test);
258         return AST_MODULE_LOAD_SUCCESS;
259 }
260
261 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dynamic string test module");