Index: trunk/psLib/test/collections/tst_psMetadataIO.c
===================================================================
--- trunk/psLib/test/collections/tst_psMetadataIO.c	(revision 3779)
+++ trunk/psLib/test/collections/tst_psMetadataIO.c	(revision 3945)
@@ -4,16 +4,15 @@
  *
  *  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
+ *    Read config file with overwrite set true
+ *    Read config file with overwrite set false
+ *    Attempt to use null fileName argument
+ *    Attempt to open nonexistant file
  *
  *  @author  Ross Harman, MHPCC
  *  @author  Robert DeSonia, MHPCC
+ *  @author  Eric Van Alst, MHPCC
  *
- *  @version $Revision: 1.14 $  $Name: not supported by cvs2svn $
- *  @date  $Date: 2005-04-28 02:45:12 $
+ *  @version $Revision: 1.15 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-05-16 19:41:40 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -25,148 +24,949 @@
 #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;
-
+static psS32 testMetadataParseConfig(void);
+static psS32 testMetadataParseConfig1(void);
+static psS32 testMetadataParseConfig2(void);
+
+testDescription tests[] = {
+                              {testMetadataParseConfig,000,"psMetadataParseConfig",0,false},
+                              {testMetadataParseConfig1,000,"psMetadataParseConfig",0,false},
+                              {testMetadataParseConfig2,000,"psMetadataParseConfig",0,false},
+                              {NULL}
+                          };
+
+static void writeMetadataItem(psMetadataItem* metadataIem, char* indentStr);
+static void writeMetadata(psMetadata* metadata, char* indentStr);
+static void writeMetadataList(psList *metadataItemList, char* indentStr);
+
+static psBool checkFailedLines(psS32 failedLines, psS32 expectedFailedLines, char* configFile);
+static psBool checkNumberOfItems(psMetadata* md, psS32 expectedItems, char* configFile);
+static psBool checkItemName(psMetadataItem* mdItem, char* expectedName, char* configFile);
+static psBool checkItemType(psMetadataItem* mdItem, psS32 expectedType, char* configFile);
+static psBool checkItemComment(psMetadataItem* mdItem, char* expectedComment, char* configFile);
+
+#define ERROR_TOL  0.0001
+
+const char testConfig3[] = "test3.config";
+const psS32 testConfig3Fails = 1;
+
+const char testConfig2[] = "test2.config";
+const psS32 testConfig2Fails = 17;
+
+// SDR-14 test config file #1
+const char  testConfig1[] = "test1.config";
+const psS32 testConfig1FailsOverwrite = 0;
+const psS32 testConfig1Fails = 1;
+const psS32 testConfig1Items = 25;
+const char* testConfig1KeyOverwrite[] =
+    {
+        "Double","String","boolean","primes","comment",
+        "comment","comment","comment","comment","Float",
+        "boolean1","negprimes","vector1","vector2","vector3",
+        "vector4","vector5","vector6","vector7","vector8",
+        "CELL.00", "CELL.01","MYCELL","MYCELL","cell"
+    };
+const char* testConfig1CommentOverwrite[] =
+    {
+        "This is a comment","comment","The value of 'boolean' is 'true'","These are prime numbers",
+        "","","","","",
+        "This generates a warning, and, if 'overwrite' is 'false', is ignored","The value of 'boolean' is 'false'",
+        "","","","","",
+        "","","","",
+        "","","","A number",""
+    };
+const psMetadataType testConfig1TypeOverwrite[] =
+    {
+        PS_META_F64, PS_META_STR, PS_META_BOOL, PS_META_VEC, PS_META_STR,
+        PS_META_STR, PS_META_STR, PS_META_STR, PS_META_STR,  PS_META_F64,
+        PS_META_BOOL, PS_META_VEC, PS_META_VEC, PS_META_VEC, PS_META_VEC,
+        PS_META_VEC, PS_META_VEC, PS_META_VEC, PS_META_VEC, PS_META_VEC,
+        PS_META_META, PS_META_META, PS_META_META, PS_META_S32, PS_META_META
+    };
+const psS32 testConfig1ValueS32Overwrite[] =
+    {
+        0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0,
+        0, 0, 0, 123, 0
+    };
+const psF32 testConfig1ValueF32Overwrite[] =
+    {
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0
+    };
+const psF64 testConfig1ValueF64Overwrite[] =
+    {
+        1.23456789, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 1.23456,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0,
+        0.0, 0.0, 0.0, 0.0, 0.0
+    };
+const psBool testConfig1ValueBoolOverwrite[] =
+    {
+        false, false, true, false, false,
+        false, false, false, false, false,
+        false, false, false, false, false,
+        false, false, false, false, false,
+        false, false, false, false, false
+    };
+const char* testConfig1ValueStrOverwrite[] =
+    {
+        "", "This is the string that forms the value","","","This",
+        "is","a","non-unique","key","",
+        "","","","","",
+        "","","","","",
+        "","","","",""
+    };
+const psS32 testConfig1ValueVecItemsU8 = 7;
+const psElemType testConfig1ValueVecTypeU8 = PS_TYPE_U8;
+const psU8 testConfig1ValueVecValueU8[] =
+    {
+        2, 3, 5, 7, 11, 13, 17
+    };
+const psS32 testConfig1ValueVecItemsS8 = 8;
+const psElemType testConfig1ValueVecTypeS8 = PS_TYPE_S8;
+const psS8 testConfig1ValueVecValueS8[] =
+    {
+        -2, -3, -5, -7, -11, -13, -17, -19
+    };
+const psS32 testConfig1ValueVecItemsU16 = 5;
+const psElemType testConfig1ValueVecTypeU16 = PS_TYPE_U16;
+const psU16 testConfig1ValueVecValueU16[] =
+    {
+        0, 1, 2, 4, 8
+    };
+const psS32 testConfig1ValueVecItemsU32 = 6;
+const psElemType testConfig1ValueVecTypeU32 = PS_TYPE_U32;
+const psU32 testConfig1ValueVecValueU32[] =
+    {
+        0, 8, 16, 32, 64, 128
+    };
+const psS32 testConfig1ValueVecItemsU64 = 3;
+const psElemType testConfig1ValueVecTypeU64 = PS_TYPE_U64;
+const psU64 testConfig1ValueVecValueU64[] =
+    {
+        0, 64, 256
+    };
+const psS32 testConfig1ValueVecItemsS16 = 5;
+const psElemType testConfig1ValueVecTypeS16 = PS_TYPE_S16;
+const psS16 testConfig1ValueVecValueS16[] =
+    {
+        -2, -1, 0, 1, 2
+    };
+const psS32 testConfig1ValueVecItemsS32 = 6;
+const psElemType testConfig1ValueVecTypeS32 = PS_TYPE_S32;
+const psS32 testConfig1ValueVecValueS32[] =
+    {
+        -4, -2, 0, 2, 4, 6
+    };
+const psS32 testConfig1ValueVecItemsS64 = 7;
+const psElemType testConfig1ValueVecTypeS64 = PS_TYPE_S64;
+const psS64 testConfig1ValueVecValueS64[] =
+    {
+        -16, -4, 0, 4, 16, 36, 64
+    };
+const psS32 testConfig1ValueVecItemsF32 = 4;
+const psElemType testConfig1ValueVecTypeF32 = PS_TYPE_F32;
+const psF32 testConfig1ValueVecValueF32[] =
+    {
+        -1.03, 1.04, -1.05, 1.06
+    };
+const psS32 testConfig1ValueVecItemsF64 = 5;
+const psElemType testConfig1ValueVecTypeF64 = PS_TYPE_F64;
+const psF64 testConfig1ValueVecValueF64[] =
+    {
+        -2.22, 2.21, -2.20, 2.19, -2.18
+    };
+const psS32 testConfig1ValueMetaItems1 = 3;
+const char* testConfig1ValueMetaNames1[] =
+    {
+        "EXTNAME","BIASSEC","CHIP"
+    };
+const psMetadataType testConfig1ValueMetaTypes1[] =
+    {
+        PS_META_STR, PS_META_STR, PS_META_STR
+    };
+const char* testConfig1ValueMetaValue1[] =
+    {
+        "CCD00","BSEC-00","CHIP.00"
+    };
+const psS32 testConfig1ValueMetaItems2 = 3;
+const char* testConfig1ValueMetaNames2[] =
+    {
+        "EXTNAME","BIASSEC","CHIP"
+    };
+const psMetadataType testConfig1ValueMetaTypes2[] =
+    {
+        PS_META_STR, PS_META_STR, PS_META_STR
+    };
+const char* testConfig1ValueMetaValue2[] =
+    {
+        "CCD01","BSEC-01","CHIP.00"
+    };
+const psS32 testConfig1ValueMetaItems3 = 4;
+const char* testConfig1ValueMetaNames3[] =
+    {
+        "EXTNAME","BIASSEC","CHIP","NCELL"
+    };
+const psMetadataType testConfig1ValueMetaTypes3[] =
+    {
+        PS_META_STR, PS_META_STR, PS_META_STR, PS_META_S32
+    };
+const char* testConfig1ValueMetaValueStr3[] =
+    {
+        "CCD00","BSEC-00","CHIP.00",""
+    };
+const psS32 testConfig1ValueMetaValueS323[] =
+    {
+        0, 0, 0, 24
+    };
+
+static void writeMetadata(psMetadata* metadata, char* indentStr)
+{
+    writeMetadataList(metadata->list, indentStr);
+}
+
+static void writeMetadataList(psList* metadataItemList, char* indentStr)
+{
+    psMetadataItem* entryChild        = NULL;
+    psMetadataItem* searchChild       = NULL;
+    psArray*        nonUniqueKeyArray = NULL;
+    psBool          keyFound          = false;
+    char*           tempKey           = NULL;
+
+    // Allocate iterator for moving through metadata list
     psListIterator* iter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);
