

/** @file  tst_psMetadata_05.c
*
*  @brief Test driver for psMetadata functions
*
*  This test driver contains the following tests for psMetadata:
*     Test A - Allocate metadata and items
*     Test B - Set iterator at second index
*     Test C - Get next item at index
*     Test D - Get next item at index and string
*     Test E - Get previous item at index
*     Test F - Write metadata item to file
*     Test G - Attempt to use null metadata with setIterator
*     Test H - Attempt to use null metadata with getNext
*     Test I - Attempt to use null metadata with getPrevious
*     Test J - Attempt to use null file with itemPrint
*     Test K - Attempt to use null format with itemPrint
*     Test L - Attempt to use null item with itemPrint
*     Test M - Free psMetadata
*
*  @author  Ross Harman, MHPCC
*
*  @version $Revision: 1.24 $  $Name: not supported by cvs2svn $
*  @date  $Date: 2005-04-07 20:27:41 $
*
*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
*
*/

#include <string.h>
#include "pslib_strict.h"
#include "psTest.h"

static void printMetadataItem(psMetadataItem *metadataItem)
{
    printf("Key Name: %8s  ", metadataItem->name);
    printf("Key mdType: 0x%08x  ", metadataItem->type);

    switch (metadataItem->type) {
    case PS_META_MULTI:
        printf("Key Value: %17c", ' ');
        break;
    case PS_META_BOOL:
        printf("Key Value: %15d  ", metadataItem->data.B);
        break;
    case PS_META_S32:
        printf("Key Value: %15d  ", metadataItem->data.S32);
        break;
    case PS_META_F32:
        printf("Key Value: %15.3f  ", metadataItem->data.F32);
        break;
    case PS_META_F64:
        printf("Key Value: %15.3f  ", metadataItem->data.F64);
        break;
    case PS_META_STR:
        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
        break;
    default:
        printf("Bad type: %d ", metadataItem->type);
    }
    printf("Key Comment: %s\n", metadataItem->comment);
}


