/** @file  tst_psMetadata_01.c
*
*  @brief Test driver for psMetadata functions
*
*  @author  dRob, MHPCC
*
*  @version $Revision: 1.8 $  $Name: not supported by cvs2svn $
*  @date  $Date: 2006-06-10 02:28:17 $
*
*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
*
*/

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

static psS32 testMetadataItemCopy(void);
static psS32 testMetadataPrint(void);

testDescription tests[] = {
                              {testMetadataItemCopy, 666, "psMetadataItemCopy()", 0, false},
                              {testMetadataPrint,667,"psMetadataPrint",0,false},
                              {NULL}
                          };

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

    return ( !runTestSuite(stderr,"psMetadata_01",tests,argc,argv) );

}

psS32 testMetadataItemCopy(void)
{
    psMetadataItem *item = psMetadataItemAlloc("metaITEM", PS_DATA_S32, "no Comment");
    item->data.S32 = 666;
    psMetadataItem *item2 = NULL;

    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
    item2 = psMetadataItemCopy(NULL);
    if (item2 != NULL) {
        psError(PS_ERR_BAD_PARAMETER_NULL, false,
                "psMetadataItemCopy failed to return NULL for NULL input psMetadataItem.\n");
        return 1;
    }

    //Simple copy of psS32 data
    item2 = psMetadataItemCopy(item);
    if (item2 == NULL) {
        psError(PS_ERR_BAD_PARAMETER_NULL, false,
                "psMetadataItemCopy incorrectly returned NULL for valid input psMetadataItem.\n");
        return 2;
    }
    if ( strncmp(item2->name, item->name, 10) || item2->type != item->type ||
            item2->data.S32 != item->data.S32 || strncmp(item2->comment, item->comment, 15) ) {
        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
                "psMetadataItemCopy returned an incorrect psMetadataItem (S32 test).\n");
        return 3;
    }
    psFree(item2);
    psFree(item);
    item2 = NULL;

    //Copy of MetadataItem containing a psMetadata
    psMetadata* metadata = psMetadataAlloc();
    psMetadataAddS32(metadata, PS_LIST_TAIL, "item01", 0, "", 55);
    psMetadataAddF32(metadata, PS_LIST_TAIL, "item02", 0, NULL, 3.14);
    item = psMetadataItemAlloc("metaItem2", PS_DATA_METADATA, "newMeta", metadata);
    item2 = psMetadataItemCopy(item);
    if (item2 == NULL || item2->data.md == NULL) {
        psError(PS_ERR_BAD_PARAMETER_NULL, false,
                "psMetadataItemCopy returned either a NULL item or NULL metadata data\n");
        return 4;
    }
    if ( strncmp(item2->name, item->name, 11) || item2->type != item->type ||
            strncmp(item2->comment, item->comment, 15) ) {
        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
                "psMetadataItemCopy returned an incorrect psMetadataItem (Metadata test).\n");
        return 5;
    }
    psMetadataItem *temp1 = psMetadataGet(item->data.md, PS_LIST_HEAD);
    psMetadataItem *temp2 = psMetadataGet(item2->data.md, PS_LIST_HEAD);
    if ( strncmp(temp2->name, temp1->name, 10) || temp2->type != temp1->type ||
            temp2->data.S32 != temp1->data.S32 || strncmp(temp2->comment, temp1->comment, 15) ) {
        psError(PS_ERR_BAD_PARAMETER_VALUE, false,
                "psMetadataItemCopy incorrectly returned non-matching metadata data.\n");
        return 6;
    }

    psFree(item2);
    psFree(metadata);
    psFree(item);
    return 0;
}

static psMetadata *setupMeta2(void)
{
    psMetadata *md = NULL;
    psVector *vec = NULL;
    psMetadata *newMD = NULL;
    psTime *time;
    int i = 0;
    md = psMetadataAlloc();
    newMD = psMetadataAlloc();
    vec = psVectorAlloc(60, PS_DATA_S32);
    time = psTimeAlloc(PS_TIME_TAI);
    for (i = 0; i < 5; i++) {
        vec->data.S32[i] = i+1;
    }
    vec->n = 5;
    time->sec = 1000;
    time->nsec = 25;
    time->leapsecond = true;
    psMetadataAddBool(md, PS_LIST_TAIL, "item1", 0, "I am a boolean", true);
    psMetadataAddS32(md, PS_LIST_TAIL, "item2", 0, "I am a integer", 55);
    psMetadataAddF32(md, PS_LIST_TAIL, "item3", 0, NULL, 3.14);
    psMetadataAddF64(md, PS_LIST_TAIL, "item4", 0, "", 6.28);
    psMetadataAddStr(md, PS_LIST_TAIL, "item5", 0, "I am a string", "GNIRTS");
    psMetadataAddVector(md, PS_LIST_TAIL, "vector6", 0, "I am a vector", vec);
    psMetadataAddTime(md, PS_LIST_TAIL, "time01", 0, "I am time", time);
    psMetadataAddS8(md, PS_LIST_TAIL, "item6", 0, "I am S8", 6);
    psMetadataAddS16(md, PS_LIST_TAIL, "item7", 0, "I am S16", -666);
    psMetadataAddU8(md, PS_LIST_TAIL, "item8", 0, "I am U8", 6);
    psMetadataAddU16(md, PS_LIST_TAIL, "item9", 0, "I am U16", 666);
    psMetadataAddU32(md, PS_LIST_TAIL, "item10", 0, "I am U32", 666);
    psMetadataAddS64(md, PS_LIST_TAIL, "item11", 0, "I am S64", 666);
    psMetadataAddU64(md, PS_LIST_TAIL, "item12", 0, "I am U64", 666);

    psMetadataAddS32(newMD, PS_LIST_TAIL, "ITEM01", 0, NULL, 666);
    psMetadata *newestMD = NULL;
    newestMD = psMetadataAlloc();
    psMetadataAddVector(newestMD, PS_LIST_TAIL, "VECTORNEW", 0, "Newest VECTOR", vec);
    psMetadataAddStr(newestMD, PS_LIST_TAIL, "cell", 0, "I am a p-Star", "pStArRs");
    psMetadataAddMetadata(newMD, PS_LIST_TAIL, "META NEW", 0, "I AM Newest METADATA", newestMD);
    psMetadataAddF32(newMD, PS_LIST_TAIL, "ITEM02", 0, "I AM FLOAT", 666.6);
    psMetadataAddF64(newMD, PS_LIST_TAIL, "ITEM03", 0, "I AM DOUBLE", 666.666);

    psMetadataAddMetadata(md, PS_LIST_TAIL, "metadata7", 0, "I am a metadata", newMD);
    psFree(time);
    psFree(newestMD);
    psFree(vec);
    psFree(newMD);
    return md;
}

psS32 testMetadataPrint(void)
{
    psMetadata *meta = NULL;
    meta = setupMeta2();
    psMetadataPrint(NULL, meta, 0);
    psFree(meta);
    return 0;
}
