PageRenderTime 73ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/utilities/netcdf/src/nctest/atttests.c

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