-
-    while ( (entryChild=psListGetAndIncrement(iter)) != NULL) {
-        printMetadataItem(entryChild, spaces);
+    psListIterator* searchIter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);
+
+    // Allocate array for nonUnique key names
+    nonUniqueKeyArray = psArrayAlloc(10);
+    nonUniqueKeyArray->n = 0;
+
+
+    // Loop through all items in the list
+    while ( (entryChild = psListGetAndIncrement(iter)) != NULL) {
+        // Search list for another entry with same key name
+        // Check if last entry
+        if(iter->index != metadataItemList->size) {
+            // Set search iterator to index
+            if(!psListIteratorSet(searchIter,iter->index) ) {
+                psError(PS_ERR_UNKNOWN,true,"Error searching list for multiple keys");
+                break;
+            }
+            keyFound = false;
+            while ( (searchChild = psListGetAndIncrement(searchIter)) != NULL) {
+                if(strcmp(entryChild->name,searchChild->name) == 0) {
+                    // Search nonUnique key array
+                    for(psS32 i = 0; i < nonUniqueKeyArray->n; i++) {
+                        if(strcmp(entryChild->name,nonUniqueKeyArray->data[i]) == 0) {
+                            keyFound = true;
+                        }
+                    }
+                    if(!keyFound) {
+                        // Add key to non-unique array
+                        tempKey = psStringCopy(entryChild->name);
+                        nonUniqueKeyArray = psArrayAdd(nonUniqueKeyArray,1,tempKey);
+                        psFree(tempKey);
+
+                        // Print MULTI line
+                        printf("%-25s MULTI\n",entryChild->name);
+
+                        // Break out of loop
+                        break;
+                    }
+                }
+            }
+        }
+        writeMetadataItem(entryChild,indentStr);
     }
 
     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)
