[asterisk-commits] branch russell/codetest - r7622 in
/team/russell/codetest: ./ channels/ inclu...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Sat Dec 24 21:37:29 CST 2005
Author: russell
Date: Sat Dec 24 21:37:25 2005
New Revision: 7622
URL: http://svn.digium.com/view/asterisk?rev=7622&view=rev
Log:
add an implementation of some of my ideas
I will post details to issue #6045 in a few minutes
Added:
team/russell/codetest/codetest.c
team/russell/codetest/include/asterisk/codetest.h
Modified:
team/russell/codetest/Makefile
team/russell/codetest/asterisk.c
team/russell/codetest/channels/chan_sip.c
team/russell/codetest/include/asterisk.h
Modified: team/russell/codetest/Makefile
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/Makefile?rev=7622&r1=7621&r2=7622&view=diff
==============================================================================
--- team/russell/codetest/Makefile (original)
+++ team/russell/codetest/Makefile Sat Dec 24 21:37:25 2005
@@ -154,6 +154,9 @@
# Determine by a grep 'ScriptAlias' of your httpd.conf file
HTTP_CGIDIR=/var/www/cgi-bin
+# Uncomment the following to enable code testing code to be enabled :)
+ASTCFLAGS+=-DENABLE_CODE_TEST
+
# If the file .asterisk.makeopts is present in your home directory, you can
# include all of your favorite Makefile options so that every time you download
# a new version of Asterisk, you don't have to edit the makefile to set them.
@@ -344,6 +347,10 @@
utils.o plc.o jitterbuf.o dnsmgr.o devicestate.o \
netsock.o slinfactory.o ast_expr2.o ast_expr2f.o \
cryptostub.o
+
+ifeq ($(findstring -DENABLE_CODE_TEST,$(ASTCFLAGS)),-DENABLE_CODE_TEST)
+ OBJS+= codetest.o
+endif
ifeq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/sys/poll.h),)
OBJS+= poll.o
Modified: team/russell/codetest/asterisk.c
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/asterisk.c?rev=7622&r1=7621&r2=7622&view=diff
==============================================================================
--- team/russell/codetest/asterisk.c (original)
+++ team/russell/codetest/asterisk.c Sat Dec 24 21:37:25 2005
@@ -2275,6 +2275,12 @@
srand((unsigned int) getpid() + (unsigned int) time(NULL));
srandom((unsigned int) getpid() + (unsigned int) time(NULL));
+#ifdef ENABLE_CODE_TEST
+ if (codetest_init()) {
+ printf(term_quit());
+ exit(1);
+ }
+#endif
if (init_logger()) {
printf(term_quit());
exit(1);
Modified: team/russell/codetest/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/channels/chan_sip.c?rev=7622&r1=7621&r2=7622&view=diff
==============================================================================
--- team/russell/codetest/channels/chan_sip.c (original)
+++ team/russell/codetest/channels/chan_sip.c Sat Dec 24 21:37:25 2005
@@ -81,6 +81,7 @@
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/linkedlists.h"
+#include "asterisk/codetest.h"
#ifdef OSP_SUPPORT
#include "asterisk/astosp.h"
@@ -12987,6 +12988,115 @@
);
}
+#ifdef ENABLE_CODE_TEST
+/* Create SIP messages for testing. Number indicates which test packet */
+static struct sip_request *create_sip_message(int number)
+{
+ struct sip_request *req;
+ char *demo_packet[3];
+
+ /* 1. OPTIONS packet */
+ demo_packet[0] =
+ "OPTIONS sip:3000 at 192.168.236.49 SIP/2.0\n"
+ "Via: SIP/2.0/UDP 192.168.11.11:5060;branch=z9hG4bK193148bb\n"
+ "From: \"asterisk\" <sip:asterisk at 192.168.94.55>;tag=as2b0e6ece\n"
+ "To: <sip:3000 at 192.168.236.49>\n"
+ "Contact: <sip:asterisk at 194.168.94.55>\n"
+ "Call-ID: 3f66e2987339aee36b54cc2f5e371b46 at 194.168.94.55\n"
+ "CSeq: 102 OPTIONS\n"
+ "User-Agent: Asterisk 1.0\n"
+ "Date: Fri, 23 Dec 2005 05:19:48 GMT\n"
+ "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER\n"
+ "Content-Length: 0\n";
+
+ /* 2. Asterisk reply to options (without SDP) , fromtag and totag*/
+ demo_packet[1] =
+ "SIP/2.0 200 OK\n"
+ "Via: SIP/2.0/UDP 192.168.94.55:5060;branch=z9hG4bK193148bb;received=194.168.94.55\n"
+ "From: \"asterisk\" <sip:asterisk at 194.168.94.55>;tag=as2b0e6ece\n"
+ "To: <sip:3000 at 192.168.236.49>;tag=as220106ec\n"
+ "Call-ID: 3f66e2987339aee36b54cc2f5e371b46 at 192.168.94.55\n"
+ "CSeq: 102 OPTIONS\n"
+ "User-Agent: Asterisk 1.2\n"
+ "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY\n"
+ "Max-Forwards: 70\n"
+ "Contact: <sip:192.168.236.49>\n"
+ "Accept: application/sdp\n"
+ "Content-Length: 0\n";
+
+ /* 3. Registration request without auth and no white space (WiSIP phone) */
+ demo_packet[2] =
+ "REGISTER sip:jarl.digium.com:5060 SIP/2.0\n"
+ "Via:SIP/2.0/UDP 192.168.123.149:5060;branch=z9hG4bk723df946284bd7\n"
+ "From:<sip:3300 at jarl.digium.com;user=phone>;tag=B5913DFE66749B9A26B\n"
+ "To:<sip:3300 at jarl.digium.com;user=phone>\n"
+ "Call-ID:8870-D1B9-8CA6-CD71-6061F4366992 at 192.168.123.149\n"
+ "CSeq:86034 REGISTER\n"
+ "User-Agent: WiSIP\n"
+ "Contact: <sip:3300 at 192.168.123.149:5060;transport=udp>\n"
+ "Expires: 120\n"
+ "Content-Length: 0\n";
+
+ req = malloc(sizeof(struct sip_request));
+ if (!req) {
+ ast_log(LOG_DEBUG, "Memory allocation error.\n");
+ return NULL;
+ }
+ memset(req, 0, sizeof(struct sip_request));
+ /* Copy packet into packet if you know what I mean */
+ ast_copy_string(req->data, demo_packet[number], sizeof(req->data));
+ req->len = sizeof(demo_packet[number]);
+
+ /* Fix multiline headers - only done in pedantic mode in chan_sip (sipsock_read) */
+ req->len = lws2sws(req->data, req->len);
+
+ /* Parse packet */
+ parse_request(req);
+ /* Find method */
+ req->method = find_sip_method(req->rlPart1);
+
+ /* We're done, have a full packet, parsed and ready */
+ return req;
+}
+#endif
+
+#ifdef ENABLE_CODE_TEST
+/*! \brief Test tag retrieval code */
+static int test_tags_func(int fd, int argc, char *argv[])
+{
+ struct sip_request *req;
+ char buf[BUFSIZ];
+ char *result;
+ int error = 0;
+
+ /* Test first packet, initial OPTIONS request with from tag and no to tag */
+ req = create_sip_message(0);
+ result = gettag(req, "To", buf, sizeof(buf));
+ if (option_debug > 3)
+ ast_log(LOG_DEBUG, "Test-tags: To-tag = '%s'\n", result ? result : "<none>");
+ if (result) {
+ error = 1;
+ ast_log(LOG_ERROR, "Wrong to tag in packet one, parse error.");
+ }
+ result = gettag(req, "From", buf, sizeof(buf));
+ if (option_debug > 3)
+ ast_log(LOG_DEBUG, "Test-tags: From-tag = '%s'\n", result ? result : "<none>");
+ if (!result || strcmp(result, "as2b0e6ece")) {
+ error = 1;
+ ast_log(LOG_ERROR, "Wrong From tag in packet one, parse error. Tag = %s\n", result ? result : "<none>");
+ }
+ free(req);
+
+ /* More tests of other packets */
+ /* We need packets with bad syntax and weird syntaxes, examples */
+ /* And packets with UTF8 strings in strange places */
+
+ return error;
+}
+#endif
+
+AST_DEFINE_CODE_TEST(test_tags, "tags", test_tags_func);
+
/*! \brief sip_do_reload: Reload module */
static int sip_do_reload(void)
{
@@ -13108,6 +13218,9 @@
ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM, manager_sip_show_peer,
"Show SIP peer (text format)", mandescr_show_peer);
+ /* Register code tests */
+ ast_register_codetest(&test_tags);
+
sip_poke_all_peers();
sip_send_all_registers();
@@ -13124,21 +13237,29 @@
/* First, take us out of the channel type list */
ast_channel_unregister(&sip_tech);
+ /* Unregister functions */
ast_custom_function_unregister(&sipchaninfo_function);
ast_custom_function_unregister(&sippeer_function);
ast_custom_function_unregister(&sip_header_function);
ast_custom_function_unregister(&checksipdomain_function);
+ /* Unregister applications */
ast_unregister_application(app_dtmfmode);
ast_unregister_application(app_sipaddheader);
ast_unregister_application(app_sipgetheader);
+ /* Unregister CLI commands */
ast_cli_unregister_multiple(my_clis, sizeof(my_clis) / sizeof(my_clis[0]));
+ /* Unregister rtp proto */
ast_rtp_proto_unregister(&sip_rtp);
+ /* Unregister manager actions */
ast_manager_unregister("SIPpeers");
ast_manager_unregister("SIPshowpeer");
+
+ /* Unregister Code Tests */
+ ast_unregister_codetest(&test_tags);
if (!ast_mutex_lock(&iflock)) {
/* Hangup all interfaces if they have an owner */
Added: team/russell/codetest/codetest.c
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/codetest.c?rev=7622&view=auto
==============================================================================
--- team/russell/codetest/codetest.c (added)
+++ team/russell/codetest/codetest.c Sat Dec 24 21:37:25 2005
@@ -1,0 +1,372 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2005, Russell Bryant
+ *
+ * Russell Bryant <russell 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.
+ */
+
+/*! \file
+ *
+ * \brief Code Testing Framework
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1 $")
+
+#include "asterisk/channel.h"
+#include "asterisk/logger.h"
+#include "asterisk/cli.h"
+#include "asterisk/codetest.h"
+
+struct testfile {
+ const char *filename;
+ AST_LIST_HEAD_NOLOCK(codetest_list, ast_codetest) codetests;
+ AST_LIST_ENTRY(testfile) list;
+};
+
+static AST_LIST_HEAD_STATIC(testfile_list, testfile);
+
+static struct testfile *add_testfile(struct ast_codetest *test)
+{
+ struct testfile *tf;
+
+ tf = calloc(1, sizeof(struct testfile));
+ if (!tf) {
+ ast_log(LOG_ERROR, "Memory Allocation Error!\n");
+ return NULL;
+ }
+
+ tf->filename = test->filename;
+
+ AST_LIST_INSERT_HEAD(&testfile_list, tf, list);
+
+ return tf;
+}
+
+int ast_register_codetest(struct ast_codetest *test)
+{
+ struct testfile *cur;
+
+ AST_LIST_LOCK(&testfile_list);
+
+ AST_LIST_TRAVERSE(&testfile_list, cur, list) {
+ if (!strcmp(cur->filename, test->filename))
+ break;
+ }
+
+ if (!cur)
+ cur = add_testfile(test);
+ if (!cur) {
+ AST_LIST_UNLOCK(&testfile_list);
+ return -1;
+ }
+
+ AST_LIST_INSERT_HEAD(&cur->codetests, test, list);
+
+ AST_LIST_UNLOCK(&testfile_list);
+
+ return 0;
+}
+
+int ast_unregister_codetest(struct ast_codetest *test)
+{
+ struct testfile *cur;
+
+ AST_LIST_LOCK(&testfile_list);
+
+ AST_LIST_TRAVERSE(&testfile_list, cur, list) {
+ if (!strcmp(cur->filename, test->filename))
+ break;
+ }
+ if (!cur) {
+ ast_log(LOG_WARNING, "File '%s' not found in list of files with registered tests!\n", test->filename);
+ AST_LIST_UNLOCK(&testfile_list);
+ return -1;
+ }
+
+ AST_LIST_REMOVE(&cur->codetests, test, list);
+
+ if (!cur->codetests.first) {
+ AST_LIST_REMOVE(&testfile_list, cur, list);
+ free(cur);
+ }
+
+ AST_LIST_UNLOCK(&testfile_list);
+
+ return 0;
+}
+
+static int count_tests(struct testfile *tf)
+{
+ struct ast_codetest *cur;
+ int count = 0;
+
+ AST_LIST_TRAVERSE(&tf->codetests, cur, list)
+ count++;
+
+ return count;
+}
+
+static int handle_cli_show_files(int fd, int argc, char *argv[])
+{
+ struct testfile *cur;
+ int count;
+
+ ast_cli(fd, "Files with Registered Code Tests\n");
+ ast_cli(fd, "--------------------------------\n");
+
+ AST_LIST_LOCK(&testfile_list);
+
+ AST_LIST_TRAVERSE(&testfile_list, cur, list) {
+ count = count_tests(cur);
+ ast_cli(fd, "Filename: '%s' (%d %s)\n", cur->filename, count, count > 1 ? "tests" : "test");
+ }
+
+ AST_LIST_UNLOCK(&testfile_list);
+
+ return RESULT_SUCCESS;
+}
+
+static struct ast_cli_entry cli_show_files = {
+ .cmda = { "codetest", "show", "files", NULL },
+ .handler = handle_cli_show_files,
+ .summary = "Show files with registered code tests",
+ .usage =
+ "Usage: codetest show files\n"
+ " This command will list all files that have registered code tests.\n"
+};
+
+static int handle_cli_show_file(int fd, int argc, char *argv[])
+{
+ struct testfile *cur;
+ struct ast_codetest *test;
+ int count = 0;
+
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+
+ AST_LIST_LOCK(&testfile_list);
+
+ AST_LIST_TRAVERSE(&testfile_list, cur, list) {
+ if (!strcmp(cur->filename, argv[3]))
+ break;
+ }
+
+ if (!cur) {
+ ast_cli(fd, "File '%s' not found in list of files with registered code tests!\n", argv[3]);
+ AST_LIST_UNLOCK(&testfile_list);
+ return RESULT_SHOWUSAGE;
+ }
+
+ ast_cli(fd, "Registered Code Tests for File '%s'\n", cur->filename);
+ ast_cli(fd, "---------------------------------------------\n");
+
+ AST_LIST_TRAVERSE(&cur->codetests, test, list) {
+ count++;
+ ast_cli(fd, "Test Name: '%s'\n", test->testname);
+ }
+
+ ast_cli(fd, "\n(Total Tests Registered: %d)\n", count);
+
+ AST_LIST_UNLOCK(&testfile_list);
+
+ return RESULT_SUCCESS;
+}
+
+static char *complete_testfiles(char *line, char *word, int pos, int state)
+{
+ struct testfile *cur;
+ int match = 0;
+ int wordlen;
+ char *file;
+
+ wordlen = strlen(word);
+
+ AST_LIST_LOCK(&testfile_list);
+
+ AST_LIST_TRAVERSE(&testfile_list, cur, list) {
+ if (!strncasecmp(word, cur->filename, wordlen)) {
+ match++;
+ if (match > state) {
+ file = strdup(cur->filename);
+ AST_LIST_UNLOCK(&testfile_list);
+ return file;
+ }
+ }
+ }
+
+ AST_LIST_UNLOCK(&testfile_list);
+
+ return NULL;
+
+}
+
+static char *complete_cli_show_file(char *line, char *word, int pos, int state)
+{
+ if (pos != 3)
+ return NULL;
+
+ return complete_testfiles(line, word, pos, state);
+}
+
+static struct ast_cli_entry cli_show_file = {
+ .cmda = { "codetest", "show", "file", NULL },
+ .handler = handle_cli_show_file,
+ .generator = complete_cli_show_file,
+ .summary = "Show registered code tests for a given file.",
+ .usage =
+ "Usage: codetest show file <file>\n"
+ " This command will list all registered code tests for a file.\n"
+};
+
+static void check_test_result(int fd, struct ast_codetest *test, int res)
+{
+ if (res)
+ ast_cli(fd, "Test '%s' *** FAILED *** for File '%s' !!!\n", test->testname, test->filename);
+ else
+ ast_cli(fd, "Test '%s' PASSED for File '%s' !!!\n", test->testname, test->filename);
+}
+
+static int handle_cli_run(int fd, int argc, char *argv[])
+{
+ struct testfile *tf;
+ struct ast_codetest *test;
+ char *testname = NULL;
+ int res = 0;
+ int test_argc = 0;
+ char **test_argv = NULL;
+
+ if (argc > 3) {
+ testname = argv[3];
+ if (argc > 4) {
+ test_argc = argc - 4;
+ test_argv = argv + 4;
+ }
+ }
+
+ AST_LIST_LOCK(&testfile_list);
+
+ AST_LIST_TRAVERSE(&testfile_list, tf, list) {
+ if (!strcmp(tf->filename, argv[2]))
+ break;
+ }
+ if (!tf) {
+ ast_cli(fd, "File '%s' not found in list of files with code tests.\n", argv[2]);
+ AST_LIST_UNLOCK(&testfile_list);
+ return RESULT_SHOWUSAGE;
+ }
+
+ AST_LIST_TRAVERSE(&tf->codetests, test, list) {
+ ast_cli(fd, "Executing test '%s' for file '%s' ...\n", test->testname, test->filename);
+ if (!ast_strlen_zero(testname) && !strcmp(test->testname, testname)) {
+ res = test->codetest(fd, test_argc, test_argv);
+ check_test_result(fd, test, res);
+ break;
+ } else {
+ res = test->codetest(fd, test_argc, test_argv);
+ check_test_result(fd, test, res);
+ }
+ }
+
+ AST_LIST_UNLOCK(&testfile_list);
+
+ return RESULT_SUCCESS;
+}
+
+static char *complete_tests(char *line, char *word, int pos, int state)
+{
+ char *file;
+ struct ast_codetest *test;
+ struct testfile *tf;
+ int match = 0;
+ int wordlen;
+
+ file = ast_strdupa(line);
+ if (!file) {
+ ast_log(LOG_ERROR, "Memory Allocation Error!\n");
+ return NULL;
+ }
+
+ wordlen = strlen(word);
+
+ strsep(&file, " ");
+ strsep(&file, " ");
+ file = strsep(&file, " ");
+
+ AST_LIST_LOCK(&testfile_list);
+
+ AST_LIST_TRAVERSE(&testfile_list, tf, list) {
+ if (!strcmp(file, tf->filename))
+ break;
+ }
+ if (!tf) {
+ AST_LIST_UNLOCK(&testfile_list);
+ return NULL;
+ }
+
+ AST_LIST_TRAVERSE(&tf->codetests, test, list) {
+ if (!strncasecmp(word, test->filename, wordlen)) {
+ match++;
+ if (match > state) {
+ file = strdup(test->filename);
+ AST_LIST_UNLOCK(&testfile_list);
+ return file;
+ }
+ }
+ }
+
+ AST_LIST_UNLOCK(&testfile_list);
+
+ return NULL;
+}
+
+static char *complete_cli_run(char *line, char *word, int pos, int state)
+{
+ if (pos == 2)
+ return complete_testfiles(line, word, pos, state);
+ else if (pos == 3)
+ /* XXX Why isn't this being executed ?! XXX */
+ return complete_tests(line, word, pos, state);
+
+ return NULL;
+}
+
+static struct ast_cli_entry cli_run = {
+ .cmda = { "codetest", "run", NULL },
+ .handler = handle_cli_run,
+ .generator = complete_cli_run,
+ .summary = "Run code test(s) for a file.",
+ .usage =
+ "Usage: codetest run <file> [test]\n"
+ " This command will run registered code tests for a file.\n"
+ " If a test is specified, only that test will be executed.\n"
+ " Otherwise, all available tests will be executed.\n"
+};
+
+int codetest_init(void)
+{
+ int res;
+
+ res = ast_cli_register(&cli_show_files);
+ res |= ast_cli_register(&cli_show_file);
+ res |= ast_cli_register(&cli_run);
+
+ return res;
+}
Modified: team/russell/codetest/include/asterisk.h
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/include/asterisk.h?rev=7622&r1=7621&r2=7622&view=diff
==============================================================================
--- team/russell/codetest/include/asterisk.h (original)
+++ team/russell/codetest/include/asterisk.h Sat Dec 24 21:37:25 2005
@@ -64,6 +64,10 @@
int dnsmgr_init(void);
void dnsmgr_start_refresh(void);
void dnsmgr_reload(void);
+#ifdef ENABLE_CODE_TEST
+/* Provided by codetest.c */
+int codetest_init(void);
+#endif
/*!
* \brief Register the version of a source code file with the core.
Added: team/russell/codetest/include/asterisk/codetest.h
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/include/asterisk/codetest.h?rev=7622&view=auto
==============================================================================
--- team/russell/codetest/include/asterisk/codetest.h (added)
+++ team/russell/codetest/include/asterisk/codetest.h Sat Dec 24 21:37:25 2005
@@ -1,0 +1,51 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ *
+ * Russell Bryant <russell 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 __ASTERISK_CODETEST_H
+#define __ASTERISK_CODETEST_H
+
+#ifdef ENABLE_CODE_TEST
+
+#include "asterisk/linkedlists.h"
+
+struct ast_codetest {
+ /*! The file that registered this test */
+ const char *filename;
+ /*! The name of the test */
+ const char *testname;
+ /*! The codetest callback function */
+ int (*codetest)(int fd, int argc, char *argv[]);
+ /*! For linking, used only in codetest.c */
+ AST_LIST_ENTRY(ast_codetest) list;
+};
+
+#define AST_DEFINE_CODE_TEST(name, tname, func) \
+ static struct ast_codetest name = { __FILE__, tname, func }
+
+int ast_register_codetest(struct ast_codetest *test);
+int ast_unregister_codetest(struct ast_codetest *test);
+
+#else
+
+#define ast_register_codetest(f)
+#define ast_unregister_codetest(f)
+#define AST_DEFINE_CODE_TEST(name, testname, func)
+
+#endif
+
+#endif /* __ASTERISK_CODETEST_H */
More information about the asterisk-commits
mailing list