/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * All rights reserved. * * * * This file is part of HDF. The full HDF copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at * * http://hdfgroup.org/products/hdf4/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /**************************************************************************** * tncunlim.c - tests reading/writing variables with unlimited dimension using * nc API. The tests here are added to test the behavior of the * library when dealing with unlimited dimensions with nc API. The * tests show that the data is correctly written when: * + data added immediately after last record * + data added skipping one or more records * + data overridden existing data * + data read pass the end of that variable but not the max in * all the variables in the file (on going) * * Structure of the file: * test_ncunlim - test driver * test_1dimsinglevar - tests on a single variable with only 1 dimension * test_1dimmultivars - tests on multiple variables with only 1 dimension * test_multi_dimvars - tests on multiple variables with multiple dimensions * BMR - Dec 22, 2008 ****************************************************************************/ #include "mfhdf.h" #include "/mnt/hdf/bmribler/srcdir/hdf4/mfhdf/libsrc/hdftest.h" /******************************************************************** Name: test_1dimsinglevar() - tests on a single variable with only 1 dimension Description: The main contents include: - write 4 elements starting at index 0 - append 2 elements starting at index 6, that is indices 4 and 5 will be written with fill value - append 3 elements immediately at the end of the data - overwrite indices 0 and 1 Return value: The number of errors occurred in this routine. BMR - Dec 22, 2008 *********************************************************************/ #define DIM0 20 #define FILENAME1 "onedimonevar.nc" static int test_1dimsinglevar() { int ncid; /* file id */ int varid; /* variable id */ int time_dim; /* unlimited dimension */ int dims[1]; /* variable shapes */ long dimsize = 0; /* dimension size buffer */ short outdata[DIM0]; /* data read back */ char varname[10]; /* variable name */ nc_type rh_type; /* variable type */ int rh_ndims; /* number of dims */ int rh_dims[MAX_VAR_DIMS]; /* variable shape */ int rh_natts; /* number of attributes */ int ii; short fillval = 99; /* fill value for the variable */ intn status = 0; /* returned by called functions */ intn num_errs = 0; /* number of errors so far */ /* result data to compare against read data; the first two elements will be changed to "1,2" later for the last test. */ short result[] = {320,301,301,302,99,99,30,31,801,802,803}; /* enter define mode */ ncid = nccreate(FILENAME1, NC_CLOBBER); CHECK(ncid, -1, "nccreate"); /* variables will be filled with fill values when data is missing */ status = ncsetfill(ncid, NC_FILL); CHECK(status, -1, "ncsetfill"); /* define the unlimited dimension */ time_dim = ncdimdef(ncid, "time", NC_UNLIMITED); CHECK(status, -1, "ncdimdef"); /* define the variable */ dims[0] = time_dim; varid = ncvardef (ncid, "Variable 1", NC_SHORT, 1, dims); CHECK(varid, -1, "ncvardef"); /* write the fill value attribute */ status = ncattput(ncid, varid, "_FillValue", NC_SHORT, 1, &fillval ); CHECK(status, -1, "ncattput"); /* leave define mode */ status = ncendef (ncid); CHECK(status, -1, "ncendef"); { /* write data the first time */ long rh_start[] = {0}; /* starting writing at beginning, index 0 */ long rh_edges[] = {4}; /* four elements */ short data[] = { 320,301,301,302}; /* write 4 elements starting at index 0 */ status = ncvarput(ncid, varid, rh_start, rh_edges, (void *)data); CHECK(status, -1, "ncvarput"); } /* get variable information and size of the unlimited dimension */ status = ncvarinq (ncid, varid, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 4, "ncdiminq"); /* close file */ status = ncclose (ncid); CHECK(status, -1, "ncclose"); /* open file for reading and writing */ ncid = ncopen(FILENAME1, NC_RDWR); CHECK(ncid, -1, "ncopen"); /* get access to the variable */ varid = ncvarid(ncid, "Variable 1"); CHECK(varid, -1, "ncvarid"); /* get and verify variable info and size of the unlimited dimension again */ status = ncvarinq (ncid, varid, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 4, "ncdiminq"); { /* read and verify data of the variable */ long start[] = {0}; long edges[1]; edges[0] = dimsize; HDmemset(outdata, 0, DIM0); status = ncvarget(ncid, varid, start, edges, outdata); CHECK(status, -1, "ncvarget"); /* verify data, should be "320 301 301 302" */ for (ii = 0; ii < dimsize; ii++) { if (outdata[ii] != result[ii]) fprintf(stderr,"test_1dimsinglevar: Read data %d doesn't match input %d at index %d\n", outdata[ii], result[ii], ii); } } /* end read data */ { /* append data to variable pass the end */ long rh_start[] = {6}; /* the end is 3 */ long rh_edges[] = {2}; /* two elements */ short data[] = { 30,31}; /* write 2 values starting at index 6 */ status = ncvarput(ncid, varid, rh_start, rh_edges, (void *)data); CHECK(status, -1, "ncvarput"); } /* get and verify variable info and size of the unlimited dimension again */ status = ncvarinq (ncid, varid, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 8, "ncdiminq"); { /* read variable after appending with gap */ long start[] = {0}; long edges[1]; edges[0] = dimsize; HDmemset(outdata, 0, DIM0); status = ncvarget(ncid, varid, start, edges, outdata); CHECK(status, -1, "ncvarget"); /* verify data, should be "320,301,301,302,99,99,30,31" where 99 is fillvalue */ for (ii = 0; ii < edges[0]; ii++) { if (outdata[ii] != result[ii]) fprintf(stderr,"test_1dimsinglevar: Read data %d doesn't match input %d at index %d\n", outdata[ii], result[ii], ii); } } /* end read data */ { /* write variable immediately pass the end */ long rh_start[] = {0}; long rh_edges[] = {3}; short data[] = { 801,802,803}; rh_start[0] = dimsize; /* starting immediatly pass dimension size */ /* write 3 elements to the variable starting at 'dimsize' */ status = ncvarput(ncid, varid, rh_start, rh_edges, (void *)data); CHECK(status, -1, "ncvarput"); } /* get and verify variable info and size of the unlimited dimension */ status = ncvarinq (ncid, varid, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 11, "ncdiminq"); { /* read variable */ long start[] = {0}; long edges[1]; edges[0] = dimsize; HDmemset(outdata, 0, DIM0+2); status = ncvarget(ncid, varid, start, edges, outdata); CHECK(status, -1, "ncvarget"); /* verify data, should be "320,301,301,302,99,99,30,31,801,802,803" where 99 is fill value */ for (ii = 0; ii < edges[0]; ii++) { if (outdata[ii] != result[ii]) fprintf(stderr,"test_1dimsinglevar: Read data %d doesn't match input %d at index %d\n", outdata[ii], result[ii], ii); } } /* end read data */ { /* write variable to override current values */ long rh_start[] = {0}; /* starting at the beginning */ long rh_edges[] = {2}; /* two values */ short data[] = { 1,2}; /* write 2 elements overriding the first two values */ status = ncvarput(ncid, varid, rh_start, rh_edges, (void *)data); CHECK(status, -1, "ncvarput"); /* change expected data too */ result[0] = 1; result[1] = 2; } /* get and verify variable info and size of the unlimited dimension */ status = ncvarinq (ncid, varid, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 11, "ncdiminq"); { /* read and verify data */ long start[] = {0}; long edges[1]; edges[0] = dimsize; HDmemset(outdata, 0, DIM0+2); status = ncvarget(ncid, varid, start, edges, outdata); CHECK(status, -1, "ncvarget"); /* verify data, should be "1,2,301,302,99,99,30,31,801,802,803" where 99 is fill value, and first and second values are new */ for (ii = 0; ii < edges[0]; ii++) { if (outdata[ii] != result[ii]) fprintf(stderr,"test_1dimsinglevar: Read data %d doesn't match input %d at index %d\n", outdata[ii], result[ii], ii); } } /* end read data */ status = ncclose(ncid); CHECK(status, -1, "ncclose"); return 0; } /******************************************************************** Name: test_1dim_multivars() - tests reading/writing on multiple variables, each has 1 dimension Description: The main contents include: - write 4 elements starting at index 0 to variable #1 - write 2 elements starting at index 0 to variable #2 - close file and reopen for read/write - append 2 elements to variable #1, immediately after last written record - write 3 elements to variable #2, starting at index 4 - append 3 elements to variable #1, skipping 5 records after the last written record Return value: The number of errors occurred in this routine. BMR - Dec 22, 2008 *********************************************************************/ #define FILENAME2 "onedimmultivars.nc" static int test_1dim_multivars() { int ncid; /* file id */ int varid1, varid2; /* variable id */ int time_dim; /* unlimited dimension */ int dims[1]; /* variable shapes */ long dimsize = 0; /* dimension size buffer */ short outdata1[DIM0]; /* data read back */ char varname[10]; /* variable name */ nc_type rh_type; /* variable type */ int rh_ndims; /* number of dims */ int rh_dims[MAX_VAR_DIMS]; /* variable shape */ int rh_natts; /* number of attributes */ int ii; short var1_fillval=-1; /* fill value for the variable */ short var2_fillval=-2; /* fill value for the variable */ intn status = 0; /* returned by called functions */ intn num_errs = 0; /* number of errors so far */ /* result data to compare against read data; the first two elements will be changed to "1,2" later for the last test. */ short result1[] = {300,301,302,303,400,401,-1,-1,-1,-1,-1,-1,500,501,502}; short result2[] = {102,104,-2,-2,200,201,202,-2,-2,-2,-2,-2,-2,-2,-2}; /* enter define mode */ ncid = nccreate(FILENAME2, NC_CLOBBER); CHECK(ncid, -1, "nccreate"); /* variables will be filled with fill values when data is missing */ status = ncsetfill(ncid, NC_FILL); CHECK(status, -1, "ncsetfill"); /* define the unlimited dimension */ time_dim = ncdimdef(ncid, "time", NC_UNLIMITED); CHECK(time_dim, -1, "ncdimdef"); /* define two 1-dim variables, named "Variable 1" and "Variable 2" */ dims[0] = time_dim; varid1 = ncvardef (ncid, "Variable 1", NC_SHORT, 1, dims); CHECK(varid1, -1, "ncvardef"); varid2 = ncvardef (ncid, "Variable 2", NC_SHORT, 1, dims); CHECK(varid2, -1, "ncvardef"); /* write the fill value attribute of the two variables */ status = ncattput(ncid, varid1, "_FillValue", NC_SHORT, 1, &var1_fillval); CHECK(status, -1, "ncattput"); status = ncattput(ncid, varid2, "_FillValue", NC_SHORT, 1, &var2_fillval); CHECK(status, -1, "ncattput"); /* leave define mode */ status = ncendef (ncid); CHECK(status, -1, "ncendef"); { /* Write data to both variables */ long rh_start[] = {0}; long rh_edges[] = {4}; short data1[] = { 300,301,302,303}; short data2[] = { 102, 104}; /* write 4 elements to Variable 1 starting at index 0 */ status = ncvarput(ncid, varid1, rh_start, rh_edges, (void *)data1); CHECK(status, -1, "ncvarput"); /* write 2 elements to Variable 2 starting at index 0 */ rh_edges[0] = 2; status = ncvarput(ncid, varid2, rh_start, rh_edges, (void *)data2); CHECK(status, -1, "ncvarput"); } /* get Variable 1's information and size of the unlimited dimension */ status = ncvarinq (ncid, varid1, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 4, "ncdiminq"); /* get Variable 2's information and size of the unlimited dimension */ status = ncvarinq (ncid, varid2, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 4, "ncdiminq"); /* close file */ status = ncclose (ncid); CHECK(status, -1, "ncclose"); /* open file for reading and writing */ ncid = ncopen(FILENAME2, NC_RDWR); CHECK(ncid, -1, "ncopen"); /* get access to the two variables */ varid1 = ncvarid(ncid, "Variable 1"); CHECK(varid1, -1, "ncvarid"); varid2 = ncvarid(ncid, "Variable 2"); CHECK(varid2, -1, "ncvarid"); /* get Variable 1's information and size of the unlimited dimension */ status = ncvarinq (ncid, varid1, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 4, "ncdiminq"); /* get Variable 2's information and size of the unlimited dimension */ status = ncvarinq (ncid, varid2, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 4, "ncdiminq"); { /* Read data of the variables */ long start[] = {0}; long edges[1]; edges[0] = dimsize; HDmemset(outdata1, 0, DIM0); /* read and verify data of Variable 1 */ status = ncvarget(ncid, varid1, start, edges, outdata1); CHECK(status, -1, "ncvarget"); /* verify data of Variable 1, should be "320 301 301 302" */ for (ii = 0; ii < edges[0]; ii++) { if (outdata1[ii] != result1[ii]) fprintf(stderr,"test_1dim_multivars: Read data %d doesn't match input %d at index %d in Variable 1\n", outdata1[ii], result1[ii], ii); } /* read and verify data of Variable 2 */ HDmemset(outdata1, 0, DIM0); status = ncvarget(ncid, varid2, start, edges, outdata1); CHECK(status, -1, "ncvarget"); /* verify data of Variable 2, should be "102 104" */ for (ii = 0; ii < edges[0]; ii++) { if (outdata1[ii] != result2[ii]) fprintf(stderr,"test_1dim_multivars: Read data %d doesn't match input %d at index %d in Variable 2\n", outdata1[ii], result2[ii], ii); } } /* end read data */ { /* Write to variable immediately after last written record */ long rh_start[] = {0}; long rh_edges[] = {2}; short data2[] = {400, 401}; /* write 2 elements to Variable 1 at index 'dimsize' */ rh_start[0] = dimsize; status = ncvarput(ncid, varid1, rh_start, rh_edges, (void *)data2); CHECK(status, -1, "ncvarput"); } /* get information of Variable 1 and size of the unlimited dimension */ status = ncvarinq (ncid, varid1, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 6, "ncdiminq"); { /* Read variables */ long start[] = {0}; long edges[] = {0}; /* current data of Variable 2 should look like this, because of the extension with fill value to match the max number of records in the file */ short tempresult[] = {102,104,-2,-2,-2,-2}; /* read up to max number of records in the file */ edges[0] = dimsize; /* read and verify data of Variable 1 */ /* read data should be: 300 301 302 303 400 401 */ HDmemset(outdata1, 0, DIM0); status = ncvarget(ncid, varid1, start, edges, outdata1); CHECK(status, -1, "ncvarget"); for (ii = 0; ii < edges[0]; ii++) { if (outdata1[ii] != result1[ii]) fprintf(stderr,"test_1dim_multivars: Read data %d doesn't match input %d at index %d in Variable 1\n", outdata1[ii], result1[ii], ii); } /* read and verify data of Variable 2 */ /* read data should be: 102 104 -2 -2 -2 -2 */ HDmemset(outdata1, 0, DIM0); status = ncvarget(ncid, varid2, start, edges, outdata1); CHECK(status, -1, "ncvarget"); for (ii = 0; ii < edges[0]; ii++) { if (outdata1[ii] != tempresult[ii]) fprintf(stderr,"test_1dim_multivars: Read data %d doesn't match input %d at index %d in Variable 2\n", outdata1[ii], result2[ii], ii); } } /* end read data */ { /* Append to variable with gap */ long rh_start[] = {4}; long rh_edges[] = {3}; short data2[] = {200, 201, 202}; /* write 3 elements to Variable 2 at index 4 */ status = ncvarput(ncid, varid2, rh_start, rh_edges, (void *)data2); CHECK(status, -1, "ncvarget"); } /* get variable information and size of the unlimited dimension */ status = ncvarinq (ncid, varid2, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 7, "ncdiminq"); { /* Read both variables */ long start[] = {0}; long edges[1]; edges[0] = dimsize; /* read and verify data of Variable 1 */ /* read data should be: 300 301 302 303 400 401 -1 */ HDmemset(outdata1, 0, DIM0); status = ncvarget(ncid, varid1, start, edges, outdata1); CHECK(status, -1, "ncvarget"); for (ii = 0; ii < edges[0]; ii++) { if (outdata1[ii] != result1[ii]) fprintf(stderr,"test_1dim_multivars: Read data %d doesn't match input %d at index %d in Variable 1\n", outdata1[ii], result1[ii], ii); } /* read and verify data of Variable 1 */ /* read data should be: 102 104 -2 -2 200 201 202 */ HDmemset(outdata1, 0, DIM0); status = ncvarget(ncid, varid2, start, edges, outdata1); CHECK(status, -1, "ncvarget"); for (ii = 0; ii < edges[0]; ii++) { if (outdata1[ii] != result2[ii]) fprintf(stderr,"test_1dim_multivars: Read data %d doesn't match input %d at index %d in Variable 2\n", outdata1[ii], result2[ii], ii); } } /* end read data */ { /* Append to a variable, with gap */ long rh_start[] = {0}; long rh_edges[] = {3}; short data2[] = {500, 501, 502}; rh_start[0] = dimsize+5; /* write 3 elements to Variable 1 at index 'dimsize+5', leaving a gap of 5 records that will be filled with fill value */ status = ncvarput(ncid, varid1, rh_start, rh_edges, (void *)data2); CHECK(status, -1, "ncvarput"); /* data now: 300 301 302 303 400 401 -1 -1 -1 -1 -1 -1 500 501 502 */ } /* get variable information and size of the unlimited dimension */ status = ncvarinq (ncid, varid2, varname, &rh_type, &rh_ndims, rh_dims, &rh_natts); CHECK(status, -1, "ncvarinq"); status = ncdiminq(ncid, rh_dims[0], 0, &dimsize); CHECK(status, -1, "ncdiminq"); VERIFY(dimsize, 15, "ncdiminq"); { /* Read both variables */ long start[] = {0}; long edges[1]; edges[0] = dimsize; /* read and verify data of Variable 1; read data should be: */ /* 300 301 302 303 400 401 -1 -1 -1 -1 -1 -1 500 501 502 */ HDmemset(outdata1, 0, DIM0); status = ncvarget(ncid, varid1, start, edges, outdata1); CHECK(status, -1, "ncvarget"); for (ii = 0; ii < edges[0]; ii++) { if (outdata1[ii] != result1[ii]) fprintf(stderr,"test_1dim_multivars: Read data %d doesn't match input %d at index %d in Variable 1\n", outdata1[ii], result1[ii], ii); } /* read and verify data of Variable 2; read data should be: */ /* 102 104 -2 -2 200 201 202 -2 -2 -2 -2 -2 -2 -2 -2 */ HDmemset(outdata1, 0, DIM0); status = ncvarget(ncid, varid2, start, edges, outdata1); CHECK(status, -1, "ncvarget"); for (ii = 0; ii < edges[0]; ii++) { if (outdata1[ii] != result2[ii]) fprintf(stderr,"test_1dim_multivars: Read data %d doesn't match input %d at index %d in Variable 2\n", outdata1[ii], result2[ii], ii); } } /* end read data */ /* close file */ status = ncclose(ncid); CHECK(status, -1, "ncclose"); return num_errs; } /* test_1dim_multivars */ /* Test driver for testing reading/writing variables with unlimited dimension using nc API. */ extern int main() { int num_errs = 0; /* Test single variable with 1 unlimited dimension */ num_errs = num_errs + test_1dimsinglevar(); /* Test multiple variables with 1 unlimited dimension */ num_errs = num_errs + test_1dim_multivars(); /* Test multiple variables with multiple dimensions */ /* num_errs = num_errs + test_multi_dimvars(); */ return num_errs; }