/** @file  tst_psAstrometry.c
 *
 *  @brief Contains the tests for psAstrometry.[ch]
 *
 *  @author Robert DeSonia, MHPCC
 *
 *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2005-01-14 01:46:07 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */

#include <math.h>
#include <string.h>

#include "psTest.h"
#include "pslib.h"

static psS32 testExposureAlloc(void);
static psS32 testObservatoryAlloc(void);
static psS32 testFPAAlloc(void);
static psS32 testChipAlloc(void);
static psS32 testCellAlloc(void);
static psS32 testReadoutAlloc(void);

testDescription tests[] = {
                              {testExposureAlloc,735,"psExposureAlloc",0,false},
                              {testObservatoryAlloc,736,"psObservatoryAlloc",0,false},
                              {testFPAAlloc,739,"psFPAAlloc",0,false},
                              {testChipAlloc,740,"psChipAlloc",0,false},
                              {testCellAlloc,741,"psCellAlloc",0,false},
                              {testReadoutAlloc,742,"psReadoutAlloc",0,false},
                              {NULL}
                          };

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

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

static psS32 testExposureAlloc(void)
{
    psTime* now = psTimeGetTime(PS_TIME_UTC);
    char* name = "The Kaiser Royal Observatory";

    psObservatory* obs = psObservatoryAlloc(name,
                                            20.7, 156.3, 3055.0, 9.0);

    psExposure* exp = psExposureAlloc(1.0, 2.0, 3.0, 4.0, 5.0,
                                      now, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, obs);


    if (fabs(exp->ra - 1.0) > DBL_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set ra.");
        return 1;
    }

    if (fabs(exp->dec - 2.0) > DBL_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set dec.");
        return 2;
    }

    if (fabs(exp->hourAngle - 3.0) > DBL_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set hourAngle.");
        return 3;
    }

    if (fabs(exp->zenithDistance - 4.0) > DBL_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set zenithDistance.");
        return 4;
    }

    if (fabs(exp->azimuth - 5.0) > DBL_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set azimuth.");
        return 5;
    }
    if (exp->time != now) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set time.");
        return 6;
    }

    if (fabsf(exp->rotAngle - 6.0f) > FLT_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set rotAngle.");
        return 7;
    }

    if (fabsf(exp->temperature - 7.0f) > FLT_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set temperature.");
        return 8;
    }

    if (fabsf(exp->pressure - 8.0f) > FLT_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set pressure.");
        return 9;
    }

    if (fabsf(exp->humidity - 9.0f) > FLT_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set humidity.");
        return 10;
    }

    if (fabsf(exp->exposureTime - 10.0f) > FLT_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set exposureTime.");
        return 11;
    }

    if (fabsf(exp->wavelength - 11.0f) > FLT_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set wavelength.");
        return 12;
    }

    if (exp->observatory != obs) {
        psLogMsg(__func__,PS_LOG_ERROR,"psExposureAlloc did not set wavelength.");
        return 12;
    }

    psFree(exp);
    psFree(now);
    psFree(obs);
    psLibFinalize();
    return 0;
}

static psS32 testObservatoryAlloc(void)
{
    char* name = "The Kaiser Royal Observatory";
    psObservatory* obs = psObservatoryAlloc(name,
                                            20.7*M_PI/180.0, 156.3*M_PI/180.0, 3055.0, 9.0);

    if (fabs(obs->latitude - 20.7*M_PI/180.0) > DBL_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psObservatoryAlloc did not set latitude.");
        return 1;
    }

    if (fabs(obs->longitude - 156.3*M_PI/180.0) > DBL_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psObservatoryAlloc did not set longitude.");
        return 2;
    }

    if (fabs(obs->height - 3055.0) > DBL_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psObservatoryAlloc did not set height.");
        return 3;
    }

    if (fabs(obs->tlr - 9.0) > DBL_EPSILON) {
        psLogMsg(__func__,PS_LOG_ERROR,"psObservatoryAlloc did not set tlr.");
        return 4;
    }

    if (strcmp(obs->name,name) != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,"psObservatoryAlloc did not set name.");
        return 5;
    }

    if (obs->name == name) {
        psLogMsg(__func__,PS_LOG_ERROR,"psObservatoryAlloc did not copy name.");
        return 6;
    }

    psObservatory* obs2 = psObservatoryAlloc(NULL,
                          20.7*M_PI/180.0, 156.3*M_PI/180.0, 3055.0, 9.0);

    if (obs2->name != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psObservatoryAlloc did not handle NULL name.");
        return 7;
    }

    psFree(obs);
    psFree(obs2);

    return 0;
}

