/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 I/O nc APIs for datasets with unlimited dimension. * This tests uses HDF nc APIs to create/write/read various datasets with * unlimited dimensions. Its original purpose is to verify that the APIs * behave as intented and to test some fixes related to bugzilla 1378. * The test cases in this file are listed at the bottom of the file. Each * test case is carried out in a single test function. Tests must cover these cases: - 1 unlim dim SDS - 2 unlim dim SDSs - 4 SDSs: 3 unlim SDSs and 1 2D SDS, and don't close file in between appends - appending data immediately after written records of an SDS - appending data skipping one record after written records - appending data skipping more than one record after written records - some with NC_FILL and some with NC_NOFILL * * Structure of the file: * test_ncunlim - test driver * test_1var_1Dunlim - tests writing/appending/reading with only 1 * record variable in the file. * utility function - any helper routine ****************************************************************************/ /* #include #include "h4config.h" #ifdef H4_HAVE_NETCDF #include "netcdf.h" #else #include "hdf4_netcdf.h" #endif */ #include "mfhdf.h" #define CHECKFAIL(status, mesg) {\ if (status == -1) \ fprintf(stderr," %s\n", mesg);} #define VERIFYFAIL(status, mesg) {\ if (status != -1) \ fprintf(stderr," %s\n", mesg);} float a_val[2][3] = { {1.0, 2.0, 3.0}, {4.0, 5.0, 6.0} }; int date_val[12] = {840116, 840214, 840316, 840415, 840516, 840615, 840716, 840816, 840915, 841016, 841115, 841216 }; int time_val[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; short b_val[][3][2] = { {{1, 1}, {2, 2}, {3, 3}}, {{4, 4}, {5, 5}, {6, 6}}, {{7, 7}, {8, 8}, {9, 9}}, {{10, 10}, {11, 11}, {12, 12}}, {{13, 13}, {14, 14}, {15, 15}}, {{16, 16}, {17, 17}, {18, 18}}, {{19, 19}, {20, 20}, {21, 22}}, {{23, 23}, {24, 24}, {25, 25}}, {{26, 26}, {27, 27}, {28, 28}}, {{29, 29}, {30, 30}, {31, 31}}, {{32, 32}, {33, 33}, {34, 34}}, {{35, 35}, {36, 36}, {37, 37}} }; /*************************************************************************** Test Case nc-1: Name: test_1var_1Dunlim Summary: 1 variable with 1 unlimited dimension create/write/closefile/append immediate/closefile/append with gap Details: - create an unlim dimension - create a variable that uses the unlim dimension - write 4 elements to the variable - read info and verify number of recs in the variable - close the file and re-open the file - read info and verify number of recs in the variable again - read and verify data - write 4 more elements immediately after the last written record - read and verify number of recs in the variable - read and verify data - close file and re-open the file - read and verify number of recs in the variable - write 2 more elements, skipping 3 records - read and verify number of recs in the variable - read and verify data - close file BMR - 2008/12/10 ****************************************************************************/ #define FILE1_NAME "tvars_with_unlim.nc" #define VAR_NAME "Only Variable" #define DIM_NAME "Only Dimension" static intn test_1var_1Dunlim() { static char pname[] = "test_1var_1Dunlim"; int ncid, var_id, dim_id; int dims[1]; char varname[20]; long start[] = {0}; long edges[] = {0}; long dimsize[] = {0}; nc_type type; int ndims; int natts; short outdata[100]; short final_data[] = {10,11,12,13,20,21,22,23,-32767,-32767,-32767,30,31}; int ii; int status; int num_errs = 0; fprintf(stderr, "*** Testing %s ...\t", &pname[5]); ncid = nccreate(FILE1_NAME, NC_CLOBBER); /* CHECK(ncid, FAIL, "In test_1var_1Dunlim: nccreate '%s'", path); */ /* define dimensions */ dim_id = ncdimdef(ncid, DIM_NAME, NC_UNLIMITED); /* define variables */ dims[0] = dim_id; var_id = ncvardef (ncid, VAR_NAME, NC_SHORT, 1, dims); /* leave define mode */ status = ncendef (ncid); { /* write variable first time */ start[0] = 0; edges[0] = 4; short data[] = { 10,11,12,13}; fprintf(stderr, "\n---write 4 items to Only Variable\n"); status = ncvarput(ncid, var_id, start, edges, (void *)data); fprintf(stderr, "done ---write 1x3x2 to Variable 1\n\n"); } /* inquire dimension size */ status = ncdiminq(ncid, dim_id, 0, dimsize); /* inquire about the variable */ status = ncvarinq (ncid, var_id, varname, &type, &ndims, dims, &natts); /* fprintf(stderr, "variable <%s> has %d dimensions: %d\n", varname, ndims, dimsize[0]); */ /* close file */ status = ncclose (ncid); fprintf(stderr, "Close file...\n"); /* open file for read/write to append data */ ncid = ncopen(FILE1_NAME, NC_RDWR); fprintf(stderr, "\nOpen file %s first time\n", FILE1_NAME); /* inquire dimension size */ dimsize[0] = 0; dim_id = ncdimid(ncid, DIM_NAME); status = ncdiminq(ncid, dim_id, 0, dimsize); /* Inquire about the variable */ var_id = ncvarid(ncid, VAR_NAME); /* Read and verify dimension size and variable's data */ edges[0] = dimsize[0]; HDmemset(outdata, 0, dimsize[0]); status = ncvarget(ncid, var_id, start, edges, outdata); for (ii = 0; ii < dimsize[0]; ii++) fprintf(stderr, " %d ", outdata[ii]); { /* Write 4 values to the variable, immediately after the written record */ short data[] = { 20,21,22,23}; start[0] = dimsize[0]; edges[0] = 4; status = ncvarput(ncid, var_id, start, edges, (void *)data); } /* end append data */ /* Read and verify dimension size and variable's data after appending */ status = ncdiminq(ncid, dim_id, 0, dimsize); /* read dimsize */ fprintf(stderr, "dimension size after appending = %d, should be 8\n", dimsize[0]); start[0] = 0; /* start reading at first element */ edges[0] = dimsize[0]; /* entire dimension */ HDmemset(outdata, 0, dimsize[0]); status = ncvarget(ncid, var_id, start, edges, outdata); /* read data */ /* Verify the current data of the variable */ for (ii = 0; ii < dimsize[0]; ii++) if (outdata[ii] != final_data[ii]) { num_errs++; fprintf(stderr, "Wrong value at index %d, should be %d, but read %d\n", ii, outdata[ii], final_data[ii]); } /* Close the file */ status = ncclose (ncid); /* Open file for read/write to append data */ ncid = ncopen(FILE1_NAME, NC_RDWR); fprintf(stderr, "\nOpen file %s second time\n", FILE1_NAME); /* inquire dimension size */ dimsize[0] = 0; dim_id = ncdimid(ncid, DIM_NAME); status = ncdiminq(ncid, dim_id, 0, dimsize); fprintf(stderr, "before appending 3 more, dimsize = %d\n", dimsize[0]); /* inquire about the variable */ var_id = ncvarid(ncid, VAR_NAME); /* This is supposed to verify that reading pass the end would fail, but NCsimplerecio/NCadvice/exit just terminates the tests. However, the test is left here to show that the failure had been verified - BMR edges[0] = dimsize[0] + 10; HDmemset(outdata, 0, dimsize[0]); status = ncvarget(ncid, var_id, start, edges, outdata); VERIFYFAIL(status, "Should fail here because of attempting to read pass the end\n"); */ /* read and verify dimension size and variable's data */ /* use this to verify data later for (n=0; n <12 ; n++) { if (time[n] != time_val[n]) { num_errs++; printf(" Wrong value of variable time at index %d\n", n); } } */ { /* write 2 values to the variable, but not immediately after the written record, but 3 records passed it */ short data[] = { 30,31}; start[0] = dimsize[0] + 3; edges[0] = 2; status = ncvarput(ncid, var_id, start, edges, (void *)data); } /* end append data */ /* read and verify dimension size and variable's data after appending */ status = ncdiminq(ncid, dim_id, 0, dimsize); /* read dimsize */ fprintf(stderr, "dimension size after appending again = %d, should be 13\n", dimsize[0]); start[0] = 0; /* start reading at first element */ edges[0] = dimsize[0]; /* entire dimension */ HDmemset(outdata, 0, dimsize[0]); status = ncvarget(ncid, var_id, start, edges, outdata); /* read data */ /* Verify the final data of the variable */ for (ii = 0; ii < dimsize[0]; ii++) if (outdata[ii] != final_data[ii]) { num_errs++; fprintf(stderr, "Wrong value at index %d, should be %d, but read %d\n", ii, outdata[ii], final_data[ii]); } /* Close the file */ status = ncclose(ncid); if (num_errs > 0) (void) fprintf(stderr,"FAILED! ***\n"); else (void) fprintf(stderr,"ok ***\n"); } /*************************************************************************** Test Case nc-2: Name: test_2vars_1Dunlim Summary: use NC_FILL 2 variables sharing 1 unlimited dimension (1D first, may change to 2D) create/write/closefile/append immediate to first/append with gap to second/closefile/append with gap to first Details: - set NC_FILL - create an unlim dimension - create two variables that use the unlim dimension - create two attributes with unique values for each variable - write 4 elements to both variables - read info and verify number of recs in the variable - close the file and re-open the file - write 4 more elements immediately after the last written record to the first variable - read and verify number of recs in both variables - read and verify data - write 3 more elements to the second variable, skipping 2 records - close file and re-open the file - read and verify number of recs in the variable - write 2 more elements to the first variable, skipping 1 records - read and verify number of recs in the variable - read and verify data - close file BMR - 2008/12/12 ****************************************************************************/ #define VAR1_NAME "Variable 1" #define VAR2_NAME "Variable 2" #define VAR3_NAME "Variable 3" #define UDIM_NAME "Unlimited Dimension" #define DIM1_NAME "Dimension 1" static intn test_2vars_1Dunlim() { static char pname[] = "test_2vars_1Dunlim"; int ncid, var1_id, var2_id, dim_id, dim1, udim_id; int var3_id; int dims[2]; char varname[20]; long start[] = {0}; long edges[] = {0}; long dimsize[] = {0}; nc_type type; int ndims; int natts; int32 outdata[100]; int32 final_data[] = {10,11,12,13,20,21,22,23,-32767,-32767,-32767,30,31}; int32 var1_fillval=99; int32 var2_fillval=11; int ii; int status; int num_errs = 0; fprintf(stderr, "*** Testing %s ...\t", &pname[5]); ncid = nccreate(FILE1_NAME, NC_CLOBBER); /* CHECK(ncid, FAIL, "In test_1var_1Dunlim: nccreate '%s'", path); */ status = ncsetfill(ncid, NC_FILL); /* define dimensions */ udim_id = ncdimdef(ncid, UDIM_NAME, NC_UNLIMITED); dim1 = ncdimdef(ncid, "dimension 1", 2L); /* define variables */ dims[0] = udim_id; dims[1] = dim1; var1_id = ncvardef (ncid, VAR1_NAME, NC_LONG, 2, dims); var2_id = ncvardef (ncid, VAR2_NAME, NC_LONG, 1, dims); /* var3_id = ncvardef (ncid, VAR3_NAME, NC_LONG, 1, dims); */ status = ncattput(ncid, var1_id, "_FillValue", NC_LONG, 1, &var1_fillval); status = ncattput(ncid, var2_id, "_FillValue", NC_LONG, 1, &var2_fillval); /* status = ncattput(ncid, var3_id, "_FillValue", NC_LONG, 1, &var2_fillval); */ /* leave define mode */ status = ncendef (ncid); { /* write variables first time */ long start2[] = {0,0}; long edges2[] = {4,2}; long data[] = { 100,110,120,130,200,210,220,230}; fprintf(stderr, "\n---write 4x2 items to %s\n", VAR1_NAME); status = ncvarput(ncid, var1_id, start2, edges2, (void *)data); fprintf(stderr, "done ---write 4 items to %s\n\n", VAR1_NAME); } { /* write variables first time */ start[0] = 0; edges[0] = 4; long data[] = { 100,110,120,130}; fprintf(stderr, "\n---write 4 items to %s\n", VAR2_NAME); status = ncvarput(ncid, var2_id, start, edges, (void *)data); fprintf(stderr, "done ---write 4 items to %s\n\n", VAR2_NAME); /* fprintf(stderr, "\n---write 4 items to %s\n", VAR3_NAME); status = ncvarput(ncid, var3_id, start, edges, (void *)data); fprintf(stderr, "done ---write 4 items to %s\n\n", VAR3_NAME); */ } /* inquire about the variable */ status = ncvarinq (ncid, var1_id, varname, &type, &ndims, dims, &natts); /* inquire dimension size */ status = ncdiminq(ncid, dims[0], 0, dimsize); fprintf(stderr, "variable <%s> has %d dimensions: %d\n", varname, ndims, dimsize[0]); status = ncvarinq (ncid, var2_id, varname, &type, &ndims, dims, &natts); /* inquire dimension size */ status = ncdiminq(ncid, dims[0], 0, dimsize); fprintf(stderr, "variable <%s> has %d dimensions: %d\n", varname, ndims, dimsize[0]); status = ncvarinq (ncid, var2_id, varname, &type, &ndims, dims, &natts); /* inquire dimension size */ status = ncdiminq(ncid, dims[0], 0, dimsize); fprintf(stderr, "variable <%s> has %d dimensions: %d\n", varname, ndims, dimsize[0]); #if 0 start[0] = 0; /* start reading at first element */ edges[0] = 4; HDmemset(outdata, 0, dimsize[0]); status = ncvarget(ncid, var3_id, start, edges, outdata); /* read data */ /* Verify the current data of the variable */ for (ii = 0; ii < dimsize[0]; ii++) fprintf(stderr, " %d ", outdata[ii]); fprintf(stderr, "\n"); /* if (outdata[ii] != final_data[ii]) { num_errs++; fprintf(stderr, "Wrong value at index %d, should be %d, but read %d\n", ii, outdata[ii], final_data[ii]); } */ #endif /* close file */ status = ncclose (ncid); fprintf(stderr, "Close file...\n"); #if 0 /* open file for read/write to append data */ ncid = ncopen(FILE1_NAME, NC_RDWR); fprintf(stderr, "\nOpen file %s first time\n", FILE1_NAME); /* inquire dimension size */ dimsize[0] = 0; udim_id = ncdimid(ncid, UDIM_NAME); status = ncdiminq(ncid, udim_id, 0, dimsize); /* Access the variables */ var1_id = ncvarid(ncid, VAR1_NAME); var2_id = ncvarid(ncid, VAR2_NAME); { /* Write 4 values to first var, immediately after the written records */ long data[] = { 20,21,22}; start[0] = dimsize[0]; edges[0] = 3; status = ncvarput(ncid, var1_id, start, edges, (void *)data); } /* end append data */ /* Read and verify info and variable's data */ status = ncdiminq(ncid, udim_id, 0, dimsize); edges[0] = dimsize[0]; fprintf(stderr, "after appending first variable, dimsize[0] = %d\n", dimsize[0]); HDmemset(outdata, 0, dimsize[0]); status = ncvarget(ncid, var_id, start, edges, outdata); for (ii = 0; ii < dimsize[0]; ii++) fprintf(stderr, " %d ", outdata[ii]); /* Read and verify dimension size and variable's data after appending */ status = ncdiminq(ncid, dim_id, 0, dimsize); /* read dimsize */ fprintf(stderr, "dimension size after appending = %d, should be 8\n", dimsize[0]); start[0] = 0; /* start reading at first element */ edges[0] = dimsize[0]; /* entire dimension */ HDmemset(outdata, 0, dimsize[0]); status = ncvarget(ncid, var_id, start, edges, outdata); /* read data */ /* Verify the current data of the variable */ for (ii = 0; ii < dimsize[0]; ii++) if (outdata[ii] != final_data[ii]) { num_errs++; fprintf(stderr, "Wrong value at index %d, should be %d, but read %d\n", ii, outdata[ii], final_data[ii]); } /* Close the file */ status = ncclose (ncid); /* Open file for read/write to append data */ ncid = ncopen(FILE1_NAME, NC_RDWR); fprintf(stderr, "\nOpen file %s second time\n", FILE1_NAME); /* inquire dimension size */ dimsize[0] = 0; dim_id = ncdimid(ncid, DIM_NAME); status = ncdiminq(ncid, dim_id, 0, dimsize); fprintf(stderr, "before appending 3 more, dimsize = %d\n", dimsize[0]); /* inquire about the variable */ var_id = ncvarid(ncid, VAR_NAME); /* This is supposed to verify that reading pass the end would fail, but NCsimplerecio/NCadvice/exit just terminates the tests. However, the test is left here to show that the failure had been verified - BMR edges[0] = dimsize[0] + 10; HDmemset(outdata, 0, dimsize[0]); status = ncvarget(ncid, var_id, start, edges, outdata); VERIFYFAIL(status, "Should fail here because of attempting to read pass the end\n"); */ /* read and verify dimension size and variable's data */ /* use this to verify data later for (n=0; n <12 ; n++) { if (time[n] != time_val[n]) { num_errs++; printf(" Wrong value of variable time at index %d\n", n); } } */ { /* write 2 values to the variable, but not immediately after the written record, but 3 records passed it */ short data[] = { 30,31}; start[0] = dimsize[0] + 3; edges[0] = 2; status = ncvarput(ncid, var_id, start, edges, (void *)data); } /* end append data */ /* read and verify dimension size and variable's data after appending */ status = ncdiminq(ncid, dim_id, 0, dimsize); /* read dimsize */ fprintf(stderr, "dimension size after appending again = %d, should be 13\n", dimsize[0]); start[0] = 0; /* start reading at first element */ edges[0] = dimsize[0]; /* entire dimension */ HDmemset(outdata, 0, dimsize[0]); status = ncvarget(ncid, var_id, start, edges, outdata); /* read data */ /* Verify the final data of the variable */ for (ii = 0; ii < dimsize[0]; ii++) if (outdata[ii] != final_data[ii]) { num_errs++; fprintf(stderr, "Wrong value at index %d, should be %d, but read %d\n", ii, outdata[ii], final_data[ii]); } /* Close the file */ status = ncclose(ncid); #endif if (num_errs > 0) (void) fprintf(stderr,"FAILED! ***\n"); else (void) fprintf(stderr,"ok ***\n"); } int main () { int num_errs = 0; /* num_errs = num_errs + test_1var_1Dunlim(); */ num_errs = num_errs + test_2vars_1Dunlim(); return num_errs; } /* * Test ncvarget for variables with unlimited dimensions (bug #897) */ void test_ncvarget_unlim(path) char *path; /* name of writable netcdf file to open */ { int nerrs = 0; static char pname[] = "test_ncvarget_unlim"; int status; int ncid; int var_id; float a[2][3]; int date[12]; int time[12]; short val[12][3][2]; long start[3], count[3]; int i, j, n; (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]); if ((ncid = ncopen(path, NC_NOWRITE)) == -1) { error("%s: ncopen failed", pname); return; } /* Reading 3D array with unlimited dimension */ var_id = ncvarid( ncid, "b"); start[0] = 0; start[1] = 0; start[2] = 0; count[0] = 12; count[1] = 3; count[2] = 2; if(status = ncvarget (ncid, var_id, start, count, val) == -1) { error("%s: ncvarget failed for variable b in ", pname); ncclose(ncid); return; } for (n=0; n <12 ; n++) { for (i=0; i <3; i++) { for (j=0; j<2 ; j++) { if (val[n][i][j] != b_val[n][i][j]) { nerrs++; printf(" Wrong value of variable b at index %d,%d,%d\n", n,i,j); } } } } /* Reading 2D array */ var_id = ncvarid( ncid, "a"); start[0] = 0; start[1] = 0; count[0] = 2; count[1] = 3; if(status = ncvarget (ncid, var_id, start, count, a) == -1) { error("%s: ncvarget failed for variable a in ", pname); ncclose(ncid); return; } for (i=0; i <2; i++) { for (j=0; j<3 ; j++) { if (a[i][j] != a_val[i][j]) { nerrs++; printf(" Wrong value of variable a at index %d,%d\n", i,j); } } } /* Reading 1D array with unlimited dimension */ var_id = ncvarid( ncid, "date"); start[0] = 0; count[0] = 12; if(status = ncvarget (ncid, var_id, start, count, date) == -1) { error("%s: ncvarget failed for variable date in ", pname); ncclose(ncid); return; } for (n=0; n <12 ; n++) { if (date[n] != date_val[n]) { nerrs++; printf(" Wrong value of variable date at index %d\n", n); } } /* Reading 1D array with unlimited dimension */ var_id = ncvarid( ncid, "time"); start[0] = 0; count[0] = 12; if(status = ncvarget (ncid, var_id, start, count, time) == -1) { error("%s: ncvarget failed varaible time in ", pname); ncclose(ncid); return; } for (n=0; n <12 ; n++) { if (time[n] != time_val[n]) { nerrs++; printf(" Wrong value of variable time at index %d\n", n); } } status = ncclose(ncid); if (nerrs > 0) (void) fprintf(stderr,"FAILED! ***\n"); else (void) fprintf(stderr,"ok ***\n"); } /****************** Test cases in this file ********************* Case nc-1: create/write - create an unlim dimension - create a variable that uses the unlim dimension - write 10 elements to it - read info and print out number of recs in the variable and in the file - close the file - open the file - read info and print out number of recs in the variable and in the file - read and print out data - close file Case nc-2: create/write/close/append - create an unlim dimension - write 10 elements to it - read info and print out number of recs in the variable and in the file - close the file - open the file for writing - append 8 elements to it - read info and print out number of recs in the variable and in the file - close the file - open the file for reading - read info and print out number of recs in the variable and in the file - read and print out data - close file Case nc-3: create/write/close/append 2 variables - create 2 1-dim unlim variables - write 4 elements to first variable and 6 to second - read info and print out number of recs in each variable and in the file - close the file and reopen for writing - read info and print out number of recs in each variable and in the file - append 8 elements to first variable and 5 to second - read info and print out number of recs in each variable and in the file - read and print out data - close file - reopen file for reading - read info and print out number of recs in each variable and in the file - read and print out data - close file Case nc-4: create/write/append 2 variables (same as nc-3 but no closing file) - create 2 1-dim unlim variables - write 4 elements to first variable and 6 to second - read info and print out number of recs in each variable and in the file - append 8 elements to first variable and 5 to second - read info and print out number of recs in each variable and in the file - read and print out data - close file - reopen file for reading - read info and print out number of recs in each variable and in the file - read and print out data - close file Case nc-5: create/write/closefile/append 3 variables with NC_NOFILL - set NC_FILL for file - create 3 1-dim unlim variables - set fill values for each variable (attribute) - write 4, 6, 8 elements to the variables, respectively - read info and print out number of recs in each variable and in the file - close the file and reopen for writing - read info and print out number of recs in each variable and in the file (the following tests the changes made to NCcoordck regarding unfilled >= 0) - write at index 4 of variable 1 - read info and print out number of recs in each variable and in the file - write at index 7 of variable 2 - read info and print out number of recs in each variable and in the file - write at index 10 of variable 3 Case nc-6: create/write/closefile/append 2 variables with NC_NOFILL - set NC_NOFILE for file - */