Add the TESTTIME() dialplan function, which permits testing GotoIfTime.
Specifically, by setting TESTTIME() to a particular date and time, you can test whether a dialplan correctly branches as was intended. This was developed after recent questions on the -users list on how to test their holiday dialplan logic. (closes issue #16464) Reported by: tilghman Patches: 20100112__issue16464.diff.txt uploaded by tilghman (license 14) Review: https://reviewboard.asterisk.org/r/458/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@239957 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
9a75fff5ef
commit
0183b31199
|
@ -146,6 +146,14 @@ int ast_build_timing(struct ast_timing *i, const char *info);
|
|||
*/
|
||||
int ast_check_timing(const struct ast_timing *i);
|
||||
|
||||
/*!
|
||||
* \brief Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
|
||||
* \param i Pointer to an ast_timing structure.
|
||||
* \param tv Specified time
|
||||
* \retval Returns 1, if the time matches or 0, if the time falls outside of the specified range.
|
||||
*/
|
||||
int ast_check_timing2(const struct ast_timing *i, const struct timeval tv);
|
||||
|
||||
/*!
|
||||
* \brief Deallocates memory structures associated with a timing bitmap.
|
||||
* \param i Pointer to an ast_timing structure.
|
||||
|
|
87
main/pbx.c
87
main/pbx.c
|
@ -332,6 +332,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
<see-also>
|
||||
<ref type="application">GotoIf</ref>
|
||||
<ref type="function">IFTIME</ref>
|
||||
<ref type="function">TESTTIME</ref>
|
||||
</see-also>
|
||||
</application>
|
||||
<application name="ImportVar" language="en_US">
|
||||
|
@ -717,6 +718,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
<ref type="application">RaiseException</ref>
|
||||
</see-also>
|
||||
</function>
|
||||
<function name="TESTTIME" language="en_US">
|
||||
<synopsis>
|
||||
Sets a time to be used with the channel to test logical conditions.
|
||||
<synopsis>
|
||||
<syntax>
|
||||
<parameter name="date" required="true" argsep=" ">
|
||||
<para>Date in ISO 8601 format</para>
|
||||
</parameter>
|
||||
<parameter name="time" required="true" argsep=" ">
|
||||
<para>Time in HH:MM:SS format (24-hour time)</para>
|
||||
</parameter>
|
||||
<parameter name="zone" required="false">
|
||||
<para>Timezone name</para>
|
||||
</parameter>
|
||||
</syntax>
|
||||
<description>
|
||||
<para>To test dialplan timing conditions at times other than the current time, use
|
||||
this function to set an alternate date and time. For example, you may wish to evaluate
|
||||
whether a location will correctly identify to callers that the area is closed on Christmas
|
||||
Day, when Christmas would otherwise fall on a day when the office is normally open.</para>
|
||||
<see-also>
|
||||
<ref type="application">GotoIfTime</ref>
|
||||
</see-also>
|
||||
</function>
|
||||
<manager name="ShowDialPlan" language="en_US">
|
||||
<synopsis>
|
||||
La merde se produit.
|
||||
|
@ -7284,10 +7309,14 @@ int ast_build_timing(struct ast_timing *i, const char *info_in)
|
|||
|
||||
int ast_check_timing(const struct ast_timing *i)
|
||||
{
|
||||
struct ast_tm tm;
|
||||
struct timeval now = ast_tvnow();
|
||||
return ast_check_timing2(i, ast_tvnow());
|
||||
}
|
||||
|
||||
ast_localtime(&now, &tm, i->timezone);
|
||||
int ast_check_timing2(const struct ast_timing *i, const struct timeval tv)
|
||||
{
|
||||
struct ast_tm tm;
|
||||
|
||||
ast_localtime(&tv, &tm, i->timezone);
|
||||
|
||||
/* If it's not the right month, return */
|
||||
if (!(i->monthmask & (1 << tm.tm_mon)))
|
||||
|
@ -8927,6 +8956,38 @@ static int pbx_builtin_hangup(struct ast_channel *chan, const char *data)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup functions
|
||||
*/
|
||||
static int testtime_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
|
||||
{
|
||||
struct ast_tm tm;
|
||||
struct timeval tv;
|
||||
char *remainder, result[30], timezone[80];
|
||||
|
||||
/* Turn off testing? */
|
||||
if (!pbx_checkcondition(value)) {
|
||||
pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse specified time */
|
||||
if (!(remainder = ast_strptime(value, "%Y/%m/%d %H:%M:%S", &tm))) {
|
||||
return -1;
|
||||
}
|
||||
sscanf(remainder, "%79s", timezone);
|
||||
tv = ast_mktime(&tm, S_OR(timezone, NULL));
|
||||
|
||||
snprintf(result, sizeof(result), "%ld", (long) tv.tv_sec);
|
||||
pbx_builtin_setvar_helper(chan, "__TESTTIME", result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_custom_function testtime_function = {
|
||||
.name = "TESTTIME",
|
||||
.write = testtime_write,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
@ -8934,6 +8995,9 @@ static int pbx_builtin_gotoiftime(struct ast_channel *chan, const char *data)
|
|||
{
|
||||
char *s, *ts, *branch1, *branch2, *branch;
|
||||
struct ast_timing timing;
|
||||
const char *ctime;
|
||||
struct timeval tv = ast_tvnow();
|
||||
long timesecs;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n <time range>,<days of week>,<days of month>,<months>[,<timezone>]?'labeliftrue':'labeliffalse'\n");
|
||||
|
@ -8942,16 +9006,28 @@ static int pbx_builtin_gotoiftime(struct ast_channel *chan, const char *data)
|
|||
|
||||
ts = s = ast_strdupa(data);
|
||||
|
||||
if (chan) {
|
||||
ast_channel_lock(chan);
|
||||
if ((ctime = pbx_builtin_getvar_helper(chan, "TESTTIME")) && sscanf(ctime, "%ld", ×ecs) == 1) {
|
||||
tv.tv_sec = timesecs;
|
||||
} else if (ctime) {
|
||||
ast_log(LOG_WARNING, "Using current time to evaluate\n");
|
||||
/* Reset when unparseable */
|
||||
pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
|
||||
}
|
||||
ast_channel_unlock(chan);
|
||||
}
|
||||
/* Separate the Goto path */
|
||||
strsep(&ts, "?");
|
||||
branch1 = strsep(&ts,":");
|
||||
branch2 = strsep(&ts,"");
|
||||
|
||||
/* struct ast_include include contained garbage here, fixed by zeroing it on get_timerange */
|
||||
if (ast_build_timing(&timing, s) && ast_check_timing(&timing))
|
||||
if (ast_build_timing(&timing, s) && ast_check_timing2(&timing, tv)) {
|
||||
branch = branch1;
|
||||
else
|
||||
} else {
|
||||
branch = branch2;
|
||||
}
|
||||
ast_destroy_timing(&timing);
|
||||
|
||||
if (ast_strlen_zero(branch)) {
|
||||
|
@ -9618,6 +9694,7 @@ int load_pbx(void)
|
|||
ast_verb(1, "Registering builtin applications:\n");
|
||||
ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
|
||||
__ast_custom_function_register(&exception_function, NULL);
|
||||
__ast_custom_function_register(&testtime_function, NULL);
|
||||
|
||||
/* Register builtin applications */
|
||||
for (x = 0; x < ARRAY_LEN(builtins); x++) {
|
||||
|
|
Reference in New Issue