Index: /trunk/psLib/test/types/tap_psMetadata_copying.c
===================================================================
--- /trunk/psLib/test/types/tap_psMetadata_copying.c	(revision 8375)
+++ /trunk/psLib/test/types/tap_psMetadata_copying.c	(revision 8375)
@@ -0,0 +1,464 @@
+
+#include "pstap.h"
+
+void testMetadataCopy(void);
+void testMetadataItemCopy(void);
+void testMetadataItemTransfer(void);
+
+int main(void)
+{
+    plan_tests(32);
+
+    diag("psMetadataCopy and psMetadataItemCopy tests");
+
+    testMetadataCopy();
+    testMetadataItemCopy();
+    testMetadataItemTransfer();
+
+    done();
+}
+
+void testMetadataCopy(void)
+{
+    diag("\n  >>>Test 1:  psMetadataCopy");
+    psMetadata *in = NULL;
+    psMetadata *out = NULL;
+    psMetadataItem *tempItem = NULL;
+    psMetadataItem *outItem = NULL;
+    psMetadataItem *inItem = NULL;
+
+    //Return NULL for NULL psMetadata input
+    {
+        ok( psMetadataCopy(out, NULL) == NULL,
+            "psMetadataCopy:  return NULL for NULL input metadata.");
+    }
+    //Return NULL for NULL psMetadata input->list
+    in = psMetadataAlloc();
+    if (in->list != NULL) {
+        psFree(in->list);
+        in->list = NULL;
+    }
+    {
+        ok( psMetadataCopy(out, in) == NULL,
+            "psMetadataCopy:  return NULL for NULL metadata input->list.");
+    }
+    //Return valid (but empty) metadata for NULL out input and empty input metadata.
+    in->list = psListAlloc(NULL);
+    psFree(in);
+    in = psMetadataAlloc();
+    out = psMetadataCopy(out, in);
+    tempItem = psMetadataGet(in, PS_LIST_HEAD);
+    {
+        ok( out != NULL && tempItem == NULL,
+            "psMetadataCopy:  return empty copy with no items for empty input metadata.");
+    }
+
+    //Test case: multiCheckItem->type == PS_DATA_METADATA_MULTI
+    psMetadataAddS32(in, PS_LIST_HEAD, "S32", 0, "", 1);
+    psMetadataAddS32(in, PS_LIST_TAIL, "S32", PS_META_DUPLICATE_OK, "", 1);
+    out = psMetadataCopy(out, in);
+    tempItem = psMetadataGet(out, PS_LIST_HEAD);
+    {
+        ok( tempItem->type == PS_DATA_S32 && tempItem->data.S32 == 1,
+            "psMetadataCopy:  return valid copy for a PS_DATA_METADATA_MULTI entry.");
+    }
+
+    //Test case:  !psMetadataAddItem(out, newItem, PS_LIST_TAIL, flag)
+    //XXX: doesn't seem to be easily reachable, certainly by the user...  Skipping.
+
+    //Test case: simple valid test
+    psFree(in);
+    psFree(out);
+    in = psMetadataAlloc();
+    psMetadataAddS32(in, PS_LIST_HEAD, "S32", 0, "", 666);
+    out = psMetadataCopy(out, in);
+    outItem = psMetadataGet(out, PS_LIST_HEAD);
+    inItem = psMetadataGet(in, PS_LIST_HEAD);
+    {
+        ok( outItem->type == PS_DATA_S32 && outItem->data.S32 == inItem->data.S32 &&
+            (strncmp(inItem->name, outItem->name, 10) == 0),
+            "psMetadataCopy:  return valid copy of metadata with 1 S32 entry.");
+    }
+    //Check for Memory Leaks
+    {
+        psFree(out);
+        checkMem();
+    }
+
+}
+
+void testMetadataItemCopy(void)
+{
+    diag("\n  >>>Test 2:  psMetadataItemCopy");
+
+    //Return NULL for NULL input psMetadataItem
+    {
+        ok( psMetadataItemCopy(NULL) == NULL,
+            "psMetadataItemCopy:  return NULL for NULL input metadataItem.");
+    }
+
+    //Test Simple types:  Bool, S8, S16, S32, S64, U8, U16, U32, U64, F32, F64, STRING
+    psMetadataItem *itemBool = psMetadataItemAlloc("itemBool", PS_DATA_BOOL, "", false);
+    psMetadataItem *itemS8  =  psMetadataItemAlloc("itemS8", PS_DATA_S8, "", 1);
+    psMetadataItem *itemS16 =  psMetadataItemAlloc("itemS16", PS_DATA_S16, "", 2);
+    psMetadataItem *itemS32 =  psMetadataItemAlloc("itemS32", PS_DATA_S32, "", 3);
+    psMetadataItem *itemS64 =  psMetadataItemAlloc("itemS64", PS_DATA_S64, "", 4);
+    psMetadataItem *itemU8  =  psMetadataItemAlloc("itemU8", PS_DATA_U8, "", 1);
+    psMetadataItem *itemU16 =  psMetadataItemAlloc("itemU16", PS_DATA_U16, "", 2);
+    psMetadataItem *itemU32 =  psMetadataItemAlloc("itemU32", PS_DATA_U32, "", 3);
+    psMetadataItem *itemU64 =  psMetadataItemAlloc("itemU64", PS_DATA_U64, "", 4);
+    psMetadataItem *itemF32 =  psMetadataItemAlloc("itemF32", PS_DATA_F32, "", 3.0);
+    psMetadataItem *itemF64 =  psMetadataItemAlloc("itemF64", PS_DATA_F64, "", 4.0);
+    psMetadataItem *itemString = psMetadataItemAlloc("itemString", PS_DATA_STRING, "", "I M STRiNG");
+    psMetadataItem *copy = NULL;
+    //Bool case
+    {
+        copy = psMetadataItemCopy(itemBool);
+        ok( (copy->type == PS_DATA_BOOL && (strncmp(copy->name, "itemBool", 10) == 0) &&
+             !copy->data.B && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of BOOL item.");
+        psFree(copy);
+    }
+    //S8 case
+    {
+        copy = psMetadataItemCopy(itemS8);
+        ok( (copy->type == PS_DATA_S8 && (strncmp(copy->name, "itemS8", 10) == 0) &&
+             copy->data.S8 == 1 && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of S8 item.");
+        psFree(copy);
+    }
+    //S16 case
+    {
+        copy = psMetadataItemCopy(itemS16);
+        ok( (copy->type == PS_DATA_S16 && (strncmp(copy->name, "itemS16", 10) == 0) &&
+             copy->data.S16 == 2 && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of S16 item.");
+        psFree(copy);
+    }
+    //S32 case
+    {
+        copy = psMetadataItemCopy(itemS32);
+        ok( (copy->type == PS_DATA_S32 && (strncmp(copy->name, "itemS32", 10) == 0) &&
+             copy->data.S32 == 3 && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of S32 item.");
+        psFree(copy);
+    }
+    //S64 case
+    {
+        copy = psMetadataItemCopy(itemS64);
+        ok( (copy->type == PS_DATA_S64 && (strncmp(copy->name, "itemS64", 10) == 0) &&
+             copy->data.S64 == 4 && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of S64 item.");
+        psFree(copy);
+    }
+    //U8 case
+    {
+        copy = psMetadataItemCopy(itemU8);
+        ok( (copy->type == PS_DATA_U8 && (strncmp(copy->name, "itemU8", 10) == 0) &&
+             copy->data.U8 == 1 && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of U8 item.");
+        psFree(copy);
+    }
+    //U16 case
+    {
+        copy = psMetadataItemCopy(itemU16);
+        ok( (copy->type == PS_DATA_U16 && (strncmp(copy->name, "itemU16", 10) == 0) &&
+             copy->data.U16 == 2 && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of U16 item.");
+        psFree(copy);
+    }
+    //U32 case
+    {
+        copy = psMetadataItemCopy(itemU32);
+        ok( (copy->type == PS_DATA_U32 && (strncmp(copy->name, "itemU32", 10) == 0) &&
+             copy->data.U32 == 3 && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of U32 item.");
+        psFree(copy);
+    }
+    //U64 case
+    {
+        copy = psMetadataItemCopy(itemU64);
+        ok( (copy->type == PS_DATA_U64 && (strncmp(copy->name, "itemU64", 10) == 0) &&
+             copy->data.U64 == 4 && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of U64 item.");
+        psFree(copy);
+    }
+    //F32 case
+    {
+        copy = psMetadataItemCopy(itemF32);
+        ok( (copy->type == PS_DATA_F32 && (strncmp(copy->name, "itemF32", 10) == 0) &&
+             abs(copy->data.F32-3.0) < FLT_EPSILON && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of F32 item.");
+        psFree(copy);
+    }
+    //F64 case
+    {
+        copy = psMetadataItemCopy(itemF64);
+        ok( (copy->type == PS_DATA_F64 && (strncmp(copy->name, "itemF64", 10) == 0) &&
+             abs(copy->data.F64-4.0) < DBL_EPSILON && strncmp(copy->comment, "", 2) == 0),
+            "psMetadataItemCopy:  return valid copy of F64 item.");
+        psFree(copy);
+    }
+    //STRING case
+    {
+        copy = psMetadataItemCopy(itemString);
+        ok( (copy->type == PS_DATA_STRING && (strncmp(copy->name, "itemString", 12) == 0) &&
+             strncmp(copy->data.V,"I M STRiNG",12) == 0 && strncmp(copy->comment,"",2) == 0),
+            "psMetadataItemCopy:  return valid copy of STRING item.");
+        psFree(copy);
+    }
+
+    //Test Remaining types:  Vector, Time, Metadata, Region
+    psVector *inV = psVectorAlloc(2, PS_TYPE_S32);
+    psVectorSet(inV, 0, 666);
+    psVectorSet(inV, 1, 667);
+    psMetadataItem *itemVector = psMetadataItemAlloc("itemVector", PS_DATA_VECTOR, "", inV);
+    psTime *teaTime = psTimeAlloc(PS_TIME_TAI);
+    teaTime->sec = 1;
+    teaTime->nsec = 0;
+    teaTime->leapsecond = true;
+    psMetadataItem *itemTime = psMetadataItemAlloc("itemTime", PS_DATA_TIME, "", teaTime);
+    psMetadata *md = psMetadataAlloc();
+    psMetadataAddS32(md, PS_LIST_HEAD, "mdS32", 0, "", 666);
+    psMetadataItem *itemMD = psMetadataItemAlloc("itemMD", PS_DATA_METADATA, "", md);
+    psRegion *reg = psRegionAlloc(0.0, 2.0, 1.0, 3.0);
+    psMetadataItem *itemRegion = psMetadataItemAlloc("itemRegion", PS_DATA_REGION, "", reg);
+    //Vector case
+    {
+        copy = psMetadataItemCopy(itemVector);
+        int int0 = ((psVector*)(copy->data.V))->data.S32[0];
+        int int1 = ((psVector*)(copy->data.V))->data.S32[1];
+        ok( (copy->type == PS_DATA_VECTOR && (strncmp(copy->name, "itemVector", 12) == 0)
+             && int0 == 666 && int1 == 667 && strncmp(copy->comment,"",2) == 0),
+            "psMetadataItemCopy:  return valid copy of Vector item.");
+        psFree(copy);
+    }
+    //Vector case - invalid vector item
+    {
+        psFree(itemVector->data.V);
+        itemVector->data.V = NULL;
+        copy = psMetadataItemCopy(itemVector);
+        ok( copy == NULL, "psMetadataItemCopy:  return NULL for invalid vector item");
+        //        itemVector->data.V = psVectorAlloc(1, PS_TYPE_S32);
+    }
+    //Time case
+    {
+        copy = psMetadataItemCopy(itemTime);
+        int int0 = (int)((psTime*)(copy->data.V))->sec;
+        int int1 = (int)((psTime*)(copy->data.V))->nsec;
+        bool leap = ((psTime*)(copy->data.V))->leapsecond;
+        ok( (copy->type == PS_DATA_TIME && (strncmp(copy->name, "itemTime", 12) == 0)
+             && int0 == 1 && int1 == 0 && strncmp(copy->comment,"",2) == 0) && leap,
+            "psMetadataItemCopy:  return valid copy of Time item.");
+        psFree(copy);
+    }
+    //Time case - invalid time item
+    {
+        psFree(itemTime->data.V);
+        itemTime->data.V = NULL;
+        copy = psMetadataItemCopy(itemTime);
+        ok( copy == NULL, "psMetadataItemCopy:  return NULL for invalid time item");
+        //        (itemTime->data.V) = psTimeAlloc(PS_TIME_TAI);
+    }
+    //Metadata case
+    {
+        copy = psMetadataItemCopy(itemMD);
+        psMetadataItem *testItem = NULL;
+        testItem = psMetadataGet(((psMetadata*)(copy->data.V)), PS_LIST_HEAD);
+        if (testItem == NULL)
+            printf("\nError in psMetadataGet.\n");
+        ok( copy->type == PS_DATA_METADATA && strncmp(copy->name, "itemMD", 8) == 0
+            && (strncmp(copy->comment, "",2) == 0) && testItem->type == PS_DATA_S32
+            && (strncmp(testItem->name, "mdS32", 10) == 0) && testItem->data.S32 == 666
+            && (strncmp(testItem->comment,"",2) == 0),
+            "psMetadataItemCopy:  return valid copy of Metadata item.");
+        psFree(copy);
+    }
+    //Region case
+    {
+        copy = psMetadataItemCopy(itemRegion);
+        float x0 = ((psRegion*)(copy->data.V))->x0;
+        float x1 = ((psRegion*)(copy->data.V))->x1;
+        float y0 = ((psRegion*)(copy->data.V))->y0;
+        float y1 = ((psRegion*)(copy->data.V))->y1;
+        ok( (copy->type == PS_DATA_REGION && (strncmp(copy->name, "itemRegion", 12) == 0)
+             && abs(x0-0.0) < FLT_EPSILON && abs(x1-2.0) < FLT_EPSILON
+             && abs(y0-1.0) < FLT_EPSILON && abs(y1-3.0) < FLT_EPSILON
+             && strncmp(copy->comment,"",2) == 0),
+            "psMetadataItemCopy:  return valid copy of Region item.");
+        psFree(copy);
+    }
+
+    //Test Unsupported type - (sphere for example)
+    psSphere *sphere = psSphereAlloc();
+    sphere->r = 1.0;
+    sphere->d = 6.66;
+    psMetadataItem *itemSphere = psMetadataItemAlloc("itemSphere", PS_DATA_SPHERE, "", sphere);
+    psFree(sphere);
+    {
+        copy = psMetadataItemCopy(itemSphere);
+        float R = ((psSphere*)(copy->data.V))->r;
+        float D = ((psSphere*)(copy->data.V))->d;
+        ok( (copy->type == PS_DATA_SPHERE && (strncmp(copy->name, "itemSphere", 12) == 0) &&
+             abs(R - 1.0) < FLT_EPSILON && abs(D - 6.66) < FLT_EPSILON &&
+             strncmp(copy->comment,"",2) == 0),
+            "psMetadataItemCopy:  return valid copy of SPHERE item.");
+        psFree(copy);
+    }
+
+    //Check for Memory Leaks before exit
+    {
+        psFree(inV);
+        psFree(teaTime);
+        psFree(md);
+        psFree(reg);
+        psFree(itemBool);
+        psFree(itemS8);
+        psFree(itemS16);
+        psFree(itemS32);
+        psFree(itemS64);
+        psFree(itemU8);
+        psFree(itemU16);
+        psFree(itemU32);
+        psFree(itemU64);
+        psFree(itemF32);
+        psFree(itemF64);
+        psFree(itemString);
+        psFree(itemVector);
+        psFree(itemTime);
+        psFree(itemMD);
+        psFree(itemRegion);
+        psFree(itemSphere);
+        checkMem();
+    }
+
+}
+
+void testMetadataItemTransfer(void)
+{
+    diag("\n  >>>Test 3:  psMetadataItemTransfer");
+    psMetadata *out = psMetadataAlloc();
+    psMetadata *in = psMetadataAlloc();
+    psString key = psStringAlloc(30);
+    strncpy(key, "key", 4);
+
+    //Return false for NULL in input
+    {
+        ok( !psMetadataItemTransfer(out, NULL, key),
+            "psMetadataItemTransfer:  return false for NULL in metadata.");
+    }
+    //Return false for NULL out input
+    {
+        ok( !psMetadataItemTransfer(NULL, in, key),
+            "psMetadataItemTransfer:  return false for NULL out metadata.");
+    }
+    //Return false for NULL key input
+    {
+        ok( !psMetadataItemTransfer(out, in, NULL),
+            "psMetadataItemTransfer:  return false for NULL key string.");
+    }
+    psMetadataAddS32(in, PS_LIST_HEAD, "key", PS_META_NO_REPLACE, "", 666);
+    psMetadataAddF32(out, PS_LIST_HEAD, "out", 0, "", 6.66);
+
+    //Return true for valid inputs
+    {
+        bool transfered = psMetadataItemTransfer(out, in, key);
+        psMetadataItem *item = NULL;
+        if (transfered)
+            item = psMetadataGet(out, PS_LIST_TAIL);
+        ok(transfered && item->type == PS_DATA_S32 && strncmp(item->name, "key", 4) == 0
+           && item->data.S32 == 666 && strncmp(item->comment, "", 2) == 0,
+           "psMetadataItemTransfer:  return true for valid inputs.");
+    }
+    //Return false for duplicate entry with PS_META_DEFAULT (no duplicates)
+    {
+        psMetadataRemoveKey(out, key);
+        psMetadataItem *item = psMetadataGet(in, PS_LIST_HEAD);
+        psMetadataAddItem(out, item, PS_LIST_TAIL, PS_META_NO_REPLACE);
+        //        if (item->type != PS_DATA_S32) printf("\nMetaItem was deleted from in!\n");
+        //        item = psMetadataGet(out, PS_LIST_TAIL);
+        //        if (item->type != PS_DATA_S32 || item->data.S32 != 666) printf("\nprobelm here\n");
+        ok( !psMetadataItemTransfer(out, in, key),
+            "psMetadataItemTransfer:  return false for duplicate metadataItem.");
+    }
+
+    //    psMetadataRemoveKey(out, key);
+    //    psMetadataAddS32(out, PS_LIST_TAIL, "key", 0, "", 666);
+
+
+
+    //Return false for invalid key
+    {
+        strncpy(key, "not MY key", 15);
+        ok( !psMetadataItemTransfer(out, in, key),
+            "psMetadataItemTransfer:  return false for invalid key.");
+    }
+
+    //Check for Memory Leaks
+    {
+        psFree(out);
+        psFree(in);
+        psFree(key);
+        checkMem();
+    }
+
+}
+
+
+/*
+psS32 testMetadataItemTransfer(void)
+{
+ 
+    psMetadata *md = psMetadataAlloc();
+    psMetadata *out = NULL;
+    psMetadataAddS32(md, PS_LIST_TAIL, "metaITEM", 0, "no Comment", 666);
+ 
+    //attempt transfer to NULL 'out' metadata.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psMetadataItemTransfer(out, md, "metaITEM") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to return false for NULL 'out' metadata.\n");
+        return 1;
+    }
+    out = psMetadataAlloc();
+    //attempt to transfer using a NULL key.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psMetadataItemTransfer(out, md, NULL) ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to return false for NULL key input.\n");
+        return 2;
+    }
+    //attempt transfer to NULL 'in' metadata.
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if ( psMetadataItemTransfer(out, NULL, "metaITEM") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to return false for NULL 'in' metadata.\n");
+        return 3;
+    }
+    //attempt to transfer using an allocated metadata and invalid key
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    if (psMetadataItemTransfer(out, md, "metaITEM2") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to return false for invalid 'key'.\n");
+        return 4;
+    }
+    //attempt to transfer with all valid inputs.
+    psMetadataItem *item = NULL;
+    if ( !psMetadataItemTransfer(out, md, "metaITEM") ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed with valid inputs.\n");
+        return 7;
+    }
+    item = psMetadataGet(out, PS_LIST_HEAD);
+    if (item->data.S32 != 666 || strncmp(item->comment, "no Comment", 20)) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "psMetadataItemTransfer failed to correctly transfer item data.\n");
+        return 8;
+    }
+ 
+    psFree(out);
+    psFree(md);
+ 
+    return 0;
+}
+        */