psS32 main( psS32 argc, char* argv[] )
{
    psMetadataItem *item1 = NULL;
    psMetadataItem *item2 = NULL;
    psMetadataItem *item3 = NULL;
    psMetadataItem *item4 = NULL;
    psMetadataItem *item5 = NULL;
    psMetadataItem *item6 = NULL;
    psMetadataItem *item7 = NULL;
    //    psMetadataItem *item8 = NULL;
    psMetadata *metadata = NULL;
    FILE *fd = NULL;

    // Test A - Allocate metadata and items
    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
    metadata = psMetadataAlloc();
    item1 = psMetadataItemAlloc("myItem1", PS_META_BOOL, "I am a boolean", true);
    item2 = psMetadataItemAlloc("myItem2", PS_META_S32, "I am a integer", 55);
    item3 = psMetadataItemAlloc("myItem3", PS_META_BOOL, "I am a boolean", false);
    item4 = psMetadataItemAlloc("myItem4", PS_META_S32, "I am a integer", 66);
    item5 = psMetadataItemAlloc("myItem5", PS_META_F32, "I am a float", 3.14);
    item6 = psMetadataItemAlloc("myItem6", PS_META_F64,"I am a double", 6.28);
    item7 = psMetadataItemAlloc("myItem7", PS_META_STR, "I am a string", "GNIRTS");
    //    item8 = psMetadataItemAlloc("myItem8", PS_TYPE_PTR, PS_META_UNKNOWN, "I am unknown");
    printMetadataItem(item1);
    printMetadataItem(item2);
    printMetadataItem(item3);
    printMetadataItem(item4);
    psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT);
    psMetadataAddItem(metadata, item2, PS_LIST_HEAD, PS_META_DEFAULT);
    psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT);
    psMetadataAddItem(metadata, item4, PS_LIST_HEAD, PS_META_DEFAULT);
    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);

    /*
        // Test B - Set iterator at second index
        printPositiveTestHeader(stdout, "psMetadata", "Test B - Set iterator at second index");
        if (!psMetadataSetIterator(metadata, 2)) {
            psError(PS_ERR_UNKNOWN,true,"Failed to set iterator");
            return 100;
        }
        printFooter(stdout, "psMetadata", "Test B - Set iterator at second index", true);


        // Test C - Get next item at index
        printPositiveTestHeader(stdout, "psMetadata", "Test C - Get next item at index");
        item = psMetadataGetNext(metadata, NULL, 2);
        if(item == NULL) {
            printf("ERROR: Item should not be null\n");
        } else {
            printf("Found item named %s\n", item->name);
        }
        printFooter(stdout, "psMetadata", "Test C - Get next item at index", true);


        // Test D - Get next item at index and string
        printPositiveTestHeader(stdout, "psMetadata", "Test D - Get next item at index and string");
        item = psMetadataGetNext(metadata, "myItem1", 1);
        if(item == NULL) {
            printf("ERROR: Item should not be null\n");
        } else {
            printf("Found item named %s\n", item->name);
        }
        printFooter(stdout, "psMetadata", "Test D - Get next item at index and string", true);


        // Test E - Get previous item at index
        printPositiveTestHeader(stdout, "psMetadata", "Test E - Get previous item at index");
        item = psMetadataGetPrevious(metadata, NULL, 1);
        if(item == NULL) {
            printf("ERROR: Item should not be null\n");
        } else {
            printf("Found item named %s\n", item->name);
        }
        if( psMetadataGetPrevious(metadata,"myItem3",1) == NULL) {
            psError(PS_ERR_UNKNOWN, true,"psMetadataGetPrevious did not return an item from metadata.");
            return 45;
        }
        tmpList = metadata->list;
        metadata->list = NULL;
        if ( psMetadataGetPrevious(metadata,NULL,1) != NULL) {
            psError(PS_ERR_UNKNOWN, true,"psMetadataGetPrevious did not return null for invalid metadata.");
            return 50;
        }
        metadata->list = tmpList;
        printFooter(stdout, "psMetadata", "Test E - Get previous item at index", true);

    */
    // Test F - Write metadata item to file
    printPositiveTestHeader(stdout, "psMetadata", "Test F - Write metadata item to file");
    fd = fopen("temp/tst_psMetadata05_OUT", "w");
    if(fd == NULL) {
        printf("ERROR: Couldn't open file for writing\n");
    }

    if (psMetadataItemPrint(fd, "S32 = %ld\n", item2) == false) {
        printf("ERROR: Return type should be true\n");
        return 10;
    }

    if (psMetadataItemPrint(fd, "S32 = %+06.1f\n", item2) == false) {
        printf("ERROR: Return type should be true\n");
        return 10;
    }

    if (psMetadataItemPrint(fd, "BOL = %ld\n", item3) == false) {
        printf("ERROR: Return type should be true\n");
        return 11;
    }

    if (psMetadataItemPrint(fd, "F32 = %g\n", item5) == false) {
        printf("ERROR: Return type should be true\n");
        return 12;
    }

    if (psMetadataItemPrint(fd, "F32 = % #i\n", item5) == false) {
        printf("ERROR: Return type should be true\n");
        return 12;
    }

    if (psMetadataItemPrint(fd, "F64 = %g\n", item6) == false) {
        printf("ERROR: Return type should be true\n");
        return 13;
    }

    if (psMetadataItemPrint(fd, "STR = %s\n", item7) == false) {
        printf("ERROR: Return type should be true\n");
        return 14;
    }
    //    psLogMsg(__func__,PS_LOG_INFO,"Attempt to print item of invalid type, should generate error message");
    //    if (psMetadataItemPrint(fd, "UNK = \n", item8) == true) {
    //        printf("ERROR: Return type should be false\n");
    //        fclose(fd);
    //        return 15;
    //    }
    fclose(fd);

    fd = fopen("temp/tst_psMetadata05_OUT", "r");
    if(fd == NULL) {
        printf("ERROR: Couldn't open file for reading\n");
    }

    char line[256];
    char truth1[] = "S32 = 55";
    fgets(line, 256, fd);
    if(strncmp(line, truth1, 8)) {
        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth1);
    }

    char truth1b[] = "S32 = +055.0";
    fgets(line, 256, fd);
    if(strncmp(line, truth1b, 12)) {
        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth1b);
    }

    char truth2[] = "BOL = 0";
    fgets(line, 256, fd);
    if(strncmp(line, truth2, 7)) {
        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth2);
    }

    char truth3[] = "F32 = 3.14";
    fgets(line, 256, fd);
    if(strncmp(line, truth3, 10)) {
        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth3);
    }

    char truth3b[] = "F32 =  3";
    fgets(line, 256, fd);
    if(strncmp(line, truth3b, 8)) {
        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth3b);
    }

    char truth4[] = "F64 = 6.28";
    fgets(line, 256, fd);
    if(strncmp(line, truth4, 10)) {
        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth4);
    }

    char truth5[] = "STR = GNIRTS";
    fgets(line, 256, fd);
    if(strncmp(line, truth5, 12)) {
        printf("ERROR: Data in file is not as expected. Value: %s. Should be: %s\n", line, truth5);
    }

    fclose(fd);
    printFooter(stdout, "psMetadata", "Test F - Write metadata item to file", true);
    /*
        // Test G - Attempt to use null metadata with setIterator
        printNegativeTestHeader(stdout,"psMetadata", "Test G - Attempt to use null metadata with setIterator",
                                "Null metadata collection not allowed", 0);
        if( psMetadataSetIterator(NULL, 0)) {
            psError(PS_ERR_UNKNOWN,true,"Set iterator did not detect invalid parameter.");
            return 101;
        }
        tmpList = metadata->list;
        metadata->list = NULL;
        if( psMetadataSetIterator(metadata,0)) {
            psError(PS_ERR_UNKNOWN,true,"Set iterator did not detect null list.");
            return 102;
        }
        metadata->list = tmpList;
        printFooter(stdout, "psMetadata", "Test G - Attempt to use null metadata with setIterator", true);


        // Test H - Attempt to use null metadata with getNext
        printNegativeTestHeader(stdout,"psMetadata", "Test H - Attempt to use null metadata with getNext",
                                "Null metadata collection not allowed", 0);
        if( psMetadataGetNext(NULL, "myItem2", 0) != NULL ) {
            psError(PS_ERR_UNKNOWN, true,"psMetadataGetNext did not return null for null metadata.");
            return 40;
        }
        tmpList = metadata->list;
        metadata->list = NULL;
        if ( psMetadataGetNext(metadata, "myItem2", 0) != NULL ) {
            psError(PS_ERR_UNKNOWN, true,"psMetadataGetNext did not return null for invalid metadata.");
            return 41;
        }
        metadata->list = tmpList;

        printFooter(stdout, "psMetadata", "Test H - Attempt to use null metadata with getNext", true);


        // Test I - Attempt to use null metadata with getPrevious
        printNegativeTestHeader(stdout,"psMetadata", "Test I - Attempt to use null metadata with getPrevious",
                                "Null metadata collection not allowed", 0);
        psMetadataGetPrevious(NULL, "myItem2", 0);
        printFooter(stdout, "psMetadata", "Test I - Attempt to use null metadata with getPrevious", true);

    */
    // Test J - Attempt to use null file with itemPrint
    printNegativeTestHeader(stdout,"psMetadata", "Test J - Attempt to use null file with itemPrint",
                            "Null file descriptor not allowed", 0);
    psMetadataItemPrint(NULL, "Item value: %ld", item2);
    printFooter(stdout, "psMetadata", "Test J - Attempt to use null file with itemPrint", true);


    // Test K - Attempt to use null format with itemPrint
    printNegativeTestHeader(stdout,"psMetadata", "Test K - Attempt to use null format with itemPrint",
                            "Null format not allowed", 0);
    psMetadataItemPrint(fd, NULL, item2);
    printFooter(stdout, "psMetadata", "Test K - Attempt to use null format with itemPrint", true);


    // Test L - Attempt to use null item with itemPrint
    printNegativeTestHeader(stdout,"psMetadata", "Test L - Attempt to use null item with itemPrint",
                            "Null metadata not allowed", 0);
    psMetadataItemPrint(fd, "Item value: %ld", NULL);
    printFooter(stdout, "psMetadata", "Test L - Attempt to use null item with itemPrint", true);


    // Test M - Free psMetadata
    printPositiveTestHeader(stdout, "psMetadata", "Test M - Free psMetadata");
    psFree(metadata);
    psFree(item1);
    psFree(item2);
    psFree(item3);
    psFree(item4);
    psFree(item5);
    psFree(item6);
    psFree(item7);
    //    psFree(item8);
    if ( psMemCheckLeaks(0, NULL, stdout, false) != 0 ) {
        psError(PS_ERR_UNKNOWN, true,"Memory leaks detected.");
        return 50;
    }
    psMemCheckCorruption(0);
    psS32 nBad = psMemCheckCorruption(0);
    if(nBad) {
        printf("ERROR: Found %d bad memory blocks\n", nBad);
        return 51;
    }
    printFooter(stdout, "psMetadata", "Test M - Free psMetadata", true);


    return 0;
}