static psS32 testFPAAlloc(void)
{

    psTime* now = psTimeGetTime(PS_TIME_TAI);
    char* name = "The Kaiser Royal Observatory";

    psObservatory* obs = psObservatoryAlloc(name,
                                            20.7*M_PI/180.0, 156.3*M_PI/180.0, 3055.0, 0.0065f);

    psExposure* exp = psExposureAlloc(1.0, 2.0, 3.0, 4.0, 5.0,
                                      now, 6.0f, 260.0f, 1013.0f, 0.7f, 10.0f, 0.650f, obs);

    /*
        1. Call psFPAAlloc with nChips > 0 and a non-NULL psExposure.
        a) Verify that the psExposure reference is: 1. is set in struct as
        exposure; 2. its reference count is incremented.
        b) Verify that the chip attribute is of the size specified by the
        parameter nChips and that the chips array elements are all NULL.
        c) verify that all other references in the struct is NULL.
    */

    psFPA* fpa = psFPAAlloc(8, exp);

    if (fpa == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc returned a NULL.");
        return 1;
    }

    if (fpa->exposure != exp) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set the exposure.");
        return 2;
    }

    if (psMemGetRefCounter(exp) != 2) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not increment reference counter for exposure.");
        return 3;
    }

    if (fpa->chips->n != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set the number of chips properly.");
        return 4;
    }

    if (fpa->chips->nalloc != 8) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not allocate space for the number of chips properly.");
        return 4;
    }

    for (psS32 lcv=0; lcv < 8; lcv++) {
        if (fpa->chips->data[lcv] != NULL) {
            psLogMsg(__func__,PS_LOG_ERROR,
                     "psFPAAlloc did not set chip %d to NULL.", lcv);
            return 5;
        }
    }

    if (fpa->metadata != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set metadata to NULL.");
        return 6;
    }

    if (fpa->fromTangentPlane != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set fromTangentPlane to NULL.");
        return 7;
    }

    if (fpa->toTangentPlane != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set toTangentPlane to NULL.");
        return 8;
    }

    if (fpa->pattern != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set pattern to NULL.");
        return 9;
    }

    if (fpa->grommit == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set grommit using given exposure.");
        return 10;
    }

    if (fpa->colorPlus != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set colorPlus to NULL.");
        return 11;
    }

    if (fpa->colorMinus != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set colorMinus to NULL.");
        return 12;
    }

    if (fpa->projection != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set projection to NULL.");
        return 13;
    }

    /*
        2. Call psFPAAlloc with nChips = 0. Verify that the chips array is
           zero in size and the program execution does not stop.
    */

    psFPA* fpa2 = psFPAAlloc(0,exp);

    if (fpa2->chips->n != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set the number of chips properly.");
        return 14;
    }

    if (fpa2->chips->nalloc != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set the nalloc number of chips properly.");
        return 14;
    }

    /*
        3. Call psFPAAlloc with a NULL psExposure. Verify that the program
           execution doe not stop and the exposure attribute is NULL.
    */

    psFPA* fpa3 = psFPAAlloc(4,NULL);
    if (fpa3->exposure != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psFPAAlloc did not set the exposure to NULL given NULL parameter.");
        return 15;
    }

    /*
        4. Call psFPAAlloc and set all references in the struct to a memory
           buffer. Verify that psFree cleans up all the buffers referenced in
           the struct, i.e., there is no memory leaks generated.
    */

    fpa->chips->n = fpa->chips->nalloc;
    for (psS32 lcv=0; lcv < 8; lcv++) {
        fpa->chips->data[lcv] = psAlloc(4);
    }

    fpa->metadata = psAlloc(4);
    fpa->fromTangentPlane = psAlloc(4);
    fpa->toTangentPlane = psAlloc(4);
    fpa->pattern = psAlloc(4);
    fpa->colorPlus  = psAlloc(4);
    fpa->colorMinus  = psAlloc(4);
    fpa->projection  = psAlloc(4);

    psFree(fpa3);
    psFree(fpa2);
    psFree(fpa);
    psFree(exp);
    psFree(obs);
    psFree(now);
    psLibFinalize();

    return 0;
}