-{
-    char* vecStr;
-
-    printf("%sKey Name: %8s  ", spaces, metadataItem->name);
-    printf("Key mdType: 0x%08x ", metadataItem->type);
-
-    switch (metadataItem->type) {
-    case PS_META_MULTI:
-        printf("Key Value: %17c", ' ');
+    psFree(searchIter);
+    psFree(nonUniqueKeyArray);
+}
+
+char* vectorToConfigString(psVector* vector)
+{
+    psS32  maxLength = 256;
+
+    char* str = psAlloc(sizeof(char)*maxLength+1);
+
+    if (vector == NULL) {
+        snprintf(str,maxLength, "NULL");
+        return str;
+    }
+
+    int size = vector->n;
+
+    if (size == 0) {
+        snprintf(str,maxLength, " ");
+        return str;
+    }
+
+    char* tempStr = psAlloc(sizeof(char)*maxLength+1);
+    *str = '\0';
+    bool full = false;
+
+    #define APPEND_ELEMENTS_CASE(TYPE, NATIVE_TYPE, FORMAT) \
+case PS_TYPE_##TYPE: \
+    strcat(str,#TYPE); \
+    for(psS32 i = 0; i < (strlen(str)-6); i++) {  \
+        strcat(str," "); \
+    } \
+    for (lcv=0; lcv < size && ! full; lcv++) { \
+        snprintf(tempStr, maxLength, "%s" FORMAT, prefix, (NATIVE_TYPE) (vector->data.TYPE[lcv])); \
+        strncat(str,tempStr,maxLength); \
+        full = (strlen(str) > maxLength-2); \
+        prefix = ","; \
+    } \
+    break;
+
+    int lcv;
+    char* prefix = " ";
+    switch(vector->type.type) {
+        APPEND_ELEMENTS_CASE(S8,char,"%hd")
+        APPEND_ELEMENTS_CASE(S16,short int,"%hd")
+        APPEND_ELEMENTS_CASE(S32,int,"%d")
+        APPEND_ELEMENTS_CASE(S64,long,"%ld")
+        APPEND_ELEMENTS_CASE(U8,unsigned char,"%hu")
+        APPEND_ELEMENTS_CASE(U16,unsigned short,"%hu")
+        APPEND_ELEMENTS_CASE(U32,unsigned int, "%u")
+        APPEND_ELEMENTS_CASE(U64,unsigned long,"%lu")
+        APPEND_ELEMENTS_CASE(F32,double,"%g")
+        APPEND_ELEMENTS_CASE(F64,double,"%g")
+    default:
+        snprintf(str,maxLength,"INVALID TYPE");
         break;
+    }
+
+    psFree(tempStr);
+
+    return str;
+}
+
+
+static void writeMetadataItem(psMetadataItem *metadataItem, char* indentStr)
+{
+    char*  vecStr;
+
+    switch(metadataItem->type) {
     case PS_META_BOOL:
-        printf("Key Value: %15d  ", metadataItem->data.B);
+        printf("%s%-25s BOOL  %40d",indentStr,metadataItem->name,metadataItem->data.B);
         break;
     case PS_META_S32:
-        printf("Key Value: %15d  ", metadataItem->data.S32);
+        printf("%s%-25s S32   %40d",indentStr,metadataItem->name,metadataItem->data.S32);
         break;
     case PS_META_F32:
-        printf("Key Value: %15.3f  ", metadataItem->data.F32);
+        printf("%s%-25s F32   %40f",indentStr,metadataItem->name,metadataItem->data.F32);
         break;
     case PS_META_F64:
-        printf("Key Value: %15.3f  ", metadataItem->data.F64);
+        printf("%s%-25s F64   %40lf",indentStr,metadataItem->name,metadataItem->data.F64);
         break;
     case PS_META_VEC:
-        vecStr = (char*)psVectorToString((psVector*)metadataItem->data.V, 15);
-        printf("Key Value: %15s  ", vecStr);
+        vecStr = (char*)vectorToConfigString((psVector*)metadataItem->data.V);
+        printf("%s@%-24s %s",indentStr,metadataItem->name,vecStr);
         psFree(vecStr);
         break;
     case PS_META_STR:
-        printf("Key Value: %15s  ", (char*)metadataItem->data.V);
+        printf("%s%-25s STR   %40s",indentStr,metadataItem->name,(char*)metadataItem->data.V);
+        break;
+    case PS_META_META:
+        printf("%s%-25s METADATA\n",indentStr,metadataItem->name);
+        writeMetadata((psMetadata*)metadataItem->data.md,"    ");
         break;
     default:
-        printf("Bad type: 0x%08x ", metadataItem->type);
-    }
-    printf("Key Comment: %s\n", metadataItem->comment);
-
-    if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
-        printMetadataList(metadataItem->data.V, "    ");
-    }
-}
-
+        printf("#%s%-24s BAD TYPE=%d",indentStr,metadataItem->name,metadataItem->type);
+        break;
+    }
+    if(strlen(metadataItem->comment) > 0) {
+        printf("  # %-20s\n",metadataItem->comment);
+    } else {
+        printf("\n");
+    }
+}
+
+static psBool checkFailedLines(psS32 failedLines, psS32 expectedFailedLines, char* configFile)
+{
+    psBool     returnValue = true;
+
+    // Verify the expected number of failed lines
+    if(failedLines != expectedFailedLines) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Number of failed lines = %d not as expected %d",
+                configFile,failedLines,expectedFailedLines);
+        returnValue = false;
+    }
+    return returnValue;
+}
+
+static psBool checkNumberOfItems(psMetadata* md, psS32 expectedItems, char* configFile)
+{
+    psBool     returnValue = true;
+
+    // Verify the number of items in metadata
+    if(md->list->size != expectedItems) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Number of items = %d not as expected %d",
+                configFile,md->list->size, expectedItems);
+        returnValue = false;
+    }
+    return returnValue;
+}
+
+static psBool checkItemName(psMetadataItem* mdItem, char* expectedName, char* configFile)
+{
+    psBool    returnValue = true;
+
+    // Compare key names
+    if(strcmp(mdItem->name,expectedName) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Key name %s not as expected %s",
+                configFile,mdItem->name,expectedName);
+        returnValue = false;
+    }
+
+    return returnValue;
+}
+
+static psBool checkItemType(psMetadataItem* mdItem, psS32 expectedType, char* configFile)
+{
+    psBool     returnValue = true;
+
+    // Compare types
+    if(mdItem->type != expectedType) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Type %d not as expected %d",
+                configFile,mdItem->type,expectedType);
+        returnValue = false;
+    }
+    return returnValue;
+}
+
+static psBool checkItemComment(psMetadataItem* mdItem, char* expectedComment, char* configFile)
+{
+    psBool    returnValue = true;
+
+    // Compare comments
+    if(strcmp(mdItem->comment,expectedComment) != 0) {
+        psError(PS_ERR_UNKNOWN,true,"File: %s : Comment %s not as expected %s",
+                configFile,mdItem->comment,expectedComment);
+        returnValue = false;
+    }
+    return returnValue;
+}
 
 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;
