2018-01-31 23:44:33 +08:00
|
|
|
/* This is part of the netCDF package. Copyright 2005-2018 University
|
2010-06-03 21:24:43 +08:00
|
|
|
Corporation for Atmospheric Research/Unidata. See COPYRIGHT file
|
|
|
|
for conditions of use.
|
|
|
|
|
2016-10-22 03:24:40 +08:00
|
|
|
Test copy of attributes.
|
2010-06-03 21:24:43 +08:00
|
|
|
|
2018-01-31 23:44:33 +08:00
|
|
|
Ed Hartnett, Denis Heimbigner, Ward Fisher
|
2010-06-03 21:24:43 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <nc_tests.h>
|
2016-10-22 03:24:40 +08:00
|
|
|
#include "err_macros.h"
|
2010-06-03 21:24:43 +08:00
|
|
|
#include "netcdf.h"
|
|
|
|
|
|
|
|
#define FILE_NAME1 "tst_atts2.nc"
|
|
|
|
#define FILE_NAME2 "tst_atts2_2.nc"
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
printf("\n*** Testing netcdf-4 attribute copies.\n");
|
2010-10-09 02:54:53 +08:00
|
|
|
printf("*** testing compound attribute copy to different type of same name...");
|
|
|
|
{
|
|
|
|
#define CMP_NAME1 "Ireland"
|
|
|
|
#define I1_NAME "Cork"
|
|
|
|
#define I2_NAME "Dublin"
|
|
|
|
#define DIM_LEN 3
|
|
|
|
#define ATT_NAME3 "Rain"
|
|
|
|
#define NUM_FILES 2
|
|
|
|
|
|
|
|
int ncid[NUM_FILES], typeid;
|
|
|
|
char file_name[NUM_FILES][NC_MAX_NAME + 1] = {FILE_NAME1, FILE_NAME2};
|
|
|
|
int i;
|
2016-10-22 03:24:40 +08:00
|
|
|
struct s1
|
2010-10-09 02:54:53 +08:00
|
|
|
{
|
|
|
|
int i1;
|
|
|
|
int i2;
|
|
|
|
};
|
|
|
|
struct s1 data[DIM_LEN];
|
|
|
|
struct s2
|
|
|
|
{
|
|
|
|
short i1;
|
|
|
|
int i2;
|
|
|
|
};
|
|
|
|
|
2016-10-22 03:24:40 +08:00
|
|
|
/* Create some phony data. */
|
2010-10-09 02:54:53 +08:00
|
|
|
for (i = 0; i < DIM_LEN; i++)
|
|
|
|
{
|
|
|
|
data[i].i1 = 32768;
|
|
|
|
data[i].i2 = 32767;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create two files with different compound types of the same name. */
|
|
|
|
for (i = 0; i < NUM_FILES; i++)
|
|
|
|
if (nc_create(file_name[i], NC_NETCDF4, &ncid[i])) ERR;
|
|
|
|
|
|
|
|
/* Define s1 in file 1. */
|
|
|
|
if (nc_def_compound(ncid[0], sizeof(struct s1), CMP_NAME1, &typeid)) ERR;
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_insert_compound(ncid[0], typeid, I1_NAME,
|
2010-10-09 02:54:53 +08:00
|
|
|
NC_COMPOUND_OFFSET(struct s1, i1), NC_INT)) ERR;
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_insert_compound(ncid[0], typeid, I2_NAME,
|
2010-10-09 02:54:53 +08:00
|
|
|
NC_COMPOUND_OFFSET(struct s1, i2), NC_INT)) ERR;
|
|
|
|
|
|
|
|
/* Define s2 in file 2, but named the same as s1. */
|
|
|
|
if (nc_def_compound(ncid[1], sizeof(struct s2), CMP_NAME1, &typeid)) ERR;
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_insert_compound(ncid[1], typeid, I1_NAME,
|
2010-10-09 02:54:53 +08:00
|
|
|
NC_COMPOUND_OFFSET(struct s2, i1), NC_SHORT)) ERR;
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_insert_compound(ncid[1], typeid, I2_NAME,
|
2010-10-09 02:54:53 +08:00
|
|
|
NC_COMPOUND_OFFSET(struct s2, i2), NC_INT)) ERR;
|
|
|
|
|
|
|
|
|
|
|
|
/* Write an att in one file. */
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_put_att(ncid[0], NC_GLOBAL, ATT_NAME3, typeid, DIM_LEN,
|
2010-10-09 02:54:53 +08:00
|
|
|
data)) ERR;
|
|
|
|
|
|
|
|
/* Try to copy. It must fail, because the two types are not the
|
|
|
|
* same. */
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_copy_att(ncid[0], NC_GLOBAL, ATT_NAME3, ncid[1],
|
2010-10-09 02:54:53 +08:00
|
|
|
NC_GLOBAL) != NC_EBADTYPE) ERR;
|
|
|
|
|
|
|
|
/* Close the files. */
|
|
|
|
for (i = 0; i < NUM_FILES; i++)
|
|
|
|
if (nc_close(ncid[i])) ERR;
|
|
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
2010-06-03 21:24:43 +08:00
|
|
|
printf("*** testing string attribute copy...");
|
|
|
|
{
|
|
|
|
#define ATT_NAME "Irish_Leader"
|
2016-10-22 03:24:40 +08:00
|
|
|
#define ATT_LEN 1
|
2010-06-03 21:24:43 +08:00
|
|
|
int ncid1, ncid2;
|
|
|
|
const char *mc[ATT_LEN] = {"Michael Collins"};
|
|
|
|
char *mc_in;
|
|
|
|
|
|
|
|
/* Create a file with a string att. */
|
|
|
|
if (nc_create(FILE_NAME1, NC_NETCDF4, &ncid1)) ERR;
|
|
|
|
if (nc_put_att_string(ncid1, NC_GLOBAL, ATT_NAME, ATT_LEN, mc)) ERR;
|
2016-10-22 03:24:40 +08:00
|
|
|
|
2010-06-03 21:24:43 +08:00
|
|
|
/* Create another file, and copy the att. */
|
|
|
|
if (nc_create(FILE_NAME2, NC_NETCDF4, &ncid2)) ERR;
|
2018-01-31 23:44:33 +08:00
|
|
|
|
|
|
|
/* These will not work. */
|
|
|
|
if (nc_copy_att(ncid1 + TEST_VAL_42, NC_GLOBAL, ATT_NAME, ncid2, NC_GLOBAL) != NC_EBADID) ERR;
|
|
|
|
if (nc_copy_att(ncid1, TEST_VAL_42, ATT_NAME, ncid2, NC_GLOBAL) != NC_ENOTVAR) ERR;
|
|
|
|
if (nc_copy_att(ncid1, NC_GLOBAL, NULL, ncid2, NC_GLOBAL) != NC_EBADNAME) ERR;
|
|
|
|
if (nc_copy_att(ncid1, NC_GLOBAL, ATT_NAME, ncid2 + TEST_VAL_42, NC_GLOBAL) != NC_EBADID) ERR;
|
|
|
|
if (nc_copy_att(ncid1, NC_GLOBAL, ATT_NAME, ncid2, TEST_VAL_42) != NC_ENOTVAR) ERR;
|
|
|
|
|
|
|
|
/* Copy the attribute. */
|
2010-06-03 21:24:43 +08:00
|
|
|
if (nc_copy_att(ncid1, NC_GLOBAL, ATT_NAME, ncid2, NC_GLOBAL)) ERR;
|
|
|
|
|
2016-10-22 03:24:40 +08:00
|
|
|
/* Close up. */
|
2010-06-03 21:24:43 +08:00
|
|
|
if (nc_close(ncid1)) ERR;
|
|
|
|
if (nc_close(ncid2)) ERR;
|
|
|
|
|
|
|
|
/* Reopen file 2 and see that attribute is correct. */
|
|
|
|
if (nc_open(FILE_NAME2, 0, &ncid2)) ERR;
|
|
|
|
if (nc_get_att_string(ncid2, NC_GLOBAL, ATT_NAME, &mc_in)) ERR;
|
|
|
|
if (strcmp(mc[0], mc_in)) ERR;
|
|
|
|
if (nc_close(ncid2)) ERR;
|
|
|
|
if (nc_free_string(ATT_LEN, &mc_in)) ERR;
|
|
|
|
|
|
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
|
|
printf("*** testing non-string atomic attribute copy...");
|
|
|
|
{
|
2016-10-22 03:24:40 +08:00
|
|
|
#define ATT_LEN 1
|
2010-06-03 21:24:43 +08:00
|
|
|
#define NUM_ATT 5
|
|
|
|
int ncid1, ncid2;
|
|
|
|
char name[NUM_ATT][NC_MAX_NAME + 1];
|
|
|
|
long long data = 0, data_in[NUM_ATT];
|
|
|
|
int a;
|
|
|
|
|
|
|
|
/* Create a file with non-string atomic atts. */
|
|
|
|
if (nc_create(FILE_NAME1, NC_NETCDF4, &ncid1)) ERR;
|
|
|
|
for (a = 0; a < NUM_ATT; a++)
|
|
|
|
{
|
|
|
|
sprintf(name[a], "atomic_att_type_%d", a + 1);
|
2016-10-22 03:24:40 +08:00
|
|
|
nc_put_att(ncid1, NC_GLOBAL, name[a], a + 1, ATT_LEN,
|
2010-06-03 21:24:43 +08:00
|
|
|
(void *)&data);
|
|
|
|
}
|
2016-10-22 03:24:40 +08:00
|
|
|
|
2010-06-03 21:24:43 +08:00
|
|
|
/* Create another file, and copy the att. */
|
|
|
|
if (nc_create(FILE_NAME2, NC_NETCDF4, &ncid2)) ERR;
|
|
|
|
for (a = 0; a < NUM_ATT; a++)
|
|
|
|
if (nc_copy_att(ncid1, NC_GLOBAL, name[a], ncid2, NC_GLOBAL)) ERR;
|
|
|
|
|
2016-10-22 03:24:40 +08:00
|
|
|
/* Close up. */
|
2010-06-03 21:24:43 +08:00
|
|
|
if (nc_close(ncid1)) ERR;
|
|
|
|
if (nc_close(ncid2)) ERR;
|
|
|
|
|
|
|
|
/* Reopen file 2 and see that attributes are present. */
|
|
|
|
if (nc_open(FILE_NAME2, 0, &ncid2)) ERR;
|
|
|
|
for (a = 0; a < NUM_ATT; a++)
|
|
|
|
nc_get_att(ncid1, NC_GLOBAL, name[a], (void *)&data_in[a]);
|
|
|
|
if (nc_close(ncid2)) ERR;
|
|
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
|
|
printf("*** testing simple compound attribute copy...");
|
|
|
|
{
|
|
|
|
#define CMP_NAME "cmp"
|
|
|
|
#define I1 "i1"
|
|
|
|
#define I2 "i2"
|
|
|
|
#define DIM_LEN 3
|
|
|
|
#define ATT_NAME2 "att"
|
|
|
|
#define NUM_FILES 2
|
|
|
|
|
|
|
|
int ncid[NUM_FILES], typeid;
|
|
|
|
char file_name[NUM_FILES][NC_MAX_NAME + 1] = {FILE_NAME1, FILE_NAME2};
|
|
|
|
int i;
|
2016-10-22 03:24:40 +08:00
|
|
|
struct s1
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
|
|
|
int i1;
|
|
|
|
int i2;
|
|
|
|
};
|
|
|
|
struct s1 data[DIM_LEN], data_in[DIM_LEN];
|
|
|
|
|
2016-10-22 03:24:40 +08:00
|
|
|
/* Create some phony data. */
|
2010-06-03 21:24:43 +08:00
|
|
|
for (i = 0; i < DIM_LEN; i++)
|
|
|
|
{
|
|
|
|
data[i].i1 = 5;
|
|
|
|
data[i].i2 = 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create two files with the same compound type. */
|
|
|
|
for (i = 0; i < NUM_FILES; i++)
|
|
|
|
{
|
|
|
|
if (nc_create(file_name[i], NC_NETCDF4, &ncid[i])) ERR;
|
|
|
|
if (nc_def_compound(ncid[i], sizeof(struct s1), CMP_NAME, &typeid)) ERR;
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_insert_compound(ncid[i], typeid, I1,
|
2010-06-03 21:24:43 +08:00
|
|
|
NC_COMPOUND_OFFSET(struct s1, i1), NC_INT)) ERR;
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_insert_compound(ncid[i], typeid, I2,
|
2010-06-03 21:24:43 +08:00
|
|
|
NC_COMPOUND_OFFSET(struct s1, i2), NC_INT)) ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write an att in one file and copy it. */
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_put_att(ncid[0], NC_GLOBAL, ATT_NAME2, typeid, DIM_LEN,
|
2010-06-03 21:24:43 +08:00
|
|
|
data)) ERR;
|
|
|
|
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_copy_att(ncid[0], NC_GLOBAL, ATT_NAME2, ncid[1],
|
2010-06-03 21:24:43 +08:00
|
|
|
NC_GLOBAL)) ERR;
|
|
|
|
|
|
|
|
/* Close the files. */
|
|
|
|
for (i = 0; i < NUM_FILES; i++)
|
|
|
|
if (nc_close(ncid[i])) ERR;
|
|
|
|
|
|
|
|
/* Open the second file and take a peek. */
|
|
|
|
if (nc_open(FILE_NAME1, NC_WRITE, &ncid[1])) ERR;
|
|
|
|
if (nc_get_att(ncid[1], NC_GLOBAL, ATT_NAME2, data_in)) ERR;
|
|
|
|
|
|
|
|
for (i=0; i<DIM_LEN; i++)
|
|
|
|
if (data[i].i1 != data_in[i].i1 || data[i].i2 != data_in[i].i2) ERR;
|
|
|
|
if (nc_close(ncid[1])) ERR;
|
|
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
|
|
printf("*** testing simple enum attribute copy...");
|
|
|
|
{
|
|
|
|
#define DIM_LEN_10 10
|
|
|
|
#define ATT_NAME2 "att"
|
|
|
|
#define TYPE_NAME "Irish_Province_Type"
|
|
|
|
#define NUM_FILES 2
|
|
|
|
#define NUM_MEMBERS 4
|
|
|
|
|
|
|
|
int ncid[NUM_FILES], typeid;
|
|
|
|
char file_name[NUM_FILES][NC_MAX_NAME + 1] = {FILE_NAME1, FILE_NAME2};
|
2016-10-22 03:24:40 +08:00
|
|
|
char member_name[NUM_MEMBERS][NC_MAX_NAME + 1] = {"Munster", "Connacht",
|
2010-06-03 21:24:43 +08:00
|
|
|
"Leinster", "Ulster"};
|
|
|
|
int member_value[NUM_MEMBERS] = {0, 1, 2, 3};
|
|
|
|
int data_in[DIM_LEN_10], data[DIM_LEN_10] = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1};
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
/* Create two files with the same enum type. */
|
|
|
|
for (i = 0; i < NUM_FILES; i++)
|
|
|
|
{
|
|
|
|
if (nc_create(file_name[i], NC_NETCDF4, &ncid[i])) ERR;
|
|
|
|
if (nc_def_enum(ncid[i], NC_INT, TYPE_NAME, &typeid)) ERR;
|
|
|
|
for (j = 0; j < NUM_MEMBERS; j++)
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_insert_enum(ncid[i], typeid, member_name[j],
|
2010-06-03 21:24:43 +08:00
|
|
|
&member_value[j])) ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write an att in one file and copy it. */
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_put_att(ncid[0], NC_GLOBAL, ATT_NAME2, typeid, DIM_LEN_10,
|
2010-06-03 21:24:43 +08:00
|
|
|
data)) ERR;
|
|
|
|
|
2016-10-22 03:24:40 +08:00
|
|
|
if (nc_copy_att(ncid[0], NC_GLOBAL, ATT_NAME2, ncid[1],
|
2010-06-03 21:24:43 +08:00
|
|
|
NC_GLOBAL)) ERR;
|
|
|
|
|
|
|
|
/* Close the files. */
|
|
|
|
for (i = 0; i < NUM_FILES; i++)
|
|
|
|
if (nc_close(ncid[i])) ERR;
|
|
|
|
|
|
|
|
/* Open the second file and take a peek. */
|
|
|
|
if (nc_open(FILE_NAME1, NC_WRITE, &ncid[1])) ERR;
|
|
|
|
if (nc_get_att(ncid[1], NC_GLOBAL, ATT_NAME2, data_in)) ERR;
|
|
|
|
|
|
|
|
/* Check the data. */
|
|
|
|
for (i = 0; i < DIM_LEN_10; i++)
|
|
|
|
if (data[i] != data_in[i]) ERR;
|
|
|
|
if (nc_close(ncid[1])) ERR;
|
|
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
|
|
FINAL_RESULTS;
|
|
|
|
}
|