Index: /trunk/psLib/test/sysUtils/tst_psMemory.c
===================================================================
--- /trunk/psLib/test/sysUtils/tst_psMemory.c	(revision 639)
+++ /trunk/psLib/test/sysUtils/tst_psMemory.c	(revision 640)
@@ -6,6 +6,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-05-11 03:14:49 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-05-11 20:52:33 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -34,4 +34,9 @@
 static long memAllocateCallback(const psMemBlock *ptr);
 static long memFreeCallback(const psMemBlock *ptr);
+int TPcheckLeaks(void);
+int TPmemCorruption(void);
+void memProblemCallback(const psMemBlock *ptr, const char *file, int lineno);
+
+static int problemCallbackCalled = 0;
 static int allocCallbackCalled = 0;
 static int freeCallbackCalled = 0;
@@ -43,6 +48,8 @@
                               {TPOutOfMemory,"450-TPOutOfMemory",0},
                               {TPrealloc,"451-TPrealloc",0},
-                              {TPallocCallback,"452-TPallocCallback",0},
-                              {TPFreeReferencedMemory,"TPFreeReferencedMemory",6},
+                              {TPallocCallback,"452/453-TPallocCallback",0},
+                              {TPcheckLeaks,"454-TPcheckLeaks",0},
+                              {TPmemCorruption,"455-TPmemCorruption",0},
+                              {TPFreeReferencedMemory,"456-TPFreeReferencedMemory",0},
                               {NULL}
                           };
@@ -95,10 +102,51 @@
     int* mem;
     int currentId = psMemGetId();
-
-    fprintf(stderr,"Allocating buffer.\n");
+    int ref = 0;
+    psMemProblemCallback cb;
+
+    psLogMsg(__func__,PS_LOG_INFO,"memory reference count shall be incrementable/decrementable");
+
     mem = (int*) psAlloc(100*sizeof(int));
 
+    ref = psMemGetRefCounter(mem);
+    if (ref != 1) {
+        psError(__func__,"Expected to buffer reference count to be initially 1, but it was %d.",ref);
+        return 1;
+    }
+
     psMemIncrRefCounter(mem);
-    fprintf(stderr,"Freeing buffer after incrementing reference count.\n");
+    psMemIncrRefCounter(mem);
+    psMemIncrRefCounter(mem);
+
+    ref = psMemGetRefCounter(mem);
+    if (ref != 4) {
+        psError(__func__,"Expected to find buffer reference count to be 4, but it was %d.",ref);
+        return 1;
+    }
+
+    psMemDecrRefCounter(mem);
+    psMemDecrRefCounter(mem);
+
+    ref = psMemGetRefCounter(mem);
+    if (ref != 2) {
+        psError(__func__,"Expected to find buffer reference count to be 2, but it was %d.",ref);
+        return 1;
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"expect error from free as multiple referenced buffer is freed.");
+
+    problemCallbackCalled = 0;
+    cb = psMemProblemCallbackSet(memProblemCallback);
+
+    psFree(mem);
+
+    psMemProblemCallbackSet(cb);
+
+    if (problemCallbackCalled != 1) {
+        psError(__func__,"Expected memProblemCallback to be called once, but was called %d times.",
+                problemCallbackCalled);
+        return 1;
+    }
+
     psFree(mem);
 
@@ -267,6 +315,174 @@
         return 1;
     }
