/*****************************************************************************
    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"


psS32 main( psS32 argc, char* argv[] )
{
    psLogSetFormat("HLNM");
    psLogSetLevel(PS_LOG_INFO);
    plan_tests(54);

# define DEBUG 1
# if (DEBUG)
    FILE *output = fopen ("/dev/null", "w");
    int outFD = fileno (output);
# else
    int outFD = 2;
# endif

    // testTrace00()
    {
        psMemId id = psMemGetId();
        psS32 lev = 0;
        (void)psTraceSetDestination(outFD);
        for (int i=0;i<10;i++) {
            (void)psTraceSetLevel(".", i);
            lev = psTraceGetLevel(".");
            ok(lev == i, "trace level was %d, actual was %d", i, lev);
        }

        (void)psTraceSetLevel(".", 3);
        for (int i=5;i<10;i++) {
            (void)psTraceSetLevel(".NODE00", i);
            lev = psTraceGetLevel(".NODE00");
            ok (lev == i,"(.NODE00) expected trace level was %d, actual was %d",
                i, lev);
    
            lev = psTraceGetLevel(".");
            ok (lev == 3,
                "expected trace level was %d, actual was %d", i, 3);
        }
    
        (void)psTraceSetLevel(".NODE00.NODE01", 4);
        for (int 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",
                i, lev);
        }

        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
    }


    // testTrace01()
    {
        psMemId id = psMemGetId();
        (void)psTraceSetDestination(outFD);
        (void)psTraceSetLevel(".A.B.C.D.E", 5);
        psTrace(".A.C.D.C",1,"You should not see this");
        psTrace(".A.B.C.D.E",2,"You should see this");
        psTrace(".A.B.C.D.E.F",3,"You should see this too");
        psTracePrintLevels();
        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
    }


    // testTrace02()
    {
        psMemId id = psMemGetId();
        psTraceReset();
        (void)psTraceSetDestination(outFD);
        (void)psTraceSetLevel(".A.B", 2);
        (void)psTraceSetLevel(".A.B.C.D.E", 5);
        psTracePrintLevels();
        (void)psTraceSetLevel(".A.B", 10);
        psTracePrintLevels();

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

        ok (10 == psTraceGetLevel(".A.B.C.D"),
            ".A.B.C.D did not dynamically inherit a trace level (%d)",
            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)",
            psTraceGetLevel(".A.B.C.D.E"));
        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
    }


    // testTrace03()
    {
        psMemId id = psMemGetId();
        (void)psTraceSetDestination(outFD);

        for (int i=0;i<10;i++) {
            (void)psTraceSetLevel(".", i);
            psTraceReset();
            int lev = psTraceGetLevel(".");
            ok (lev == PS_UNKNOWN_TRACE_LEVEL,
                "expected trace level was %d, actual was %d",
                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?");

        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");
        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
    }


    // testTrace04()
    {
        psMemId id = psMemGetId();
        int FD = creat("tst_psTrace02_OUT", 0666);
        for (int nb = 0 ; nb<4;nb++) {
            if (nb == 0)
                (void)psTraceSetDestination(((outFD == 2) ? 1 : outFD));
            if (nb == 1)
                (void)psTraceSetDestination(((outFD == 2) ? 2 : outFD));
            if (nb == 2)
                (void)psTraceSetDestination(((outFD == 2) ? 0 : outFD));
            if (nb == 3)
                (void)psTraceSetDestination(FD);

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

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

            (void)psTraceSetLevel(".a.b", 4);
            psTrace(".a.b", 5, "(2) This message should not be displayed (%x)",
                    0xbeefface);
            (void)psTraceSetLevel(".a.b", 7);
            psTrace(".a.b", 5, "(2) This message should be displayed (%x)",
                    0xbeefface);
            (void)psTraceSetLevel(".a.b.c", 12);
            psTrace(".a.b.c", 11, "(3) This message should be displayed (%x)",
                    0xbeefface);
        }
        close(FD);
        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
    }


    // testTrace05()
    {
        psMemId id = psMemGetId();
        (void)psTraceSetDestination(outFD);
        (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();
        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
    }


    // testTrace05a()
    {
        psMemId id = psMemGetId();
        (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();
        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
    }


    // testTrace06()
    {
        psMemId id = psMemGetId();
        (void)psTraceSetDestination(outFD);
        (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;
        }
        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
    }


    // Ensure that the leading dot in the component names are optional.
    // testTrace08()
    {
        psMemId id = psMemGetId();
        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", psTraceGetLevel("."));
            printf("psTraceGetLevel(a) is %d", psTraceGetLevel("a"));
            printf("psTraceGetLevel(b) is %d", psTraceGetLevel("b"));
            printf("psTraceGetLevel(c) is %d", psTraceGetLevel("c"));
            printf("psTraceGetLevel(a.a) is %d", psTraceGetLevel("a.a"));
            printf("psTraceGetLevel(a.b) is %d", psTraceGetLevel("a.b"));
            printf("psTraceGetLevel(b.a) is %d", psTraceGetLevel("b.a"));
            printf("psTraceGetLevel(b.b) is %d", psTraceGetLevel("b.b"));
            printf("psTraceGetLevel(c.a) is %d", psTraceGetLevel("c.a"));
            printf("psTraceGetLevel(c.b) is %d", psTraceGetLevel("c.b"));
            printf("psTraceGetLevel(c.c) is %d", psTraceGetLevel("c.c"));
            return 1;
        }
        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
    }

# if (DEBUG)
    close (outFD);
# endif

}
