<p>N A has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/16629">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_assert: Add Assert application<br><br>Adds an assertion application to the dialplan that<br>can be used to verify constraints or properties<br>in the dialplan, similar to the assert() function<br>in C. Useful for codifying and enforcing behavior<br>and for test cases in the dialplan.<br><br>ASTERISK-29701 #close<br><br>Change-Id: Ia089c2debf608f42f5f87e6c29d50e8ebcc093e5<br>---<br>A apps/app_assert.c<br>A doc/CHANGES-staging/app_assert.txt<br>2 files changed, 172 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/29/16629/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_assert.c b/apps/app_assert.c</span><br><span>new file mode 100644</span><br><span>index 0000000..556926e</span><br><span>--- /dev/null</span><br><span>+++ b/apps/app_assert.c</span><br><span>@@ -0,0 +1,167 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2021, Naveen Albert</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Naveen Albert <asterisk@phreaknet.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Dialplan assertion application</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \author Naveen Albert <asterisk@phreaknet.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \ingroup applications</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+ <support_level>extended</support_level></span><br><span style="color: hsl(120, 100%, 40%);">+ ***/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/file.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/pbx.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/channel.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/dsp.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/indications.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/conversions.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*** DOCUMENTATION</span><br><span style="color: hsl(120, 100%, 40%);">+ <application name="Assert" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ Asserts that an expression is true.</span><br><span style="color: hsl(120, 100%, 40%);">+ </synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="expression"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>The expression to evaluate.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="options"></span><br><span style="color: hsl(120, 100%, 40%);">+ <optionlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <option name="d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>Do not hang up if expression is false.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </option></span><br><span style="color: hsl(120, 100%, 40%);">+ </optionlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ </syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ <description></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>Evaluates <replaceable>expression</replaceable> and continues dialplan</span><br><span style="color: hsl(120, 100%, 40%);">+ execution if the expression is true and ends the call with a warning</span><br><span style="color: hsl(120, 100%, 40%);">+ if it is false (unless the <replaceable>d</replaceable> option is provided).</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>This application can be used to verify functional correctness</span><br><span style="color: hsl(120, 100%, 40%);">+ of dialplans (e.g. dialplan test cases), similar to the <replaceable>assert</replaceable></span><br><span style="color: hsl(120, 100%, 40%);">+ function in C. For instance, if a certain property is expected to always hold at some</span><br><span style="color: hsl(120, 100%, 40%);">+ point in your dialplan, this application can be used to enforce that.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ <see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="application">RaiseException</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ </see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ </application></span><br><span style="color: hsl(120, 100%, 40%);">+ ***/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum read_option_flags {</span><br><span style="color: hsl(120, 100%, 40%);">+ OPT_NOHANGUP = (1 << 0),</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_APP_OPTIONS(read_app_options, {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_OPTION('d', OPT_NOHANGUP),</span><br><span style="color: hsl(120, 100%, 40%);">+});</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *app = "Assert";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int assert_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *argcopy = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_flags flags = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+ int value = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_DECLARE_APP_ARGS(arglist,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(expression);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(options);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "%s requires an argument (variable)\n", app);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ argcopy = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_STANDARD_APP_ARGS(arglist, argcopy);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(arglist.options)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(arglist.expression)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "%s requires an argument (variable)\n", app);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ value = atoi(arglist.expression); /* already parsed, so it should already be an integer anyways */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!value) {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_DECLARE_APP_ARGS(extendata,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(expr);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(rest);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *exprparse = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *datacopy = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *context, *exten;</span><br><span style="color: hsl(120, 100%, 40%);">+ int priority;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* so, what was the expression? Let's find out */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_exten *e;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_lock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ context = ast_strdupa(ast_channel_context(chan));</span><br><span style="color: hsl(120, 100%, 40%);">+ exten = ast_strdupa(ast_channel_exten(chan));</span><br><span style="color: hsl(120, 100%, 40%);">+ priority = ast_channel_priority(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_unlock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_rdlock_contexts();</span><br><span style="color: hsl(120, 100%, 40%);">+ e = pbx_find_extension(chan, NULL, &q, context, exten, priority, NULL, "", E_MATCH);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_unlock_contexts();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!e) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Couldn't find current execution location\n"); /* should never happen */</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ exprparse = ast_get_extension_app_data(e);</span><br><span style="color: hsl(120, 100%, 40%);">+ datacopy = ast_strdupa(exprparse);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_STANDARD_APP_ARGS(extendata, datacopy);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Assertion failed: %s\n", extendata.expr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_test_flag(&flags, OPT_NOHANGUP)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int unload_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_unregister_application(app);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int load_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_register_application_xml(app, assert_exec);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Dialplan assertion test application");</span><br><span>diff --git a/doc/CHANGES-staging/app_assert.txt b/doc/CHANGES-staging/app_assert.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..6703b04</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/app_assert.txt</span><br><span>@@ -0,0 +1,5 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: app_assert</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Adds an Assert application that can be used to verify</span><br><span style="color: hsl(120, 100%, 40%);">+and enforce constraints or conditions in the dialplan,</span><br><span style="color: hsl(120, 100%, 40%);">+similar to the assert() function in C.</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/16629">change 16629</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/16629"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ia089c2debf608f42f5f87e6c29d50e8ebcc093e5 </div>
<div style="display:none"> Gerrit-Change-Number: 16629 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: N A <mail@interlinked.x10host.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>