/*****************************************************************************
    This code will test whether trace levels can be set successfully.
 
    XXX: For the last two testpoints, must verify that the results are
    correct, and put that verification in the test as well.
 *****************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

#include "pslib.h"
#include "tap.h"
#include "pstap.h"


static psS32 testTrace00(void);
static psS32 testTrace01(void);
static psS32 testTrace02(void);
static psS32 testTrace03(void);
static psS32 testTrace04(void);
static psS32 testTrace05(void);
static psS32 testTrace05a(void);
static psS32 testTrace06(void);
static psS32 testTrace08(void);


psS32 main( psS32 argc, char* argv[] )
{
    plan_tests(45);

    testTrace00();
    testTrace01();
    testTrace02();
    testTrace03();
    testTrace04();
    testTrace05();
    testTrace05a();
    testTrace06();
    testTrace08();
}


static psS32 testTrace00(void)
{
    diag("testTrace00");

    psS32 i;
    psS32 lev = 0;

    //    psTraceSetDestination(stderr);
    psTraceSetDestination(2);

    for (i=0;i<10;i++) {
        (void)psTraceSetLevel(".", i);
        lev = psTraceGetLevel(".");
        ok(lev == i, "trace level was %d, actual was %d\n", i, lev);
    }

    (void)psTraceSetLevel(".", 3);

    for (i=5;i<10;i++) {
        (void)psTraceSetLevel(".NODE00", i);
        lev = psTraceGetLevel(".NODE00");
        ok (lev == i,"(.NODE00) expected trace level was %d, actual was %d\n",
            i, lev);

        lev = psTraceGetLevel(".");
        ok (lev == 3,
            "expected trace level was %d, actual was %d\n", i, 3);
    }


    (void)psTraceSetLevel(".NODE00.NODE01", 4);
    for (i=0;i<10;i++) {
        (void)psTraceSetLevel(".NODE00.NODE01", i);
        lev = psTraceGetLevel(".NODE00.NODE01");
        ok (lev == i,
            "(.NODE00.NODE01) expected trace level was %d, actual was %d\n",
            i, lev);
    }

    return 0;
}


static psS32 testTrace01(void)
{
    diag("testTrace01");

    //    psTraceSetDestination(stderr);
    psTraceSetDestination(2);
    (void)psTraceSetLevel(".A.B.C.D.E", 5);

    psTrace(".A.C.D.C",1,"You should not see this.\n");
    psTrace(".A.B.C.D.E",2,"You should see this.\n");
    psTrace(".A.B.C.D.E.F",3,"You should see this too.\n");

    psTracePrintLevels();

    return 0;
}

static psS32 testTrace02(void)
{
    diag("testTrace02");

    psTraceReset();
    //    psTraceSetDestination(stderr);
    psTraceSetDestination(2);
    psTraceSetLevel(".A.B", 2);
    psTraceSetLevel(".A.B.C.D.E", 5);
    psTracePrintLevels();
    psTraceSetLevel(".A.B", 10);
    psTracePrintLevels();

    ok (10 == psTraceGetLevel(".A.B.C"),
        ".A.B.C did not dynamically inherit a trace level (%d)\n",
        psTraceGetLevel(".A.B.C"));

    ok (10 == psTraceGetLevel(".A.B.C.D"),
        ".A.B.C.D did not dynamically inherit a trace level (%d)\n",
        psTraceGetLevel(".A.B.C.D"));

    ok (5 == psTraceGetLevel(".A.B.C.D.E"),
        ".A.B.C.D.E did dynamically inherit a trace level (%d)\n",
        psTraceGetLevel(".A.B.C.D.E"));

    return 0;
}

static psS32 testTrace03(void)
{
    diag("testTrace03");

    psS32 i = 0;
    psS32 lev = 0;

    //    psTraceSetDestination(stderr);
    psTraceSetDestination(2);

    for (i=0;i<10;i++) {
        (void)psTraceSetLevel(".", i);
        psTraceReset();

        lev = psTraceGetLevel(".");
        ok (lev == PS_UNKNOWN_TRACE_LEVEL,
            "expected trace level was %d, actual was %d\n",
            PS_UNKNOWN_TRACE_LEVEL, lev);
    }

    (void)psTraceSetLevel(".", 5);
    (void)psTraceSetLevel(".a", 4);
    (void)psTraceSetLevel(".a.b", 3);
    (void)psTraceSetLevel(".a.b.c", 2);
    ok (!((5 != psTraceGetLevel(".")) ||
          (4 != psTraceGetLevel(".a")) ||
          (3 != psTraceGetLevel(".a.b")) ||
          (2 != psTraceGetLevel(".a.b.c"))),
        "trace successFlag = false;levels were not settable?\n");

    psTraceReset();
    ok (!((PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".")) ||
          (PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".a")) ||
          (PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".a.b")) ||
          (PS_UNKNOWN_TRACE_LEVEL != psTraceGetLevel(".a.b.c"))),
        "trace levels were not reset properly\n");

    return 0;
}


static psS32 testTrace04(void)
{
    diag("testTrace04");

    int FD;
    psS32 nb = 0;
    FD = creat("tst_psTrace02_OUT", 0666);
    //    printf("\nFD = %d\n", FD);
    //    fp = fopen("tst_psTrace02_OUT", "w");
    for (nb = 0 ; nb<4;nb++) {
        if (nb == 0)
            //            psTraceSetDestination(stdout);
            psTraceSetDestination(1);
        if (nb == 1)
            //            psTraceSetDestination(stderr);
            psTraceSetDestination(2);
        if (nb == 2)
            psTraceSetDestination(0); //NULL
        if (nb == 3)
            psTraceSetDestination(FD);

        (void)psTraceSetLevel(".", 4);
        psTrace(".", 5, "(0) This message should not be displayed (%x)\n",
                0xbeefface);
        (void)psTraceSetLevel(".", 7);
        psTrace(".", 5, "(0) This message should be displayed (%x)\n",
                0xbeefface);

        (void)psTraceSetLevel(".a", 4);
        psTrace(".a", 5, "(1) This message should not be displayed (%x)\n",
                0xbeefface);
        (void)psTraceSetLevel(".a", 7);
        psTrace(".a", 5, "(1) This message should be displayed (%x)\n",
                0xbeefface);


        (void)psTraceSetLevel(".a.b", 4);
        psTrace(".a.b", 5, "(2) This message should not be displayed (%x)\n",
                0xbeefface);
        (void)psTraceSetLevel(".a.b", 7);
        psTrace(".a.b", 5, "(2) This message should be displayed (%x)\n",
                0xbeefface);
        (void)psTraceSetLevel(".a.b.c", 12);
        psTrace(".a.b.c", 11, "(3) This message should be displayed (%x)\n",
                0xbeefface);

    }

    close(FD);

    return(0);
}

static psS32 testTrace05(void)
{
    //    psTraceSetDestination(stderr);
    psTraceSetDestination(2);

    (void)psTraceSetLevel(".", 9);

    (void)psTraceSetLevel(".a", 8);
    (void)psTraceSetLevel(".b", 7);
    (void)psTraceSetLevel(".c", 5);

    (void)psTraceSetLevel(".a.a", 4);
    (void)psTraceSetLevel(".a.b", 3);

    (void)psTraceSetLevel(".b.a", 2);
    (void)psTraceSetLevel(".b.b", 1);

    (void)psTraceSetLevel(".c.a", 0);
    (void)psTraceSetLevel(".c.b", 3);
    (void)psTraceSetLevel(".c.c", 5);

    psTracePrintLevels();

    return 0;

}

static psS32 testTrace05a(void)
{
    (void)psTraceSetLevel(".", 9);

    (void)psTraceSetLevel("a", 8);
    (void)psTraceSetLevel("b", 7);
    (void)psTraceSetLevel("c", 5);

    (void)psTraceSetLevel("a.a", 4);
    (void)psTraceSetLevel("a.b", 3);

    (void)psTraceSetLevel("b.a", 2);
    (void)psTraceSetLevel("b.b", 1);

    (void)psTraceSetLevel("c.a", 0);
    (void)psTraceSetLevel("c.b", 3);
    (void)psTraceSetLevel("c.c", 5);

    psTracePrintLevels();

    return 0;

}

static psS32 testTrace06(void)
{
    //    psTraceSetDestination(stderr);
    psTraceSetDestination(2);

    (void)psTraceSetLevel(".", 9);

    (void)psTraceSetLevel(".a", 8);
    (void)psTraceSetLevel(".b", 7);
    (void)psTraceSetLevel(".c", 5);

    (void)psTraceSetLevel(".a.a", 4);
    (void)psTraceSetLevel(".a.b", 3);

    (void)psTraceSetLevel(".b.a", 2);
    (void)psTraceSetLevel(".b.b", 1);

    (void)psTraceSetLevel(".c.a", 0);
    (void)psTraceSetLevel(".c.b", 3);
    (void)psTraceSetLevel(".c.c", 5);

    psTraceReset();

    if ((psTraceGetLevel(".")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".a")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".b")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".c")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".a.a")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".a.b")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".b.a")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".b.b")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".c.a")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".c.b")!=PS_UNKNOWN_TRACE_LEVEL) ||
            (psTraceGetLevel(".c.c")!=PS_UNKNOWN_TRACE_LEVEL)) {
        return 1;
    }

    return 0;
}

// Ensure that the leading dot in the component names are optional.
static psS32 testTrace08(void)
{
    psTraceReset();
    (void)psTraceSetLevel(".", 9);

    (void)psTraceSetLevel(".a", 8);
    (void)psTraceSetLevel(".b", 7);
    (void)psTraceSetLevel(".c", 5);

    (void)psTraceSetLevel(".a.a", 4);
    (void)psTraceSetLevel(".a.b", 3);

    (void)psTraceSetLevel(".b.a", 2);
    (void)psTraceSetLevel(".b.b", 1);

    (void)psTraceSetLevel(".c.a", 0);
    (void)psTraceSetLevel(".c.b", 3);
    (void)psTraceSetLevel(".c.c", 5);

    psTracePrintLevels();

    if ((psTraceGetLevel(".")!=9) ||
            (psTraceGetLevel("a")!=8) ||
            (psTraceGetLevel("b")!=7) ||
            (psTraceGetLevel("c")!=5) ||
            (psTraceGetLevel("a.a")!=4) ||
            (psTraceGetLevel("a.b")!=3) ||
            (psTraceGetLevel("b.a")!=2) ||
            (psTraceGetLevel("b.b")!=1) ||
            (psTraceGetLevel("c.a")!=0) ||
            (psTraceGetLevel("c.b")!=3) ||
            (psTraceGetLevel("c.c")!=5)) {
        printf("psTraceGetLevel(.) is %d\n", psTraceGetLevel("."));
        printf("psTraceGetLevel(a) is %d\n", psTraceGetLevel("a"));
        printf("psTraceGetLevel(b) is %d\n", psTraceGetLevel("b"));
        printf("psTraceGetLevel(c) is %d\n", psTraceGetLevel("c"));
        printf("psTraceGetLevel(a.a) is %d\n", psTraceGetLevel("a.a"));
        printf("psTraceGetLevel(a.b) is %d\n", psTraceGetLevel("a.b"));
        printf("psTraceGetLevel(b.a) is %d\n", psTraceGetLevel("b.a"));
        printf("psTraceGetLevel(b.b) is %d\n", psTraceGetLevel("b.b"));
        printf("psTraceGetLevel(c.a) is %d\n", psTraceGetLevel("c.a"));
        printf("psTraceGetLevel(c.b) is %d\n", psTraceGetLevel("c.b"));
        printf("psTraceGetLevel(c.c) is %d\n", psTraceGetLevel("c.c"));

        return 1;
    }

    return 0;
}
