[asterisk-commits] tilghman: trunk r239957 - in /trunk: include/asterisk/pbx.h main/pbx.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jan 13 15:27:38 CST 2010


Author: tilghman
Date: Wed Jan 13 15:27:34 2010
New Revision: 239957

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=239957
Log:
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/

Modified:
    trunk/include/asterisk/pbx.h
    trunk/main/pbx.c

Modified: trunk/include/asterisk/pbx.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/pbx.h?view=diff&rev=239957&r1=239956&r2=239957
==============================================================================
--- trunk/include/asterisk/pbx.h (original)
+++ trunk/include/asterisk/pbx.h Wed Jan 13 15:27:34 2010
@@ -147,6 +147,14 @@
 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.
  * \retval 0 success

Modified: trunk/main/pbx.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/pbx.c?view=diff&rev=239957&r1=239956&r2=239957
==============================================================================
--- trunk/main/pbx.c (original)
+++ trunk/main/pbx.c Wed Jan 13 15:27:34 2010
@@ -332,6 +332,7 @@
 		<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 @@
 			<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_check_timing(const struct ast_timing *i)
 {
+	return ast_check_timing2(i, ast_tvnow());
+}
+
+int ast_check_timing2(const struct ast_timing *i, const struct timeval tv)
+{
 	struct ast_tm tm;
-	struct timeval now = ast_tvnow();
-
-	ast_localtime(&now, &tm, i->timezone);
+
+	ast_localtime(&tv, &tm, i->timezone);
 
 	/* If it's not the right month, return */
 	if (!(i->monthmask & (1 << tm.tm_mon)))
@@ -8928,12 +8957,47 @@
 }
 
 /*!
+ * \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
  */
 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 @@
 
 	ts = s = ast_strdupa(data);
 
+	if (chan) {
+		ast_channel_lock(chan);
+		if ((ctime = pbx_builtin_getvar_helper(chan, "TESTTIME")) && sscanf(ctime, "%ld", &timesecs) == 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 @@
 	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++) {




More information about the asterisk-commits mailing list