/** @file  tst_psMetadata_03.c
*
*  @brief Test driver for psMetadata functions
*
*  This test driver contains the following tests for psMetadata:
*     Test A - Allocate metadata and items
*     Test B - Remove items from metadata by name
*     Test C - Remove items from metadata by index
*     Test D - Attempt to use null metadata
*     Test E - Attempt to remove non-existant metadata item by name
*     Test F - Attempt to remove non-existant metadata item by index
*     Test G - Attempt to add item to an invalid metadata structure
*     Test H - Attempt to add item to an invalid metadata structure
*     Test I - Attempt to add item with a null name
*     Test J - Attempt to add item to an invalid metadata structure
*     Test K - Free psMetadata
*
*  @author  Ross Harman, MHPCC
*
*  @version $Revision: 1.3 $  $Name: not supported by cvs2svn $
*  @date  $Date: 2005-09-26 21:13:33 $
*
*  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_DATA_METADATA_MULTI:
        printf("Key Value: %17c", ' ');
        break;
    case PS_DATA_BOOL:
        printf("Key Value: %15d  ", metadataItem->data.B);
        break;
    case PS_DATA_S32:
        printf("Key Value: %15d  ", metadataItem->data.S32);
        break;
    case PS_DATA_F32:
        printf("Key Value: %15.3f  ", metadataItem->data.F32);
        break;
    case PS_DATA_F64:
        printf("Key Value: %15.3f  ", metadataItem->data.F64);
        break;
    case PS_DATA_STRING:
        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 *errItem = NULL;
    psMetadata *metadata = NULL;
    psMetadata *errMetadata = NULL;
    psHash *mdTable = NULL;
    psList *mdList = NULL;
    char *errName = NULL;

    // Test A - Allocate metadata and items
    printPositiveTestHeader(stdout, "psMetadata", "Test A - Allocate metadata items");
    metadata = psMetadataAlloc();
    item1 = psMetadataItemAlloc("myItem1", PS_DATA_BOOL, "I am a boolean", true);
    item2 = psMetadataItemAlloc("myItem2", PS_DATA_S32, "I am a integer", 55);
    item3 = psMetadataItemAlloc("myItem3", PS_DATA_BOOL, "I am a boolean", false);
    item4 = psMetadataItemAlloc("myItem4", PS_DATA_S32, "I am a integer", 66);
    errItem = psMetadataItemAlloc("errItem", PS_DATA_S32, "I am a integer", 99);
    printMetadataItem(item1);
    printMetadataItem(item2);
    printMetadataItem(item3);
    printMetadataItem(item4);
    printFooter(stdout, "psMetadata", "Test A - Allocate metadata items", true);


    // Test B - Remove items from metadata by name
    printPositiveTestHeader(stdout, "psMetadata", "Test B - Remove items from metadata by name");
    if(!psMetadataAddItem(metadata, item1, PS_LIST_HEAD, PS_META_DEFAULT)) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by name.");
        return 10;
    }
    if(!psMetadataAdd(metadata,PS_LIST_HEAD,"myItem2", PS_DATA_S32, "I am S32 integer",77)) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by name.");
        return 11;
    }
    if (!psMetadataRemove(metadata, 0, "myItem1")) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return true when removing by name.");
        return 12;
    }
    if (!psMetadataRemove(metadata, 0, "myItem2")) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return true when removing by name.");
        return 13;
    }
    printFooter(stdout, "psMetadata", "Test B - Remove items from metadata by name", true);


    // Test C - Remove items from metadata by index
    printPositiveTestHeader(stdout, "psMetadata", "Test C - Remove items from metadata by index");
    if ( ! psMetadataAddItem(metadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by index.");
        return 14;
    }
    if ( ! psMetadataAdd(metadata,PS_LIST_HEAD,"myItem4", PS_DATA_S32, "I am S32 integer",88) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return true when adding by index.");
        return 15;
    }
    if( ! psMetadataRemove(metadata, 0, NULL) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return true when removing by index.");
        return 16;
    }
    if ( ! psMetadataRemove(metadata, 0, NULL ) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return true when removing by index.");
        return 17;
    }
    printFooter(stdout, "psMetadata", "Test C - Remove items from metadata by index", true);


    // Test D - Attempt to use null metadata
    printNegativeTestHeader(stdout,"psMetadata", "Test D - Attempt to use null metadata",
                            "Null metadata collection not allowed", 0);
    if ( psMetadataRemove(NULL, 0, NULL) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false when removing from null metadata.");
        return 18;
    }
    printFooter(stdout, "psMetadata", "Test D - Attempt to use null metadata", true);


    // Test E - Attempt to remove non-existant metadata item by name
    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to remove non-existant metadata item by name",
                            "Couldn't find metadata item. Name: AARGH", 0);
    if( psMetadataRemove(metadata, 0, "AARGH") ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false when removing non-existant item.");
        return 19;
    }
    printFooter(stdout, "psMetadata", "Test E - Attempt to remove non-existant metadata item by name", true);


    // Test F - Attempt to remove non-existant metadata item by index
    printNegativeTestHeader(stdout,"psMetadata", "Test E - Attempt to remove non-existant metadata item by index",
                            "Couldn't find metadata item in list. Index: 22", 0);
    if( psMetadataRemove(metadata, 22, NULL) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false when removing non-existant item.");
        return 20;
    }
    printFooter(stdout, "psMetadata", "Test E - Attempt to remove non-existant metadata item by index", true);


    // Test G - Attempt to add item to an invalid metadata structure
    printNegativeTestHeader(stdout,"psMetadata","Test G - Attempt to add item to metadata w/o hash table",
                            "Couldn't add item to invalid metadata structure.",0);
    errMetadata = psMetadataAlloc();
    mdTable = errMetadata->hash;
    errMetadata->hash = NULL;
    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o hash table.");
        return 21;
    }
    if ( psMetadataRemove(errMetadata, PS_LIST_HEAD, "errItem") ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false w/ invalid metadata struct w/o hash table.");
        return 31;
    }
    errMetadata->hash = mdTable;
    printFooter(stdout,"psMetadata","Test G - Attempt to add item to invalid metadata w/o hash table", true);

    // Test H - Attempt to add item to an invalid metadata structure
    printNegativeTestHeader(stdout,"psMetadata","Test H - Attempt to add item to metadata w/o link list",
                            "Couldn't add item to invalid metadata structure.",0);
    mdList = errMetadata->list;
    errMetadata->list = NULL;
    if ( psMetadataAddItem(errMetadata, item3, PS_LIST_HEAD, PS_META_DEFAULT) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o link list.");
        return 22;
    }
    if ( psMetadataRemove(errMetadata, PS_LIST_HEAD, "errItem") ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataRemove did not return false w/ invalid metadata struct w/o link list.");
        return 32;
    }
    errMetadata->list = mdList;
    printFooter(stdout,"psMetadata","Test H - Attempt to add item to invalid metadata w/o link list", true);

    // Test I - Attempt to add item with a null name
    printNegativeTestHeader(stdout,"psMetadata","Test I - Attempt to add item with null name",
                            "Couldn't add item with null name.",0);
    errName = errItem->name;
    errItem->name = NULL;
    if ( psMetadataAddItem(errMetadata, errItem, PS_LIST_HEAD, PS_META_DEFAULT) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false with item with null name.");
        return 23;
    }
    errItem->name = errName;
    printFooter(stdout,"psMetadata","Test I - Attempt to add item with null name", true);

    // Test J - Attempt to add item to an invalid metadata structure
    printNegativeTestHeader(stdout,"psMetadata","Test J - Attempt to add item to metadata w/o hash table",
                            "Couldn't add item to invalid metadata structure.",0);
    mdTable = errMetadata->hash;
    errMetadata->hash = NULL;
    if (psMetadataAdd(errMetadata, PS_LIST_HEAD, "errItem", PS_DATA_S32, "Integer",22) ) {
        psError(PS_ERR_UNKNOWN, true,"psMetadataAddItem did not return false w/ invalid metadata struct w/o hash table.");
        return 24;
    }
    errMetadata->hash = mdTable;
    printFooter(stdout,"psMetadata","Test J - Attempt to add item to invalid metadata w/o hash table", true);

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


    return 0;
}
