Commit d79e7059 authored by unknown's avatar unknown

negative lists in dbug (-#-d,info => everything but "info").

unit tests for dbug


dbug/Makefile.am:
  unit tests for dbug
dbug/dbug.c:
  negative lists (-#-d,info => everything but "info")
include/my_dbug.h:
  negative lists (-#-d,info => everything but "info")
unittest/Makefile.am:
  unit tests for dbug
dbug/tests-t.pl:
  unit tests for dbug
dbug/tests.c:
  unit tests for dbug
parent 74efae60
...@@ -23,19 +23,20 @@ libdbug_a_SOURCES = dbug.c sanity.c ...@@ -23,19 +23,20 @@ libdbug_a_SOURCES = dbug.c sanity.c
EXTRA_DIST = CMakeLists.txt example1.c example2.c example3.c \ EXTRA_DIST = CMakeLists.txt example1.c example2.c example3.c \
user.r monty.doc dbug_add_tags.pl \ user.r monty.doc dbug_add_tags.pl \
my_main.c main.c factorial.c dbug_analyze.c \ my_main.c main.c factorial.c dbug_analyze.c \
CMakeLists.txt CMakeLists.txt tests.c tests-t.pl
NROFF_INC = example1.r example2.r example3.r main.r \ NROFF_INC = example1.r example2.r example3.r main.r \
factorial.r output1.r output2.r output3.r \ factorial.r output1.r output2.r output3.r \
output4.r output5.r output4.r output5.r
CLEANFILES = $(NROFF_INC) user.t user.ps CLEANFILES = $(NROFF_INC) user.t user.ps tests-t
# Must be linked with libs that are not compiled yet # Must be linked with libs that are not compiled yet
noinst_PROGRAMS = factorial dbug_analyze noinst_PROGRAMS = factorial dbug_analyze tests
factorial_SOURCES = my_main.c factorial.c factorial_SOURCES = my_main.c factorial.c
tests_SOURCES = tests.c
dbug_analyze_SOURCES = dbug_analyze.c dbug_analyze_SOURCES = dbug_analyze.c
all: user.t user.ps all: user.t user.ps tests-t
user.t: user.r $(NROFF_INC) user.t: user.r $(NROFF_INC)
-nroff -mm user.r > $@ -nroff -mm user.r > $@
...@@ -61,5 +62,9 @@ output5.r: factorial ...@@ -61,5 +62,9 @@ output5.r: factorial
@RM@ -f $@ @RM@ -f $@
@SED@ -e 's!\\!\\\\!g' $< > $@ @SED@ -e 's!\\!\\\\!g' $< > $@
# a hack to have executable in builddir, not in srcdir
tests-t: tests-t.pl
cp $(srcdir)/tests-t.pl $(builddir)/tests-t
# Don't update the files from bitkeeper # Don't update the files from bitkeeper
%::SCCS/s.% %::SCCS/s.%
...@@ -57,17 +57,19 @@ ...@@ -57,17 +57,19 @@
* seismo!bpa!sjuvax!bbanerje * seismo!bpa!sjuvax!bbanerje
* *
* Michael Widenius: * Michael Widenius:
* DBUG_DUMP - To dump a block of memory. * DBUG_DUMP - To dump a block of memory.
* PUSH_FLAG "O" - To be used insted of "o" if we * PUSH_FLAG "O" - To be used insted of "o" if we
* want flushing after each write * want flushing after each write
* PUSH_FLAG "A" - as 'O', but we will append to the out file instead * PUSH_FLAG "A" - as 'O', but we will append to the out file instead
* of creating a new one. * of creating a new one.
* Check of malloc on entry/exit (option "S") * Check of malloc on entry/exit (option "S")
* *
* DBUG_EXECUTE_IF * Sergei Golubchik:
* incremental mode (-#+t:-d,info ...) * DBUG_EXECUTE_IF
* DBUG_SET, _db_explain_ * incremental mode (-#+t:-d,info ...)
* thread-local settings * DBUG_SET, _db_explain_
* thread-local settings
* negative lists (-#-d,info => everything but "info")
* *
*/ */
...@@ -174,9 +176,14 @@ IMPORT int _sanity(const char *file,uint line); /* safemalloc sanity checker */ ...@@ -174,9 +176,14 @@ IMPORT int _sanity(const char *file,uint line); /* safemalloc sanity checker */
struct link { struct link {
struct link *next_link; /* Pointer to the next link */ struct link *next_link; /* Pointer to the next link */
char str[1]; /* Pointer to link's contents */ char flags;
char str[1]; /* Pointer to link's contents */
}; };
/* flags for struct link */
#define INCLUDE 1
#define EXCLUDE 2
/* /*
* Debugging settings can be pushed or popped off of a * Debugging settings can be pushed or popped off of a
* stack which is implemented as a linked list. Note * stack which is implemented as a linked list. Note
...@@ -188,18 +195,18 @@ struct link { ...@@ -188,18 +195,18 @@ struct link {
*/ */
struct settings { struct settings {
int flags; /* Current settings flags */ int flags; /* Current settings flags */
int maxdepth; /* Current maximum trace depth */ int maxdepth; /* Current maximum trace depth */
uint delay; /* Delay after each output line */ uint delay; /* Delay after each output line */
int sub_level; /* Sub this from code_state->level */ int sub_level; /* Sub this from code_state->level */
FILE *out_file; /* Current output stream */ FILE *out_file; /* Current output stream */
FILE *prof_file; /* Current profiling stream */ FILE *prof_file; /* Current profiling stream */
char name[FN_REFLEN]; /* Name of output file */ char name[FN_REFLEN]; /* Name of output file */
struct link *functions; /* List of functions */ struct link *functions; /* List of functions */
struct link *p_functions; /* List of profiled functions */ struct link *p_functions; /* List of profiled functions */
struct link *keywords; /* List of debug keywords */ struct link *keywords; /* List of debug keywords */
struct link *processes; /* List of process names */ struct link *processes; /* List of process names */
struct settings *next; /* Next settings in the list */ struct settings *next; /* Next settings in the list */
}; };
#define is_shared(S, V) ((S)->next && (S)->next->V == (S)->V) #define is_shared(S, V) ((S)->next && (S)->next->V == (S)->V)
...@@ -249,9 +256,12 @@ typedef struct _db_code_state_ { ...@@ -249,9 +256,12 @@ typedef struct _db_code_state_ {
#define get_code_state_or_return if (!((cs=code_state()))) return #define get_code_state_or_return if (!((cs=code_state()))) return
/* Handling lists */ /* Handling lists */
static struct link *ListAdd(struct link *, const char *, const char *); #define ListAdd(A,B,C) ListAddDel(A,B,C,INCLUDE)
static struct link *ListDel(struct link *, const char *, const char *); #define ListDel(A,B,C) ListAddDel(A,B,C,EXCLUDE)
static struct link *ListAddDel(struct link *, const char *, const char *, int);
static struct link *ListCopy(struct link *); static struct link *ListCopy(struct link *);
static int InList(struct link *linkp,const char *cp);
static int ListFlags(struct link *linkp);
static void FreeList(struct link *linkp); static void FreeList(struct link *linkp);
/* OpenClose debug output stream */ /* OpenClose debug output stream */
...@@ -277,7 +287,6 @@ static void DoPrefix(CODE_STATE *cs, uint line); ...@@ -277,7 +287,6 @@ static void DoPrefix(CODE_STATE *cs, uint line);
static char *DbugMalloc(size_t size); static char *DbugMalloc(size_t size);
static const char *BaseName(const char *pathname); static const char *BaseName(const char *pathname);
static void Indent(CODE_STATE *cs, int indent); static void Indent(CODE_STATE *cs, int indent);
static BOOLEAN InList(struct link *linkp,const char *cp);
static void dbug_flush(CODE_STATE *); static void dbug_flush(CODE_STATE *);
static void DbugExit(const char *why); static void DbugExit(const char *why);
static const char *DbugStrTok(const char *s); static const char *DbugStrTok(const char *s);
...@@ -508,7 +517,7 @@ void _db_set_(CODE_STATE *cs, const char *control) ...@@ -508,7 +517,7 @@ void _db_set_(CODE_STATE *cs, const char *control)
{ {
int c, sign= (*control == '+') ? 1 : (*control == '-') ? -1 : 0; int c, sign= (*control == '+') ? 1 : (*control == '-') ? -1 : 0;
if (sign) control++; if (sign) control++;
if (!rel) sign=0; /* if (!rel) sign=0; */
c= *control++; c= *control++;
if (*control == ',') control++; if (*control == ',') control++;
/* XXX when adding new cases here, don't forget _db_explain_ ! */ /* XXX when adding new cases here, don't forget _db_explain_ ! */
...@@ -780,11 +789,12 @@ void _db_pop_() ...@@ -780,11 +789,12 @@ void _db_pop_()
buf=strnmov(buf, (S), len+1); \ buf=strnmov(buf, (S), len+1); \
if (buf >= end) goto overflow; \ if (buf >= end) goto overflow; \
} while (0) } while (0)
#define list_to_buf(l) do { \ #define list_to_buf(l, f) do { \
struct link *listp=(l); \ struct link *listp=(l); \
while (listp) \ while (listp) \
{ \ { \
str_to_buf(listp->str); \ if (listp->flags & (f)) \
str_to_buf(listp->str); \
listp=listp->next_link; \ listp=listp->next_link; \
} \ } \
} while (0) } while (0)
...@@ -824,9 +834,18 @@ void _db_pop_() ...@@ -824,9 +834,18 @@ void _db_pop_()
#define op_list_to_buf(C, val, cond) do { \ #define op_list_to_buf(C, val, cond) do { \
if ((cond)) \ if ((cond)) \
{ \ { \
int f=ListFlags(val); \
colon_to_buf; \ colon_to_buf; \
char_to_buf((C)); \ char_to_buf((C)); \
list_to_buf(val); \ if (f & INCLUDE) \
list_to_buf(val, INCLUDE); \
if (f & EXCLUDE) \
{ \
colon_to_buf; \
char_to_buf('-'); \
char_to_buf((C)); \
list_to_buf(val, EXCLUDE); \
} \
} \ } \
} while (0) } while (0)
#define op_bool_to_buf(C, cond) do { \ #define op_bool_to_buf(C, cond) do { \
...@@ -1137,7 +1156,7 @@ void _db_doprnt_(const char *format,...) ...@@ -1137,7 +1156,7 @@ void _db_doprnt_(const char *format,...)
va_start(args,format); va_start(args,format);
if (_db_keyword_(cs, cs->u_keyword)) if (_db_keyword_(cs, cs->u_keyword, 0))
{ {
int save_errno=errno; int save_errno=errno;
if (!cs->locked) if (!cs->locked)
...@@ -1183,7 +1202,7 @@ void _db_dump_(uint _line_, const char *keyword, ...@@ -1183,7 +1202,7 @@ void _db_dump_(uint _line_, const char *keyword,
CODE_STATE *cs; CODE_STATE *cs;
get_code_state_or_return; get_code_state_or_return;
if (_db_keyword_(cs, keyword)) if (_db_keyword_(cs, keyword, 0))
{ {
if (!cs->locked) if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug); pthread_mutex_lock(&THR_LOCK_dbug);
...@@ -1223,93 +1242,66 @@ void _db_dump_(uint _line_, const char *keyword, ...@@ -1223,93 +1242,66 @@ void _db_dump_(uint _line_, const char *keyword,
/* /*
* FUNCTION * FUNCTION
* *
* ListAdd add to the list modifiers from debug control string * ListAddDel modify the list according to debug control string
*
* SYNOPSIS
*
* static struct link *ListAdd(listp, ctlp, end)
* struct link *listp;
* char *ctlp;
* char *end;
* *
* DESCRIPTION * DESCRIPTION
* *
* Given pointer to a comma separated list of strings in "cltp", * Given pointer to a comma separated list of strings in "cltp",
* parses the list, and adds it to listp, returning a pointer * parses the list, and modifies "listp", returning a pointer
* to the new list * to the new list.
* *
* Note that since each link is added at the head of the list, * The mode of operation is defined by "todo" parameter.
* the final list will be in "reverse order", which is not
* significant for our usage here.
* *
*/ * If it's INCLUDE, elements (strings from "cltp") are added to the
* list, they'll have INCLUDE flag set. If the list already contains
static struct link *ListAdd(struct link *head, * the string in question, new element is not added, but a flag of
const char *ctlp, const char *end) * the existing element is adjusted (INCLUDE bit is set, EXCLUDE bit
{ * is removed).
const char *start;
struct link *new_malloc;
int len;
while (ctlp < end)
{
start= ctlp;
while (ctlp < end && *ctlp != ',')
ctlp++;
len=ctlp-start;
new_malloc= (struct link *) DbugMalloc(sizeof(struct link)+len);
memcpy(new_malloc->str, start, len);
new_malloc->str[len]=0;
new_malloc->next_link= head;
head= new_malloc;
ctlp++;
}
return head;
}
/*
* FUNCTION
*
* ListDel remove from the list modifiers in debug control string
*
* SYNOPSIS
*
* static struct link *ListDel(listp, ctlp, end)
* struct link *listp;
* char *ctlp;
* char *end;
*
* DESCRIPTION
*
* Given pointer to a comma separated list of strings in "cltp",
* parses the list, and removes these strings from the listp,
* returning a pointer to the new list.
* *
* If it's EXCLUDE, elements are added to the list with the EXCLUDE
* flag set. If the list already contains the string in question,
* it is removed, new element is not added.
*/ */
static struct link *ListDel(struct link *head, static struct link *ListAddDel(struct link *head, const char *ctlp,
const char *ctlp, const char *end) const char *end, int todo)
{ {
const char *start; const char *start;
struct link **cur; struct link **cur;
int len; int len;
while (ctlp < end) ctlp--;
next:
while (++ctlp < end)
{ {
start= ctlp; start= ctlp;
while (ctlp < end && *ctlp != ',') while (ctlp < end && *ctlp != ',')
ctlp++; ctlp++;
len=ctlp-start; len=ctlp-start;
cur=&head; if (len == 0) continue;
do for (cur=&head; *cur; cur=&((*cur)->next_link))
{ {
while (*cur && !strncmp((*cur)->str, start, len)) if (!strncmp((*cur)->str, start, len))
{ {
struct link *delme=*cur; if (todo == EXCLUDE)
*cur=(*cur)->next_link; {
free((void*) delme); struct link *delme=*cur;
*cur=(*cur)->next_link;
free((void*) delme);
}
else
{
(*cur)->flags&=~EXCLUDE;
(*cur)->flags|=INCLUDE;
}
goto next;
} }
} while (*cur && *(cur=&((*cur)->next_link))); }
*cur= (struct link *) DbugMalloc(sizeof(struct link)+len);
memcpy((*cur)->str, start, len);
(*cur)->str[len]=0;
(*cur)->flags=todo;
(*cur)->next_link=0;
} }
return head; return head;
} }
...@@ -1350,6 +1342,7 @@ static struct link *ListCopy(struct link *orig) ...@@ -1350,6 +1342,7 @@ static struct link *ListCopy(struct link *orig)
new_malloc= (struct link *) DbugMalloc(sizeof(struct link)+len); new_malloc= (struct link *) DbugMalloc(sizeof(struct link)+len);
memcpy(new_malloc->str, orig->str, len); memcpy(new_malloc->str, orig->str, len);
new_malloc->str[len]= 0; new_malloc->str[len]= 0;
new_malloc->flags=orig->flags;
new_malloc->next_link= head; new_malloc->next_link= head;
head= new_malloc; head= new_malloc;
orig= orig->next_link; orig= orig->next_link;
...@@ -1364,7 +1357,7 @@ static struct link *ListCopy(struct link *orig) ...@@ -1364,7 +1357,7 @@ static struct link *ListCopy(struct link *orig)
* *
* SYNOPSIS * SYNOPSIS
* *
* static BOOLEAN InList(linkp, cp) * static int InList(linkp, cp)
* struct link *linkp; * struct link *linkp;
* char *cp; * char *cp;
* *
...@@ -1372,37 +1365,48 @@ static struct link *ListCopy(struct link *orig) ...@@ -1372,37 +1365,48 @@ static struct link *ListCopy(struct link *orig)
* *
* Tests the string pointed to by "cp" to determine if it is in * Tests the string pointed to by "cp" to determine if it is in
* the list pointed to by "linkp". Linkp points to the first * the list pointed to by "linkp". Linkp points to the first
* link in the list. If linkp is NULL then the string is treated * link in the list. If linkp is NULL or contains only EXCLUDE
* as if it is in the list (I.E all strings are in the null list). * elements then the string is treated as if it is in the list.
* This may seem rather strange at first but leads to the desired * This may seem rather strange at first but leads to the desired
* operation if no list is given. The net effect is that all * operation if no list is given. The net effect is that all
* strings will be accepted when there is no list, and when there * strings will be accepted when there is no list, and when there
* is a list, only those strings in the list will be accepted. * is a list, only those strings in the list will be accepted.
* *
* RETURN
* 0 - not in the list (or matched an EXCLUDE element)
* 1 - in the list by default (list is empty or only has EXCLUDE elements)
* 2 - in the list explictly (matched an INCLUDE element)
*
*/ */
static BOOLEAN InList(struct link *linkp, const char *cp) static int InList(struct link *linkp, const char *cp)
{ {
REGISTER struct link *scan; int result;
REGISTER BOOLEAN result;
if (linkp == NULL) for (result=1; linkp != NULL; linkp= linkp->next_link)
result= TRUE;
else
{ {
result= FALSE; if (!strcmp(linkp->str, cp))
for (scan= linkp; scan != NULL; scan= scan->next_link) return linkp->flags & EXCLUDE ? 0 : 2;
{ if (!(linkp->flags & EXCLUDE))
if (!strcmp(scan->str, cp)) result=0;
{
result= TRUE;
break;
}
}
} }
return result; return result;
} }
/*
* FUNCTION
*
* ListFlags returns aggregated list flags (ORed over all elements)
*
*/
static int ListFlags(struct link *linkp)
{
int f;
for (f=0; linkp != NULL; linkp= linkp->next_link)
f|= linkp->flags;
return f;
}
/* /*
* FUNCTION * FUNCTION
...@@ -1589,50 +1593,15 @@ FILE *_db_fp_(void) ...@@ -1589,50 +1593,15 @@ FILE *_db_fp_(void)
return cs->stack->out_file; return cs->stack->out_file;
} }
/*
* FUNCTION
*
* _db_strict_keyword_ test keyword for member of keyword list
*
* SYNOPSIS
*
* BOOLEAN _db_strict_keyword_(keyword)
* char *keyword;
*
* DESCRIPTION
*
* Similar to _db_keyword_, but keyword is NOT accepted if keyword list
* is empty. Used in DBUG_EXECUTE_IF() - for actions that must not be
* executed by default.
*
* Returns TRUE if keyword accepted, FALSE otherwise.
*
*/
BOOLEAN _db_strict_keyword_(const char *keyword)
{
CODE_STATE *cs;
get_code_state_or_return FALSE;
if (!DEBUGGING || cs->stack->keywords == NULL)
return FALSE;
return _db_keyword_(cs, keyword);
}
/* /*
* FUNCTION * FUNCTION
* *
* _db_keyword_ test keyword for member of keyword list * _db_keyword_ test keyword for member of keyword list
* *
* SYNOPSIS
*
* BOOLEAN _db_keyword_(keyword)
* char *keyword;
*
* DESCRIPTION * DESCRIPTION
* *
* Test a keyword to determine if it is in the currently active * Test a keyword to determine if it is in the currently active
* keyword list. As with the function list, a keyword is accepted * keyword list. If strict=0, a keyword is accepted
* if the list is null, otherwise it must match one of the list * if the list is null, otherwise it must match one of the list
* members. When debugging is not on, no keywords are accepted. * members. When debugging is not on, no keywords are accepted.
* After the maximum trace level is exceeded, no keywords are * After the maximum trace level is exceeded, no keywords are
...@@ -1644,14 +1613,14 @@ BOOLEAN _db_strict_keyword_(const char *keyword) ...@@ -1644,14 +1613,14 @@ BOOLEAN _db_strict_keyword_(const char *keyword)
* *
*/ */
BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword) BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict)
{ {
get_code_state_if_not_set_or_return FALSE; get_code_state_if_not_set_or_return FALSE;
return (DEBUGGING && return (DEBUGGING &&
(!TRACING || cs->level <= cs->stack->maxdepth) && (!TRACING || cs->level <= cs->stack->maxdepth) &&
InList(cs->stack->functions, cs->func) && InList(cs->stack->functions, cs->func) &&
InList(cs->stack->keywords, keyword) && InList(cs->stack->keywords, keyword) > (strict != 0) &&
InList(cs->stack->processes, cs->process)); InList(cs->stack->processes, cs->process));
} }
......
#!/usr/bin/perl
#
# A driver program to test DBUG features - runs tests (shell commands)
# from the end of file to invoke tests.c, which does the real dbug work.
#
$exe=$0;
die unless $exe =~ s/(tests)-t(\.exe)?$/$1$2 /;
# load tests
@tests=();
while (<DATA>) {
if (/^% tests /) {
push @tests, [ $' ]
} else {
push @{$tests[$#tests]}, $_
}
}
# require/import instead of use - we know the plan only when tests are loaded
require Test::More;
import Test::More tests => scalar(@tests);
for (@tests) {
$t=$exe . shift @$_;
chomp($t);
open F, '-|', $t or die "open($t|): $!";
local $";
$out=join($", <F>); close(F);
# special cases are handled here:
$out =~ s/Memory: 0x[0-9A-Fa-f]+/Memory: 0x####/g if $t =~ /dump/;
# compare ("\n" at the beginning makes better output in case of errors)
is("\n$out","\n@$_", $t);
}
__DATA__
% tests -#d
func2: info: s=ok
func2: info: s=ok
=> execute
=> evaluate: ON
=> evaluate_if: OFF
main: explain: dbug explained: d
% tests -#d,ret3
=> evaluate: OFF
=> evaluate_if: OFF
% tests -#d:-d,ret3
func2: info: s=ko
func2: info: s=ko
=> execute
=> evaluate: ON
=> evaluate_if: OFF
main: explain: dbug explained: d:-d,ret3
% tests -#t:-d,ret3
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | <func2
| <func1
| >func2
| | >func3
| | <func3
| <func2
=> evaluate: OFF
=> evaluate_if: OFF
<main
% tests -#t:d,info:-d,ret3
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | | info: s=ko
| | <func2
| <func1
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
=> evaluate: OFF
=> evaluate_if: OFF
<main
% tests -#t:d,info:-d,ret3:-f,func2
>main
| >func1
| | | >func3
| | | <func3
| <func1
| | >func3
| | <func3
=> evaluate: OFF
=> evaluate_if: OFF
<main
% tests -#t:d,info:-d,ret3:-f,func2 d,evaluate
=> evaluate: ON
=> evaluate_if: OFF
% tests -#t:d,info:-d,ret3:-f,func2 d,evaluate_if
=> evaluate: OFF
=> evaluate_if: ON
% tests -#t:d:-d,ret3:-f,func2 d,evaluate_if
=> evaluate: OFF
=> evaluate_if: ON
% tests -#t:d:-d,ret3:-f,func2 +d,evaluate_if
>main
| >func1
| | | >func3
| | | <func3
| <func1
| | >func3
| | <func3
=> evaluate: OFF
=> evaluate_if: ON
<main
% tests -#t:d:-d,ret3:-f,func2
>main
| >func1
| | | >func3
| | | <func3
| <func1
| | >func3
| | <func3
=> execute
=> evaluate: ON
=> evaluate_if: OFF
| explain: dbug explained: d:-d,ret3:f:-f,func2:t
<main
% tests -#t:d:-d,ret3:f:-f,func2 -#+d,dump
>main
| >func1
| | | >func3
| | | <func3
| <func1
| | >func3
| | <func3
| dump: Memory: 0x#### Bytes: (27)
64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
74
=> evaluate: OFF
=> evaluate_if: OFF
<main
% tests -#t:d:-d,ret3:f:-f,func2 +d,dump
>main
| >func1
| | | >func3
| | | <func3
| <func1
| | >func3
| | <func3
| dump: Memory: 0x#### Bytes: (27)
64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
74
=> evaluate: OFF
=> evaluate_if: OFF
<main
% tests -#t:d:-d,ret3:f:-f,func2:+d,dump
>main
| >func1
| | | >func3
| | | <func3
| <func1
| | >func3
| | <func3
| dump: Memory: 0x#### Bytes: (27)
64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
74
=> evaluate: OFF
=> evaluate_if: OFF
<main
% tests -#t:d:-d,ret3:f:-f,func2 +d,dump,explain
>main
| >func1
| | | >func3
| | | <func3
| <func1
| | >func3
| | <func3
| dump: Memory: 0x#### Bytes: (35)
64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
66 2C 66 75 6E 63 32 3A 74
=> evaluate: OFF
=> evaluate_if: OFF
| explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:t
<main
% tests -#t:d:-d,ret3:f:-f,func2 +d,dump,explain:P
dbug: >main
dbug-tests: | >func1
dbug-tests: | | | >func3
dbug-tests: | | | <func3
dbug-tests: | <func1
dbug-tests: | | >func3
dbug-tests: | | <func3
dbug-tests: | dump: Memory: 0x#### Bytes: (37)
64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
66 2C 66 75 6E 63 32 3A 50 3A 74
=> evaluate: OFF
=> evaluate_if: OFF
dbug-tests: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:P:t
dbug-tests: <main
% tests -#t:d:-d,ret3:f:-f,func2 +d,dump,explain:P:F
dbug: tests.c: >main
dbug-tests: tests.c: | >func1
dbug-tests: tests.c: | | | >func3
dbug-tests: tests.c: | | | <func3
dbug-tests: tests.c: | <func1
dbug-tests: tests.c: | | >func3
dbug-tests: tests.c: | | <func3
dbug-tests: tests.c: | dump: Memory: 0x#### Bytes: (39)
64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
66 2C 66 75 6E 63 32 3A 46 3A 50 3A 74
=> evaluate: OFF
=> evaluate_if: OFF
dbug-tests: tests.c: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:F:P:t
dbug-tests: tests.c: <main
% tests -#t:d:-d,ret3:f:-f,func2
>main
| >func1
| | | >func3
| | | <func3
| <func1
| | >func3
| | <func3
=> execute
=> evaluate: ON
=> evaluate_if: OFF
| explain: dbug explained: d:-d,ret3:f:-f,func2:t
<main
% tests -#t:d:-d,ret3
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | | info: s=ko
| | <func2
| <func1
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
=> execute
=> evaluate: ON
=> evaluate_if: OFF
| explain: dbug explained: d:-d,ret3:t
<main
% tests -#t:d,info:-d,ret3:d,push
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | | info: s=ko
| | <func2
| <func1
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
=> evaluate: OFF
=> evaluate_if: OFF
<main
% tests -#d,info:-d,ret3:d,push
func2: info: s=ko
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
<main
% tests -#d,info:-d,ret3:d,push,explain
func2: info: s=ko
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
| explain: dbug explained: d,info,push,explain:-d,ret3:t
<main
% tests -#d,info:-d,ret3:d,explain
func2: info: s=ko
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
main: explain: dbug explained: d,info,explain:-d,ret3
% tests -#d,info:-d,ret3:d,explain,pop
func2: info: s=ko
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
% tests -#d,info:-d,ret3:d,explain,pop t
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | <func2
| <func1
| >func2
| | >func3
| | <func3
| <func2
=> evaluate: OFF
=> evaluate_if: OFF
<main
% tests -#d,info:-d,ret3:d,explain,pop +t
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | | info: s=ko
| | <func2
| <func1
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
=> evaluate: OFF
=> evaluate_if: OFF
main: explain: dbug explained: d,info,explain,pop:-d,ret3
% tests -#d,info:-d,ret3:d,explain,set
func2: info: s=ko
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
tests.c: main: explain: dbug explained: d,info,explain,set:-d,ret3:F
% tests -#d,info:-d,ret3:d,explain,set:t
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | | info: s=ko
| | <func2
| <func1
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
=> evaluate: OFF
=> evaluate_if: OFF
tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
tests.c: <main
% tests t -#d,info:-d,ret3:d,explain,set:t
>main
| >func1
| | >func2
| | | >func3
| | | <func3
| | | info: s=ko
| | <func2
| <func1
| >func2
| | >func3
| | <func3
| | info: s=ko
| <func2
=> evaluate: OFF
=> evaluate_if: OFF
tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
tests.c: <main
% tests t -#d,info:-d,ret3:d,explain,set,pop
func2: info: s=ko
func2: info: s=ko
=> evaluate: OFF
=> evaluate_if: OFF
<main
/*
A program to test DBUG features. Used by tests-t.pl
*/
#ifdef DBUG_OFF /* We are testing dbug */
#undef DBUG_OFF
#endif
#include <my_global.h> /* This includes dbug.h */
#include <my_pthread.h>
#include <string.h>
const char *func3()
{
DBUG_ENTER("func3");
DBUG_RETURN(DBUG_EVALUATE("ret3", "ok", "ko"));
}
void func2()
{
const char *s;
DBUG_ENTER("func2");
s=func3();
DBUG_PRINT("info", ("s=%s", s));
DBUG_VOID_RETURN;
}
int func1()
{
DBUG_ENTER("func1");
func2();
DBUG_RETURN(10);
}
int main (int argc, char *argv[])
{
int i;
#if defined(HAVE_PTHREAD_INIT) && defined(THREAD)
pthread_init(); /* Must be called before DBUG_ENTER */
#endif
#ifdef THREAD
my_thread_global_init();
#endif
dup2(1, 2);
for (i = 1; i < argc; i++)
DBUG_PUSH (argv[i]);
{
DBUG_ENTER ("main");
DBUG_PROCESS ("dbug-tests");
func1();
func2();
DBUG_EXECUTE_IF("dump",
{
char s[1000];
DBUG_EXPLAIN(s, sizeof(s)-1);
DBUG_DUMP("dump", (uchar*)s, strlen(s));
});
DBUG_EXECUTE_IF("push", DBUG_PUSH("+t"); );
DBUG_EXECUTE("execute", fprintf(DBUG_FILE, "=> execute\n"); );
DBUG_EXECUTE_IF("set", DBUG_SET("+F"); );
fprintf(DBUG_FILE, "=> evaluate: %s\n",
DBUG_EVALUATE("evaluate", "ON", "OFF"));
fprintf(DBUG_FILE, "=> evaluate_if: %s\n",
DBUG_EVALUATE_IF("evaluate_if", "ON", "OFF"));
DBUG_EXECUTE_IF("pop", DBUG_POP(); );
{
char s[1000];
DBUG_EXPLAIN(s, sizeof(s)-1);
DBUG_PRINT("explain", ("dbug explained: %s", s));
}
DBUG_RETURN (0);
}
}
...@@ -22,8 +22,7 @@ extern "C" { ...@@ -22,8 +22,7 @@ extern "C" {
#if !defined(DBUG_OFF) && !defined(_lint) #if !defined(DBUG_OFF) && !defined(_lint)
struct _db_code_state_; struct _db_code_state_;
extern my_bool _dbug_on_; extern my_bool _dbug_on_;
extern my_bool _db_keyword_(struct _db_code_state_ *cs, const char *keyword); extern my_bool _db_keyword_(struct _db_code_state_ *, const char *, int);
extern my_bool _db_strict_keyword_(const char *keyword);
extern int _db_explain_(struct _db_code_state_ *cs, char *buf, size_t len); extern int _db_explain_(struct _db_code_state_ *cs, char *buf, size_t len);
extern int _db_explain_init_(char *buf, size_t len); extern int _db_explain_init_(char *buf, size_t len);
extern void _db_setjmp_(void); extern void _db_setjmp_(void);
...@@ -58,13 +57,13 @@ extern void _db_force_flush(); ...@@ -58,13 +57,13 @@ extern void _db_force_flush();
#define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0) #define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0)
#define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0) #define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0)
#define DBUG_EXECUTE(keyword,a1) \ #define DBUG_EXECUTE(keyword,a1) \
do {if (_db_keyword_(0, (keyword))) { a1 }} while(0) do {if (_db_keyword_(0, (keyword), 0)) { a1 }} while(0)
#define DBUG_EXECUTE_IF(keyword,a1) \ #define DBUG_EXECUTE_IF(keyword,a1) \
do {if (_db_strict_keyword_ (keyword)) { a1 } } while(0) do {if (_db_keyword_(0, (keyword), 1)) { a1 }} while(0)
#define DBUG_EVALUATE(keyword,a1,a2) \ #define DBUG_EVALUATE(keyword,a1,a2) \
(_db_keyword_(0,(keyword)) ? (a1) : (a2)) (_db_keyword_(0,(keyword), 0) ? (a1) : (a2))
#define DBUG_EVALUATE_IF(keyword,a1,a2) \ #define DBUG_EVALUATE_IF(keyword,a1,a2) \
(_db_strict_keyword_((keyword)) ? (a1) : (a2)) (_db_keyword_(0,(keyword), 1) ? (a1) : (a2))
#define DBUG_PRINT(keyword,arglist) \ #define DBUG_PRINT(keyword,arglist) \
do {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;} while(0) do {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;} while(0)
#define DBUG_PUSH(a1) _db_push_ (a1) #define DBUG_PUSH(a1) _db_push_ (a1)
......
...@@ -18,7 +18,7 @@ SUBDIRS = mytap mysys examples ...@@ -18,7 +18,7 @@ SUBDIRS = mytap mysys examples
EXTRA_DIST = unit.pl EXTRA_DIST = unit.pl
CLEANFILES = unit CLEANFILES = unit
unittests = mytap mysys @mysql_se_unittest_dirs@ @mysql_pg_unittest_dirs@ unittests = mytap mysys @mysql_se_unittest_dirs@ @mysql_pg_unittest_dirs@ ../dbug
test: test:
perl unit.pl run $(unittests) perl unit.pl run $(unittests)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment