Asterisk - The Open Source Telephony Project GIT-master-f36a736
test_gosub.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2010, Digium, Inc.
5 *
6 * Tilghman Lesher <tlesher AT digium DOT 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/*!
20 * \file
21 * \brief Gosub tests
22 *
23 * \author Tilghman Lesher \verbatim <tlesher AT digium DOT com> \endverbatim
24 *
25 * \ingroup tests
26 */
27
28/*** MODULEINFO
29 <depend>TEST_FRAMEWORK</depend>
30 <support_level>core</support_level>
31 ***/
32
33#include "asterisk.h"
34
35#include "asterisk/utils.h"
36#include "asterisk/module.h"
37#include "asterisk/test.h"
38#include "asterisk/pbx.h"
39#include "asterisk/channel.h"
40
41AST_TEST_DEFINE(test_gosub)
42{
43#define CONTEXT_NAME "tests_test_gosub_virtual_context"
44 int res = AST_TEST_PASS, i;
45 struct ast_channel *chan;
46 struct ast_str *str;
47 struct testplan {
48 const char *app;
49 const char *args;
50 const char *expected_value;
51 } testplan[] = {
52 { NULL, "${STACK_PEEK(1,e,1)}", "" }, /* Stack is empty */
53 { "Gosub", "tests_test_gosub_virtual_context,s,1" },
54 { NULL, "${PRIORITY}", "1" },
55 { NULL, "${EXTEN}", "s" },
56 { NULL, "${STACK_PEEK(1,e,1)}", "" }, /* No extension originally */
57 { "Gosub", "test,dne,1", (const char *) -1 }, /* This is the only invocation that should fail. */
58 { NULL, "${PRIORITY}", "1" },
59 { NULL, "${EXTEN}", "s" },
60 { "Gosub", "tests_test_gosub_virtual_context,s,1(5,5,5,5,5)" },
61 { NULL, "${PRIORITY}", "1" },
62 { NULL, "$[0${ARG1} + 0${ARG5}]", "10" },
63 { NULL, "${STACK_PEEK(1,e)}", "s" },
64 { NULL, "${STACK_PEEK(1,c)}", "tests_test_gosub_virtual_context" },
65 { NULL, "${STACK_PEEK(1,p)}", "1" },
66 { NULL, "${STACK_PEEK(1,l)}", "tests_test_gosub_virtual_context,s,1" },
67 { "StackPop", "" },
68 { NULL, "${STACK_PEEK(1,e,1)}", "" }, /* Only 1 frame deep, my caller is top-level */
69 { "Gosub", "tests_test_gosub_virtual_context,s,1(5,5,5,5,5)" },
70 { "Gosub", "tests_test_gosub_virtual_context,s,1(4,4,4,4)" },
71 { NULL, "$[0${ARG1} + 0${ARG5}]", "4" },
72 { NULL, "$[0${ARG1} + 0${ARG4}]", "8" },
73 { "Gosub", "tests_test_gosub_virtual_context,s,1(3,3,3)" },
74 { NULL, "$[0${ARG1} + 0${ARG4}]", "3" },
75 { NULL, "$[0${ARG1} + 0${ARG3}]", "6" },
76 { "Gosub", "tests_test_gosub_virtual_context,s,1(2,2)" },
77 { NULL, "$[0${ARG1} + 0${ARG3}]", "2" },
78 { NULL, "$[0${ARG1} + 0${ARG2}]", "4" },
79 { "Gosub", "tests_test_gosub_virtual_context,s,1(1)" },
80 { NULL, "$[0${ARG1} + 0${ARG2}]", "1" },
81 { NULL, "$[0${ARG1} + 0${ARG1}]", "2" },
82 { "Gosub", "tests_test_gosub_virtual_context,s,1" },
83 { NULL, "$[0${ARG1} + 0${ARG1}]", "0" }, /* All arguments are correctly masked */
84 { "Set", "LOCAL(foo)=5" },
85 { NULL, "${foo}", "5" }, /* LOCAL() set a variable correctly */
86 { NULL, "${LOCAL_PEEK(0,ARG1)}", "" }, /* LOCAL_PEEK() arguments work correctly */
87 { NULL, "${LOCAL_PEEK(4,ARG1)}", "4" }, /* LOCAL_PEEK() arguments work correctly */
88 { NULL, "$[0${LOCAL_PEEK(3,ARG1)} + 0${LOCAL_PEEK(5,ARG1)}]", "8" },
89 { "StackPop", "" },
90 { NULL, "${foo}", "" }, /* StackPop removed the variable set with LOCAL() */
91 { "Return", "7" },
92 { NULL, "${GOSUB_RETVAL}", "7" }, /* Return sets a return value correctly */
93 { NULL, "$[0${GOSUB_RETVAL} + 0${ARG1}]", "9" }, /* Two frames less means ARG1 should have 2 */
94 };
95
96 switch (cmd) {
97 case TEST_INIT:
98 info->name = "gosub application";
99 info->category = "/apps/app_gosub/";
100 info->summary = "Verify functionality of gosub application";
101 info->description =
102 "Verify functionality of gosub application";
103 return AST_TEST_NOT_RUN;
104 case TEST_EXECUTE:
105 break;
106 }
107
108 if (!(chan = ast_dummy_channel_alloc())) {
109 ast_test_status_update(test, "Unable to allocate dummy channel\n");
110 return AST_TEST_FAIL;
111 }
112
113 if (!(str = ast_str_create(16))) {
114 ast_test_status_update(test, "Unable to allocate dynamic string buffer\n");
115 ast_channel_unref(chan);
116 return AST_TEST_FAIL;
117 }
118
119 /* Create our test dialplan */
120 if (!ast_context_find_or_create(NULL, NULL, CONTEXT_NAME, "test_gosub")) {
121 ast_test_status_update(test, "Unable to create test dialplan context");
122 ast_free(str);
123 ast_channel_unref(chan);
124 return AST_TEST_FAIL;
125 }
126
127 ast_add_extension(CONTEXT_NAME, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "test_gosub");
128
129 for (i = 0; i < ARRAY_LEN(testplan); i++) {
130 if (testplan[i].app == NULL) {
131 /* Evaluation */
132 ast_str_substitute_variables(&str, 0, chan, testplan[i].args);
133 if (strcmp(ast_str_buffer(str), testplan[i].expected_value)) {
134 ast_test_status_update(test, "Evaluation of '%s' returned '%s' instead of the expected value '%s'\n",
135 testplan[i].args, ast_str_buffer(str), testplan[i].expected_value);
136 res = AST_TEST_FAIL;
137 }
138 } else {
139 /* Run application */
140 intptr_t exec_res;
141 struct ast_app *app = pbx_findapp(testplan[i].app);
142 if (!app) {
143 ast_test_status_update(test, "Could not find '%s' in application listing!\n", testplan[i].app);
144 res = AST_TEST_FAIL;
145 break;
146 }
147
148 if ((exec_res = pbx_exec(chan, app, testplan[i].args)) && ((const char *) exec_res != testplan[i].expected_value)) {
149 ast_test_status_update(test, "Application '%s' exited abnormally (with code %d)\n", testplan[i].app, (int) exec_res);
150 res = AST_TEST_FAIL;
151 break;
152 }
153 }
154 }
155
156 ast_free(str);
157 ast_channel_unref(chan);
159 ast_context_destroy(NULL, "test_gosub");
160
161 return res;
162}
163
164static int unload_module(void)
165{
166 AST_TEST_UNREGISTER(test_gosub);
167 return 0;
168}
169
170static int load_module(void)
171{
172 AST_TEST_REGISTER(test_gosub);
174}
175
static const char app[]
Definition: app_adsiprog.c:56
const char * str
Definition: app_jack.c:147
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
General Asterisk PBX channel definitions.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1328
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
Core PBX routines and definitions.
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:6928
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6149
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:4948
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: pbx.c:8221
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define NULL
Definition: resample.c:96
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
ast_app: A registered application
Definition: pbx_app.c:45
Main Channel structure associated with a channel.
Support for dynamic strings.
Definition: strings.h:623
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
const char * args
AST_TEST_DEFINE(test_gosub)
Definition: test_gosub.c:41
#define CONTEXT_NAME
static int load_module(void)
Definition: test_gosub.c:170
static int unload_module(void)
Definition: test_gosub.c:164
Utility functions.
#define ARRAY_LEN(a)
Definition: utils.h:666