1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
|
/* This is part of the netCDF package. Copyright 2005-2018 University
Corporation for Atmospheric Research/Unidata. See COPYRIGHT file
for conditions of use.
Test handling of formats.
Ed Hartnett, 11/22/17
*/
#include "config.h"
#include <nc_tests.h>
#include "err_macros.h"
#define FILE_NAME_BASE "tst_formats"
#define HDF4_FILE "ref_contiguous.hdf4"
#define NDIM1 1
#define DIM_LEN 10
#define VAR_NAME "Copernicus_var"
#define DIM_NAME "Copernicus_dim"
#define NUM_FILL_WRITE_TESTS 2
#define NUM_FILL_WRITE_METHOD_TESTS 2
/* Determine how many formats are available, and what they are. */
void
determine_test_formats(int *num_formats, int *format)
{
int ind = 0;
int num;
/* Check inputs. */
assert(num_formats && format);
/* We always have classic and 64-bit offset */
num = 2;
format[ind++] = NC_FORMAT_CLASSIC;
format[ind++] = NC_FORMAT_64BIT_OFFSET;
/* Do we have netCDF-4 and netCDF-4 classic? */
#ifdef USE_HDF5
num += 2;
format[ind++] = NC_FORMAT_NETCDF4;
format[ind++] = NC_FORMAT_NETCDF4_CLASSIC;
#endif /* USE_HDF5 */
/* Do we have CDF5? */
#ifdef ENABLE_CDF5
num++;
format[ind++] = NC_FORMAT_CDF5;
#endif /* ENABLE_CDF5 */
*num_formats = num;
}
/* Function to test nc_inq_format(). */
int
check_inq_format(int ncid, int expected_format, int expected_extended_format, int expected_mode)
{
int format;
int extended_format;
int mode;
if (nc_inq_format(ncid + 66000, NULL) != NC_EBADID) ERR;
if (nc_inq_format(ncid, NULL)) ERR;
if (nc_inq_format(ncid, &format)) ERR;
if (format != expected_format) {
printf("format %d expected_format %d\n", format, expected_format);
ERR;
}
if (nc_inq_format_extended(ncid + 66000, &extended_format, &mode) != NC_EBADID) ERR;
{
int mode;
if (nc_inq_format_extended(ncid, NULL, &mode)) ERR;
if (mode != expected_mode) {
printf("expected_mode %x mode %x\n", expected_mode, mode);
/*ERR;*/
}
}
{
int extended_format;
if (nc_inq_format_extended(ncid, &extended_format, NULL)) ERR;
if (extended_format != expected_extended_format) ERR;
}
if (nc_inq_format_extended(ncid, &extended_format, &mode)) ERR;
if (mode != expected_mode) ERR;
if (extended_format != expected_extended_format) ERR;
/* Nothing to do with inq_format, but let's check the base_pe
* functions. */
if (nc_set_base_pe(ncid, 0)) ERR;
if (nc_inq_base_pe(ncid, NULL)) ERR;
return 0;
}
int
main(int argc, char **argv)
{
printf("\n*** Testing netcdf format functions.\n");
{
int ncid;
int f, d, a;
int format[MAX_NUM_FORMATS];
int num_formats;
int ret;
/* How many formats to be tested? */
determine_test_formats(&num_formats, format);
for (f = 0; f < num_formats; f++)
{
printf("*** testing nc_inq_format() and nc_inq_format_extended() with format %d...", format[f]);
{
char file_name[NC_MAX_NAME + 1];
int expected_mode;
int expected_extended_format;
sprintf(file_name, "%s_%d.nc", FILE_NAME_BASE, format[f]);
/* Set up test. */
switch (format[f]) {
case NC_FORMAT_CLASSIC:
expected_extended_format = NC_FORMATX_NC3;
expected_mode = 0;
break;
case NC_FORMAT_64BIT_OFFSET:
expected_extended_format = NC_FORMATX_NC3;
expected_mode = NC_64BIT_OFFSET;
break;
case NC_FORMAT_CDF5:
expected_extended_format = NC_FORMATX_NC3;
expected_mode = NC_CDF5;
break;
case NC_FORMAT_NETCDF4:
expected_extended_format = NC_FORMATX_NC4;
expected_mode = NC_NETCDF4;
break;
case NC_FORMAT_NETCDF4_CLASSIC:
expected_extended_format = NC_FORMATX_NC4;
expected_mode = NC_NETCDF4|NC_CLASSIC_MODEL;
break;
}
if (nc_set_default_format(format[f], NULL)) ERR;
/* Create a file. */
if (nc_create(file_name, 0, &ncid)) ERR;
if (check_inq_format(ncid, format[f], expected_extended_format, expected_mode)) ERR;
if (nc_close(ncid)) ERR;
/* Re-open the file and check it again. */
if (nc_open(file_name, 0, &ncid)) ERR;
/* Classic flag is not set on mode in nc_open(). Not sure if
* this is a bug or not. */
if (format[f] == NC_FORMAT_NETCDF4_CLASSIC)
expected_mode = NC_NETCDF4;
if (check_inq_format(ncid, format[f], expected_extended_format, expected_mode)) ERR;
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
/* Test without and with actual data write. */
for (d = 0; d < NUM_FILL_WRITE_TESTS; d++)
{
/* Test setting _FillValue directly or calling nc_def_var_fill(). */
for (a = 0; a < NUM_FILL_WRITE_METHOD_TESTS; a++)
{
printf("*** testing late fill handling with format %d writing %d "
"using def_var_fill %d...", format[f], d, a);
char file_name[NC_MAX_NAME + 1];
int dimid, varid;
size_t index = {DIM_LEN - 1};
int data = TEST_VAL_42;
int data_in;
int fill_value = TEST_VAL_42 * 2;
/* Try to set fill mode after data have been written. */
sprintf(file_name, "%s_%d_%d_%d_elatefill.nc", FILE_NAME_BASE, format[f], d, a);
if (nc_set_default_format(format[f], NULL)) ERR;
if (nc_create(file_name, 0, &ncid)) ERR;
if (nc_def_dim(ncid, DIM_NAME, DIM_LEN, &dimid)) ERR;
if (nc_def_var(ncid, VAR_NAME, NC_INT, NDIM1, &dimid, &varid)) ERR;
if (nc_enddef(ncid)) ERR;
/* For netCDF-4, we don't actually have to write data to
* prevent future setting of the fill value. Once the user
* leaves calls enddef after defining a var, fill values
* can no longer be set. */
if (d)
if (nc_put_var1_int(ncid, varid, &index, &data)) ERR;
if (nc_redef(ncid)) ERR;
if (a)
{
ret = nc_def_var_fill(ncid, varid, NC_FILL, &fill_value);
}
else
{
ret = nc_put_att_int(ncid, varid, "_FillValue", NC_INT, 1,
&fill_value);
}
/* Setting the fill value after data are written is
* allowed in classic formats, but not netcdf-4. */
if (format[f] == NC_FORMAT_CLASSIC || format[f] == NC_FORMAT_64BIT_OFFSET ||
format[f] == NC_FORMAT_CDF5)
{
if (ret) ERR;
}
else
{
if (ret != (a ? NC_ELATEDEF: NC_ELATEFILL)) ERR;
}
if (nc_enddef(ncid)) ERR;
if (nc_close(ncid)) ERR;
/* Open the file and check data. */
if (nc_open(file_name, NC_NOWRITE, &ncid)) ERR;
if (nc_get_var1_int(ncid, varid, &index, &data_in)) ERR;
if (data_in != (d ? data : NC_FILL_INT)) ERR;
if (nc_close(ncid)) ERR;
SUMMARIZE_ERR;
} /* next fill value method test */
} /* next fill val write test */
#define NDIM2 2
#define DIM1_NAME "dim1"
#define DIM2_NAME "dim2"
#define NTYPE 6
#define DATA_LEN 4
printf("*** testing handling of null strides with format %d... ",
format[f]);
{
char file_name[NC_MAX_NAME + 1];
char var_name[NC_MAX_NAME + 1];
int dimid[NDIM2];
int xtype[NTYPE] = {NC_BYTE, NC_CHAR, NC_SHORT, NC_INT, NC_FLOAT, NC_DOUBLE};
int type_size[NTYPE] = {1, 1, 2, 4, 4, 8};
int varid[NTYPE];
size_t start[NDIM2] = {0, 0};
size_t count[NDIM2] = {2, 2};
signed char data_byte[DATA_LEN] = {1, 2, 3, 4};
unsigned char data_char[DATA_LEN] = {1, 2, 3, 4};
short data_short[DATA_LEN] = {1, 2, 3, 4};
int data_int[DATA_LEN] = {1, 2, 3, 4};
float data_float[DATA_LEN] = {1, 2, 3, 4};
double data_double[DATA_LEN] = {1, 2, 3, 4};
void *data_ptr[NTYPE] = {data_byte, data_char, data_short, data_int, data_float, data_double};
int t;
/* Create the test file. */
sprintf(file_name, "%s_%d_null_strides.nc", FILE_NAME_BASE, format[f]);
if (nc_set_default_format(format[f], NULL)) ERR;
if (nc_create(file_name, 0, &ncid)) ERR;
if (nc_def_dim(ncid, DIM1_NAME, DIM_LEN, &dimid[0])) ERR;
if (nc_def_dim(ncid, DIM2_NAME, DIM_LEN, &dimid[1])) ERR;
for (t = 0; t < NTYPE; t++)
{
sprintf(var_name, "var_%d", xtype[t]);
if (nc_def_var(ncid, var_name, xtype[t], NDIM2, dimid, &varid[t])) ERR;
}
if (nc_enddef(ncid)) ERR;
/* Write some data. */
for (t = 0; t < NTYPE; t++)
{
if (nc_put_vars(ncid, varid[t], start, count, NULL, data_ptr[t])) ERR;
}
if (nc_close(ncid)) ERR;
/* Open the file and check data. */
{
int ndims, nvars, ngatts, unlimdimid;
if (nc_open(file_name, NC_NOWRITE, &ncid)) ERR;
if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
if (ndims != 2 || nvars != NTYPE || ngatts != 0 || unlimdimid != -1) ERR;
for (t = 0; t < NTYPE; t++)
{
nc_type my_type;
int var_ndims, natts;
int var_dimid[NDIM2];
void *data_in;
if (nc_inq_var(ncid, varid[t], NULL, &my_type, &var_ndims, var_dimid, &natts)) ERR;
if (my_type != xtype[t] || var_ndims != 2 || var_dimid[0] != dimid[0] ||
var_dimid[1] != dimid[1] || natts != 0) ERR;
if (!(data_in = malloc(DATA_LEN * type_size[t]))) ERR;
if (nc_get_vars(ncid, varid[t], start, count, NULL, data_in)) ERR;
if (memcmp(data_in, data_ptr[t], DATA_LEN * type_size[t])) ERR;
free(data_in);
}
if (nc_close(ncid)) ERR;
}
}
SUMMARIZE_ERR;
printf("*** testing bad name for nc_open/nc_create with format %d... ", format[f]);
{
int ncid;
if (nc_set_default_format(format[f], NULL)) ERR;
if (nc_create(NULL, 0, &ncid) != NC_EINVAL) ERR;
if (nc_open(NULL, NC_NOWRITE, &ncid) != NC_EINVAL) ERR;
if (nc_delete(NULL) != NC_EINVAL) ERR;
}
SUMMARIZE_ERR;
} /* next format */
}
FINAL_RESULTS;
}
|