-    psU32 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();
-    psU32 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");
+    psLogSetLevel(PS_LOG_INFO);
+
+    if( !runTestSuite(stderr,"psMetadataParseConfig",tests,argc,argv)) {
+        return 1;
+    }
+
+    return 0;
+}
+
+psS32 testMetadataParseConfig(void)
+{
+    psMetadata*       metadata1      = NULL;
+    psMetadataItem*   entryChild     = NULL;
+    psS32             failedLines    = 0;
+    psListIterator*   iter           = NULL;
+    psListIterator*   mdIter         = NULL;
+    psMetadataItem*   mdChild        = NULL;
+    psS32             metaCounter    = 0;
+    psS32             mdCounter      = 0;
+
+    // Read config file test1.config with overwrite set true
+    metadata1 = psMetadataParseConfig(metadata1,&failedLines,testConfig1,true);
+    // Verify the expected number of failed lines
+    if(!checkFailedLines(failedLines,testConfig1FailsOverwrite,(char*)testConfig1)) {
+        return 1;
+    }
+    // Verify the number of items in metadata
+    if(!checkNumberOfItems(metadata1,testConfig1Items,(char*)testConfig1)) {
+        return 2;
+    }
+    // Verify metadata item quads
+    iter = psListIteratorAlloc(metadata1->list, PS_LIST_HEAD, true);
+    for(psS32 i = 0; i < testConfig1Items; i++) {
+        // Get list item
+        entryChild = psListGetAndIncrement(iter);
+
+        // Verify end of list not reached prematurely
+        if(entryChild == NULL) {
+            psError(PS_ERR_UNKNOWN,true,"End of list encountered at %d not as expected %d",
+                    i,testConfig1Items);
+            return i*10+1;
+        }
+        // Verify name
+        if(!checkItemName(entryChild,(char*)testConfig1KeyOverwrite[i],(char*)testConfig1)) {
+            return i*10+2;
+        }
+        // Verify type
+        if(!checkItemType(entryChild,testConfig1TypeOverwrite[i],(char*)testConfig1)) {
+            return i*10+3;
+        }
+        // Verify comment
+        if(!checkItemComment(entryChild,(char*)testConfig1CommentOverwrite[i],(char*)testConfig1)) {
+            return i*10+4;
+        }
+        // Compare values
+        switch(entryChild->type) {
+        case PS_META_S32:
+            if(entryChild->data.S32 != testConfig1ValueS32Overwrite[i]) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %d not as expected %d",
+                        testConfig1,entryChild->data.S32, testConfig1ValueS32Overwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_META_F32:
+            if(fabs(entryChild->data.F32 - testConfig1ValueF32Overwrite[i]) > ERROR_TOL) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %f not as expected %f",
+                        testConfig1,entryChild->data.F32, testConfig1ValueF32Overwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_META_F64:
+            if(fabs(entryChild->data.F64 - testConfig1ValueF64Overwrite[i]) > ERROR_TOL) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %lf not as expected %lf",
+                        testConfig1,entryChild->data.F64, testConfig1ValueF64Overwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_META_BOOL:
+            if(entryChild->data.B != testConfig1ValueBoolOverwrite[i]) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %d not as expected %d",
+                        testConfig1,entryChild->data.B,testConfig1ValueBoolOverwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_META_STR:
+            if(strcmp(entryChild->data.V,testConfig1ValueStrOverwrite[i]) != 0) {
+                psError(PS_ERR_UNKNOWN,true,"File: %s : Value %s not as expected %s",
+                        testConfig1,entryChild->data.V,testConfig1ValueStrOverwrite[i]);
+                return i*10+5;
+            }
+            break;
+        case PS_META_VEC:
+            // Verify the correct number of entries
+            switch(((psVector*)(entryChild->data.V))->type.type) {
+            case PS_TYPE_U8:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU8) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU8);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU8) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU8);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsU8; j++) {
+                    if(((psVector*)entryChild->data.V)->data.U8[j] != testConfig1ValueVecValueU8[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.U8[j],
+                                testConfig1ValueVecValueU8[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_U16:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU16) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU16);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU16) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU16);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsU16; j++) {
+                    if(((psVector*)entryChild->data.V)->data.U16[j] != testConfig1ValueVecValueU16[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.U16[j],
+                                testConfig1ValueVecValueU16[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_U32:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU32);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU32);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsU32; j++) {
+                    if(((psVector*)entryChild->data.V)->data.U32[j] != testConfig1ValueVecValueU32[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.U32[j],
+                                testConfig1ValueVecValueU32[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_U64:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsU64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsU64);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeU64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeU64);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsU64; j++) {
+                    if(((psVector*)entryChild->data.V)->data.U64[j] != testConfig1ValueVecValueU64[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %ld not as expected %ld",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.U64[j],
+                                testConfig1ValueVecValueU64[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_S8:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS8) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS8);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS8) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS8);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsS8; j++) {
+                    if(((psVector*)entryChild->data.V)->data.S8[j] != testConfig1ValueVecValueS8[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.S8[j],
+                                testConfig1ValueVecValueS8[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_S16:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS16) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS16);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS16) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS16);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsS16; j++) {
+                    if(((psVector*)entryChild->data.V)->data.S16[j] != testConfig1ValueVecValueS16[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.S16[j],
+                                testConfig1ValueVecValueS16[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_S32:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS32);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS32);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsS32; j++) {
+                    if(((psVector*)entryChild->data.V)->data.S32[j] != testConfig1ValueVecValueS32[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %d not as expected %d",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.S32[j],
+                                testConfig1ValueVecValueS32[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_S64:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsS64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsS64);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeS64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeS64);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsS64; j++) {
+                    if(((psVector*)entryChild->data.V)->data.S64[j] != testConfig1ValueVecValueS64[j]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %ld not as expected %ld",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.S64[j],
+                                testConfig1ValueVecValueS64[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_F32:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsF32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsF32);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeF32) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeF32);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsF32; j++) {
+                    if(fabs(((psVector*)entryChild->data.V)->data.F32[j]-testConfig1ValueVecValueF32[j])
+                            > ERROR_TOL) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %f not as expected %f",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.F32[j],
+                                testConfig1ValueVecValueF32[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            case PS_TYPE_F64:
+                if(((psVector*)(entryChild->data.V))->n != testConfig1ValueVecItemsF64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector entries %d not as expected %d",
+                            testConfig1,((psVector*)(entryChild->data.V))->n,testConfig1ValueVecItemsF64);
+                    return i*10+5;
+                }
+                // Verify the correct type
+                if(((psVector*)(entryChild->data.V))->type.type != testConfig1ValueVecTypeF64) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Vector type %d not as expected %s",
+                            testConfig1,((psVector*)entryChild->data.V)->type.type,testConfig1ValueVecTypeF64);
+                    return i*10+5;
+                }
+                // Verify the values in vector
+                for(psS32 j = 0; j < testConfig1ValueVecItemsF64; j++) {
+                    if(fabs(((psVector*)entryChild->data.V)->data.F64[j]-testConfig1ValueVecValueF64[j])
+                            > ERROR_TOL) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Vector data[%d] = %lf not as expected %lf",
+                                testConfig1,j,((psVector*)entryChild->data.V)->data.F64[j],
+                                testConfig1ValueVecValueF64[j]);
+                        return i*10+5*j;
+                    }
+                }
+                break;
+            default:
+                break;
+            }
+            break;
+        case PS_META_META:
+            if(metaCounter == 0) {
+                // Check if number of items is as expected
+                if(entryChild->data.md->list->size != testConfig1ValueMetaItems1) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 items %d not as expected %d",
+                            testConfig1,entryChild->data.md->list->size,testConfig1ValueMetaItems1);
+                    return i*10+6;
+                }
+                // Loop through metadata items
+                mdIter = psListIteratorAlloc(entryChild->data.md->list, PS_LIST_HEAD, true);
+                mdCounter = 0;
+                while ( (mdChild = psListGetAndIncrement(mdIter)) != NULL) {
+                    if(strcmp(mdChild->name,testConfig1ValueMetaNames1[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 name[%d] %s not as expected %s",
+                                testConfig1,mdCounter,mdChild->name,testConfig1ValueMetaNames1[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(mdChild->type != testConfig1ValueMetaTypes1[mdCounter]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 type[%d] %d not as expected %d",
+                                testConfig1,mdCounter,mdChild->type,testConfig1ValueMetaTypes1[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(strcmp((char*)mdChild->data.V,testConfig1ValueMetaValue1[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 1 value[%d] %s not as expected %s",
+                                testConfig1,mdCounter,(char*)mdChild->data.V,testConfig1ValueMetaValue1[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    mdCounter++;
+                }
+                psFree(mdIter);
+            } else if(metaCounter == 1) {
+                // Check if number of items is as expected
+                if(entryChild->data.md->list->size != testConfig1ValueMetaItems2) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 items %d not as expected %d",
+                            testConfig1,entryChild->data.md->list->size,testConfig1ValueMetaItems2);
+                    return i*10+6;
+                }
+                // Loop through metadata items
+                mdIter = psListIteratorAlloc(entryChild->data.md->list, PS_LIST_HEAD, true);
+                mdCounter = 0;
+                while ( (mdChild = psListGetAndIncrement(mdIter)) != NULL) {
+                    if(strcmp(mdChild->name,testConfig1ValueMetaNames2[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 name[%d] %s not as expected %s",
+                                testConfig1,mdCounter,mdChild->name,testConfig1ValueMetaNames2[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(mdChild->type != testConfig1ValueMetaTypes2[mdCounter]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 type[%d] %d not as expected %d",
+                                testConfig1,mdCounter,mdChild->type,testConfig1ValueMetaTypes2[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(strcmp((char*)mdChild->data.V,testConfig1ValueMetaValue2[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 2 value[%d] %s not as expected %s",
+                                testConfig1,mdCounter,(char*)mdChild->data.V,testConfig1ValueMetaValue2[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    mdCounter++;
+                }
+                psFree(mdIter);
+            } else if(metaCounter == 2) {
+                // Check if number of items is as expected
+                if(entryChild->data.md->list->size != testConfig1ValueMetaItems3) {
+                    psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 items %d not as expected %d",
+                            testConfig1,entryChild->data.md->list->size,testConfig1ValueMetaItems3);
+                    return i*10+6;
+                }
+                // Loop through metadata items
+                mdIter = psListIteratorAlloc(entryChild->data.md->list, PS_LIST_HEAD, true);
+                mdCounter = 0;
+                while ( (mdChild = psListGetAndIncrement(mdIter)) != NULL) {
+                    if(strcmp(mdChild->name,testConfig1ValueMetaNames3[mdCounter]) != 0) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 name[%d] %s not as expected %s",
+                                testConfig1,mdCounter,mdChild->name,testConfig1ValueMetaNames3[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    if(mdChild->type != testConfig1ValueMetaTypes3[mdCounter]) {
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 type[%d] %d not as expected %d",
+                                testConfig1,mdCounter,mdChild->type,testConfig1ValueMetaTypes3[mdCounter]);
+                        return i*10+6*mdCounter;
+                    }
+                    switch(mdChild->type) {
+                    case PS_META_STR:
+                        if(strcmp((char*)mdChild->data.V,testConfig1ValueMetaValueStr3[mdCounter]) != 0) {
+                            psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 value[%d] %s not as expected %s",
+                                    testConfig1,mdCounter,(char*)mdChild->data.V,
+                                    testConfig1ValueMetaValueStr3[mdCounter]);
+                            return i*10+6*mdCounter;
+                        }
+                        break;
+                    case PS_META_S32:
+                        if(mdChild->data.S32 != testConfig1ValueMetaValueS323[mdCounter]) {
+                            psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 value[%d] %d not as expected %d",
+                                    testConfig1,mdCounter,mdChild->data.S32,
+                                    testConfig1ValueMetaValueS323[mdCounter]);
+                            return i*10+6*mdCounter;
+                        }
+                        break;
+                    default:
+                        psError(PS_ERR_UNKNOWN,true,"File: %s : Metadata 3 value[%d] unknown type",
+                                testConfig1,mdCounter);
+                        return i*10+6*mdCounter;
+                        break;
+                    }
+                    mdCounter++;
+                }
+                psFree(mdIter);
+            }
+            metaCounter++;
+            break;
+        default:
+            psError(PS_ERR_UNKNOWN,true,"Unexpected type %d encountered",entryChild->type);
+            return i*10+5;
+            break;
+        }
+    }
+
+    writeMetadata(metadata1,"");
+
     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;
 }
+
+psS32 testMetadataParseConfig1(void)
+{
+    psMetadata*       metadata1      = NULL;
+    psS32             failedLines    = 0;
+
+    // Read config file test2.config with overwrite set true
+    // This file contains parse errors
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate parse error message");
+    metadata1 = psMetadataParseConfig(metadata1,&failedLines,testConfig2,true);
+    // Verify the expected number of failed lines
+    if(!checkFailedLines(failedLines,testConfig2Fails,(char*)testConfig2)) {
+        return 1;
+    }
+    // Verify return value is null
+    if(metadata1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for failed parse");
+        return 2;
+    }
+
+    // Attempt parse a non-existant file
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    metadata1 = psMetadataParseConfig(metadata1,&failedLines,"ab.config",true);
+    if(metadata1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for non-existant file");
+        return 3;
+    }
+
+    // Attempt parse with NULL failed lines ptr
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL failed lines arg");
+    metadata1 = psMetadataParseConfig(metadata1,NULL,testConfig2,true);
+    if(metadata1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for NULL failed lines argument");
+        return 4;
+    }
+
+    // Attempt parse with NULL file name
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL file name arg");
+    metadata1 = psMetadataParseConfig(metadata1,&failedLines,NULL,true);
+    if(metadata1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for NULL filename argument");
+        return 5;
+    }
+
+    psFree(metadata1);
+
+    return 0;
+}
+
+psS32 testMetadataParseConfig2(void)
+{
+    psMetadata*       metadata1      = NULL;
+    psS32             failedLines    = 0;
+
+    // Read config file test1.config with overwrite set false
+    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error of duplicate key names");
+    metadata1 = psMetadataParseConfig(metadata1,&failedLines,testConfig3,false);
+    // Verify the expected number of failed lines
+    if(!checkFailedLines(failedLines,testConfig3Fails,(char*)testConfig3)) {
+        return 1;
+    }
+    if(metadata1 != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Expected a NULL return for failed due to overwrite false");
+        return 2;
+    }
+    psFree(metadata1);
+
+    return 0;
+}
+
