From 5c0dd4d6d4b1540e8f28004815720d907b1a9411 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Wed, 31 Mar 2021 11:27:27 +0200 Subject: [PATCH 1/9] Adds fuzz target for oss-fuzz integration --- CMakeLists.txt | 2 ++ fuzz/CMakeLists.txt | 4 ++++ fuzz/fuzz_open.c | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 fuzz/CMakeLists.txt create mode 100644 fuzz/fuzz_open.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 804be33f0..fe4352056 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2243,6 +2243,8 @@ IF(ENABLE_TESTS) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ncdap_test/pingurl.c ${CMAKE_CURRENT_BINARY_DIR}/dap4_test/pingurl4.c @ONLY NEWLINE_STYLE LF) ENDIF() +add_subdirectory(fuzz) + #### # Export files #### diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt new file mode 100644 index 000000000..abfc4719d --- /dev/null +++ b/fuzz/CMakeLists.txt @@ -0,0 +1,4 @@ +if(DEFINED ENV{LIB_FUZZING_ENGINE}) + add_executable(fuzz_open fuzz_open.c) + target_link_libraries(fuzz_open netcdf $ENV{LIB_FUZZING_ENGINE}) +endif() diff --git a/fuzz/fuzz_open.c b/fuzz/fuzz_open.c new file mode 100644 index 000000000..7691c2f5c --- /dev/null +++ b/fuzz/fuzz_open.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include +#include + +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int ncid; + if (nc_open_mem("/tmp/fuzz.nc", 0, Size, (void *) Data, &ncid) == NC_NOERR) { + nc_close(ncid); + } + return 0; +} + From a71e777c56375d55af48151ed821b33bff81590a Mon Sep 17 00:00:00 2001 From: Edward Hartnett Date: Tue, 18 May 2021 10:41:59 -0600 Subject: [PATCH 2/9] improved program nc_perf/tst_gfs_data_1.c --- nc_perf/tst_gfs_data_1.c | 205 +++++++++++++++++++++++++-------------- 1 file changed, 132 insertions(+), 73 deletions(-) diff --git a/nc_perf/tst_gfs_data_1.c b/nc_perf/tst_gfs_data_1.c index 00c74ba54..2d5c95272 100644 --- a/nc_perf/tst_gfs_data_1.c +++ b/nc_perf/tst_gfs_data_1.c @@ -13,38 +13,54 @@ Ed Hartnett, 6/28/20 */ +#include #include #include #include /* Extra high precision time info. */ #include "err_macros.h" #include +#include +#include +#include +#include +#include +#include -#define FILE_NAME "tst_gfs_data_1.nc" +#define TEST_NAME "tst_gfs_data_1" #define NUM_META_VARS 7 #define NUM_META_TRIES 2 #define NDIM2 2 #define NDIM4 4 #define NDIM5 5 #define NUM_PROC 4 -#define NUM_SHUFFLE_SETTINGS 2 -#ifdef HAVE_H5Z_SZIP -#define NUM_COMPRESSION_FILTERS 2 -#else -#define NUM_COMPRESSION_FILTERS 1 -#endif +#define NUM_SHUFFLE_SETTINGS 1 +/* #define NUM_DEFLATE_LEVELS 3 */ #define NUM_DEFLATE_LEVELS 3 #define NUM_UNLIM_TRIES 1 #define THOUSAND 1000 -#define NUM_DATA_VARS 10 +#define NUM_DATA_VARS 3 #define ERR_AWFUL 1 +/* #define USE_SMALL 1 */ + +#ifdef USE_SMALL +#define GRID_XT_LEN 8 +#define GRID_YT_LEN 4 +#define PFULL_LEN 4 +#define PHALF_LEN 5 +#else #define GRID_XT_LEN 3072 #define GRID_YT_LEN 1536 #define PFULL_LEN 127 #define PHALF_LEN 128 +#endif /* USE_SMALL */ #define TIME_LEN 1 +#define MAX_COMPRESSION_FILTERS 4 +char compression_filter_name[MAX_COMPRESSION_FILTERS][NC_MAX_NAME + 1]; +int deflate_level[MAX_COMPRESSION_FILTERS][NUM_DEFLATE_LEVELS]; + char dim_name[NDIM5][NC_MAX_NAME + 1] = {"grid_xt", "grid_yt", "pfull", "phalf", "time"}; char var_name[NUM_META_VARS][NC_MAX_NAME + 1] = {"grid_xt", "lon", "grid_yt", @@ -171,7 +187,6 @@ write_meta(int ncid, int *data_varid, int s, int f, int deflate, int u, int varid[NUM_META_VARS]; double value_time = 2.0; int dv; - int res; /* Turn off fill mode. */ if (nc_set_fill(ncid, NC_NOFILL, NULL)) ERR; @@ -275,21 +290,15 @@ write_meta(int ncid, int *data_varid, int s, int f, int deflate, int u, if (nc_def_var(ncid, data_var_name, NC_FLOAT, NDIM4, dimid_data, &data_varid[dv])) ERR; /* Setting any filter only will work for HDF5-1.10.3 and later */ - /* versions. */ - if (!f) - res = nc_def_var_deflate(ncid, data_varid[dv], s, 1, deflate); - else - { - res = nc_def_var_deflate(ncid, data_varid[dv], s, 0, 0); - if (!res) - res = nc_def_var_szip(ncid, data_varid[dv], 32, 32); - } -#ifdef HDF5_SUPPORTS_PAR_FILTERS - if (res) ERR; -#else - if (res != NC_EINVAL) ERR; -#endif - + /* versions. Do nothing for "none". */ + if (!strcmp(compression_filter_name[f], "zlib")) + if (nc_def_var_deflate(ncid, data_varid[dv], s, 1, deflate)) ERR; + +#if NC_HAS_SZIP_WRITE + if (!strcmp(compression_filter_name[f], "szip")) + if (nc_def_var_szip(ncid, data_varid[dv], 32, 32)) ERR; +#endif /* NC_HAS_SZIP_WRITE */ + if (nc_var_par_access(ncid, data_varid[dv], NC_COLLECTIVE)) ERR; if (nc_enddef(ncid)) ERR; } @@ -356,9 +365,8 @@ decomp_latlon(int my_rank, int mpi_size, int *dim_len, size_t *latlon_start, latlon_start[1] = dim_len[1]/2; } } - else if (mpi_size == 36) - { - } + else + return ERR_AWFUL; /* Allocate storage. */ if (!(*lon = malloc(latlon_count[0] * latlon_count[1] * sizeof(double)))) ERR; @@ -374,8 +382,8 @@ decomp_latlon(int my_rank, int mpi_size, int *dim_len, size_t *latlon_start, } } - printf("%d: latlon_start %ld %ld latlon_count %ld %ld\n", my_rank, latlon_start[0], - latlon_start[1], latlon_count[0], latlon_count[1]); + /* printf("%d: latlon_start %ld %ld latlon_count %ld %ld\n", my_rank, latlon_start[0], */ + /* latlon_start[1], latlon_count[0], latlon_count[1]); */ return 0; } @@ -385,9 +393,11 @@ decomp_latlon(int my_rank, int mpi_size, int *dim_len, size_t *latlon_start, int decomp_4D(int my_rank, int mpi_size, int *dim_len, size_t *start, size_t *count) { + /* Time dimension. */ start[0] = 0; count[0] = 1; + /* Vertical dimension (pfull). */ count[1] = dim_len[2]; start[1] = 0; @@ -395,36 +405,28 @@ decomp_4D(int my_rank, int mpi_size, int *dim_len, size_t *start, size_t *count) { start[2] = 0; start[3] = 0; - count[2] = dim_len[2]; - count[3] = dim_len[3]; + count[2] = dim_len[1]; + count[3] = dim_len[0]; } else if (mpi_size == 4) { - if (my_rank == 0 || my_rank == 1) - { - start[2] = 0; - start[3] = 0; - } - else - { - start[2] = 768; - start[3] = 768; - } +#ifdef USE_SMALL + start[2] = (my_rank < 2) ? 0 : 2; + start[3] = (!my_rank || my_rank == 2) ? 0 : 4; + count[2] = 2; + count[3] = 4; +#else + start[2] = (my_rank < 2) ? 0 : 768; + start[3] = (!my_rank || my_rank == 2) ? 0 : 1536; count[2] = 768; count[3] = 1536; - } - else if (mpi_size == 36) - { - start[2] = my_rank * 256; - start[3] = my_rank * 512; - count[2] = 256; - count[3] = 512; +#endif /* USE_SMALL */ } else return ERR_AWFUL; - printf("%d: start %ld %ld %ld %ld count %ld %ld %ld %ld\n", my_rank, start[0], - start[1], start[2], start[3], count[0], count[1], count[2], count[3]); + /* printf("%d: start %ld %ld %ld %ld count %ld %ld %ld %ld\n", my_rank, start[0], */ + /* start[1], start[2], start[3], count[0], count[1], count[2], count[3]); */ return 0; } @@ -495,6 +497,34 @@ decomp_p(int my_rank, int mpi_size, size_t *data_count, int *dim_len, return 0; } +/* Determine what compression filters are present. */ +int +find_filters(int *num_compression_filters, char compression_filter_name[][NC_MAX_NAME + 1], + int deflate_level[][NUM_DEFLATE_LEVELS]) +{ + int nfilters = 0; + + /* Try with no compression. */ + strcpy(compression_filter_name[nfilters], "none"); + nfilters++; + + /* zlib is always present. */ + strcpy(compression_filter_name[nfilters], "zlib"); + deflate_level[nfilters][0] = 1; + deflate_level[nfilters][1] = 4; + deflate_level[nfilters][2] = 9; + nfilters++; + + /* szip is optionally present. */ +#if NC_HAS_SZIP_WRITE + strcpy(compression_filter_name[nfilters], "szip"); + nfilters++; +#endif /* NC_HAS_SZIP_WRITE */ + + *num_compression_filters = nfilters; + return 0; +} + int main(int argc, char **argv) { @@ -524,16 +554,23 @@ main(int argc, char **argv) double *lon = NULL; double *lat = NULL; float *value_data; - int deflate_level[NUM_DEFLATE_LEVELS] = {1, 4, 9}; + + /* Compression filter info. */ + int num_compression_filters; int f, s, u; int i, j, k, dv, dl; + int ret; /* Initialize MPI. */ MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); + /* Determine what compression filters are present. */ + if ((ret = find_filters(&num_compression_filters, compression_filter_name, deflate_level))) + return ret; + /* Determine 4D data decomposition to write data vars. */ if (decomp_4D(my_rank, mpi_size, dim_len, data_start, data_count)) ERR; @@ -548,42 +585,60 @@ main(int argc, char **argv) /* Decompose phalf and pfull. */ if (decomp_p(my_rank, mpi_size, data_count, dim_len, &phalf_start, &phalf_size, &phalf, &pfull_start, &pfull_size, &pfull)) ERR; + + /* printf("%d: data_count[3] %ld data_count[2] %ld data_count[1] %ld\n", my_rank, */ + /* data_count[3], data_count[2], data_count[1]); */ /* Allocate space to hold the data. */ if (!(value_data = malloc(data_count[3] * data_count[2] * data_count[1] * sizeof(float)))) ERR; /* Create some data. */ + size_t cnt = 0; for (k = 0; k < data_count[1]; k++) + { for (j = 0; j < data_count[2]; j++) + { for(i = 0; i < data_count[3]; i++) - value_data[j * data_count[3] + i] = my_rank * 100 + i + j + k; + { + value_data[cnt] = my_rank * 1000 + cnt / sqrt(my_rank + cnt + 1); + /* printf("%d: value_data[%ld] %g\n", my_rank, cnt, value_data[cnt]); */ + cnt++; + } + } + } if (my_rank == 0) { - printf("Benchmarking creation of UFS file.\n"); + printf("Benchmarking creation of file similar to one produced by the UFS.\n"); printf("unlim, comp, level, shuffle, meta wr time (s), data wr rate (MB/s), " "file size (MB)\n"); } for (u = 0; u < NUM_UNLIM_TRIES; u++) { - for (f = 0; f < NUM_COMPRESSION_FILTERS; f++) + for (f = 0; f < num_compression_filters; f++) { for (s = 0; s < NUM_SHUFFLE_SETTINGS; s++) { for (dl = 0; dl < NUM_DEFLATE_LEVELS; dl++) { size_t file_size; + char file_name[NC_MAX_NAME * 3 + 1]; - /* No deflate levels for szip. */ - if (f && dl) continue; + /* No deflate levels for szip or none. */ + if (!strcmp(compression_filter_name[f], "szip") && dl) continue; + if (!strcmp(compression_filter_name[f], "none") && dl) continue; + + /* Use the same filename every time, so we don't + * create many large files, just one. ;-) */ + sprintf(file_name, "%s.nc", TEST_NAME); /* nc_set_log_level(3); */ /* Create a parallel netcdf-4 file. */ meta_start_time = MPI_Wtime(); - if (nc_create_par(FILE_NAME, NC_NETCDF4, comm, info, + if (nc_create_par(file_name, NC_NETCDF4, comm, info, &ncid)) ERR; - if (write_meta(ncid, data_varid, s, f, deflate_level[dl], u, + if (write_meta(ncid, data_varid, s, f, deflate_level[f][dl], u, phalf_size, phalf_start, phalf, data_start, data_count, pfull_start, pfull_size, pfull, grid_xt_start, grid_xt_size, grid_xt, grid_yt_start, @@ -598,8 +653,11 @@ main(int argc, char **argv) /* Write one record each of the data variables. */ for (dv = 0; dv < NUM_DATA_VARS; dv++) { - if (nc_put_vara_float(ncid, data_varid[dv], data_start, - data_count, value_data)) ERR; + /* printf("%d: data_start %ld %ld %ld %ld data_count %ld %ld %ld %ld\n", my_rank, data_start[0], data_start[1], */ + /* data_start[2], data_start[3], data_count[0], data_count[1], data_count[2], data_count[3]); */ + /* MPI_Barrier(MPI_COMM_WORLD); */ + if (nc_put_vara_float(ncid, data_varid[dv], data_start, data_count, + value_data)) ERR; if (nc_redef(ncid)) ERR; } @@ -611,28 +669,29 @@ main(int argc, char **argv) data_stop_time = MPI_Wtime(); /* Get the file size. */ - if (get_file_size(FILE_NAME, &file_size)) ERR; + if (get_file_size(file_name, &file_size)) ERR; /* Check the file metadata for correctness. */ - if (nc_open_par(FILE_NAME, NC_NOWRITE, comm, info, &ncid)) ERR; - if (check_meta(ncid, data_varid, s, f, deflate_level[dl], u, - phalf_size, phalf_start, phalf, - data_start, data_count, pfull_start, pfull_size, - pfull, grid_xt_start, grid_xt_size, grid_xt, - grid_yt_start, grid_yt_size, grid_yt, latlon_start, - latlon_count, lat, lon, my_rank)) ERR; + if (nc_open_par(file_name, NC_NOWRITE, comm, info, &ncid)) ERR; + if (check_meta(ncid, data_varid, s, f, deflate_level[f][dl], u, + phalf_size, phalf_start, phalf, + data_start, data_count, pfull_start, pfull_size, + pfull, grid_xt_start, grid_xt_size, grid_xt, + grid_yt_start, grid_yt_size, grid_yt, latlon_start, + latlon_count, lat, lon, my_rank)) ERR; if (nc_close(ncid)) ERR; /* Print out results. */ if (my_rank == 0) { float data_size, data_rate; - data_size = NUM_DATA_VARS * dim_len[0] * dim_len[1] * - dim_len[3] * sizeof(float)/1000000; + data_size = (NUM_DATA_VARS * dim_len[0] * dim_len[1] * dim_len[2] * + dim_len[4] * sizeof(float))/MILLION; + /* printf("data_size %f (data_stop_time - data_start_time) %g\n", data_size, (data_stop_time - data_start_time)); */ data_rate = data_size / (data_stop_time - data_start_time); - printf("%d %s, %d, %d, %g, %g, %g\n", u, (f ? "szip" : "zlib"), - deflate_level[dl], s, meta_stop_time - meta_start_time, - data_rate, (float)file_size/1000000); + printf("%d, %s, %d, %d, %g, %g, %g\n", u, compression_filter_name[f], + deflate_level[f][dl], s, meta_stop_time - meta_start_time, + data_rate, (float)file_size/MILLION); } MPI_Barrier(MPI_COMM_WORLD); } /* next deflate level */ From e755a08f11dc7a3b31039a912334505bdd90ecd8 Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Wed, 2 Jun 2021 11:40:01 -0600 Subject: [PATCH 3/9] Simply version check logic We use the CMake `VERSION_LESS` test other places, might as well use it here and eliminate another compile-based test. --- CMakeLists.txt | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d999a1458..061606fd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -802,19 +802,11 @@ IF(USE_HDF5) # Check to see if HDF5 library is 1.10.6 or greater. # Used to control path name conversion - # Check HDF5 version - SET(HDF5_UTF8_PATHS OFF) - CHECK_C_SOURCE_COMPILES(" - #include - int main() { -#if (H5_VERS_MAJOR*10000 + H5_VERS_MINOR*100 + H5_VERS_RELEASE < 11006) - choke me; -#endif - }" HDF5_VERSION_1106) - - IF(HDF5_VERSION_1106) - SET(HDF5_UTF8_PATHS ON) - ENDIF(HDF5_VERSION_1106) + IF(${HDF5_VERSION} VERSION_GREATER "1.10.5") + SET(HDF5_UTF8_PATHS ON) + ELSE() + SET(HDF5_UTF8_PATHS OFF) + ENDIF() MESSAGE("-- Checking for HDF5 version 1.10.6 or later: ${HDF5_UTF8_PATHS}") From 477c4de95b33883b1370cd94069805e5914ea29e Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Wed, 2 Jun 2021 12:54:05 -0600 Subject: [PATCH 4/9] Clean up curl symbol tests * Set `CMAKE_REQUIRED_INCLUDES` to include the path found for `curl.h`. The `CHECK_C_SOURCE_COMPILES` function uses this and not the `INCLUDE_DIRECTORIES` * Make the test for version 7.66 or later match the same test in `configure.ac` * If the version is 7.66 or later, then we can skip the tests for the curl symbols which were all added in versions prior to 7.66. * If the version is earlier than 7.66, then continue to perform the tests. --- CMakeLists.txt | 100 ++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d999a1458..a58313884 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -858,57 +858,71 @@ ELSE() SET(FOUND_CURL FALSE) ENDIF() -# Check to see if CURLOPT_USERNAME is defined. -# It is present starting version 7.19.1. -CHECK_C_SOURCE_COMPILES(" -#include -int main() {int x = CURLOPT_USERNAME;}" HAVE_CURLOPT_USERNAME) - -# Check to see if CURLOPT_PASSWORD is defined. -# It is present starting version 7.19.1. -CHECK_C_SOURCE_COMPILES(" -#include -int main() {int x = CURLOPT_PASSWORD;}" HAVE_CURLOPT_PASSWORD) - -# Check to see if CURLOPT_KEYPASSWD is defined. -# It is present starting version 7.16.4. -CHECK_C_SOURCE_COMPILES(" -#include -int main() {int x = CURLOPT_KEYPASSWD;}" HAVE_CURLOPT_KEYPASSWD) - -# Check to see if CURLINFO_RESPONSE_CODE is defined. -# It showed up in curl 7.10.7. -CHECK_C_SOURCE_COMPILES(" -#include -int main() {int x = CURLINFO_RESPONSE_CODE;}" HAVE_CURLINFO_RESPONSE_CODE) - -# Check to see if CURLINFO_HTTP_CONNECTCODE is defined. -# It showed up in curl 7.10.7. -CHECK_C_SOURCE_COMPILES(" -#include -int main() {int x = CURLINFO_HTTP_CONNECTCODE;}" HAVE_CURLINFO_HTTP_CONNECTCODE) - -# Check to see if CURLOPT_BUFFERSIZE is defined. -# It is present starting version 7.59 -CHECK_C_SOURCE_COMPILES(" -#include -int main() {int x = CURLOPT_BUFFERSIZE;}" HAVE_CURLOPT_BUFFERSIZE) - -# Check to see if CURLOPT_TCP_KEEPALIVE is defined. -# It is present starting version 7.25 -CHECK_C_SOURCE_COMPILES(" -#include -int main() {int x = CURLOPT_TCP_KEEPALIVE;}" HAVE_CURLOPT_KEEPALIVE) - +set (CMAKE_REQUIRED_INCLUDES ${CURL_INCLUDE_DIRS}) # Check to see if we have libcurl 7.66 or later CHECK_C_SOURCE_COMPILES(" #include int main() { -#if (LIBCURL_VERSION_MAJOR*1000 + LIBCURL_VERSION_MINOR < 7066) +#if LIBCURL_VERSION_NUM < 0x074200 choke me; #endif }" HAVE_LIBCURL_766) +IF (HAVE_LIBCURL_766) + # If libcurl version is >= 7.66, then can skip tests + # for these symbols which were added in an earlier version + set(HAVE_CURLOPT_USERNAME TRUE) + set(HAVE_CURLOPT_PASSWORD TRUE) + set(HAVE_CURLOPT_KEYPASSWD TRUE) + set(HAVE_CURLINFO_RESPONSE_CODE TRUE) + set(HAVE_CURLINFO_HTTP_CONNECTCODE TRUE) + set(HAVE_CURLOPT_BUFFERSIZE TRUE) + set(HAVE_CURLOPT_KEEPALIVE TRUE) + MESSAGE("-- Skipping CURL tests: ${HAVE_LIBCURL_766}") +ELSE() + # Check to see if CURLOPT_USERNAME is defined. + # It is present starting version 7.19.1. + CHECK_C_SOURCE_COMPILES(" + #include + int main() {int x = CURLOPT_USERNAME;}" HAVE_CURLOPT_USERNAME) + + # Check to see if CURLOPT_PASSWORD is defined. + # It is present starting version 7.19.1. + CHECK_C_SOURCE_COMPILES(" + #include + int main() {int x = CURLOPT_PASSWORD;}" HAVE_CURLOPT_PASSWORD) + + # Check to see if CURLOPT_KEYPASSWD is defined. + # It is present starting version 7.16.4. + CHECK_C_SOURCE_COMPILES(" + #include + int main() {int x = CURLOPT_KEYPASSWD;}" HAVE_CURLOPT_KEYPASSWD) + + # Check to see if CURLINFO_RESPONSE_CODE is defined. + # It showed up in curl 7.10.7. + CHECK_C_SOURCE_COMPILES(" + #include + int main() {int x = CURLINFO_RESPONSE_CODE;}" HAVE_CURLINFO_RESPONSE_CODE) + + # Check to see if CURLINFO_HTTP_CONNECTCODE is defined. + # It showed up in curl 7.10.7. + CHECK_C_SOURCE_COMPILES(" + #include + int main() {int x = CURLINFO_HTTP_CONNECTCODE;}" HAVE_CURLINFO_HTTP_CONNECTCODE) + + # Check to see if CURLOPT_BUFFERSIZE is defined. + # It is present starting version 7.59 + CHECK_C_SOURCE_COMPILES(" + #include + int main() {int x = CURLOPT_BUFFERSIZE;}" HAVE_CURLOPT_BUFFERSIZE) + + # Check to see if CURLOPT_TCP_KEEPALIVE is defined. + # It is present starting version 7.25 + CHECK_C_SOURCE_COMPILES(" + #include + int main() {int x = CURLOPT_TCP_KEEPALIVE;}" HAVE_CURLOPT_KEEPALIVE) +ENDIF() + IF(ENABLE_DAP) SET(USE_DAP ON CACHE BOOL "") SET(ENABLE_DAP2 ON CACHE BOOL "") From 31f0c80adec5c59e8d21cfc407d430f2d7337f13 Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Wed, 2 Jun 2021 12:55:36 -0600 Subject: [PATCH 5/9] Remove a debug print --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a58313884..78ccde7e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -878,7 +878,6 @@ IF (HAVE_LIBCURL_766) set(HAVE_CURLINFO_HTTP_CONNECTCODE TRUE) set(HAVE_CURLOPT_BUFFERSIZE TRUE) set(HAVE_CURLOPT_KEEPALIVE TRUE) - MESSAGE("-- Skipping CURL tests: ${HAVE_LIBCURL_766}") ELSE() # Check to see if CURLOPT_USERNAME is defined. # It is present starting version 7.19.1. From 4a18f6b54ea06513774ce426bab3b7770bcda092 Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Wed, 2 Jun 2021 12:55:50 -0600 Subject: [PATCH 6/9] Remove a debug print From 1c3e86440ea17828709be544625da88d7c6a891e Mon Sep 17 00:00:00 2001 From: Dennis Heimbigner Date: Sat, 5 Jun 2021 14:12:21 -0600 Subject: [PATCH 7/9] NCZarr is outputting fill value as an array instead of a singleton. re: https://github.com/Unidata/netcdf-c/issues/2008 The fill_value key in a .zarray should have a single value, but it currently has a value that is a 1 element array. Fix is to pull out the single element. This occurred because the fill_value is taken from the _FillValue attribute, and all netcdf attributes are stored as arrays, of length 1 in this case. In a related change, any attribute with length 1 is now stored in .zattrs as a singleton rather than an array of length 1. This make the generated Zarr more consistent with other Zarr implementations. Misc. other changes: 1. Fix bug in testpathcvt caused by the way various shells handle backslash escapes. 2. Fix bug in testauth where test for MSVC is wrong. --- libnczarr/zcvt.c | 13 ++++-- libnczarr/zsync.c | 70 +++++++++++++++++++------------- ncdap_test/pathcvt.c | 26 ++++++------ ncdap_test/ref_pathcvt.txt | 81 +++++++++++++++++--------------------- ncdap_test/testauth.sh | 2 +- ncdap_test/testpathcvt.sh | 30 +++++++------- 6 files changed, 117 insertions(+), 105 deletions(-) diff --git a/libnczarr/zcvt.c b/libnczarr/zcvt.c index 9e263f081..cb0d388cb 100644 --- a/libnczarr/zcvt.c +++ b/libnczarr/zcvt.c @@ -324,8 +324,12 @@ NCZ_stringconvert(nc_type typeid, size_t len, void* data0, NCjson** jdatap) /* Create a string valued json object */ if((stat = NCJnewstringn(NCJ_STRING,len,src,&jdata))) goto done; - } else { /* for all other values, create an array of values */ - if((stat = NCJnew(NCJ_ARRAY,&jdata))) goto done; + } else { /* all other cases */ + if(len == 0) {stat = NC_EINVAL; goto done;} + if(len > 1) { + if((stat = NCJnew(NCJ_ARRAY,&jdata))) goto done; + } else /* return a singletone */ + jdata = NULL; for(i=0;ivalue = str; str = NULL; - nclistpush(jdata->contents,jvalue); + if(len == 1) + jdata = jvalue; + else + nclistpush(jdata->contents,jvalue); jvalue = NULL; src += typelen; } diff --git a/libnczarr/zsync.c b/libnczarr/zsync.c index 410c44bb7..83913214c 100644 --- a/libnczarr/zsync.c +++ b/libnczarr/zsync.c @@ -15,7 +15,7 @@ static int ncz_jsonize_atts(NCindex* attlist, NCjson** jattrsp); static int load_jatts(NCZMAP* map, NC_OBJ* container, NCjson** jattrsp, NClist** atypes); static int zconvert(nc_type typeid, size_t typelen, void* dst, NCjson* src); static int computeattrinfo(const char* name, NClist* atypes, NCjson* values, - nc_type* typeidp, size_t* lenp, void** datap); + nc_type* typeidp, size_t* typelenp, size_t* lenp, void** datap); static int parse_group_content(NCjson* jcontent, NClist* dimdefs, NClist* varnames, NClist* subgrps); static int parse_group_content_pure(NCZ_FILE_INFO_T* zinfo, NC_GRP_INFO_T* grp, NClist* varnames, NClist* subgrps); static int define_grp(NC_FILE_INFO_T* file, NC_GRP_INFO_T* grp); @@ -28,7 +28,7 @@ static int locategroup(NC_FILE_INFO_T* file, size_t nsegs, NClist* segments, NC_ static int createdim(NC_FILE_INFO_T* file, const char* name, size64_t dimlen, NC_DIM_INFO_T** dimp); static int parsedimrefs(NC_FILE_INFO_T*, NClist* dimnames, size64_t* shape, NC_DIM_INFO_T** dims, int create); static int decodeints(NCjson* jshape, size64_t* shapes); -static int computeattrdata(nc_type* typeidp, NCjson* values, size_t* lenp, void** datap); +static int computeattrdata(nc_type* typeidp, NCjson* values, size_t* typelenp, size_t* lenp, void** datap); static int inferattrtype(NCjson* values, nc_type* typeidp); static int mininttype(unsigned long long u64, int negative); static int computedimrefs(NC_FILE_INFO_T* file, NC_VAR_INFO_T* var, int purezarr, int xarray, int ndims, NClist* dimnames, size64_t* shapes, NC_DIM_INFO_T** dims); @@ -244,6 +244,7 @@ ncz_sync_var(NC_FILE_INFO_T* file, NC_VAR_INFO_T* var) NCjson* jncvar = NULL; NCjson* jdimrefs = NULL; NCjson* jtmp = NULL; + NCjson* jfill = NULL; size64_t shape[NC_MAX_VAR_DIMS]; NCZ_VAR_INFO_T* zvar = var->format_var_info; @@ -325,7 +326,6 @@ ncz_sync_var(NC_FILE_INFO_T* file, NC_VAR_INFO_T* var) if(!var->no_fill) { int fillsort; int atomictype = var->type_info->hdr.id; - NCjson* jfill = NULL; /* A scalar value providing the default value to use for uninitialized portions of the array, or ``null`` if no fill_value is to be used. */ /* Use the defaults defined in netdf.h */ @@ -339,9 +339,17 @@ ncz_sync_var(NC_FILE_INFO_T* file, NC_VAR_INFO_T* var) if((stat = nc4_get_default_fill_value(atomictype,var->fill_value))) goto done; } /* Convert var->fill_value to a string */ - if((stat = NCZ_stringconvert(atomictype,1,var->fill_value,&jfill))) - goto done; - if((stat = NCJinsert(jvar,"fill_value",jfill))) goto done; + if((stat = NCZ_stringconvert(atomictype,1,var->fill_value,&jfill))) goto done; + if(jfill->sort == NCJ_ARRAY) { /* stringconvert should prevent this from happening */ + assert(NCJlength(jfill) > 0); + if((stat = NCJarrayith(jfill,0,&jtmp))) goto done; /* use the 0th element */ + if((stat = NCJclone(jtmp,&jtmp))) goto done; /* clone so we can free it later */ + NCJreclaim(jfill); + jfill = jtmp; + jtmp = NULL; + } + if((stat = NCJinsert(jvar,"fill_value",jfill))) goto done; + jfill = NULL; } /* order key */ @@ -463,6 +471,7 @@ done: NCJreclaim(jvar); NCJreclaim(jncvar); NCJreclaim(jtmp); + NCJreclaim(jfill); return THROW(stat); } @@ -683,6 +692,8 @@ done: /** @internal Convert a list of attributes to corresponding json. Note that this does not push to the file. +Also note that attributes of length 1 are stored as singletons, not arrays. +This is to be more consistent with pure zarr. @param attlist - [in] the attributes to dictify @param jattrsp - [out] the json'ized att list @return NC_NOERR @@ -858,11 +869,11 @@ Extract type and data for an attribute */ static int computeattrinfo(const char* name, NClist* atypes, NCjson* values, - nc_type* typeidp, size_t* lenp, void** datap) + nc_type* typeidp, size_t* typelenp, size_t* lenp, void** datap) { int stat = NC_NOERR; int i; - size_t len; + size_t len, typelen; void* data; nc_type typeid; @@ -880,10 +891,11 @@ computeattrinfo(const char* name, NClist* atypes, NCjson* values, } if(typeid >= NC_STRING) {stat = NC_EINTERNAL; goto done;} - if((stat = computeattrdata(&typeid, values, &len, &data))) goto done; + if((stat = computeattrdata(&typeid, values, &typelen, &len, &data))) goto done; if(typeidp) *typeidp = typeid; if(lenp) *lenp = len; + if(typelenp) *typelenp = typelen; if(datap) {*datap = data; data = NULL;} done: @@ -895,7 +907,7 @@ done: Extract data for an attribute */ static int -computeattrdata(nc_type* typeidp, NCjson* values, size_t* lenp, void** datap) +computeattrdata(nc_type* typeidp, NCjson* values, size_t* typelenp, size_t* lenp, void** datap) { int stat = NC_NOERR; size_t datalen; @@ -911,7 +923,7 @@ computeattrdata(nc_type* typeidp, NCjson* values, size_t* lenp, void** datap) /* Collect the length of the attribute; might be a singleton */ switch (values->sort) { - case NCJ_DICT: stat = NC_EINTERNAL; goto done; + case NCJ_DICT: stat = NC_ENCZARR; goto done; case NCJ_ARRAY: datalen = nclistlength(values->contents); break; @@ -923,21 +935,22 @@ computeattrdata(nc_type* typeidp, NCjson* values, size_t* lenp, void** datap) break; } - /* Allocate data space */ - if((stat = NC4_inq_atomic_type(typeid, NULL, &typelen))) - goto done; - if(typeid == NC_CHAR) - data = malloc(typelen*(datalen+1)); - else - data = malloc(typelen*datalen); - if(data == NULL) - {stat = NC_ENOMEM; goto done;} - - /* convert to target type */ - if((stat = zconvert(typeid, typelen, data, values))) - goto done; - + if(datalen > 0) { + /* Allocate data space */ + if((stat = NC4_inq_atomic_type(typeid, NULL, &typelen))) + goto done; + if(typeid == NC_CHAR) + data = malloc(typelen*(datalen+1)); + else + data = malloc(typelen*datalen); + if(data == NULL) + {stat = NC_ENOMEM; goto done;} + /* convert to target type */ + if((stat = zconvert(typeid, typelen, data, values))) + goto done; + } if(lenp) *lenp = datalen; + if(typelenp) *typelenp = typelen; if(datap) {*datap = data; data = NULL;} if(typeidp) *typeidp = typeid; /* return possibly inferred type */ @@ -982,7 +995,7 @@ inferattrtype(NCjson* value, nc_type* typeidp) typeid = NC_CHAR; break; default: - return NC_EINTERNAL; + return NC_ENCZARR; } if(typeidp) *typeidp = typeid; return NC_NOERR; @@ -1203,7 +1216,7 @@ ncz_read_atts(NC_FILE_INFO_T* file, NC_OBJ* container) /* Create the attribute */ /* Collect the attribute's type and value */ if((stat = computeattrinfo(key->value,atypes,value, - &typeid,&len,&data))) + &typeid,NULL,&len,&data))) goto done; if((stat = ncz_makeattr(container,attlist,key->value,typeid,len,data,&att))) goto done; @@ -1430,9 +1443,10 @@ define_vars(NC_FILE_INFO_T* file, NC_GRP_INFO_T* grp, NClist* varnames) if(jvalue == NULL) var->no_fill = 1; else { + size_t fvlen; typeid = var->type_info->hdr.id; var->no_fill = 0; - if((stat = computeattrdata(&typeid, jvalue, NULL, &var->fill_value))) + if((stat = computeattrdata(&typeid, jvalue, NULL, &fvlen, &var->fill_value))) goto done; assert(typeid == var->type_info->hdr.id); /* Note that we do not create the _FillValue diff --git a/ncdap_test/pathcvt.c b/ncdap_test/pathcvt.c index d85e0564f..58f854b17 100755 --- a/ncdap_test/pathcvt.c +++ b/ncdap_test/pathcvt.c @@ -27,10 +27,11 @@ /* Synopsis -pathcvt [-u|-w|-m|-c] [-e] PATH +pathcvt [-u|-w|-m|-c] [-e] [-d ] PATH Options -e add backslash escapes to '\' and ' ' + -d use driveletter when needed; defaults to 'c' Output type options: -u convert to Unix form of path -w convert to Windows form of path @@ -45,7 +46,8 @@ Default is to convert to the format used by the platform. struct Options { int target; - int escape; + int escapes; + int drive; int debug; } cvtoptions; @@ -60,11 +62,13 @@ main(int argc, char** argv) char* inpath; memset((void*)&cvtoptions,0,sizeof(cvtoptions)); + cvtoptions.drive = 'c'; - while ((c = getopt(argc, argv, "cD:ehmuw")) != EOF) { + while ((c = getopt(argc, argv, "cD:d:ehmuw")) != EOF) { switch(c) { case 'c': cvtoptions.target = NCPD_CYGWIN; break; - case 'e': cvtoptions.escape = 1; break; + case 'd': cvtoptions.drive = optarg[0]; break; + case 'e': cvtoptions.escapes = 1; break; case 'h': usage(NULL); break; case 'm': cvtoptions.target = NCPD_MSYS; break; case 'u': cvtoptions.target = NCPD_NIX; break; @@ -90,8 +94,8 @@ main(int argc, char** argv) if(cvtoptions.target == NCPD_UNKNOWN) cvtpath = NCpathcvt(inpath); else - cvtpath = NCpathcvt_test(inpath,cvtoptions.target,'c'); - if(cvtpath && cvtoptions.escape) { + cvtpath = NCpathcvt_test(inpath,cvtoptions.target,(char)cvtoptions.drive); + if(cvtpath && cvtoptions.escapes) { char* path = cvtpath; cvtpath = NULL; cvtpath = escape(path); free(path); @@ -116,20 +120,16 @@ escape(const char* path) const char* p; char* q; char* epath = NULL; + const char* escapes = " \\"; epath = (char*)malloc((2*slen) + 1); if(epath == NULL) usage("out of memtory"); p = path; q = epath; for(;*p;p++) { - switch (*p) { - case '\\': case ' ': + if(strchr(escapes,*p) != NULL) *q++ = '\\'; - /* fall thru */ - default: - *q++ = *p; - break; - } + *q++ = *p; } *q = '\0'; return epath; diff --git a/ncdap_test/ref_pathcvt.txt b/ncdap_test/ref_pathcvt.txt index 1398eb14f..a883135c2 100644 --- a/ncdap_test/ref_pathcvt.txt +++ b/ncdap_test/ref_pathcvt.txt @@ -1,45 +1,36 @@ -path: /xxx/a/b - /xxx/a/b - /cygdrive/c/xxx/a/b - /c/xxx/a/b - c:\\xxx\\a\\b -path: d:/x/y - /d/x/y - /cygdrive/d/x/y - /d/x/y - d:\\x\\y -path: /cygdrive/d/x/y - /d/x/y - /cygdrive/d/x/y - /d/x/y - d:\\x\\y -path: /d/x/y - /d/x/y - /cygdrive/d/x/y - /d/x/y - d:\\x\\y -path: /cygdrive/d - /d - /cygdrive/d - /d - d: -path: /d - /d - /cygdrive/d - /d - d: -path: /cygdrive/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn - /d/git/netcdf-c/dap4_test/test_anon_dim.2.syn - /cygdrive/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn - /d/git/netcdf-c/dap4_test/test_anon_dim.2.syn - d:\\git\\netcdf-c\\dap4_test\\test_anon_dim.2.syn -path: d:\x\y - /d/x/y - /cygdrive/d/x/y - /d/x/y - d:\\x\\y -path: d:\x\y w\z - /d/x/y w/z - /cygdrive/d/x/y w/z - /d/x/y w/z - d:\\x\\y\\ w\\z +path: -u: |/xxx/x/y| => |/xxx/x/y| +path: -c: |/xxx/x/y| => |/cygdrive/c/xxx/x/y| +path: -m: |/xxx/x/y| => |/c/xxx/x/y| +path: -w: |/xxx/x/y| => |c:\\xxx\\x\\y| +path: -u: |d:/x/y| => |/d/x/y| +path: -c: |d:/x/y| => |/cygdrive/d/x/y| +path: -m: |d:/x/y| => |/d/x/y| +path: -w: |d:/x/y| => |d:\\x\\y| +path: -u: |/cygdrive/d/x/y| => |/d/x/y| +path: -c: |/cygdrive/d/x/y| => |/cygdrive/d/x/y| +path: -m: |/cygdrive/d/x/y| => |/d/x/y| +path: -w: |/cygdrive/d/x/y| => |d:\\x\\y| +path: -u: |/d/x/y| => |/d/x/y| +path: -c: |/d/x/y| => |/cygdrive/d/x/y| +path: -m: |/d/x/y| => |/d/x/y| +path: -w: |/d/x/y| => |d:\\x\\y| +path: -u: |/cygdrive/d| => |/d| +path: -c: |/cygdrive/d| => |/cygdrive/d| +path: -m: |/cygdrive/d| => |/d| +path: -w: |/cygdrive/d| => |d:| +path: -u: |/d| => |/d| +path: -c: |/d| => |/cygdrive/d| +path: -m: |/d| => |/d| +path: -w: |/d| => |d:| +path: -u: |/cygdrive/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn| => |/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn| +path: -c: |/cygdrive/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn| => |/cygdrive/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn| +path: -m: |/cygdrive/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn| => |/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn| +path: -w: |/cygdrive/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn| => |d:\\git\\netcdf-c\\dap4_test\\test_anon_dim.2.syn| +path: -u: |d:\x\y| => |/d/x/y| +path: -c: |d:\x\y| => |/cygdrive/d/x/y| +path: -m: |d:\x\y| => |/d/x/y| +path: -w: |d:\x\y| => |d:\\x\\y| +path: -u: |d:\x\y w\z| => |/d/x/y\ w/z| +path: -c: |d:\x\y w\z| => |/cygdrive/d/x/y\ w/z| +path: -m: |d:\x\y w\z| => |/d/x/y\ w/z| +path: -w: |d:\x\y w\z| => |d:\\x\\y\ w\\z| diff --git a/ncdap_test/testauth.sh b/ncdap_test/testauth.sh index c35dd8153..811b6227a 100755 --- a/ncdap_test/testauth.sh +++ b/ncdap_test/testauth.sh @@ -41,7 +41,7 @@ LOCALRCFILES="$WD/.dodsrc $WD/.daprc $WD/.ncrc $WD/$NETRC $WD/$NETRCIMP" HOMERCFILES="$HOME/.dodsrc $HOME/.daprc $HOME/.ncrc $HOME/$NETRC $HOME/$NETRCIMP" NETRCFILE=$WD/$NETRC DAPRCFILE=$WD/$RC -if test "x$FP_ISMSVC" = x1 ; then +if test "x$FP_ISMSVC" != x ; then LOCALRCFILES=`${execdir}/pathcvt "$LOCALRCFILES"` HOMERCFILES=`${execdir}/pathcvt "$HOMERCFILES"` NETRCFILE=`${execdir}/pathcvt "$NETRCFILE"` diff --git a/ncdap_test/testpathcvt.sh b/ncdap_test/testpathcvt.sh index e4588b66a..cf1cd1abd 100755 --- a/ncdap_test/testpathcvt.sh +++ b/ncdap_test/testpathcvt.sh @@ -8,31 +8,31 @@ set -e testcase1() { T="$1" P="$2" -C=`${execdir}/pathcvt $T "$P"` -echo " $C" +echo -n "path: $T: |$P| => |" >>tmp_pathcvt.txt +${execdir}/pathcvt "$T" -e "$P" >>tmp_pathcvt.txt +echo "|" >> tmp_pathcvt.txt } testcase() { -#X=`echo -n "$1" | sed -e 's/\\\/\\\\\\\/g'` -X="$1" -echo "path:" "$X" testcase1 "-u" "$1" testcase1 "-c" "$1" testcase1 "-m" "$1" - testcase1 "-ew" "$1" | sed -e 's/\\/\\\\/g' + testcase1 "-w" "$1" } rm -f tmp_pathcvt.txt -testcase "/xxx/a/b" >> tmp_pathcvt.txt -testcase "d:/x/y" >> tmp_pathcvt.txt -testcase "/cygdrive/d/x/y" >> tmp_pathcvt.txt -testcase "/d/x/y" >> tmp_pathcvt.txt -testcase "/cygdrive/d" >> tmp_pathcvt.txt -testcase "/d" >> tmp_pathcvt.txt -testcase "/cygdrive/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn" >> tmp_pathcvt.txt -testcase "d:\\x\\y" >> tmp_pathcvt.txt -testcase "d:\\x\\y w\\z" >> tmp_pathcvt.txt +set -x + +testcase "/xxx/x/y" +testcase "d:/x/y" +testcase "/cygdrive/d/x/y" +testcase "/d/x/y" +testcase "/cygdrive/d" +testcase "/d" +testcase "/cygdrive/d/git/netcdf-c/dap4_test/test_anon_dim.2.syn" +testcase "d:\\x\\y" +testcase "d:\\x\\y w\\z" diff -w ${srcdir}/ref_pathcvt.txt ./tmp_pathcvt.txt From 6f03935de4c36ac80d6fb1711fc78825af5b2f9a Mon Sep 17 00:00:00 2001 From: Dennis Heimbigner Date: Sat, 5 Jun 2021 14:15:11 -0600 Subject: [PATCH 8/9] Update release notes --- RELEASE_NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 1df3a0e88..972be809f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -7,6 +7,7 @@ This file contains a high-level description of this package's evolution. Release ## 4.8.1 - TBD +* [Bug Fix] Store NCZarr fillvalue as a singleton instead of a 1-element array. See [Github #2017](https://github.com/Unidata/netcdf-c/issues/2017). * [Bug Fixes] The netcdf-c library was incorrectly determining the scope of dimension; similar to the type scope problem. See [Github #2012](https://github.com/Unidata/netcdf-c/pull/2012) for more information. * [Bug Fix] Re-enable DAP2 authorization testing. See [Github #2011](https://github.com/Unidata/netcdf-c/issues/2011). * [Bug Fix] Fix bug with windows version of mkstemp that causes failure to create more than 26 temp files. See [Github #1998](https://github.com/Unidata/netcdf-c/pull/1998). From ad11c54a79af1be366b4fea7d9c3ed2f5ef338d7 Mon Sep 17 00:00:00 2001 From: Ward Fisher Date: Wed, 9 Jun 2021 15:55:11 -0600 Subject: [PATCH 9/9] Added a temporary fix in support of https://github.com/Unidata/netcdf-c/issues/2018. Also, fixed a missing reference file when using cmake-based build systems. --- ncdap_test/CMakeLists.txt | 2 +- ncdap_test/testpathcvt.sh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ncdap_test/CMakeLists.txt b/ncdap_test/CMakeLists.txt index 8e55b6c04..1489371e2 100644 --- a/ncdap_test/CMakeLists.txt +++ b/ncdap_test/CMakeLists.txt @@ -10,7 +10,7 @@ add_definitions(-D"TOPBINDIR=${CMAKE_CURRENT_BINARY_DIR}/../") remove_definitions(-DDLL_EXPORT) # add_definitions(-D"TOPSRCDIR=${CMAKE_CURRENT_SOURCE_DIR}") -FILE(GLOB COPY_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.sh) +FILE(GLOB COPY_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.sh ${CMAKE_CURRENT_SOURCE_DIR}/ref_pathcvt.txt) FILE(COPY ${COPY_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ FILE_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE) diff --git a/ncdap_test/testpathcvt.sh b/ncdap_test/testpathcvt.sh index cf1cd1abd..9c1e2aedc 100755 --- a/ncdap_test/testpathcvt.sh +++ b/ncdap_test/testpathcvt.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash if test "x$srcdir" = x ; then srcdir=`pwd`; fi . ../test_common.sh @@ -11,6 +11,7 @@ P="$2" echo -n "path: $T: |$P| => |" >>tmp_pathcvt.txt ${execdir}/pathcvt "$T" -e "$P" >>tmp_pathcvt.txt echo "|" >> tmp_pathcvt.txt + } testcase() { @@ -18,7 +19,7 @@ testcase() { testcase1 "-c" "$1" testcase1 "-m" "$1" testcase1 "-w" "$1" -} +} rm -f tmp_pathcvt.txt