[asterisk-commits] mnicholson: branch mnicholson/asttest r167251 - in /team/mnicholson/asttest/a...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Jan 6 12:28:56 CST 2009
Author: mnicholson
Date: Tue Jan 6 12:28:55 2009
New Revision: 167251
URL: http://svn.digium.com/view/asterisk?view=rev&rev=167251
Log:
Tweaked test execution code and added a basic test library to the test driver.
* asttest/tools/mkstring.c: added, builds a c string out of the given file
* asttest/include/asttest/testsuite.h: added ts_result enum
* asttest/include/asttest/lua.h, asttest/lib/lua.c: added, lua utitily
functions
* asttest/lib/asttest.lua: added, lua testing library
* asttest/lib/testsuite.c (ts_print): fixed textual error
* asttest/asttest.c (process_test_result): return the test result
* asttest/asttest.c (print_test_name): added, for progress output
* asttest/asttest.c (print_test_result): added, for progress output
* asttest/asttest.c (run_test): return the test result and treat no explicit
test result as a pass
* asttest/asttest.c (ignored_dir): refactored
* asttest/asttest.c (process_tests_in_dir): renamed to process_test_dir
* asttest/asttest.c (process_test_dir): return an error if tests failed and
print out test status as tests are run
* asttest/Makefile: updated
Added:
team/mnicholson/asttest/asttest/include/asttest/lua.h (with props)
team/mnicholson/asttest/asttest/lib/asttest.lua (with props)
team/mnicholson/asttest/asttest/lib/lua.c (with props)
team/mnicholson/asttest/asttest/tools/
team/mnicholson/asttest/asttest/tools/mkstring.c (with props)
Modified:
team/mnicholson/asttest/asttest/Makefile
team/mnicholson/asttest/asttest/asttest.c
team/mnicholson/asttest/asttest/include/asttest/testsuite.h
team/mnicholson/asttest/asttest/lib/testsuite.c
Modified: team/mnicholson/asttest/asttest/Makefile
URL: http://svn.digium.com/view/asterisk/team/mnicholson/asttest/asttest/Makefile?view=diff&rev=167251&r1=167250&r2=167251
==============================================================================
--- team/mnicholson/asttest/asttest/Makefile (original)
+++ team/mnicholson/asttest/asttest/Makefile Tue Jan 6 12:28:55 2009
@@ -21,7 +21,7 @@
.PHONY: clean dist-clean distclean test check asterisk
# Basic set of sources and flags/libraries/includes
-OBJS:=asttest.o lib/testsuite.o
+OBJS:=asttest.o lib/lua.o lib/testsuite.o
CFLAGS:=-g -c -D_GNU_SOURCE -Wall -I/usr/include/lua5.1 -Iinclude
T_LIBS:=-llua5.1
@@ -63,8 +63,17 @@
cd ../ && ./configure --enable-dev-mode --prefix=$(AST_INSTALL_DIR) --localstatedir=$(AST_INSTALL_DIR)/var
$(MAKE) -C ../ install
+lib/lua.o: lib/lua.c include/asttest/lua.h include/asttest/testsuite.h lib/asttest_lua.h
+lib/testsuite.o: lib/testsuite.c include/asttest/testsuite.h
+
asttest: $(OBJS) $(T_OBJS)
$(CC) -o $@ $^ $(T_LIBS)
+
+lib/asttest_lua.h: lib/asttest.lua tools/mkstring
+ ./tools/mkstring -n asttest_lua -o lib/asttest_lua.h lib/asttest.lua
+
+tools/mkstring: tools/mkstring.c
+ $(CC) -D_GNU_SOURCE -Wall -o $@ $^
check: test
tests: test
@@ -73,6 +82,8 @@
clean:
rm -f asttest $(OBJS) $(M_OBJS) $(C_OBJS) $(G_OBJS) $(N_OBJS)
+ rm -f lib/asttest_lua.h
+ rm -f tools/mkstring
rm -rf $(AST_INSTALL_DIR)
dist-clean: distclean
Modified: team/mnicholson/asttest/asttest/asttest.c
URL: http://svn.digium.com/view/asterisk/team/mnicholson/asttest/asttest/asttest.c?view=diff&rev=167251&r1=167250&r2=167251
==============================================================================
--- team/mnicholson/asttest/asttest/asttest.c (original)
+++ team/mnicholson/asttest/asttest/asttest.c Tue Jan 6 12:28:55 2009
@@ -31,6 +31,7 @@
#include <lauxlib.h>
#include <lualib.h>
+#include "asttest/lua.h"
#include "asttest/testsuite.h"
@@ -69,13 +70,16 @@
* }
* \endcode
*/
-void process_test_result(struct testsuite *ts, const char *test_name, lua_State *L) {
+enum ts_result process_test_result(struct testsuite *ts, const char *test_name, lua_State *L) {
+ enum ts_result res = TS_SKIP;
+
if (lua_isstring(L, -1)) {
/* this is not a test result, log the error */
ts_log(ts, test_name, "error: %s\n", lua_tostring(L, -1));
lua_pop(L, 1);
ts_skip(ts, test_name);
+ res = TS_SKIP;
} else if (lua_type(L, -1) == LUA_TTABLE) {
int result_table = lua_gettop(L);
int reason_string = 0;
@@ -92,6 +96,7 @@
lua_pop(L, 1);
ts_log(ts, test_name, "error reading test result\n");
ts_skip(ts, test_name);
+ res = TS_SKIP;
} else {
test_result = lua_gettop(L);
@@ -100,15 +105,20 @@
if (result_equals(L, test_result, "pass")) {
ts_pass(ts, test_name);
+ res = TS_PASS;
} else if (result_equals(L, test_result, "fail")) {
ts_fail(ts, test_name);
+ res = TS_FAIL;
} else if (result_equals(L, test_result, "xfail")) {
ts_xfail(ts, test_name);
+ res = TS_XFAIL;
} else if (result_equals(L, test_result, "skip")) {
ts_skip(ts, test_name);
+ res = TS_SKIP;
} else {
ts_log(ts, test_name, "unknown result '%s'\n", lua_tostring(L, test_result));
ts_skip(ts, test_name);
+ res = TS_SKIP;
}
}
@@ -122,35 +132,73 @@
lua_pop(L, 1);
ts_log(ts, test_name, "missing test result\n");
ts_skip(ts, test_name);
- }
-}
-
-int run_test(struct testsuite *ts, const char *test_name, const char *test_dir_path) {
+ res = TS_SKIP;
+ }
+
+ return res;
+}
+
+void print_test_name(struct testsuite *ts, const char *test_name) {
+ int len, i;
+
+ /* first print a number */
+ len = printf("%d.", ts->total + 1);
+
+ /* pad the number printed */
+ for (i = 4 - len; i > 0; i--) {
+ printf(" ");
+ }
+
+ /* now print the test name */
+ len = printf(" %s: ", test_name);
+
+ /* now pad the test name */
+ for (i = 31 - len; i > 0; i--) {
+ printf(" ");
+ }
+}
+
+void print_test_result(enum ts_result result) {
+ switch (result) {
+ case TS_PASS:
+ printf("pass\n");
+ break;
+ case TS_FAIL:
+ printf("fail\n");
+ break;
+ case TS_XFAIL:
+ printf("xfail\n");
+ break;
+ case TS_SKIP:
+ printf("skip\n");
+ break;
+ default:
+ printf("unknown\n");
+ break;
+ }
+}
+
+enum ts_result run_test(struct testsuite *ts, const char *test_name, const char *test_dir_path) {
char test_file_path[1024];
- lua_State *L = luaL_newstate();
+ lua_State *L = get_lua_state(ts, test_name);
+ enum ts_result result = TS_SKIP;
if (!L) {
- fprintf(stderr, "Error creating lua_State\n");
- return 1;
- }
-
- luaL_openlibs(L);
-
- // TODO load the standard test libraries
-
+ ts_log(ts, test_name, "internal error, cannot run test\n");
+ ts_skip(ts, test_name);
+ return result;
+ }
+
snprintf(test_file_path, sizeof(test_file_path), "%s/test.lua", test_dir_path);
if (luaL_dofile(L, test_file_path)) {
- process_test_result(ts, test_name, L);
- lua_close(L);
- return 1;
+ result = process_test_result(ts, test_name, L);
} else {
- ts_log(ts, test_name, "test did not return a result\n");
- ts_skip(ts, test_name);
- lua_close(L);
- return 1;
+ /* we got not explicit result, consider it a pass */
+ ts_pass(ts, test_name);
+ result = TS_PASS;
}
lua_close(L);
- return 0;
+ return result;
}
int is_directory(const char *dir) {
@@ -165,20 +213,23 @@
int ignored_dir(const char *dir) {
char *dir_dup = strdup(dir); /* dup the string as basename may modify it */
char *base_dir = basename(dir_dup);
+ int res = 0;
if (base_dir[0] == '.') {
- free(dir_dup);
- return 1;
- }
+ res = 1;
+ }
+
free(dir_dup);
- return 0;
-}
-
-int process_tests_in_dir(const char *path) {
+ return res;
+}
+
+int process_test_dir(const char *path) {
DIR *main_dir = opendir(path);
char full_path[1024];
struct testsuite ts;
struct dirent *ent;
+ enum ts_result result;
+ int res = 0;
if (!main_dir) {
fprintf(stderr, "Error opening path '%s': %s\n", path, strerror(errno));
@@ -190,15 +241,26 @@
while ((ent = readdir(main_dir))) {
snprintf(full_path, sizeof(full_path), "%s/%s", path, ent->d_name);
if (is_directory(full_path) && !ignored_dir(full_path)) {
- run_test(&ts, ent->d_name, full_path);
+ print_test_name(&ts, ent->d_name);
+ result = run_test(&ts, ent->d_name, full_path);
+ print_test_result(result);
}
}
closedir(main_dir);
+ printf("\n");
ts_print(&ts);
+ /* consider this run a failure if any tests failed */
+ if (ts.fail)
+ res = 1;
+
+ /* if any tests were skipped print a warning */
+ if (ts.skip)
+ printf("\n***WARNING: some tests were skipped, see log for details\n");
+
ts_cleanup(&ts);
- return 0;
+ return res;
}
void usage(const char *prog_name) {
@@ -215,5 +277,5 @@
// TODO process args and except --log (-l) as an argument for where to log
- return process_tests_in_dir(argv[1]);
-}
+ return process_test_dir(argv[1]);
+}
Added: team/mnicholson/asttest/asttest/include/asttest/lua.h
URL: http://svn.digium.com/view/asterisk/team/mnicholson/asttest/asttest/include/asttest/lua.h?view=auto&rev=167251
==============================================================================
--- team/mnicholson/asttest/asttest/include/asttest/lua.h (added)
+++ team/mnicholson/asttest/asttest/include/asttest/lua.h Tue Jan 6 12:28:55 2009
@@ -1,0 +1,28 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2008, Digium, Inc.
+ *
+ * Matthew Nichiolson <mnicholson at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#ifndef ASTTEST_LUA_H
+#define ASTTEST_LUA_H
+
+#include <lua.h>
+
+#include "asttest/testsuite.h"
+
+lua_State *get_lua_state(struct testsuite *ts, const char *test_name);
+
+#endif
Propchange: team/mnicholson/asttest/asttest/include/asttest/lua.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mnicholson/asttest/asttest/include/asttest/lua.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mnicholson/asttest/asttest/include/asttest/lua.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/mnicholson/asttest/asttest/include/asttest/testsuite.h
URL: http://svn.digium.com/view/asterisk/team/mnicholson/asttest/asttest/include/asttest/testsuite.h?view=diff&rev=167251&r1=167250&r2=167251
==============================================================================
--- team/mnicholson/asttest/asttest/include/asttest/testsuite.h (original)
+++ team/mnicholson/asttest/asttest/include/asttest/testsuite.h Tue Jan 6 12:28:55 2009
@@ -28,6 +28,13 @@
FILE *log;
};
+enum ts_result {
+ TS_PASS,
+ TS_FAIL,
+ TS_XFAIL,
+ TS_SKIP,
+};
+
int ts_init(struct testsuite *ts, const char *log_file_path);
void ts_cleanup(struct testsuite *ts);
Added: team/mnicholson/asttest/asttest/lib/asttest.lua
URL: http://svn.digium.com/view/asterisk/team/mnicholson/asttest/asttest/lib/asttest.lua?view=auto&rev=167251
==============================================================================
--- team/mnicholson/asttest/asttest/lib/asttest.lua (added)
+++ team/mnicholson/asttest/asttest/lib/asttest.lua Tue Jan 6 12:28:55 2009
@@ -1,0 +1,75 @@
+--
+-- Asterisk -- An open source telephony toolkit.
+--
+-- Copyright (C) 1999 - 2008, Digium, Inc.
+--
+-- Matthew Nichiolson <mnicholson at digium.com>
+--
+-- See http://www.asterisk.org for more information about
+-- the Asterisk project. Please do not directly contact
+-- any of the maintainers of this project for assistance;
+-- the project provides a web site, mailing lists and IRC
+-- channels for your use.
+--
+-- This program is free software, distributed under the terms of
+-- the GNU General Public License Version 2. See the LICENSE file
+-- at the top of the source tree.
+--
+
+--
+-- basic pass/fail/xfail/skip functions
+-- note: none of these functions actually return
+--
+
+function pass(reason)
+ return error{result = "pass", reason = reason}
+end
+
+function fail(reason)
+ return error{result = "fail", reason = reason}
+end
+
+function xfail(reason)
+ return error{result = "xfail", reason = reason}
+end
+
+function skip(reason)
+ return error{result = "skip", reason = reason}
+end
+
+--
+-- utility functions
+--
+
+-- fail if condition is false using message as the reason
+function check(condition, message)
+ if not condition then
+ return fail(message)
+ end
+end
+
+-- xfail if condition is false using message as the reason
+function xcheck(condition, message)
+ if not condition then
+ return xfail(message)
+ end
+end
+
+--
+-- replacements for global functions
+--
+
+-- print to the test log instead of stdout
+function print(...)
+ local string = ""
+ for i, v in ipairs(arg) do
+ if i == 1 then
+ string = string .. tostring(v)
+ else
+ string = string .. "\t" .. tostring(v)
+ end
+ end
+ string = string .. "\n"
+ ts_log(string)
+end
+
Propchange: team/mnicholson/asttest/asttest/lib/asttest.lua
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mnicholson/asttest/asttest/lib/asttest.lua
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mnicholson/asttest/asttest/lib/asttest.lua
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/mnicholson/asttest/asttest/lib/lua.c
URL: http://svn.digium.com/view/asterisk/team/mnicholson/asttest/asttest/lib/lua.c?view=auto&rev=167251
==============================================================================
--- team/mnicholson/asttest/asttest/lib/lua.c (added)
+++ team/mnicholson/asttest/asttest/lib/lua.c Tue Jan 6 12:28:55 2009
@@ -1,0 +1,112 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2008, Digium, Inc.
+ *
+ * Matthew Nichiolson <mnicholson at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+#include "asttest/lua.h"
+#include "asttest/testsuite.h"
+
+#include "asttest_lua.h"
+
+/*
+ * \brief Push the current testsuite on the stack and return a pointer to it.
+ * \param L the lua state to use
+ */
+struct testsuite *push_ts(lua_State *L) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "asttest_ts");
+ return lua_touserdata(L, -1);
+}
+
+/*
+ * \brief Push the current test's name on the stack and return a pointer to it.
+ * \param L the lua state to use
+ */
+const char *push_test_name(lua_State *L) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "asttest_name");
+ return lua_tostring(L, -1);
+}
+
+/*
+ * \brief [lua_CFunction] Log a message for the current test.
+ * \param message [lua] the string to log
+ */
+int lua_ts_log(lua_State *L) {
+ const char *string = luaL_checkstring(L, 1);
+ struct testsuite *ts = push_ts(L);
+ const char *name = push_test_name(L);
+
+ ts_log(ts, name, "%s\n", string);
+
+ return 0;
+}
+
+/*
+ * \brief Setup lua registry values.
+ * \param ts the test suite
+ * \param test_name the name of the current test
+ */
+int setup_registry(lua_State *L, struct testsuite *ts, const char *test_name) {
+ lua_pushlightuserdata(L, ts);
+ lua_setfield(L, LUA_REGISTRYINDEX, "asttest_ts");
+
+ lua_pushstring(L, test_name);
+ lua_setfield(L, LUA_REGISTRYINDEX, "asttest_name");
+
+ return 0;
+}
+
+/*
+ * \brief Setup lua global values.
+ * \param test_name the name of the current test
+ *
+ * This function sets up global values such as the name of the current test and
+ * global functions and objects that tests can use.
+ */
+int setup_globals(lua_State *L, const char *test_name) {
+ lua_pushstring(L, test_name);
+ lua_setglobal(L, "name");
+
+ lua_pushcfunction(L, lua_ts_log);
+ lua_setglobal(L, "ts_log");
+
+ return 0;
+}
+
+lua_State *get_lua_state(struct testsuite *ts, const char *test_name) {
+ lua_State *L = luaL_newstate();
+ if (!L) {
+ return NULL;
+ }
+
+ luaL_openlibs(L);
+
+ setup_registry(L, ts, test_name);
+ setup_globals(L, test_name);
+
+ /* load the test library */
+ if (luaL_loadbuffer(L, asttest_lua, sizeof(asttest_lua), "asttest.lua") || lua_pcall(L, 0, LUA_MULTRET, 0)) {
+ ts_log(ts, test_name, "error loading test library: %s\n", lua_tostring(L, -1));
+ lua_close(L);
+ return NULL;
+ }
+
+ return L;
+}
+
Propchange: team/mnicholson/asttest/asttest/lib/lua.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mnicholson/asttest/asttest/lib/lua.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mnicholson/asttest/asttest/lib/lua.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/mnicholson/asttest/asttest/lib/testsuite.c
URL: http://svn.digium.com/view/asterisk/team/mnicholson/asttest/asttest/lib/testsuite.c?view=diff&rev=167251&r1=167250&r2=167251
==============================================================================
--- team/mnicholson/asttest/asttest/lib/testsuite.c (original)
+++ team/mnicholson/asttest/asttest/lib/testsuite.c Tue Jan 6 12:28:55 2009
@@ -49,7 +49,7 @@
printf(" expected failures: %d\n", ts->xfail);
printf(" tests skipped: %d\n", ts->skip);
printf("\n");
- printf("Total test run: %d\n", ts->total);
+ printf("Total tests run: %d\n", ts->total);
}
int ts_log_va(struct testsuite *ts, const char *test_name, const char *fmt, va_list ap) {
Added: team/mnicholson/asttest/asttest/tools/mkstring.c
URL: http://svn.digium.com/view/asterisk/team/mnicholson/asttest/asttest/tools/mkstring.c?view=auto&rev=167251
==============================================================================
--- team/mnicholson/asttest/asttest/tools/mkstring.c (added)
+++ team/mnicholson/asttest/asttest/tools/mkstring.c Tue Jan 6 12:28:55 2009
@@ -1,0 +1,120 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2008, Digium, Inc.
+ *
+ * Matthew Nichiolson <mnicholson at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+struct mkstring_options {
+ char *infile;
+ char *outfile;
+ char *name;
+};
+
+int mkstring(struct mkstring_options *opts) {
+ FILE *infile;
+ FILE *outfile;
+ char c;
+ int count;
+
+ if (!(infile = fopen(opts->infile, "r"))) {
+ fprintf(stderr, "Error opening file '%s' for reading: %s\n", opts->infile, strerror(errno));
+ return 1;
+ }
+
+ if (!(outfile = fopen(opts->outfile, "w"))) {
+ fprintf(stderr, "Error opening file '%s' for wriring: %s\n", opts->outfile, strerror(errno));
+ fclose(infile);
+ return 1;
+ }
+
+ fprintf(outfile,
+ "/* This file is automatically generated. DO NOT EDIT. */\n"
+ "\n"
+ "const char %s[] = {\n", opts->name);
+
+ count = 0;
+ while (fread(&c, sizeof(char), 1, infile)) {
+ count += fprintf(outfile, "%3i, ", c);
+ if (count > 72) {
+ count = 0;
+ fprintf(outfile, "\n");
+ }
+ }
+
+ fprintf(outfile, "\n};\n");
+
+ fclose(infile);
+ fclose(outfile);
+ return 0;
+}
+
+char *parse_option(int argc, char *argv[], int i) {
+ // option in the form of '-ooption'
+ if (strlen(argv[i]) > 2) {
+ return argv[i] + 2;
+ } else { // option in the form '-o option'
+ if (argc > i + 1)
+ return argv[i + 1];
+ }
+ return NULL;
+}
+
+int parse_cmdline(int argc, char *argv[], struct mkstring_options *opts) {
+ int i = 0;
+ for (i = 0; i < argc; i++) {
+ if (i == 0)
+ continue;
+
+ if (argv[i][0] == '-' && strlen(argv[i]) >= 2) {
+ if (argv[i][1] == 'o') {
+ opts->outfile = parse_option(argc, argv, i);
+ } else if (argv[i][1] == 'n') {
+ opts->name = parse_option(argc, argv, i);
+ }
+ } else {
+ opts->infile = argv[i];
+ }
+ }
+
+ if (!opts->infile
+ || !opts->outfile
+ || !opts->name) {
+ fprintf(stderr, "Invalid arguments\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+void usage(const char *prog_name) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s -n <string_name> -o <out.h> <in.txt>\n", prog_name);
+}
+
+int main(int argc, char *argv[]) {
+ struct mkstring_options opts;
+ memset(&opts, 0, sizeof(struct mkstring_options));
+
+ if (parse_cmdline(argc, argv, &opts)) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ return mkstring(&opts);
+}
Propchange: team/mnicholson/asttest/asttest/tools/mkstring.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mnicholson/asttest/asttest/tools/mkstring.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mnicholson/asttest/asttest/tools/mkstring.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the asterisk-commits
mailing list