/******************************************************************************
*
*  NSSDC/CDF                            Y2K Test Program (C interface).
*
*  Version 1.0, 07-May-98, Raytheon STX.
*
*  Modification history:
*
*   V1.0   07-May-98, M Liu      Check to see if CDF is Y2K compliant
*
******************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "cdf.h"

#if defined(vms)
#include <ssdef>
#define EXIT_SUCCESS_   SS$_NORMAL
#define EXIT_FAILURE_   SS$_ABORT
#else
#define EXIT_SUCCESS_   0
#define EXIT_FAILURE_   1
#endif

/******************************************************************************
* Increased stack size for Borland C on IBM PC.
******************************************************************************/

#if defined(BORLANDC)
extern unsigned _stklen = 12000u;
#endif

/******************************************************************************
* Macros/prototypes.
******************************************************************************/

#define N_DIMS          1
#define DIM_0_SIZE      4

void QuitCDF PROTOARGs((CDFstatus status, char *where, CDFid id));
void QuitEPOCH PROTOARGs((char *where));

/******************************************************************************
* Main.
******************************************************************************/

int main () {
CDFid           id;
CDFstatus       status;
int             dim_n;
static long     encoding = NETWORK_ENCODING;
static long     majority = ROW_MAJOR;
static long     numDims = N_DIMS;
static long     dimSizes[N_DIMS] = { DIM_0_SIZE };
static long     varDataType = { CDF_EPOCH };
static long     varNumElements = { 1 };
static long	indices[N_DIMS] = { DIM_0_SIZE };
long            varNum_out;
long            recNum;

static long     varRecVariance = { VARY };
static long     varDimVariances[N_DIMS] = { VARY };

static char     varName[] = "VAR1";

int 		i;
long            year, testyear[4];
long            month = 10;
long            day = 13;
long            hour = 12;
long            minute = 15;
long            second = 30;
long            msec = 000;
long            yearOut, monthOut, dayOut,
		hourOut, minuteOut, secondOut, msecOut;
double          epoch, epochOut;
char            epString[EPOCH_STRING_LEN+1];
char            epString1[EPOCH1_STRING_LEN+1];
char            epString2[EPOCH2_STRING_LEN+1];
char            epString3[EPOCH3_STRING_LEN+1];
char   		epStringTrue[4][EPOCH_STRING_LEN+1];
char 		epString1True[4][EPOCH1_STRING_LEN+1];
char    	epString2True[4][EPOCH2_STRING_LEN+1];
char	     	epString3True[4][EPOCH3_STRING_LEN+1];

/******************************************************************************
* Display title.
******************************************************************************/

printf ("Testing Y2K...\n");

/******************************************************************************
* Create CDF.
******************************************************************************/

status = CDFcreate ("TESTY2K", numDims, dimSizes, encoding, majority, &id);
if (status < CDF_OK) {
  if (status == CDF_EXISTS) {
     status = CDFopen ("TEST", &id);
     if (status < CDF_OK) QuitCDF (status, "1.0", id);
     status = CDFdelete (id);
     if (status < CDF_OK) QuitCDF (status, "1.1", id);
     status = CDFcreate ("TEST", numDims, dimSizes, encoding, majority, &id);
     if (status < CDF_OK) QuitCDF (status, "1.2", id);
  }
  else
     QuitCDF (status, "1.3", id);
}

/******************************************************************************
* Create variable.
******************************************************************************/

status = CDFvarCreate (id, varName, varDataType, varNumElements,
                       varRecVariance, varDimVariances, &varNum_out);
if (status < CDF_OK) QuitCDF (status, "2.0", id);

recNum = 0;
/******************************************************************************
* First test for 4-digit year 
******************************************************************************/
testyear[0] = 94; /* for year 94 not 1994 */
testyear[1] = 194; /* for year 194 */
testyear[2] = 1994; /* for year 1994 */
testyear[3] = 2000; /* for year 2000 */
printf(" test for 4-digit year...\n");
for (i=0; i<4; i++) {

  year = testyear[i]; 
  sprintf(epStringTrue[i],"13-Oct-%04ld 12:15:30.000",year);
  sprintf(epString1True[i],"%04ld1013.5107639",year);
  sprintf(epString2True[i],"%04ld1013121530",year);
  sprintf(epString3True[i],"%04ld-10-13T12:15:30.000Z",year);
  epoch = computeEPOCH (year, month, day, hour, minute, second, msec);

/******************************************************************************
* PUT to variable.
******************************************************************************/
  indices[0] = i;
  status = CDFvarPut (id, varNum_out, recNum, indices,
                      &epoch);
  if (status < CDF_OK) QuitCDF (status, "3.0", id);
}

for (i=0; i<4; i++) {
/******************************************************************************
* GET from the variable.
******************************************************************************/
  indices[0] = i;
  status = CDFvarGet (id, varNum_out, recNum, indices,
                      &epoch);
  if (status < CDF_OK) QuitCDF (status, "4.0", id);

  encodeEPOCH (epoch, epString);
  if (strcmp(epString,epStringTrue[i])) QuitEPOCH ("5.0");

  epochOut = parseEPOCH (epString);
  if (epochOut != epoch) QuitEPOCH ("5.1");

  encodeEPOCH1 (epoch, epString1); 
  if (strcmp(epString1,epString1True[i])) QuitEPOCH ("5.2");

  epochOut = parseEPOCH1 (epString1);
  if (epochOut != epoch) QuitEPOCH ("5.3");

  encodeEPOCH2 (epoch, epString2); 
  if (strcmp(epString2,epString2True[i])) QuitEPOCH ("5.4");

  epochOut = parseEPOCH2 (epString2);
  if (epochOut != epoch) QuitEPOCH ("5.5");

  encodeEPOCH3 (epoch, epString3);
  if (strcmp(epString3,epString3True[i])) QuitEPOCH ("5.6");

  epochOut = parseEPOCH3 (epString3);
  if (epochOut != epoch) QuitEPOCH ("5.7");

  EPOCHbreakdown (epoch, &yearOut, &monthOut, &dayOut, &hourOut, &minuteOut,
	  	  &secondOut, &msecOut);
  if (yearOut != testyear[i]) QuitEPOCH ("5a.1");
  if (monthOut != month) QuitEPOCH ("5a.2");
  if (dayOut != day) QuitEPOCH ("5a.3");
  if (hourOut != hour) QuitEPOCH ("5a.4");
  if (minuteOut != minute) QuitEPOCH ("5a.5");
  if (secondOut != second) QuitEPOCH ("5a.6");
  if (msecOut != msec) QuitEPOCH ("5a.7");
/*  printf(" test for year:%ld month:%ld day:%ld hour:%ld minute:%ld second:%ld millisecond:%ld\n",testyear[i],month,day,hour,minute,second,msec); */
}

recNum ++;
/******************************************************************************     
* Second test for leap year
******************************************************************************/
printf(" test for non-leap year...\n");
month = 2;
day = 29;
testyear[0] = 1997; /* not a lead year, so no 2/29. it should be 3/1 */
testyear[1] = 1999; /* ditto */
testyear[2] = 2001; /* ditto */
testyear[3] = 2002; /* ditto */

for (i=0; i<4; i++) {                                                               

  year = testyear[i];
  sprintf(epStringTrue[i],"01-Mar-%04ld 12:15:30.000",year);
  sprintf(epString1True[i],"%04ld0301.5107639",year);
  sprintf(epString2True[i],"%04ld0301121530",year);
  sprintf(epString3True[i],"%04ld-03-01T12:15:30.000Z",year);
  epoch = computeEPOCH (year, month, day, hour, minute, second, msec);

/******************************************************************************
* PUT to variable.
******************************************************************************/
  indices[0] = i;
  status = CDFvarPut (id, varNum_out, recNum, indices,
                      &epoch);
  if (status < CDF_OK) QuitCDF (status, "6.0", id);
}

for (i=0; i<4; i++) {
/******************************************************************************
* GET from the variable.
******************************************************************************/
  indices[0] = i;
  status = CDFvarGet (id, varNum_out, recNum, indices,
                      &epoch);
  if (status < CDF_OK) QuitCDF (status, "7.0", id);

  encodeEPOCH (epoch, epString);
  if (strcmp(epString,epStringTrue[i])) QuitEPOCH ("8.0");

  epochOut = parseEPOCH (epString);
  if (epochOut != epoch) QuitEPOCH ("8.1");

  encodeEPOCH1 (epoch, epString1);
  if (strcmp(epString1,epString1True[i])) QuitEPOCH ("8.2");

  epochOut = parseEPOCH1 (epString1);
  if (epochOut != epoch) QuitEPOCH ("8.3");

  encodeEPOCH2 (epoch, epString2);
  if (strcmp(epString2,epString2True[i])) QuitEPOCH ("8.4");

  epochOut = parseEPOCH2 (epString2);
  if (epochOut != epoch) QuitEPOCH ("8.5");

  encodeEPOCH3 (epoch, epString3);
  if (strcmp(epString3,epString3True[i])) QuitEPOCH ("8.6");

  epochOut = parseEPOCH3 (epString3);
  if (epochOut != epoch) QuitEPOCH ("8.7");

  EPOCHbreakdown (epoch, &yearOut, &monthOut, &dayOut, &hourOut, &minuteOut,
                  &secondOut, &msecOut);
  if (yearOut != testyear[i]) QuitEPOCH ("8a.1");
  if (monthOut != 3) QuitEPOCH ("8a.2");
  if (dayOut != 1) QuitEPOCH ("8a.3");
  if (hourOut != hour) QuitEPOCH ("8a.4");
  if (minuteOut != minute) QuitEPOCH ("8a.5");
  if (secondOut != second) QuitEPOCH ("8a.6");
  if (msecOut != msec) QuitEPOCH ("8a.7");
/*  printf(" test for year:%ld month:%ld day:%ld hour:%ld minute:%ld second:%ld millisecond:%ld\n",testyear[i],month,day,hour,minute,second,msec); */
/*  printf("   conveted to year:%ld month:%ld day:%ld hour:%ld minute:%ld second:%ld millisecond:%ld \n",yearOut,monthOut,dayOut,hour,minute,second,msec); */

}

recNum ++;

printf(" test for leap year...\n");
month = 2;
day = 29;
testyear[0] = 1996; /* a lead year, so 2/29 is good */
testyear[1] = 2000; /* ditto */
testyear[2] = 2004; /* ditto */
testyear[3] = 2008; /* ditto */

for (i=0; i<4; i++) {                                                               

  year = testyear[i];
  sprintf(epStringTrue[i],"29-Feb-%04ld 12:15:30.000",year);
  sprintf(epString1True[i],"%04ld0229.5107639",year);
  sprintf(epString2True[i],"%04ld0229121530",year);
  sprintf(epString3True[i],"%04ld-02-29T12:15:30.000Z",year);
  epoch = computeEPOCH (year, month, day, hour, minute, second, msec);

/******************************************************************************
* PUT to variable.
******************************************************************************/
  indices[0] = i;
  status = CDFvarPut (id, varNum_out, recNum, indices,
                      &epoch);
  if (status < CDF_OK) QuitCDF (status, "9.0", id);
}

for (i=0; i<4; i++) {
/******************************************************************************
* GET from the variable.
******************************************************************************/
  indices[0] = i;
  status = CDFvarGet (id, varNum_out, recNum, indices,
                      &epoch);
  if (status < CDF_OK) QuitCDF (status, "10.0", id);

  encodeEPOCH (epoch, epString);
  if (strcmp(epString,epStringTrue[i])) QuitEPOCH ("11.0");

  epochOut = parseEPOCH (epString);
  if (epochOut != epoch) QuitEPOCH ("11.1");

  encodeEPOCH1 (epoch, epString1);
  if (strcmp(epString1,epString1True[i])) QuitEPOCH ("11.2");

  epochOut = parseEPOCH1 (epString1);
  if (epochOut != epoch) QuitEPOCH ("11.3");

  encodeEPOCH2 (epoch, epString2);
  if (strcmp(epString2,epString2True[i])) QuitEPOCH ("11.4");

  epochOut = parseEPOCH2 (epString2);
  if (epochOut != epoch) QuitEPOCH ("11.5");

  encodeEPOCH3 (epoch, epString3);
  if (strcmp(epString3,epString3True[i])) QuitEPOCH ("11.6");

  epochOut = parseEPOCH3 (epString3);
  if (epochOut != epoch) QuitEPOCH ("11.7");

  EPOCHbreakdown (epoch, &yearOut, &monthOut, &dayOut, &hourOut, &minuteOut,
                  &secondOut, &msecOut);
  if (yearOut != testyear[i]) QuitEPOCH ("11a.1");
  if (monthOut != month) QuitEPOCH ("11a.2");
  if (dayOut != day) QuitEPOCH ("11a.3");
  if (hourOut != hour) QuitEPOCH ("11a.4");
  if (minuteOut != minute) QuitEPOCH ("11a.5");
  if (secondOut != second) QuitEPOCH ("11a.6");
  if (msecOut != msec) QuitEPOCH ("11a.7");
/*  printf(" test for year:%ld month:%ld day:%ld hour:%ld minute:%ld second:%ld millisecond:%ld\n",testyear[i],month,day,hour,minute,second,msec);*/
}

/******************************************************************************
* Close CDF.
******************************************************************************/

status = CDFclose (id);
if (status < CDF_OK) QuitCDF (status, "24.0", id);

/******************************************************************************
* Successful completion.
******************************************************************************/
printf("Testing successful...\n");
return EXIT_SUCCESS_;
}

/******************************************************************************
* QuitCDF.
******************************************************************************/

void QuitCDF (status, where, id)
CDFstatus status;
char *where;
CDFid id;
{
  char text[CDF_STATUSTEXT_LEN+1];
  printf ("Aborting at %s...\n", where);
  if (status < CDF_OK) {
    CDFerror (status, text);
    printf ("%s\n", text);
  }
  CDFclose (id);
  printf ("...test aborted.\n");
  exit (EXIT_FAILURE_);
}

/******************************************************************************
* QuitEPOCH.
******************************************************************************/

void QuitEPOCH (where)
char *where;
{
  printf ("Aborting at %s...test aborted.\n", where);
  exit (EXIT_FAILURE_);
}

