Index: trunk/psLib/test/astro/tap_psCoord.c
===================================================================
--- trunk/psLib/test/astro/tap_psCoord.c	(revision 11180)
+++ trunk/psLib/test/astro/tap_psCoord.c	(revision 11180)
@@ -0,0 +1,371 @@
+/** @file  tst_psCoord.c
+*
+*  @brief The code will ...
+*
+*  @author GLG, MHPCC
+*
+*  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-01-19 20:42:21 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define ORDER_X 2
+#define ORDER_Y 3
+#define ORDER_Z 4
+#define ORDER_T 5
+#define N 10
+#define COLOR 1.0
+#define MAGNITUDE 1.0
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(57);
+
+    // Test psPlaneAlloc()
+    {
+        psMemId id = psMemGetId();
+        psPlane *myP = psPlaneAlloc();
+        ok(myP != NULL, "psPlaneAlloc() returned non-NULL");
+        skip_start(myP == NULL, 4, "Skipping tests because psPlaneAlloc() returned NULL");
+        ok(isnan(myP->x), "psPlane->x is NAN");
+        ok(isnan(myP->y), "psPlane->y is NAN");
+        ok(isnan(myP->xErr), "psPlane->xErr is NAN");
+        ok(isnan(myP->yErr), "psPlane->yErr is NAN");
+        skip_end();
+        psFree(myP);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test psPlaneTransformAlloc()
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *myPT = psPlaneTransformAlloc(ORDER_X, ORDER_Y);
+        ok(myPT != NULL, "psPlaneTransformAlloc() returned non-NULL");
+        skip_start(myPT == NULL, 6, "Skipping tests because psPlaneTransformAlloc() returned NULL");
+        ok(myPT->x->nX == ORDER_X, "psPlaneTransform->x->nX set correctly");
+        ok(myPT->y->nX == ORDER_X, "psPlaneTransform->y->nX set correctly");
+        ok(myPT->x->nY == ORDER_Y, "psPlaneTransform->x->nY set correctly");
+        ok(myPT->y->nY == ORDER_Y, "psPlaneTransform->y->nY set correctly");
+        psFree(myPT);
+
+        // Attempt to specify negative x order and verify NULL returned and
+        // errror message generated
+        myPT = psPlaneTransformAlloc(-1, 1);
+        ok(myPT == NULL, "psPlaneTransformAlloc(-1, 1) returned NULL");
+        psFree(myPT);
+
+        myPT = psPlaneTransformAlloc(1, -1);
+        ok(myPT == NULL, "psPlaneTransformAlloc(1, -11) returned NULL");
+        psFree(myPT);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test psPlaneDistortAlloc()
+    {
+        psMemId id = psMemGetId();
+        psPlaneDistort *myPD = psPlaneDistortAlloc(ORDER_X, ORDER_Y, ORDER_Z, ORDER_T);
+        ok(myPD != NULL, "psPlaneDistortAlloc() returned non-NULL");
+        skip_start(myPD == NULL, 12, "Skipping tests because psPlaneDistortAlloc() returned NULL");
+        ok(myPD->x->nX == ORDER_X, "psPlaneDistort->x->nX set correctly");
+        ok(myPD->x->nY == ORDER_Y, "psPlaneDistort->x->nY set correctly");
+        ok(myPD->x->nZ == ORDER_Z, "psPlaneDistort->x->nZ set correctly");
+        ok(myPD->x->nT == ORDER_T, "psPlaneDistort->x->nT set correctly");
+        ok(myPD->y->nX == ORDER_X, "psPlaneDistort->y->nX set correctly");
+        ok(myPD->y->nY == ORDER_Y, "psPlaneDistort->y->nY set correctly");
+        ok(myPD->y->nZ == ORDER_Z, "psPlaneDistort->y->nZ set correctly");
+        ok(myPD->y->nT == ORDER_T, "psPlaneDistort->y->nT set correctly");
+        psFree(myPD);
+
+        myPD = psPlaneDistortAlloc(-1, 1, 1, 1);
+        ok(myPD == NULL, "psPlaneDistortAlloc(-1, 1, 1, 1) returned NULL");
+        psFree(myPD);
+        myPD = psPlaneDistortAlloc(1, -1, 1, 1);
+        ok(myPD == NULL, "psPlaneDistortAlloc(1, -1, 1, 1) returned NULL");
+        psFree(myPD);
+        myPD = psPlaneDistortAlloc(1, 1, -1, 1);
+        ok(myPD == NULL, "psPlaneDistortAlloc(1, 1, -1, 1) returned NULL");
+        psFree(myPD);
+        myPD = psPlaneDistortAlloc(1, 1, 1, -1);
+        ok(myPD == NULL, "psPlaneDistortAlloc(1, 1, 1, -1) returned NULL");
+        psFree(myPD);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // We test psPlaneTransformApply() on a simple identity transformation for few x,y pairs.
+    {
+        psMemId id = psMemGetId();
+        psPlane* in = psPlaneAlloc();
+        ok(in != NULL, "psPlaneAlloc() returned non-NULL");
+        skip_start(in == NULL, 2, "Skipping tests because psPlaneAlloc() returned NULL");
+        psPlaneTransform* pt = psPlaneTransformAlloc(2,2);
+        ok(pt != NULL, "psPlaneTransformAlloc() returned non-NULL");
+        skip_start(pt == NULL, 1, "Skipping tests because psPlaneTransformAlloc() returned NULL");
+
+        // Set transform coefficients so the x coord input will equal x coord output, same for y
+        pt->x->coeff[1][0] = 1.0;
+        pt->y->coeff[0][1] = 1.0;
+
+        // Apply transform for several points
+        bool errorFlag = false;
+        for (psS32 i = 0; i < N; i++)
+        {
+            in->x = (psF64) i;
+            in->y = (psF64) (i + 5.0);
+            in->xErr = 0.0;
+            in->yErr = 0.0;
+
+            // XXX: psPlane *out = psPlaneTransformApply(out, pt, in); causes a seg-fault.  Why?
+            psPlane *out = psPlaneTransformApply(NULL, pt, in);
+            if(out == NULL) {
+                diag("ERROR: psPlaneTransformApply() returned NULL");
+                errorFlag = true;
+            } else {
+                if (FLT_EPSILON < fabs(out->x - in->x)) {
+                    diag("ERROR: out.x is %lf, should be %lf", out->x, in->x);
+                    errorFlag = true;
+                }
+
+                if (FLT_EPSILON < fabs(out->y - in->y)) {
+                    diag("ERROR: out.y is %lf, should be %lf", out->y, in->y);
+                    errorFlag = true;
+                }
+            }
+            psFree(out);
+        }
+        ok(!errorFlag, "psPlaneTransformApply() successful on several data points");
+        psFree(pt);
+        psFree(in);
+        skip_end();
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneTransformApply should generate error message for NULL psPlaneTransform
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlane* in = psPlaneAlloc();
+        psPlane *tmpPL = psPlaneTransformApply(NULL, NULL, in);
+        ok(tmpPL == NULL, "psPlaneTransformApply(NULL, NULL, in) returned NULL");
+        psFree(in);
+        psFree(tmpPL);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneTransformApply should generate error message for NULL x coeff psPlaneTransform
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psPlaneTransform *pt = psPlaneTransformAlloc(2,2);
+        psFree(pt->x);
+        pt->x = NULL;
+        psPlane *tmpPL = psPlaneTransformApply(NULL, pt, in);
+        ok(tmpPL == NULL, "psPlaneTransformApply(NULL, pt, in) returned NULL with NULL x coeff psPlaneTransform");
+        psFree(in);
+        psFree(pt);
+        psFree(tmpPL);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneTransformApply Should generate error message for NULL y coeff psPlaneTransform");
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlane* in = psPlaneAlloc();
+        psPlaneTransform* pt = psPlaneTransformAlloc(2,2);
+        psFree(pt->y);
+        pt->y = NULL;
+        psPlane *tmpPL = psPlaneTransformApply(NULL, pt, in);
+        ok(tmpPL == NULL, "psPlaneTransformApply(NULL, pt, in) returned NULL with NULL y coeff psPlaneTransform");
+        psFree(tmpPL);
+        psFree(pt);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneTransformApply() should generate error message for NULL psPlane");
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlaneTransform* pt = psPlaneTransformAlloc(2,2);
+        psPlane *tmpPL = psPlaneTransformApply(NULL, pt, NULL);
+        ok(tmpPL == NULL, "psPlaneTransformApply(NULL, pt, NULL) did not return NULL");
+        psFree(tmpPL);
+        psFree(pt);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // We test psPlaneDistortApply() on a simple identity transformation for few x,y pairs.
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        ok(in != NULL, "psPlaneAlloc() returned non-NULL");
+        skip_start(in == NULL, 1, "Skipping tests because psPlaneAlloc() returned NULL");
+        psPlaneDistort *pt = psPlaneDistortAlloc(2, 2, 2, 2);
+        ok(pt != NULL, "psPlaneDistortAlloc() returned non-NULL");
+        skip_start(pt == NULL, 1, "Skipping tests because psPlaneTransformAlloc() returned NULL");
+
+        pt->x->coeff[1][0][0][0] = 1.0;
+        pt->x->coeff[0][0][1][0] = 1.0;
+        pt->x->coeff[0][0][0][1] = 1.0;
+        pt->y->coeff[0][1][0][0] = 1.0;
+        pt->y->coeff[0][0][1][0] = 1.0;
+        pt->y->coeff[0][0][0][1] = 1.0;
+
+        bool errorFlag = false;
+        for (psS32 i = 0; i < N; i++)
+        {
+            in->x = (psF64) i;
+            in->y = (psF64) (i + 5.0);
+            in->xErr = 0.0;
+            in->yErr = 0.0;
+
+            // XXX: psPlane *out = psPlaneDistortApply(out, pt, in, COLOR, MAGNITUDE); generates a seg-fault.  Why?
+            psPlane *out = psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE);
+            if(out == NULL) {
+                diag("ERROR: psPlaneDistortApply() returned NULL");
+                errorFlag = true;
+            } else {
+                if (FLT_EPSILON < fabs(out->x - COLOR - MAGNITUDE - in->x)) {
+                    diag("ERROR: out->x is %lf, should be %lf",
+                         out->x, in->x + COLOR + MAGNITUDE);
+                    errorFlag = true;
+                }
+                if (FLT_EPSILON < fabs(out->y - COLOR - MAGNITUDE - in->y)) {
+                    diag("ERROR: out->y is %lf, should be %lf",
+                         out->y, in->y + COLOR + MAGNITUDE);
+                    errorFlag = true;
+                }
+            }
+            psFree(out);
+        }
+        ok(!errorFlag, "psPlaneDistortApply() successful on several data points");
+        psFree(in);
+        psFree(pt);
+        skip_end();
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneDistortApply() should generate an error message for null psPlaneDistort
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psPlane *tmpPL = psPlaneDistortApply(NULL, NULL, in, COLOR, MAGNITUDE);
+        ok(tmpPL == NULL, "psPlaneDistortApply(NULL, NULL, in, COLOR, MAGNITUDE) returned NULL");
+        psFree(tmpPL);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneDistortApply() should generate an error message for null x member psPlaneDistort
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psPlaneDistort *pt = psPlaneDistortAlloc(2, 2, 2, 2);
+        psFree(pt->x);
+        pt->x = NULL;
+        psPlane *tmpPL = psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE);
+        ok(tmpPL == NULL, "psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE) with NULL pt->x member");
+        psFree(tmpPL);
+        psFree(pt);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneDistortApply() should generate an error message for null y member psPlaneDistort
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psPlaneDistort *pt = psPlaneDistortAlloc(2, 2, 2, 2);
+        psFree(pt->y);
+        pt->y = NULL;
+        psPlane *tmpPL = psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE);
+        ok(tmpPL == NULL, "psPlaneDistortApply(NULL, pt, in, COLOR, MAGNITUDE) with NULL pt->y member");
+        psFree(tmpPL);
+        psFree(pt);
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPlaneDistortApply() should generate an error message for null input psPlane
+    if (1) {
+        psMemId id = psMemGetId();
+        psPlaneDistort *pt = psPlaneDistortAlloc(2, 2, 2, 2);
+        psPlane *tmpPL = psPlaneDistortApply(NULL, pt, NULL, COLOR, MAGNITUDE);
+        ok(tmpPL == NULL, "psPlaneDistortApply(NULL, pt, NULL, COLOR, MAGNITUDE) returned NULL");
+        psFree(tmpPL);
+        psFree(pt);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test psPixelsTransform()
+    // psPixelsTransform() should generate error message for NULL input pixels
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 3);
+        psPixels *output = psPixelsTransform(NULL, NULL, trans);
+        ok(output == NULL, "psPixelsTransform(NULL, NULL, trans) returned NULL");
+        psFree(trans);
+        psFree(output);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psPixelsTransform() should generate error message for NULL input PlaneTransform
+    {
+        psMemId id = psMemGetId();
+        psPixels *input = psPixelsAlloc(2);
+        psPixels *output = psPixelsTransform(NULL, input, NULL);
+        ok(output == NULL, "psPixelsTransform(NULL, input, NULL) returned NULL");
+        psFree(output);
+        psFree(input);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // We test psPixelsTransform() on several data points
+    {
+        psMemId id = psMemGetId();
+        psPixels *input = psPixelsAlloc(2);
+        input->n = 2;
+        input->data[0].x = 1.0;
+        input->data[0].y = 1.0;
+        input->data[1].x = 1.0;
+        input->data[1].y = 6.0;
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 3);
+        trans->x->coeff[0][0] = 0;
+        trans->x->coeff[1][0] = 1.0;
+        trans->y->coeff[0][0] = 0;
+        trans->y->coeff[0][0] = 0;
+        trans->y->coeff[0][2] = 0.5;
+
+        // XXX: Fix this
+        psPixels *output = psPixelsTransform(NULL, input, trans);
+        int nExpected = 9;
+        if (output->n != nExpected)
+        {
+            diag("ERROR: psPixelsTransform failed to return the expected number of pixels.\n");
+            printf("\n output returned with %ld pixels\n\n", output->n);
+            for (int i = 0; i < output->n; i++) {
+                printf("  (%6.2lf, %6.2lf) pixel %d\n", output->data[i].x, output->data[i].y, i+1);
+            }
+            return 3;
+        }
+
+        psFree(trans);
+        psFree(input);
+        psFree(output);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    /* HERE
+    */
+}
+
Index: trunk/psLib/test/astro/tap_psCoord01.c
===================================================================
--- trunk/psLib/test/astro/tap_psCoord01.c	(revision 11180)
+++ trunk/psLib/test/astro/tap_psCoord01.c	(revision 11180)
@@ -0,0 +1,1047 @@
+/**  @file  tst_psCoord01.c
+*
+*    @brief  The code will test several functions with PSLib source file
+*            psCoord.c
+*
+*    @author Eric Van Alst, MHPCC
+*
+* XXX: must do (r,d) -> (x, y) -> (r, d) test to ensure correctness.
+* XXX: The (Xs, Ys) scales are not be used properly.
+* XXX: Much work remains to be done.  The original tests defined correct
+*      input/output pairs and compared results.  It's not clear how those
+*      values were obtained, and they nearly all fail now.
+*
+*    @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*    @date  $Date: 2007-01-19 20:42:21 $
+*    @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*    @date  $Date: 2007-01-19 20:42:21 $
+*
+*    Copyright 2005 Maui High Performance Computing Center, Univ. of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define ERROR_TOL    0.0001
+#define TESTPOINTS   4
+#define DEG_INC   30.0
+
+#define MY_TINY 0.0001
+#define PS_COMPARE_TINY_THEN_PRINT_ERROR(ACTUAL, EXPECT, TESTSTATUS) \
+if (MY_TINY < fabs(EXPECT - ACTUAL)) { \
+    diag("%s is %lg, should be %lg", #ACTUAL, ACTUAL, EXPECT, TESTSTATUS); \
+    errorFlag = true; \
+}
+
+
+//  alpha, delta, alpha-center, delta-center, scale-x, scale-y
+psF64 projectionTestPoint[TESTPOINTS][6] = {
+            {  0.785398,  0.785398,  0.000000,  0.000000,  1.000000,  1.000000 },
+            {  0.100000,  1.500000,  0.500000,  0.250000,  1.000000,  1.000000 },
+            {  0.628319,  0.448799,  0.000000,  0.000000,  0.250000,  0.750000 },
+            { -1.047196,  0.222222, -0.250000,  0.000000,  1.500000,  1.250000 }
+        };
+
+// Expected values for TAN
+psF64 projectionTanExpected[TESTPOINTS][2] = {
+            { -1.000000, -1.414214 },
+            {  0.088884, -3.066567 },
+            { -0.181636, -0.446444 },
+            {  1.535818, -0.404231 }
+        };
+
+// Expected values for SIN
+psF64 projectionSinExpected[TESTPOINTS][2] = {
+            { -0.500000, -0.707101 },
+            {  0.027546, -0.950366 },
+            { -0.132394, -0.325413 },
+            {  1.046712, -0.275497 }
+        };
+
+// Expected values for AIT
+psF64 projectionAitExpected[TESTPOINTS][2] = {
+            { -0.549175,  0.523375 },
+            {  0.027895,  0.313807 },
+            { -0.162822,  0.607646 },
+            {  1.455312,  0.955388 }
+        };
+
+// Expected values for PAR
+psF64 projectionParExpected[TESTPOINTS][2] = {
+            { -0.541244,  0.545532 },
+            {  0.027703,  0.329366 },
+            { -0.157157,  0.633550 },
+            {  1.432951,  0.971372 }
+        };
+
+// Testpoints, offset and expected values for psSphereSetOffset test
+#define TESTPOINTS_OFFSET  4
+psF64 setOffsetTestpoint[TESTPOINTS_OFFSET][2] = {
+            { 0.50,  0.50 },
+            {-0.50,  0.50 },
+            { 0.00,  0.00 },
+            { 1.50, -0.10 }
+        };
+
+psF64 setOffsetOffset[TESTPOINTS_OFFSET][2] = {
+            { 0.190761, -0.272205 },
+            {-0.553049, -0.460926 },
+            { 0.100335,-14.172222 },
+            {14.172222, -0.100335 }
+        };
+
+psF64 setOffsetResult[TESTPOINTS_OFFSET][2] = {
+            //XXX: Eugene says his values are correct, so i'm changing these values to the output.
+            //            { 0.25,  0.75 },
+            //            { 0.20,  0.80 },
+            //            {-0.10,  1.50 },
+            //            { 0.00,  0.00 }
+            { 0.68702,   0.230294},
+            { -0.966388,  0.0608434 },
+            {0.10,  -1.50 },
+            { 3.00141, -0.0140538  }
+        };
+
+psF64 getOffsetTestpoint1[TESTPOINTS_OFFSET][2] = {
+            { 0.00,  0.00 },
+            {-0.25,  0.50 },
+            { 0.50, -0.25 },
+            { 0.25, -0.10 }
+        };
+
+psF64 getOffsetTestpoint2[TESTPOINTS_OFFSET][2] = {
+            { 0.75,  0.25 },
+            { 0.40, -0.60 },
+            { 1.50,  0.50 },
+            { 0.10,  0.75 }
+        };
+
+psF64 getOffsetResult[TESTPOINTS_OFFSET][2] = {
+            //XXX: Eugene says his values are correct, so i'm changing these values to the output.
+            //            { -0.931596, -0.348976 },
+            //            { -1.632830,  2.649629 },
+            //            { -2.166795, -1.707211 },
+            //            {  0.167752, -1.151351 }
+            { 0.931596, 0.348976 },
+            { 1.632830,  -2.649629 },
+            { 2.166795, 1.707211 },
+            {  -0.167752, 1.151351 }
+        };
+
+
+psS32 main( psS32 argc, char *argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(87);
+
+    // psProjectionAlloc()
+    {
+        psMemId id = psMemGetId();
+        psProjection *myProjection = psProjectionAlloc(1.1, 2.2, 3.3, 4.4, PS_PROJ_AIT);
+        ok(myProjection != NULL, "psProjectionAlloc() returned non-NULL");
+        ok(myProjection->R == 1.1, "psProjection->R set correctly");
+        ok(myProjection->D == 2.2, "psProjection->D set correctly");
+        ok(myProjection->Xs == 3.3, "psProjection->Xs set correctly");
+        ok(myProjection->Ys == 4.4, "psProjection->Ys set correctly");
+        ok(myProjection->type == PS_PROJ_AIT, "psProjection->type set correctly");
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testProjectTan()
+    // We do a psProject() then a psDeproject() on several data points and
+    // verify that we produce the original data point.
+    // XXX: This test currently fails.
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psSphere *inTest = NULL;
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+
+        // Perform projecton on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            in->r = projectionTestPoint[i][0];
+            in->d = projectionTestPoint[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            psPlane *out = psProject(in, myProjection);
+            if(out == NULL) {
+                diag("psProject() returned NULL");
+                errorFlag = true;
+            } else {
+                inTest = psDeproject(out, myProjection);
+                if(fabs(out->x - projectionTanExpected[i][0]) > ERROR_TOL) {
+                    diag("TEST ERROR: Testpoint %d  psPlane->x = %lg  expected %lg",
+                         i,out->x, projectionTanExpected[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->y - projectionTanExpected[i][1]) > ERROR_TOL) {
+                    diag("TEST ERROR: Testpoint % d psPlane->y = %lg  expected %lg",
+                         i,out->y, projectionTanExpected[i][1]);
+                    errorFlag = true;
+                }
+
+                // Verify output is as expected
+                if(fabs(in->r - inTest->r) > ERROR_TOL) {
+                    diag("TEST ERROR: (in->r, inTest->r) (%.2f %.2f)\n", in->r, inTest->r);
+                    errorFlag = true;
+                }
+                if(fabs(in->d - inTest->d) > ERROR_TOL) {
+                    diag("TEST ERROR: (in->d, inTest->d) (%.2f %.2f)\n", in->d, inTest->d);
+                    errorFlag = true;
+                }
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+            psFree(inTest);
+            psFree(out);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectTan()
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+
+        // Perform deprojection on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and projection members
+            in->x = projectionTanExpected[i][0];
+            in->y = projectionTanExpected[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform deprojection
+            psSphere *out = psDeproject(in, myProjection);
+
+            // Verify output is not NULL
+            if(out == NULL) {
+                diag("psDeproject() returned NULL");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->r = %lg  expected %lg",
+                         i,out->r,projectionTestPoint[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->d = %lg expected %lg",
+                         i, out->d, projectionTestPoint[i][1]);
+                    errorFlag = true;
+                }
+            }
+            psFree(out);
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testProjectSin()
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_SIN);
+
+        // Perform projecton on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and project members
+            in->r = projectionTestPoint[i][0];
+            in->d = projectionTestPoint[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform projection
+            psPlane *out = psProject(in, myProjection);
+
+            // Verify output not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->x - projectionSinExpected[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psPlane->x = %lg  expected %lg",
+                         i,out->x, projectionSinExpected[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->y - projectionSinExpected[i][1]) > ERROR_TOL) {
+                    diag("Testpoint % d  psPlane->y = %lg  expected %lg",
+                         i,out->y, projectionSinExpected[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectSin()
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_SIN);
+
+        // Perform deprojection on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and projection members
+            in->x = projectionSinExpected[i][0];
+            in->y = projectionSinExpected[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform deprojection
+            psSphere *out = psDeproject(in, myProjection);
+
+            // Verify output is not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->r = %lg  expected %lg",
+                         i,out->r,projectionTestPoint[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->d = %lg expected %lg",
+                         i, out->d, projectionTestPoint[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testProjectAit()
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_AIT);
+
+        // Perform projecton on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and project members
+            in->r = projectionTestPoint[i][0];
+            in->d = projectionTestPoint[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform projection
+            psPlane *out = psProject(in, myProjection);
+
+            // Verify output not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->x - projectionAitExpected[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psPlane->x = %lg  expected %lg",
+                         i,out->x, projectionAitExpected[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->y - projectionAitExpected[i][1]) > ERROR_TOL) {
+                    diag("Testpoint % d  psPlane->y = %lg  expected %lg",
+                         i,out->y, projectionAitExpected[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectAit()
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_AIT);
+
+        // Perform deprojection on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and projection members
+            in->x = projectionAitExpected[i][0];
+            in->y = projectionAitExpected[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform deprojection
+            psSphere *out = psDeproject(in, myProjection);
+
+            // Verify output is not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->r = %lg  expected %lg",
+                         i,out->r,projectionTestPoint[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->d = %lg expected %lg",
+                         i, out->d, projectionTestPoint[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testProjectPar()
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_PAR);
+
+        // Perform projecton on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and project members
+            in->r = projectionTestPoint[i][0];
+            in->d = projectionTestPoint[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform projection
+            psPlane *out = psProject(in, myProjection);
+
+            // Verify output not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->x - projectionParExpected[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psPlane->x = %lg  expected %lg",
+                         i,out->x, projectionParExpected[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->y - projectionParExpected[i][1]) > ERROR_TOL) {
+                    diag("Testpoint % d  psPlane->y = %lg  expected %lg",
+                         i,out->y, projectionParExpected[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectPar()
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_PAR);
+
+        // Perform deprojection on various test points
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize input and projection members
+            in->x = projectionParExpected[i][0];
+            in->y = projectionParExpected[i][1];
+            myProjection->R = projectionTestPoint[i][2];
+            myProjection->D = projectionTestPoint[i][3];
+            myProjection->Xs = projectionTestPoint[i][4];
+            myProjection->Ys = projectionTestPoint[i][5];
+
+            // Perform deprojection
+            psSphere *out = psDeproject(in, myProjection);
+
+            // Verify output is not NULL
+            if(out == NULL) {
+                diag("Return null not expected");
+                errorFlag = true;
+            } else {
+                // Verify output is as expected
+                if(fabs(out->r - projectionTestPoint[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->r = %lg  expected %lg",
+                         i,out->r,projectionTestPoint[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - projectionTestPoint[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d  psSphere->d = %lg expected %lg",
+                         i, out->d, projectionTestPoint[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+            ok(!errorFlag, "psProject()/psDeproject() successful for test point %d\n", i);
+        }
+
+        psFree(in);
+        psFree(myProjection);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psProject(): Invoke function with null coordinate argument
+    // Following should generate an error message for null coord arg
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+        psPlane *out = psProject(NULL, myProjection);
+        ok(out == NULL, "psProject(NULL, xxx) returned NULL");
+        psFree(myProjection);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Invoke function with null projection argument
+    // Following should generate an error message for null projection arg
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *in = psSphereAlloc();
+        psPlane *out = psProject(in, NULL);
+        ok(out == NULL, "psProject(in, NULL) returned NULL");
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Invoke function with unallowed projection type
+    // Following should generate an error message for unallowed projection type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+        myProjection->type = PS_PROJ_NTYPE;
+        psSphere *in = psSphereAlloc();
+        psPlane *out = psProject(in,myProjection);
+        ok(out == NULL, "psProject(in, out) returned NULL with unallowed projection type");
+        psFree(myProjection);
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testDeprojectFail()
+    psMemId id = psMemGetId();
+
+
+    // Invoke function with null coordinate argument
+    // Following should generate an error message for null coord arg
+    // XXX: We do not test the error generation
+    {
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+        psSphere *out = psDeproject(NULL, myProjection);
+        ok(out == NULL, "psDeproject(NULL, myProjection) returned NULL");
+        psFree(myProjection);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with null projection argument
+    // Following should generate an error message for null projection arg
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psPlane *in = psPlaneAlloc();
+        psSphere *out = psDeproject(in, NULL);
+        ok(out == NULL, "psDeproject(in, NULL) returned NULL");
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Invoke function with unallowed projection type
+    // Following should generate an error message for unallowed projection type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psProjection *myProjection = psProjectionAlloc(0.0,0.0,1.0,1.0,PS_PROJ_TAN);
+        psPlane *in = psPlaneAlloc();
+        myProjection->type = PS_PROJ_NTYPE;
+        psSphere *out = psDeproject(in,myProjection);
+        ok(out == NULL, "psDeproject(in,myProjection) returned NULL with unallowed projection type");
+        psFree(myProjection);
+        psFree(in);
+        psFree(out);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // testSetOffsetSphere()
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = NULL;
+        psSphere *offset = psSphereAlloc();
+        psSphere *tmpOffset = psSphereAlloc();
+        bool errorFlag = false;
+
+        // Initialize first position
+        position1->r = DEG_TO_RAD(90.0);
+        position1->d = DEG_TO_RAD(45.0);
+        position1->rErr = 0.0;
+        position1->dErr = 0.0;
+
+        //  Using various offset verify spherical offset
+        //  Use all the valid unit types
+        for (psF64 r = 0.0; r < 180.0; r += DEG_INC)
+        {
+            for (psF64 d = 0.0; d < 90.0; d += DEG_INC) {
+
+                offset->r = DEG_TO_RAD(r);
+                offset->d = DEG_TO_RAD(d);
+                offset->rErr = 0.0;
+                offset->dErr = 0.0;
+
+                position2 = psSphereSetOffset(position1, offset, PS_SPHERICAL, PS_RADIAN);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 1);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 2);
+                psFree(position2);
+
+                tmpOffset->r = RAD_TO_DEG(offset->r);
+                tmpOffset->d = RAD_TO_DEG(offset->d);
+                tmpOffset->rErr = 0.0;
+                tmpOffset->dErr = 0.0;
+                position2 = psSphereSetOffset(position1, tmpOffset, PS_SPHERICAL, PS_DEGREE);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 3);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 4);
+                psFree(position2);
+
+                tmpOffset->r = RAD_TO_MIN(offset->r);
+                tmpOffset->d = RAD_TO_MIN(offset->d);
+                tmpOffset->rErr = 0.0;
+                tmpOffset->dErr = 0.0;
+                position2 = psSphereSetOffset(position1, tmpOffset, PS_SPHERICAL, PS_ARCMIN);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 5);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 6);
+                psFree(position2);
+
+                tmpOffset->r = RAD_TO_SEC(offset->r);
+                tmpOffset->d = RAD_TO_SEC(offset->d);
+                tmpOffset->rErr = 0.0;
+                tmpOffset->dErr = 0.0;
+                position2 = psSphereSetOffset(position1, tmpOffset, PS_SPHERICAL, PS_ARCSEC);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->r, (position1->r + offset->r), 7);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(position2->d, (position1->d + offset->d), 8);
+                psFree(position2);
+            }
+        }
+        ok(!errorFlag, "psSphereSetOffset() successful on several dat points");
+
+        psFree(position1);
+        psFree(offset);
+        psFree(tmpOffset);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to call function with null input coordinate
+    // Following should generate error message null input coord
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *offset = psSphereAlloc();
+        psSphere *position2 = psSphereSetOffset(NULL, offset, PS_LINEAR, PS_ARCSEC);
+        ok(position2 == NULL, "psSphereSetOffset() returned NULL with NULL input coordinate");
+        psFree(position2);
+        psFree(offset);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to call function with null offset
+    // Following should generate error message null offset
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereSetOffset(position1, NULL, PS_LINEAR, PS_ARCSEC);
+        ok(position2 == NULL, "psSphereSetOffset() returned NULL with NULL offset");
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to call function with unallowed mode
+    // Following should generate error message unallowed mode
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *offset = psSphereAlloc();
+        psSphere *position2 = psSphereSetOffset(position1, offset, 0x54321, 0);
+        ok(position2 == NULL, "psSphereSetOffset() returned NULL with unallowed mode");
+        psFree(position1);
+        psFree(position2);
+        psFree(offset);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to call function with unallowed unit
+    // Following should generate an error message unallowed unit
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *offset = psSphereAlloc();
+        psSphere *position2 = psSphereSetOffset(position1, offset, PS_SPHERICAL, 0x54321);
+        ok(position2 == NULL, "psSphereSetOffset() returned NULL with unallowed unit");
+        psFree(position1);
+        psFree(position2);
+        psFree(offset);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testSetOffsetLinear()
+    {
+        psMemId id = psMemGetId();
+        psSphere *coord = psSphereAlloc();
+        psSphere *offset = psSphereAlloc();
+        psSphere *out = NULL;
+        bool errorFlag = false;
+
+        for(psS32 i = 0; i < TESTPOINTS_OFFSET; i++)
+        {
+            bool errorFlag = false;
+            coord->r = setOffsetTestpoint[i][0];
+            coord->d = setOffsetTestpoint[i][1];
+
+            offset->r = setOffsetOffset[i][0];
+            offset->d = setOffsetOffset[i][1];
+
+            out = psSphereSetOffset(coord, offset, PS_LINEAR, PS_RADIAN);
+
+            if(fabs(out->r - setOffsetResult[i][0]) > ERROR_TOL) {
+                diag("Testpoint %d: Result out->r = %lg not equal to expected %lg",
+                     i, out->r, setOffsetResult[i][0]);
+                errorFlag = true;
+            }
+            if(fabs(out->d - setOffsetResult[i][1]) > ERROR_TOL) {
+                diag("Testpoint %d: Result out->d = %lg not equal to expected %lg",
+                     i,out->d, setOffsetResult[i][1]);
+                errorFlag = true;
+            }
+
+            psFree(out);
+        }
+        psFree(coord);
+        psFree(offset);
+        ok(!errorFlag, "psSphereSetOffset(), linear, successful on several data points");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testGetOffsetSphere()
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        psSphere *offset = NULL;
+        bool errorFlag = false;
+        position1->r = DEG_TO_RAD(90.0);
+        position1->d = DEG_TO_RAD(45.0);
+        position1->rErr = 0.0;
+        position1->dErr = 0.0;
+
+        for (psF64 r = 0.0; r < 180.0;r += DEG_INC)
+        {
+            for (psF64 d = 0.0;d < 90.0; d += DEG_INC) {
+                position2->r = DEG_TO_RAD(r);
+                position2->d = DEG_TO_RAD(d);
+                position2->rErr = 0.0;
+                position2->dErr = 0.0;
+
+                offset = psSphereGetOffset( position1,  position2,
+                                            PS_SPHERICAL, PS_RADIAN);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 1);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 1);
+                psFree(offset);
+
+                offset = psSphereGetOffset( position1, position2,
+                                            PS_SPHERICAL, PS_DEGREE);
+                offset->r = DEG_TO_RAD(offset->r);
+                offset->d = DEG_TO_RAD(offset->d);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 2);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 3);
+                psFree(offset);
+
+                offset = psSphereGetOffset( position1,  position2,
+                                            PS_SPHERICAL, PS_ARCMIN);
+                offset->r = MIN_TO_RAD(offset->r);
+                offset->d = MIN_TO_RAD(offset->d);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 2);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 3);
+                psFree(offset);
+
+                offset = psSphereGetOffset( position1,  position2,
+                                            PS_SPHERICAL, PS_ARCSEC);
+                offset->r = SEC_TO_RAD(offset->r);
+                offset->d = SEC_TO_RAD(offset->d);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->r, (position2->r - position1->r), 2);
+                PS_COMPARE_TINY_THEN_PRINT_ERROR(offset->d, (position2->d - position1->d), 3);
+                psFree(offset);
+            }
+        }
+        psFree(position1);
+        psFree(position2);
+        ok(!errorFlag, "psSphereSetOffset(), linear, successful on several data points");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with null position 1 parameter
+    // Following should generate an error message for null position
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position2 = psSphereAlloc();
+        psSphere *offset = psSphereGetOffset(NULL, position2, PS_LINEAR, 0);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with null position 1 parameter");
+        psFree(offset);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with null position 2 parameter
+    // Following should generate an error message for null position
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *offset = psSphereGetOffset(position1, NULL, PS_LINEAR, 0);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with null position 2 parameter");
+        psFree(offset);
+        psFree(position1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with unallowed mode
+    // Following should generate an error message for unallowed mode
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        psSphere *offset = psSphereGetOffset(position1, position2, 0x54321, 0);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with unallowed mode");
+        psFree(offset);
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with unallowed unit type
+    // Following should generate an error message for unallowed unit type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        psSphere *offset = psSphereGetOffset(position1, position2, PS_SPHERICAL, 0x54321);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with unallowed unit type");
+        psFree(offset);
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with coordinate 1 declination value 90.0 degree
+    // Following should generate warning message
+    // XXX: We do not test the warning generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        position1->d = DEG_TO_RAD(90.0);
+        psSphere *offset = psSphereGetOffset(position1, position2, PS_SPHERICAL, PS_RADIAN);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with coordinate 1 declination value 90.0 degree");
+        psFree(offset);
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to invoke function with coordinate 2 declination value 90.0 degree
+    // Following should generate warning message
+    // XXX: We do not test the warning generation
+    {
+        psMemId id = psMemGetId();
+        psSphere *position1 = psSphereAlloc();
+        psSphere *position2 = psSphereAlloc();
+        position1->d = DEG_TO_RAD(45.0);
+        position2->d = DEG_TO_RAD(90.0);
+        psSphere *offset = psSphereGetOffset(position1, position2, PS_SPHERICAL, PS_RADIAN);
+        ok(offset == NULL, "psSphereGetOffset() returned NULL with coordinate 2 declination value 90.0 degree");
+        psFree(offset);
+        psFree(position1);
+        psFree(position2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testGetOffsetLinear()
+    {
+        psMemId id = psMemGetId();
+        psSphere *coord1 = psSphereAlloc();
+        psSphere *coord2 = psSphereAlloc();
+        bool errorFlag = false;
+
+        for(psS32 i = 0; i < TESTPOINTS_OFFSET; i++)
+        {
+            bool errorFlag = false;
+            coord1->r = getOffsetTestpoint1[i][0];
+            coord1->d = getOffsetTestpoint1[i][1];
+            coord2->r = getOffsetTestpoint2[i][0];
+            coord2->d = getOffsetTestpoint2[i][1];
+            psSphere *out = psSphereGetOffset(coord1, coord2, PS_LINEAR, PS_RADIAN);
+            if (out == NULL) {
+                diag("TEST ERROR: psSphereGetOffset() returned NULL");
+                errorFlag = true;
+            } else {
+                if(fabs(out->r - getOffsetResult[i][0]) > ERROR_TOL) {
+                    diag("Testpoint %d: Result out->r = %lg not equal to expected %lg",
+                         i, out->r, getOffsetResult[i][0]);
+                    errorFlag = true;
+                }
+                if(fabs(out->d - getOffsetResult[i][1]) > ERROR_TOL) {
+                    diag("Testpoint %d: Result out->d = %lg not equal to expected %lg",
+                         i,out->d, getOffsetResult[i][1]);
+                    errorFlag = true;
+                }
+                psFree(out);
+            }
+        }
+        psFree(coord1);
+        psFree(coord2);
+        ok(!errorFlag, "psSphereGetOffset() worked on several data points");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    /* HERE
+        #define DEG_INC2 15.0
+        #define VERBOSE 0
+        // testProjectTanDeProjectTan()
+        // XXX: Get rid of this?
+        {
+            psMemId id = psMemGetId();
+            bool errorFlag = false;
+            //
+            // I'm not convinced that the p_psProject() and p_psDeproject() functions work
+            // correctly.  If we project a set of coordinates over a wide range of (R, D)
+            // values, then deproject them, the original (R, D) values are only produced
+            // when D is larger than 0.  This code demonstrates that.
+            //
+            psProjection *tmpProj = psProjectionAlloc(0.0,0.0,10.0,10.0,PS_PROJ_TAN);
+            psPlane planeCoord01;
+            psSphere skyCoord01;
+            psSphere skyCoord02;
+            for (psF32 R = -90.0 ; R <= 90.0 ; R+= DEG_INC2) {
+                for (psF32 D = -90.0 ; D <= 90.0 ; D+= DEG_INC2) {
+                    if ((fabs(R) != 90.0) && (fabs(D) != 90.0)) {
+                        skyCoord01.r = DEG_TO_RAD(R);
+                        skyCoord01.d = DEG_TO_RAD(D);
+                        p_psProject(&planeCoord01, &skyCoord01, tmpProj);
+                        p_psDeproject(&skyCoord02, &planeCoord01, tmpProj);
+                        if ((fabs(skyCoord01.r - skyCoord02.r) < FLT_EPSILON) &&
+                            (fabs(skyCoord01.d - skyCoord02.d) < FLT_EPSILON)) {
+                            if (VERBOSE) {
+                                printf("CORRECT: (%.2fr %.2fd) (%.2fr %.2fd) -> (%.2f %.2f) -> (%.2fr %.2fd)\n", R, D,
+                                       skyCoord01.r, skyCoord01.d,
+                                       planeCoord01.x, planeCoord01.y,
+                                       skyCoord02.r, skyCoord02.d);
+                            }
+                        } else {
+                            diag("TEST ERROR: (%.2fr %.2fd) (%.2fr %.2fd) -> (%.2f %.2f) -> (%.2fr %.2fd)\n", R, D,
+                                  skyCoord01.r, skyCoord01.d,
+                                  planeCoord01.x, planeCoord01.y,
+                                  skyCoord02.r, skyCoord02.d);
+                            errorFlag = true;
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "p_psProject()/p_psDeproject() worked on several data points");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        }
+    */
+}
+
+
+
Index: trunk/psLib/test/astro/tap_psCoord02.c
===================================================================
--- trunk/psLib/test/astro/tap_psCoord02.c	(revision 11180)
+++ trunk/psLib/test/astro/tap_psCoord02.c	(revision 11180)
@@ -0,0 +1,572 @@
+/** @file  tst_psCoord02.c
+*
+*  @brief This file contains test code for:
+*
+*  @author GLG, MHPCC
+*
+*  XXX: These tests should probably be split among several files
+*
+*  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-01-19 20:42:21 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define PS_PERCENT_COMPARE(X, Y, PERCENT_FRACTION) (fabs((Y)-(X))/fabs(X) < (PERCENT_FRACTION))
+#define PS_GEN_RAN_FLOAT (-0.5 + ((psF32)rand()) / ((psF32) RAND_MAX))
+#define RANDOM_SEED 1995
+
+// These macros determine the number of x/y test points which will be x-formed.
+#define TST04_X_MIN 0.0
+#define TST04_X_MAX 10.0
+#define TST04_Y_MIN 0.0
+#define TST04_Y_MAX 10.0
+#define TST04_NUM 5.0
+// These macros define the max sizes of the various input transforms.
+#define TST04_T1_X_X 2
+#define TST04_T1_X_Y 3
+#define TST04_T1_Y_X 3
+#define TST04_T1_Y_Y 3
+#define TST04_T2_X_X 3
+#define TST04_T2_X_Y 3
+#define TST04_T2_Y_X 3
+#define TST04_T2_Y_Y 3
+
+/******************************************************************************
+tstTransforms(t1, t2, t3): this function generates a set of arbitrary x/y
+coordinates, then transforms them into output coordinates via the t3
+transform, as well as the t1 followed by the t2 transform.  It verifies the
+output coordinates are identical and returns TRUE if so.  Otherwise, it prints
+a diag message and returns FALSE.
+ *****************************************************************************/
+bool tstTransforms(psPlaneTransform *t1, psPlaneTransform *t2, psPlaneTransform *t3)
+{
+    bool testStatus = true;
+    psPlane *in = psPlaneAlloc();
+    in->xErr = 0.0;
+    in->yErr = 0.0;
+
+    for (in->x = TST04_X_MIN ; in->x <= TST04_X_MAX ; in->x+= (TST04_X_MAX-TST04_X_MIN) / TST04_NUM) {
+        for (in->y = TST04_Y_MIN ; in->y <= TST04_Y_MAX ; in->y+= (TST04_Y_MAX-TST04_Y_MIN) / TST04_NUM) {
+            // Apply the t1/t2 transforms individually to the in coords.
+            psPlane *mid = psPlaneTransformApply(NULL, t1, in);
+            if (mid == NULL) {
+                diag("TEST ERROR: intermediate psPlane coords are NULL.\n");
+                psFree(in);
+                return(false);
+            }
+
+            psPlane *outT1T2 = psPlaneTransformApply(NULL, t2, mid);
+            if (outT1T2 == NULL) {
+                diag("TEST ERROR: intermediate psPlane coords are NULL.\n");
+                psFree(mid);
+                return(false);
+            }
+
+            // Apply the t3 transforms individually to the in coords.
+            psPlane *outT3 = psPlaneTransformApply(NULL, t3, in);
+            if (outT3 == NULL) {
+                diag("TEST ERROR: intermediate psPlane coords are NULL.\n");
+                psFree(mid);
+                psFree(outT1T2);
+                return(false);
+            }
+
+            // Verify that the results are identical.
+            if (!PS_PERCENT_COMPARE(outT3->x, outT1T2->x, 0.01)) {
+                diag("TEST ERROR: x is %f, should be %f\n", outT3->x, outT1T2->x);
+                testStatus = false;
+            }
+            // Verify that the results are identical.
+            if (!PS_PERCENT_COMPARE(outT3->y, outT1T2->y, 0.01)) {
+                diag("TEST ERROR: y is %f, should be %f\n", outT3->y, outT1T2->y);
+                testStatus = false;
+            }
+            if (0) {
+                if (fabs(outT3->x - outT1T2->x) > FLT_EPSILON) {
+                    printf("TEST ERROR: x is %f, should be %f\n", outT3->x, outT1T2->x);
+                    testStatus = false;
+                    printf("(in->x, in->y) is (%f, %f)\n", in->x, in->y);
+                    printf("(mid->x, mid->y) is (%f, %f)\n", mid->x, mid->y);
+                    printf("(outT1T2->x, outT1T2->y) is (%f, %f)\n", outT1T2->x, outT1T2->y);
+                    printf("(outT3->x, outT3->y) is (%f, %f)\n", outT3->x, outT3->y);
+                    PS_POLY_PRINT_2D(t1->x);
+                    PS_POLY_PRINT_2D(t1->y);
+                    PS_POLY_PRINT_2D(t2->x);
+                    PS_POLY_PRINT_2D(t2->y);
+                    PS_POLY_PRINT_2D(t3->x);
+                    PS_POLY_PRINT_2D(t3->y);
+                }
+                if (fabs(outT3->y - outT1T2->y) > FLT_EPSILON) {
+                    printf("TEST ERROR: y is %f, should be %f\n", outT3->y, outT1T2->y);
+                    testStatus = false;
+                    printf("(in->x, in->y) is (%f, %f)\n", in->x, in->y);
+                    printf("(mid->x, mid->y) is (%f, %f)\n", mid->x, mid->y);
+                    printf("(outT1T2->x, outT1T2->y) is (%f, %f)\n", outT1T2->x, outT1T2->y);
+                    printf("(outT3->x, outT3->y) is (%f, %f)\n", outT3->x, outT3->y);
+                    PS_POLY_PRINT_2D(t1->x);
+                    PS_POLY_PRINT_2D(t1->y);
+                    PS_POLY_PRINT_2D(t2->x);
+                    PS_POLY_PRINT_2D(t2->y);
+                    PS_POLY_PRINT_2D(t3->x);
+                    PS_POLY_PRINT_2D(t3->y);
+                }
+            }
+            psFree(mid);
+            psFree(outT1T2);
+            psFree(outT3);
+        }
+    }
+
+    psFree(in);
+    return(testStatus);
+}
+
+/******************************************************************************
+setCoeffs(t1, t2): this function sets the coefficients of the t1 and t2
+transforms to somewhat arbitrary values.
+ *****************************************************************************/
+int setCoeffs(psPlaneTransform *t1, psPlaneTransform *t2)
+{
+    for (psS32 t1xx = 0 ; t1xx < t1->x->nX+1 ; t1xx++) {
+        for (psS32 t1xy = 0 ; t1xy < t1->x->nY+1 ; t1xy++) {
+            t1->x->coeff[t1xx][t1xy] = PS_GEN_RAN_FLOAT;
+        }
+    }
+
+    for (psS32 t1yx = 0 ; t1yx < t1->y->nX+1 ; t1yx++) {
+        for (psS32 t1yy = 0 ; t1yy < t1->y->nY+1 ; t1yy++) {
+            t1->y->coeff[t1yx][t1yy] = PS_GEN_RAN_FLOAT;
+        }
+    }
+    for (psS32 t2xx = 0 ; t2xx < t2->x->nX+1 ; t2xx++) {
+        for (psS32 t2xy = 0 ; t2xy < t2->x->nY+1 ; t2xy++) {
+            t2->x->coeff[t2xx][t2xy] = PS_GEN_RAN_FLOAT;
+        }
+    }
+    for (psS32 t2yx = 0 ; t2yx < t2->y->nX+1 ; t2yx++) {
+        for (psS32 t2yy = 0 ; t2yy < t2->y->nY+1 ; t2yy++) {
+            t2->y->coeff[t2yx][t2yy] = PS_GEN_RAN_FLOAT;
+        }
+    }
+    return(0);
+}
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(27);
+    srand(RANDOM_SEED);
+
+    // We test psPlaneTransformCombine() with a variety of input transforms
+    // as well as input coordinates
+    //
+    //    The strategy here is to generate a pair of transforms t1 and t2 with a wide
+    //    variety of sizes for the x/y components of the x/y transforms, then set the
+    //    coefficients of t1/t2 to arbitray values, then generate a new transform t3 via
+    //    psPlaneTransformCombine() function.  Then, for several arbitrary input plane
+    //    coordinates, we tarnsform them via the new transform t3, as well as
+    //    individually via t1 then t2, and verify that they produce identical output
+    //    coordinates.
+    //
+    {
+        psMemId id = psMemGetId();
+        bool errorFlag = false;
+        for (psS32 t1xx = 0 ; t1xx < TST04_T1_X_X ; t1xx++)
+        {
+            for (psS32 t1xy = 0 ; t1xy < TST04_T1_X_Y ; t1xy++) {
+                for (psS32 t1yx = 0 ; t1yx < TST04_T1_Y_X ; t1yx++) {
+                    for (psS32 t1yy = 0 ; t1yy < TST04_T1_Y_Y ; t1yy++) {
+                        for (psS32 t2xx = 0 ; t2xx < TST04_T2_X_X ; t2xx++) {
+                            for (psS32 t2xy = 0 ; t2xy < TST04_T2_X_Y ; t2xy++) {
+                                for (psS32 t2yx = 0 ; t2yx < TST04_T2_Y_X ; t2yx++) {
+                                    for (psS32 t2yy = 0 ; t2yy < TST04_T2_Y_Y ; t2yy++) {
+                                        //printf("(%d %d %d %d %d %d %d %d)\n", t1xx, t1xy, t1yx, t1yy, t2xx, t2xy, t2yx, t2yy);
+                                        psPlaneTransform *trans1 = psPlaneTransformAlloc(PS_MAX(t1xx, t1yx), PS_MAX(t1xy, t1yy));
+                                        psPlaneTransform *trans2 = psPlaneTransformAlloc(PS_MAX(t2xx, t2yx), PS_MAX(t2xy, t2yy));
+                                        psPlaneTransform *trans3 = NULL;
+                                        setCoeffs(trans1, trans2);
+                                        trans3 = psPlaneTransformCombine(NULL, trans1,
+                                                                         trans2, psRegionSet(NAN,NAN,NAN,NAN), 0);
+                                        //XXX: the last two parameters are bogus.  Needs to change.  -rdd
+
+                                        if (trans3 == NULL) {
+                                            diag("TEST ERROR: psPlaneTransformCombine() returned NULL");
+                                            errorFlag = true;
+                                        } else {
+                                            bool testStatus = tstTransforms(trans1, trans2, trans3);
+                                            if (!testStatus) {
+                                                diag("TEST ERROR: psPlaneTransformCombine() did not produce correct results");
+                                                errorFlag = true;
+                                            }
+                                        }
+                                        psFree(trans1);
+                                        psFree(trans2);
+                                        psFree(trans3);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "psPlaneTransformCombine() successful on a variety of transforms and data points");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling psPlaneTransformCombine with NULL trans1
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans2 = psPlaneTransformAlloc(2, 2);
+        psPlaneTransform *trans3 = psPlaneTransformCombine(NULL, NULL, trans2, psRegionSet(0,0,0,0), 10);
+        ok(trans3 == NULL, "psPlaneTransformCombine() returned NULL with NULL trans1 input");
+        psFree(trans2);
+        psFree(trans3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Calling psPlaneTransformCombine with NULL trans2
+    // Should generate error and return NULL.\n");
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans1 = psPlaneTransformAlloc(2, 2);
+        psPlaneTransform *trans3 = psPlaneTransformCombine(NULL, trans1, NULL, psRegionSet(0,0,0,0), 10);
+        ok(trans3 == NULL, "psPlaneTransformCombine() returned NULL with NULL trans2 input");
+        psFree(trans1);
+        psFree(trans3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // XXX: Clean this, put it elsewhere
+    #define TST05_X_MIN 0.0
+    #define TST05_X_MAX 10.0
+    #define TST05_Y_MIN 0.0
+    #define TST05_Y_MAX 10.0
+    #define TST05_NUM_X 5.0
+    #define TST05_NUM_Y 5.0
+    #define TST05_X_POLY_ORDER 3
+    #define TST05_Y_POLY_ORDER 3
+    #define TST05_NUM_DATA (TST05_NUM_X * TST05_NUM_Y)
+    #define TST05_IGNORE 1
+    #define TST05_VERBOSE 0
+
+    // Calling psPlaneTransformFit with NULL trans
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psArray *src = psArrayAlloc((int) TST05_NUM_DATA);
+        psArray *dst = psArrayAlloc((int) TST05_NUM_DATA);
+        psMemId id = psMemGetId();
+        ok(!psPlaneTransformFit(NULL, src, dst, 100, 100.0), "psPlaneTransformFit() returned FALSE with NULL trans");
+        psFree(src);
+        psFree(dst);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling psPlaneTransformFit with NULL src psArray
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+        psArray *dst = psArrayAlloc((int) TST05_NUM_DATA);
+        ok(!psPlaneTransformFit(trans, NULL, dst, 100, 100.0), "psPlaneTransformFit() returned FALSE with NULL src psArray");
+        psFree(trans);
+        psFree(dst);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Calling psPlaneTransformFit with NULL dst psArray
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+        psArray *src = psArrayAlloc((int) TST05_NUM_DATA);
+        ok(!psPlaneTransformFit(trans, src, NULL, 100, 100.0), "psPlaneTransformFit() returned FALSE with NULL dst psArray");
+        psFree(trans);
+        psFree(src);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformFit()
+    // XXX: This is only a rudimentary test of the psPlaneTransformFit() function.
+    //      It tests some simple linear transformations.
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+        psPlaneTransform *transInit = psPlaneTransformAlloc(TST05_X_POLY_ORDER, TST05_Y_POLY_ORDER);
+        psArray *src = psArrayAlloc((int) TST05_NUM_DATA);
+        psArray *dst = psArrayAlloc((int) TST05_NUM_DATA);
+        bool rc;
+
+        // We set an arbitrary non-linear transformation.
+        for (psS32 x = 0 ; x < TST05_X_POLY_ORDER+1 ; x++)
+        {
+            for (psS32 y = 0 ; y < TST05_Y_POLY_ORDER+1 ; y++) {
+                transInit->x->coeff[x][y] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                transInit->y->coeff[x][y] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+            }
+        }
+        if (TST05_VERBOSE)
+        {
+            PS_POLY_PRINT_2D(transInit->x);
+            PS_POLY_PRINT_2D(transInit->y);
+        }
+
+        // We generate a grid of input data points in the x1,y1 plane, calculate the
+        // corresponding values in the transformed plane, and set these to
+        // the src and dst psVectors.
+        psS32 i = 0;
+        for (psF32 x = TST05_X_MIN ; x < TST05_X_MAX ; x+= (TST05_X_MAX-TST05_X_MIN)/TST05_NUM_X)
+        {
+            for (psF32 y = TST05_Y_MIN ; y < TST05_Y_MAX ; y+= (TST05_Y_MAX-TST05_Y_MIN)/TST05_NUM_Y) {
+                if (i == src->n) {
+                    if (src->n == src->nalloc) {
+                        src = psArrayRealloc(src, src->n+1);
+                    }
+                    src->n++;
+                }
+                if (i == dst->n) {
+                    if (dst->n == dst->nalloc) {
+                        dst = psArrayRealloc(dst, dst->n+1);
+                    }
+                    dst->n++;
+                }
+                src->data[i] = (psPtr *) psPlaneAlloc();
+                ((psPlane *) src->data[i])->x = x;
+                ((psPlane *) src->data[i])->y = y;
+
+                dst->data[i] = psPlaneTransformApply(NULL, transInit, ((psPlane *) src->data[i]));
+                i++;
+            }
+        }
+
+        // Call psPlaneTransformFit with above data arrays
+        rc = psPlaneTransformFit(trans, src, dst, 100, 100.0);
+        ok(rc, "psPlaneTransformFit() returned TRUE");
+        skip_start(!rc, 1, "Skipping tests because psPlaneTransformFit() returned FALSE");
+        if (TST05_VERBOSE)
+        {
+            PS_POLY_PRINT_2D(trans->x);
+            PS_POLY_PRINT_2D(trans->y);
+        }
+
+        // For the initial grid of input points, we transform them to output points with
+        // the derived transformation, and verify that they are within 10%.
+        bool errorFlag = false;
+        for (psS32 i = TST05_IGNORE ; i < src->n-TST05_IGNORE ; i++)
+        {
+            psPlane *inData = (psPlane *) src->data[i];
+            psPlane *outData = (psPlane *) dst->data[i];
+            psPlane *outDataDeriv = psPlaneTransformApply(NULL, trans, inData);
+            if (!PS_PERCENT_COMPARE(outDataDeriv->x, outData->x, 0.20) ||
+                    !PS_PERCENT_COMPARE(outDataDeriv->y, outData->y, 0.20)) {
+                diag("TEST ERROR: the derived output coords (%d) were (%.2f, %.2f) should have been (%.2f, %.2f).\n",
+                     i, outDataDeriv->x, outDataDeriv->y, outData->x, outData->y);
+                errorFlag = true;
+            } else if (TST05_VERBOSE) {
+                diag("GOOD: the derived output coords (%d) were (%.2f, %.2f) should have been (%.2f, %.2f).\n",
+                     i, outDataDeriv->x, outDataDeriv->y, outData->x, outData->y);
+            }
+            psFree(outDataDeriv);
+        }
+        ok(!errorFlag, "The derived transformation was correct");
+        skip_end();
+        psFree(transInit);
+        psFree(trans);
+        psFree(src);
+        psFree(dst);
+        ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformInvert()
+    // Calling psPlaneTransformInvert with NULL trans
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psRegion myRegion = psRegionSet(1.0, 5.0, 1.0, 5.0);
+        psPlaneTransform *transInverse = psPlaneTransformInvert(NULL, NULL, myRegion, 10);
+        ok(transInverse == NULL, "psPlaneTransformInvert() returned NULL with NULL trans");
+        psFree(transInverse);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformInvert()
+    // Calling psPlaneTransformInvert with zero nSamples
+    // Should generate error and return NULL
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 1);
+        psRegion myRegion = psRegionSet(1.0, 5.0, 1.0, 5.0);
+        psPlaneTransform *transInverse = psPlaneTransformInvert(NULL, trans, myRegion, 0);
+        ok(transInverse == NULL, "psPlaneTransformInvert() returned NULL with zero nSamples");
+        psFree(trans);
+        psFree(transInverse);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    #define NUM_TRANSFORMS 100
+    // psPlaneTransformInvert()
+    // This is only a rudimentary test of the psPlaneTransformInvert() function.
+    // It tests: Several random linear transformations.
+    // XXX: Must extensively test non-linear transformations.
+    {
+        psMemId id = psMemGetId();
+        bool errorFlag = false;
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 1);
+        psPlaneTransform *transInverse = NULL;
+        psRegion myRegion = psRegionSet(1.0, 5.0, 1.0, 5.0);
+
+        trans->x->coeff[0][0] = 0.0;
+        trans->x->coeff[0][1] = 1.0;
+        trans->x->coeff[1][0] = 2.0;
+        trans->x->coeff[1][1] = 3.0;
+        trans->y->coeff[0][0] = 4.0;
+        trans->y->coeff[0][1] = 5.0;
+        trans->y->coeff[1][0] = 6.0;
+        trans->y->coeff[1][1] = 7.0;
+
+        // We calling psPlaneTransformInvert with acceptable linear transformations
+        for (psS32 n = 0 ; n < NUM_TRANSFORMS ; n++)
+    {
+        if (n == 0) {
+                // I ensure that we test the identity transformation since this was
+                // giving us probs before.
+                trans->x->coeff[0][0] = 0.0;
+                trans->x->coeff[0][1] = 0.0;
+                trans->x->coeff[1][0] = 1.0;
+                trans->x->coeff[1][1] = 0.0;
+                trans->y->coeff[0][0] = 0.0;
+                trans->y->coeff[0][1] = 1.0;
+                trans->y->coeff[1][0] = 0.0;
+                trans->y->coeff[1][1] = 0.0;
+            } else {
+                // We create a random linear transformation and hope it is invertible.
+                trans->x->coeff[0][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->x->coeff[0][1] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->x->coeff[1][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->x->coeff[1][1] = 0.0;
+                trans->y->coeff[0][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->y->coeff[0][1] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->y->coeff[1][0] = (psF32)rand() / (psF32)RAND_MAX * 10.0f;
+                trans->y->coeff[1][1] = 0.0;
+            }
+
+            transInverse = psPlaneTransformInvert(NULL, trans, myRegion, 10);
+            if (transInverse == NULL) {
+                diag("TEST ERROR: psPlaneTransformInvert() returned a NULL psPlaneTransform.\n");
+                errorFlag = true;
+            } else {
+                // Transform the "in" coords to "mid" with psPlaneTransform "trans", then
+                // transform "mid" to "out" with psPlaneTransform "transInverse".
+                // XXX: Must loop on a few data points.
+                psPlane *in = psPlaneAlloc();
+                in->x = 2.0;
+                in->y = 3.0;
+                psPlane *mid = psPlaneTransformApply(NULL, trans, in);
+                psPlane *out = psPlaneTransformApply(NULL, transInverse, mid);
+
+                if (((fabs(in->x - out->x) > FLT_EPSILON)) ||
+                        ((fabs(in->y - out->y) > FLT_EPSILON)) ||
+                        isnan(out->x) ||
+                        isnan(out->y)) {
+                    diag("TEST ERROR: in coords were (%f, %f), out coords were (%f, %f).\n",
+                         in->x, in->y, out->x, out->y);
+                    errorFlag = true;
+                }
+                psFree(in);
+                psFree(mid);
+                psFree(out);
+            }
+            psFree(transInverse);
+        }
+        psFree(trans);
+        ok(!errorFlag, "psPlaneTransformInvert() successful on several transforms");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformDeriv()
+    // Ensure psPlaneTransformDeriv() returns NULL for NULL input plane transform
+    // Following should generate error message
+    // XXX: We do not test error generation
+    // XXX: This test fails, probably because of spec changes
+    {
+        psMemId id = psMemGetId();
+        psPlane *coord = psPlaneAlloc();
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 3);
+        psPlane *deriv = psPlaneTransformDeriv(NULL, trans, coord);
+        ok(deriv == NULL, "psPlaneTransformDeriv(NULL, trans, coord) returned NULL");
+        psFree(coord);
+        psFree(trans);
+        psFree(deriv);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformDeriv()
+    // Ensure psPlaneTransformDeriv() returns NULL for NULL input plane
+    // psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message");
+    // Following should generate error message
+    // XXX: un-NULL the first parameter since we test that above
+    // XXX: We do not test error generation
+    {
+        psMemId id = psMemGetId();
+        psPlaneTransform *trans = psPlaneTransformAlloc(1, 3);
+        psPlane *deriv = psPlaneTransformDeriv(NULL, trans, NULL);
+        ok(deriv == NULL, "psPlaneTransformDeriv(NULL, trans, NULL) returned NULL");
+        psFree(trans);
+        psFree(deriv);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psPlaneTransformDeriv()
+    // We test on a very simple transformation.
+    {
+        psMemId id = psMemGetId();
+        psPlane *coord = psPlaneAlloc();
+        psPlane *deriv = NULL;
+        psPlaneTransform *trans = NULL;
+        coord->x = 3.0;
+        coord->y = 1.0;
+        trans = psPlaneTransformAlloc(1, 3);
+        //Set Polynomials.  f(x) = x, f(y) = 0.5*y^2  -->  f'(x) = 1, f'(y) = y
+        //So for 1,1  -> f'(1) = 1, f'(1) = 1
+        trans->x->coeff[0][0] = 0.0;
+        trans->x->coeff[1][0] = 1.0;
+        trans->y->coeff[0][0] = 0.0;
+        trans->y->coeff[0][1] = 0.0;
+        trans->y->coeff[0][2] = 0.5;
+
+        deriv = psPlaneTransformDeriv(NULL, trans, coord);
+        ok(deriv->x == 1.0 && deriv->y == 1.0, "psPlaneTransformDeriv() returned the correct values");
+        psFree(trans);
+        psFree(deriv);
+        psFree(coord);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    /* HERE
+    */
+}
+
Index: trunk/psLib/test/astro/tap_psTime_01.c
===================================================================
--- trunk/psLib/test/astro/tap_psTime_01.c	(revision 11180)
+++ trunk/psLib/test/astro/tap_psTime_01.c	(revision 11180)
@@ -0,0 +1,1090 @@
+/** @file  tst_psTime_01.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *     1) Allocate psTime structure
+ *     2) Get current time
+ *     3) Get UT1 UTC delta
+ *     4) Convert psTime to MJD
+ *     5) Convert psTime to JD
+ *     6) Convert psTime to ISO
+ *     7) Convert psTime to timeval
+ *     8) Create psTime from MJD
+ *     9) Create psTime from JD
+ *    10) Create psTime from ISO
+ *    11) Create psTime from timeval
+ *    12) Create psTime from TM
+ *    13) Convert time between different types
+ *
+ *     O) Convert psTime time to LMST
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-01-19 20:42:21 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define ERROR_TOL    0.0001
+
+// Test Time 1 : July 21, 2004  18:22:24.3
+//               MJD = 53207.765559
+//               JD = 2453208.265559
+// UTC Test Time 1
+const psS64 testTime1SecondsUTC     = 1090434144;
+const psU32 testTime1NanosecondsUTC = 272044000;
+// TAI Test Time 1
+const psS64 testTime1SecondsTAI     = 1090434176;
+const psU32 testTime1NanosecondsTAI = 272044000;
+const psF64 testTime1MJDTAI         = 53207.76592937;
+const psF64 testTime1JDTAI          = 2453208.26592937;
+
+// TT Test Time 1
+const psS64 testTime1SecondsTT      = 1090434208;
+const psU32 testTime1NanosecondsTT  = 456044000;
+// Expected UT1-UTC IERS A & B
+const psF64 testTime1UT1DeltaBullA  = -0.457233186;
+const psF64 testTime1UT1DeltaBullB  = -0.457227;
+// UT1 Test Time 1
+const psS64 testTime1SecondsUT1     = 1090434143;
+//const psU32 testTime1NanosecondsUT1 = 814810814;
+const psU32 testTime1NanosecondsUT1 = 814810861;
+// Expected MJD & JD
+const psF64 testTime1MJD            = 53207.765559;
+const psF64 testTime1JD             = 2453208.265559;
+// Expected ISO string
+const char* testTime1Str     = "2004-07-21T18:22:24.2Z";
+const char* testTime1StrLeap = "2004-07-21T18:22:60.2Z";
+// Expected timeval values
+const psS32 testTime1TimevalSec = 1090434144;
+const psS32 testTime1TimevalUsec = 272044;
+
+// Test Time 2 : Jan. 1, 1973 00:00:00.0000
+//               MJD = 41683.0000
+//               JD = 2441683.5000
+const psS64 testTime2SecondsUTC     = 94694400;
+const psU32 testTime2NanosecondsUTC = 0;
+
+// Expected UT1-UTC IERS A & B
+const psF64 testTime2UT1DeltaBullA  = 0.000000;
+const psF64 testTime2UT1DeltaBullB  = 0.000000;
+
+// Test Time 3 : Sept. 21, 2006 00:00:00.0000
+//               MJD = 53999
+//               JD = 2453999.5
+const psS64 testTime3SecondsUTC     = 1158796800;
+const psU32 testTime3NanosecondsUTC = 0;
+// Expected UT1-UTC IERS A & B
+const psF64 testTime3UT1DeltaBullA  = -0.63574;
+const psF64 testTime3UT1DeltaBullB  = -0.63574;
+
+// Test Time 4 : Jan. 1, 1969 00:00:00.0000
+//               MJD = 40222
+//               JD = 2440222.5
+const psS64 testTime4SecondsUTC     = -31536000;
+const psU32 testTime4NanosecondsUTC = 0;
+// Expected MJD and JD
+const psF64 testTime4MJD            = 40222.0;
+const psF64 testTime4JD             = 2440222.5;
+
+// Test Time 5 : Dec 31, 0001 BC 23:59:59
+//               MJD = -1397755
+//               JD = 1002245.4999
+const psS64 testTime5SecondsUTC     = -62125920001;
+const psU32 testTime5NanosecondsUTC  = 0;
+
+// Test Time 6 : Jan. 1, 10000 AD 00:00:00
+const psS64 testTime6SecondsUTC      = 253202544001;
+const psU32 testTime6NanosecondsUTC  = 0;
+
+// Test Time 7 : Jan. 1, 2004 00:00:00,0
+const psS64 testTime7Seconds         = 1072915200;
+const psU32 testTime7Nanoseconds     = 0;
+const psS32 testTime7TmYear          = 104;
+const psS32 testTime7TmMon           = 0;
+const psS32 testTime7TmDay           = 1;
+const psS32 testTime7TmHour          = 0;
+const psS32 testTime7TmMin           = 0;
+const psS32 testTime7TmSec           = 0;
+
+// Test Time 8 : Dec. 31, 2003 00:00:00,0
+const psS64 testTime8Seconds         = 1072828800;
+const psU32 testTime8Nanoseconds     = 0;
+const psS32 testTime8TmYear          = 103;
+const psS32 testTime8TmMon           = 11;
+const psS32 testTime8TmDay           = 31;
+const psS32 testTime8TmHour          = 0;
+const psS32 testTime8TmMin           = 0;
+const psS32 testTime8TmSec           = 0;
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(116);
+    // Initialize library internal structures
+    psLibInit("pslib.config");
+
+
+    // Test psTimeAlloc()
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        ok(time != NULL, "psTimeAlloc() did not return NULL");
+        skip_start(time == NULL, 4, "Skipping tests because psTimeAlloc() failed");
+        ok(time->type == PS_TIME_TAI, "psTimeAlloc() correctly set psTime->type");
+        ok(time->sec == 0, "psTimeAlloc() correctly set psTime->sec");
+        ok(time->nsec == 0, "psTimeAlloc() correctly set psTime->nsec");
+        ok(time->leapsecond == false, "psTimeAlloc() correctly set psTime->leapsecond");
+        psFree(time);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate new psTime with invalid time type
+    // Following should generate error message
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(-100);
+        ok(time == NULL, "psTimeAlloc(-100) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test psTimeGetNow()
+    {
+        psMemId id = psMemGetId();
+        psTime *timeNow = psTimeGetNow(PS_TIME_TAI);
+        ok(timeNow != NULL, "psTimeGetNow() returned NULL");
+        skip_start(time == NULL, 4, "Skipping tests because psTimeGetNow() failed");
+        ok(timeNow->type == PS_TIME_TAI, "psTimeGetNow() correctly set psTime->type");
+        psFree(timeNow);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to get time with invalid type
+    // Following should generate an error message for invalid time type
+    {
+        psMemId id = psMemGetId();
+        psTime *timeNow = psTimeGetNow(-100);
+        ok(timeNow == NULL, "psTimeGetNow(-100) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test psTimeGetUT1Delta()
+    // Attempt to convert NULL time
+    // psTimeGetUT1Delta() should generate an error message for NULL time
+    {
+        psMemId id = psMemGetId();
+        psF64 ut1Delta = psTimeGetUT1Delta(NULL, PS_IERS_B);
+        ok(isnan(ut1Delta), "psTimeGetUT1Delta(NULL, PS_IERS_B) returned NAN");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to convert invalid time
+    // Following should generate an error message for incorrect time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = 1;
+        time->nsec = 2e9;
+        time->leapsecond = false;
+        psF64 ut1Delta = psTimeGetUT1Delta(time, PS_IERS_B);
+        ok(isnan(ut1Delta), "psTimeGetUT1Delta() returned NAN for incorrect time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to convert time with invalid bulletin
+    // Following should generate an error message for incorrect bulletin
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = 1;
+        time->nsec = 2;
+        time->leapsecond = false;
+        psF64 ut1Delta = psTimeGetUT1Delta(time, -100);
+        ok(isnan(ut1Delta), "psTimeGetUT1Delta(time, -100) returned NAN (incorrect bulletin)");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to get delta with valid time and bulletin A
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec  = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        time->leapsecond = false;
+        psF64 ut1Delta = psTimeGetUT1Delta(time, PS_IERS_A);
+        ok(fabs(ut1Delta - testTime1UT1DeltaBullA) < ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin A");
+        //      diag("ERROR: UT1 Delta %lf not as expected %lf test time 1 bulletin A", ut1Delta, testTime1UT1DeltaBullA);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to get delta with valid time and bulletin B
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec  = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time, PS_IERS_B);
+        ok(fabs(ut1Delta - testTime1UT1DeltaBullB) < ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+        //      diag("UT1 Delta %lf not as expected %lf test time 1 bulletin B", ut1Delta, testTime1UT1DeltaBullB);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to get delta with valid time and bulletin A
+    // Following should generate a warning message predating table
+    // XXX: We don't test whether the warning message is generated
+    if (1) {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime2SecondsUTC;
+        time->nsec = testTime2NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time,PS_IERS_A);
+        ok(fabs(ut1Delta - testTime2UT1DeltaBullA) < ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+        //      diag("UT1 Delta %lf not as expected %lf test time 2 bulletin A", ut1Delta, testTime2UT1DeltaBullA);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to get delta with valid time and bulletin B
+    // Following should generate a warning message predating table
+    // XXX: We don't test whether the warning message is generated
+    if (1) {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime2SecondsUTC;
+        time->nsec = testTime2NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time,PS_IERS_B);
+        ok(fabs(ut1Delta - testTime2UT1DeltaBullB) < ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+        //      diag("UT1 Delta %lf not as expected %lf test time 2 bulletin B", ut1Delta, testTime2UT1DeltaBullB);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to get delta with valid time and bulletin A
+    // Following should generate a warning message postdating table
+    // XXX: We don't test whether the warning message is generated
+    if (1) {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec  = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time,PS_IERS_A);
+        ok(fabs(ut1Delta - testTime3UT1DeltaBullA) < ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+        //      diag("UT1 Delta %lf not as expected %lf test time 3 bulletin A", ut1Delta, testTime3UT1DeltaBullA);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Attempt to get delta with valid time and bulletin B
+    // Following should generate a warning message postdating table
+    // XXX: We don't test whether the warning message is generated
+    if (1) {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec  = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psF64 ut1Delta = psTimeGetUT1Delta(time,PS_IERS_B);
+        ok(fabs(ut1Delta - testTime3UT1DeltaBullB) < ERROR_TOL, "psTimeGetUT1Delta() produced the correct result: bulletin B");
+        //      diag("UT1 Delta %lf not as expected %lf test time 3 bulletin B", ut1Delta, testTime3UT1DeltaBullB);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToMJD()
+    // Attempt to convert with time NULL
+    // Following should generate an error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psF64 mjd = psTimeToMJD(NULL);
+        ok(isnan(mjd), "psTimeToMJD(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToMJD()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    // Following should generate an error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = 1;
+        time->nsec = 2e9;
+        time->leapsecond = false;
+        psF64 mjd = psTimeToMJD(time);
+        ok(isnan(mjd), "psTimeToMJD() returned NAN for incorrect time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToMJD()
+    // Check valid time conversion to MJD after 1/1/1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        psF64 mjd = psTimeToMJD(time);
+        ok(fabs(mjd - 53207.765929) < ERROR_TOL, "psTimeToMJD() returned correct time after 1/1/1970 epoch");
+        //      diag("Expected MJD = %lf not as expected %lf", mjd, testTime1MJD);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psTimeToMJD()
+    // Check valid time conversion to MJD before 1/1/1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime4SecondsUTC;
+        time->nsec = testTime4NanosecondsUTC;
+        psF64 mjd = psTimeToMJD(time);
+        ok(fabs(mjd - testTime4MJD) < ERROR_TOL, "psTimeToMJD() returned correct time before 1/1/1970 epoch");
+        //      diag("Expected MJD = %lf not as expected %lf", mjd, testTime4MJD);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToJD()
+    // Attempt to convert with time NULL
+    // Following should generate an error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psF64 jd = psTimeToJD(NULL);
+        ok(isnan(jd), "psTimeToJD(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psTimeToJD()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = 1;
+        time->nsec = 2e9;
+        time->leapsecond = false;
+        psF64 jd = psTimeToJD(time);
+        ok(isnan(jd), "psTimeToJD() returned NAN for incorrect time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToJD()
+    // Check valid time conversion to MJD after 1/1/1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        psF64 jd = psTimeToJD(time);
+        ok(fabs(jd - 2453208.265929) < ERROR_TOL, "psTimeToJD() returned the correct time after 1/1/1970 epoch");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToJD()
+    // Check valid time conversion to MJD before 1/1/1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime4SecondsUTC;
+        time->nsec = testTime4NanosecondsUTC;
+        psF64 jd = psTimeToJD(time);
+        ok(fabs(jd - testTime4JD) < ERROR_TOL, "psTimeToJD() returned the correct time before 1/1/1970 epoch");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Attempt to convert with NULL time
+    // Following should generate error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        char *timeStr = psTimeToISO(NULL);
+        ok(timeStr == NULL, "psTimeToISO(NULL) returned NULL");
+        psFree(timeStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Test psTimeToISO()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = 1;
+        time->nsec = 2e9;
+        char *timeStr = psTimeToISO(time);
+        ok(timeStr == NULL, "psTimeToISO(time) returned NULL for incorrect time");
+        psFree(time);
+        psFree(timeStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Verify return NULL for time prior to year 0000
+    // Following should generate error message for time prior year 0000
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime5SecondsUTC;
+        time->nsec = testTime5NanosecondsUTC;
+        char *timeStr = psTimeToISO(time);
+        ok(timeStr == NULL, "psTimeToISO(time) returned NULL for time prior to year 0000");
+        psFree(time);
+        psFree(timeStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Verify return NULL for time after to year 9999
+    // Following should generate error message for time after year 9999
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = testTime6SecondsUTC;
+        time->nsec = testTime6NanosecondsUTC;
+        char *timeStr = psTimeToISO(time);
+        ok(timeStr == NULL, "psTimeToISO(time) returned NULL for time after year 9999");
+        psFree(time);
+        psFree(timeStr);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Verify return string with valid time
+    // XXX: These tests fail.  They used to succeed in early 2006, I think
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        char *timeStr = psTimeToISO(time);
+        ok(strcmp(timeStr,testTime1Str) == 0, "psTimeToISO(time) returned correct time (no leapsecond)");
+        psFree(timeStr);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToISO()
+    // Verify return string with valid time and leap second set
+    // XXX: These tests fail.  They used to succeed in early 2006, I think
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = true;
+        char *timeStr = psTimeToISO(time);
+        ok(strcmp(timeStr,testTime1StrLeap) == 0, "psTimeToISO(time) returned correct time (with leapsecond)");
+        psFree(timeStr);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToTimeval()
+    // Attempt to convert with NULL time
+    // Following should generate error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        struct timeval *timevalTime = psTimeToTimeval(NULL);
+        ok(timevalTime == NULL, "psTimeToTimeval(NULL) returned NULL");
+        psFree(timevalTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToTimeval()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = 1;
+        time->nsec = 2e9;
+        struct timeval *timevalTime = psTimeToTimeval(time);
+        ok(timevalTime == NULL, "psTimeToTimeval() returned NULL for incorrect time");
+        psFree(time);
+        psFree(timevalTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToTimeval()
+    // Attempt to convert incorrect time
+    // Following should generate an error message for incorrect time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = -1;
+        time->nsec = 0;
+        struct timeval *timevalTime = psTimeToTimeval(time);
+        ok(timevalTime == NULL, "psTimeToTimeval() returned NULL for incorrect time");
+        psFree(time);
+        psFree(timevalTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeToTimeval()
+    // Verify convert to timeval with valid time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->leapsecond = false;
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        struct timeval *timevalTime = psTimeToTimeval(time);
+        ok(timevalTime->tv_sec == testTime1TimevalSec, "psTimeToTimeval() returned correct time");
+        //      diag("Timeval seconds %ld not as expectd %ld", timevalTime->tv_sec, testTime1TimevalSec);
+        ok(timevalTime->tv_usec == testTime1TimevalUsec, "psTimeToTimeval() returned correct time");
+        //      diag("Timeval useconds %ld not as expected %ld", timevalTime->tv_usec, testTime1TimevalUsec);
+        psFree(time);
+        psFree(timevalTime);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromMJD()
+    // Attempt to convert valid time to psTime
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromMJD(testTime1MJDTAI);
+        ok(time->type == PS_TIME_TAI, "psTimeFromMJD() returned the correct type");
+        ok(time->sec == testTime1SecondsTAI, "psTimeFromMJD() returned the correct ->sec");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromMJD()
+    // Attempt to convert valid time before 1970 epoch
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromMJD(testTime4MJD);
+        ok(time->type == PS_TIME_TAI, "psTimeFromMJD() returned the correct type");
+        ok(time->sec == testTime4SecondsUTC, "psTimeFromMJD() returned the correct ->sec");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeFromJD()
+    // Attempt to convert valid time to psTime
+    // XXX: This fails on the type test.  Should it?
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromJD(testTime1JDTAI);
+        ok(time->type == PS_TIME_TAI, "psTimeFromJD() returned the correct type");
+        ok(time->sec == testTime1SecondsTAI, "psTimeFromJD() returned the correct ->sec");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeFromJD()
+    // Attempt to convert valid time before 1970 epoch
+    // XXX: This fails on the type test.  Should it?
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromJD(testTime4JD);
+        ok(time->type != PS_TIME_TAI, "psTimeFromJD() returned the correct type");
+        ok(time->sec != testTime4SecondsUTC, "psTimeFromJD() returned the correct ->sec");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromISO()
+    // Attempt to convert NULL string
+    // Following should generate error message for NULL ISO string");
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromISO(NULL, PS_TIME_TAI);
+        ok(time == NULL, "psTimeFromISO(NULL, PS_TIME_TAI) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromISO()
+    // Convert valid ISO string
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromISO(testTime1Str, PS_TIME_TAI);
+        ok(time->type == PS_TIME_TAI, "psTimeFromISO() returned the correct type");
+        ok(time->sec == testTime1SecondsUTC, "psTimeFromISO() returned the correct ->sec");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromISO()
+    // Attempt to convert incorrect ISO string
+    // Following should generate an error for incorrect ISO string");
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromISO("Here I am", PS_TIME_TAI);
+        ok(time == NULL, "psTimeFromISO() returned NULL for incorrect ISO string");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeFromTimeval()
+    // Attempt to create psTime from NULL timeval ptr
+    // Following should generate error message for NULL timeval
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromTimeval(NULL);
+        ok(time == NULL, "psTimeFromTimeval(NULL) returned NULL");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test psTimeFromTimeval()
+    // Convert valid timeval structure
+    {
+        psMemId id = psMemGetId();
+        struct timeval *timevalTime = (struct timeval*)psAlloc(sizeof(struct timeval));
+        timevalTime->tv_sec = testTime1SecondsTAI;
+        timevalTime->tv_usec = testTime1NanosecondsTAI / 1000;
+        psTime *time = psTimeFromTimeval(timevalTime);
+        ok(time != NULL, "psTimeFromTimeval() returned NULL for correct timeval structure");
+        skip_start(time == NULL, 3, "Skipping tests because psTimeFromTimeval() returned NULL");
+        ok(time->type == PS_TIME_TAI, "psTimeFromTimeval() returned the correct type");
+        ok(time->sec == testTime1SecondsTAI, "psTimeFromTimeval() returned the correct ->sec");
+        ok(time->nsec == testTime1NanosecondsTAI, "psTimeFromTimeval() returned the correct ->nsec");
+        skip_end();
+        psFree(timevalTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTM()
+    // Attempt to convert from NULL tm structure ptr
+    // Following should generate error message for NULL tm ptr
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromTM(NULL);
+        ok(time == NULL, "psTimeFromTM(NULL) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTM()
+    {
+        psMemId id = psMemGetId();
+        // Verify convert for valid tm structure
+        struct tm *tmTime = (struct tm*)psAlloc(sizeof(struct tm));
+        tmTime->tm_year = testTime7TmYear;
+        tmTime->tm_mon  = testTime7TmMon;
+        tmTime->tm_mday = testTime7TmDay;
+        tmTime->tm_hour = testTime7TmHour;
+        tmTime->tm_min  = testTime7TmMin;
+        tmTime->tm_sec  = testTime7TmSec;
+        psTime *time = psTimeFromTM(tmTime);
+        ok(time != NULL, "psTimeFromTM(NULL) returned non-NULL");
+        skip_start(time == NULL, 2, "Skipping tests because psTimeFromTM() returned NULL");
+        ok(time->sec == testTime7Seconds, "psTimeFromTM() returned the correct ->sec");
+        ok(time->nsec == testTime7Nanoseconds, "psTimeFromTM() returned the correct ->nsec");
+        skip_end();
+        psFree(tmTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTM()
+    // Verify convert for valid tm structure
+    {
+        psMemId id = psMemGetId();
+        struct tm *tmTime = (struct tm*)psAlloc(sizeof(struct tm));
+        tmTime->tm_year = testTime8TmYear;
+        tmTime->tm_mon  = testTime8TmMon;
+        tmTime->tm_mday = testTime8TmDay;
+        tmTime->tm_hour = testTime8TmHour;
+        tmTime->tm_min  = testTime8TmMin;
+        tmTime->tm_sec  = testTime8TmSec;
+        psTime *time = psTimeFromTM(tmTime);
+        ok(time != NULL, "psTimeFromTM(NULL) returned non-NULL");
+        skip_start(time == NULL, 2, "Skipping tests because psTimeFromTM() returned NULL");
+        ok(time->sec == testTime8Seconds, "psTimeFromTM() returned the correct ->sec");
+        ok(time->nsec == testTime8Nanoseconds, "psTimeFromTM() returned the correct ->nsec");
+        psFree(tmTime);
+        psFree(time);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert NULL time
+    // Following should generate an error message for NULL time
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time2 = psTimeConvert(NULL, PS_TIME_TAI);
+        ok(time2 == NULL, "psTimeConvert(NULL, PS_TIME_TAI) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        psFree(time2);
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert to incorrect type
+    // Following should generate an error message for incorrect type
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        psTime *time2 = psTimeConvert(time1,-100);
+        ok(time2 == NULL, "psTimeConvert(time1, -100) returned NULL");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Following should generate an error message for incorrect type
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->type = PS_TIME_UTC;
+        psTime *time2 = psTimeConvert(time1,-100);
+        ok(time2 == NULL, "psTimeConvert(time1, -100) returned NULL");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Following should generate an error message for incorrect type
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->type = PS_TIME_TT;
+        psTime *time2 = psTimeConvert(time1,-100);
+        ok(time2 == NULL, "psTimeConvert(time1, -100) returned NULL");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Following should generate an error message for incorrect type
+    // XXX: We don't test whether the error message is generated
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->type = -100;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TAI);
+        ok(time2 == NULL, "psTimeConvert(time1, PS_TIME_TAI) returned NULL");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert with incorrect time nsec > 1e9
+    // Following should generate an error message for incorrect time
+    // XXX: We don't test whether the error message is generated
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->nsec = 2e9;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TAI);
+        ok(time2 == time1, "psTimeConvert(time1, PS_TIME_TAI) didn't return time1 for incorrect time");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    //Attempt to convert a time to the same type
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = 1;
+        time1->nsec = 2;
+        time1->type = PS_TIME_TAI;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TAI);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        ok((time2->sec == 1) && (time2->nsec == 2) && (time2->type == PS_TIME_TAI) &&
+           (time2->leapsecond == false), "There were no time member changes when no change expected");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a UTC time to a TAI
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->type = PS_TIME_UTC;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TAI);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        ok(time2->type == PS_TIME_TAI, "psTimeConvert() returned the correct type");
+        ok(time2->sec == testTime1SecondsTAI, "psTimeConvert() returned the correct ->sec");
+        ok(time2->nsec == testTime1NanosecondsTAI, "psTimeConvert() returned the correct ->nsec");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a UTC time to a TT
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->type = PS_TIME_UTC;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TT);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        ok(time2->type == PS_TIME_TT, "psTimeConvert() returned the correct type");
+        ok(time2->sec == testTime1SecondsTT, "psTimeConvert() returned the correct ->sec");
+        ok(time2->nsec == testTime1NanosecondsTT, "psTimeConvert() returned the correct ->nsec");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a UTC time to UT1
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->type = PS_TIME_UTC;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UT1);
+        ok(time1 == time2, "psTimeConvert() returned time for conversion to same type");
+        ok(time2->type == PS_TIME_UT1, "psTimeConvert() returned the correct type");
+        ok(time2->sec == testTime1SecondsUT1, "psTimeConvert() returned the correct ->sec");
+        ok(time2->nsec == testTime1NanosecondsUT1, "psTimeConvert() returned the correct ->nsec");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psTimeConvert()
+    // Attempt to convert a TAI time to UTC
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsTAI;
+        time1->nsec = testTime1NanosecondsTAI;
+        time1->type = PS_TIME_TAI;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UTC);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        ok(time2->type == PS_TIME_UTC, "psTimeConvert() returned the correct type");
+        ok(time2->sec == testTime1SecondsUTC, "psTimeConvert() returned the correct ->sec");
+        ok(time2->nsec == testTime1NanosecondsUTC, "psTimeConvert() returned the correct ->nsec");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TAI time to TT
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsTAI;
+        time1->nsec = testTime1NanosecondsTAI;
+        time1->type = PS_TIME_TAI;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TT);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        ok(time2->type == PS_TIME_TT, "psTimeConvert() returned the correct type");
+        ok(time2->sec == testTime1SecondsTT, "psTimeConvert() returned the correct ->sec");
+        ok(time2->nsec == testTime1NanosecondsTT, "psTimeConvert() returned the correct ->nsec");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TAI time to UT1
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsTAI;
+        time1->nsec = testTime1NanosecondsTAI;
+        time1->type = PS_TIME_TAI;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UT1);
+        ok(time1 == time2, "psTimeConvert() returned time for conversion to same type");
+        ok(time2->type == PS_TIME_UT1, "psTimeConvert() returned the correct type");
+        ok(time2->sec == testTime1SecondsUT1, "psTimeConvert() returned the correct ->sec");
+        ok(time2->nsec == testTime1NanosecondsUT1, "psTimeConvert() returned the correct ->nsec");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TT time to UTC
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsTT;
+        time1->nsec = testTime1NanosecondsTT;
+        time1->type = PS_TIME_TT;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UTC);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        ok(time2->type == PS_TIME_UTC, "psTimeConvert() returned the correct type");
+        ok(time2->sec == testTime1SecondsUTC, "psTimeConvert() returned the correct ->sec");
+        ok(time2->nsec == testTime1NanosecondsUTC, "psTimeConvert() returned the correct ->nsec");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TT time to TAI
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsTT;
+        time1->nsec = testTime1NanosecondsTT;
+        time1->type = PS_TIME_TT;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_TAI);
+        ok(time2 == time1, "psTimeConvert() returned time for conversion to same type");
+        ok(time2->type == PS_TIME_TAI, "psTimeConvert() returned the correct type");
+        ok(time2->sec == testTime1SecondsTAI, "psTimeConvert() returned the correct ->sec");
+        ok(time2->nsec == testTime1NanosecondsTAI, "psTimeConvert() returned the correct ->nsec");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert a TT time to UT1
+    // XXX: This generates memory errors and aborts, so I if'ed it out
+    if (0) {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = testTime1SecondsTT;
+        time1->nsec = testTime1NanosecondsTT;
+        time1->type = PS_TIME_TT;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1,PS_TIME_UT1);
+        ok(time1 == time2, "psTimeConvert() returned time for conversion to same type");
+        ok(time2->type == PS_TIME_UT1, "psTimeConvert() returned the correct type");
+        ok(time2->sec == testTime1SecondsUT1, "psTimeConvert() returned the correct ->sec");
+        ok(time2->nsec == testTime1NanosecondsUT1, "psTimeConvert() returned the correct ->nsec");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // Attempt to convert from UT1 to TAI, UTC, TT
+    // Following should generate an error message converting from UT1");
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_TAI);
+        time1->sec = 1;
+        time1->nsec = 2;
+        time1->type = PS_TIME_UT1;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeConvert(time1, PS_TIME_UTC);
+        ok(time2 == NULL, "psTimeConvert() returned NULL for conversion from UT1");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: trunk/psLib/test/astro/tap_psTime_02.c
===================================================================
--- trunk/psLib/test/astro/tap_psTime_02.c	(revision 11180)
+++ trunk/psLib/test/astro/tap_psTime_02.c	(revision 11180)
@@ -0,0 +1,400 @@
+/** @file  tst_psTime_02.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *     1) Convert psTime to Local Mean Sidereal Time (LMST)
+ *     2) Calculate leap second delta between times
+ *     3) Creation of psTime of type TT
+ *     4) Creation of psTime of type UTC
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-01-19 20:42:21 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define ERROR_TOL  0.001
+// Test Time 1 : May 9, 2005  00:00:00,0
+//               MJD = 53499.000
+//               JD = 2453499.5
+// UTC Test Time 1
+const psS64 testTime1SecondsUTC     = 1115596900;
+const psU32 testTime1NanosecondsUTC = 0;
+// Expected LMST  15:09:18
+const psF64 testTime1LMST0          = 3.967604;
+
+// Test Time 2 : May 9, 1995 00:00:00,0
+//               MJD = 49846.00
+//               JD = 2449846.5
+// UTC Test Time 2
+const psS64 testTime2SecondsUTC     = 799977600;
+const psU32 testTime2NanosecondsUTC = 0;
+// Expected leap second delta
+const psS64 testTimeLeapSecondDelta1 = 3;
+
+// Test Time 3: Jan 1, 1999 00:00:00,0
+//              MJD = 51179
+//              JD = 2451179.5
+const psS64 testTime3SecondsUTC     = 915148800;
+const psU32 testTime3NanosecondsUTC = 0;
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+    psLogSetFormat("HLNM");
+    plan_tests(50);
+    psLibInit("pslib.config");
+
+    // psTimeToLMST()
+    // Attempt to get LMST with NULL time
+    // Following should generate an error message for NULL time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psF64 lmst = psTimeToLMST(NULL, 0);
+        ok(isnan(lmst), "psTimeToLMST(time,0) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToLMST()
+    // Attempt to get LMST with valid test time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = false;
+        psF64 lmst = psTimeToLMST(time, 0.0);
+        ok(fabs(lmst-testTime1LMST0) < ERROR_TOL, "psTimeToLMST() returned the correct time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeToLMST()
+    // Attempt to get LMST with invalid input time UT1
+    // Following should generate error message for incorrect type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = false;
+        time->type = PS_TIME_UT1;
+        psF64 lmst = psTimeToLMST(time,0.0);
+        ok(isnan(lmst), "psTimeToLMST() generated a NAN for incorrect type");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeLeapSecondDelta()
+    // Attempt to get delta with NULL time1 argument
+    // Following should generate an error message for NULL time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psS64 delta = psTimeLeapSecondDelta(NULL, NULL);
+        ok(delta == 0, "psTimeLeapSecondDelta(NULL, NULL) returned 0");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Set test time 1
+    // Attempt to get delta with NULL time2 argument
+    // Following should generate an error message for NULL time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+
+        psS64 delta = psTimeLeapSecondDelta(time1, NULL);
+        ok(delta == 0, "psTimeLeapSecondDelta(time1, NULL) returned 0");
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Set test time 2 with invalid time
+    // Attempt to get delta with invalid time2
+    // Following should generate an error message for invalid time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = 0;
+        time2->nsec = 2e9;
+        time2->leapsecond = false;
+
+        psS64 delta = psTimeLeapSecondDelta(time1,time2);
+        ok(delta == 0, "psTimeLeapSecondDelta(time1, time2) returned 0 with incorrect time2");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Set test time 2 valid
+    // Attempt to get delta with invalid time1
+    // Following should generate an error message for invalid time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->leapsecond = false;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->leapsecond = false;
+        time2->sec = testTime2SecondsUTC;
+        time2->nsec = testTime2NanosecondsUTC;
+        // Set test time 1 incorrect
+        time1->sec = 0;
+        time1->nsec = 2e9;
+
+        psS64 delta = psTimeLeapSecondDelta(time1,time2);
+        ok(delta == 0, "psTimeLeapSecondDelta(time1, time2) returned 0 with incorrect time1");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Set test time 1 to greater time
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->leapsecond = false;
+        time2->sec = testTime2SecondsUTC;
+        time2->nsec = testTime2NanosecondsUTC;
+
+        psS64 delta = psTimeLeapSecondDelta(time1,time2);
+        ok(delta == testTimeLeapSecondDelta1, "psTimeLeapSecondDelta() produced the correct result");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Set test time 1 to lesser time
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = testTime2SecondsUTC;
+        time2->nsec = testTime2NanosecondsUTC;
+        psS64 delta = psTimeLeapSecondDelta(time2,time1);
+        ok(delta == testTimeLeapSecondDelta1, "psTimeLeapSecondDelta() produced the correct result");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Attempt to get delta with times equal
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        time1->leapsecond = false;
+
+        psS64 delta = psTimeLeapSecondDelta(time1,time1);
+        ok(delta == 0, "psTimeLeapSecondDelta() produced the correct result");
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Attempt to determine if leap second with NULL time
+    // Following should generate an error message for NULL time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psBool leapsecond = psTimeIsLeapSecond(NULL);
+        ok(!leapsecond, "psTimeIsLeapSecond(NULL) returned correct value");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Set time
+    // Attempt to determine if leap second with non-UTC time
+    // Following should generate an error message for invalid type
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = false;
+        psBool leapsecond = psTimeIsLeapSecond(time);
+        ok(!leapsecond, "psTimeIsLeapSecond() returned false with incorrect type");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Set time to UTC
+    // Attempt to determine if leap second with valid time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        time->leapsecond = false;
+        time->type = PS_TIME_UTC;
+        psBool leapsecond = psTimeIsLeapSecond(time);
+        ok(!leapsecond, "psTimeIsLeapSecond() returned false");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Set time to UTC with leap second
+    // XXX: This test fails.  Looks like it failed in the code as of 2007.
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        psBool leapsecond = psTimeIsLeapSecond(time);
+        ok(leapsecond, "psTimeIsLeapSecond() returned true");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Set time to 1 second before a known leap second
+    // XXX: This test fails.  Looks like it failed in the code as of 2007.
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        time->sec--;
+        psBool leapsecond = psTimeIsLeapSecond(time);
+        ok(leapsecond, "psTimeIsLeapSecond() returned true");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeIsLeapSecond()
+    // Set time to 1 second after a known leap second
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_TAI);
+        time->sec = testTime3SecondsUTC;
+        time->nsec = testTime3NanosecondsUTC;
+        time->sec ++;
+        psBool leapsecond = psTimeIsLeapSecond(time);
+        ok(!leapsecond, "psTimeIsLeapSecond() returned false");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTT()
+    // Attempt to create psTime with invalid time
+    // Following should generate an error message for invalid time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromTT(0,2e9);
+        ok(time == NULL, "psTimeFromTT() returned NULL with incorrect time");
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromTT()
+    // Attempt to create psTime with valid time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromTT(testTime1SecondsUTC,testTime1NanosecondsUTC);
+        ok(time != NULL, "psTimeFromTT() returned non-NULL with valid time");
+        skip_start(time == NULL, 2, "Skipping tests because psTimeFromTT() returned NULL");
+
+        ok(time->type == PS_TIME_TT, "psTimeFromTT() returned correct type");
+        ok((time->sec == testTime1SecondsUTC) && (time->nsec == testTime1NanosecondsUTC),
+           "psTimeFromTT() returned correct ->sec and ->nsec");
+        skip_end();
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromUTC()
+    // Attempt to create psTime with invalid time
+    // Following should generate an error message for invalid time
+    // XXX: We do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromUTC(0, 2e9, true);
+        ok(time == NULL, "psTimeFromUTC() returned NULL with incorrect time input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromUTC()
+    // Attempt to create psTime with valid non-leapsecond time and leapsecond flag true
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromUTC(testTime1SecondsUTC, testTime1NanosecondsUTC, true);
+        ok(time != NULL, "psTimeFromUTC() returned non-NULL with correct input");
+        skip_start(time == NULL, 3, "Skipping tests because psTimeFromUTC() returned NULL");
+        ok(time->type == PS_TIME_UTC, "psTimeFromUTC() returned the correct type");
+        ok((time->sec == testTime1SecondsUTC) && (time->nsec == testTime1NanosecondsUTC),
+           "psTimeFromUTC() returned the correct ->sec and ->nsec");
+        ok(!time->leapsecond, "psTimeFromUTC() returned the correct leapsecond flag");
+        psFree(time);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeFromUTC()
+    // Attempt to create psTime with valid leapsecond time but leapsecond flag false
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeFromUTC(testTime3SecondsUTC, testTime3NanosecondsUTC, false);
+        ok(time != NULL, "psTimeFromUTC() returned non-NULL with correct input");
+        skip_start(time == NULL, 5, "Skipping tests because psTimeFromUTC() returned NULL");
+        ok(time->type == PS_TIME_UTC, "psTimeFromUTC() returned the correct type");
+        ok((time->sec == testTime3SecondsUTC) && (time->nsec == testTime3NanosecondsUTC),
+           "psTimeFromUTC() returned the correct ->sec and ->nsec");
+        ok(time->leapsecond, "psTimeFromUTC() returned the correct leapsecond flag");
+        psFree(time);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: trunk/psLib/test/astro/tap_psTime_03.c
===================================================================
--- trunk/psLib/test/astro/tap_psTime_03.c	(revision 11180)
+++ trunk/psLib/test/astro/tap_psTime_03.c	(revision 11180)
@@ -0,0 +1,515 @@
+/** @file  tst_psTime_03.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *   1) psTimeMath invalid times
+ *   2) psTimeMath valid time of different types
+ *   3) psTimeDelta valid times with different types
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *
+ *  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-01-19 20:42:21 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#define ERROR_TOL    0.001
+
+// Test Time 1 : May 9, 2005 00:00:00,0
+//               MJD = 53499.00
+//               JD = 2453499.5
+// UTC Test Time 1
+const psS64 testTime1SecondsUTC         = 1115596900;
+const psU32 testTime1NanosecondsUTC     = 0;
+// TAI Test Time 1
+const psS64 testTime1SecondsTAI         = 1115596932;
+const psU32 testTime1NanosecondsTAI     = 0;
+// TT Test Time 1
+const psS64 testTime1SecondsTT          = 1115596964;
+const psU32 testTime1NanosecondsTT      = 184000000;
+// UT1 Test Time 1
+const psS64 testTime1SecondsUT1         = 1115596900;
+const psU32 testTime1NanosecondsUT1     = 184000000;
+// Delta 1
+const psF64 deltaTime1                  = -15.5;
+// Expected UTC Time 1
+const psS64 newTestTime1SecondsUTC      = 1115596884;
+const psU32 newTestTime1NanosecondsUTC  = 500000000;
+// Expected TAI Time 1
+const psS64 newTestTime1SecondsTAI      = 1115596916;
+const psU32 newTestTime1NanosecondsTAI  = 500000000;
+// Delta 2
+const psF64 deltaTime2                  = 123.066;
+// Expected TT Time 1 w/ delta 2
+const psS64 newTestTime1SecondsTT       = 1115597087;
+const psU32 newTestTime1NanosecondsTT   = 250000000;
+// Expected UT1 Time 1 w/ delta 2
+const psS64 newTestTime1SecondsUT1      = 1115597023;
+const psU32 newTestTime1NanosecondsUT1  = 250000000;
+
+// Test Time 2 : Dec. 31 1998 23:59:45,0
+//               MJD = 51178.99983
+//               JD = 2451179.49983
+// UTC Test Time 1
+const psS64 testTime2SecondsUTC         = 915148785;
+const psU32 testTime2NanosecondsUTC     = 0;
+// Delta 3
+const psF64 deltaTime3                    = 30.0;
+// Expected UTC Time
+const psS64 newTestTime2SecondsUTC      = 915148814;
+const psU32 newTestTime2NanosecondsUTC  = 0;
+
+// Appendix B time conversion tests
+//
+#define APPB_TESTS    8
+const psS64 testTimeBSeconds[APPB_TESTS] =
+    {
+        915148829,
+        915148829,
+        915148830,
+        915148830,
+        915148831,
+        915148831,
+        915148832,
+        915148832
+    };
+const psU32 testTimeBNanoseconds[APPB_TESTS] =
+    {
+        0,
+        500000000,
+        0,
+        500000000,
+        0,
+        500000000,
+        0,
+        500000000
+    };
+const psBool testTimeBLeapsecond[APPB_TESTS] =
+    {
+        false,
+        false,
+        false,
+        false,
+        true,
+        true,
+        false,
+        false
+    };
+// Expected results
+const char* testTimeBStrUTC[APPB_TESTS] =
+    {
+        "1998-12-31T23:59:58.0Z",
+        "1998-12-31T23:59:58.5Z",
+        "1998-12-31T23:59:59.0Z",
+        "1998-12-31T23:59:59.5Z",
+        "1998-12-31T23:59:60.0Z",
+        "1998-12-31T23:59:60.5Z",
+        "1999-01-01T00:00:00.0Z",
+        "1999-01-01T00:00:00.5Z"
+    };
+const char* testTimeBStrTAI[APPB_TESTS] =
+    {
+        "1999-01-01T00:00:29.0Z",
+        "1999-01-01T00:00:29.5Z",
+        "1999-01-01T00:00:30.0Z",
+        "1999-01-01T00:00:30.5Z",
+        "1999-01-01T00:00:31.0Z",
+        "1999-01-01T00:00:31.5Z",
+        "1999-01-01T00:00:32.0Z",
+        "1999-01-01T00:00:32.5Z"
+    };
+const char* testTimeBStrTT[APPB_TESTS] =
+    {
+        "1999-01-01T00:01:01.1Z",
+        "1999-01-01T00:01:01.6Z",
+        "1999-01-01T00:01:02.1Z",
+        "1999-01-01T00:01:02.6Z",
+        "1999-01-01T00:01:03.1Z",
+        "1999-01-01T00:01:03.6Z",
+        "1999-01-01T00:01:04.1Z",
+        "1999-01-01T00:01:04.6Z"
+    };
+const char* testTimeBStrUT1[APPB_TESTS] =
+    {
+        "1998-12-31T23:59:58.7Z",
+        "1998-12-31T23:59:59.2Z",
+        "1998-12-31T23:59:59.7Z",
+        "1998-12-31T23:59:60.2Z",
+        "1998-12-31T23:59:60.7Z",
+        "1999-01-01T00:00:00.2Z",
+        "1999-01-01T00:00:00.7Z",
+        "1999-01-01T00:00:01.2Z"
+    };
+
+// Test Time B1 : Dec 31, 1998 23:59:58,0
+//                MJD = 51178.99998
+//                JD = 2451179.49998
+//const psS64 testTimeB1SecondsUTC        = 915148798;
+//const psU32 testTimeB1NanosecondsUTC    = 0;
+// Expected ISO times
+//const char testTimeB1StrUTC[] = "1998-12-31T23:59:58,0Z";
+//const char testTimeB1StrTAI[] = "1999-01-01T00:00:29,0Z";
+//const char testTimeB1StrTT[]  = "1999-01-01T00:01:01,1Z";
+//const char testTimeB1StrUT1[] = "1998-12-31T23:59:57,7Z";
+//
+// Test Time B2 : Dec 31, 1998 23:59:58,5
+//
+//
+//const psS64 testTimeB2SecondsUTC       = 915148798;
+//const psU32 testTimeB2NanosecondsUTC   = 500000000;
+// Expected ISO times
+//const char testTimeB2StrUTC[] = "1998-12-31T23:59:58,5Z";
+//const char testTimeB2StrTAI[] = "1991-01-01T00:00:29,5Z";
+//const char testTimeB2StrTT[]  = "1999-01-01T00:01:01,6Z";
+//const char testTimeB2StrUT1[] = "1998-12-31T23:59:58,2Z";
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(24);
+    psLibInit("pslib.config");
+
+    // psTimeMath()
+    // Attempt to perform math operation on NULL time
+    // Following should generate error message for NULL time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        ok(psTimeMath(NULL, -1.1) == NULL, "psTimeMath(NULL, -1.1) returned NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with invalid nanoseconds
+    // Following should generate error message for invalid time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = 0;
+        time->nsec = 2e9;
+        ok(psTimeMath(time, -1.1) == NULL, "psTimeMath() returns NULL for unallowable time input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUTC;
+        time->nsec = testTime1NanosecondsUTC;
+        psTime *newTime = psTimeMath(time, deltaTime1);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_UTC)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_UTC, "psTimeMath() returns the correct type (PS_TIME_UTC)");
+        ok((newTime->sec == newTestTime1SecondsUTC) && (newTime->nsec == newTestTime1NanosecondsUTC),
+           "psTimeMath() returns the correct ->sec and ->nsec (PS_TIME_UTC)");
+        skip_end();
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid TAI time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsTAI;
+        time->nsec = testTime1NanosecondsTAI;
+        time->type = PS_TIME_TAI;
+        psTime *newTime = psTimeMath(time, deltaTime1);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_TAI)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_TAI, "psTimeMath() returns the correct type (PS_TIME_TAI)");
+        ok((newTime->sec == newTestTime1SecondsTAI) && (newTime->nsec == newTestTime1NanosecondsTAI),
+           "psTimeMath() returns the correct ->sec and ->nsec (PS_TIME_TAI)");
+        skip_end();
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid TT time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsTT;
+        time->nsec = testTime1NanosecondsTT;
+        time->type = PS_TIME_TT;
+        psTime *newTime = psTimeMath(time,deltaTime2);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_TT)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_TT, "psTimeMath() returns the correct type (PS_TIME_TT)");
+        ok((newTime->sec == newTestTime1SecondsTT) && (newTime->nsec == newTestTime1NanosecondsTT),
+           "psTimeMath() returns the correct ->sec and ->nsec (PS_TIME_TT)");
+        skip_end();
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid TT time
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime1SecondsUT1;
+        time->nsec = testTime1NanosecondsUT1;
+        time->type = PS_TIME_UT1;
+        psTime *newTime = psTimeMath(time,deltaTime2);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_UT1)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_UT1, "psTimeMath() returns the correct type (PS_TIME_UT1)");
+        ok((newTime->sec == newTestTime1SecondsUT1) && (newTime->nsec == newTestTime1NanosecondsUT1),
+           "psTimeMath() returns the correct ->sec and ->nsec (PS_TIME_UT1)");
+        skip_end();
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeMath()
+    // Set up input time with valid UTC time and delt which crosses leap second
+    {
+        psMemId id = psMemGetId();
+        psTime *time = psTimeAlloc(PS_TIME_UTC);
+        time->sec = testTime2SecondsUTC;
+        time->nsec = testTime2NanosecondsUTC;
+        time->type = PS_TIME_UTC;
+        psTime *newTime = psTimeMath(time,deltaTime3);
+        ok(newTime != NULL, "psTimeMath() returns non-NULL for allowable time input (PS_TIME_UTC)");
+        skip_start(newTime == NULL, 2, "Skipping tests because psTimeMath() returned NULL");
+        ok(newTime->type == PS_TIME_UTC, "psTimeMath() returns the correct type (PS_TIME_UTC)");
+        ok((newTime->sec == newTestTime2SecondsUTC) && (newTime->nsec == newTestTime2NanosecondsUTC),
+           "psTimeMath() returns the correct ->sec and ->nsec (PS_TIME_UTC)");
+        skip_end();
+        psFree(newTime);
+        psFree(time);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Attempt to get delta with time1 NULL
+    // Following should generate error message for NULL time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        psF64 delta = psTimeDelta(NULL, NULL);
+        ok(fabs(delta-0.0) < ERROR_TOL, "psTimeDelta(NULL, NULL) returned 0.0");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Attempt to get delta with time2 NULL
+    // Following should generate error message for NULL time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        psF64 delta = psTimeDelta(time1, NULL);
+        ok(fabs(delta-0.0) < ERROR_TOL, "psTimeDelta(time1, NULL) returned 0.0");
+        psFree(time1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Attempt to get delta with time1 invalid
+    // Following should generate error message for invalid time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = 0;
+        time1->nsec = 2e9;
+        psF64 delta = psTimeDelta(time1, time2);
+        ok(fabs(delta-0.0) < ERROR_TOL, "psTimeDelta(time1, NULL) returned 0.0 for unallowed time1 arg");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Attempt to get delta with time2 invalid
+    // Following should generate error message for invalid time
+    // XXX: We do not test error generation here
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = 0;
+        time2->nsec = 2e9;
+        psF64 delta = psTimeDelta(time1, time2);
+        ok(fabs(delta-0.0) < ERROR_TOL, "psTimeDelta(time1, NULL) returned 0.0 for unallowed time2 arg");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Set time 2 valid but different type
+    // Attempt to get delta with different time types
+    // Following should generate error message for incorrect type
+    // XXX: We do not test error generation here
+    // XXX: this currently fails; probably because specs have changed
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        psTime *time2 = psTimeAlloc(PS_TIME_TAI);
+        time2->sec = newTestTime1SecondsUTC;
+        time2->nsec = newTestTime1NanosecondsUTC;
+        psF64 delta = psTimeDelta(time1, time2);
+        ok(fabs(delta-0.0) < ERROR_TOL, "psTimeDelta(time1, NULL) returned 0.0 for different time types");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Set time 2 to same as time 1
+    // Attempt to get delta with valid times of the same type
+    // XXX: this currently fails; probably because specs have changed
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsUTC;
+        time1->nsec = testTime1NanosecondsUTC;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = newTestTime1SecondsUTC;
+        time2->nsec = newTestTime1NanosecondsUTC;
+        psF64 delta = psTimeDelta(time2, time1);
+        ok(fabs(delta-deltaTime1) < ERROR_TOL, "psTimeDelta(time1, NULL) returned correct delta for times of the same type");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Set time 1 and 2 as different times with same type
+    // Attempt to get delta with valid times of the same type
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime1SecondsTT;
+        time1->nsec = testTime1NanosecondsTT;
+        time1->type = PS_TIME_TT;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = newTestTime1SecondsTT;
+        time2->nsec = newTestTime1NanosecondsTT;
+        time2->type = PS_TIME_TT;
+        psF64 delta = psTimeDelta(time2,time1);
+        ok(fabs(delta-deltaTime2) < ERROR_TOL, "psTimeDelta(time1, NULL) returned correct delta for times of the same type");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeDelta()
+    // Set time 1 and 2 as different times with same type
+    // Attempt to get delta with valid times of the same type
+    {
+        psMemId id = psMemGetId();
+        psTime *time1 = psTimeAlloc(PS_TIME_UTC);
+        time1->sec = testTime2SecondsUTC;
+        time1->nsec = testTime2NanosecondsUTC;
+        time1->type = PS_TIME_UTC;
+        psTime *time2 = psTimeAlloc(PS_TIME_UTC);
+        time2->sec = newTestTime2SecondsUTC;
+        time2->nsec = newTestTime2NanosecondsUTC;
+        time2->type = PS_TIME_UTC;
+        psF64 delta = psTimeDelta(time2,time1);
+        ok(fabs(delta-deltaTime3) < ERROR_TOL, "psTimeDelta(time1, NULL) returned correct delta for times of the same type");
+        psFree(time1);
+        psFree(time2);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // psTimeConvert()
+    // XXX: This currently produces lots of errors
+    {
+        for(psS32 i = 0; i < APPB_TESTS; i++)
+        {
+            bool errorFlag = false;
+            // Initialize time for test time B1
+            psTime *time = psTimeAlloc(PS_TIME_TAI);
+            time->sec = testTimeBSeconds[i];
+            time->nsec = testTimeBNanoseconds[i];
+
+            // Verify TAI ISO string
+            char *timeStr = psTimeToISO(time);
+            if(strcmp(timeStr,testTimeBStrTAI[i]) != 0) {
+                diag("TEST ERROR: TAI ISO string %s not as expected %s",
+                     timeStr, testTimeBStrTAI[i]);
+                errorFlag = true;
+            }
+            psFree(timeStr);
+
+            time = psTimeConvert(time,PS_TIME_TT);
+            timeStr = psTimeToISO(time);
+            if(strcmp(timeStr,testTimeBStrTT[i]) != 0) {
+                diag("TEST ERROR: TT ISO string %s not as expected %s",
+                     timeStr, testTimeBStrTT[i]);
+                errorFlag = true;
+            }
+            psFree(timeStr);
+
+            // Verify UTC ISO string
+            time = psTimeConvert(time,PS_TIME_UTC);
+            time->leapsecond = testTimeBLeapsecond[i];
+            timeStr = psTimeToISO(time);
+            if(strcmp(timeStr,testTimeBStrUTC[i]) != 0) {
+                if(strncmp(timeStr,"1999-01-01T00:00:60.0Z", 10) != 0) {
+                    diag("TEST ERROR: UTC ISO string %s not as expected %s",
+                         timeStr, testTimeBStrUTC[i]);
+                    errorFlag = true;
+                }
+            }
+            psFree(timeStr);
+
+            time = psTimeConvert(time,PS_TIME_UT1);
+            timeStr = psTimeToISO(time);
+            if(strcmp(timeStr,testTimeBStrUT1[i]) != 0) {
+                if(strncmp(timeStr,"1999-01-01T00:00:60.2Z", 10) != 0) {
+                    diag("TEST ERROR: UT1 ISO string %s not as expected %s",
+                         timeStr, testTimeBStrUT1[i]);
+                    errorFlag = true;
+                }
+            }
+            psFree(timeStr);
+            psFree(time);
+            ok(!errorFlag, "psTimeConvert() successful on test case %d", i);
+        }
+
+    }
+}
Index: trunk/psLib/test/astro/tap_psTime_04.c
===================================================================
--- trunk/psLib/test/astro/tap_psTime_04.c	(revision 11180)
+++ trunk/psLib/test/astro/tap_psTime_04.c	(revision 11180)
@@ -0,0 +1,139 @@
+/** @file  tst_psTime_04.c
+ *
+ *  @brief Test driver for psTime functions
+ *
+ *  This test driver contains the following tests for psTime:
+ *      Test A - Initialize time
+ *      Test B - Attempt to open non-existant time config file
+ *      Test C - Attempt to open non-existant time data files
+ *      Test D - Attempt to read incorrect number of files
+ *      Test E - Attempt to read incorrect number of from values
+ *      Test F - Attempt to read data file with typo in number
+ *      Test G - Free data
+ *      Test H - Attempt to use all timer functions
+ *      Test I - Tidal Corrections to UT1-UTC
+ *
+ *  @author  Ross Harman, MHPCC
+ *  @author  Eric Van Alst, MHPCC
+ *  @author  David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2007-01-19 20:42:21 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(15);
+
+
+    // Test A - Initialize time
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("pslib.config");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test B - Attempt to open non-existant time config file
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("zzz");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test C - Attempt to open non-existant time data files
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("test.psTime.config1");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test D - Attempt to read incorrect number of files
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("test.psTime.config2");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test E - Attempt to read incorrect number of from values
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("test.psTime.config3");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Test F - Attempt to read data file with typo in number
+    // XXX: Noting is actually verified here
+    {
+        psMemId id = psMemGetId();
+        psLibInit("test.psTime.config4");
+        psLibFinalize();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testTimer1()
+    {
+        psMemId id = psMemGetId();
+        psF64 testTime = 0.0;
+        psF64 testTime2 = 0.0;
+        psF64 testTime3 = 0.0;
+
+        ok(psTimerStart("newTime"), "psTimerStart successful");
+        testTime = psTimerMark("newTime");
+        ok(testTime != 0.0, "psTimerMark() successful");
+        testTime2 = psTimerClear("newTime");
+        ok(testTime2 != 0.0, "psTimerClear() successful");
+        psTimerStart("newTime");
+        testTime3 = psTimerStop();
+        ok(testTime3 != 0.0, "psTimerStop() successful");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // testTideUT1Corr()
+    {
+        psMemId id = psMemGetId();
+        psTime *empty = NULL;
+        psTime *tide = NULL;
+        psTime *noTide = psTimeAlloc(PS_TIME_UTC);
+        noTide->sec = 1049160600;
+        noTide->nsec = 0;
+        noTide->leapsecond = false;
+        // Following should generate error message
+        // XXX: We do not test error generation here
+        empty = psTime_TideUT1Corr(tide);
+        ok(empty == NULL, "psTime_TideUT1Corr() returned NULL for NULL input time");
+
+        empty = psTime_TideUT1Corr(noTide);
+        ok((empty->sec == 1049160599) && (empty->nsec == 656981971),
+           "psTime_TideUT1Corr() returned correct values");
+
+        ok(p_psTimeFinalize(), "p_psTimeFinalize() successful");
+        psFree(empty);
+        psFree(noTide);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
