/********************************************************************* * Copyright 1996, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Id: test_read.c,v 1.32 2008/04/04 20:23:51 dmh Exp $ *********************************************************************/ #include "tests.h" /* * Test nc_strerror. * Try on a bad error status. * Test for each defined error status. */ void test_nc_strerror(void) { int i; const char *message; static const struct { int status; const char *msg; } ncerrs[] = { {NC_NOERR, "No error"}, {NC_EBADID, "NetCDF: Not a valid ID"}, {NC_ENFILE, "NetCDF: Too many files open"}, {NC_EEXIST, "NetCDF: File exists && NC_NOCLOBBER"}, {NC_EINVAL, "NetCDF: Invalid argument"}, {NC_EPERM, "NetCDF: Write to read only"}, {NC_ENOTINDEFINE, "NetCDF: Operation not allowed in data mode"}, {NC_EINDEFINE, "NetCDF: Operation not allowed in define mode"}, {NC_EINVALCOORDS, "NetCDF: Index exceeds dimension bound"}, {NC_EMAXDIMS, "NetCDF: NC_MAX_DIMS exceeded"}, {NC_ENAMEINUSE, "NetCDF: String match to name in use"}, {NC_ENOTATT, "NetCDF: Attribute not found"}, {NC_EMAXATTS, "NetCDF: NC_MAX_ATTRS exceeded"}, {NC_EBADTYPE, "NetCDF: Not a valid data type or _FillValue type mismatch"}, {NC_EBADDIM, "NetCDF: Invalid dimension ID or name"}, {NC_EUNLIMPOS, "NetCDF: NC_UNLIMITED in the wrong index"}, {NC_EMAXVARS, "NetCDF: NC_MAX_VARS exceeded"}, {NC_ENOTVAR, "NetCDF: Variable not found"}, {NC_EGLOBAL, "NetCDF: Action prohibited on NC_GLOBAL varid"}, {NC_ENOTNC, "NetCDF: Unknown file format"}, {NC_ESTS, "NetCDF: In Fortran, string too short"}, {NC_EMAXNAME, "NetCDF: NC_MAX_NAME exceeded"}, {NC_EUNLIMIT, "NetCDF: NC_UNLIMITED size already in use"}, {NC_ENORECVARS, "NetCDF: nc_rec op when there are no record vars"}, {NC_ECHAR, "NetCDF: Attempt to convert between text & numbers"}, {NC_EEDGE, "NetCDF: Start+count exceeds dimension bound"}, {NC_ESTRIDE, "NetCDF: Illegal stride"}, {NC_EBADNAME, "NetCDF: Name contains illegal characters"}, {NC_ERANGE, "NetCDF: Numeric conversion not representable"}, {NC_ENOMEM, "NetCDF: Memory allocation (malloc) failure"}, {NC_EVARSIZE, "NetCDF: One or more variable sizes violate format constraints"}, {NC_EDIMSIZE, "NetCDF: Invalid dimension size"} }; /* Try on a bad error status */ /* Dmh: allow trailing extra info */ message = nc_strerror(-666);/* should fail */ IF (strcmp(message, "Unknown Error") != 0) error("nc_strerror on bad error status returned: %s", message); /* Try on each legitimate error status */ /* Dmh: allow trailing extra info */ for (i=0; i> j) & 1) { start[j] = 0; edge[j] = mid[j]; }else{ start[j] = mid[j]; edge[j] = var_shape[i][j] - mid[j]; } nels *= edge[j]; } if (var_rank[i] == 0 && i%2 ) err = nc_get_vara(ncid, i, NULL, NULL, buf); else err = nc_get_vara(ncid, i, start, edge, buf); IF (err) { error("%s", nc_strerror(err)); } else { for (j = 0; j < nels; j++) { p = (char *) buf; p += j * nctypelen(var_type[i]); err = nc2dbl( var_type[i], p, & got ); IF (err) error("error in nc2dbl"); err = toMixedBase(j, var_rank[i], edge, index); IF (err) error("error in toMixedBase 1"); for (d = 0; d < var_rank[i]; d++) index[d] += start[d]; expect = hash(var_type[i], var_rank[i], index); if (inRange(expect,var_type[i])) { IF (!equal(got,expect,var_type[i],NCT_DOUBLE)) { error("value read not that expected"); if (verbose) { error("\n"); error("varid: %d, ", i); error("var_name: %s, ", var_name[i]); error("element number: %d ", j); error("expect: %g", expect); error("got: %g", got); } } else { nok++; } } } } } } err = nc_close(ncid); IF (err) error("nc_close: %s", nc_strerror(err)); print_nok(nok); } /* * Test nc_get_vars * Choose a random point dividing each dim into 2 parts * Get 2^rank (nslabs) slabs so defined * Each get overwrites buffer, so check after each get. */ void test_nc_get_vars(void) { int ncid; int d; int i; int j; int k; int m; int err; int nels; int nslabs; int nstarts; /* number of different starts */ int nok = 0; /* total count of valid comparisons */ int n; /* count of valid comparisons within var */ size_t start[MAX_RANK]; size_t edge[MAX_RANK]; size_t index[MAX_RANK]; size_t index2[MAX_RANK]; size_t mid[MAX_RANK]; size_t count[MAX_RANK]; size_t sstride[MAX_RANK]; ptrdiff_t stride[MAX_RANK]; double buf[MAX_NELS]; /* (void *) buffer */ char *p; /* (void *) pointer */ double expect; double got; err = nc_open(testfile, NC_NOWRITE, &ncid); IF (err) error("nc_open: %s", nc_strerror(err)); for (i = 0; i < NVARS; i++) { assert(var_rank[i] <= MAX_RANK); assert(var_nels[i] <= MAX_NELS); for (j = 0; j < var_rank[i]; j++) { start[j] = 0; edge[j] = 1; stride[j] = 1; } err = nc_get_vars(BAD_ID, i, start, edge, stride, buf); IF (err != NC_EBADID) error("bad ncid: status = %d", err); err = nc_get_vars(ncid, BAD_VARID, start, edge, stride, buf); IF (err != NC_ENOTVAR) error("bad var id: status = %d", err); for (j = 0; j < var_rank[i]; j++) { start[j] = var_shape[i][j]; err = nc_get_vars(ncid, i, start, edge, stride, buf); IF (err != NC_EINVALCOORDS) error("bad index: status = %d", err); start[j] = 0; edge[j] = var_shape[i][j] + 1; err = nc_get_vars(ncid, i, start, edge, stride, buf); IF (err != NC_EEDGE) error("bad edge: status = %d", err); edge[j] = 1; stride[j] = 0; err = nc_get_vars(ncid, i, start, edge, stride, buf); IF (err != NC_ESTRIDE) error("bad stride: status = %d", err); stride[j] = 1; } /* Choose a random point dividing each dim into 2 parts */ /* get 2^rank (nslabs) slabs so defined */ nslabs = 1; for (j = 0; j < var_rank[i]; j++) { mid[j] = roll( var_shape[i][j] ); nslabs *= 2; } /* bits of k determine whether to get lower or upper part of dim */ /* choose random stride from 1 to edge */ n = 0; for (k = 0; k < nslabs; k++) { nstarts = 1; for (j = 0; j < var_rank[i]; j++) { if ((k >> j) & 1) { start[j] = 0; edge[j] = mid[j]; }else{ start[j] = mid[j]; edge[j] = var_shape[i][j] - mid[j]; } sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; nstarts *= stride[j]; } for (m = 0; m < nstarts; m++) { err = toMixedBase(m, var_rank[i], sstride, index); IF (err) error("error in toMixedBase"); nels = 1; for (j = 0; j < var_rank[i]; j++) { count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; nels *= count[j]; index[j] += start[j]; } /* Random choice of forward or backward */ /* TODO if ( roll(2) ) { for (j = 0; j < var_rank[i]; j++) { index[j] += (count[j] - 1) * stride[j]; stride[j] = -stride[j]; } } */ if (var_rank[i] == 0 && i%2 ) err = nc_get_vars(ncid, i, NULL, NULL, NULL, buf); else err = nc_get_vars(ncid, i, index, count, stride, buf); IF (err) { error("%s", nc_strerror(err)); } else { for (j = 0; j < nels; j++) { p = (char *) buf; p += j * nctypelen(var_type[i]); err = nc2dbl( var_type[i], p, & got ); IF (err) error("error in nc2dbl"); err = toMixedBase(j, var_rank[i], count, index2); IF (err) error("error in toMixedBase 1"); for (d = 0; d < var_rank[i]; d++) index2[d] = index[d] + index2[d] * stride[d]; expect = hash(var_type[i], var_rank[i], index2); if (inRange(expect,var_type[i])) { IF (!equal(got,expect,var_type[i],NCT_DOUBLE)) { error("value read not that expected"); if (verbose) { error("\n"); error("varid: %d, ", i); error("var_name: %s, ", var_name[i]); error("element number: %d ", j); error("expect: %g, ", expect); error("got: %g ", got); } } else { nok++; } } n++; } } } } IF (n != var_nels[i]) { error("count != nels"); if (verbose) { error("\n"); error("varid: %d, ", i); error("var_name: %s, ", var_name[i]); error("count: %d, ", n); error("nels: %d ", var_nels[i]); } } } err = nc_close(ncid); IF (err) error("nc_close: %s", nc_strerror(err)); print_nok(nok); } /* * Test nc_get_varm * Choose a random point dividing each dim into 2 parts * Get 2^rank (nslabs) slabs so defined * Choose random stride from 1 to edge * Buffer should end up being bit image of external variable. * So all gets for a variable store in different elements of buffer */ void test_nc_get_varm(void) { int ncid; int i; int j; int k; int m; int err; int nslabs; int nstarts; /* number of different starts */ int nok = 0; /* total count of valid comparisons */ size_t start[MAX_RANK]; size_t edge[MAX_RANK]; size_t index[MAX_RANK]; size_t mid[MAX_RANK]; size_t count[MAX_RANK]; size_t sstride[MAX_RANK]; ptrdiff_t stride[MAX_RANK]; ptrdiff_t imap[MAX_RANK]; ptrdiff_t imap2[MAX_RANK]; double buf[MAX_NELS]; /* (void *) buffer */ char *p; /* (void *) pointer */ double expect; double got; err = nc_open(testfile, NC_NOWRITE, &ncid); IF (err) error("nc_open: %s", nc_strerror(err)); for (i = 0; i < NVARS; i++) { assert(var_rank[i] <= MAX_RANK); assert(var_nels[i] <= MAX_NELS); for (j = 0; j < var_rank[i]; j++) { start[j] = 0; edge[j] = 1; stride[j] = 1; } if (var_rank[i] > 0) { j = var_rank[i] - 1; imap[j] = nctypelen(var_type[i]); for (; j > 0; j--) imap[j-1] = imap[j] * var_shape[i][j]; } err = nc_get_varm(BAD_ID, i, start, edge, stride, imap, buf); IF (err != NC_EBADID) error("bad ncid: status = %d", err); err = nc_get_varm(ncid, BAD_VARID, start, edge, stride, imap, buf); IF (err != NC_ENOTVAR) error("bad var id: status = %d", err); for (j = 0; j < var_rank[i]; j++) { start[j] = var_shape[i][j]; err = nc_get_varm(ncid, i, start, edge, stride, imap, buf); IF (err != NC_EINVALCOORDS) error("bad index: status = %d", err); start[j] = 0; edge[j] = var_shape[i][j] + 1; err = nc_get_varm(ncid, i, start, edge, stride, imap, buf); IF (err != NC_EEDGE) error("bad edge: status = %d", err); edge[j] = 1; stride[j] = 0; err = nc_get_varm(ncid, i, start, edge, stride, imap, buf); IF (err != NC_ESTRIDE) error("bad stride: status = %d", err); stride[j] = 1; } /* Choose a random point dividing each dim into 2 parts */ /* get 2^rank (nslabs) slabs so defined */ nslabs = 1; for (j = 0; j < var_rank[i]; j++) { mid[j] = roll( var_shape[i][j] ); nslabs *= 2; } /* bits of k determine whether to get lower or upper part of dim */ /* choose random stride from 1 to edge */ for (k = 0; k < nslabs; k++) { nstarts = 1; for (j = 0; j < var_rank[i]; j++) { if ((k >> j) & 1) { start[j] = 0; edge[j] = mid[j]; }else{ start[j] = mid[j]; edge[j] = var_shape[i][j] - mid[j]; } sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1; imap2[j] = imap[j] * sstride[j]; nstarts *= stride[j]; } for (m = 0; m < nstarts; m++) { if (var_rank[i] == 0 && i%2 ) { err = nc_get_varm(ncid, i, NULL, NULL, NULL, NULL, buf); } else { err = toMixedBase(m, var_rank[i], sstride, index); IF (err) error("error in toMixedBase"); for (j = 0; j < var_rank[i]; j++) { count[j] = 1 + (edge[j] - index[j] - 1) / stride[j]; index[j] += start[j]; } /* Random choice of forward or backward */ /* TODO if ( roll(2) ) { for (j = 0; j < var_rank[i]; j++) { index[j] += (count[j] - 1) * stride[j]; stride[j] = -stride[j]; } } */ j = fromMixedBase(var_rank[i], index, var_shape[i]); p = (char *) buf + j * nctypelen(var_type[i]); err = nc_get_varm(ncid, i, index, count, stride, imap2, p); } IF (err) error("%s", nc_strerror(err)); } } p = (char *) buf; for (j = 0; j < var_nels[i]; j++) { err = toMixedBase(j, var_rank[i], var_shape[i], index); IF (err) error("error in toMixedBase"); expect = hash( var_type[i], var_rank[i], index); err = nc2dbl( var_type[i], p, & got ); IF (err) error("error in nc2dbl"); if (inRange(expect,var_type[i])) { IF (!equal(got,expect,var_type[i],NCT_DOUBLE)) { error("value read not that expected"); if (verbose) { error("\n"); error("varid: %d, ", i); error("var_name: %s, ", var_name[i]); error("element number: %d ", j); error("expect: %g, ", expect); error("got: %g ", got); } } else { nok++; } } p += nctypelen(var_type[i]); } } err = nc_close(ncid); IF (err) error("nc_close: %s", nc_strerror(err)); print_nok(nok); } void test_nc_get_att(void) { int ncid; int i; int j; size_t k; int err; double buf[MAX_NELS]; /* (void *) buffer */ char *p; /* (void *) pointer */ double expect; double got; int nok = 0; /* count of valid comparisons */ err = nc_open(testfile, NC_NOWRITE, &ncid); IF (err) error("nc_open: %s", nc_strerror(err)); for (i = -1; i < NVARS; i++) { for (j = 0; j < NATTS(i); j++) { err = nc_get_att(BAD_ID, i, ATT_NAME(i,j), buf); IF (err != NC_EBADID) error("bad ncid: status = %d", err); err = nc_get_att(ncid, BAD_VARID, ATT_NAME(i,j), buf); IF (err != NC_ENOTVAR) error("bad var id: status = %d", err); err = nc_get_att(ncid, i, "noSuch", buf); IF (err != NC_ENOTATT) error("Bad attribute name: status = %d", err); err = nc_get_att(ncid, i, ATT_NAME(i,j), buf); IF (err) { error("%s", nc_strerror(err)); } else { for (k = 0; k < ATT_LEN(i,j); k++) { expect = hash(ATT_TYPE(i,j), -1, &k ); p = (char *) buf; p += k * nctypelen(ATT_TYPE(i,j)); err = nc2dbl( ATT_TYPE(i,j), p, &got ); IF (err) error("error in nc2dbl"); if (inRange(expect,ATT_TYPE(i,j))) { IF (!equal(got,expect,ATT_TYPE(i,j),NCT_DOUBLE)) { error("value read not that expected"); if (verbose) { error("\n"); error("varid: %d, ", i); error("var_name: %s, ", i >= 0 ? var_name[i] : "Global"); error("att_name: %s, ", ATT_NAME(i,j)); error("element number: %d\n", k); error("expect: %-23.16e\n", expect); error(" got: %-23.16e", got); } } else { nok++; } } } } } } err = nc_close(ncid); IF (err) error("nc_close: %s", nc_strerror(err)); print_nok(nok); } void test_nc_inq_att(void) { int ncid; int i; int j; int err; nc_type t; size_t n; err = nc_open(testfile, NC_NOWRITE, &ncid); IF (err) error("nc_open: %s", nc_strerror(err)); for (i = -1; i < NVARS; i++) { for (j = 0; j < NATTS(i); j++) { err = nc_inq_att(BAD_ID, i, ATT_NAME(i,j), &t, &n); IF (err != NC_EBADID) error("bad ncid: status = %d", err); err = nc_inq_att(ncid, BAD_VARID, ATT_NAME(i,j), &t, &n); IF (err != NC_ENOTVAR) error("bad var id: status = %d", err); err = nc_inq_att(ncid, i, "noSuch", &t, &n); IF (err != NC_ENOTATT) error("Bad attribute name: status = %d", err); err = nc_inq_att(ncid, i, ATT_NAME(i,j), &t, &n); IF (err) { error("%s", nc_strerror(err)); } else { IF (t != ATT_TYPE(i,j)) error("type not that expected"); IF (n != ATT_LEN(i,j)) error("length not that expected"); } } } err = nc_close(ncid); IF (err) error("nc_close: %s", nc_strerror(err)); } void test_nc_inq_attlen(void) { int ncid; int i; int j; int err; size_t len; err = nc_open(testfile, NC_NOWRITE, &ncid); IF (err) error("nc_open: %s", nc_strerror(err)); for (i = -1; i < NVARS; i++) { err = nc_inq_attlen(ncid, i, "noSuch", &len); IF (err != NC_ENOTATT) error("Bad attribute name: status = %d", err); for (j = 0; j < NATTS(i); j++) { err = nc_inq_attlen(BAD_ID, i, ATT_NAME(i,j), &len); IF (err != NC_EBADID) error("bad ncid: status = %d", err); err = nc_inq_attlen(ncid, BAD_VARID, ATT_NAME(i,j), &len); IF (err != NC_ENOTVAR) error("bad varid: status = %d", err); err = nc_inq_attlen(ncid, i, ATT_NAME(i,j), &len); IF (err) { error("%s", nc_strerror(err)); } else { IF (len != ATT_LEN(i,j)) error("len not that expected"); } } } err = nc_close(ncid); IF (err) error("nc_close: %s", nc_strerror(err)); } void test_nc_inq_atttype(void) { int ncid; int i; int j; int err; nc_type datatype; err = nc_open(testfile, NC_NOWRITE, &ncid); IF (err) error("nc_open: %s", nc_strerror(err)); for (i = -1; i < NVARS; i++) { err = nc_inq_atttype(ncid, i, "noSuch", &datatype); IF (err != NC_ENOTATT) error("Bad attribute name: status = %d", err); for (j = 0; j < NATTS(i); j++) { err = nc_inq_atttype(BAD_ID, i, ATT_NAME(i,j), &datatype); IF (err != NC_EBADID) error("bad ncid: status = %d", err); err = nc_inq_atttype(ncid, BAD_VARID, ATT_NAME(i,j), &datatype); IF (err != NC_ENOTVAR) error("bad varid: status = %d", err); err = nc_inq_atttype(ncid, i, ATT_NAME(i,j), &datatype); IF (err) { error("%s", nc_strerror(err)); } else { IF (datatype != ATT_TYPE(i,j)) error("type not that expected"); } } } err = nc_close(ncid); IF (err) error("nc_close: %s", nc_strerror(err)); } void test_nc_inq_attname(void) { int ncid; int i; int j; int err; char name[NC_MAX_NAME]; err = nc_open(testfile, NC_NOWRITE, &ncid); IF (err) error("nc_open: %s", nc_strerror(err)); for (i = -1; i < NVARS; i++) { err = nc_inq_attname(ncid, i, BAD_ATTNUM, name); IF (err != NC_ENOTATT) error("Bad attribute number: status = %d", err); err = nc_inq_attname(ncid, i, NATTS(i), name); IF (err != NC_ENOTATT) error("Bad attribute number: status = %d", err); for (j = 0; j < NATTS(i); j++) { err = nc_inq_attname(BAD_ID, i, j, name); IF (err != NC_EBADID) error("bad ncid: status = %d", err); err = nc_inq_attname(ncid, BAD_VARID, j, name); IF (err != NC_ENOTVAR) error("bad var id: status = %d", err); err = nc_inq_attname(ncid, i, j, name); IF (err) { error("%s", nc_strerror(err)); } else { IF (strcmp(ATT_NAME(i,j), name) != 0) error("name not that expected"); } } } err = nc_close(ncid); IF (err) error("nc_close: %s", nc_strerror(err)); } void test_nc_inq_attid(void) { int ncid; int i; int j; int err; int attnum; err = nc_open(testfile, NC_NOWRITE, &ncid); IF (err) error("nc_open: %s", nc_strerror(err)); for (i = -1; i < NVARS; i++) { err = nc_inq_attid(ncid, i, "noSuch", &attnum); IF (err != NC_ENOTATT) error("Bad attribute name: status = %d", err); for (j = 0; j < NATTS(i); j++) { err = nc_inq_attid(BAD_ID, i, ATT_NAME(i,j), &attnum); IF (err != NC_EBADID) error("bad ncid: status = %d", err); err = nc_inq_attid(ncid, BAD_VARID, ATT_NAME(i,j), &attnum); IF (err != NC_ENOTVAR) error("bad varid: status = %d", err); err = nc_inq_attid(ncid, i, ATT_NAME(i,j), &attnum); IF (err) { error("%s", nc_strerror(err)); } else { IF (attnum != j) error("attnum not that expected"); } } } err = nc_close(ncid); IF (err) error("nc_close: %s", nc_strerror(err)); }