diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | include/osmocom/core/logging.h | 5 | ||||
| -rw-r--r-- | include/osmocom/core/loggingrb.h | 40 | ||||
| -rw-r--r-- | include/osmocom/core/strrb.h | 58 | ||||
| -rw-r--r-- | src/Makefile.am | 4 | ||||
| -rw-r--r-- | src/loggingrb.c | 98 | ||||
| -rw-r--r-- | src/strrb.c | 170 | ||||
| -rw-r--r-- | src/vty/logging_vty.c | 85 | ||||
| -rw-r--r-- | tests/Makefile.am | 13 | ||||
| -rw-r--r-- | tests/loggingrb/logging_test.err | 3 | ||||
| -rw-r--r-- | tests/loggingrb/logging_test.ok | 0 | ||||
| -rw-r--r-- | tests/loggingrb/loggingrb_test.c | 83 | ||||
| -rw-r--r-- | tests/strrb/strrb_test.c | 225 | ||||
| -rw-r--r-- | tests/strrb/strrb_test.ok | 1 | ||||
| -rw-r--r-- | tests/testsuite.at | 13 | 
15 files changed, 792 insertions, 8 deletions
| @@ -69,6 +69,8 @@ tests/gb/bssgp_fc_test  tests/gsm0408/gsm0408_test  tests/logging/logging_test  tests/fr/fr_test +tests/loggingrb/loggingrb_test +tests/ringbuf/ringbuf_test  utils/osmo-arfcn  utils/osmo-auc-gen diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index 54262b7f..fa3365ad 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -114,6 +114,7 @@ enum log_target_type {  	LOG_TGT_TYPE_SYSLOG,	/*!< \brief syslog based logging */  	LOG_TGT_TYPE_FILE,	/*!< \brief text file logging */  	LOG_TGT_TYPE_STDERR,	/*!< \brief stderr logging */ +	LOG_TGT_TYPE_STRRB,	/*!< \brief osmo_strrb-backed logging */  };  /*! \brief structure representing a logging target */ @@ -154,6 +155,10 @@ struct log_target {  		struct {  			void *vty;  		} tgt_vty; + +		struct { +			void *rb; +		} tgt_rb;  	};  	/*! \brief call-back function to be called when the logging framework diff --git a/include/osmocom/core/loggingrb.h b/include/osmocom/core/loggingrb.h new file mode 100644 index 00000000..a6f377b1 --- /dev/null +++ b/include/osmocom/core/loggingrb.h @@ -0,0 +1,40 @@ +#ifndef _LOGGINGRB_H +#define _LOGGINGRB_H + +/* (C) 2012-2013 by Katerina Barone-Adesi <kat.obsc@gmail.com> + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + + +/*! \defgroup loggingrb Osmocom ringbuffer-backed logging + *  @{ + */ + +/*! \file loggingrb.h + */ + +struct log_info; + +size_t log_target_rb_used_size(struct log_target const *target); +size_t log_target_rb_avail_size(struct log_target const *target); +const char *log_target_rb_get(struct log_target const *target, size_t logindex); +struct log_target *log_target_create_rb(size_t size); + +/*! @} */ + +#endif /* _LOGGINGRB_H  */ diff --git a/include/osmocom/core/strrb.h b/include/osmocom/core/strrb.h new file mode 100644 index 00000000..cfc56dc0 --- /dev/null +++ b/include/osmocom/core/strrb.h @@ -0,0 +1,58 @@ +#ifndef _STRRB_H +#define _STRRB_H + +/* (C) 2012-2013 by Katerina Barone-Adesi <kat.obsc@gmail.com> + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/*! \defgroup osmo_strrb Osmocom ringbuffers for log strings + *  @{ + */ + +/*! \file strrb.h + *  \brief Osmocom string ringbuffer handling routines + */ + +#include <unistd.h> +#include <stdbool.h> +#include <stdint.h> + +#include <osmocom/core/talloc.h> + +/*! \brief A structure representing an osmocom string ringbuffer */ + +#define RB_MAX_MESSAGE_SIZE 240 +struct osmo_strrb { +	uint16_t start;		/*!< \brief index of the first slot */ +	uint16_t end;		/*!< \brief index of the last slot */ +	uint16_t size;		/*!< \brief max number of messages to store */ +	char **buffer;		/*!< \brief storage for messages */ +}; + +struct osmo_strrb *osmo_strrb_create(TALLOC_CTX * ctx, size_t rb_size); +bool osmo_strrb_is_empty(const struct osmo_strrb *rb); +const char *osmo_strrb_get_nth(const struct osmo_strrb *rb, +			       unsigned int string_index); +bool _osmo_strrb_is_bufindex_valid(const struct osmo_strrb *rb, +				   unsigned int offset); +size_t osmo_strrb_elements(const struct osmo_strrb *rb); +int osmo_strrb_add(struct osmo_strrb *rb, const char *data); + +/*! @} */ + +#endif /* _STRRB_H */ diff --git a/src/Makefile.am b/src/Makefile.am index b425ea19..081be966 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,8 +11,8 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \  			 write_queue.c utils.c socket.c \  			 logging.c logging_syslog.c rate_ctr.c \  			 gsmtap_util.c crc16.c panic.c backtrace.c \ -			 conv.c application.c rbtree.c \ -			 crc8gen.c crc16gen.c crc32gen.c crc64gen.c +			 conv.c application.c rbtree.c strrb.c \ +			 loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c  BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c diff --git a/src/loggingrb.c b/src/loggingrb.c new file mode 100644 index 00000000..8faa5b11 --- /dev/null +++ b/src/loggingrb.c @@ -0,0 +1,98 @@ +/* Ringbuffer-backed logging support code */ + +/* (C) 2012-2013 by Katerina Barone-Adesi + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/*! \addtogroup logging + *  @{ + */ + +/*! \file loggingrb.c */ + +#include <osmocom/core/strrb.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/loggingrb.h> + +static void _rb_output(struct log_target *target, +			  unsigned int level, const char *log) +{ +	osmo_strrb_add(target->tgt_rb.rb, log); +} + +/*! \brief Return the number of log strings in the osmo_strrb-backed target. + *  \param[in] target The target to search. + * + *  \return The number of log strings in the osmo_strrb-backed target. + */ +size_t log_target_rb_used_size(struct log_target const *target) +{ +	return osmo_strrb_elements(target->tgt_rb.rb); +} + +/*! \brief Return the capacity of the osmo_strrb-backed target. + *  \param[in] target The target to search. + * + * Note that this is the capacity (aka max number of messages). + * It is not the number of unused message slots. + *  \return The number of log strings in the osmo_strrb-backed target. + */ +size_t log_target_rb_avail_size(struct log_target const *target) +{ +	struct osmo_strrb *rb = target->tgt_rb.rb; +	return rb->size - 1; +} + +/*! \brief Return the nth log entry in a target. + *  \param[in] target The target to search. + *  \param[in] logindex The index of the log entry/error message. + * + *  \return A pointer to the nth message, or NULL if logindex is invalid. + */ +const char *log_target_rb_get(struct log_target const *target, size_t logindex) +{ +	return osmo_strrb_get_nth(target->tgt_rb.rb, logindex); +} + +/*! \brief Create a new logging target for ringbuffer-backed logging. + *  \param[in] size The size of the internal backing osmo_strrb (messages). + *  \returns A log target in case of success, NULL in case of error. + */ +struct log_target *log_target_create_rb(size_t size) +{ +	struct log_target *target; +	struct osmo_strrb *rb; + +	target = log_target_create(); +	if (!target) +		return NULL; + +	rb = osmo_strrb_create(target, size + 1); +	if (!rb) { +		log_target_destroy(target); +		return NULL; +	} + +	target->tgt_rb.rb = rb; +	target->type = LOG_TGT_TYPE_STRRB; +	target->output = _rb_output; + +	return target; +} + +/* @} */ diff --git a/src/strrb.c b/src/strrb.c new file mode 100644 index 00000000..626ade69 --- /dev/null +++ b/src/strrb.c @@ -0,0 +1,170 @@ +/* Ringbuffer implementation, tailored for logging. + * This is a lossy ringbuffer. It keeps up to N of the newest messages, + * overwriting the oldest as newer ones come in. + * + * (C) 2012-2013, Katerina Barone-Adesi <kat.obsc@gmail.com> + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/*! \file strrb.c + *  \brief Lossy string ringbuffer for logging; keeps newest messages. + */ + +#include <stdio.h> +#include <string.h> +#include <strings.h> + +#include <osmocom/core/strrb.h> + +/* Ringbuffer assumptions, invarients, and notes: + * - start is the index of the first used index slot in the ring buffer. + * - end is the index of the next index slot in the ring buffer. + * - start == end => buffer is empty + * - Consequence: the buffer can hold at most size - 1 messages + * (if this were not the case, full and empty buffers would be indistinguishable + * given the conventions in this implementation). + * - Whenever the ringbuffer is full, start is advanced. The second oldest + * message becomes unreachable by valid indexes (end is not a valid index) + * and the oldest message is overwritten (if there was a message there, which + * is the case unless this is the first time the ringbuffer becomes full). +*/ + +/*! \brief Create an empty, initialized osmo_strrb. + *  \param[in] ctx The talloc memory context which should own this. + *  \param[in] rb_size The number of messages the osmo_strrb can hold. + *  \returns A struct osmo_strrb* on success, NULL in case of error. + * + * This function creates and initializes a ringbuffer. + */ + +struct osmo_strrb *osmo_strrb_create(TALLOC_CTX * ctx, size_t rb_size) +{ +	struct osmo_strrb *rb = NULL; +	unsigned int i; + +	rb = talloc_zero(ctx, struct osmo_strrb); +	if (!rb) +		goto alloc_error; + +	/* start and end are zero already, which is correct */ +	rb->size = rb_size; + +	rb->buffer = talloc_array(rb, char *, rb->size); +	if (!rb->buffer) +		goto alloc_error; +	for (i = 0; i < rb->size; i++) { +		rb->buffer[i] = +		    talloc_zero_size(rb->buffer, RB_MAX_MESSAGE_SIZE); +		if (!rb->buffer[i]) +			goto alloc_error; +	} + +	return rb; + +alloc_error:			/* talloc_free(NULL) is safe */ +	talloc_free(rb); +	return NULL; +} + +/*! \brief Check if an osmo_strrb is empty. + *  \param[in] rb The osmo_strrb to check. + *  \returns True if the osmo_strrb is empty, false otherwise. + */ +bool osmo_strrb_is_empty(const struct osmo_strrb *rb) +{ +	return rb->end == rb->start; +} + +/*! \brief Return a pointer to the Nth string in the osmo_strrb. + * \param[in] rb The osmo_strrb to search. + * \param[in] string_index The index sought (N), zero-indexed. + * + * Return a pointer to the Nth string in the osmo_strrb. + * Return NULL if there is no Nth string. + * Note that N is zero-indexed. + * \returns A pointer to the target string on success, NULL in case of error. + */ +const char *osmo_strrb_get_nth(const struct osmo_strrb *rb, +			       unsigned int string_index) +{ +	unsigned int offset = string_index + rb->start; + +	if ((offset >= rb->size) && (rb->start > rb->end)) +		offset -= rb->size; +	if (_osmo_strrb_is_bufindex_valid(rb, offset)) +		return rb->buffer[offset]; + +	return NULL; +} + +bool _osmo_strrb_is_bufindex_valid(const struct osmo_strrb *rb, +				   unsigned int bufi) +{ +	if (osmo_strrb_is_empty(rb)) +		return 0; +	if ((bufi >= rb->size) || (bufi < 0)) +		return 0; +	if (rb->start < rb->end) +		return (bufi >= rb->start) && (bufi < rb->end); +	return (bufi < rb->end) || (bufi >= rb->start); +} + +/*! \brief Count the number of log messages in an osmo_strrb. + *  \param[in] rb The osmo_strrb to count the elements of. + * + *  \returns The number of log messages in the osmo_strrb. + */ +size_t osmo_strrb_elements(const struct osmo_strrb *rb) +{ +	if (rb->end < rb->start) +		return rb->end + (rb->size - rb->start); + +	return rb->end - rb->start; +} + +/*! \brief Add a string to the osmo_strrb. + * \param[in] rb The osmo_strrb to add to. + * \param[in] data The string to add. + * + * Add a message to the osmo_strrb. + * Older messages will be overwritten as necessary. + * \returns 0 normally, 1 as a warning (ie, if data was truncated). + */ +int osmo_strrb_add(struct osmo_strrb *rb, const char *data) +{ +	size_t len = strlen(data); +	int ret = 0; + +	if (len >= RB_MAX_MESSAGE_SIZE) { +		len = RB_MAX_MESSAGE_SIZE - 1; +		ret = 1; +	} + +	memcpy(rb->buffer[rb->end], data, len); +	rb->buffer[rb->end][len] = '\0'; + +	rb->end += 1; +	rb->end %= rb->size; + +	/* The buffer is full; oldest message is forgotten - see notes above */ +	if (rb->end == rb->start) { +		rb->start += 1; +		rb->start %= rb->size; +	} +	return ret; +} diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index d473f129..ace346a2 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -27,8 +27,8 @@  #include <osmocom/core/talloc.h>  #include <osmocom/core/logging.h>  #include <osmocom/core/utils.h> - -//#include <openbsc/vty.h> +#include <osmocom/core/strrb.h> +#include <osmocom/core/loggingrb.h>  #include <osmocom/vty/command.h>  #include <osmocom/vty/buffer.h> @@ -252,8 +252,8 @@ static void vty_print_logtarget(struct vty *vty, const struct log_info *info,  #define SHOW_LOG_STR "Show current logging configuration\n"  DEFUN(show_logging_vty, -      show_logging_vty_cmd, -      "show logging vty", +	show_logging_vty_cmd, +	"show logging vty",  	SHOW_STR SHOW_LOG_STR  	"Show current logging configuration for this vty\n")  { @@ -267,6 +267,33 @@ DEFUN(show_logging_vty,  	return CMD_SUCCESS;  } +DEFUN(show_alarms, +	show_alarms_cmd, +	"show alarms", +	SHOW_STR SHOW_LOG_STR +	"Show the contents of the logging ringbuffer\n") +{ +	int i, num_alarms; +	struct osmo_strrb *rb; +	struct log_target *tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL); +	if (!tgt) { +		vty_out(vty, "%% No alarms, run 'log alarms <2-32700>'%s", +			VTY_NEWLINE); +		return CMD_WARNING; +	} + +	rb = tgt->tgt_rb.rb; +	num_alarms = osmo_strrb_elements(rb); + +	vty_out(vty, "%% Showing %i alarms%s", num_alarms, VTY_NEWLINE); + +	for (i = 0; i < num_alarms; i++) +		vty_out(vty, "%% %s%s", osmo_strrb_get_nth(rb, i), +			VTY_NEWLINE); + +	return CMD_SUCCESS; +} +  gDEFUN(cfg_description, cfg_description_cmd,  	"description .TEXT",  	"Save human-readable decription of the object\n" @@ -510,6 +537,49 @@ DEFUN(cfg_no_log_file, cfg_no_log_file_cmd,  	return CMD_SUCCESS;  } +DEFUN(cfg_log_alarms, cfg_log_alarms_cmd, +	"log alarms <2-32700>", +	LOG_STR "Logging alarms to osmo_strrb\n" +	"Maximum number of messages to log\n") +{ +	struct log_target *tgt; +	unsigned int rbsize = atoi(argv[0]); + +	tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL); +	if (tgt) +		log_target_destroy(tgt); + +	tgt = log_target_create_rb(rbsize); +	if (!tgt) { +		vty_out(vty, "%% Unable to create osmo_strrb (size %u)%s", +			rbsize, VTY_NEWLINE); +		return CMD_WARNING; +	} +	log_add_target(tgt); + +	vty->index = tgt; +	vty->node = CFG_LOG_NODE; + +	return CMD_SUCCESS; +} + +DEFUN(cfg_no_log_alarms, cfg_no_log_alarms_cmd, +	"no log alarms", +	NO_STR LOG_STR "Logging alarms to osmo_strrb\n") +{ +	struct log_target *tgt; + +	tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL); +	if (!tgt) { +		vty_out(vty, "%% No osmo_strrb target found%s", VTY_NEWLINE); +		return CMD_WARNING; +	} + +	log_target_destroy(tgt); + +	return CMD_SUCCESS; +} +  static int config_write_log_single(struct vty *vty, struct log_target *tgt)  {  	int i; @@ -533,6 +603,10 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt)  	case LOG_TGT_TYPE_FILE:  		vty_out(vty, "log file %s%s", tgt->tgt_file.fname, VTY_NEWLINE);  		break; +	case LOG_TGT_TYPE_STRRB: +		vty_out(vty, "log alarms %zu%s", +			log_target_rb_avail_size(tgt), VTY_NEWLINE); +		break;  	}  	vty_out(vty, "  logging filter all %u%s", @@ -590,6 +664,7 @@ void logging_vty_add_cmds(const struct log_info *cat)  	logging_level_cmd.doc = log_vty_command_description(cat);  	install_element_ve(&logging_level_cmd);  	install_element_ve(&show_logging_vty_cmd); +	install_element_ve(&show_alarms_cmd);  	install_node(&cfg_log_node, config_write_log);  	install_default(CFG_LOG_NODE); @@ -603,6 +678,8 @@ void logging_vty_add_cmds(const struct log_info *cat)  	install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd);  	install_element(CONFIG_NODE, &cfg_log_file_cmd);  	install_element(CONFIG_NODE, &cfg_no_log_file_cmd); +	install_element(CONFIG_NODE, &cfg_log_alarms_cmd); +	install_element(CONFIG_NODE, &cfg_no_log_alarms_cmd);  #ifdef HAVE_SYSLOG_H  	install_element(CONFIG_NODE, &cfg_log_syslog_cmd);  	install_element(CONFIG_NODE, &cfg_log_syslog_local_cmd); diff --git a/tests/Makefile.am b/tests/Makefile.am index be0b5f4c..bc9b7de6 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,7 +4,9 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test		\                   smscb/smscb_test bits/bitrev_test a5/a5_test		\                   conv/conv_test auth/milenage_test lapd/lapd_test	\                   gsm0808/gsm0808_test gsm0408/gsm0408_test		\ -		 gb/bssgp_fc_test logging/logging_test fr/fr_test +		 gb/bssgp_fc_test logging/logging_test fr/fr_test	\ +		 loggingrb/loggingrb_test strrb/strrb_test +  if ENABLE_MSGFILE  check_PROGRAMS += msgfile/msgfile_test  endif @@ -54,6 +56,12 @@ logging_logging_test_LDADD = $(top_builddir)/src/libosmocore.la  fr_fr_test_SOURCES = fr/fr_test.c  fr_fr_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gb/libosmogb.la +loggingrb_loggingrb_test_SOURCES = logging/logging_test.c +loggingrb_loggingrb_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/vty/libosmovty.la + +strrb_strrb_test_SOURCES = strrb/strrb_test.c +strrb_strrb_test_LDADD = $(top_builddir)/src/libosmocore.la +  # The `:;' works around a Bash 3.2 bug when the output is not writeable.  $(srcdir)/package.m4: $(top_srcdir)/configure.ac @@ -82,7 +90,8 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE)		\               gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh			\               msgfile/msgfile_test.ok msgfile/msgconfig.cfg		\               logging/logging_test.ok logging/logging_test.err		\ -             fr/fr_test.ok +             fr/fr_test.ok loggingrb/logging_test.ok			\ +             loggingrb/logging_test.err	strrb/strrb_test.ok  DISTCLEANFILES = atconfig diff --git a/tests/loggingrb/logging_test.err b/tests/loggingrb/logging_test.err new file mode 100644 index 00000000..b59d2e83 --- /dev/null +++ b/tests/loggingrb/logging_test.err @@ -0,0 +1,3 @@ +[1;31mYou should see this +[0;m[1;32mYou should see this +[0;m
\ No newline at end of file diff --git a/tests/loggingrb/logging_test.ok b/tests/loggingrb/logging_test.ok new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/loggingrb/logging_test.ok diff --git a/tests/loggingrb/loggingrb_test.c b/tests/loggingrb/loggingrb_test.c new file mode 100644 index 00000000..1ab5212d --- /dev/null +++ b/tests/loggingrb/loggingrb_test.c @@ -0,0 +1,83 @@ +/* simple test for the debug interface */ +/* + * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org> + * (C) 2012-2013 by Katerina Barone-Adesi <kat.obsc@gmail.com> + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + * + */ +#include <assert.h> + +#include <osmocom/core/logging.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/ringb.h> +#include <osmocom/vty/logging_rbvty.h> + +enum { +	DRLL, +	DCC, +	DMM, +}; + +static const struct log_info_cat default_categories[] = { +	[DRLL] = { +		  .name = "DRLL", +		  .description = "A-bis Radio Link Layer (RLL)", +		  .color = "\033[1;31m", +		  .enabled = 1, .loglevel = LOGL_NOTICE, +		  }, +	[DCC] = { +		 .name = "DCC", +		 .description = "Layer3 Call Control (CC)", +		 .color = "\033[1;32m", +		 .enabled = 1, .loglevel = LOGL_NOTICE, +		 }, +	[DMM] = { +		 .name = NULL, +		 .description = "Layer3 Mobility Management (MM)", +		 .color = "\033[1;33m", +		 .enabled = 1, .loglevel = LOGL_NOTICE, +		 }, +}; + +const struct log_info log_info = { +	.cat = default_categories, +	.num_cat = ARRAY_SIZE(default_categories), +}; + +int main(int argc, char **argv) +{ +	struct log_target *ringbuf_target; + +	log_init(&log_info, NULL); +	ringbuf_target = log_target_create_rbvty(NULL, 0x1000); +	log_add_target(ringbuf_target); +	log_set_all_filter(ringbuf_target, 1); +	log_set_print_filename(ringbuf_target, 0); + +	log_parse_category_mask(ringbuf_target, "DRLL:DCC"); +	log_parse_category_mask(ringbuf_target, "DRLL"); +	DEBUGP(DCC, "You should not see this\n"); + +	log_parse_category_mask(ringbuf_target, "DRLL:DCC"); +	DEBUGP(DRLL, "You should see this\n"); +	DEBUGP(DCC, "You should see this\n"); +	DEBUGP(DMM, "You should not see this\n"); +	fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 0)); +	fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 1)); +	assert(!ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 2)); + +	return 0; +} diff --git a/tests/strrb/strrb_test.c b/tests/strrb/strrb_test.c new file mode 100644 index 00000000..b7c5e27f --- /dev/null +++ b/tests/strrb/strrb_test.c @@ -0,0 +1,225 @@ +/* (C) 2012-2013 by Katerina Barone-Adesi <kat.obsc@gmail.com> + * All Rights Reserved + * + * This program is iree software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <stdio.h> +#include <assert.h> +#include <string.h> + +#include <osmocom/core/strrb.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/logging.h> + +struct osmo_strrb *rb0, *rb1, *rb2, *rb3, *rb4, *rb5; + +#define STR0 "hello" +#define STR1 "a" +#define STR2 "world" +#define STR3 "sky" +#define STR4 "moon" + +#define TESTSIZE 2 + +void init_rbs(void) +{ +	rb0 = osmo_strrb_create(NULL, TESTSIZE); + +	rb1 = osmo_strrb_create(NULL, TESTSIZE); +	osmo_strrb_add(rb1, STR0); + +	rb2 = osmo_strrb_create(NULL, TESTSIZE); +	osmo_strrb_add(rb2, STR0); +	osmo_strrb_add(rb2, STR1); + +	rb3 = osmo_strrb_create(NULL, TESTSIZE); +	osmo_strrb_add(rb3, STR0); +	osmo_strrb_add(rb3, STR1); +	osmo_strrb_add(rb3, STR2); + +	rb4 = osmo_strrb_create(NULL, TESTSIZE); +	osmo_strrb_add(rb4, STR0); +	osmo_strrb_add(rb4, STR1); +	osmo_strrb_add(rb4, STR2); +	osmo_strrb_add(rb4, STR3); + +	rb5 = osmo_strrb_create(NULL, TESTSIZE); +	osmo_strrb_add(rb5, STR0); +	osmo_strrb_add(rb5, STR1); +	osmo_strrb_add(rb5, STR2); +	osmo_strrb_add(rb5, STR3); +	osmo_strrb_add(rb5, STR4); +} + +void free_rbs(void) +{ +	talloc_free(rb0); +	talloc_free(rb1); +	talloc_free(rb2); +	talloc_free(rb3); +	talloc_free(rb4); +	talloc_free(rb5); +} + +void test_offset_valid(void) +{ +	assert(_osmo_strrb_is_bufindex_valid(rb1, 0)); +	assert(!_osmo_strrb_is_bufindex_valid(rb1, 1)); +	assert(!_osmo_strrb_is_bufindex_valid(rb1, 2)); + +	assert(!_osmo_strrb_is_bufindex_valid(rb3, 0)); +	assert(_osmo_strrb_is_bufindex_valid(rb3, 1)); +	assert(_osmo_strrb_is_bufindex_valid(rb3, 2)); + +	assert(_osmo_strrb_is_bufindex_valid(rb4, 0)); +	assert(!_osmo_strrb_is_bufindex_valid(rb4, 1)); +	assert(_osmo_strrb_is_bufindex_valid(rb4, 2)); + +	assert(_osmo_strrb_is_bufindex_valid(rb5, 0)); +	assert(_osmo_strrb_is_bufindex_valid(rb5, 1)); +	assert(!_osmo_strrb_is_bufindex_valid(rb5, 2)); +} + +void test_elems(void) +{ +	assert(osmo_strrb_elements(rb0) == 0); +	assert(osmo_strrb_elements(rb1) == 1); +	assert(osmo_strrb_elements(rb2) == 2); +	assert(osmo_strrb_elements(rb3) == 2); +} + +void test_getn(void) +{ +	assert(!osmo_strrb_get_nth(rb0, 0)); +	assert(!strcmp(STR0, osmo_strrb_get_nth(rb2, 0))); +	assert(!strcmp(STR1, osmo_strrb_get_nth(rb2, 1))); +	assert(!strcmp(STR1, osmo_strrb_get_nth(rb3, 0))); +	assert(!strcmp(STR2, osmo_strrb_get_nth(rb3, 1))); +	assert(!osmo_strrb_get_nth(rb3, 2)); +} + +void test_getn_wrap(void) +{ +	assert(!strcmp(STR2, osmo_strrb_get_nth(rb4, 0))); +	assert(!strcmp(STR3, osmo_strrb_get_nth(rb4, 1))); + +	assert(!strcmp(STR3, osmo_strrb_get_nth(rb5, 0))); +	assert(!strcmp(STR4, osmo_strrb_get_nth(rb5, 1))); +} + +void test_add(void) +{ +	struct osmo_strrb *rb = osmo_strrb_create(NULL, 3); +	assert(rb->start == 0); +	assert(rb->end == 0); + +	osmo_strrb_add(rb, "a"); +	osmo_strrb_add(rb, "b"); +	osmo_strrb_add(rb, "c"); +	assert(rb->start == 0); +	assert(rb->end == 3); +	assert(osmo_strrb_elements(rb) == 3); + +	osmo_strrb_add(rb, "d"); +	assert(rb->start == 1); +	assert(rb->end == 0); +	assert(osmo_strrb_elements(rb) == 3); +	assert(!strcmp("b", osmo_strrb_get_nth(rb, 0))); +	assert(!strcmp("c", osmo_strrb_get_nth(rb, 1))); +	assert(!strcmp("d", osmo_strrb_get_nth(rb, 2))); + +	osmo_strrb_add(rb, "e"); +	assert(rb->start == 2); +	assert(rb->end == 1); +	assert(!strcmp("c", osmo_strrb_get_nth(rb, 0))); +	assert(!strcmp("d", osmo_strrb_get_nth(rb, 1))); +	assert(!strcmp("e", osmo_strrb_get_nth(rb, 2))); + +	osmo_strrb_add(rb, "f"); +	assert(rb->start == 3); +	assert(rb->end == 2); +	assert(!strcmp("d", osmo_strrb_get_nth(rb, 0))); +	assert(!strcmp("e", osmo_strrb_get_nth(rb, 1))); +	assert(!strcmp("f", osmo_strrb_get_nth(rb, 2))); + +	osmo_strrb_add(rb, "g"); +	assert(rb->start == 0); +	assert(rb->end == 3); +	assert(!strcmp("e", osmo_strrb_get_nth(rb, 0))); +	assert(!strcmp("f", osmo_strrb_get_nth(rb, 1))); +	assert(!strcmp("g", osmo_strrb_get_nth(rb, 2))); + +	osmo_strrb_add(rb, "h"); +	assert(rb->start == 1); +	assert(rb->end == 0); +	assert(!strcmp("f", osmo_strrb_get_nth(rb, 0))); +	assert(!strcmp("g", osmo_strrb_get_nth(rb, 1))); +	assert(!strcmp("h", osmo_strrb_get_nth(rb, 2))); + +	talloc_free(rb); +} + +void test_long_msg(void) +{ +	struct osmo_strrb *rb = osmo_strrb_create(NULL, 2); +	int test_size = RB_MAX_MESSAGE_SIZE + 7; +	char *tests1, *tests2; +	const char *rb_content; +	int i; + +	tests1 = malloc(test_size); +	tests2 = malloc(test_size); +	/* Be certain allocating memory worked before continuing */ +	assert(tests1); +	assert(tests2); + +	for (i = 0; i < RB_MAX_MESSAGE_SIZE; i += 2) { +		tests1[i] = 'a'; +		tests1[i + 1] = 'b'; +	} +	tests1[i] = '\0'; + +	osmo_strrb_add(rb, tests1); +	strcpy(tests2, tests1); + +	/* Verify that no stale data from test1 is lingering... */ +	bzero(tests1, test_size); +	free(tests1); + +	rb_content = osmo_strrb_get_nth(rb, 0); +	assert(!strncmp(tests2, rb_content, RB_MAX_MESSAGE_SIZE - 1)); +	assert(!rb_content[RB_MAX_MESSAGE_SIZE - 1]); +	assert(strlen(rb_content) == RB_MAX_MESSAGE_SIZE - 1); + +	free(tests2); +	talloc_free(rb); +} + +int main(int argc, char **argv) +{ +	init_rbs(); +	test_offset_valid(); +	test_elems(); +	test_getn(); +	test_getn_wrap(); +	test_add(); +	test_long_msg(); +	printf("All tests passed\n"); + +	free_rbs(); +	return 0; +} diff --git a/tests/strrb/strrb_test.ok b/tests/strrb/strrb_test.ok new file mode 100644 index 00000000..9ac5124e --- /dev/null +++ b/tests/strrb/strrb_test.ok @@ -0,0 +1 @@ +All tests passed diff --git a/tests/testsuite.at b/tests/testsuite.at index 5029b9e9..21fad1d6 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -99,3 +99,16 @@ cat $abs_srcdir/fr/fr_test.err > experr  AT_CHECK([$abs_top_builddir/tests/fr/fr_test], [], [expout], [experr])  AT_CLEANUP + +AT_SETUP([loggingrb]) +AT_KEYWORDS([loggingrb]) +cat $abs_srcdir/loggingrb/logging_test.ok > expout +cat $abs_srcdir/loggingrb/logging_test.err > experr +AT_CHECK([$abs_top_builddir/tests/loggingrb/loggingrb_test], [], [expout], [experr]) +AT_CLEANUP + +AT_SETUP([strrb]) +AT_KEYWORDS([strrb]) +cat $abs_srcdir/strrb/strrb_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/strrb/strrb_test], [], [expout], [ignore]) +AT_CLEANUP | 
