/** @file  tst_psMetadataIO.c
*
*  @brief Test driver for psMetadataIO functions
*
*  This test driver contains the following tests for psMetadata:
*    Test A - Read config file with overwrite set true
*    Test B - Read config file with overwrite set false
*    Test C - Read config file without auto-allocation of metadata
*    Test D - Attempt to use null fileName argument
*    Test E - Attempt to open nonexistant file
*    Test F - Free psMetadata
*
*  @author  Ross Harman, MHPCC
*
*  @version $Revision: 1.8 $  $Name: not supported by cvs2svn $
*  @date  $Date: 2005-02-03 00:54:12 $
*
*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
*
*/

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

static void printMetadataItem(psMetadataItem *metadataItem, char *spaces);
static void printMetadata(psMetadata *metadata);
static void printMetadataList(psList *metadataItemList, char* spaces);
static void printMetadataTable(psHash *mdTable);

static void printMetadata(psMetadata *metadata)
{
    printf("Contents of metadata list:\n");
    printMetadataList(metadata->list, " ");
    printf("\nContents of metadata table:\n");
    printMetadataTable(metadata->table);
}

static void printMetadataList(psList *metadataItemList, char* spaces)
{
    psMetadataItem *entryChild = NULL;

    psListIterator* iter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);

    while ( (entryChild=psListGetAndIncrement(iter)) != NULL) {
        printMetadataItem(entryChild, spaces);
    }

    psFree(iter);
}

static void printMetadataTable(psHash *mdTable)
{
    psS32 i;
    psHashBucket* ptr = NULL;
    for(i=0; i<mdTable->nbucket; i++) {
        ptr = mdTable->buckets[i];
        while (ptr != NULL) {
            printMetadataItem(ptr->data, " ");
            ptr = ptr->next;
        }
    }
}

static void printMetadataItem(psMetadataItem *metadataItem, char *spaces)
{
    printf("%sKey Name: %8s  ", spaces, metadataItem->name);
    printf("Key pType: %d  ", metadataItem->pType);
    printf("Key mdType: %d  ", metadataItem->type);

    switch (metadataItem->type) {
    case PS_META_LIST:
        printf("Key Value: %17c", ' ');
        break;
    case PS_META_PRIMITIVE:
        switch(metadataItem->pType) {
        case PS_TYPE_BOOL:
            printf("Key Value: %15d  ", metadataItem->data.B);
            break;
        case PS_TYPE_S32:
            printf("Key Value: %15d  ", metadataItem->data.S32);
            break;
        case PS_TYPE_F32:
            printf("Key Value: %15.3f  ", metadataItem->data.F32);
            break;
        case PS_TYPE_F64:
            printf("Key Value: %15.3f  ", metadataItem->data.F64);
            break;
        default:
            printf("Bad type: %d ", metadataItem->pType);
        }
        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);

    if(metadataItem->data.V && metadataItem->type==PS_META_LIST) {
        printMetadataList(metadataItem->data.V, "    ");
    }
}


psS32 main(psS32 argc, char* argv[])
{
    // Test A - Read config file with overwrite set true
    printPositiveTestHeader(stdout, "psMetadata", "Test A - Read config file with overwrite set true");
    psMetadata *metadata1 = NULL;
    psU32 failedLines1 = 0;
    metadata1 = psMetadataParseConfig(metadata1, &failedLines1, "test.config", true);
    printf("Failed lines: %d Expected: 6\n", failedLines1);
    printMetadata(metadata1);
    printFooter(stdout, "psMetadata", "Test A - Read config file with overwrite set true", true);


    // Test B - Read config file with overwrite set false
    printPositiveTestHeader(stdout, "psMetadata", "Test B - Read config file with overwrite set false");
    psMetadata *metadata2 = NULL;
    psS32 failedLines2 = 0;
    metadata2 = psMetadataParseConfig(metadata2, &failedLines2, "test.config", false);
    printf("Failed lines: %d Expected: 7 ", failedLines2);
    printMetadata(metadata2);
    printFooter(stdout, "psMetadata", "Test B - Read config file with overwrite set false", true);


    // Test C - Read config file without auto-allocation of metadata
    printPositiveTestHeader(stdout, "psMetadata", "Test C - Read config file without auto-allocation of metadata");
    psMetadata *metadata3 = psMetadataAlloc();
    psS32 failedLines3 = 0;
    metadata3 = psMetadataParseConfig(metadata3, &failedLines3, "test.config", true);
    printf("Failed lines: %d Expected: 6 ", failedLines3);
    printMetadata(metadata3);
    printFooter(stdout, "psMetadata", "Test C - Read config file without auto-allocation of metadata", true);


    // Test D - Attempt to use null fileName argument
    printNegativeTestHeader(stdout,"psMetadataIO", "Test D - Attempt to use null fileName argument",
                            "Null failedLines not allowed", 0);
    psMetadataParseConfig(metadata1, &failedLines1, NULL, true);
    printFooter(stdout, "psMetadata", "Test D - Attempt to use null fileName argument", true);


    // Test E - Attempt to open nonexistant file
    printNegativeTestHeader(stdout,"psMetadataIO", "Test E - Attempt to open nonexistant file",
                            "Error opening file", 0);
    psMetadataParseConfig(metadata1, &failedLines1, "abcedfg", true);
    printFooter(stdout, "psMetadata", "Test E - Attempt to open nonexistant file", true);


    // Test F - Free psMetadata
    printPositiveTestHeader(stdout, "psMetadata", "Test F - Free psMetadata");
    psFree(metadata1);
    psFree(metadata2);
    psFree(metadata3);
    if(psMemCheckLeaks(0, NULL, stdout,false)) {
        psError(PS_ERR_UNKNOWN,true,"Memory leak detected");
        return 10;
    }
    psMemCheckCorruption(0);
    psS32 nBad = psMemCheckCorruption(0);
    if(nBad) {
        printf("ERROR: Found %d bad memory blocks\n", nBad);
    }
    printFooter(stdout, "psMetadata", "Test F - Free psMetadata", true);


    return 0;
}
