netcdf-c/nc_test4/tst_enums.c
2018-12-06 15:27:32 -07:00

364 lines
13 KiB
C

/* This is part of the netCDF package. Copyright 2018 University
Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
conditions of use. See www.unidata.ucar.edu for more info.
Test netcdf-4 enum types.
Ed Hartnett
*/
#include <nc_tests.h>
#include "err_macros.h"
#include "netcdf.h"
#define FILE_NAME "tst_enums.nc"
#define DIM_LEN 4
#define NUM_MEMBERS 4
#define DIM_NAME "dim"
#define BASE_SIZE 20
#define VAR_NAME "Advice"
#define TYPE_NAME "Mysterous_Word"
int
main(int argc, char **argv)
{
int ncid;
nc_type typeid;
int i;
char name_in[NC_MAX_NAME+1];
int ntypes, typeids[1] = {0};
nc_type base_nc_type, base_nc_type_in;
size_t nfields_in, num_members, base_size_in;
int class_in;
printf("\n*** Testing netcdf-4 enum type.\n");
printf("*** testing creation of enum type...");
{
int value_in;
/* Can't use the same name twice! */
char member_name[NUM_MEMBERS][NC_MAX_NAME + 1] = {"Mene1", "Mene2",
"Tekel", "Upharsin"};
int member_value[NUM_MEMBERS] = {0, 99, 81232, 12};
/* Create a file. */
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
/* Create an enum type. */
if (nc_def_enum(ncid, NC_INT, TYPE_NAME, &typeid)) ERR;
for (i = 0; i < NUM_MEMBERS; i++)
if (nc_insert_enum(ncid, typeid, member_name[i],
&member_value[i])) ERR;
/* Check it out. */
if (nc_inq_user_type(ncid, typeid, name_in, &base_size_in, &base_nc_type_in,
&nfields_in, &class_in)) ERR;
if (strcmp(name_in, TYPE_NAME) || base_size_in != sizeof(int) ||
base_nc_type_in != NC_INT || nfields_in != NUM_MEMBERS || class_in != NC_ENUM) ERR;
if (nc_inq_enum(ncid, typeid, name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
if (strcmp(name_in, TYPE_NAME) || base_nc_type != NC_INT ||
num_members != NUM_MEMBERS) ERR;
for (i = 0; i < NUM_MEMBERS; i++)
{
if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR;
if (strcmp(name_in, member_name[i]) || value_in != member_value[i]) ERR;
if (nc_inq_enum_ident(ncid, typeid, member_value[i], name_in)) ERR;
if (strcmp(name_in, member_name[i])) ERR;
}
/* Write the file. */
if (nc_close(ncid)) ERR;
/* Reopen the file. */
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
/* Get type info. */
if (nc_inq_typeids(ncid, &ntypes, typeids)) ERR;
if (ntypes != 1 || !typeids[0]) ERR;
/* Check it out. */
if (nc_inq_user_type(ncid, typeids[0], name_in, &base_size_in, &base_nc_type_in,
&nfields_in, &class_in)) ERR;
if (strcmp(name_in, TYPE_NAME) || base_size_in != sizeof(int) ||
base_nc_type_in != NC_INT || nfields_in != NUM_MEMBERS || class_in != NC_ENUM) ERR;
if (nc_inq_type(ncid, typeids[0], name_in, &base_size_in)) ERR;
if (strcmp(name_in, TYPE_NAME) || base_size_in != sizeof(int)) ERR;
if (nc_inq_enum(ncid, typeids[0], name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
if (strcmp(name_in, TYPE_NAME) || base_nc_type != NC_INT || num_members != NUM_MEMBERS) ERR;
for (i = 0; i < NUM_MEMBERS; i++)
{
if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR;
if (strcmp(name_in, member_name[i]) || value_in != member_value[i]) ERR;
if (nc_inq_enum_ident(ncid, typeid, member_value[i], name_in)) ERR;
if (strcmp(name_in, member_name[i])) ERR;
}
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
#define NUM_BRADYS 9
#define BRADYS "Bradys"
#define BRADY_DIM_LEN 3
#define ATT_NAME "brady_attribute"
printf("*** testing enum attribute...");
{
char brady_name[NUM_BRADYS][NC_MAX_NAME + 1] = {"Mike", "Carol", "Greg", "Marsha",
"Peter", "Jan", "Bobby", "Whats-her-face",
"Alice"};
unsigned char brady_value[NUM_BRADYS] = {8, 7, 6 , 5, 4, 3, 2, 1, 0};
unsigned char data[BRADY_DIM_LEN] = {0, 4, 8};
unsigned char value_in;
/* Create a file. */
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
/* Create an enum type based on unsigned bytes. */
if (nc_def_enum(ncid, NC_UBYTE, BRADYS, &typeid)) ERR;
for (i = 0; i < NUM_BRADYS; i++)
if (nc_insert_enum(ncid, typeid, brady_name[i],
&brady_value[i])) ERR;
/* Check it out. */
if (nc_inq_user_type(ncid, typeid, name_in, &base_size_in, &base_nc_type_in,
&nfields_in, &class_in)) ERR;
if (strcmp(name_in, BRADYS) || base_size_in != 1 ||
base_nc_type_in != NC_UBYTE || nfields_in != NUM_BRADYS || class_in != NC_ENUM) ERR;
if (nc_inq_enum(ncid, typeid, name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
if (strcmp(name_in, BRADYS) || base_nc_type != NC_UBYTE || base_size_in != 1 ||
num_members != NUM_BRADYS) ERR;
for (i = 0; i < NUM_BRADYS; i++)
{
if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR;
if (strcmp(name_in, brady_name[i]) || value_in != brady_value[i]) ERR;
if (nc_inq_enum_ident(ncid, typeid, brady_value[i], name_in)) ERR;
if (strcmp(name_in, brady_name[i])) ERR;
}
/* Write an att of this enum type. */
if (nc_put_att(ncid, NC_GLOBAL, ATT_NAME, typeid, BRADY_DIM_LEN, data)) ERR;
/* Close the file. */
if (nc_close(ncid)) ERR;
/* Reopen. */
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
/* Check it out. */
if (nc_inq_user_type(ncid, typeid, name_in, &base_size_in, &base_nc_type_in,
&nfields_in, &class_in)) ERR;
if (strcmp(name_in, BRADYS) || base_size_in != 1 ||
base_nc_type_in != NC_UBYTE || nfields_in != NUM_BRADYS || class_in != NC_ENUM) ERR;
if (nc_inq_enum(ncid, typeid, name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
if (strcmp(name_in, BRADYS) || base_nc_type != NC_UBYTE || base_size_in != 1 ||
num_members != NUM_BRADYS) ERR;
for (i = 0; i < NUM_BRADYS; i++)
{
if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR;
if (strcmp(name_in, brady_name[i]) || value_in != brady_value[i]) ERR;
if (nc_inq_enum_ident(ncid, typeid, brady_value[i], name_in)) ERR;
if (strcmp(name_in, brady_name[i])) ERR;
}
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
#define TYPE2_NAME "cloud_type"
#define DIM2_NAME "station"
#define DIM2_LEN 5
#define VAR2_NAME "primary_cloud"
#define VAR2_RANK 1
#define ATT2_NAME "_FillValue"
#define ATT2_LEN 1
printf("*** testing enum fill value ...");
{
int dimid, varid;
size_t num_members_in;
int class_in;
unsigned char value_in;
unsigned char att_value_in;
enum clouds { /* a C enumeration */
CLEAR=0,
CUMULONIMBUS=1,
STRATUS=2,
STRATOCUMULUS=3,
CUMULUS=4,
ALTOSTRATUS=5,
NIMBOSTRATUS=6,
ALTOCUMULUS=7,
CIRROSTRATUS=8,
CIRROCUMULUS=9,
CIRRUS=10,
MISSING=255};
struct {
char *name;
unsigned char value;
} cloud_types[] = {
{"Clear", CLEAR},
{"Cumulonimbus", CUMULONIMBUS},
{"Stratus", STRATUS},
{"Stratocumulus", STRATOCUMULUS},
{"Cumulus", CUMULUS},
{"Altostratus", ALTOSTRATUS},
{"Nimbostratus", NIMBOSTRATUS},
{"Altocumulus", ALTOCUMULUS},
{"Cirrostratus", CIRROSTRATUS},
{"Cirrocumulus", CIRROCUMULUS},
{"Cirrus", CIRRUS},
{"Missing", MISSING}
};
int var_dims[VAR2_RANK];
unsigned char att_val;
unsigned char cloud_data[DIM2_LEN] = {
CLEAR, STRATUS, CLEAR, CUMULONIMBUS, MISSING};
unsigned char cloud_data_in[DIM2_LEN];
if (nc_create(FILE_NAME, NC_CLOBBER | NC_NETCDF4, &ncid)) ERR;
/* Create an enum type. */
if (nc_def_enum(ncid, NC_UBYTE, TYPE2_NAME, &typeid)) ERR;
num_members = (sizeof cloud_types) / (sizeof cloud_types[0]);
for (i = 0; i < num_members; i++)
if (nc_insert_enum(ncid, typeid, cloud_types[i].name,
&cloud_types[i].value)) ERR;
/* Declare a station dimension */
if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimid)) ERR;
/* Declare a variable of the enum type */
var_dims[0] = dimid;
if (nc_def_var(ncid, VAR2_NAME, typeid, VAR2_RANK, var_dims, &varid)) ERR;
/* Create and write a variable attribute of the enum type */
att_val = MISSING;
if (nc_put_att(ncid, varid, ATT2_NAME, typeid, ATT2_LEN, &att_val)) ERR;
if (nc_enddef(ncid)) ERR;
/* Store some data of the enum type */
if(nc_put_var(ncid, varid, cloud_data)) ERR;
/* Write the file. */
if (nc_close(ncid)) ERR;
/* Check it out. */
/* Reopen the file. */
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
if (nc_inq_user_type(ncid, typeid, name_in, &base_size_in, &base_nc_type_in,
&nfields_in, &class_in)) ERR;
if (strcmp(name_in, TYPE2_NAME) ||
base_size_in != sizeof(unsigned char) ||
base_nc_type_in != NC_UBYTE ||
nfields_in != num_members ||
class_in != NC_ENUM) ERR;
if (nc_inq_enum(ncid, typeid, name_in,
&base_nc_type_in, &base_size_in, &num_members_in)) ERR;
if (strcmp(name_in, TYPE2_NAME) ||
base_nc_type_in != NC_UBYTE ||
num_members_in != num_members) ERR;
for (i = 0; i < num_members; i++)
{
if (nc_inq_enum_member(ncid, typeid, i, name_in, &value_in)) ERR;
if (strcmp(name_in, cloud_types[i].name) ||
value_in != cloud_types[i].value) ERR;
if (nc_inq_enum_ident(ncid, typeid, cloud_types[i].value,
name_in)) ERR;
if (strcmp(name_in, cloud_types[i].name)) ERR;
}
if (nc_inq_varid(ncid, VAR2_NAME, &varid)) ERR;
if (nc_get_att(ncid, varid, ATT2_NAME, &att_value_in)) ERR;
if (att_value_in != MISSING) ERR;
if(nc_get_var(ncid, varid, cloud_data_in)) ERR;
for (i = 0; i < DIM2_LEN; i++) {
if (cloud_data_in[i] != cloud_data[i]) ERR;
}
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
printf("*** testing enum interuptus...");
{
unsigned char ubyte_value = 42;
#define GEEKY_NAME "Galadriel"
/* Create a file. */
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
/* Create an enum type based on unsigned bytes. */
if (nc_def_enum(ncid, NC_UBYTE, GEEKY_NAME, &typeid)) ERR;
/* Check it out. */
if (nc_inq_user_type(ncid, typeid, name_in, &base_size_in, &base_nc_type_in,
&nfields_in, &class_in)) ERR;
if (strcmp(name_in, GEEKY_NAME) || base_size_in != 1 ||
base_nc_type_in != NC_UBYTE || nfields_in != 0 || class_in != NC_ENUM) ERR;
if (nc_inq_enum(ncid, typeid, name_in, &base_nc_type, &base_size_in, &num_members)) ERR;
if (strcmp(name_in, GEEKY_NAME) || base_nc_type != NC_UBYTE || base_size_in != 1 ||
num_members != 0) ERR;
/* Close the file. */
if (nc_close(ncid) != NC_EINVAL) ERR;
if (nc_redef(ncid)) ERR;
if (nc_insert_enum(ncid, typeid, "name", &ubyte_value)) ERR;
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
printf("*** testing enum ncdump...");
#define ENUM_NAME "cargo"
#define ENUM_VAR_NAME "in_the_hold_of_the_Irish_Rover"
#define NUM_ENUM_FIELDS 8
#define DIMSIZE 4
#define NDIMS1 1
{
int ncid, dimid, v1id, typeid;
int f;
size_t start[NDIMS1] = {0}, count[NDIMS1] = {1};
char field_name[NUM_ENUM_FIELDS][NC_MAX_NAME + 1] = {"bags of the best Sligo rags", "barrels of bones",
"bails of old nanny goats' tails", "barrels of stones",
"dogs", "hogs", "barrels of porter",
"sides of old blind horses hides"};
unsigned long long field_value[NUM_ENUM_FIELDS] = {1000000, 2000000, 3000000, 4000000,
5000000, 6000000, 7000000, 8000000};
unsigned long long data = 1000000, data_in;
/* Create a netcdf-4 file. */
/*nc_set_log_level(3);*/
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
/* Create a dimension. */
if (nc_def_dim(ncid, DIM_NAME, DIMSIZE, &dimid)) ERR;
/* Create an enum type. */
if (nc_def_enum(ncid, NC_UINT64, ENUM_NAME, &typeid)) ERR;
for (f = 0; f < NUM_ENUM_FIELDS; f++)
if (nc_insert_enum(ncid, typeid, field_name[f], &field_value[f])) ERR;
/* Create one var. */
if (nc_def_var(ncid, ENUM_VAR_NAME, typeid, NDIMS1, &dimid, &v1id)) ERR;
/* Write metadata to file. */
if (nc_enddef(ncid)) ERR;
/* Write phoney data. */
if (nc_put_vara(ncid, v1id, start, count, &data)) ERR;
if (nc_sync(ncid)) ERR;
/* Read phoney data. */
if (nc_get_vara(ncid, v1id, start, count, &data_in)) ERR;
if (data_in != data) ERR;
/* Close the netcdf file. */
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
FINAL_RESULTS;
}