[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