netcdf-c/dap4_test/test_common.h
Dennis Heimbigner 245961de00 re: github issues
https://github.com/Unidata/netcdf-c/issues/1168
    https://github.com/Unidata/netcdf-c/issues/1163
    https://github.com/Unidata/netcdf-c/issues/1162

This PR partially fixes memory leaks in the netcdf-c library,
in the ncdump utility, and in some test cases.

The netcdf-c library now runs memory clean with the assumption
that the --disable-utilities option is used. The primary remaining
problem is ncgen. Once that is fixed, I believe the netcdf-c library
will run memory clean with no limitations.

Notes
-----------
1. Memory checking was performed using gcc -fsanitize=address.
   Valgrind-based testing has yet to be performed.
2. The pnetcdf, hdf4, and examples code has not been tested.

Misc. Non-leak changes
1. Make tst_diskless2 only run when netcdf4 is enabled (issue 1162)
2. Fix CmakeLists.txt to turn off logging if ENABLE_NETCDF_4 is OFF
3. Isolated all my debug scripts into a single top-level directory
   called debug
4. Fix some USE_NETCDF4 dependencies in nc_test and nc_test4 Makefile.am
2018-10-30 20:48:12 -06:00

188 lines
4.3 KiB
C

/*********************************************************************
* Copyright 2016, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
*********************************************************************/
/* Define various things common to all the t_dmr*.c testers */
#undef DEBUG
#undef DUMP
#include "d4includes.h"
#ifdef DEBUG
#include "ezxml.h"
#endif
typedef int TDMR;
#define TDMR_PARSE 1
#define TDMR_META 2
#define TDMR_DATA 4
static NCbytes* input = NULL;
static NCbytes* output = NULL;
static NCD4meta* metadata = NULL;
static char* infile = NULL;
static char* outfile = NULL;
static int ncid = 0;
static int translatenc4 = 0;
static int
readfile(const char* filename, NCbytes* content)
{
FILE* stream;
char part[1024];
stream = fopen(filename,"r");
if(stream == NULL) return errno;
for(;;) {
size_t count = fread(part, 1, sizeof(part), stream);
if(count <= 0) break;
ncbytesappendn(content,part,count);
if(ferror(stream)) {fclose(stream); return NC_EIO;}
if(feof(stream)) break;
}
ncbytesnull(content);
fclose(stream);
return NC_NOERR;
}
static void
fail(int code)
{
if(code != NC_NOERR)
fprintf(stderr,"***Fail: %s\n",nc_strerror(code));
exit((code==NC_NOERR?EXIT_SUCCESS:EXIT_FAILURE));
}
static void
setup(int tdmr, int argc, char** argv)
{
int ret = NC_NOERR;
argc--; argv++;
int expected = 0;
NCD4mode mode = 0;
switch(tdmr) {
case TDMR_PARSE:
expected = 1;
mode = NCD4_DMR;
break;
case TDMR_META:
expected = 2;
mode = NCD4_DMR;
break;
case TDMR_DATA:
fprintf(stderr,"setup is not used for t_dmrdata\n");
mode = NCD4_DAP;
exit(1);
}
if(argc < expected) {
fprintf(stderr, "too few arguments\n");
exit(1);
}
infile = argv[0];
outfile = NULL;
input = ncbytesnew();
output = ncbytesnew();
if((ret = readfile(infile,input))) fail(ret);
{
const char* trans = getenv("translatenc4");
if(trans != NULL)
translatenc4 = 1;
}
#ifdef DUMP
NCD4_dumpbytes(ncbyteslength(input),ncbytescontents(input),0);
#endif
if((metadata=NCD4_newmeta(ncbyteslength(input),ncbytescontents(input)))==NULL)
fail(NC_ENOMEM);
metadata->mode = mode;
/* Create a fake NCD4INFO */
{
NCD4INFO* controller = (NCD4INFO*)calloc(1,sizeof(NCD4INFO));
if(controller == NULL)
fail(NC_ENOMEM);
metadata->controller = controller;
controller->controls.translation = NCD4_TRANSNC4;
if(translatenc4)
controller->controls.translation = NCD4_TRANSNC4;
NCD4_applyclientparamcontrols(controller);
}
if((ret=NCD4_dechunk(metadata))) /* ok for mode == DMR or mode == DAP */
fail(ret);
#ifdef DEBUG
{
int swap = (metadata->serial.hostbigendian != metadata->serial.remotebigendian);
void* d = metadata->serial.dap;
size_t sz = metadata->serial.dapsize;
fprintf(stderr,"====================\n");
fprintf(stderr,"%s\n",metadata->serial.dmr);
fprintf(stderr,"----------\n");
NCD4_dumpbytes(sz,d,swap);
fprintf(stderr,"====================\n");
fflush(stderr);
}
#endif
if(expected > 1) {
outfile = argv[1];
if((ret = nc_create(outfile,NC_CLOBBER|NC_NETCDF4,&ncid))) fail(ret);
}
#ifdef DEBUG
{
char* tree;
ezxml_t dom = ezxml_parse_str(ncbytescontents(input),ncbyteslength(input));
if(dom == NULL) exit(1);
tree = ezxml_toxml(dom);
fprintf(stderr,"////////////////////\n");
fprintf(stderr,"%s\n",tree);
fprintf(stderr,"////////////////////\n");
}
#endif
{
const char* slevel = getenv("d4loglevel");
int level;
if(slevel != NULL && sscanf(slevel,"%d",&level) == 1) {
nc_set_log_level(level);
}
}
}
int
cleanup(int ret)
{
if(outfile != NULL) {
if(ret != NC_NOERR)
ret = nc_abort(ncid);
else
ret = nc_close(ncid);
}
if(metadata->controller != NULL)
free(metadata->controller);
NCD4_reclaimMeta(metadata);
ncbytesfree(input);
ncbytesfree(output);
if(ret)
fail(ret);
else
exit(EXIT_SUCCESS);
return 0;
}
#if 0
static void
printxml(const char* input)
{
char* tree;
ezxml_t dom = ezxml_parse_str(input,strlen(input));
if(dom == NULL) exit(1);
tree = ezxml_toxml(dom);
fprintf(stderr,"////////////////////\n");
fprintf(stderr,"%s\n",tree);
fprintf(stderr,"////////////////////\n");
}
#endif