static psS32 testChipAlloc(void)
{
    char* name = "The Kaiser Royal Observatory";

    psTime* now = psTimeGetTime(PS_TIME_TAI);

    psObservatory* obs = psObservatoryAlloc(name,
                                            20.7*M_PI/180.0, 156.3*M_PI/180.0, 3055.0, 0.0065f);

    psExposure* exp = psExposureAlloc(1.0, 2.0, 3.0, 4.0, 5.0,
                                      now, 6.0f, 260.0f, 1013.0f, 0.7f, 10.0f, 0.650f, obs);

    psFPA* fpa = psFPAAlloc(8, exp);

    // N.B. psFPAAlloc made made a reference to any of these that it is
    // referencing, so these don't necessary are actually freed here.  Just
    // these references to the buffers are freed.
    psFree(exp);
    psFree(obs);
    psFree(now);

    /*
        1. invoke psChipAlloc with nCells > 0 and parentFPA non-NULL. Verify
           that:
        a. the cells array is of the size nCells and all elements are NULL.
        b. parent attribute is set to parentFPA parameter and the ref. count
           was incremented.
        c. all other attributes are initialized to NULL or 0.
    */

    psChip* chip = psChipAlloc(8, fpa);

    if (chip == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psChipAlloc returned NULL.");
        return 1;
    }

    if (chip->cells->n != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not set the number of cells properly.");
        return 2;
    }

    if (chip->cells->nalloc != 8) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not allocate cell array size properly.");
        return 2;
    }

    for (psS32 lcv=0; lcv < 8; lcv++) {
        if (chip->cells->data[lcv] != NULL) {
            psLogMsg(__func__,PS_LOG_ERROR,
                     "psChipAlloc did not set cell %d to NULL.", lcv);
            return 3;
        }
        chip->cells->data[lcv] = psAlloc(4); // to check if these are freed.
    }
    chip->cells->n = 8;

    if (chip->parent != fpa) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not set the parent properly.");
        return 4;
    }

    if (psMemGetRefCounter(fpa) != 1) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc incremented reference counter for parent FPA.");
        return 5;
    }

    if (chip->metadata != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not set metadata to NULL.");
        return 6;
    }
    chip->metadata = psAlloc(4); // to check if these are freed.

    if (chip->toFPA != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not set toFPA to NULL.");
        return 7;
    }
    chip->toFPA = psAlloc(4); // to check if these are freed.

    if (chip->fromFPA != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not set fromFPA to NULL.");
        return 8;
    }
    chip->fromFPA = psAlloc(4); // to check if these are freed.

    /*
        2. invoke psChipAlloc with nCells = 0. Verify that:
        a. execution does not halt
        b. the cells array is of the size of one.
    */

    psChip* chip2 = psChipAlloc(0,fpa);

    if (chip2 == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psChipAlloc returned NULL.");
        return 11;
    }

    if (chip2->cells->n != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not set the number of cells properly.");
        return 12;
    }

    if (chip2->cells->nalloc != 1) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not allocate cell array size properly.");
        return 12;
    }

    if (chip2->parent != fpa) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not set the parent properly.");
        return 14;
    }

    if (psMemGetRefCounter(fpa) != 1) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc incremented reference counter for parent FPA.");
        return 15;
    }

    /*
        3. invoke psChipAlloc with parentFPA = NULL. Verify that parent
           attribute is NULL and no error is generated.
    */

    psChip* chip3 = psChipAlloc(8,NULL);

    if (chip3 == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psChipAlloc returned NULL.");
        return 21;
    }

    if (chip3->cells->n != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not set the number of cells properly.");
        return 22;
    }

    if (chip3->cells->nalloc != 8) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not allocate cell array properly.");
        return 23;
    }

    if (chip3->parent != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psChipAlloc did not set the parent to NULL.");
        return 24;
    }

    psFree(chip);
    psFree(chip2);
    psFree(chip3);
    psFree(fpa);
    psLibFinalize();

    return 0;
}

