netcdf-c/nc_test/tst_names.c
Wei-keng Liao 0ee68a3263 This commit fixes the logical problem of using the default file formats.
The fix includes the following changes.
1. Checking and using the default file format at file create time is now
   done only when the create mode (argument cmode) does not include any
   format related flags, i.e. NC_64BIT_OFFSET, NC_64BIT_DATA,
   NC_CLASSIC_MODEL, and NC_NETCDF4.
2. Adjustment of cmode based on the default format is now done in
   NC_create() only. The idea is to adjust cmode before entering the
   dispatcher's file create subroutine.
3. Any adjustment of cmode is removed from all I/O dispatchers, i.e.
   NC4_create(), NC3_create(), and NCP_create().
4. Checking for illegal cmode has been done in check_create_mode() called
   in NC_create(). This commit removes the redundant checking from
   NCP_create().
5. Remove PnetCDF tests in nc_test/tst_names.c, so it can focus on testing
   all classic formats and netCDF4 formats.

Two new test programs are added. They can be used to test netCDF with and
without this commit.
1. nc_test/tst_default_format.c
2. nc_test/tst_default_format_pnetcdf.c (use when PnetCDF is enabled).
2018-07-28 11:18:28 -05:00

329 lines
9.0 KiB
C

/* This is part of the netCDF package.
Copyright 2006 University Corporation for Atmospheric Research/Unidata.
See COPYRIGHT file for conditions of use.
This is a very simple example which tests rejection of bad names for
netCDF data objects, including names with "/" character, trailing spaces,
leading special characters, and invalid UTF-8 strings.
$Id: tst_names.c 2792 2014-10-27 06:02:59Z wkliao $
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netcdf.h>
#ifdef USE_PARALLEL
#include <netcdf_par.h>
#endif
#include <nc_tests.h>
#include "err_macros.h"
/* The data file we will create. */
#define FILE_NAME "tst_names.nc"
#define NDIMS 1
#define DIMLEN 1
#define ERROR {printf("Error at line %d: %s\n",__LINE__,nc_strerror(res)); nerrs++; continue;}
#define ERRORI {printf("Error at line %d (loop=%d): %s\n",__LINE__,i,nc_strerror(res)); nerrs++; continue;}
int
main(int argc, char **argv)
{
char *valid[] = {
/* pressure in 23 languages */
"\xd8\xa7\xd9\x84\xd8\xb6\xd8\xba\xd8\xb7",
"\xd0\xbd\xd0\xb0\xd0\xbb\xd1\x8f\xd0\xb3\xd0\xb0\xd0\xbd\xd0\xb5",
"\xe5\x8e\x8b\xe5\x8a\x9b",
"\xe5\xa3\x93\xe5\x8a\x9b",
"pritisak",
"tlaku",
"pres",
"druk",
"pressure",
"paine",
"pression",
"Druck",
"\xcf\x80\xce\xaf\xce\xb5\xcf\x83\xce\xb7",
"\xe0\xa4\xa6\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb5",
"pressione",
"\xe5\x9c\xa7\xe5\x8a\x9b",
"\xec\x95\x95\xeb\xa0\xa5",
"press",
"ci\xc5\x9bnienie",
"Press\xc3\xa3o",
"presiune",
"\xd0\xb4\xd0\xb0\xd0\xb2\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5",
"presi\xc3\xb3n",
/* special characters in names, numeric characters at the start of names */
"has blank",
"has:colon",
"a",
"A",
"0leading_numeric_char",
"1",
"0x123"
};
char *notvalid[] = {
"-leading_special_char",
"trailing_space ",
"trailing_tab\t",
"trailing_newline\n",
"has_control_char_\a_in_name",
"has ascii_del_\x7f_in name",
/* Invalid UTF-8 of various sorts, thanks to Markus Kuhn */
"\xA0\xB0\xC0\xD0",
"xyz\x80", /* unexpected continuation bytes */
"\x80xyz",
"xyz\xBF",
"\xBFxyz",
"\xC0xyz", /* lonely start characters */
"x\xC0yz",
"xy\xC0z",
"xyz\xC0",
"\xDFxyz",
"x\xDFyz",
"xy\xDFz",
"xyz\xDF",
"\xE0xyz",
"x\xE0yz",
"xy\xE0z",
"xyz\xE0",
"\xE0\xBFxy",
"x\xE0\xBFy",
"xy\xE0\xBF",
"\xEFxyz",
"x\xEFyz",
"xy\xEFz",
"xyz\xEF",
"\xEF\x80xy",
"x\xEF\x80y",
"xy\xEF\x80",
"\xF0xyz",
"x\xF0yz",
"xy\xF0z",
"xyz\xF0",
"\xF7xyz",
"x\xF7yz",
"xy\xF7z",
"xyz\xF7",
"\xF8xyz",
"x\xF8yz",
"xy\xF8z",
"xyz\xF8",
"\xFBxyz",
"x\xFByz",
"xy\xFBz",
"xyz\xFB",
"\xFCxyz",
"x\xFCyz",
"xy\xFCz",
"xyz\xFC",
"\xFDxyz",
"x\xFDyz",
"xy\xFDz",
"xyz\xFD",
"\xC0\xC0xy", /* last continuation byte missing */
"x\xC0\xC0y",
"xy\xC0\xC0",
"\xDF\xDFxy",
"x\xDF\xDFy",
"xy\xDF\xDF",
"\xE0\x80xy",
"x\xE0\x80y",
"xy\xE0\x80",
"\xEF\x80xy",
"x\xEF\x80y",
"xy\xEF\x80",
"\xF0\x80\x80x",
"x\xF0\x80\x80",
"\xF7\x80\x80x",
"x\xF7\x80\x80",
"\xF8\x80\x80\x80x",
"x\xF8\x80\x80\x80",
"\xFB\x80\x80\x80x",
"x\xFB\x80\x80\x80",
"\xFC\x80\x80\x80\x80x",
"x\xFC\x80\x80\x80\x80",
"\xFD\x80\x80\x80\x80x",
"x\xFD\x80\x80\x80\x80",
"\xFExyz", /* impossible bytes */
"x\xFEyz",
"xy\xFEz",
"xyz\xFE",
"\xFFxyz",
"x\xFFyz",
"xy\xFFz",
"xyz\xFF",
"\xC0\xAFxy", /* overlong sequences */
"x\xC0\xAFy",
"xy\xC0\xAF",
"\xE0\x80\xAFx",
"x\xE0\x80\xAF",
"\xF0\x80\x80\xAFx",
"x\xF0\x80\x80\xAF",
"\xF8\x80\x80\x80\xAFx",
"x\xF8\x80\x80\x80\xAF",
"\xFC\x80\x80\x80\x80\xAFx",
"x\xFC\x80\x80\x80\x80\xAF",
"\xC1\xBFxy",
"x\xC1\xBFy",
"xy\xC1\xBF",
"\xE0\x9F\xBFx",
"x\xE0\x9F\xBF",
"\xF0\x8F\xBF\xBFx",
"x\xF0\x8F\xBF\xBF",
"\xF8\x87\xBF\xBF\xBFx",
"x\xF8\x87\xBF\xBF\xBF",
"\xFC\x83\xBF\xBF\xBF\xBFx",
"x\xFC\x83\xBF\xBF\xBF\xBF",
"x\xC0\x80", /* overlong NULs */
"x\xE0\x80\x80",
"x\xF0\x80\x80\x80",
"x\xF8\x80\x80\x80\x80",
"x\xFC\x80\x80\x80\x80\x80",
/* single UTF-16 surrogates */
"x\xED\xA0\x80",
"x\xED\xAD\xBF",
"x\xED\xAE\x80",
"x\xED\xAF\xBF",
"x\xED\xB0\x80",
"x\xED\xBE\x80",
"x\xED\xBF\xBF",
"x\xED\xA0\x80\xED\xB0\x80", /* paired UTF-16 surrogates */
"x\xED\xA0\x80\xED\xBF\xBF",
"x\xED\xAD\xBF\xED\xB0\x80",
"x\xED\xAD\xBF\xED\xBF\xBF",
"x\xED\xAE\x80\xED\xB0\x80",
"x\xED\xAE\x80\xED\xBF\xBF",
"x\xED\xAF\xBF\xED\xB0\x80",
"x\xED\xAF\xBF\xED\xBF\xBF"
#if 0
/* The two below is legal since UTF8PROC_VERSION_MAJOR 2 */
"x\xEF\xBF\xBE", /* other illegal code positions */
"x\xEF\xBF\xBF"
#endif
};
int nerrs=0;
int i, j;
#define NUM_BAD (sizeof notvalid / sizeof notvalid[0])
#define NUM_GOOD (sizeof valid / sizeof valid[0])
int ncid, dimid, varid, res;
double attvals[] = {-2.0};
double attvals_in[1];
#define NATTVALS (sizeof attvals / sizeof attvals[0])
char *attstring = "text";
#define MAX_ATTSTRING_LEN 100
char attstr_in[MAX_ATTSTRING_LEN];
int dimids[NUM_GOOD];
int varids[NUM_GOOD];
#if 0
int attnums[NUM_GOOD];
#endif
char *testfile = FILE_NAME;
int formats[] = {
NC_FORMAT_CLASSIC
,
NC_FORMAT_64BIT_OFFSET
#ifdef ENABLE_CDF5
,
NC_FORMAT_CDF5
#endif
#ifdef USE_NETCDF4
,
NC_FORMAT_NETCDF4
,
NC_FORMAT_NETCDF4_CLASSIC
#endif /* USE_NETCDF4 */
};
int num_formats = (sizeof formats) / (sizeof formats[0]);
char *format_names[] = {
"classic", "64-bit offset", "64-bit data", "netCDF-4/HDF5", "netCDF-4 classic model"
};
printf("\n*** testing names with file %s...\n", testfile);
for (j = 0; j < num_formats; j++)
{
printf("*** switching to netCDF %s format...", format_names[j]);
nc_set_default_format(formats[j], NULL);
if((res = nc_create(testfile, NC_CLOBBER, &ncid)))
ERROR
/* Define dimensions, variables, and attributes with various
* acceptable names */
for (i = 0; i < NUM_GOOD; i++) {
if ((res = nc_def_dim(ncid, valid[i], DIMLEN, &dimid)))
ERRORI
dimids[i] = dimid;
/* Define variable with same name */
if ((res = nc_def_var(ncid, valid[i], NC_FLOAT, NDIMS, &dimids[i],
&varid)))
ERRORI
varids[i] = varid;
/* Define variable and global attributes with same name and value */
if ((res = nc_put_att_text(ncid, varid, valid[i],
strlen(valid[i]), valid[i])))
ERRORI
if ((res = nc_put_att_double(ncid, NC_GLOBAL, valid[i], NC_DOUBLE,
NATTVALS, attvals)))
ERRORI
#if 0
attnums[i] = i;
#endif
}
/* Try defining dimensions, variables, and attributes with various
* bad names and make sure these are rejected */
for (i = 0; i < NUM_BAD; i++) {
if ((res = nc_def_dim(ncid, notvalid[i], DIMLEN, &dimid))
!= NC_EBADNAME) ERRORI
if ((res = nc_def_var(ncid, notvalid[i], NC_FLOAT, NDIMS, dimids,
&varid))
!= NC_EBADNAME) ERRORI
if ((res = nc_put_att_text(ncid, varid, notvalid[i],
strlen(attstring), attstring))
!= NC_EBADNAME) ERRORI
if ((res = nc_put_att_double(ncid, NC_GLOBAL, notvalid[i], NC_DOUBLE,
NATTVALS, attvals))
!= NC_EBADNAME) ERRORI
}
if ((res = nc_enddef(ncid)))
ERROR
if ((res = nc_close(ncid)))
ERROR
/* Check it out, make sure all objects with good names were defined OK */
if ((res = nc_open(testfile, NC_NOWRITE, &ncid)))
ERROR
for (i = 0; i < NUM_GOOD; i++) {
size_t attlen;
if ((res = nc_inq_dimid(ncid, valid[i], &dimid)) ||
dimid != dimids[i])
ERRORI
if ((res = nc_inq_varid(ncid, valid[i], &varid)) ||
varid != varids[i])
ERRORI
res = nc_inq_attlen(ncid, varid, valid[i], &attlen);
if ((res = nc_get_att_text(ncid, varid, valid[i], attstr_in)))
ERRORI
attstr_in[attlen] = '\0';
if (strcmp(valid[i], attstr_in) != 0)
ERRORI
if ((res = nc_get_att_double(ncid, NC_GLOBAL, valid[i],
attvals_in))
|| attvals[0] != attvals_in[0])
ERRORI
}
if ((res = nc_close(ncid)))
ERROR
/* (void) remove(testfile); */
SUMMARIZE_ERR;
}
total_err += nerrs;
FINAL_RESULTS;
return 0;
}