
/* $Header: /private/postgres/src/test/RCS/testtrace.c,v 1.7 1989/09/05 16:55:02 mao Version_2 $
 *   TESTTRACE.C
 *
 *   This program tests the trace module.  The trace module allows you
 *   to turn on and off tracing according to one or more 'trace variables'.
 *   Currently you can do two things with these variables:
 *
 *   (1) Call TraceMsg[0..2]() to print trace (debug) messages.  Whether
 *	 they are actually printed or not depends on whether the variables
 *	 are enabled or not.
 *
 *   (2) Track the subroutine call stack using TracePush() and TracePop().
 *	 All such calls are saved but only those whos associated trace
 *	 variables are enabled are actually printed.
 *
 *	 A failed assertion or other exception will cause the stack
 *	 maintained by TracePush() and TracePop() align.  Additionaly,
 *	 some amount of error checking is done to attempt to catch 
 *	 programmers who forget to TracePop() what they have pushed.
 *
 *   To Use, setenv TRACE_VarName  <somenumber> for any or all the trace
 *   variables and then run testtrace.  Example:
 *
 *   % setenv TRACE_Alpha 1
 *   % setenv TRACE_Beta 1
 *   % testtrace
 *      ...
 *   % setenv TESTASSERT 2
 *   % testtrace
 *
 *   The TESTASSERT enviroment variable will cause an Assert(0) to be called
 *   within the subroutine tracing test, forcing a program abort.  Before
 *   the program aborts a trace dump will be printed as of that point.
 */

#include <stdio.h>
#include "trace.h"

/*
 *  Use DeclareTrace() to declare trace variables.  Multiple modules may
 *  declare trace variables of the same name.  These identifiers will be
 *  passed to various trace routines later on.
 */

DeclareTrace(Alpha);
DeclareTrace(Beta);
DeclareTrace(Gamma);
DeclareTrace(Delta);

/*
 *  Use DeclareTraceParents() to give a trace variable up to two parent
 *  variables.  The parent names need not be declared with DeclareTrace().
 *
 *  Turning tracing on for a given parent automatically turns it on for
 *  its children.
 */

DeclareTraceParents(Epsilon, Root, P1);
DeclareTraceParents(Indi,    Root, P1);
DeclareTraceParents(Bravo,   Root, P2);
DeclareTraceParents(Hotel,   Root, P2);

/*
 *  Locally only one level hierarchy is allowed.  Better to modify
 *  trace.c and add your own global hierarchy.
 * 
 *  XXX
 */

DeclareTrace(P);
DeclareTraceParent(P1, P);
DeclareTraceParent(P2, P);

static int TestAssert;

main()
{
    if (getenv("TESTASSERT") != NULL)
	TestAssert = atoi(getenv("TESTASSERT"));

    EnableTrace(true);

    if (getenv("TRACEFILE") == NULL)
	TraceFileName("/dev/tty");

    puts("Trace Enabled");

    if (Traced(Alpha))
	puts("Alpha is Traced");
    TraceMsg0(Alpha, "Alpha Msg");
    TraceMsg0(Beta,  "Beta Msg");
    TraceMsg0(Gamma, "Gamma Msg");
    TraceMsg0(Delta, "Delta Msg");

    TraceMsg0(Epsilon, "Epsilon Msg");
    TraceMsg0(Indi,  "Indi Msg");
    TraceMsg0(Bravo, "Bravo Msg");
    TraceMsg0(Hotel, "Hotel Msg");

    TraceMsg0(P1, "P1 Msg");
    TraceMsg0(P2, "P2 Msg");

    TraceMsg0(P, "P Msg");

    puts("");
    puts("NOW TESTING SUBROUTINE TRACE.  FOUR LEVELS OF SUBROUTINES");
    puts("NOTE: If 'TESTASSERT' enviroment variable is set to some");
    puts("      number 1..4 I will call Assert(0) from inside that");
    puts("      particular level");
    fflush(stdout);
    sleep(1);

    LevelAlpha(0);
    LevelAlpha(1);

    puts("END OF TESTING SUBROUTINE TRACE");
    fflush(stdout);

    EnableTrace(false);
    puts("Trace Disabled");
}

/*
 *  Notes on subroutine call stack tracing.  You must specify the same
 *  trace variable in the Pop as you did for the Push.
 *
 *  You may reuse trace block names (i.e. they could all use 'Alpha'
 *  if they wanted to).  The trace block is used to determine when to
 *  display subroutine tracing messages (if tracing is on for that 
 *  block) and to retrieve the module name when printing messages.
 */

LevelAlpha(x)
{
    TracePush(Alpha, "Level 1");
    LevelBeta(0);
    LevelBeta(1);
    if (x && TestAssert == 1)
	Assert(0);
    TracePop(Alpha);
}

LevelBeta(x)
{
    TracePush(Beta, "Level 2");
    LevelGamma(0);
    sleep(1);
    LevelGamma(1);
    sleep(1);
    if (x && TestAssert == 2)
	Assert(0);
    TracePop(Beta);
}

LevelGamma(x)
{
    TracePush(Gamma, "Level 3");
    LevelDelta(0);
    LevelDelta(1);
    if (x && TestAssert == 3)
	Assert(0);
    TracePop(Gamma);
}

LevelDelta(x)
{
    TracePush(Delta, "Level 4");
    if (x && TestAssert == 4)
	Assert(0);
    TracePop(Delta);
}

