
/** @file  tst_psTime_03.c
 *
 *  @brief Test driver for psTime functions
 *
 *  This test driver contains the following tests for psTime:
 *
 *   Test A - Add two times
 *   Test B - Add two times with overflow in microseconds
 *   Test C - Subtact two times
 *   Test D - Subtact two times with underflow in microseconds
 *   Test E - Delta two times
 *   Test F - Delta two times with underflow in microseconds
 *   Test G - Add two times across leapsecond boundary
 *   Test H - Find number of leapseconds added between two times
 *   Test H1 - Verify error message to invalid time type in psTimeAlloc
 *   Test G - Free data
 *
 *  @author  Ross Harman, MHPCC
 *
 *  @version $Revision: 1.12 $  $Name: not supported by cvs2svn $
 *  @date  $Date: 2005-02-17 19:26:24 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 *
 */

#include "pslib.h"
#include "psTest.h"

#define PRINT_TIME(TEXT,TIME) \
printf("%s Seconds = %lld Microseconds = %u\n", TEXT, (long long int)TIME->sec, TIME->usec);

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

    psLibInit(true,"psTime.config");

    // Test A - Add two times
    printPositiveTestHeader(stdout, "psTime", "Test A - Add two times");
    psTime *time1a = NULL;
    psF64 time1b = 1.111111;
    psTime *timeOut1 = NULL;
    time1a = psTimeAlloc(PS_TIME_TAI);
    time1a->sec  = 1;
    time1a->usec = 111111;
    timeOut1 = psTimeMath(time1a, time1b);
    if(timeOut1->sec!=2 && timeOut1->usec!=222222) {
        printf("ERROR: Incorrect time, %lld:%u. Expected 2:222222\n",(long long int)timeOut1->sec, timeOut1->usec);
    }
    printFooter(stdout, "psTime", "Test A - Add two times", true);


    // Test B - Add two times with overflow in microseconds
    printPositiveTestHeader(stdout, "psTime", "Test B - Add two times with overflow in microseconds");
    psTime *time2a = NULL;
    psF64 time2b = 5.500001;
    psTime *timeOut2 = NULL;
    time2a = psTimeAlloc(PS_TIME_TAI);
    time2a->sec  = 6;
    time2a->usec = 600001;
    timeOut2 = psTimeMath(time2a, time2b);
    if(timeOut2->sec!=12 && timeOut2->usec!=100002) {
        printf("ERROR: Incorrect time, %lld:%u. Expected 12:100002\n",(long long int)timeOut2->sec, timeOut2->usec);
    }
    printFooter(stdout, "psTime", "Test B - Add two times with overflow in microseconds", true);


    // Test C - Subtact two times
    printPositiveTestHeader(stdout, "psTime", "Test C - Subtract two times");
    psTime *time3a = NULL;
    psF64 time3b = -1.111111;
    psTime *timeOut3 = NULL;
    time3a = psTimeAlloc(PS_TIME_TAI);
    time3a->sec  = 3;
    time3a->usec = 333333;
    timeOut3 = psTimeMath(time3a, time3b);
    if(timeOut3->sec!=2 && timeOut3->usec!=222222) {
        printf("ERROR: Incorrect time, %lld:%u. Expected 2:222222\n",(long long int)timeOut3->sec, timeOut3->usec);
    }
    printFooter(stdout, "psTime", "Test C - Subtract two times", true);


    // Test D - Subtact two times with underflow in microseconds
    printPositiveTestHeader(stdout, "psTime", "Test D - Subtact two times with underflow in microseconds");
    psTime *time4a = NULL;
    psF64 time4b = -2.000003;
    psTime *timeOut4 = NULL;
    time4a = psTimeAlloc(PS_TIME_TAI);
    time4a->sec  = 5;
    time4a->usec = 1;
    timeOut4 = psTimeMath(time4a, time4b);
    if(timeOut4->sec!=2 && timeOut4->usec!=999997) {
        printf("ERROR: Incorrect time, %lld:%u. Expected 2:999997\n",(long long int)timeOut4->sec, timeOut4->usec);
    }
    printFooter(stdout, "psTime", "Test D - Subtact two times with underflow in microseconds", true);


    // Test E - Delta two times
    printPositiveTestHeader(stdout, "psTime", "Test E - Delta two times");
    psTime *time5a = NULL;
    psTime *time5b = NULL;
    psF64 timeOut5 = 0.0;
    time5a = psTimeAlloc(PS_TIME_TAI);
    time5b = psTimeAlloc(PS_TIME_TAI);
    time5a->sec  = 8;
    time5a->usec = 8;
    time5b->sec  = 7;
    time5b->usec = 7;
    timeOut5 = psTimeDelta(time5a, time5b);
    if(fabs(timeOut5-1.000001) > FLT_EPSILON) {
        printf("ERROR: Incorrect delta, %lf. Expected -1.000001\n", timeOut5);
    }
    printFooter(stdout, "psTime", "Test E - Delta two times", true);


    // Test F - Delta two times with underflow in microseconds
    printPositiveTestHeader(stdout, "psTime", "Test F - Delta two times with underflow in microseconds");
    psTime *time6a = NULL;
    psTime *time6b = NULL;
    psF64 timeOut6 = 0.0;
    time6a = psTimeAlloc(PS_TIME_TAI);
    time6b = psTimeAlloc(PS_TIME_TAI);
    time6a->sec  = 8;
    time6a->usec = 1;
    time6b->sec  = 7;
    time6b->usec = 7;
    timeOut6 = psTimeDelta(time6a, time6b);
    if(fabs(timeOut6-0.999994) > FLT_EPSILON) {
        printf("ERROR: Incorrect delta, %lf. Expected 0.999994\n", timeOut6);
    }
    printFooter(stdout, "psTime", "Test F - Delta two times with underflow in microseconds", true);

    // Test F1 - Delta two times in UTC type
    printPositiveTestHeader(stdout,"psTime","Test F1 - Delta two UTC times");
    psTime *time20a = NULL;
    psTime *time20b = NULL;
    psF64 timeOut20 = 0.0;
    time20a = psTimeAlloc(PS_TIME_UTC);
    time20b = psTimeAlloc(PS_TIME_UTC);
    time20a->sec = 1090434113;
    time20a->usec = 272044;
    time20b->sec = 1090434112;
    time20b->usec = 272044;
    timeOut20 = psTimeDelta(time20a, time20b);
    if(fabs(timeOut20-1.000000000) > FLT_EPSILON) {
        printf("ERROR: Incorrect delta, %lf. Expected -1.00000\n",timeOut20);
    }
    printFooter(stdout,"psTime","Test F1 - Delta two UTC times",true);

    // Test G - Add two times across leapsecond boundary
    printPositiveTestHeader(stdout, "psTime", "Test G - Add two times across leapsecond boundary");
    psF64 time7b = 30.0;
    char *out7 = NULL;
    psTime *time7a = NULL;
    psTime *timeOut7 = NULL;
    time7a = psTimeFromISOTime("1998-12-31T23:59:45.00");
    time7a->type = PS_TIME_UTC;
    timeOut7 = psTimeMath(time7a, time7b);
    out7 = psTimeToISOTime(timeOut7);
    printf("%s\n", out7);
    printFooter(stdout, "psTime", "Test G - Add two times across leapsecond boundary", true);


    // Test H - Find number of leapseconds added between two times
    printPositiveTestHeader(stdout, "psTime", "Test H - Find number of leapseconds added between two times");
    psS64 out = 0.0;
    psTime *time8a = NULL;
    psTime *time8b = NULL;
    time8a = psTimeFromISOTime("2004-12-18T1:00:00.00");
    time8b = psTimeFromISOTime("1972-1-1T1:00:00.00");
    out = psTimeLeapseconds(time8a, time8b);
    printf("%lld\n", (long long int)out);
    printFooter(stdout, "psTime", "Test H - Find number of leapseconds added between two times", true);

    // Test H1 - Error in allocating time not UTC or TAI
    printPositiveTestHeader(stdout,"psTime","Test H1 - Verify error message in allocating invalid time type");
    psLogMsg(__func__,PS_LOG_INFO,"Invalid time type during allocation should generate error message");
    psTime *time10 = psTimeAlloc(10);
    if(time10 != NULL) {
        printf("ERROR: returned time should be NULL\n");
    }
    printFooter(stdout,"psTime","Test H1 - Verify error message in allocating invalid time type",true);

    // Test G - Free data
    printPositiveTestHeader(stdout, "psTime", "Test I - Free data");
    psLibFinalize();
    psFree(time1a);
    psFree(timeOut1);
    psFree(time2a);
    psFree(timeOut2);
    psFree(time3a);
    psFree(timeOut3);
    psFree(time4a);
    psFree(timeOut4);
    psFree(time5a);
    psFree(time5b);
    psFree(time6a);
    psFree(time6b);
    psFree(out7);
    psFree(time7a);
    psFree(timeOut7);
    psFree(time8a);
    psFree(time8b);
    psFree(time20a);
    psFree(time20b);
    if (psMemCheckLeaks(0, NULL, stdout,false)) {
        psError(PS_ERR_UNKNOWN,true,"Memory leaks detected.");
        return 10;
    }
    psMemCheckCorruption(0);
    psS32 nBad = psMemCheckCorruption(0);
    if(nBad) {
        printf("ERROR: Found %d bad memory blocks\n", nBad);
    }
    printFooter(stdout, "psTime", "Test I - Free data", true);
    return 0;
}
