/utilities/netcdf/src/nctest/atttests.c
C | 1371 lines | 1137 code | 45 blank | 189 comment | 410 complexity | 1c244674ee86f434abfcea657e8f91b7 MD5 | raw file
1/********************************************************************* 2 * Copyright 1993, UCAR/Unidata 3 * See netcdf/COPYRIGHT file for copying and redistribution conditions. 4 * $Header$ 5 *********************************************************************/ 6 7#ifdef _MPW 8#define __SEG__ toobig /* under MPW on MacOS, makes it fit */ 9#endif 10 11#include <stdio.h> 12#include <string.h> 13#include <stdlib.h> /* for free() */ 14#include "netcdf.h" 15#include "testcdf.h" /* defines in-memory test cdf structure */ 16#include "add.h" /* functions to update in-memory netcdf */ 17#include "error.h" 18#include "emalloc.h" 19#include "tests.h" 20#include "val.h" 21 22#define LEN_OF(array) ((sizeof array) / (sizeof array[0])) 23 24 25/* 26 * Test ncattput 27 * check that new attribute put works in define mode 28 * check that NC_GLOBAL variable id works 29 * check that changing type of existing attribute works in define mode 30 * check that increasing length of attribute works in define mode 31 * check that changing value of existing attribute works in define mode 32 * try with bad datatype, should fail 33 * try with negative length, should fail 34 * try increasing length of attribute in data mode, should fail 35 * try putting new attribute in data mode, should fail 36 * check that changing type of existing attribute works in data mode 37 * check that decreasing length of attribute works in data mode 38 * check that changing value of existing attribute works in data mode 39 * try with bad variable handle, should fail 40 * try with bad netCDF handle, check error 41 */ 42void 43test_ncattput(path) 44 const char *path; /* name of writable netcdf file to open */ 45{ 46 int nerrs = 0; 47 static char pname[] = "test_ncattput"; 48 int cdfid; /* netcdf id */ 49 int ndims; /* number of dimensions */ 50 int nvars; /* number of variables */ 51 int ngatts_prev, ngatts; /* number of global attributes */ 52 int xdimid; /* id of unlimited dimension */ 53 int ia, id; 54 static char byte_vals[] = {'a', 'b'}; 55 static char char_vals[] = "chars"; 56 static short short_vals[] = {-999, 0, 999}; 57 static nclong long_vals[] = {10, 20}; 58 static float float_vals[] = {1.5, 2.5, 3.5 }; 59 static double double_vals[] = {4.5, 5.5, 6.5, 7.5}; 60 /* 61 * test attributes; it is important for this test that the size 62 * required for the attribute values increases monotonically. 63 */ 64 static struct cdfatt atts[] = { 65 {___, "att0", NC_BYTE, LEN_OF(byte_vals), (void *) byte_vals}, 66 {___, "att1", NC_CHAR, LEN_OF(char_vals), (void *) char_vals}, 67 {___, "att2", NC_SHORT, LEN_OF(short_vals), (void *) short_vals}, 68 {___, "att3", NC_LONG, LEN_OF(long_vals), (void *) long_vals}, 69 {___, "att4", NC_FLOAT, LEN_OF(float_vals), (void *) float_vals}, 70 {___, "att5", NC_DOUBLE, LEN_OF(double_vals), (void *) double_vals} 71 }; 72 int na = LEN_OF(atts); /* number of test attributes */ 73 int ww_id; /* variable id */ 74 static struct cdfvar ww = /* new variable */ 75 {"ww", NC_LONG, 1, ___, 0}; 76 static struct cdfatt tmp; /* attribute */ 77 78 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]); 79 80 if ((cdfid = ncopen(path, NC_WRITE)) == -1) { 81 error("%s: ncopen failed", pname); 82 return; 83 } 84 /* enter define mode */ 85 if (ncredef(cdfid) == -1) { 86 error("%s: cdredef failed", pname); 87 ncclose(cdfid); return; 88 } 89 /* get count of global attributes */ 90 if (ncinquire(cdfid, &ndims, &nvars, &ngatts, &xdimid) == -1) { 91 error("%s: ncinquire failed", pname); 92 ncclose(cdfid); return; 93 } 94 ngatts_prev = ngatts; 95 /* in define mode, add global attributes of every type */ 96 for (ia = 0; ia < na; ia++) { 97 if (ncattput(cdfid, NC_GLOBAL, atts[ia].name, atts[ia].type, 98 atts[ia].len, atts[ia].val) == -1) { 99 error("%s: ncattput of NC_GLOBAL attribute failed", pname); 100 ncclose(cdfid); return; 101 } 102 add_att(&test, NC_GLOBAL, &atts[ia]); /* keep in-memory netcdf updated */ 103 } 104 /* make sure count of global attributes has been updated */ 105 if (ncinquire(cdfid, &ndims, &nvars, &ngatts, &xdimid) == -1) { 106 error("%s: ncinquire failed", pname); 107 ncclose(cdfid); return; 108 } 109 if (ngatts != ngatts_prev + na) { 110 error("%s: number of global = %d, expected %d", 111 pname, ngatts, ngatts_prev + na); 112 nerrs++; 113 } 114 /* check with ncattinq and ncattget that NC_GLOBAL attributes put OK */ 115 for (ia = 0; ia < na; ia++) { 116 if (ncattinq(cdfid, NC_GLOBAL, atts[ia].name, 117 &tmp.type, &tmp.len) == -1) { 118 error("%s: ncattinq of global attribute failed", pname); 119 ncclose(cdfid); return; 120 } 121 if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) { 122 error("%s: NC_GLOBAL ncattinq got unexpected type or len", 123 pname); 124 ncclose(cdfid); return; 125 } 126 /* allocate space to hold the attribute value to be retrieved */ 127 tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type)); 128 if (ncattget(cdfid, NC_GLOBAL, atts[ia].name, tmp.val) == -1) { 129 error("%s: ncattget of variable attribute failed", pname); 130 ncclose(cdfid); return; 131 } 132 if (val_cmp(tmp.type, tmp.len, tmp.val, atts[ia].val) != 0) { 133 error("%s: ncattget got bad values after put of NC_GLOBAL attrs", 134 pname); 135 nerrs++; 136 } 137 free (tmp.val); 138 } 139 /* add a variable, then variable attributes of every type */ 140 ww.dims = (int *) emalloc(sizeof(int) * ww.ndims); 141 for (id = 0; id < ww.ndims; id++) 142 ww.dims[id] = id; 143 if ((ww_id = ncvardef(cdfid, 144 ww.name, ww.type, ww.ndims, ww.dims)) == -1) { 145 error("%s: ncvardef failed", pname); 146 ncclose(cdfid); return; 147 } 148 add_var(&test, &ww); /* keep in-memory netcdf in sync */ 149 for (ia = 0; ia < na; ia++) { 150 if (ncattput(cdfid, ww_id, 151 atts[ia].name, atts[ia].type, atts[ia].len, atts[ia].val) 152 == -1) { 153 error("%s: ncattput of variable attribute failed", pname); 154 ncclose(cdfid); return; 155 } 156 add_att(&test, ww_id, &atts[ia]); /* keep in-memory netcdf updated */ 157 } 158 /* check with ncattinq and ncattget that variable attributes put OK */ 159 for (ia = 0; ia < na; ia++) { 160 if (ncattinq(cdfid, ww_id, atts[ia].name, 161 &tmp.type, &tmp.len) == -1) { 162 error("%s: ncattinq of variable attribute failed", pname); 163 ncclose(cdfid); return; 164 } 165 if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) { 166 error("%s: ncattinq for new attribute got bad type or len", 167 pname); 168 ncclose(cdfid); return; 169 } 170 /* allocate space to hold the attribute value to be retrieved */ 171 tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type)); 172 if (ncattget(cdfid, ww_id, atts[ia].name, tmp.val) == -1) { 173 error("%s: ncattget of variable attribute failed", pname); 174 ncclose(cdfid); return; 175 } 176 if (val_cmp(tmp.type, tmp.len, tmp.val, atts[ia].val) != 0) { 177 error("%s: ncattget got bad values after put of variable attrs", 178 pname); 179 nerrs++; 180 } 181 free (tmp.val); 182 } 183 /* 184 * check that changing type of existing attribute, increasing 185 * length of attribute, and changing value of existing attribute 186 * work OK in define mode. 187 */ 188 tmp.name = (char *) emalloc(MAX_NC_NAME); 189 for (ia = 1; ia < na; ia++) { 190 if (ncattput(cdfid, ww_id, atts[ia-1].name, atts[ia].type, 191 atts[ia].len, atts[ia].val) == -1) { 192 error("%s: ncattput of larger attribute failed", pname); 193 ncclose(cdfid); return; 194 } 195 tmp.var = atts[ia].var; 196 (void) strcpy (tmp.name, atts[ia-1].name); 197 tmp.type = atts[ia].type; 198 tmp.len = atts[ia].len; 199 tmp.val = atts[ia].val; 200 add_att(&test, ww_id, &tmp); /* keep in-memory netcdf updated */ 201 } 202 /* check with ncattinq and ncattget that variable attributes put OK */ 203 for (ia = 1; ia < na; ia++) { 204 if (ncattinq(cdfid, ww_id, atts[ia-1].name, 205 &tmp.type, &tmp.len) == -1) { 206 error("%s: ncattinq of larger attribute failed", pname); 207 ncclose(cdfid); return; 208 } 209 if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) { 210 error("%s: ncattinq for larger attribute got bad type or len", 211 pname); 212 ncclose(cdfid); return; 213 } 214 /* allocate space to hold the attribute value to be retrieved */ 215 tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type)); 216 if (ncattget(cdfid, ww_id, atts[ia-1].name, tmp.val) == -1) { 217 error("%s: ncattget of variable attribute failed", pname); 218 ncclose(cdfid); return; 219 } 220 if (val_cmp(tmp.type, tmp.len, tmp.val, atts[ia].val) != 0) { 221 error("%s: ncattget got bad values after put of larger attrs", 222 pname); 223 nerrs++; 224 } 225 free (tmp.val); 226 } 227 /* try with bad datatype, should fail */ 228 if (ncattput(cdfid, ww_id, "bogus_att1", BAD_TYPE, 229 atts[0].len, atts[0].val) != -1) { 230 error("%s: ncattput should fail with bad type", pname); 231 nerrs++; 232 } 233 /* try with negative length, should fail */ 234 if (ncattput(cdfid, ww_id, "bogus_att2", atts[0].type, 235 -1, atts[0].val) != -1) { 236 error("%s: ncattput should fail with bad length", pname); 237 nerrs++; 238 } 239 if (ncendef (cdfid) == -1) { 240 error("%s: ncendef failed", pname); 241 ncclose(cdfid); return; 242 } 243 /* in data mode try increasing length of attribute, should fail */ 244 if (ncattput(cdfid, ww_id, atts[0].name, atts[0].type, 245 atts[0].len + 10, atts[0].val) != -1) { 246 error("%s: ncattput should fail with increased length in data mode", 247 pname); 248 nerrs++; 249 /* reset to correct length for later tests */ 250 if (ncattput(cdfid, ww_id, atts[0].name, atts[0].type, 251 atts[0].len, atts[0].val) != -1) { 252 error("%s: ncattput failed to reset length in data mode", pname); 253 nerrs++; 254 } 255 } 256 /* try creating new attribute in data mode, should fail */ 257 if (ncattput(cdfid, ww_id, "new_name", atts[0].type, 258 atts[0].len, atts[0].val) != -1) { 259 error("%s: ncattput of new attribute in data mode should fail", 260 pname); 261 ncclose(cdfid); return; 262 } 263 /* 264 * check that changing type of existing attribute, decreasing 265 * length of attribute, and changing value of existing attribute 266 * work OK in data mode 267 */ 268 for (ia = 0; ia < na - 1; ia++) { 269 if (ncattput(cdfid, ww_id, atts[ia+1].name, atts[ia].type, 270 atts[ia].len, atts[ia].val) == -1) { 271 error("%s: ncattput of smaller attribute failed in data mode", 272 pname); 273 ncclose(cdfid); return; 274 } 275 tmp.var = atts[ia].var; 276 (void) strcpy (tmp.name, atts[ia+1].name); 277 tmp.type = atts[ia].type; 278 tmp.len = atts[ia].len; 279 tmp.val = atts[ia].val; 280 add_att(&test, ww_id, &tmp); /* keep in-memory netcdf updated */ 281 } 282 /* check with ncattinq and ncattget that variable attributes put OK */ 283 for (ia = 0; ia < na - 1; ia++) { 284 if (ncattinq(cdfid, ww_id, atts[ia+1].name, &tmp.type, &tmp.len) 285 == -1) { 286 error("%s: ncattinq of variable attribute failed in data mode", 287 pname); 288 ncclose(cdfid); return; 289 } 290 if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) { 291 error("%s: VARIABLE ncattinq got bad type or len in data mode", 292 pname); 293 ncclose(cdfid); return; 294 } 295 /* allocate space to hold the attribute value to be retrieved */ 296 tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type)); 297 if (ncattget(cdfid, ww_id, atts[ia+1].name, tmp.val) == -1) { 298 error("%s: ncattget of variable attribute failed in data mode", 299 pname); 300 ncclose(cdfid); return; 301 } 302 if (val_cmp(tmp.type, tmp.len, tmp.val, atts[ia].val) != 0) { 303 error("%s: ncattget got bad values in data mode", pname); 304 nerrs++; 305 } 306 free (tmp.val); 307 } 308 /* try with bad variable handle, should fail */ 309 if (ncattput(cdfid, test.nvars, atts[0].name, atts[0].type, atts[0].len, 310 atts[0].val) != -1) { 311 error("%s: ncattput should fail with bad variable handle", pname); 312 ncclose(cdfid); return; 313 } 314 if (ncclose (cdfid) == -1) { 315 error("%s: ncclose failed", pname); 316 return; 317 } 318 /* try with bad netcdf handle, should fail */ 319 if (ncattput(cdfid, ww_id, atts[0].name, atts[0].type, atts[0].len, 320 atts[0].val) != -1) { 321 error("%s: ncattput should fail with bad netcdf handle", pname); 322 ncclose(cdfid); return; 323 } 324 free(tmp.name); 325 if (nerrs > 0) 326 (void) fprintf(stderr,"FAILED! ***\n"); 327 else 328 (void) fprintf(stderr,"ok ***\n"); 329} 330 331 332/* 333 * Test ncattinq 334 * check returned values of properly created attributes 335 * try with nonexisting attribute, check error 336 * try with bad variable handle, check error 337 * try with bad netCDF handle, check error 338 */ 339void 340test_ncattinq(path) 341 const char *path; /* name of writable netcdf file to open */ 342{ 343 int nerrs = 0; 344 static char pname[] = "test_ncattinq"; 345 int cdfid; /* netcdf id */ 346 int ia, id; /* attribute number */ 347 nc_type type; 348 int len; 349 int vv_id; /* variable id */ 350 static struct cdfvar vv = /* new variable */ 351 {"vv", NC_SHORT, 2, ___, 0}; 352 353 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]); 354 355 if ((cdfid = ncopen(path, NC_WRITE)) == -1) { 356 error("%s: ncopen failed", pname); 357 return; 358 } 359 /* in data mode, check all attributes against test netcdf */ 360 for (ia = 0; ia < test.natts; ia++) { 361 if (ncattinq(cdfid, test.atts[ia].var, test.atts[ia].name, 362 &type, &len) == -1) { 363 error("%s: ncattinq failed", pname); 364 ncclose(cdfid); 365 return; 366 } 367 if (type != test.atts[ia].type) { 368 error("%s: ncattinq returned wrong type", pname); 369 ncclose(cdfid); 370 return; 371 } 372 if (len != test.atts[ia].len) { 373 error("%s: ncattinq returned wrong len", pname); 374 ncclose(cdfid); 375 return; 376 } 377 } 378 379 /* enter define mode */ 380 if (ncredef(cdfid) == -1) { 381 error("%s: cdredef failed", pname); 382 ncclose(cdfid); return; 383 } 384 /* in define mode, add a variable */ 385 vv.dims = (int *) emalloc(sizeof(int) * vv.ndims); 386 for (id = 0; id < vv.ndims; id++) 387 vv.dims[id] = id; /* assumes vv.ndims <= test.ndims */ 388 if ((vv_id = ncvardef(cdfid, vv.name, vv.type, vv.ndims, vv.dims)) 389 == -1) { 390 error("%s: ncvardef failed", pname); 391 ncclose(cdfid); return; 392 } 393 add_var(&test, &vv); /* keep in-memory netcdf in sync */ 394 395 /* try with nonexisting attribute, should fail */ 396 if (ncattinq(cdfid, vv_id, "nonesuch", &type, &len) != -1) { 397 error("%s: ncattinq should fail with nonexisting attribute", pname); 398 ncclose(cdfid); return; 399 } 400 /* try with bad variable handle, should fail */ 401 if (ncattinq(cdfid, test.nvars, test.atts[0].name, &type, &len) != -1) { 402 error("%s: ncattinq should fail with bad variable id", pname); 403 ncclose(cdfid); return; 404 } 405 /* in define mode check all attributes against test netcdf */ 406 for (ia = 0; ia < test.natts; ia++) { 407 if (ncattinq(cdfid, test.atts[ia].var, test.atts[ia].name, 408 &type, &len) == -1) { 409 error("%s: ncattinq in define mode failed", pname); 410 ncclose(cdfid); 411 return; 412 } 413 if (type != test.atts[ia].type) { 414 error("%s: ncattinq in define mode returned wrong type", pname); 415 ncclose(cdfid); 416 return; 417 } 418 if (len != test.atts[ia].len) { 419 error("%s: ncattinq in define mode returned wrong len", pname); 420 ncclose(cdfid); 421 return; 422 } 423 } 424 if (ncendef (cdfid) == -1) { 425 error("%s: ncendef failed", pname); 426 ncclose(cdfid); return; 427 } 428 if (ncclose (cdfid) == -1) { 429 error("%s: ncclose failed", pname); 430 return; 431 } 432 if (ncattinq(cdfid, NC_GLOBAL, test.atts[0].name, &type, &len) != -1) { 433 error("%s: ncattinq should fail with bad cdfid", pname); 434 nerrs++; 435 } 436 if (nerrs > 0) 437 (void) fprintf(stderr,"FAILED! ***\n"); 438 else 439 (void) fprintf(stderr,"ok ***\n"); 440} 441 442 443/* 444 * Test ncattget 445 * check that NC_GLOBAL variable id works 446 * check in both modes 447 * check that proper call worked after ncattput 448 * try with bad variable handle, check error 449 * try with nonexisting attribute, check error 450 * try with bad netCDF handle, check error 451 */ 452void 453test_ncattget(path) 454 const char *path; /* name of writable netcdf file to open */ 455{ 456 int nerrs = 0; 457 int cdfid; /* netcdf id */ 458 int ia, id; 459 static struct cdfatt tmp; /* attribute */ 460 int uu_id; /* variable id */ 461 static struct cdfvar uu = /* variable */ 462 {"uu", NC_LONG, 2, ___, 0}; 463 static nclong uumax = 1000; /* attribute value */ 464 static struct cdfatt vmax = /* attribute */ 465 {___, "valid_max", NC_LONG, 1, (void *) &uumax}; 466 467 static char pname[] = "test_ncattget"; 468 469 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]); 470 471 if ((cdfid = ncopen(path, NC_WRITE)) == -1) { 472 error("%s: ncopen failed", pname); 473 return; 474 } 475 /* enter define mode */ 476 if (ncredef(cdfid) == -1) { 477 error("%s: cdredef failed", pname); 478 ncclose(cdfid); return; 479 } 480 /* add a variable */ 481 uu.dims = (int *) emalloc(sizeof(int) * uu.ndims); 482 for (id = 0; id < uu.ndims; id++) 483 uu.dims[id] = id; 484 if ((uu_id = ncvardef(cdfid, 485 uu.name, uu.type, uu.ndims, uu.dims)) == -1) { 486 error("%s: ncvardef failed", pname); 487 ncclose(cdfid); return; 488 } 489 add_var(&test, &uu); /* keep in-memory netcdf in sync */ 490 491 /* add an attribute */ 492 if (ncattput(cdfid, uu_id, 493 vmax.name, vmax.type, vmax.len, vmax.val) 494 == -1) { 495 error("%s: ncattput of variable attribute failed", pname); 496 ncclose(cdfid); return; 497 } 498 add_att(&test, uu_id, &vmax); /* keep in-memory netcdf updated */ 499 500 /* in define mode, check all attributes values against test netcdf */ 501 for (ia = 0; ia < test.natts; ia++) { 502 if (ncattinq(cdfid, test.atts[ia].var, test.atts[ia].name, 503 &tmp.type, &tmp.len) == -1) { 504 error("%s: ncattinq in define mode failed", pname); 505 ncclose(cdfid); return; 506 } 507 if (tmp.type != test.atts[ia].type) { 508 error("%s: ncattinq in define mode returned wrong type", pname); 509 ncclose(cdfid); 510 return; 511 } 512 if (tmp.len != test.atts[ia].len) { 513 error("%s: ncattinq in define mode returned wrong len", pname); 514 ncclose(cdfid); return; 515 } 516 /* allocate space to hold the attribute value to be retrieved */ 517 tmp.val = emalloc(tmp.len * nctypelen(tmp.type)); 518 if (ncattget(cdfid, test.atts[ia].var, test.atts[ia].name, tmp.val) 519 == -1) { 520 error("%s: ncattget of variable attribute failed in define mode", 521 pname); 522 ncclose(cdfid); return; 523 } 524 if (val_cmp(tmp.type, tmp.len, tmp.val, test.atts[ia].val) != 0) { 525 error("%s: ncattget got bad values in define mode", pname); 526 error(" cdfid=%d, varname=%s, attname=%s, type=%d, len=%d", 527 cdfid, test.vars[test.atts[ia].var].name, 528 test.atts[ia].name, test.atts[ia].type, test.atts[ia].len); 529 (void)fprintf(stderr,"should have got:"); 530 val_out(test.atts[ia].type, test.atts[ia].len, 531 test.atts[ia].val); 532 (void)fprintf(stderr," instead got:"); 533 val_out(tmp.type, tmp.len, tmp.val); 534 nerrs++; 535 } 536 free (tmp.val); 537 } 538 if (ncendef (cdfid) == -1) { 539 error("%s: ncendef failed", pname); 540 ncclose(cdfid); return; 541 } 542 543 /* in data mode, check all attributes values against test netcdf */ 544 for (ia = 0; ia < test.natts; ia++) { 545 if (ncattinq(cdfid, test.atts[ia].var, test.atts[ia].name, 546 &tmp.type, &tmp.len) == -1) { 547 error("%s: ncattinq failed", pname); 548 ncclose(cdfid); 549 return; 550 } 551 if (tmp.type != test.atts[ia].type) { 552 error("%s: ncattinq returned wrong type", pname); 553 ncclose(cdfid); 554 return; 555 } 556 if (tmp.len != test.atts[ia].len) { 557 error("%s: ncattinq returned wrong len", pname); 558 ncclose(cdfid); 559 return; 560 } 561 /* allocate space to hold the attribute value to be retrieved */ 562 tmp.val = emalloc(tmp.len * nctypelen(tmp.type)); 563 if (ncattget(cdfid, test.atts[ia].var, test.atts[ia].name, tmp.val) 564 == -1) { 565 error("%s: ncattget of variable attribute failed in data mode", 566 pname); 567 ncclose(cdfid); return; 568 } 569 if (val_cmp(tmp.type, tmp.len, tmp.val, test.atts[ia].val) != 0) { 570 error("%s: ncattget got bad values in data mode", pname); 571 error(" cdfid=%d, varname=%s, attname=%s, type=%d, len=%d", 572 cdfid, test.vars[test.atts[ia].var].name, 573 test.atts[ia].name, test.atts[ia].type, test.atts[ia].len); 574 (void)fprintf(stderr,"should have got:"); 575 val_out(test.atts[ia].type, test.atts[ia].len, 576 test.atts[ia].val); 577 (void)fprintf(stderr," instead got:"); 578 val_out(tmp.type, tmp.len, tmp.val); 579 nerrs++; 580 } 581 free (tmp.val); 582 } 583 /* try with bad variable handle, should fail */ 584 if (ncattget(cdfid, test.nvars, vmax.name, vmax.val) != -1) { 585 error("%s: ncattget should fail with bad variable handle", pname); 586 ncclose(cdfid); return; 587 } 588 /* try getting non-existent attribute, should fail */ 589 if (ncattget(cdfid, uu_id, "nonesuch", vmax.val) != -1) { 590 error("%s: ncattget should fail with nonexistant attribute", pname); 591 ncclose(cdfid); return; 592 } 593 if (ncclose (cdfid) == -1) { 594 error("%s: ncclose failed", pname); 595 return; 596 } 597 /* try with bad netcdf handle, should fail */ 598 if (ncattget(cdfid, uu_id, vmax.name, vmax.val) != -1) { 599 error("%s: ncattput should fail with bad netcdf handle", pname); 600 ncclose(cdfid); return; 601 } 602 if (nerrs > 0) 603 (void) fprintf(stderr,"FAILED! ***\n"); 604 else 605 (void) fprintf(stderr,"ok ***\n"); 606} 607 608 609/* 610 * Test ncattcopy 611 * check that NC_GLOBAL variable for source or target works 612 * check that new attribute put works with target in define mode 613 * check that old attribute put works with target in data mode 614 * check that changing type and length of an attribute work OK 615 * try with same cdfid for source and target, different variables 616 * try with same cdfid for source and target, same variable 617 * try with nonexisting attribute, check error 618 * try with bad source or target netCDF handles, check error 619 * try with bad source or target variable handle, check error 620 */ 621void 622test_ncattcopy(path1, path2) 623 const char *path1; /* name of input netcdf file to open */ 624 const char *path2; /* name of output netcdf file to create */ 625{ 626 int nerrs = 0; 627 static char pname[] = "test_ncattcopy"; 628 int cdfid, cdfid2; /* netcdf id */ 629 int id; /* dimension id */ 630 int tt_id; /* variable id */ 631 static struct cdfvar tt = /* new variable for source netcdf */ 632 {"tt", NC_LONG, 1, ___, 0}; 633 int tu_id, tu2_id; /* variable ids */ 634 static struct cdfvar tu = /* new variable for target netcdf */ 635 {"tu", NC_DOUBLE, 2, ___, 0}; 636 static double double_vals[] = {-1., -2.}; 637 static float float_vals[] = {-1., -2.}; 638 static struct cdfatt att = /* attribute */ 639 {___, "att", NC_DOUBLE, LEN_OF(double_vals), (void *) double_vals}; 640 static struct cdfatt att2 = /* attribute */ 641 {___, "att", NC_FLOAT, LEN_OF(float_vals), (void *) float_vals}; 642 static struct cdfatt tmp; /* attribute */ 643 644 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]); 645 646 if ((cdfid = ncopen(path1, NC_WRITE)) == -1) { 647 error("%s: ncopen failed", pname); 648 return; 649 } 650 /* opened OK, enter define mode */ 651 if (ncredef(cdfid) == -1) { 652 error("%s: ncredef failed on source", pname); 653 ncclose(cdfid); return; 654 } 655 /* in define mode, add a global attribute, a variable and an attribute */ 656 if (ncattput(cdfid, NC_GLOBAL, att.name, att.type, att.len, att.val) == -1) { 657 error("%s: ncattput failed", pname); 658 ncclose(cdfid); return; 659 } 660 add_att(&test, NC_GLOBAL, &att); /* keep in-memory netcdf consistent */ 661 tt.dims = (int *) emalloc(sizeof(int) * tt.ndims); 662 for (id=0; id < tt.ndims; id++) 663 tt.dims[0] = id; 664 if ((tt_id=ncvardef(cdfid, tt.name, tt.type, tt.ndims, tt.dims)) == -1) { 665 error("%s: ncvardef failed", pname); 666 ncclose(cdfid); return; 667 } 668 add_var(&test, &tt); /* keep in-memory netcdf consistent */ 669 if (ncattput(cdfid, tt_id, att.name, att.type, att.len, att.val) == -1) { 670 error("%s: ncattput failed", pname); 671 ncclose(cdfid); return; 672 } 673 add_att(&test, tt_id, &att); /* keep in-memory netcdf consistent */ 674 675 tu.dims = (int *) emalloc(sizeof(int) * tu.ndims); 676 for (id = 0; id < tu.ndims; id++) 677 tu.dims[id] = id; 678 if ((tu_id=ncvardef(cdfid, tu.name, tu.type, tu.ndims, tu.dims)) == -1) { 679 error("%s: ncvardef failed", pname); 680 ncclose(cdfid); return; 681 } 682 add_var(&test, &tu); /* keep in-memory netcdf consistent */ 683 if (ncattput(cdfid, tu_id, att.name, att.type, att.len, att.val) == -1) { 684 error("%s: ncattput failed", pname); 685 ncclose(cdfid); return; 686 } 687 add_att(&test, tu_id, &att); /* keep in-memory netcdf consistent */ 688 if (ncendef (cdfid) == -1) { 689 error("%s: ncendef failed", pname); 690 ncclose(cdfid); return; 691 } 692 /* first (source) netcdf is in data mode */ 693 /* create second netCDF to copy attributes to */ 694 if ((cdfid2 = nccreate(path2, NC_CLOBBER)) == -1) { 695 error("%s: nccreate failed", pname); 696 return; 697 } 698 /* create dimensions and variable in second netcdf */ 699 for (id = 0; id < tu.ndims; id++) { /* copy dimensions from source */ 700 if ((tu.dims[id] =ncdimdef(cdfid2, test.dims[id].name, 701 test.dims[id].size)) == -1) { 702 error("%s: ncdimdef failed", pname); 703 ncclose(cdfid); ncclose(cdfid2); return; 704 } 705 } 706 if ((tu2_id=ncvardef(cdfid2, tu.name, tu.type, tu.ndims, tu.dims)) == -1) { 707 error("%s: ncvardef failed", pname); 708 ncclose(cdfid); ncclose(cdfid2); return; 709 } 710 /* try copying NC_GLOBAL attribute from source to target */ 711 if (ncattcopy(cdfid, NC_GLOBAL, att.name, cdfid2, NC_GLOBAL) == -1) { 712 error("%s: ncattcopy on NC_GLOBAL attribute '%s' failed", 713 pname, att.name); 714 ncclose(cdfid); ncclose(cdfid2); return; 715 } 716 /* check that copy worked with ncattinq and ncattget */ 717 if (ncattinq(cdfid2, NC_GLOBAL, att.name, &tmp.type, &tmp.len) == -1) { 718 error("%s: ncattinq of NC_GLOBAL attribute failed", pname); 719 ncclose(cdfid); ncclose(cdfid2); return; 720 } 721 if (att.type != tmp.type || att.len != tmp.len) { 722 error("%s: NC_GLOBAL ncattinq got unexpected type or len", pname); 723 ncclose(cdfid); ncclose(cdfid2); return; 724 } 725 /* allocate space to hold the attribute value to be retrieved */ 726 tmp.val = emalloc(att.len * nctypelen(att.type)); 727 if (ncattget(cdfid2, NC_GLOBAL, att.name, tmp.val) == -1) { 728 error("%s: ncattget of variable attribute failed", pname); 729 ncclose(cdfid); ncclose(cdfid2); return; 730 } 731 if (val_cmp(tmp.type, tmp.len, tmp.val, att.val) != 0) { 732 error("%s: ncattget got bad values after put of NC_GLOBAL attrs", 733 pname); 734 nerrs++; 735 } 736 free (tmp.val); 737 /* try copying variable attribute from source to target */ 738 if (ncattcopy(cdfid, tt_id, att.name, cdfid2, tu2_id) == -1) { 739 error("%s: ncattcopy failed", pname); 740 ncclose(cdfid); ncclose(cdfid2); return; 741 } 742 /* check that copy worked with ncattinq and ncattget */ 743 if (ncattinq(cdfid2, tu2_id, att.name, &tmp.type, &tmp.len) == -1) { 744 error("%s: ncattinq of variable attribute failed", pname); 745 ncclose(cdfid); ncclose(cdfid2); return; 746 } 747 if (att.type != tmp.type || att.len != tmp.len) { 748 error("%s: variable ncattinq got unexpected type or len", pname); 749 ncclose(cdfid); ncclose(cdfid2); return; 750 } 751 /* allocate space to hold the attribute value to be retrieved */ 752 tmp.val = emalloc(att.len * nctypelen(att.type)); 753 if (ncattget(cdfid2, tu2_id, att.name, tmp.val) == -1) { 754 error("%s: ncattget of variable attribute failed", pname); 755 ncclose(cdfid); ncclose(cdfid2); return; 756 } 757 if (val_cmp(tmp.type, tmp.len, tmp.val, att.val) != 0) { 758 error("%s: ncattget got bad values after copy of variable attrs", 759 pname); 760 nerrs++; 761 } 762 free (tmp.val); 763 764 /* 765 * check that old attribute put works with target in data mode, 766 * also checks that changing type and length of an attribute works OK 767 */ 768 if (ncendef (cdfid2) == -1) { 769 error("%s: ncendef failed", pname); 770 ncclose(cdfid); ncclose(cdfid2); return; 771 } 772 /* change attribute to shorter attribute */ 773 if (ncattput(cdfid, NC_GLOBAL, att2.name, att2.type, att2.len, att2.val) 774 == -1) { 775 error("%s: ncattput of shorter NC_GLOBAL attribute failed", pname); 776 ncclose(cdfid); ncclose(cdfid2); return; 777 } 778 add_att(&test, NC_GLOBAL, &att2); /* keep in-memory netcdf consistent */ 779 /* copy shorter attribute on existing attribute */ 780 if (ncattcopy(cdfid, NC_GLOBAL, att2.name, cdfid2, tu2_id) == -1) { 781 error("%s: ncattcopy of shorter attribute on old attribute failed", 782 pname); 783 ncclose(cdfid); ncclose(cdfid2); return; 784 } 785 /* check that copy worked with ncattinq and ncattget */ 786 if (ncattinq(cdfid2, tu2_id, att2.name, &tmp.type, &tmp.len) == -1) { 787 error("%s: ncattinq of variable attribute failed", pname); 788 ncclose(cdfid); ncclose(cdfid2); return; 789 } 790 if (att2.type != tmp.type || att2.len != tmp.len) { 791 error("%s: variable ncattinq got unexpected type or len", pname); 792 ncclose(cdfid); ncclose(cdfid2); return; 793 } 794 /* allocate space to hold the attribute value to be retrieved */ 795 tmp.val = emalloc(att2.len * nctypelen(att2.type)); 796 if (ncattget(cdfid2, tu2_id, att2.name, tmp.val) == -1) { 797 error("%s: ncattget of variable attribute failed", pname); 798 ncclose(cdfid); ncclose(cdfid2); return; 799 } 800 if (val_cmp(tmp.type, tmp.len, tmp.val, att2.val) != 0) { 801 error("%s: ncattget got bad values after copy of variable attrs", 802 pname); 803 nerrs++; 804 } 805 free (tmp.val); 806 807 /* try copying with same source and target netcdf, different variables */ 808 /* copy shorter attribute on existing attribute */ 809 if (ncattcopy(cdfid, NC_GLOBAL, att2.name, cdfid, tu_id) == -1) { 810 error("%s: ncattcopy of shorter NC_GLOBAL attribute failed", pname); 811 ncclose(cdfid); ncclose(cdfid2); return; 812 } 813 add_att(&test, tu_id, &att2); /* keep in-memory netcdf consistent */ 814 /* check that copy worked with ncattinq and ncattget */ 815 if (ncattinq(cdfid, tu_id, att2.name, &tmp.type, &tmp.len) == -1) { 816 error("%s: ncattinq of variable attribute failed", pname); 817 ncclose(cdfid); ncclose(cdfid2); return; 818 } 819 if (att2.type != tmp.type || att2.len != tmp.len) { 820 error("%s: variable ncattinq got unexpected type or len", pname); 821 ncclose(cdfid); ncclose(cdfid2); return; 822 } 823 /* allocate space to hold the attribute value to be retrieved */ 824 tmp.val = emalloc(att2.len * nctypelen(att2.type)); 825 if (ncattget(cdfid, tu_id, att2.name, tmp.val) == -1) { 826 error("%s: ncattget of variable attribute failed", pname); 827 ncclose(cdfid); ncclose(cdfid2); return; 828 } 829 if (val_cmp(tmp.type, tmp.len, tmp.val, att2.val) != 0) { 830 error("%s: ncattget got bad values after copy of variable attrs", 831 pname); 832 nerrs++; 833 } 834 free (tmp.val); 835 836 /* try with same cdfid for source and target, same variable */ 837 if (ncattcopy(cdfid, tu_id, att.name, cdfid, tu_id) == -1) { 838 error("%s: ncattcopy failed with identical source and target", 839 pname); 840 ncclose(cdfid); ncclose(cdfid2); return; 841 } 842 /* try with nonexisting attribute, check error */ 843 if (ncattcopy(cdfid, tt_id, "nonesuch", cdfid, tu_id) != -1) { 844 error("%s: ncattcopy should fail with bad attribute name", 845 pname); 846 ncclose(cdfid); ncclose(cdfid2); return; 847 } 848 /* try with bad source or target variable handle, check error */ 849 if (ncattcopy(cdfid, test.nvars, att.name, cdfid, tu_id) != -1) { 850 error("%s: ncattcopy should fail with bad source variable id", 851 pname); 852 ncclose(cdfid); ncclose(cdfid2); return; 853 } 854 if (ncattcopy(cdfid, tt_id, att.name, cdfid, 2) != -1) { 855 error("%s: ncattcopy should fail with bad target variable id", 856 pname); 857 ncclose(cdfid); ncclose(cdfid2); return; 858 } 859 if (ncclose (cdfid2) == -1) { 860 error("%s: ncclose failed", pname); 861 ncclose(cdfid); return; 862 } 863 /* try with bad source or target netCDF handles, check error */ 864 if (ncattcopy(cdfid, tt_id, att.name, cdfid2, tu_id) != -1) { 865 error("%s: ncattcopy should fail with bad target netcdf id", 866 pname); 867 ncclose(cdfid); return; 868 } 869 if (ncclose (cdfid) == -1) { 870 error("%s: ncclose failed", pname); 871 return; 872 } 873 if (ncattcopy(cdfid, tt_id, att.name, cdfid2, tu_id) != -1) { 874 error("%s: ncattcopy should fail with bad netcdf id", pname); 875 nerrs++; 876 } 877 if (nerrs > 0) 878 (void) fprintf(stderr,"FAILED! ***\n"); 879 else 880 (void) fprintf(stderr,"ok ***\n"); 881} 882 883 884/* 885 * Test ncattname 886 * check that NC_GLOBAL variable id works 887 * check in both modes 888 * check that proper call worked after ncattput 889 * try with bad netCDF handle, check error 890 * try with bad variable handle, check error 891 * try with bad attribute number, check error 892 */ 893void 894test_ncattname(path) 895 const char *path; /* name of writable netcdf file to open */ 896{ 897 int nerrs = 0; 898 static char pname[] = "test_ncattname"; 899 int cdfid; /* netcdf id */ 900 struct cdfatt tmp; /* attributes */ 901 int ia, ib; /* attribute numbers */ 902 int iv; /* variable id */ 903 static short short_vals[] = {3, 4, 5}; 904 static struct cdfatt att = /* attribute */ 905 {___, ___, NC_SHORT, LEN_OF(short_vals), (void *) short_vals}; 906 907 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]); 908 909 if ((cdfid = ncopen(path, NC_WRITE)) == -1) { 910 error("%s: ncopen failed", pname); 911 return; 912 } 913 /* opened OK, enter define mode */ 914 if (ncredef(cdfid) == -1) { 915 error("%s: ncredef failed", pname); 916 ncclose(cdfid); return; 917 } 918 /* for each NC_GLOBAL attribute, get name and compare with expected name */ 919 att.name = (char *) emalloc(MAX_NC_NAME); 920 ib = 0; 921 for (ia = 0; ia < test.ngatts; ia++) { 922 if (ncattname(cdfid, NC_GLOBAL, ia, att.name) == -1) { 923 error("%s: ncattname failed on global attribute", pname); 924 ncclose(cdfid); return; 925 } 926 /* find number of next global attribute */ 927 while (ib < test.natts && test.atts[ib].var != NC_GLOBAL) 928 ib++; 929 if (ib >= test.natts) { 930 error("%s: test problem, expected global attribute not found", 931 pname); 932 ncclose(cdfid); return; 933 } 934 if (strcmp(att.name, test.atts[ib].name) != 0) { 935 error("%s: NC_GLOBAL attribute name `%s' instead of expected `%s'", 936 pname, att.name, test.atts[ib].name); 937 nerrs++; 938 } 939 ib++; 940 } 941 /* for each variable attribute, get name and compare with expected name */ 942 for (iv = 0; iv < test.nvars; iv++) { 943 ib = 0; 944 for (ia = 0; ia < test.vars[iv].natts; ia++) { 945 if (ncattname(cdfid, iv, ia, att.name) == -1) { 946 error("%s: ncattname failed on variable attribute", pname); 947 ncclose(cdfid); return; 948 } 949 /* find number of next attribute */ 950 while (ib < test.natts && test.atts[ib].var != iv) 951 ib++; 952 if (ib >= test.natts) { 953 error("%s: problem in test, expected attribute not found", 954 pname); 955 ncclose(cdfid); return; 956 } 957 if (strcmp(att.name, test.atts[ib].name) != 0) { 958 error("%s: variable '%s' name `%s' instead of expected `%s'", 959 pname, test.vars[iv].name, att.name, test.atts[ib].name); 960 nerrs++; 961 } 962 ib++; 963 } 964 } 965 /* in define mode, add a global attribute */ 966 (void) strcpy(att.name,"attx"); 967 if (ncattput(cdfid, NC_GLOBAL, att.name, att.type, att.len, att.val) 968 == -1) { 969 error("%s: ncattput failed", pname); 970 ncclose(cdfid); return; 971 } 972 add_att(&test, NC_GLOBAL, &att); /* keep in-memory netcdf consistent */ 973 /* test that ncattname works immediately after ncattput */ 974 tmp.name = (char *) emalloc(MAX_NC_NAME); 975 if (ncattname(cdfid, NC_GLOBAL, test.ngatts-1, tmp.name) == -1) { 976 error("%s: ncattname failed on variable attribute", pname); 977 ncclose(cdfid); return; 978 } 979 if (strcmp(att.name, tmp.name) != 0) { 980 error("%s: immediate NC_GLOBAL name `%s' instead of expected `%s'", 981 pname, tmp.name, att.name); 982 nerrs++; 983 } 984 if (ncendef (cdfid) == -1) { 985 error("%s: ncendef failed", pname); 986 ncclose(cdfid); return; 987 } 988 /* in data mode */ 989 /* for each NC_GLOBAL attribute, get name and compare with expected name */ 990 ib = 0; 991 for (ia = 0; ia < test.ngatts; ia++) { 992 if (ncattname(cdfid, NC_GLOBAL, ia, att.name) == -1) { 993 error("%s: ncattname failed on global attribute", pname); 994 ncclose(cdfid); return; 995 } 996 /* find number of next global attribute */ 997 while (ib < test.natts && test.atts[ib].var != NC_GLOBAL) 998 ib++; 999 if (ib >= test.natts) { 1000 error("%s: test problem, expected global attribute not found", 1001 pname); 1002 ncclose(cdfid); return; 1003 } 1004 if (strcmp(att.name, test.atts[ib].name) != 0) { 1005 error("%s: NC_GLOBAL attribute name `%s' instead of expected `%s'", 1006 pname, att.name, test.atts[ib].name); 1007 nerrs++; 1008 } 1009 ib++; 1010 } 1011 /* for each variable attribute, get name and compare with expected name */ 1012 for (iv = 0; iv < test.nvars; iv++) { 1013 ib = 0; 1014 for (ia = 0; ia < test.vars[iv].natts; ia++) { 1015 if (ncattname(cdfid, iv, ia, att.name) == -1) { 1016 error("%s: ncattname failed on variable attribute", pname); 1017 ncclose(cdfid); return; 1018 } 1019 /* find number of next attribute */ 1020 while (ib < test.natts && test.atts[ib].var != iv) 1021 ib++; 1022 if (ib >= test.natts) { 1023 error("%s: problem in test, expected attribute not found", 1024 pname); 1025 ncclose(cdfid); return; 1026 } 1027 if (strcmp(att.name, test.atts[ib].name) != 0) { 1028 error("%s: variable '%s' name `%s' instead of expected `%s'", 1029 pname, test.vars[iv].name, att.name, test.atts[ib].name); 1030 nerrs++; 1031 } 1032 ib++; 1033 } 1034 } 1035 /* try with bad variable handle, check error */ 1036 if (ncattname(cdfid, test.nvars, 0, att.name) != -1) { 1037 error("%s: ncattname should fail with bad variable handle", pname); 1038 ncclose(cdfid); return; 1039 } 1040 /* try with bad attribute number, check error */ 1041 if (ncattname(cdfid, NC_GLOBAL, -1, att.name) != -1) { 1042 error("%s: ncattname should fail with negative number", pname); 1043 ncclose(cdfid); return; 1044 } 1045 if (ncattname(cdfid, NC_GLOBAL, test.ngatts, att.name) != -1) { 1046 error("%s: ncattname should fail with too-high number", pname); 1047 ncclose(cdfid); return; 1048 } 1049 if (ncclose (cdfid) == -1) { 1050 error("%s: ncclose failed", pname); 1051 nerrs++; 1052 return; 1053 } 1054 /* try with bad netCDF handle, check error */ 1055 if (ncattname(cdfid, NC_GLOBAL, 0, att.name) != -1) { 1056 error("%s: ncattname shoul fail with bad cdfid", pname); 1057 nerrs++; 1058 } 1059 free (tmp.name); 1060 free (att.name); 1061 if (nerrs > 0) 1062 (void) fprintf(stderr,"FAILED! ***\n"); 1063 else 1064 (void) fprintf(stderr,"ok ***\n"); 1065} 1066 1067 1068/* 1069 * Test ncattrename 1070 * check that proper rename worked with ncattinq, ncattget 1071 * try renaming to existing attribute name, check error 1072 * try with nonexisting attribute, check error 1073 * try with bad variable handle, check error 1074 * try in data mode, check error 1075 * try with bad netCDF handle, check error 1076 */ 1077void 1078test_ncattrename(path) 1079 const char *path; /* name of writable netcdf file to open */ 1080{ 1081 int nerrs = 0; 1082 static char pname[] = "test_ncattrename"; 1083 int cdfid; /* netcdf id */ 1084 static char newname[] = "shorter"; 1085 static char longername[] = "longer_name"; 1086 struct cdfatt tmp; /* attributes */ 1087 static short short_vals[] = {3, 4, 5}; 1088 static struct cdfatt atty = /* attribute */ 1089 {___, "long_name", NC_SHORT, LEN_OF(short_vals), (void *) short_vals}; 1090 static struct cdfatt attz = /* attribute */ 1091 {___, "arggh", NC_SHORT, LEN_OF(short_vals), (void *) short_vals}; 1092 int ynum; /* attribute number */ 1093 1094 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]); 1095 1096 if ((cdfid = ncopen(path, NC_WRITE)) == -1) { 1097 error("%s: ncopen failed", pname); 1098 return; 1099 } 1100 /* opened OK, enter define mode */ 1101 if (ncredef(cdfid) == -1) { 1102 error("%s: cdredef failed", pname); 1103 ncclose(cdfid); return; 1104 } 1105 /* in define mode, add two attributes */ 1106 if (ncattput(cdfid, NC_GLOBAL, atty.name, atty.type, atty.len, 1107 atty.val) == -1) { 1108 error("%s: ncattput failed", pname); 1109 ncclose(cdfid); return; 1110 } 1111 add_att(&test, NC_GLOBAL, &atty); /* keep in-memory netcdf in sync */ 1112 ynum = test.natts-1; /* number of attribute just put */ 1113 if (ncattput(cdfid, NC_GLOBAL, attz.name, attz.type, attz.len, 1114 attz.val) == -1) { 1115 error("%s: ncattput failed", pname); 1116 ncclose(cdfid); return; 1117 } 1118 add_att(&test, NC_GLOBAL, &attz); /* keep in-memory netcdf in sync */ 1119 1120 /* rename first attribute to shorter name */ 1121 if (ncattrename(cdfid, NC_GLOBAL, atty.name, newname) == -1) { 1122 error("%s: ncattrename failed", pname); 1123 ncclose(cdfid); return; 1124 } 1125 (void) strcpy(test.atts[ynum].name, newname); /* keep test consistent */ 1126 /* check new name with ncattinq */ 1127 if (ncattinq(cdfid, NC_GLOBAL, newname, &tmp.type, &tmp.len) == -1) { 1128 error("%s: ncattinq of renamed attribute failed", pname); 1129 ncclose(cdfid); return; 1130 } 1131 if (atty.type != tmp.type || atty.len != tmp.len) { 1132 error("%s: NC_GLOBAL ncattinq got unexpected type or len", pname); 1133 ncclose(cdfid); return; 1134 } 1135 /* allocate space to hold the attribute value to be retrieved */ 1136 tmp.val = emalloc(atty.len * nctypelen(atty.type)); 1137 if (ncattget(cdfid, NC_GLOBAL, newname, tmp.val) == -1) { 1138 error("%s: ncattget of variable attribute failed", pname); 1139 ncclose(cdfid); return; 1140 } 1141 if (val_cmp(tmp.type, tmp.len, tmp.val, atty.val) != 0) { 1142 error("%s: ncattget got bad values after rename attrs", pname); 1143 nerrs++; 1144 } 1145 if (ncattinq(cdfid, NC_GLOBAL, atty.name, &tmp.type, &tmp.len) != -1) { 1146 error("%s: ncattrename left attribute with old name", pname); 1147 ncclose(cdfid); return; 1148 } 1149 /* try to rename second attribute same as first, should fail */ 1150 if (ncattrename(cdfid, NC_GLOBAL, attz.name, newname) != -1) { 1151 error("%s: ncattrename should have failed with used name", pname); 1152 ncclose(cdfid); return; 1153 } 1154 /* try to rename second attribute with a longer name */ 1155 if (ncattrename(cdfid, NC_GLOBAL, attz.name, longername) == -1) { 1156 error("%s: ncattrename failed with longer name", pname); 1157 ncclose(cdfid); return; 1158 } 1159 /* try with bad variable handle, check for failure */ 1160 if (ncattrename(cdfid, test.nvars, newname, atty.name) != -1) { 1161 error("%s: ncattrename should have failed on bad variable id", pname); 1162 ncclose(cdfid); return; 1163 } 1164 /* try with bad attribute name, check for failure */ 1165 if (ncattrename(cdfid, NC_GLOBAL, "nonesuch", newname) != -1) { 1166 error("%s: ncattrename should have failed on bad attribute name", 1167 pname); 1168 ncclose(cdfid); return; 1169 } 1170 if (ncendef (cdfid) == -1) { 1171 error("%s: ncendef failed", pname); 1172 ncclose(cdfid); return; 1173 } 1174 /* in data mode change name to even shorter and check value */ 1175 if (ncattrename(cdfid, NC_GLOBAL, newname, "short") == -1) { 1176 error("%s: ncattrename to shorter name failed in data mode", pname); 1177 ncclose(cdfid); return; 1178 } 1179 if (ncattrename(cdfid, NC_GLOBAL, "short", "plugh") == -1) { 1180 error("%s: ncattrename to same length failed in data mode", pname); 1181 ncclose(cdfid); return; 1182 } 1183 if (ncattget(cdfid, NC_GLOBAL, "plugh", tmp.val) == -1) { 1184 error("%s: ncgetatt of renamed attribute failed in data mode", pname); 1185 ncclose(cdfid); return; 1186 } 1187 if (val_cmp(tmp.type, tmp.len, tmp.val, atty.val) != 0) { 1188 error("%s: ncattget got bad values after data mode rename", pname); 1189 nerrs++; 1190 } 1191 free (tmp.val); 1192 if (ncclose (cdfid) == -1) { 1193 error("%s: ncclose failed", pname); 1194 return; 1195 } 1196 /* should fail, since bad handle */ 1197 if (ncattrename(cdfid, NC_GLOBAL, newname, atty.name) != -1) { 1198 error("%s: ncattrename should fail with bad cdfid", pname); 1199 ncclose(cdfid); return; 1200 } 1201 if (nerrs > 0) 1202 (void) fprintf(stderr,"FAILED! ***\n"); 1203 else 1204 (void) fprintf(stderr,"ok ***\n"); 1205} 1206 1207 1208/* 1209 * Test ncattdel 1210 * check that proper delete worked 1211 * try with bad netCDF handle, check error 1212 * try with bad variable handle, check error 1213 * try with nonexisting attribute, check error 1214 * try in data mode, check error 1215 */ 1216void 1217test_ncattdel(path) 1218 const char *path; /* name of writable netcdf file to open */ 1219{ 1220 int nerrs = 0; 1221 static char pname[] = "test_ncattdel"; 1222 int cdfid; /* netcdf id */ 1223 static short short_vals[] = {-1, -2, -3 }; 1224 static struct cdfatt yaa = /* attribute */ 1225 {___, "yet_another_attribute", NC_SHORT, LEN_OF(short_vals), 1226 (void *) short_vals}; 1227 int id; /* dimension id */ 1228 int yav_id; /* variable id */ 1229 static struct cdfvar yav = /* new variable for target netcdf */ 1230 {"yet_another_variable", NC_DOUBLE, 2, ___, 0}; 1231 struct cdfvar vtmp; /* variable */ 1232 struct cdfatt atmp; /* attribute */ 1233 int ndims; /* number of dimensions */ 1234 int nvars; /* number of variables */ 1235 int ngatts1, ngatts2; /* number of global attributes */ 1236 int natts; /* number of variable attributes */ 1237 int xdimid; /* id of unlimited dimension */ 1238 1239 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]); 1240 1241 if ((cdfid = ncopen(path, NC_WRITE)) == -1) { 1242 error("%s: ncopen failed", pname); 1243 return; 1244 } 1245 /* opened OK, enter define mode */ 1246 if (ncredef(cdfid) == -1) { 1247 error("%s: cdredef failed", pname); 1248 ncclose(cdfid); return; 1249 } 1250 /* in define mode, add global attribute, variable, variable attribute */ 1251 if (ncattput(cdfid, NC_GLOBAL, yaa.name, yaa.type, yaa.len, yaa.val) == -1) { 1252 error("%s: ncattput failed", pname); 1253 ncclose(cdfid); return; 1254 } 1255 add_att(&test, NC_GLOBAL, &yaa); /* keep in-memory netcdf in sync */ 1256 yav.dims = (int *) emalloc(sizeof(int) * yav.ndims); 1257 for (id = 0; id < yav.ndims; id++) 1258 yav.dims[id] = id; 1259 if ((yav_id=ncvardef(cdfid, yav.name, yav.type, yav.ndims, yav.dims)) 1260 == -1) { 1261 error("%s: ncvardef failed", pname); 1262 ncclose(cdfid); return; 1263 } 1264 add_var(&test, &yav); /* keep in-memory netcdf consistent */ 1265 if (ncattput(cdfid, yav_id, yaa.name, yaa.type, yaa.len, yaa.val) == -1) { 1266 error("%s: ncattput failed", pname); 1267 ncclose(cdfid); return; 1268 } 1269 add_att(&test, yav_id, &yaa); /* keep in-memory netcdf consistent */ 1270 1271 /* get number of global attributes, number of attributes for variable */ 1272 if (ncinquire(cdfid, &ndims, &nvars, &ngatts1, &xdimid) == -1) { 1273 error("%s: ncinquire in data mode failed", pname); 1274 ncclose(cdfid); return; 1275 } 1276 vtmp.dims = (int *) emalloc(sizeof(int) * MAX_VAR_DIMS); 1277 vtmp.name = (char *) emalloc(MAX_NC_NAME); 1278 if (ncvarinq(cdfid, yav_id, vtmp.name, &vtmp.type, &vtmp.ndims, vtmp.dims, 1279 &natts) == -1) { 1280 error("%s: ncvarinq failed", pname); 1281 ncclose(cdfid); return; 1282 } 1283 1284 /* delete global attribute and check that it's gone */ 1285 if (ncattdel(cdfid, NC_GLOBAL, yaa.name) == -1) { 1286 error("%s: ncattdel failed", pname); 1287 ncclose(cdfid); return; 1288 } 1289 del_att(&test, NC_GLOBAL, &yaa); /* keep in-memory netcdf consistent */ 1290 if (ncinquire(cdfid, &ndims, &nvars, &ngatts2, &xdimid) == -1) { 1291 error("%s: ncinquire failed", pname); 1292 ncclose(cdfid); return; 1293 } 1294 if (ngatts2 != ngatts1 - 1) { 1295 error("%s: NC_GLOBAL attribute deleted, but ngatts did not decrement", 1296 pname); 1297 ncclose(cdfid); return; 1298 } 1299 if (ncattinq(cdfid, NC_GLOBAL, yaa.name, &atmp.type, &atmp.len) != -1) { 1300 error("%s: ncattinq on deleted NC_GLOBAL attribute should fail", pname); 1301 ncclose(cdfid); return; 1302 } 1303 1304 /* delete variable attribute and check that it's gone */ 1305 if (ncattdel(cdfid, yav_id, yaa.name) == -1) { 1306 error("%s: ncattdel failed", pname); 1307 ncclose(cdfid); return; 1308 } 1309 del_att(&test, yav_id, &yaa); /* keep in-memory netcdf consistent */ 1310 if (ncvarinq(cdfid, yav_id, vtmp.name, &vtmp.type, &vtmp.ndims, 1311 vtmp.dims, &vtmp.natts) == -1) { 1312 error("%s: ncvarinq failed", pname); 1313 ncclose(cdfid); return; 1314 } 1315 if (vtmp.natts != natts - 1) { 1316 error("%s: NC_GLOBAL attribute deleted, but ngatts did not decrement", 1317 pname); 1318 ncclose(cdfid); return; 1319 } 1320 if (ncattinq(cdfid, yav_id, yaa.name, &atmp.type, &atmp.len) != -1) { 1321 error("%s: ncattinq on deleted variable attribute should fail", 1322 pname); 1323 ncclose(cdfid); return; 1324 } 1325 /* re-add global attribute, variable, variable attribute */ 1326 if (ncattput(cdfid, NC_GLOBAL, yaa.name, yaa.type, yaa.len, yaa.val) == -1) { 1327 error("%s: ncattput failed", pname); 1328 ncclose(cdfid); return; 1329 } 1330 add_att(&test, NC_GLOBAL, &yaa); /* keep in-memory netcdf in sync */ 1331 if (ncattput(cdfid, yav_id, yaa.name, yaa.type, yaa.len, yaa.val) == -1) { 1332 error("%s: ncattput failed", pname); 1333 ncclose(cdfid); return; 1334 } 1335 add_att(&test, yav_id, &yaa); /* keep in-memory netcdf consistent */ 1336 /* try on nonexistent attribute, should fail */ 1337 if (ncattdel(cdfid, yav_id, "nonesuch") != -1) { 1338 error("%s: ncattdel should fail on bogus attribute", pname); 1339 ncclose(cdfid); return; 1340 } 1341 /* try on bad variable id, should fail */ 1342 if (ncattdel(cdfid, test.nvars, yaa.name) != -1) { 1343 error("%s: ncattdel should fail on bad variable id", pname); 1344 ncclose(cdfid); return; 1345 } 1346 if (ncendef (cdfid) == -1) { 1347 error("%s: ncendef failed", pname); 1348 ncclose(cdfid); return; 1349 } 1350 /* in data mode, should fail */ 1351 if (ncattdel(cdfid, NC_GLOBAL, yaa.name) != -1) { 1352 error("%s: ncattdel in data mode should fail", pname); 1353 ncclose(cdfid); return; 1354 } 1355 if (ncclose (cdfid) == -1) { 1356 error("%s: ncclose failed", pname); 1357 return; 1358 } 1359 /* try on bad netcdf handle, should fail */ 1360 if (ncattdel(cdfid, yav_id, yaa.name) != -1) { 1361 error("%s: ncattdel should fail on bad netcdf id", pname); 1362 nerrs++; 1363 } 1364 free(vtmp.dims); 1365 free(vtmp.name); 1366 free(yav.dims); 1367 if (nerrs > 0) 1368 (void) fprintf(stderr,"FAILED! ***\n"); 1369 else 1370 (void) fprintf(stderr,"ok ***\n"); 1371}