Merge "Revert "app_voicemail: Remove need to subscribe to stasis""
[asterisk/asterisk.git] / tests / test_pbx.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 PBX Tests
22  *
23  * \author Mark Michelson <mmichelson@digium.com>
24  *
25  * This module will run some PBX tests.
26  * \ingroup tests
27  */
28
29 /*** MODULEINFO
30         <depend>TEST_FRAMEWORK</depend>
31         <support_level>core</support_level>
32  ***/
33
34 #include "asterisk.h"
35
36 #include "asterisk/module.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/test.h"
39
40 #include <signal.h>
41
42 /*!
43  * If we determine that we really need
44  * to be able to register more than 10
45  * priorities for a single extension, then
46  * fine, we can do that later.
47  */
48 #define MAX_PRIORITIES 10
49
50 /*!
51  * \brief an extension to add to our context
52  */
53 struct exten_info {
54         /*!
55          * \brief Context
56          *
57          * \details
58          * The extension specified will be added to
59          * this context when it is created.
60          */
61         const char *context;
62         /*!
63          * \brief Extension pattern
64          *
65          * \details
66          * The extension pattern to use. This can be
67          * anything you would normally find in a dialplan,
68          * such as "1000" or "NXXNXXX" or whatever you
69          * wish it to be. If, however, you want a CID match
70          * to be part of the extension, do not include that
71          * here.
72          */
73         const char *exten;
74         /*!
75          * \brief CID match
76          *
77          * \details
78          * If your extension requires a specific caller ID in
79          * order to match, place that in this field. Note that
80          * a NULL and an empty CID match are two very different
81          * things. If you want no CID match, leave this NULL. If
82          * you want to explicitly match a blank CID, then put
83          * an empty string here.
84          */
85         const char *cid;
86         /*!
87          * \brief Number of priorities
88          *
89          * \details
90          * Tell the number of priorities to register for this
91          * extension. All priorities registered will just have a
92          * Noop application with the extension pattern as its
93          * data.
94          */
95         const int num_priorities;
96         /*!
97          * \brief The priorities to register
98          *
99          * \details
100          * In most cases, when registering multiple priorities for
101          * an extension, we'll be starting at priority 1 and going
102          * sequentially until we've read num_priorities. However,
103          * for some tests, it may be beneficial to start at a higher
104          * priority or skip certain priorities. This is why you have
105          * the freedom here to specify which priorities to register
106          * for the extension.
107          */
108         const int priorities[MAX_PRIORITIES];
109 };
110
111 struct pbx_test_pattern {
112         /*!
113          * \brief Test context
114          *
115          * \details
116          * This is the context to look in for a specific extension.
117          */
118         const char *context;
119         /*!
120          * \brief Test extension number
121          *
122          * \details
123          * This should be in the form of a specific number or string.
124          * For instance, if you were trying to match an extension defined
125          * with the pattern "_2." you might have as the test_exten one of
126          * "2000" , "2legit2quit" or some other specific match for the pattern.
127          */
128         const char *test_exten;
129         /*!
130          * \brief Test CID match
131          *
132          * \details
133          * If a specific CID match is required for pattern matching, then specify
134          * it in this parameter. Remember that a NULL CID and an empty CID are
135          * interpreted differently. For no CID match, leave this NULL. If you wish
136          * to explicitly match an empty CID, then use an empty string here.
137          */
138         const char *test_cid;
139         /*!
140          * \brief The priority to find
141          */
142         const int priority;
143         /*!
144          * \brief Expected extension match.
145          *
146          * \details
147          * This struct corresponds to an extension that was previously
148          * added to our test context. Once we have used all the above data
149          * to find an extension in the dialplan. We compare the data from that
150          * extension to the data that we have stored in this structure to be
151          * sure that what was matched was what we expected to match.
152          */
153         const struct exten_info *exten;
154 };
155
156 static int test_exten(const struct pbx_test_pattern *test_pattern, struct ast_test *test, int new_engine)
157 {
158         struct pbx_find_info pfi = { { 0 }, };
159         struct ast_exten *exten;
160         if (!(exten = pbx_find_extension(NULL, NULL, &pfi, test_pattern->context,
161                                         test_pattern->test_exten, test_pattern->priority, NULL,
162                                         test_pattern->test_cid, E_MATCH))) {
163                 ast_test_status_update(test, "Cannot find extension %s in context %s with the %s pattern match engine. "
164                                 "Test failed.\n", test_pattern->test_exten, test_pattern->context, (new_engine ? "new" : "old"));
165                 return -1;
166         }
167         if (strcmp(ast_get_extension_name(exten), test_pattern->exten->exten)) {
168                 ast_test_status_update(test, "Expected extension %s but got extension %s instead with the %s pattern match engine. "
169                                 "Test failed.\n", test_pattern->exten->exten, ast_get_extension_name(exten), (new_engine ? "new" : "old"));
170                 return -1;
171         }
172         if (test_pattern->test_cid && strcmp(ast_get_extension_cidmatch(exten), test_pattern->test_cid)) {
173                 ast_test_status_update(test, "Expected CID match %s but got CID match %s instead with the %s pattern match engine. "
174                                 "Test failed.\n", test_pattern->exten->cid, ast_get_extension_cidmatch(exten), (new_engine ? "new" : "old"));
175                 return -1;
176         }
177         if (!ast_canmatch_extension(NULL, test_pattern->context, test_pattern->test_exten,
178                                         test_pattern->priority, test_pattern->test_cid)) {
179                 ast_test_status_update(test, "Partial match failed for extension %s in context %s with the %s pattern match engine. "
180                                 "Test failed.\n", test_pattern->test_exten, test_pattern->context, (new_engine ? "new" : "old"));
181                 return -1;
182         }
183         ast_test_status_update(test, "Successfully matched %s to exten %s in context %s with the %s pattern match engine\n",
184                         test_pattern->test_exten, test_pattern->exten->exten, test_pattern->context, (new_engine ? "new" : "old"));
185         return 0;
186 }
187
188 AST_TEST_DEFINE(pattern_match_test)
189 {
190         static const char registrar[] = "test_pbx";
191         enum ast_test_result_state res = AST_TEST_PASS;
192         static const char TEST_PATTERN[] = "test_pattern";
193         static const char TEST_PATTERN_INCLUDE[] = "test_pattern_include";
194         int i, j;
195
196         /* The array of contexts to register for our test.
197          * To add more contexts, just add more rows to this array.
198          */
199         struct {
200                 const char * context_string;
201         } contexts[] = {
202                 { TEST_PATTERN, },
203                 { TEST_PATTERN_INCLUDE, },
204         };
205
206         /*
207          * Map to indicate which contexts should be included inside
208          * other contexts. The first context listed will include
209          * the second context listed.
210          *
211          * To add more inclusions, add new rows to this array.
212          */
213         const struct {
214                 const char *outer_context;
215                 const char *inner_context;
216         } context_includes[] = {
217                 { TEST_PATTERN, TEST_PATTERN_INCLUDE },
218         };
219
220         /* The array of extensions to add to our test context.
221          * For more information about the individual fields, see
222          * the doxygen for struct exten_info.
223          *
224          * To add new extensions to the test, simply add new rows
225          * to this array. All extensions will automatically be
226          * added when the test is run.
227          */
228         const struct exten_info extens[] = {
229                 [0] = { TEST_PATTERN, "_2.", NULL, 1, { 1 } },
230                 [1] = { TEST_PATTERN, "2000", NULL, 1, { 1 } },
231                 [2] = { TEST_PATTERN_INCLUDE, "2000", NULL, 1, { 2 } },
232         };
233
234         /* This array contains our test material. See the doxygen
235          * for struct pbx_test_pattern for more information on each
236          * component.
237          *
238          * To add more test cases, add more lines to this array. Each
239          * case will be tested automatically when the test is run.
240          */
241         const struct pbx_test_pattern tests[] = {
242                 { TEST_PATTERN, "200", NULL, 1, &extens[0] },
243                 { TEST_PATTERN, "2000", NULL, 1, &extens[1] },
244                 { TEST_PATTERN, "2000", NULL, 2, &extens[2] },
245                 { TEST_PATTERN_INCLUDE, "2000", NULL, 2, &extens[2] },
246         };
247
248         switch (cmd) {
249         case TEST_INIT:
250                 info->name = "pattern_match_test";
251                 info->category = "/main/pbx/";
252                 info->summary = "Test pattern matching";
253                 info->description = "Create a context with a bunch of extensions within. Then attempt\n"
254                         "to match some strings to the extensions.";
255                 return AST_TEST_NOT_RUN;
256         case TEST_EXECUTE:
257                 break;
258         }
259
260         /* Step one is to build the dialplan.
261          *
262          * We iterate first through the contexts array to build
263          * all the contexts we'll need. Then, we iterate over the
264          * extens array to add all the extensions to the appropriate
265          * contexts.
266          */
267
268         for (i = 0; i < ARRAY_LEN(contexts); ++i) {
269                 if (!ast_context_find_or_create(NULL, NULL, contexts[i].context_string, registrar)) {
270                         ast_test_status_update(test, "Failed to create context %s\n", contexts[i].context_string);
271                         res = AST_TEST_FAIL;
272                         goto cleanup;
273                 }
274         }
275
276         for (i = 0; i < ARRAY_LEN(context_includes); ++i) {
277                 if (ast_context_add_include(context_includes[i].outer_context,
278                                         context_includes[i].inner_context, registrar)) {
279                         ast_test_status_update(test, "Failed to include context %s inside context %s\n",
280                                         context_includes[i].inner_context, context_includes[i].outer_context);
281                         res = AST_TEST_FAIL;
282                         goto cleanup;
283                 }
284         }
285
286         for (i = 0; i < ARRAY_LEN(extens); ++i) {
287                 int priority;
288                 if (extens[i].num_priorities > MAX_PRIORITIES) {
289                         ast_test_status_update(test, "Invalid number of priorities specified for extension %s."
290                                         "Max is %d, but we requested %d. Test failed\n",
291                                         extens[i].exten, MAX_PRIORITIES, extens[i].num_priorities);
292                         res = AST_TEST_FAIL;
293                         goto cleanup;
294                 }
295                 for (priority = 0; priority < extens[i].num_priorities; ++priority) {
296                         if (ast_add_extension(extens[i].context, 0, extens[i].exten, extens[i].priorities[priority],
297                                                 NULL, extens[i].cid, "Noop", (void *) extens[i].exten, NULL, registrar)) {
298                                 ast_test_status_update(test, "Failed to add extension %s, priority %d, to context %s."
299                                                 "Test failed\n", extens[i].exten, extens[i].priorities[priority], extens[i].context);
300                                 res = AST_TEST_FAIL;
301                                 goto cleanup;
302                         }
303                 }
304         }
305
306         /* At this stage, the dialplan is built. Now we iterate over
307          * the tests array to attempt to find each of the specified
308          * extensions with the old and new pattern matching engines.
309          */
310         for (j = 0; j < 2; j++) {
311                 pbx_set_extenpatternmatchnew(j);
312                 for (i = 0; i < ARRAY_LEN(tests); ++i) {
313                         if (test_exten(&tests[i], test, j)) {
314                                 res = AST_TEST_FAIL;
315                                 break;
316                         }
317                 }
318         }
319
320 cleanup:
321         ast_context_destroy(NULL, registrar);
322
323         return res;
324 }
325
326 AST_TEST_DEFINE(segv)
327 {
328         switch (cmd) {
329         case TEST_INIT:
330                 info->name = "RAISE_SEGV";
331                 info->category = "/DO_NOT_RUN/";
332                 info->summary = "RAISES SEGV!!! (will only be run if explicitly called)";
333                 info->description = "RAISES SEGV!!! (will only be run if explicitly called). "
334                         "This test is mainly used for testing CI and tool failure scenarios.";
335                 info->explicit_only = 1;
336                 return AST_TEST_NOT_RUN;
337         case TEST_EXECUTE:
338                 break;
339         }
340
341         raise(SIGSEGV);
342
343         return AST_TEST_FAIL;
344 }
345
346 AST_TEST_DEFINE(call_assert)
347 {
348         switch (cmd) {
349         case TEST_INIT:
350                 info->name = "CALL_ASSERT";
351                 info->category = "/DO_NOT_RUN/";
352                 info->summary = "Calls ast_asert()!!! (will only be run if explicitly called)";
353                 info->description = "Calls ast_asert()!!! (will only be run if explicitly called). "
354                         "This test is mainly used for testing CI and tool failure scenarios.";
355                 info->explicit_only = 1;
356                 return AST_TEST_NOT_RUN;
357         case TEST_EXECUTE:
358                 break;
359         }
360
361         ast_assert(0);
362
363         return AST_TEST_PASS;
364 }
365
366 AST_TEST_DEFINE(call_backtrace)
367 {
368         switch (cmd) {
369         case TEST_INIT:
370                 info->name = "CALL_BACKTRACE";
371                 info->category = "/DO_NOT_RUN/";
372                 info->summary = "Calls ast_log_backtrace()!!! (will only be run if explicitly called)";
373                 info->description = "Calls ast_log_backtrace()!!! (will only be run if explicitly called). "
374                         "This test is mainly used for testing CI and tool failure scenarios.";
375                 info->explicit_only = 1;
376                 return AST_TEST_NOT_RUN;
377         case TEST_EXECUTE:
378                 break;
379         }
380
381         ast_log_backtrace();
382
383         return AST_TEST_PASS;
384 }
385
386 static int unload_module(void)
387 {
388         AST_TEST_UNREGISTER(call_backtrace);
389         AST_TEST_UNREGISTER(call_assert);
390         AST_TEST_UNREGISTER(segv);
391         AST_TEST_UNREGISTER(pattern_match_test);
392         return 0;
393 }
394
395 static int load_module(void)
396 {
397         AST_TEST_REGISTER(pattern_match_test);
398         AST_TEST_REGISTER(segv);
399         AST_TEST_REGISTER(call_assert);
400         AST_TEST_REGISTER(call_backtrace);
401         return AST_MODULE_LOAD_SUCCESS;
402 }
403
404 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "PBX test module");