-    return 0;
-
+
+    psMemCheckLeaks(currentId,NULL,NULL);
+    psMemCheckCorruption(1);
+
+    return 0;
+
+}
+
+int TPcheckLeaks(void)
+{
+    const int numBuffers = 5;
+    int* buffers[5];
+    int lcv;
+    int currentId = psMemGetId();
+    psMemBlock** blks;
+    int nLeaks = 0;
+    int lineMark = 0;
+
+    psLogMsg(__func__,PS_LOG_INFO,"psMemCheckLeaks shall return the number of blocks above an ID "
+             "that are still allocated");
+
+    for (lcv=0;lcv<numBuffers;lcv++) {
+        lineMark = __LINE__+1;
+        buffers[lcv] = psAlloc(sizeof(int));
+    }
+
+    for (lcv=1;lcv<numBuffers;lcv++) {
+        psFree(buffers[lcv]);
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"following psMemCheckLeaks call should produce one instance.");
+
+    nLeaks = psMemCheckLeaks(currentId, &blks, stderr);
+
+    if (nLeaks != 1) {
+        psError(__FILE__,"psMemCheckLeaks should have found 1 leak, but found %d in %s.",nLeaks,__func__);
+        return 1;
+    }
+
+    if (blks[0]->lineno != lineMark) {
+        psError(__FILE__,"psMemCheckLeaks found a leak other than the expected one (line %d vs %d) in %s.",
+                lineMark, blks[0]->lineno, __func__);
+        return 1;
+    }
+
+    psFree(buffers[0]);
+    psFree(blks);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Testing psMemCheckLeaks again with a different leak location");
+    psMemCheckLeaks(currentId,NULL,stderr);
+
+    for (lcv=0;lcv<numBuffers;lcv++) {
+        lineMark = __LINE__+1;
+        buffers[lcv] = psAlloc(sizeof(int));
+    }
+
+    for (lcv=0;lcv<numBuffers-1;lcv++) {
+        psFree(buffers[lcv]);
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"following psMemCheckLeaks call should produce one error.");
+
+    nLeaks = psMemCheckLeaks(currentId, &blks, stderr);
+
+    if (nLeaks != 1) {
+        psError(__FILE__,"psMemCheckLeaks should have found 1 leak, but found %d in %s.",nLeaks,__func__);
+        return 1;
+    }
+
+    if (blks[0]->lineno != lineMark) {
+        psError(__FILE__,"psMemCheckLeaks found a leak other than the expected one in %s.",__func__);
+        return 1;
+    }
+
+    psFree(buffers[4]);
+    psFree(blks);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Testing psMemCheckLeaks again with multiple leak locations.");
+
+    for (lcv=0;lcv<numBuffers;lcv++) {
+        lineMark = __LINE__+1;
+        buffers[lcv] = psAlloc(sizeof(int));
+    }
+
+    for (lcv=0;lcv<numBuffers;lcv++) {
+        if (lcv%2 == 0) {
+            psFree(buffers[lcv]);
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"following psMemCheckLeaks call should produce two errors.");
+
+    nLeaks = psMemCheckLeaks(currentId, &blks, stderr);
+
+    if (nLeaks != 2) {
+        psError(__FILE__,"psMemCheckLeaks should have found 1 leak, but found %d in %s.",nLeaks,__func__);
+        return 1;
+    }
+
+    if (blks[0]->lineno != lineMark) {
+        psError(__FILE__,"psMemCheckLeaks found a leak other than the expected one in %s.",__func__);
+        return 1;
+    }
+
+    psFree(blks);
+    psFree(buffers[1]);
+    psFree(buffers[3]);
+
+    psMemCheckLeaks(currentId,NULL,NULL);
+    psMemCheckCorruption(1);
+
+    return 0;
+}
+
+int TPmemCorruption(void)
+{
+    int* buffer = NULL;
+    int oldValue = 0;
+    int corruptions = 0;
+    psMemProblemCallback cb;
+
+    psLogMsg(__func__,PS_LOG_INFO,"psMemCheckCorruption shall detect memory corruptions");
+
+    buffer = psAlloc(sizeof(int));
+
+    // cause memory corruption via buffer underflow
+    *buffer = 1;
+    buffer--;
+    oldValue = *buffer;
+    *buffer = 2;
+
+    problemCallbackCalled = 0;
+    cb = psMemProblemCallbackSet(memProblemCallback);
+
+    psLogMsg(__func__,PS_LOG_INFO,"psMemCheckCorruption should output an error message and "
+             "memProblemCallback callback should be called.");
+
+    corruptions = psMemCheckCorruption(0);
+
+    // restore the memory problem callback
+    psMemProblemCallbackSet(cb);
+
+    // restore the value, 'uncorrupting' the buffer
+    *buffer = oldValue;
+    buffer++;
+
+    psFree(buffer);
+
+    if (corruptions != 1) {
+        psError(__FILE__,"Expected one memory corruption but found %d in %s.",
+                corruptions, __func__);
+        return 1;
+    }
+
+    if (problemCallbackCalled != 1) {
+        psError(__FILE__,"The memProblemCallback was not invoked but should have been in %s",
+                __func__);
+        return 1;
+    }
+
+    return 0;
+
+}
+
+void memProblemCallback(const psMemBlock *ptr, const char *file, int lineno)
+{
+    psLogMsg(__func__,PS_LOG_INFO,"memory callback called for id %d (%s:%d).",
+             ptr->id, file, lineno);
+    problemCallbackCalled++;
+    return;
 }
 
Index: /trunk/psLib/test/sysUtils/verified/tst_psMemory.stderr
===================================================================
--- /trunk/psLib/test/sysUtils/verified/tst_psMemory.stderr	(revision 639)
+++ /trunk/psLib/test/sysUtils/verified/tst_psMemory.stderr	(revision 640)
@@ -34,5 +34,5 @@
 /----------------------------- TESTPOINT ------------------------------------------\
 |             TestFile: tst_psMemory.c                                             |
-|            TestPoint: psMemory{452-TPallocCallback}                              |
+|            TestPoint: psMemory{452/453-TPallocCallback}                          |
 |             TestType: Positive                                                   |
 \----------------------------------------------------------------------------------/
@@ -47,17 +47,52 @@
  <DATE> <TIME> <HOST> |I|memFreeCallback|block 4 was freed
 
----> TESTPOINT PASSED (psMemory{452-TPallocCallback} | tst_psMemory.c)
+---> TESTPOINT PASSED (psMemory{452/453-TPallocCallback} | tst_psMemory.c)
 
 /----------------------------- TESTPOINT ------------------------------------------\
 |             TestFile: tst_psMemory.c                                             |
-|            TestPoint: psMemory{TPFreeReferencedMemory}                           |
+|            TestPoint: psMemory{454-TPcheckLeaks}                                 |
 |             TestType: Positive                                                   |
 \----------------------------------------------------------------------------------/
 
-Allocating buffer.
-Freeing buffer after incrementing reference count.
+ <DATE> <TIME> <HOST> |I|TPcheckLeaks   |psMemCheckLeaks shall return the number of blocks above an ID that are still allocated
+ <DATE> <TIME> <HOST> |I|TPcheckLeaks   |following psMemCheckLeaks call should produce one instance.
+                   file:line ID
+         tst_psMemory.c:340  1
+ <DATE> <TIME> <HOST> |I|TPcheckLeaks   |Testing psMemCheckLeaks again with a different leak location
+ <DATE> <TIME> <HOST> |I|TPcheckLeaks   |following psMemCheckLeaks call should produce one error.
+                   file:line ID
+         tst_psMemory.c:370  11
+ <DATE> <TIME> <HOST> |I|TPcheckLeaks   |Testing psMemCheckLeaks again with multiple leak locations.
+ <DATE> <TIME> <HOST> |I|TPcheckLeaks   |following psMemCheckLeaks call should produce two errors.
+                   file:line ID
+         tst_psMemory.c:398  16
+         tst_psMemory.c:398  14
+
+---> TESTPOINT PASSED (psMemory{454-TPcheckLeaks} | tst_psMemory.c)
+
+/----------------------------- TESTPOINT ------------------------------------------\
+|             TestFile: tst_psMemory.c                                             |
+|            TestPoint: psMemory{455-TPmemCorruption}                              |
+|             TestType: Positive                                                   |
+\----------------------------------------------------------------------------------/
+
+ <DATE> <TIME> <HOST> |I|TPmemCorruption|psMemCheckCorruption shall detect memory corruptions
+ <DATE> <TIME> <HOST> |I|TPmemCorruption|psMemCheckCorruption should output an error message and memProblemCallback callback should be called.
+ <DATE> <TIME> <HOST> |E|psMemCheckCorruption|psMemCheckCorruption: memory block 1 is corrupted (0xdeadbeef 0x2deadbeef)
+ <DATE> <TIME> <HOST> |I|memProblemCallback|memory callback called for id 1 (psMemCheckCorruption:220).
+
+---> TESTPOINT PASSED (psMemory{455-TPmemCorruption} | tst_psMemory.c)
+
+/----------------------------- TESTPOINT ------------------------------------------\
+|             TestFile: tst_psMemory.c                                             |
+|            TestPoint: psMemory{456-TPFreeReferencedMemory}                       |
+|             TestType: Positive                                                   |
+\----------------------------------------------------------------------------------/
+
+ <DATE> <TIME> <HOST> |I|TPFreeReferencedMemory|memory reference count shall be incrementable/decrementable
+ <DATE> <TIME> <HOST> |I|TPFreeReferencedMemory|expect error from free as multiple referenced buffer is freed.
  <DATE> <TIME> <HOST> |E|p_psFree       |The buffer being freed is referenced elsewhere. Buffer's reference count was decremented instead.
- <DATE> <TIME> <HOST> |A|memProblemCallbackDefault|Detected a problem in the memory system at tst_psMemory.c:103
+ <DATE> <TIME> <HOST> |I|memProblemCallback|memory callback called for id 1 (tst_psMemory.c:141).
 
----> TESTPOINT PASSED (psMemory{TPFreeReferencedMemory} | tst_psMemory.c)
+---> TESTPOINT PASSED (psMemory{456-TPFreeReferencedMemory} | tst_psMemory.c)
 