static psS32 testCellAlloc(void)
{
    char* name = "The Kaiser Royal Observatory";

    psTime* now = psTimeGetTime(PS_TIME_TAI);

    psObservatory* obs = psObservatoryAlloc(name,
                                            20.7*M_PI/180.0,
                                            156.3*M_PI/180.0,
                                            3055.0,
                                            0.0065f);

    psExposure* exp = psExposureAlloc(1.0,
                                      2.0,
                                      3.0,
                                      4.0,
                                      5.0,
                                      now,
                                      6.0f,
                                      260.0f,
                                      1013.0f,
                                      0.7f,
                                      10.0f,
                                      0.650f,
                                      obs);

    psFPA* fpa = psFPAAlloc(8, exp);

    psChip* chip = psChipAlloc(8, fpa);

    // N.B. psChipAlloc made a reference to any of these that it is
    // referencing, so these are not actually freed here.  Just
    // these references to the buffers are freed.
    psFree(fpa);
    psFree(exp);
    psFree(obs);
    psFree(now);

    /*
        1. invoke psCellAlloc with nReadouts > 0 and parentChip non-NULL. Verify that:
        a. the readouts array is of the size nReadouts and all elements are NULL.
        b. parent attribute is set to parentChip parameter and the ref. count
           was incremented.
        c. all other attributes are initialized to NULL or 0.
    */

    psCell* cell1 = psCellAlloc(8,chip);

    if (cell1 == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psCellAlloc returned NULL.");
        return 1;
    }

    if (cell1->readouts->n != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set the number of readouts properly.");
        return 2;
    }

    if (cell1->readouts->nalloc != 8) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not allocat the readout array properly.");
        return 2;
    }

    for (psS32 lcv=0; lcv < 8; lcv++) {
        if (cell1->readouts->data[lcv] != NULL) {
            psLogMsg(__func__,PS_LOG_ERROR,
                     "psCellAlloc did not set readout %d to NULL.", lcv);
            return 3;
        }
        cell1->readouts->data[lcv] = psAlloc(4); // to check if these are freed.
    }
    cell1->readouts->n = 8;

    if (cell1->parent != chip) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set the parent properly.");
        return 4;
    }

    if (psMemGetRefCounter(chip) != 1) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc incremented reference counter for parent.");
        return 5;
    }

    if (cell1->metadata != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set metadata to NULL.");
        return 6;
    }
    cell1->metadata = psAlloc(4); // to check if these are freed.

    if (cell1->toChip != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set toChip to NULL.");
        return 7;
    }
    cell1->toChip = psAlloc(4); // to check if these are freed.

    if (cell1->fromChip != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set fromChip to NULL.");
        return 8;
    }
    cell1->fromChip = psAlloc(4); // to check if these are freed.

    if (cell1->toFPA != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set toFPA to NULL.");
        return 9;
    }
    cell1->toFPA = psAlloc(4); // to check if these are freed.

    if (cell1->toTP != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set toTP to NULL.");
        return 10;
    }
    cell1->toTP = psAlloc(4); // to check if these are freed.

    /*
        2. invoke psChipAlloc with nCells = 0. Verify that:
        a. execution does not halt
        b. the cells array is of the size of one.
    */

    psCell* cell2 = psCellAlloc(0,chip);

    if (cell2 == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psCellAlloc returned NULL.");
        return 11;
    }

    if (cell2->readouts->n != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set the number of readouts properly.");
        return 12;
    }

    if (cell2->readouts->nalloc != 1) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not allocate the readout array properly.");
        return 13;
    }

    if (cell2->parent != chip) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set the parent properly.");
        return 14;
    }

    if (psMemGetRefCounter(chip) != 1) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc incremented reference counter for parent FPA.");
        return 15;
    }

    /*
        3. invoke psChipAlloc with parentFPA = NULL. Verify that parent
           attribute is NULL and no error is generated.
    */

    psCell* cell3 = psCellAlloc(8,NULL);

    if (cell3 == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psCellAlloc returned NULL.");
        return 21;
    }

    if (cell3->readouts->n != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set the number of cells properly.");
        return 22;
    }

    if (cell3->readouts->nalloc != 8) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set the number of cells properly.");
        return 23;
    }

    if (cell3->parent != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psCellAlloc did not set the parent to NULL.");
        return 24;
    }

    psFree(chip);
    psFree(cell1);
    psFree(cell2);
    psFree(cell3);
    psLibFinalize();

    return 0;
}

static psS32 testReadoutAlloc(void)
{
    psReadout* readout = psReadoutAlloc();

    if (readout == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psReadoutAlloc returned NULL.");
        return 1;
    }

    if (readout->col0 != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psReadoutAlloc did not set col0 properly.");
        return 2;
    }

    if (readout->row0 != 0) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psReadoutAlloc did not set row0 properly.");
        return 3;
    }

    if (readout->image != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psReadoutAlloc did not set the image properly.");
        return 4;
    }

    readout->image = psAlloc(4); // to check if these are freed.

    if (readout->metadata != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psReadoutAlloc did not set metadata to NULL.");
        return 6;
    }
    readout->metadata = psAlloc(4); // to check if these are freed.

    if (readout->mask != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psReadoutAlloc did not set mask to NULL.");
        return 7;
    }
    readout->mask = psAlloc(4); // to check if these are freed.

    if (readout->objects != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,
                 "psReadoutAlloc did not set objects to NULL.");
        return 8;
    }
    readout->objects = psAlloc(4); // to check if these are freed.

    /*
        2. invoke psReadoutAlloc with NULL image. Verify that:
        a. execution does not halt
        b. the image attribute is NULL.
    */

    psReadout* readout2 = psReadoutAlloc(3,4,NULL);

    if (readout2 == NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psReadoutAlloc returned NULL.");
        return 11;
    }

    if (readout2->image != NULL) {
        psLogMsg(__func__,PS_LOG_ERROR,"psReadoutAlloc didn't set image to NULL, as given.");
        return 12;
    }

    psFree(readout);
    psFree(readout2);

    return 0;
}
