From 7eadbc25ce72ad0cc84f8653ab7eb1c490ae668f Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Wed, 20 Mar 2019 15:43:27 -0400 Subject: [PATCH 01/16] Adding unit test and refactoring Added unit test for errormanager and refactored to simplify use of error_check() method. --- src/epanet_py.c | 21 ++------- src/util/errormanager.c | 40 ++++++++++------ src/util/errormanager.h | 17 +++++-- tests/util/CMakeLists.txt | 18 +++++++ tests/util/test_errormanager.cpp | 81 ++++++++++++++++++++++++++++++++ 5 files changed, 141 insertions(+), 36 deletions(-) create mode 100644 tests/util/CMakeLists.txt create mode 100644 tests/util/test_errormanager.cpp diff --git a/src/epanet_py.c b/src/epanet_py.c index 05e7a20..3ee3898 100644 --- a/src/epanet_py.c +++ b/src/epanet_py.c @@ -93,7 +93,7 @@ int EXPORT_PY_API proj_gettitle(Handle ph, char *line1, char *line2, char *line3 int EXPORT_PY_API proj_settitle(Handle ph, const char *line1, const char *line2, const char *line3) { handle_t *pr = (handle_t *)ph; - return error_set(pr->error, EN_settitle(pr->project, line1, line2, line3)); + return error_set(pr->error, EN_settitle(pr->project, (char *)line1, (char *)line2, (char *)line3)); } int EXPORT_PY_API proj_getcount(Handle ph, EN_CountType code, int *count) @@ -761,28 +761,13 @@ void EXPORT_PY_API err_clear(Handle ph) int EXPORT_PY_API err_check(Handle ph, char** msg_buffer) // -// Purpose: Returns the error message or NULL. +// Purpose: Returns the error code and message or 0 and NULL respectively. // // Note: Caller must free memory allocated by EN_check_error // { - int errorcode = 0; - char *temp = NULL; - handle_t *pr = (handle_t *)ph; - - - if (pr == NULL) return -1; - else - { - errorcode = pr->error->error_status; - if (errorcode) - temp = error_check(pr->error); - - *msg_buffer = temp; - } - - return errorcode; + return error_check(pr->error, msg_buffer); } int EXPORT_PY_API toolkit_getversion(int *version) diff --git a/src/util/errormanager.c b/src/util/errormanager.c index 3f4f47c..d8ca078 100644 --- a/src/util/errormanager.c +++ b/src/util/errormanager.c @@ -9,16 +9,25 @@ // Author: Michael E. Tryby // US EPA - ORD/NRMRL //----------------------------------------------------------------------------- + +//#ifdef _WIN32 +//#define _CRTDBG_MAP_ALLOC +//#include +//#include +//#else #include +//#endif #include + #include "errormanager.h" -error_handle_t* error_new_manager(void (*p_error_message)(int, char*, int)) + +error_handle_t *error_new_manager(void (*p_error_message)(int, char*, int)) // // Purpose: Constructs a new error handle. // { - error_handle_t* error_handle; + error_handle_t *error_handle; error_handle = (error_handle_t*)calloc(1, sizeof(error_handle_t)); error_handle->p_msg_lookup = p_error_message; @@ -26,7 +35,7 @@ error_handle_t* error_new_manager(void (*p_error_message)(int, char*, int)) return error_handle; } -void error_dst_manager(error_handle_t* error_handle) +void error_dst_manager(error_handle_t *error_handle) // // Purpose: Destroys the error handle. // @@ -34,38 +43,39 @@ void error_dst_manager(error_handle_t* error_handle) free(error_handle); } -int error_set(error_handle_t* error_handle, int errorcode) +int error_set(error_handle_t *error_handle, int error_code) // // Purpose: Sets an error code in the handle. // { // If the error code is 0 no action is taken and 0 is returned. // This is a feature not a bug. - if (errorcode) - error_handle->error_status = errorcode; + if (error_code) + error_handle->error_status = error_code; - return errorcode; + return error_code; } -char* error_check(error_handle_t* error_handle) +int error_check(error_handle_t *error_handle, char **error_message) // // Purpose: Returns the error message or NULL. // // Note: Caller must free memory allocated by check_error // -{ - char* temp = NULL; +{ int error_code = error_handle->error_status; + char *temp = NULL; - if (error_handle->error_status != 0) { - temp = (char*) calloc(ERR_MAXMSG, sizeof(char)); + if (error_code != 0) { + temp = (char*) calloc(ERR_MAXMSG + 1, sizeof(char)); if (temp) - error_handle->p_msg_lookup(error_handle->error_status, temp, ERR_MAXMSG); + error_handle->p_msg_lookup(error_code, temp, ERR_MAXMSG); } - return temp; + *error_message = temp; + return error_code; } -void error_clear(error_handle_t* error_handle) +void error_clear(error_handle_t *error_handle) // // Purpose: Clears the error from the handle. // diff --git a/src/util/errormanager.h b/src/util/errormanager.h index 2a8099f..5501e0d 100644 --- a/src/util/errormanager.h +++ b/src/util/errormanager.h @@ -12,16 +12,27 @@ #define ERR_MAXMSG 256 + +#if defined(__cplusplus) +extern "C" { +#endif + + typedef struct error_s { - int error_status; + int error_status; void (*p_msg_lookup)(int, char*, int); } error_handle_t; error_handle_t* error_new_manager(void (*p_error_message)(int, char*, int)); void error_dst_manager(error_handle_t* error_handle); -int error_set(error_handle_t* error_handle, int errorcode); -char* error_check(error_handle_t* error_handle); +int error_set(error_handle_t* error_handle, int error_code); +int error_check(error_handle_t* error_handle, char **error_message); void error_clear(error_handle_t* error_handle); + +#if defined(__cplusplus) +} +#endif + #endif /* ERRORMANAGER_H_ */ diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt new file mode 100644 index 0000000..df2f743 --- /dev/null +++ b/tests/util/CMakeLists.txt @@ -0,0 +1,18 @@ + + +cmake_minimum_required(VERSION 3.12) + +enable_testing() + +set (Boost_USE_STATIC_LIBS OFF) +find_package(Boost COMPONENTS unit_test_framework) +include_directories (${Boost_INCLUDE_DIRS} ../../src/) + +set (test_source +./test_errormanager.cpp +../../src/util/errormanager.c +) + +add_executable(test_errormanager ${test_source}) + +target_link_libraries(test_errormanager ${Boost_LIBRARIES}) diff --git a/tests/util/test_errormanager.cpp b/tests/util/test_errormanager.cpp new file mode 100644 index 0000000..7d270ae --- /dev/null +++ b/tests/util/test_errormanager.cpp @@ -0,0 +1,81 @@ + + +#define BOOST_TEST_MODULE errormanager +#define BOOST_TEST_DYN_LINK +#include + +#include "util/errormanager.h" + + +#define MESSAGE_STRING "This is unit testing!" + + +void mock_lookup(int errcode, char *errmsg, int len) +{ + char *msg = NULL; + + if (errcode == 100) { + msg = MESSAGE_STRING; + } + else { + msg = ""; + } + strncpy(errmsg, msg, len); +} + +boost::test_tools::predicate_result check_string(std::string test, std::string ref) +{ + if (ref.compare(test) == 0) + return true; + else + return false; +} + + +BOOST_AUTO_TEST_SUITE(test_errormanager) + +BOOST_AUTO_TEST_CASE (test_create_destroy) +{ + error_handle_t *error_handle = NULL; + error_handle = error_new_manager(&mock_lookup); + + error_dst_manager(error_handle); +} + + +struct Fixture{ + Fixture() { + error_message = NULL; + error_handle = error_new_manager(&mock_lookup); + } + ~Fixture() { + error_dst_manager(error_handle); + free(error_message); + } + int error; + error_handle_t *error_handle; + char *error_message; +}; + + +BOOST_FIXTURE_TEST_CASE (test_set_clear, Fixture) +{ + error = error_set(error_handle, 100); + BOOST_CHECK(error == 100); + + error_clear(error_handle); + error = error_check(error_handle, &error_message); + BOOST_CHECK(error == 0); + BOOST_CHECK(error_message == NULL); +} + +BOOST_FIXTURE_TEST_CASE(test_set_check, Fixture) +{ + error = error_set(error_handle, 100); + BOOST_CHECK(error == 100); + + error = error_check(error_handle, &error_message); + BOOST_CHECK(check_string(error_message, MESSAGE_STRING)); +} + +BOOST_AUTO_TEST_SUITE_END() From ccbb4222599156fd9d1b3364e644c71d8b189d36 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Wed, 20 Mar 2019 17:58:24 -0400 Subject: [PATCH 02/16] Reorganizing src and test folders Moving epanet_output library from tools to src folder. Setting up parallel folder hierarchy in tests folder. --- CMakeLists.txt | 3 +- src/outfile/CMakeLists.txt | 40 + src/outfile/include/epanet_output.h | 82 ++ src/outfile/include/epanet_output_enums.h | 79 ++ src/outfile/src/epanet_output.c | 990 ++++++++++++++++++++++ src/outfile/src/messages.h | 29 + src/util/errormanager.c | 10 +- src/util/errormanager.h | 10 +- tests/outfile/CMakeLists.txt | 19 + tests/{ => outfile}/test_output.cpp | 97 ++- 10 files changed, 1304 insertions(+), 55 deletions(-) create mode 100644 src/outfile/CMakeLists.txt create mode 100644 src/outfile/include/epanet_output.h create mode 100644 src/outfile/include/epanet_output_enums.h create mode 100644 src/outfile/src/epanet_output.c create mode 100644 src/outfile/src/messages.h create mode 100644 tests/outfile/CMakeLists.txt rename tests/{ => outfile}/test_output.cpp (87%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 92f834e..499b1e4 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,10 +41,11 @@ option(BUILD_COVERAGE "Build library for coverage" OFF) IF (NOT BUILD_PY_LIB) add_subdirectory(run) ENDIF (NOT BUILD_PY_LIB) -add_subdirectory(tools/epanet-output) +add_subdirectory(src/outfile) IF (BUILD_TESTS) add_subdirectory(tests) + add_subdirectory(tests/outfile) ENDIF (BUILD_TESTS) diff --git a/src/outfile/CMakeLists.txt b/src/outfile/CMakeLists.txt new file mode 100644 index 0000000..cdd2f0f --- /dev/null +++ b/src/outfile/CMakeLists.txt @@ -0,0 +1,40 @@ +# +# CMakeLists.txt - CMake configuration file for epanet-output library +# +# Created: March 9, 2018 +# Author: Michael E. Tryby +# US EPA ORD/NRMRL +# + + +# Sets for output directory for executables and libraries. +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + + +set(CMAKE_C_VISIBILITY_PRESET hidden) +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + + +# configure file groups +set(EPANET_OUT_SOURCES src/epanet_output.c + ../util/errormanager.c) + + +# the binary output file API +add_library(epanet-output SHARED ${EPANET_OUT_SOURCES}) +target_include_directories(epanet-output PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/../) + +include(GenerateExportHeader) +generate_export_header(epanet-output + BASE_NAME epanet_output + EXPORT_MACRO_NAME EXPORT_OUT_API + EXPORT_FILE_NAME epanet_output_export.h + STATIC_DEFINE SHARED_EXPORTS_BUILT_AS_STATIC) + +file(COPY ${CMAKE_CURRENT_BINARY_DIR}/epanet_output_export.h DESTINATION + ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/src/outfile/include/epanet_output.h b/src/outfile/include/epanet_output.h new file mode 100644 index 0000000..9c06522 --- /dev/null +++ b/src/outfile/include/epanet_output.h @@ -0,0 +1,82 @@ +/* + * epanet_output.h - EPANET Output API + * + * Created on: Jun 4, 2014 + * + * Author: Michael E. Tryby + * US EPA - ORD/NRMRL + */ + +#ifndef EPANET_OUTPUT_H_ +#define EPANET_OUTPUT_H_ +/* Epanet Results binary file API */ + + +#define MAXFNAME 259 // Max characters in file name +#define MAXID 31 // Max characters in ID name + + +// This is an opaque pointer to struct. Do not access variables. +typedef void* ENR_Handle; + + +#include "epanet_output_enums.h" +#include "epanet_output_export.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +int EXPORT_OUT_API ENR_init(ENR_Handle* p_handle_out); + +int EXPORT_OUT_API ENR_open(ENR_Handle p_handle_in, const char* path); + +int EXPORT_OUT_API ENR_getVersion(ENR_Handle p_handle_in, int* int_out); + +int EXPORT_OUT_API ENR_getNetSize(ENR_Handle p_handle_in, int** int_out, int* int_dim); + +int EXPORT_OUT_API ENR_getUnits(ENR_Handle p_handle_in, ENR_Units t_enum, int* int_out); + +int EXPORT_OUT_API ENR_getTimes(ENR_Handle p_handle_in, ENR_Time t_enum, int* int_out); + +int EXPORT_OUT_API ENR_getElementName(ENR_Handle p_handle_in, ENR_ElementType t_enum, + int elementIndex, char** string_out, int* slen); + +int EXPORT_OUT_API ENR_getEnergyUsage(ENR_Handle p_handle_in, int pumpIndex, + int* int_out, float** float_out, int* int_dim); + +int EXPORT_OUT_API ENR_getNetReacts(ENR_Handle p_handle_in, float** float_out, int* int_dim); + + +int EXPORT_OUT_API ENR_getNodeSeries(ENR_Handle p_handle_in, int nodeIndex, ENR_NodeAttribute t_enum, + int startPeriod, int endPeriod, float** outValueSeries, int* dim); + +int EXPORT_OUT_API ENR_getLinkSeries(ENR_Handle p_handle_in, int linkIndex, ENR_LinkAttribute t_enum, + int startPeriod, int endPeriod, float** outValueSeries, int* dim); + +int EXPORT_OUT_API ENR_getNodeAttribute(ENR_Handle p_handle_in, int periodIndex, + ENR_NodeAttribute t_enum, float** outValueArray, int* dim); + +int EXPORT_OUT_API ENR_getLinkAttribute(ENR_Handle p_handle_in, int periodIndex, + ENR_LinkAttribute t_enum, float** outValueArray, int* dim); + +int EXPORT_OUT_API ENR_getNodeResult(ENR_Handle p_handle_in, int periodIndex, int nodeIndex, + float** float_out, int* int_dim); + +int EXPORT_OUT_API ENR_getLinkResult(ENR_Handle p_handle_in, int periodIndex, int linkIndex, + float** float_out, int* int_dim); + +int EXPORT_OUT_API ENR_close(ENR_Handle* p_handle_out); + +void EXPORT_OUT_API ENR_free(void** array); + +void EXPORT_OUT_API ENR_clearError(ENR_Handle p_handle_in); + +int EXPORT_OUT_API ENR_checkError(ENR_Handle p_handle_in, char** msg_buffer); + +#ifdef __cplusplus +} +#endif + +#endif /* EPANET_OUTPUT_H_ */ diff --git a/src/outfile/include/epanet_output_enums.h b/src/outfile/include/epanet_output_enums.h new file mode 100644 index 0000000..0fa012f --- /dev/null +++ b/src/outfile/include/epanet_output_enums.h @@ -0,0 +1,79 @@ +/* + * epanet_output_enums.h - EPANET Output API enums + * + * Created on: March 11, 2019 + * + * Author: Michael E. Tryby + * US EPA - ORD/NRMRL + */ + + +#ifndef EPANET_OUTPUT_ENUMS_H_ +#define EPANET_OUTPUT_ENUMS_H_ + + +typedef enum { + ENR_node = 1, + ENR_link = 2 +} ENR_ElementType; + +typedef enum { + ENR_flowUnits = 1, + ENR_pressUnits = 2, + ENR_qualUnits = 3 +} ENR_Units; + +typedef enum { + ENR_CFS = 0, + ENR_GPM = 1, + ENR_MGD = 2, + ENR_IMGD = 3, + ENR_AFD = 4, + ENR_LPS = 5, + ENR_LPM = 6, + ENR_MLD = 7, + ENR_CMH = 8, + ENR_CMD = 9 +} ENR_FlowUnits; + +typedef enum { + ENR_PSI = 0, + ENR_MTR = 1, + ENR_KPA = 2 +} ENR_PressUnits; + +typedef enum { + ENR_NONE = 0, + ENR_MGL = 1, + ENR_UGL = 2, + ENR_HOURS = 3, + ENR_PRCNT = 4 +} ENR_QualUnits; + +typedef enum { + ENR_reportStart = 1, + ENR_reportStep = 2, + ENR_simDuration = 3, + ENR_numPeriods = 4 +}ENR_Time; + +typedef enum { + ENR_demand = 1, + ENR_head = 2, + ENR_pressure = 3, + ENR_quality = 4 +} ENR_NodeAttribute; + +typedef enum { + ENR_flow = 1, + ENR_velocity = 2, + ENR_headloss = 3, + ENR_avgQuality = 4, + ENR_status = 5, + ENR_setting = 6, + ENR_rxRate = 7, + ENR_frctnFctr = 8 +} ENR_LinkAttribute; + + +#endif /* EPANET_OUTPUT_ENUMS_H_ */ diff --git a/src/outfile/src/epanet_output.c b/src/outfile/src/epanet_output.c new file mode 100644 index 0000000..dcbcd75 --- /dev/null +++ b/src/outfile/src/epanet_output.c @@ -0,0 +1,990 @@ +//----------------------------------------------------------------------------- +// +// epanet_output.c -- API for reading results from EPANET binary output file +// +// Version: 0.30 +// Date 09/06/2017 +// 06/17/2016 +// 08/05/2014 +// 05/21/2014 +// +// Author: Michael E. Tryby +// US EPA - ORD/NRMRL +// +// Modified: Maurizio Cingi +// University of Modena +// +// Purpose: Output API provides an interface for retrieving results from an +// EPANET binary output file. +// +// Output data in the binary file are aligned on a 4 byte word size. +// Therefore all values both integers and reals are 32 bits in length. +// +// All values returned by the output API are indexed from 0 to n-1. This +// differs from how node and link elements are indexed by the binary file +// writer found in EPANET. Times correspond to reporting periods are indexed +// from 0 to number of reporting periods minus one. Node and link elements +// are indexed from 0 to nodeCount minus one and 0 to linkCount minus one +// respectively. +// +// The Output API functions provide a convenient way to select "slices" of +// data from the output file. As such they return arrays of data. The API +// functions automatically allocate memory for the array to be returned. The +// caller is responsible for deallocating memory. The function ENR_free() is +// provided for that purpose. +// +//----------------------------------------------------------------------------- + +#include +#include +#include + +#include "util/errormanager.h" + +#include "epanet_output.h" +#include "messages.h" + + +// NOTE: These depend on machine data model and may change when porting +// F_OFF Must be a 8 byte / 64 bit integer for large file support +#ifdef _WIN32 // Windows (32-bit and 64-bit) +#define F_OFF __int64 +#else // Other platforms +#define F_OFF off_t +#endif +#define INT4 int // Must be a 4 byte / 32 bit integer type +#define REAL4 float // Must be a 4 byte / 32 bit real type +#define WORDSIZE 4 // Memory alignment 4 byte word size for both int and real + +#define MINNREC 14 // Minimum allowable number of records +#define PROLOGUE 884 // Preliminary fixed length section of header +#define MAXID_P1 32 // EPANET max characters in ID name PLUS 1 +#define MAXMSG_P1 80 // EPANET max characters in message text PLUS 1 + +#define NELEMENTTYPES 5 // Number of element types +#define NENERGYRESULTS 6 // Number of energy results +#define NNODERESULTS 4 // number of result fields for nodes +#define NLINKRESULTS 8 // number of result fields for links +#define NREACTRESULTS 4 // number of net reaction results + +#define MEMCHECK(x) (((x) == NULL) ? 411 : 0 ) + +// Typedefs for opaque pointer +typedef struct data_s { + char name[MAXFNAME+1]; // file path/name + FILE* file; // FILE structure pointer + INT4 nodeCount, tankCount, linkCount, pumpCount, valveCount, nPeriods; + F_OFF outputStartPos; // starting file position of output data + F_OFF bytesPerPeriod; // bytes saved per simulation time period + + error_handle_t* error_handle; +} data_t; + +//----------------------------------------------------------------------------- +// Local functions +//----------------------------------------------------------------------------- +void errorLookup(int errcode, char* errmsg, int length); +int validateFile(ENR_Handle); +float getNodeValue(ENR_Handle, int, int, int); +float getLinkValue(ENR_Handle, int, int, int); + +int _fopen(FILE **f, const char *name, const char *mode); +int _fseek(FILE* stream, F_OFF offset, int whence); +F_OFF _ftell(FILE* stream); + +float* newFloatArray(int n); +int* newIntArray(int n); +char* newCharArray(int n); + + +int EXPORT_OUT_API ENR_init(ENR_Handle* dp_handle) +// Purpose: Initialized pointer for the opaque ENR_Handle. +// +// Returns: Error code 0 on success, -1 on failure +// +// Note: The existence of this function has been carefully considered. +// Don't change it. +// +{ + int errorcode = 0; + data_t* p_data; + + // Allocate memory for private data + p_data = (data_t*)calloc(1, sizeof(data_t)); + + if (p_data != NULL){ + p_data->error_handle = create_error_manager(&errorLookup); + *dp_handle = p_data; + } + else + errorcode = -1; + + // TODO: Need to handle errors during initialization better. + return errorcode; +} + +int EXPORT_OUT_API ENR_close(ENR_Handle* p_handle) +/*------------------------------------------------------------------------ + ** Input: *p_handle = pointer to ENR_Handle struct + ** + ** Returns: Error code 0 on success, -1 on failure + ** + ** Purpose: Close the output binary file, dellocate ENR_Handle struc + ** and nullify pointer to ENR_Handle struct + ** + ** NOTE: ENR_close must be called before program end + ** after calling ENR_close data in ENR_Handle struct are no more + ** accessible + **------------------------------------------------------------------------- + */ +{ + data_t* p_data; + int errorcode = 0; + + p_data = (data_t*)(*p_handle); + + if (p_data == NULL || p_data->file == NULL) + errorcode = -1; + + else + { + delete_error_manager(p_data->error_handle); + fclose(p_data->file); + free(p_data); + + *p_handle = NULL; + } + + return errorcode; +} + +int EXPORT_OUT_API ENR_open(ENR_Handle p_handle, const char* path) +/*------------------------------------------------------------------------ + ** Input: path + ** Output: p_handle = pointer to ENR_Handle struct + ** Returns: warning / error code + ** Purpose: Opens the output binary file and reads prologue and epilogue + ** + ** NOTE: ENR_init must be called before anyother ENR_* functions + **------------------------------------------------------------------------- + */ +{ + int err, errorcode = 0; + F_OFF bytecount; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + else + { + strncpy(p_data->name, path, MAXFNAME); + // Attempt to open binary output file for reading only + if ((_fopen(&(p_data->file), path, "rb")) != 0) errorcode = 434; + + // Perform checks to insure the file is valid + else if ((err = validateFile(p_data)) != 0) errorcode = err; + + // If a warning is encountered read file header + if (errorcode < 400 ) { + + // read network size + fseek(p_data->file, 2*WORDSIZE, SEEK_SET); + fread(&(p_data->nodeCount), WORDSIZE, 1, p_data->file); + fread(&(p_data->tankCount), WORDSIZE, 1, p_data->file); + fread(&(p_data->linkCount), WORDSIZE, 1, p_data->file); + fread(&(p_data->pumpCount), WORDSIZE, 1, p_data->file); + fread(&(p_data->valveCount), WORDSIZE, 1, p_data->file); + + // Compute positions and offsets for retrieving data + // fixed portion of header + title section + filenames + chem names + bytecount = PROLOGUE; + // node names + link names + bytecount += MAXID_P1*p_data->nodeCount + MAXID_P1*p_data->linkCount; + // network connectivity + tank nodes + tank areas + bytecount += 3*WORDSIZE*p_data->linkCount + 2*WORDSIZE*p_data->tankCount; + // node elevations + link lengths and link diameters + bytecount += WORDSIZE*p_data->nodeCount + 2*WORDSIZE*p_data->linkCount; + // pump energy summary + bytecount += 7*WORDSIZE*p_data->pumpCount + WORDSIZE; + p_data->outputStartPos= bytecount; + + p_data->bytesPerPeriod = NNODERESULTS*WORDSIZE*p_data->nodeCount + + NLINKRESULTS*WORDSIZE*p_data->linkCount; + } + } + // If error close the binary file + if (errorcode > 400) { + set_error(p_data->error_handle, errorcode); + ENR_close(&p_handle); + } + + return errorcode; +} + +int EXPORT_OUT_API ENR_getVersion(ENR_Handle p_handle, int* version) +/*------------------------------------------------------------------------ + ** Input: p_handle = pointer to ENR_Handle struct + ** Output: version Epanet version + ** Returns: error code + ** + ** Purpose: Returns Epanet version that wrote EBOFile + **--------------element codes------------------------------------------- + */ +{ + int errorcode = 0; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + else + { + fseek(p_data->file, 1*WORDSIZE, SEEK_SET); + if (fread(version, WORDSIZE, 1, p_data->file) != 1) + errorcode = 436; + } + + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getNetSize(ENR_Handle p_handle, int** elementCount, int* length) +/*------------------------------------------------------------------------ + ** Input: p_handle = pointer to ENR_Handle struct + ** Output: array of element counts (nodes, tanks, links, pumps, valves) + ** Returns: error code + ** Purpose: Returns an array of count values + **------------------------------------------------------------------------- + */ +{ + int errorcode = 0; + int* temp = newIntArray(NELEMENTTYPES); + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + else + { + temp[0] = p_data->nodeCount; + temp[1] = p_data->tankCount; + temp[2] = p_data->linkCount; + temp[3] = p_data->pumpCount; + temp[4] = p_data->valveCount; + + *elementCount = temp; + *length = NELEMENTTYPES; + } + + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getUnits(ENR_Handle p_handle, ENR_Units code, int* unitFlag) +/*------------------------------------------------------------------------ + ** Input: p_handle = pointer to ENR_Handle struct + ** code + ** Output: count + ** Returns: unitFlag + ** Purpose: Returns pressure or flow unit flag + **--------------pressure unit flags---------------------------------------- + ** 0 = psi + ** 1 = meters + ** 2 = kPa + **------------------flow unit flags---------------------------------------- + ** 0 = cubic feet/second + ** 1 = gallons/minute + ** 2 = million gallons/day + ** 3 = Imperial million gallons/day + ** 4 = acre-ft/day + ** 5 = liters/second + ** 6 = liters/minute + ** 7 = megaliters/day + ** 8 = cubic meters/hour + ** 9 = cubic meters/day + **------------------------------------------------------------------------- + */ +{ + int errorcode = 0; + F_OFF offset; + char temp[MAXID_P1]; + data_t* p_data; + + *unitFlag = -1; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + else + { + switch (code) + { + case ENR_flowUnits: + _fseek(p_data->file, 9*WORDSIZE, SEEK_SET); + fread(unitFlag, WORDSIZE, 1, p_data->file); + break; + + case ENR_pressUnits: + _fseek(p_data->file, 10*WORDSIZE, SEEK_SET); + fread(unitFlag, WORDSIZE, 1, p_data->file); + break; + + case ENR_qualUnits: + offset = 7*WORDSIZE; + _fseek(p_data->file, offset, SEEK_SET); + fread(unitFlag, WORDSIZE, 1, p_data->file); + + if (*unitFlag == 0) *unitFlag = ENR_NONE; + + else if (*unitFlag == 1) { + offset = 15*WORDSIZE + 3*MAXMSG_P1 + 2*(MAXFNAME+1) + MAXID_P1; + _fseek(p_data->file, offset, SEEK_SET); + fread(temp, MAXID_P1, 1, p_data->file); + + if (!strcmp(temp, "mg/L")) *unitFlag = ENR_MGL; + else *unitFlag = ENR_UGL; + } + + else if (*unitFlag == 2) *unitFlag = ENR_HOURS; + + else *unitFlag = ENR_PRCNT; + + break; + + default: errorcode = 421; + } + } + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getTimes(ENR_Handle p_handle, ENR_Time code, int* time) +/*------------------------------------------------------------------------ + ** Input: p_handle = pointer to ENR_Handle struct + ** code = element code + ** Output: time + ** Returns: error code + ** Purpose: Returns report and simulation time related parameters. + **------------------------------------------------------------------------- + */ +{ + int errorcode = 0; + data_t* p_data; + + *time = -1; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + else + { + switch (code) + { + case ENR_reportStart: + fseek(p_data->file, 12*WORDSIZE, SEEK_SET); + fread(time, WORDSIZE, 1, p_data->file); + break; + + case ENR_reportStep: + fseek(p_data->file, 13*WORDSIZE, SEEK_SET); + fread(time, WORDSIZE, 1, p_data->file); + break; + + case ENR_simDuration: + fseek(p_data->file, 14*WORDSIZE, SEEK_SET); + fread(time, WORDSIZE, 1, p_data->file); + break; + + case ENR_numPeriods: + *time = p_data->nPeriods; + break; + + default: + errorcode = 421; + } + } + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getChemData(ENR_Handle p_handle, char** name, int* length) + +{ + return 0; +} + +int EXPORT_OUT_API ENR_getElementName(ENR_Handle p_handle, ENR_ElementType type, + int elementIndex, char** name, int* length) +/*------------------------------------------------------------------------ + ** Input: p_handle = pointer to ENR_Handle struct + ** type = ENR_node or ENR_link + ** elementIndex from 1 to nodeCount or 1 to linkCount + ** Output: name = elementName + ** Returns: error code + ** Purpose: Retrieves Name of a specified node or link element + ** NOTE: 'name' must be able to hold MAXID characters + ** TODO: Takes EPANET indexing from 1 to n not 0 to n-1 + **------------------------------------------------------------------------- + */ +{ + F_OFF offset; + int errorcode = 0; + char* temp; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + /* Allocate memory for name */ + else if MEMCHECK(temp = newCharArray(MAXID_P1)) errorcode = 411; + + else + { + switch (type) + { + case ENR_node: + if (elementIndex < 1 || elementIndex > p_data->nodeCount) + errorcode = 423; + else offset = PROLOGUE + (elementIndex - 1)*MAXID_P1; + break; + + case ENR_link: + if (elementIndex < 1 || elementIndex > p_data->linkCount) + errorcode = 423; + else + offset = PROLOGUE + p_data->nodeCount*MAXID_P1 + + (elementIndex - 1)*MAXID_P1; + break; + + default: + errorcode = 421; + } + + if (!errorcode) + { + _fseek(p_data->file, offset, SEEK_SET); + fread(temp, 1, MAXID_P1, p_data->file); + + *name = temp; + *length = MAXID_P1; + } + } + + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getEnergyUsage(ENR_Handle p_handle, int pumpIndex, + int* linkIndex, float** outValues, int* length) +/* + * Purpose: Returns pump energy usage statistics. + * + * Energy usage statistics: + * 0 = pump utilization + * 1 = avg. efficiency + * 2 = avg. kW/flow + * 3 = avg. kwatts + * 4 = peak kwatts + * 5 = cost/day + */ +{ + F_OFF offset; + int errorcode = 0; + float* temp; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + // Check for valid pump index + else if (pumpIndex < 1 || pumpIndex > p_data->pumpCount) errorcode = 423; + // Check memory for outValues + else if MEMCHECK(temp = newFloatArray(NENERGYRESULTS)) errorcode = 411; + + else + { + // Position offset to start of pump energy summary + offset = p_data->outputStartPos - (p_data->pumpCount*(WORDSIZE + 6*WORDSIZE) + WORDSIZE); + // Adjust offset by pump index + offset += (pumpIndex - 1)*(WORDSIZE + 6*WORDSIZE); + + // Power summary is 1 int and 6 floats for each pump + _fseek(p_data->file, offset, SEEK_SET); + fread(linkIndex, WORDSIZE, 1, p_data->file); + fread(temp, WORDSIZE, 6, p_data->file); + + *outValues = temp; + *length = NENERGYRESULTS; + } + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getNetReacts(ENR_Handle p_handle, float** outValues, int* length) +/* + * Purpose: Returns network wide average reaction rates and average + * source mass inflow: + * 0 = bulk + * 1 = wall + * 2 = tank + * 3 = source + */ +{ + F_OFF offset; + int errorcode = 0; + float* temp; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + // Check memory for outValues + else if MEMCHECK(temp = newFloatArray(NREACTRESULTS)) errorcode = 411; + + else + { + // Reaction summary is 4 floats located right before epilogue. + // This offset is relative to the end of the file. + offset = - 3*WORDSIZE - 4*WORDSIZE; + _fseek(p_data->file, offset, SEEK_END); + fread(temp, WORDSIZE, 4, p_data->file); + + *outValues = temp; + *length = NREACTRESULTS; + } + return set_error(p_data->error_handle, errorcode); +} + +void EXPORT_OUT_API ENR_free(void** array) +// +// Purpose: Frees memory allocated by API calls +// +{ + if (array != NULL) { + free(*array); + *array = NULL; + } +} + +int EXPORT_OUT_API ENR_getNodeSeries(ENR_Handle p_handle, int nodeIndex, ENR_NodeAttribute attr, + int startPeriod, int endPeriod, float** outValueSeries, int* dim) +// +// Purpose: Get time series results for particular attribute. Specify series +// start and length using seriesStart and seriesLength respectively. +// +// NOTE: The node index argument corresponds to the EPANET node index from 1 to +// nnodes. The series returned is indexed from 0 to nperiods - 1. +// +{ + int k, length, errorcode = 0; + float* temp; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + else if (nodeIndex < 1 || nodeIndex > p_data->nodeCount) errorcode = 423; + else if (startPeriod < 0 || endPeriod >= p_data->nPeriods || + endPeriod <= startPeriod) errorcode = 422; + // Check memory for outValues + else if MEMCHECK(temp = newFloatArray(length = endPeriod - startPeriod)) errorcode = 411; + else + { + // loop over and build time series + for (k = 0; k < length; k++) + temp[k] = getNodeValue(p_handle, startPeriod + k, + nodeIndex, attr); + + *outValueSeries = temp; + *dim = length; + } + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getLinkSeries(ENR_Handle p_handle, int linkIndex, ENR_LinkAttribute attr, + int startPeriod, int endPeriod, float** outValueSeries, int* dim) +// +// Purpose: Get time series results for particular attribute. Specify series +// start and length using seriesStart and seriesLength respectively. +// +// NOTE: +// The link index argument corresponds to the EPANET link index from 1 to +// nlinks. The series returned is indexed from 0 to nperiods - 1. +// +{ + int k, length, errorcode = 0; + float* temp; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + else if (linkIndex < 1 || linkIndex > p_data->linkCount) errorcode = 423; + else if (startPeriod < 0 || endPeriod >= p_data->nPeriods || + endPeriod <= startPeriod) errorcode = 422; + // Check memory for outValues + else if MEMCHECK(temp = newFloatArray(length = endPeriod - startPeriod)) errorcode = 411; + else + { + // loop over and build time series + for (k = 0; k < length; k++) + temp[k] = getLinkValue(p_handle, startPeriod + k, linkIndex, attr); + + *outValueSeries = temp; + *dim = length; + } + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getNodeAttribute(ENR_Handle p_handle, int periodIndex, + ENR_NodeAttribute attr, float** outValueArray, int* length) +// +// Purpose: +// For all nodes at given time, get a particular attribute +// +// Returns: +// Error code +// OutValueArray of results is indexed from 0 to nodeCount +// +// Warning: +// Caller must free memory allocated for outValueArray +// +// NOTE: +// The array returned is indexed from 0 to nnodes - 1. So to access +// node values by their EPANET index, the index value must be +// decremented by one. +// +{ + F_OFF offset; + int errorcode = 0; + float * temp; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + // if the time index is out of range return an error + else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422; + // Check memory for outValues + else if MEMCHECK(temp = newFloatArray(p_data->nodeCount)) errorcode = 411; + + else + { + // calculate byte offset to start time for series + offset = p_data->outputStartPos + (periodIndex)*p_data->bytesPerPeriod; + // add offset for node and attribute + offset += ((attr - 1)*p_data->nodeCount)*WORDSIZE; + + _fseek(p_data->file, offset, SEEK_SET); + fread(temp, WORDSIZE, p_data->nodeCount, p_data->file); + + *outValueArray = temp; + *length = p_data->nodeCount; + } + + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getLinkAttribute(ENR_Handle p_handle, int periodIndex, + ENR_LinkAttribute attr, float** outValueArray, int* length) +// +// Purpose: +// For all links at given time, get a particular attribute +// +// Returns: +// Error code +// OutValueArray of results is indexed from 0 to linkCount +// +// Warning: +// Caller must free memory allocated for outValueArray +// +// NOTE: +// The array returned is indexed from 0 to nlinks - 1. So to access +// link values by their EPANET index, the index value must be +// decremented by one. +// +{ + F_OFF offset; + int errorcode = 0; + float* temp; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + // if the time index is out of range return an error + else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422; + // Check memory for outValues + else if MEMCHECK(temp = newFloatArray(p_data->linkCount)) errorcode = 411; + + else + { + // calculate byte offset to start time for series + offset = p_data->outputStartPos + (periodIndex)*p_data->bytesPerPeriod + + (NNODERESULTS*p_data->nodeCount)*WORDSIZE; + // add offset for link and attribute + offset += ((attr - 1)*p_data->linkCount)*WORDSIZE; + + _fseek(p_data->file, offset, SEEK_SET); + fread(temp, WORDSIZE, p_data->linkCount, p_data->file); + + *outValueArray = temp; + *length = p_data->linkCount; + } + + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getNodeResult(ENR_Handle p_handle, int periodIndex, + int nodeIndex, float** outValueArray, int* length) +// +// Purpose: For a node at given time, get all attributes. +// +// NOTE: +// +{ + int j, errorcode = 0; + float* temp; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422; + else if (nodeIndex < 1 || nodeIndex > p_data->nodeCount) errorcode = 423; + else if MEMCHECK(temp = newFloatArray(NNODERESULTS)) errorcode = 411; + else + { + for (j = 0; j < NNODERESULTS; j++) + temp[j] = getNodeValue(p_handle, periodIndex, nodeIndex, j); + + *outValueArray = temp; + *length = NNODERESULTS; + } + + return set_error(p_data->error_handle, errorcode); +} + +int EXPORT_OUT_API ENR_getLinkResult(ENR_Handle p_handle, int periodIndex, + int linkIndex, float** outValueArray, int* length) +// +// Purpose: For a link at given time, get all attributes +// +{ + int j, errorcode = 0; + float* temp; + data_t* p_data; + + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422; + else if (linkIndex < 1 || linkIndex > p_data->linkCount) errorcode = 423; + else if MEMCHECK(temp = newFloatArray(NLINKRESULTS)) errorcode = 411; + else + { + for (j = 0; j < NLINKRESULTS; j++) + temp[j] = getLinkValue(p_handle, periodIndex, linkIndex, j); + + *outValueArray = temp; + *length = NLINKRESULTS; + } + return set_error(p_data->error_handle, errorcode); +} + +void EXPORT_OUT_API ENR_clearError(ENR_Handle p_handle) +{ + data_t* p_data; + + p_data = (data_t*)p_handle; + clear_error(p_data->error_handle); +} + +int EXPORT_OUT_API ENR_checkError(ENR_Handle p_handle, char** msg_buffer) +{ + data_t* p_data; + p_data = (data_t*)p_handle; + + if (p_data == NULL) return -1; + + return check_error(p_data->error_handle, msg_buffer); +} + + +void errorLookup(int errcode, char* dest_msg, int dest_len) +// +// Purpose: takes error code returns error message +// +{ + const char* msg; + + switch (errcode) + { + case 10: msg = WARN10; + break; + case 411: msg = ERR411; + break; + case 412: msg = ERR412; + break; + case 421: msg = ERR421; + break; + case 422: msg = ERR422; + break; + case 423: msg = ERR423; + break; + case 434: msg = ERR434; + break; + case 435: msg = ERR435; + break; + case 436: msg = ERR436; + break; + default: msg = ERRERR; + } + + strncpy(dest_msg, msg, MSG_MAXLEN); +} + +int validateFile(ENR_Handle p_handle) +// Returns: +// Error code: 435, 436 +// Warning code: 10 +{ + INT4 magic1, magic2, hydcode; + int errorcode = 0; + F_OFF filepos; + data_t* p_data; + + p_data = (data_t*)p_handle; + + // Read magic number from beginning of file + fseek(p_data->file, 0L, SEEK_SET); + fread(&magic1, WORDSIZE, 1, p_data->file); + + // Fast forward to end and read file epilogue + fseek(p_data->file, -3*WORDSIZE, SEEK_END); + fread(&(p_data->nPeriods), WORDSIZE, 1, p_data->file); + fread(&hydcode, WORDSIZE, 1, p_data->file); + fread(&magic2, WORDSIZE, 1, p_data->file); + + filepos = _ftell(p_data->file); + + // Is the file an EPANET binary file? + if (magic1 != magic2) errorcode = 435; + // Does the binary file contain results? + else if (filepos < MINNREC*WORDSIZE || p_data->nPeriods == 0) + errorcode = 436; + // Issue warning if there were problems with the model run. + else if (hydcode != 0) errorcode = 10; + + return errorcode; +} + +float getNodeValue(ENR_Handle p_handle, int periodIndex, int nodeIndex, + int attr) +// +// Purpose: Retrieves an attribute value at a specified node and time +// +{ + F_OFF offset; + REAL4 y; + data_t* p_data; + + p_data = (data_t*)p_handle; + + // calculate byte offset to start time for series + offset = p_data->outputStartPos + periodIndex*p_data->bytesPerPeriod; + // add byte position for attribute and node + offset += ((attr - 1)*p_data->nodeCount + (nodeIndex - 1))*WORDSIZE; + + _fseek(p_data->file, offset, SEEK_SET); + fread(&y, WORDSIZE, 1, p_data->file); + + return y; +} + +float getLinkValue(ENR_Handle p_handle, int periodIndex, int linkIndex, + int attr) +// +// Purpose: Retrieves an attribute value at a specified link and time +// +{ + F_OFF offset; + REAL4 y; + data_t* p_data; + + p_data = (data_t*)p_handle; + + // Calculate byte offset to start time for series + offset = p_data->outputStartPos + periodIndex*p_data->bytesPerPeriod + + (NNODERESULTS*p_data->nodeCount)*WORDSIZE; + // add byte position for attribute and link + offset += ((attr - 1)*p_data->linkCount + (linkIndex - 1))*WORDSIZE; + + _fseek(p_data->file, offset, SEEK_SET); + fread(&y, WORDSIZE, 1, p_data->file); + + return y; +} + +int _fopen(FILE **f, const char *name, const char *mode) { + // + // Purpose: Substitute for fopen_s on platforms where it doesn't exist + // Note: fopen_s is part of C++11 standard + // + int ret = 0; +#ifdef _WIN32 + ret = (int)fopen_s(f, name, mode); +#else + *f = fopen(name, mode); + if (!*f) + ret = -1; +#endif + return ret; +} + +int _fseek(FILE* stream, F_OFF offset, int whence) +// +// Purpose: Selects platform fseek() for large file support +// +{ +#ifdef _WIN32 // Windows (32-bit and 64-bit) +#define FSEEK64 _fseeki64 +#else // Other platforms +#define FSEEK64 fseeko +#endif + + return FSEEK64(stream, offset, whence); +} + +F_OFF _ftell(FILE* stream) +// +// Purpose: Selects platform ftell() for large file support +// +{ +#ifdef _WIN32 // Windows (32-bit and 64-bit) +#define FTELL64 _ftelli64 +#else // Other platforms +#define FTELL64 ftello +#endif + + return FTELL64(stream); +} + +float* newFloatArray(int n) +// +// Warning: Caller must free memory allocated by this function. +// +{ + return (float*) malloc((n)*sizeof(float)); +} + +int* newIntArray(int n) +// +// Warning: Caller must free memory allocated by this function. +// +{ + return (int*) malloc((n)*sizeof(int)); +} + +char* newCharArray(int n) +// +// Warning: Caller must free memory allocated by this function. +// +{ + return (char*) malloc((n)*sizeof(char)); +} diff --git a/src/outfile/src/messages.h b/src/outfile/src/messages.h new file mode 100644 index 0000000..bc04a7d --- /dev/null +++ b/src/outfile/src/messages.h @@ -0,0 +1,29 @@ +/* + * messages.h - EPANET + * + * Created on: June 1, 2017 + * + * Author: Michael E. Tryby + * US EPA - ORD/NRMRL + */ + +#ifndef MESSAGES_H_ +#define MESSAGES_H_ +/*------------------- Error Messages --------------------*/ +#define MSG_MAXLEN 53 + +#define WARN10 "Warning: model run issued warnings" + +#define ERR411 "Input Error 411: no memory allocated for results" +#define ERR412 "Input Error 412: binary file hasn't been opened" +#define ERR421 "Input Error 421: invalid parameter code" +#define ERR422 "Input Error 422: reporting period index out of range" +#define ERR423 "Input Error 423: element index out of range" + +#define ERR434 "File Error 434: unable to open binary file" +#define ERR435 "File Error 435: invalid binary file type" +#define ERR436 "File Error 436: no results in binary file" + +#define ERRERR "Error: An unknown error has occurred" + +#endif /* MESSAGES_H_ */ diff --git a/src/util/errormanager.c b/src/util/errormanager.c index d8ca078..5a9876c 100644 --- a/src/util/errormanager.c +++ b/src/util/errormanager.c @@ -22,7 +22,7 @@ #include "errormanager.h" -error_handle_t *error_new_manager(void (*p_error_message)(int, char*, int)) +error_handle_t *create_error_manager(void (*p_error_message)(int, char*, int)) // // Purpose: Constructs a new error handle. // @@ -35,7 +35,7 @@ error_handle_t *error_new_manager(void (*p_error_message)(int, char*, int)) return error_handle; } -void error_dst_manager(error_handle_t *error_handle) +void delete_error_manager(error_handle_t *error_handle) // // Purpose: Destroys the error handle. // @@ -43,7 +43,7 @@ void error_dst_manager(error_handle_t *error_handle) free(error_handle); } -int error_set(error_handle_t *error_handle, int error_code) +int set_error(error_handle_t *error_handle, int error_code) // // Purpose: Sets an error code in the handle. // @@ -56,7 +56,7 @@ int error_set(error_handle_t *error_handle, int error_code) return error_code; } -int error_check(error_handle_t *error_handle, char **error_message) +int check_error(error_handle_t *error_handle, char **error_message) // // Purpose: Returns the error message or NULL. // @@ -75,7 +75,7 @@ int error_check(error_handle_t *error_handle, char **error_message) return error_code; } -void error_clear(error_handle_t *error_handle) +void clear_error(error_handle_t *error_handle) // // Purpose: Clears the error from the handle. // diff --git a/src/util/errormanager.h b/src/util/errormanager.h index 5501e0d..6939f35 100644 --- a/src/util/errormanager.h +++ b/src/util/errormanager.h @@ -23,12 +23,12 @@ typedef struct error_s { void (*p_msg_lookup)(int, char*, int); } error_handle_t; -error_handle_t* error_new_manager(void (*p_error_message)(int, char*, int)); -void error_dst_manager(error_handle_t* error_handle); +error_handle_t* create_error_manager(void (*p_error_message)(int, char*, int)); +void delete_error_manager(error_handle_t* error_handle); -int error_set(error_handle_t* error_handle, int error_code); -int error_check(error_handle_t* error_handle, char **error_message); -void error_clear(error_handle_t* error_handle); +int set_error(error_handle_t* error_handle, int error_code); +int check_error(error_handle_t* error_handle, char **error_message); +void clear_error(error_handle_t* error_handle); #if defined(__cplusplus) diff --git a/tests/outfile/CMakeLists.txt b/tests/outfile/CMakeLists.txt new file mode 100644 index 0000000..e7c2de7 --- /dev/null +++ b/tests/outfile/CMakeLists.txt @@ -0,0 +1,19 @@ + + + +enable_testing() + +# Sets for output directory for executables and libraries +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + + +set (Boost_USE_STATIC_LIBS OFF) +find_package(Boost COMPONENTS unit_test_framework) +include_directories (${Boost_INCLUDE_DIRS} ../../src/outfile/include) + + +add_executable(test_errormanager test_output.cpp) + +target_link_libraries(test_errormanager ${Boost_LIBRARIES} epanet-output) diff --git a/tests/test_output.cpp b/tests/outfile/test_output.cpp similarity index 87% rename from tests/test_output.cpp rename to tests/outfile/test_output.cpp index 89feede..eb381b2 100644 --- a/tests/test_output.cpp +++ b/tests/outfile/test_output.cpp @@ -1,5 +1,5 @@ /* - * test_epanet_output.cpp + * test_output.cpp * * Created: 8/4/2017 * Author: Michael E. Tryby @@ -13,17 +13,18 @@ //#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "output" +#define BOOST_TEST_DYN_LINK + #include #include #include #include -#define BOOST_TEST_MODULE "output" -//#include -#include "shared_test.hpp" +#include #include "epanet_output.h" -#include "epanet2_2.h" +//#include "epanet2_2.h" boost::test_tools::predicate_result check_cdd_float(std::vector& test, @@ -60,6 +61,14 @@ boost::test_tools::predicate_result check_cdd_float(std::vector& test, return floor(min_cdd) >= cdd_tol; } +boost::test_tools::predicate_result check_string(std::string test, std::string ref) +{ + if (ref.compare(test) == 0) + return true; + else + return false; +} + #define DATA_PATH_OUTPUT "./example1.out" @@ -85,45 +94,45 @@ BOOST_AUTO_TEST_CASE(OpenCloseTest) { } -// Test access to output file with the project open -BOOST_AUTO_TEST_CASE(AccessTest){ - - std::string path_inp(DATA_PATH_NET1); - std::string path_rpt(DATA_PATH_RPT); - std::string path_out(DATA_PATH_OUT); - - EN_Project ph = NULL; - ENR_Handle p_handle = NULL; - - EN_createproject(&ph); - - int error = EN_open(ph, path_inp.c_str(), path_rpt.c_str(), path_out.c_str()); - BOOST_REQUIRE(error == 0); - - error = EN_solveH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_solveQ(ph); - BOOST_REQUIRE(error == 0); - - error = EN_report(ph); - BOOST_REQUIRE(error == 0); - - - // Access to output file prior to project close - error = ENR_init(&p_handle); - BOOST_REQUIRE(error == 0); - error = ENR_open(p_handle, path_out.c_str()); - BOOST_REQUIRE(error == 0); - error = ENR_close(&p_handle); - BOOST_REQUIRE(error == 0); - - - error = EN_close(ph); - BOOST_REQUIRE(error == 0); - - EN_deleteproject(&ph); -} +// // Test access to output file with the project open +// BOOST_AUTO_TEST_CASE(AccessTest){ +// +// std::string path_inp(DATA_PATH_NET1); +// std::string path_rpt(DATA_PATH_RPT); +// std::string path_out(DATA_PATH_OUT); +// +// EN_Project ph = NULL; +// ENR_Handle p_handle = NULL; +// +// EN_createproject(&ph); +// +// int error = EN_open(ph, path_inp.c_str(), path_rpt.c_str(), path_out.c_str()); +// BOOST_REQUIRE(error == 0); +// +// error = EN_solveH(ph); +// BOOST_REQUIRE(error == 0); +// +// error = EN_solveQ(ph); +// BOOST_REQUIRE(error == 0); +// +// error = EN_report(ph); +// BOOST_REQUIRE(error == 0); +// +// +// // Access to output file prior to project close +// error = ENR_init(&p_handle); +// BOOST_REQUIRE(error == 0); +// error = ENR_open(p_handle, path_out.c_str()); +// BOOST_REQUIRE(error == 0); +// error = ENR_close(&p_handle); +// BOOST_REQUIRE(error == 0); +// +// +// error = EN_close(ph); +// BOOST_REQUIRE(error == 0); +// +// EN_deleteproject(&ph); +// } BOOST_AUTO_TEST_SUITE_END() From 80ce382a387dfacc58d8e675055a58f35837994f Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Wed, 20 Mar 2019 18:01:11 -0400 Subject: [PATCH 03/16] Removing epanet-output from tools folder epanet-output has been moved to epanet/src/outfile --- tools/epanet-output/CMakeLists.txt | 40 - tools/epanet-output/include/epanet_output.h | 82 -- .../include/epanet_output_enums.h | 79 -- tools/epanet-output/setup.py | 41 - tools/epanet-output/src/epanet_output.c | 1000 ----------------- tools/epanet-output/src/epanet_output.i | 203 ---- tools/epanet-output/src/errormanager.c | 74 -- tools/epanet-output/src/errormanager.h | 27 - tools/epanet-output/src/messages.h | 29 - tools/epanet-output/test/data/__init__.py | 14 - tools/epanet-output/test/data/net1.out | Bin 16832 -> 0 bytes .../epanet-output/test/test_epanet_output.cpp | 251 ----- 12 files changed, 1840 deletions(-) delete mode 100644 tools/epanet-output/CMakeLists.txt delete mode 100644 tools/epanet-output/include/epanet_output.h delete mode 100644 tools/epanet-output/include/epanet_output_enums.h delete mode 100644 tools/epanet-output/setup.py delete mode 100644 tools/epanet-output/src/epanet_output.c delete mode 100644 tools/epanet-output/src/epanet_output.i delete mode 100644 tools/epanet-output/src/errormanager.c delete mode 100644 tools/epanet-output/src/errormanager.h delete mode 100644 tools/epanet-output/src/messages.h delete mode 100644 tools/epanet-output/test/data/__init__.py delete mode 100644 tools/epanet-output/test/data/net1.out delete mode 100644 tools/epanet-output/test/test_epanet_output.cpp diff --git a/tools/epanet-output/CMakeLists.txt b/tools/epanet-output/CMakeLists.txt deleted file mode 100644 index 0d85da4..0000000 --- a/tools/epanet-output/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -# -# CMakeLists.txt - CMake configuration file for epanet-output library -# -# Created: March 9, 2018 -# Author: Michael E. Tryby -# US EPA ORD/NRMRL -# - -cmake_minimum_required (VERSION 3.0) - - -# Sets for output directory for executables and libraries. -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - - -set(CMAKE_C_VISIBILITY_PRESET hidden) -set(CMAKE_CXX_VISIBILITY_PRESET hidden) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_INCLUDE_CURRENT_DIR ON) - - -# configure file groups -set(EPANET_OUT_SOURCES src/epanet_output.c src/errormanager.c) - - -# the binary output file API -add_library(epanet-output SHARED ${EPANET_OUT_SOURCES}) -target_include_directories(epanet-output PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) - -include(GenerateExportHeader) -generate_export_header(epanet-output - BASE_NAME epanet_output - EXPORT_MACRO_NAME EXPORT_OUT_API - EXPORT_FILE_NAME epanet_output_export.h - STATIC_DEFINE SHARED_EXPORTS_BUILT_AS_STATIC) - -file(COPY ${CMAKE_CURRENT_BINARY_DIR}/epanet_output_export.h DESTINATION - ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/tools/epanet-output/include/epanet_output.h b/tools/epanet-output/include/epanet_output.h deleted file mode 100644 index 9c06522..0000000 --- a/tools/epanet-output/include/epanet_output.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * epanet_output.h - EPANET Output API - * - * Created on: Jun 4, 2014 - * - * Author: Michael E. Tryby - * US EPA - ORD/NRMRL - */ - -#ifndef EPANET_OUTPUT_H_ -#define EPANET_OUTPUT_H_ -/* Epanet Results binary file API */ - - -#define MAXFNAME 259 // Max characters in file name -#define MAXID 31 // Max characters in ID name - - -// This is an opaque pointer to struct. Do not access variables. -typedef void* ENR_Handle; - - -#include "epanet_output_enums.h" -#include "epanet_output_export.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -int EXPORT_OUT_API ENR_init(ENR_Handle* p_handle_out); - -int EXPORT_OUT_API ENR_open(ENR_Handle p_handle_in, const char* path); - -int EXPORT_OUT_API ENR_getVersion(ENR_Handle p_handle_in, int* int_out); - -int EXPORT_OUT_API ENR_getNetSize(ENR_Handle p_handle_in, int** int_out, int* int_dim); - -int EXPORT_OUT_API ENR_getUnits(ENR_Handle p_handle_in, ENR_Units t_enum, int* int_out); - -int EXPORT_OUT_API ENR_getTimes(ENR_Handle p_handle_in, ENR_Time t_enum, int* int_out); - -int EXPORT_OUT_API ENR_getElementName(ENR_Handle p_handle_in, ENR_ElementType t_enum, - int elementIndex, char** string_out, int* slen); - -int EXPORT_OUT_API ENR_getEnergyUsage(ENR_Handle p_handle_in, int pumpIndex, - int* int_out, float** float_out, int* int_dim); - -int EXPORT_OUT_API ENR_getNetReacts(ENR_Handle p_handle_in, float** float_out, int* int_dim); - - -int EXPORT_OUT_API ENR_getNodeSeries(ENR_Handle p_handle_in, int nodeIndex, ENR_NodeAttribute t_enum, - int startPeriod, int endPeriod, float** outValueSeries, int* dim); - -int EXPORT_OUT_API ENR_getLinkSeries(ENR_Handle p_handle_in, int linkIndex, ENR_LinkAttribute t_enum, - int startPeriod, int endPeriod, float** outValueSeries, int* dim); - -int EXPORT_OUT_API ENR_getNodeAttribute(ENR_Handle p_handle_in, int periodIndex, - ENR_NodeAttribute t_enum, float** outValueArray, int* dim); - -int EXPORT_OUT_API ENR_getLinkAttribute(ENR_Handle p_handle_in, int periodIndex, - ENR_LinkAttribute t_enum, float** outValueArray, int* dim); - -int EXPORT_OUT_API ENR_getNodeResult(ENR_Handle p_handle_in, int periodIndex, int nodeIndex, - float** float_out, int* int_dim); - -int EXPORT_OUT_API ENR_getLinkResult(ENR_Handle p_handle_in, int periodIndex, int linkIndex, - float** float_out, int* int_dim); - -int EXPORT_OUT_API ENR_close(ENR_Handle* p_handle_out); - -void EXPORT_OUT_API ENR_free(void** array); - -void EXPORT_OUT_API ENR_clearError(ENR_Handle p_handle_in); - -int EXPORT_OUT_API ENR_checkError(ENR_Handle p_handle_in, char** msg_buffer); - -#ifdef __cplusplus -} -#endif - -#endif /* EPANET_OUTPUT_H_ */ diff --git a/tools/epanet-output/include/epanet_output_enums.h b/tools/epanet-output/include/epanet_output_enums.h deleted file mode 100644 index 0fa012f..0000000 --- a/tools/epanet-output/include/epanet_output_enums.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * epanet_output_enums.h - EPANET Output API enums - * - * Created on: March 11, 2019 - * - * Author: Michael E. Tryby - * US EPA - ORD/NRMRL - */ - - -#ifndef EPANET_OUTPUT_ENUMS_H_ -#define EPANET_OUTPUT_ENUMS_H_ - - -typedef enum { - ENR_node = 1, - ENR_link = 2 -} ENR_ElementType; - -typedef enum { - ENR_flowUnits = 1, - ENR_pressUnits = 2, - ENR_qualUnits = 3 -} ENR_Units; - -typedef enum { - ENR_CFS = 0, - ENR_GPM = 1, - ENR_MGD = 2, - ENR_IMGD = 3, - ENR_AFD = 4, - ENR_LPS = 5, - ENR_LPM = 6, - ENR_MLD = 7, - ENR_CMH = 8, - ENR_CMD = 9 -} ENR_FlowUnits; - -typedef enum { - ENR_PSI = 0, - ENR_MTR = 1, - ENR_KPA = 2 -} ENR_PressUnits; - -typedef enum { - ENR_NONE = 0, - ENR_MGL = 1, - ENR_UGL = 2, - ENR_HOURS = 3, - ENR_PRCNT = 4 -} ENR_QualUnits; - -typedef enum { - ENR_reportStart = 1, - ENR_reportStep = 2, - ENR_simDuration = 3, - ENR_numPeriods = 4 -}ENR_Time; - -typedef enum { - ENR_demand = 1, - ENR_head = 2, - ENR_pressure = 3, - ENR_quality = 4 -} ENR_NodeAttribute; - -typedef enum { - ENR_flow = 1, - ENR_velocity = 2, - ENR_headloss = 3, - ENR_avgQuality = 4, - ENR_status = 5, - ENR_setting = 6, - ENR_rxRate = 7, - ENR_frctnFctr = 8 -} ENR_LinkAttribute; - - -#endif /* EPANET_OUTPUT_ENUMS_H_ */ diff --git a/tools/epanet-output/setup.py b/tools/epanet-output/setup.py deleted file mode 100644 index 92881ce..0000000 --- a/tools/epanet-output/setup.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# -# setup.py -# -# Created: 9/20/2017 -# Author: Michael E. Tryby -# US EPA - ORD/NRMRL -# -# Setup up script for en_outputapi python extension -# -# Requires: -# Platform C language compiler -# Python packages: numpy -# - -try: - from setuptools import setup, Extension - from setuptools.command.build_ext import build_ext -except ImportError: - from distutils.core import setup, Extension - from distutils.command.build_ext import build_ext - -setup( - name = "epanet-output", - version = "0.1.0-alpha", - ext_modules = [ - Extension("_epanet_output", - define_macros = [('epanet_output_EXPORTS', None)], - include_dirs = ['include'], - sources = ['src/epanet_output.i', 'src/epanet_output.c', 'src/errormanager.c'], - swig_opts=['-modern'], - language = 'C' - ) - ], - package_dir = {'':'src'}, - py_modules = ['epanet_output'], - - install_requires = [ - 'enum34' - ] -) diff --git a/tools/epanet-output/src/epanet_output.c b/tools/epanet-output/src/epanet_output.c deleted file mode 100644 index eef6957..0000000 --- a/tools/epanet-output/src/epanet_output.c +++ /dev/null @@ -1,1000 +0,0 @@ -//----------------------------------------------------------------------------- -// -// epanet_output.c -- API for reading results from EPANET binary output file -// -// Version: 0.30 -// Date 09/06/2017 -// 06/17/2016 -// 08/05/2014 -// 05/21/2014 -// -// Author: Michael E. Tryby -// US EPA - ORD/NRMRL -// -// Modified: Maurizio Cingi -// University of Modena -// -// Purpose: Output API provides an interface for retrieving results from an -// EPANET binary output file. -// -// Output data in the binary file are aligned on a 4 byte word size. -// Therefore all values both integers and reals are 32 bits in length. -// -// All values returned by the output API are indexed from 0 to n-1. This -// differs from how node and link elements are indexed by the binary file -// writer found in EPANET. Times correspond to reporting periods are indexed -// from 0 to number of reporting periods minus one. Node and link elements -// are indexed from 0 to nodeCount minus one and 0 to linkCount minus one -// respectively. -// -// The Output API functions provide a convenient way to select "slices" of -// data from the output file. As such they return arrays of data. The API -// functions automatically allocate memory for the array to be returned. The -// caller is responsible for deallocating memory. The function ENR_free() is -// provided for that purpose. -// -//----------------------------------------------------------------------------- - -#include "epanet_output.h" - -#include -#include -#include - -#include "errormanager.h" -#include "messages.h" - -// NOTE: These depend on machine data model and may change when porting -// F_OFF Must be a 8 byte / 64 bit integer for large file support -#ifdef _WIN32 // Windows (32-bit and 64-bit) -#define F_OFF __int64 -#else // Other platforms -#define F_OFF off_t -#endif -#define INT4 int // Must be a 4 byte / 32 bit integer type -#define REAL4 float // Must be a 4 byte / 32 bit real type -#define WORDSIZE 4 // Memory alignment 4 byte word size for both int and real - -#define MINNREC 14 // Minimum allowable number of records -#define PROLOGUE 884 // Preliminary fixed length section of header -#define MAXID_P1 32 // EPANET max characters in ID name PLUS 1 -#define MAXMSG_P1 80 // EPANET max characters in message text PLUS 1 - -#define NELEMENTTYPES 5 // Number of element types -#define NENERGYRESULTS 6 // Number of energy results -#define NNODERESULTS 4 // number of result fields for nodes -#define NLINKRESULTS 8 // number of result fields for links -#define NREACTRESULTS 4 // number of net reaction results - -#define MEMCHECK(x) (((x) == NULL) ? 411 : 0 ) - -// Typedefs for opaque pointer -typedef struct data_s { - char name[MAXFNAME+1]; // file path/name - FILE* file; // FILE structure pointer - INT4 nodeCount, tankCount, linkCount, pumpCount, valveCount, nPeriods; - F_OFF outputStartPos; // starting file position of output data - F_OFF bytesPerPeriod; // bytes saved per simulation time period - - error_handle_t* error_handle; -} data_t; - -//----------------------------------------------------------------------------- -// Local functions -//----------------------------------------------------------------------------- -void errorLookup(int errcode, char* errmsg, int length); -int validateFile(ENR_Handle); -float getNodeValue(ENR_Handle, int, int, int); -float getLinkValue(ENR_Handle, int, int, int); - -int _fopen(FILE **f, const char *name, const char *mode); -int _fseek(FILE* stream, F_OFF offset, int whence); -F_OFF _ftell(FILE* stream); - -float* newFloatArray(int n); -int* newIntArray(int n); -char* newCharArray(int n); - - -int EXPORT_OUT_API ENR_init(ENR_Handle* dp_handle) -// Purpose: Initialized pointer for the opaque ENR_Handle. -// -// Returns: Error code 0 on success, -1 on failure -// -// Note: The existence of this function has been carefully considered. -// Don't change it. -// -{ - int errorcode = 0; - data_t* p_data; - - // Allocate memory for private data - p_data = (data_t*)calloc(1, sizeof(data_t)); - - if (p_data != NULL){ - p_data->error_handle = new_errormanager(&errorLookup); - *dp_handle = p_data; - } - else - errorcode = -1; - - // TODO: Need to handle errors during initialization better. - return errorcode; -} - -int EXPORT_OUT_API ENR_close(ENR_Handle* p_handle) -/*------------------------------------------------------------------------ - ** Input: *p_handle = pointer to ENR_Handle struct - ** - ** Returns: Error code 0 on success, -1 on failure - ** - ** Purpose: Close the output binary file, dellocate ENR_Handle struc - ** and nullify pointer to ENR_Handle struct - ** - ** NOTE: ENR_close must be called before program end - ** after calling ENR_close data in ENR_Handle struct are no more - ** accessible - **------------------------------------------------------------------------- - */ -{ - data_t* p_data; - int errorcode = 0; - - p_data = (data_t*)(*p_handle); - - if (p_data == NULL || p_data->file == NULL) - errorcode = -1; - - else - { - dst_errormanager(p_data->error_handle); - fclose(p_data->file); - free(p_data); - - *p_handle = NULL; - } - - return errorcode; -} - -int EXPORT_OUT_API ENR_open(ENR_Handle p_handle, const char* path) -/*------------------------------------------------------------------------ - ** Input: path - ** Output: p_handle = pointer to ENR_Handle struct - ** Returns: warning / error code - ** Purpose: Opens the output binary file and reads prologue and epilogue - ** - ** NOTE: ENR_init must be called before anyother ENR_* functions - **------------------------------------------------------------------------- - */ -{ - int err, errorcode = 0; - F_OFF bytecount; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else - { - strncpy(p_data->name, path, MAXFNAME); - // Attempt to open binary output file for reading only - if ((_fopen(&(p_data->file), path, "rb")) != 0) errorcode = 434; - - // Perform checks to insure the file is valid - else if ((err = validateFile(p_data)) != 0) errorcode = err; - - // If a warning is encountered read file header - if (errorcode < 400 ) { - - // read network size - fseek(p_data->file, 2*WORDSIZE, SEEK_SET); - fread(&(p_data->nodeCount), WORDSIZE, 1, p_data->file); - fread(&(p_data->tankCount), WORDSIZE, 1, p_data->file); - fread(&(p_data->linkCount), WORDSIZE, 1, p_data->file); - fread(&(p_data->pumpCount), WORDSIZE, 1, p_data->file); - fread(&(p_data->valveCount), WORDSIZE, 1, p_data->file); - - // Compute positions and offsets for retrieving data - // fixed portion of header + title section + filenames + chem names - bytecount = PROLOGUE; - // node names + link names - bytecount += MAXID_P1*p_data->nodeCount + MAXID_P1*p_data->linkCount; - // network connectivity + tank nodes + tank areas - bytecount += 3*WORDSIZE*p_data->linkCount + 2*WORDSIZE*p_data->tankCount; - // node elevations + link lengths and link diameters - bytecount += WORDSIZE*p_data->nodeCount + 2*WORDSIZE*p_data->linkCount; - // pump energy summary - bytecount += 7*WORDSIZE*p_data->pumpCount + WORDSIZE; - p_data->outputStartPos= bytecount; - - p_data->bytesPerPeriod = NNODERESULTS*WORDSIZE*p_data->nodeCount + - NLINKRESULTS*WORDSIZE*p_data->linkCount; - } - } - // If error close the binary file - if (errorcode > 400) { - set_error(p_data->error_handle, errorcode); - ENR_close(&p_handle); - } - - return errorcode; -} - -int EXPORT_OUT_API ENR_getVersion(ENR_Handle p_handle, int* version) -/*------------------------------------------------------------------------ - ** Input: p_handle = pointer to ENR_Handle struct - ** Output: version Epanet version - ** Returns: error code - ** - ** Purpose: Returns Epanet version that wrote EBOFile - **--------------element codes------------------------------------------- - */ -{ - int errorcode = 0; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else - { - fseek(p_data->file, 1*WORDSIZE, SEEK_SET); - if (fread(version, WORDSIZE, 1, p_data->file) != 1) - errorcode = 436; - } - - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getNetSize(ENR_Handle p_handle, int** elementCount, int* length) -/*------------------------------------------------------------------------ - ** Input: p_handle = pointer to ENR_Handle struct - ** Output: array of element counts (nodes, tanks, links, pumps, valves) - ** Returns: error code - ** Purpose: Returns an array of count values - **------------------------------------------------------------------------- - */ -{ - int errorcode = 0; - int* temp = newIntArray(NELEMENTTYPES); - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else - { - temp[0] = p_data->nodeCount; - temp[1] = p_data->tankCount; - temp[2] = p_data->linkCount; - temp[3] = p_data->pumpCount; - temp[4] = p_data->valveCount; - - *elementCount = temp; - *length = NELEMENTTYPES; - } - - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getUnits(ENR_Handle p_handle, ENR_Units code, int* unitFlag) -/*------------------------------------------------------------------------ - ** Input: p_handle = pointer to ENR_Handle struct - ** code - ** Output: count - ** Returns: unitFlag - ** Purpose: Returns pressure or flow unit flag - **--------------pressure unit flags---------------------------------------- - ** 0 = psi - ** 1 = meters - ** 2 = kPa - **------------------flow unit flags---------------------------------------- - ** 0 = cubic feet/second - ** 1 = gallons/minute - ** 2 = million gallons/day - ** 3 = Imperial million gallons/day - ** 4 = acre-ft/day - ** 5 = liters/second - ** 6 = liters/minute - ** 7 = megaliters/day - ** 8 = cubic meters/hour - ** 9 = cubic meters/day - **------------------------------------------------------------------------- - */ -{ - int errorcode = 0; - F_OFF offset; - char temp[MAXID_P1]; - data_t* p_data; - - *unitFlag = -1; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else - { - switch (code) - { - case ENR_flowUnits: - _fseek(p_data->file, 9*WORDSIZE, SEEK_SET); - fread(unitFlag, WORDSIZE, 1, p_data->file); - break; - - case ENR_pressUnits: - _fseek(p_data->file, 10*WORDSIZE, SEEK_SET); - fread(unitFlag, WORDSIZE, 1, p_data->file); - break; - - case ENR_qualUnits: - offset = 7*WORDSIZE; - _fseek(p_data->file, offset, SEEK_SET); - fread(unitFlag, WORDSIZE, 1, p_data->file); - - if (*unitFlag == 0) *unitFlag = ENR_NONE; - - else if (*unitFlag == 1) { - offset = 15*WORDSIZE + 3*MAXMSG_P1 + 2*(MAXFNAME+1) + MAXID_P1; - _fseek(p_data->file, offset, SEEK_SET); - fread(temp, MAXID_P1, 1, p_data->file); - - if (!strcmp(temp, "mg/L")) *unitFlag = ENR_MGL; - else *unitFlag = ENR_UGL; - } - - else if (*unitFlag == 2) *unitFlag = ENR_HOURS; - - else *unitFlag = ENR_PRCNT; - - break; - - default: errorcode = 421; - } - } - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getTimes(ENR_Handle p_handle, ENR_Time code, int* time) -/*------------------------------------------------------------------------ - ** Input: p_handle = pointer to ENR_Handle struct - ** code = element code - ** Output: time - ** Returns: error code - ** Purpose: Returns report and simulation time related parameters. - **------------------------------------------------------------------------- - */ -{ - int errorcode = 0; - data_t* p_data; - - *time = -1; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else - { - switch (code) - { - case ENR_reportStart: - fseek(p_data->file, 12*WORDSIZE, SEEK_SET); - fread(time, WORDSIZE, 1, p_data->file); - break; - - case ENR_reportStep: - fseek(p_data->file, 13*WORDSIZE, SEEK_SET); - fread(time, WORDSIZE, 1, p_data->file); - break; - - case ENR_simDuration: - fseek(p_data->file, 14*WORDSIZE, SEEK_SET); - fread(time, WORDSIZE, 1, p_data->file); - break; - - case ENR_numPeriods: - *time = p_data->nPeriods; - break; - - default: - errorcode = 421; - } - } - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getChemData(ENR_Handle p_handle, char** name, int* length) - -{ - return 0; -} - -int EXPORT_OUT_API ENR_getElementName(ENR_Handle p_handle, ENR_ElementType type, - int elementIndex, char** name, int* length) -/*------------------------------------------------------------------------ - ** Input: p_handle = pointer to ENR_Handle struct - ** type = ENR_node or ENR_link - ** elementIndex from 1 to nodeCount or 1 to linkCount - ** Output: name = elementName - ** Returns: error code - ** Purpose: Retrieves Name of a specified node or link element - ** NOTE: 'name' must be able to hold MAXID characters - ** TODO: Takes EPANET indexing from 1 to n not 0 to n-1 - **------------------------------------------------------------------------- - */ -{ - F_OFF offset; - int errorcode = 0; - char* temp; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - /* Allocate memory for name */ - else if MEMCHECK(temp = newCharArray(MAXID_P1)) errorcode = 411; - - else - { - switch (type) - { - case ENR_node: - if (elementIndex < 1 || elementIndex > p_data->nodeCount) - errorcode = 423; - else offset = PROLOGUE + (elementIndex - 1)*MAXID_P1; - break; - - case ENR_link: - if (elementIndex < 1 || elementIndex > p_data->linkCount) - errorcode = 423; - else - offset = PROLOGUE + p_data->nodeCount*MAXID_P1 + - (elementIndex - 1)*MAXID_P1; - break; - - default: - errorcode = 421; - } - - if (!errorcode) - { - _fseek(p_data->file, offset, SEEK_SET); - fread(temp, 1, MAXID_P1, p_data->file); - - *name = temp; - *length = MAXID_P1; - } - } - - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getEnergyUsage(ENR_Handle p_handle, int pumpIndex, - int* linkIndex, float** outValues, int* length) -/* - * Purpose: Returns pump energy usage statistics. - * - * Energy usage statistics: - * 0 = pump utilization - * 1 = avg. efficiency - * 2 = avg. kW/flow - * 3 = avg. kwatts - * 4 = peak kwatts - * 5 = cost/day - */ -{ - F_OFF offset; - int errorcode = 0; - float* temp; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - // Check for valid pump index - else if (pumpIndex < 1 || pumpIndex > p_data->pumpCount) errorcode = 423; - // Check memory for outValues - else if MEMCHECK(temp = newFloatArray(NENERGYRESULTS)) errorcode = 411; - - else - { - // Position offset to start of pump energy summary - offset = p_data->outputStartPos - (p_data->pumpCount*(WORDSIZE + 6*WORDSIZE) + WORDSIZE); - // Adjust offset by pump index - offset += (pumpIndex - 1)*(WORDSIZE + 6*WORDSIZE); - - // Power summary is 1 int and 6 floats for each pump - _fseek(p_data->file, offset, SEEK_SET); - fread(linkIndex, WORDSIZE, 1, p_data->file); - fread(temp, WORDSIZE, 6, p_data->file); - - *outValues = temp; - *length = NENERGYRESULTS; - } - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getNetReacts(ENR_Handle p_handle, float** outValues, int* length) -/* - * Purpose: Returns network wide average reaction rates and average - * source mass inflow: - * 0 = bulk - * 1 = wall - * 2 = tank - * 3 = source - */ -{ - F_OFF offset; - int errorcode = 0; - float* temp; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - // Check memory for outValues - else if MEMCHECK(temp = newFloatArray(NREACTRESULTS)) errorcode = 411; - - else - { - // Reaction summary is 4 floats located right before epilogue. - // This offset is relative to the end of the file. - offset = - 3*WORDSIZE - 4*WORDSIZE; - _fseek(p_data->file, offset, SEEK_END); - fread(temp, WORDSIZE, 4, p_data->file); - - *outValues = temp; - *length = NREACTRESULTS; - } - return set_error(p_data->error_handle, errorcode); -} - -void EXPORT_OUT_API ENR_free(void** array) -// -// Purpose: Frees memory allocated by API calls -// -{ - if (array != NULL) { - free(*array); - *array = NULL; - } -} - -int EXPORT_OUT_API ENR_getNodeSeries(ENR_Handle p_handle, int nodeIndex, ENR_NodeAttribute attr, - int startPeriod, int endPeriod, float** outValueSeries, int* dim) -// -// Purpose: Get time series results for particular attribute. Specify series -// start and length using seriesStart and seriesLength respectively. -// -// NOTE: The node index argument corresponds to the EPANET node index from 1 to -// nnodes. The series returned is indexed from 0 to nperiods - 1. -// -{ - int k, length, errorcode = 0; - float* temp; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else if (nodeIndex < 1 || nodeIndex > p_data->nodeCount) errorcode = 423; - else if (startPeriod < 0 || endPeriod >= p_data->nPeriods || - endPeriod <= startPeriod) errorcode = 422; - // Check memory for outValues - else if MEMCHECK(temp = newFloatArray(length = endPeriod - startPeriod)) errorcode = 411; - else - { - // loop over and build time series - for (k = 0; k < length; k++) - temp[k] = getNodeValue(p_handle, startPeriod + k, - nodeIndex, attr); - - *outValueSeries = temp; - *dim = length; - } - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getLinkSeries(ENR_Handle p_handle, int linkIndex, ENR_LinkAttribute attr, - int startPeriod, int endPeriod, float** outValueSeries, int* dim) -// -// Purpose: Get time series results for particular attribute. Specify series -// start and length using seriesStart and seriesLength respectively. -// -// NOTE: -// The link index argument corresponds to the EPANET link index from 1 to -// nlinks. The series returned is indexed from 0 to nperiods - 1. -// -{ - int k, length, errorcode = 0; - float* temp; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else if (linkIndex < 1 || linkIndex > p_data->linkCount) errorcode = 423; - else if (startPeriod < 0 || endPeriod >= p_data->nPeriods || - endPeriod <= startPeriod) errorcode = 422; - // Check memory for outValues - else if MEMCHECK(temp = newFloatArray(length = endPeriod - startPeriod)) errorcode = 411; - else - { - // loop over and build time series - for (k = 0; k < length; k++) - temp[k] = getLinkValue(p_handle, startPeriod + k, linkIndex, attr); - - *outValueSeries = temp; - *dim = length; - } - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getNodeAttribute(ENR_Handle p_handle, int periodIndex, - ENR_NodeAttribute attr, float** outValueArray, int* length) -// -// Purpose: -// For all nodes at given time, get a particular attribute -// -// Returns: -// Error code -// OutValueArray of results is indexed from 0 to nodeCount -// -// Warning: -// Caller must free memory allocated for outValueArray -// -// NOTE: -// The array returned is indexed from 0 to nnodes - 1. So to access -// node values by their EPANET index, the index value must be -// decremented by one. -// -{ - F_OFF offset; - int errorcode = 0; - float * temp; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - // if the time index is out of range return an error - else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422; - // Check memory for outValues - else if MEMCHECK(temp = newFloatArray(p_data->nodeCount)) errorcode = 411; - - else - { - // calculate byte offset to start time for series - offset = p_data->outputStartPos + (periodIndex)*p_data->bytesPerPeriod; - // add offset for node and attribute - offset += ((attr - 1)*p_data->nodeCount)*WORDSIZE; - - _fseek(p_data->file, offset, SEEK_SET); - fread(temp, WORDSIZE, p_data->nodeCount, p_data->file); - - *outValueArray = temp; - *length = p_data->nodeCount; - } - - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getLinkAttribute(ENR_Handle p_handle, int periodIndex, - ENR_LinkAttribute attr, float** outValueArray, int* length) -// -// Purpose: -// For all links at given time, get a particular attribute -// -// Returns: -// Error code -// OutValueArray of results is indexed from 0 to linkCount -// -// Warning: -// Caller must free memory allocated for outValueArray -// -// NOTE: -// The array returned is indexed from 0 to nlinks - 1. So to access -// link values by their EPANET index, the index value must be -// decremented by one. -// -{ - F_OFF offset; - int errorcode = 0; - float* temp; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - // if the time index is out of range return an error - else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422; - // Check memory for outValues - else if MEMCHECK(temp = newFloatArray(p_data->linkCount)) errorcode = 411; - - else - { - // calculate byte offset to start time for series - offset = p_data->outputStartPos + (periodIndex)*p_data->bytesPerPeriod - + (NNODERESULTS*p_data->nodeCount)*WORDSIZE; - // add offset for link and attribute - offset += ((attr - 1)*p_data->linkCount)*WORDSIZE; - - _fseek(p_data->file, offset, SEEK_SET); - fread(temp, WORDSIZE, p_data->linkCount, p_data->file); - - *outValueArray = temp; - *length = p_data->linkCount; - } - - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getNodeResult(ENR_Handle p_handle, int periodIndex, - int nodeIndex, float** outValueArray, int* length) -// -// Purpose: For a node at given time, get all attributes. -// -// NOTE: -// -{ - int j, errorcode = 0; - float* temp; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422; - else if (nodeIndex < 1 || nodeIndex > p_data->nodeCount) errorcode = 423; - else if MEMCHECK(temp = newFloatArray(NNODERESULTS)) errorcode = 411; - else - { - for (j = 0; j < NNODERESULTS; j++) - temp[j] = getNodeValue(p_handle, periodIndex, nodeIndex, j); - - *outValueArray = temp; - *length = NNODERESULTS; - } - - return set_error(p_data->error_handle, errorcode); -} - -int EXPORT_OUT_API ENR_getLinkResult(ENR_Handle p_handle, int periodIndex, - int linkIndex, float** outValueArray, int* length) -// -// Purpose: For a link at given time, get all attributes -// -{ - int j, errorcode = 0; - float* temp; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else if (periodIndex < 0 || periodIndex >= p_data->nPeriods) errorcode = 422; - else if (linkIndex < 1 || linkIndex > p_data->linkCount) errorcode = 423; - else if MEMCHECK(temp = newFloatArray(NLINKRESULTS)) errorcode = 411; - else - { - for (j = 0; j < NLINKRESULTS; j++) - temp[j] = getLinkValue(p_handle, periodIndex, linkIndex, j); - - *outValueArray = temp; - *length = NLINKRESULTS; - } - return set_error(p_data->error_handle, errorcode); -} - -void EXPORT_OUT_API ENR_clearError(ENR_Handle p_handle) -{ - data_t* p_data; - - p_data = (data_t*)p_handle; - clear_error(p_data->error_handle); -} - -int EXPORT_OUT_API ENR_checkError(ENR_Handle p_handle, char** msg_buffer) -{ - int errorcode = 0; - char *temp = NULL; - data_t* p_data; - - p_data = (data_t*)p_handle; - - if (p_data == NULL) return -1; - else - { - errorcode = p_data->error_handle->error_status; - if (errorcode) - temp = check_error(p_data->error_handle); - - *msg_buffer = temp; - } - - return errorcode; -} - - -void errorLookup(int errcode, char* dest_msg, int dest_len) -// -// Purpose: takes error code returns error message -// -{ - const char* msg; - - switch (errcode) - { - case 10: msg = WARN10; - break; - case 411: msg = ERR411; - break; - case 412: msg = ERR412; - break; - case 421: msg = ERR421; - break; - case 422: msg = ERR422; - break; - case 423: msg = ERR423; - break; - case 434: msg = ERR434; - break; - case 435: msg = ERR435; - break; - case 436: msg = ERR436; - break; - default: msg = ERRERR; - } - - strncpy(dest_msg, msg, MSG_MAXLEN); -} - -int validateFile(ENR_Handle p_handle) -// Returns: -// Error code: 435, 436 -// Warning code: 10 -{ - INT4 magic1, magic2, hydcode; - int errorcode = 0; - F_OFF filepos; - data_t* p_data; - - p_data = (data_t*)p_handle; - - // Read magic number from beginning of file - fseek(p_data->file, 0L, SEEK_SET); - fread(&magic1, WORDSIZE, 1, p_data->file); - - // Fast forward to end and read file epilogue - fseek(p_data->file, -3*WORDSIZE, SEEK_END); - fread(&(p_data->nPeriods), WORDSIZE, 1, p_data->file); - fread(&hydcode, WORDSIZE, 1, p_data->file); - fread(&magic2, WORDSIZE, 1, p_data->file); - - filepos = _ftell(p_data->file); - - // Is the file an EPANET binary file? - if (magic1 != magic2) errorcode = 435; - // Does the binary file contain results? - else if (filepos < MINNREC*WORDSIZE || p_data->nPeriods == 0) - errorcode = 436; - // Issue warning if there were problems with the model run. - else if (hydcode != 0) errorcode = 10; - - return errorcode; -} - -float getNodeValue(ENR_Handle p_handle, int periodIndex, int nodeIndex, - int attr) -// -// Purpose: Retrieves an attribute value at a specified node and time -// -{ - F_OFF offset; - REAL4 y; - data_t* p_data; - - p_data = (data_t*)p_handle; - - // calculate byte offset to start time for series - offset = p_data->outputStartPos + periodIndex*p_data->bytesPerPeriod; - // add byte position for attribute and node - offset += ((attr - 1)*p_data->nodeCount + (nodeIndex - 1))*WORDSIZE; - - _fseek(p_data->file, offset, SEEK_SET); - fread(&y, WORDSIZE, 1, p_data->file); - - return y; -} - -float getLinkValue(ENR_Handle p_handle, int periodIndex, int linkIndex, - int attr) -// -// Purpose: Retrieves an attribute value at a specified link and time -// -{ - F_OFF offset; - REAL4 y; - data_t* p_data; - - p_data = (data_t*)p_handle; - - // Calculate byte offset to start time for series - offset = p_data->outputStartPos + periodIndex*p_data->bytesPerPeriod - + (NNODERESULTS*p_data->nodeCount)*WORDSIZE; - // add byte position for attribute and link - offset += ((attr - 1)*p_data->linkCount + (linkIndex - 1))*WORDSIZE; - - _fseek(p_data->file, offset, SEEK_SET); - fread(&y, WORDSIZE, 1, p_data->file); - - return y; -} - -int _fopen(FILE **f, const char *name, const char *mode) { - // - // Purpose: Substitute for fopen_s on platforms where it doesn't exist - // Note: fopen_s is part of C++11 standard - // - int ret = 0; -#ifdef _WIN32 - ret = (int)fopen_s(f, name, mode); -#else - *f = fopen(name, mode); - if (!*f) - ret = -1; -#endif - return ret; -} - -int _fseek(FILE* stream, F_OFF offset, int whence) -// -// Purpose: Selects platform fseek() for large file support -// -{ -#ifdef _WIN32 // Windows (32-bit and 64-bit) -#define FSEEK64 _fseeki64 -#else // Other platforms -#define FSEEK64 fseeko -#endif - - return FSEEK64(stream, offset, whence); -} - -F_OFF _ftell(FILE* stream) -// -// Purpose: Selects platform ftell() for large file support -// -{ -#ifdef _WIN32 // Windows (32-bit and 64-bit) -#define FTELL64 _ftelli64 -#else // Other platforms -#define FTELL64 ftello -#endif - - return FTELL64(stream); -} - -float* newFloatArray(int n) -// -// Warning: Caller must free memory allocated by this function. -// -{ - return (float*) malloc((n)*sizeof(float)); -} - -int* newIntArray(int n) -// -// Warning: Caller must free memory allocated by this function. -// -{ - return (int*) malloc((n)*sizeof(int)); -} - -char* newCharArray(int n) -// -// Warning: Caller must free memory allocated by this function. -// -{ - return (char*) malloc((n)*sizeof(char)); -} diff --git a/tools/epanet-output/src/epanet_output.i b/tools/epanet-output/src/epanet_output.i deleted file mode 100644 index 8a239d6..0000000 --- a/tools/epanet-output/src/epanet_output.i +++ /dev/null @@ -1,203 +0,0 @@ -/* - * epanet_output.i - SWIG interface description file for EPANET Output API - * - * Created: 9/20/2017 - * - * Author: Michael E. Tryby - * US EPA - ORD/NRMRL - * -*/ -%module epanet_output -%{ -#include "errormanager.h" -#include "messages.h" -#include "epanet_output.h" - -#define SWIG_FILE_WITH_INIT -%} - -%include "typemaps.i" - -/* DEFINE AND TYPEDEF MUST BE INCLUDED */ -#define MAXMSG 53 - -typedef void* ENR_Handle; - - -%include "epanet_output_enums.h" - - -/* TYPEMAPS FOR OPAQUE POINTER */ -/* Used for functions that output a new opaque pointer */ -%typemap(in, numinputs=0) ENR_Handle* p_handle_out (ENR_Handle retval) -{ - /* OUTPUT in */ - retval = NULL; - $1 = &retval; -} -/* used for functions that take in an opaque pointer (or NULL) -and return a (possibly) different pointer */ -%typemap(argout) ENR_Handle* p_handle_out -{ - /* OUTPUT argout */ - %append_output(SWIG_NewPointerObj(SWIG_as_voidptr(retval$argnum), $1_descriptor, 0)); -} -/* No need for special IN typemap for opaque pointers, it works anyway */ - - -/* TYPEMAP FOR IGNORING INT ERROR CODE RETURN VALUE */ -%typemap(out) int { - $result = Py_None; - Py_INCREF($result); -} - -/* TYPEMAPS FOR INT ARGUMENT AS RETURN VALUE */ -%typemap(in, numinputs=0) int* int_out (int temp) { - $1 = &temp; -} -%typemap(argout) int* int_out { - %append_output(PyInt_FromLong(*$1)); -} - -/* TYPEMAP FOR MEMORY MANAGEMENT AND ENCODING OF STRINGS */ -%typemap(in, numinputs=0)char** string_out (char* temp), int* slen (int temp){ - $1 = &temp; -} -%typemap(argout)(char** string_out, int* slen) { - if (*$1) { - PyObject* o; - o = PyUnicode_FromStringAndSize(*$1, *$2); - - $result = SWIG_Python_AppendOutput($result, o); - free(*$1); - } -} - -/* TYPEMAPS FOR MEMORY MANAGEMNET OF FLOAT ARRAYS */ -%typemap(in, numinputs=0)float** float_out (float* temp), int* int_dim (int temp){ - $1 = &temp; -} -%typemap(argout) (float** float_out, int* int_dim) { - if (*$1) { - PyObject *o = PyList_New(*$2); - int i; - float* temp = *$1; - for(i=0; i<*$2; i++) { - PyList_SetItem(o, i, PyFloat_FromDouble((double)temp[i])); - } - $result = SWIG_Python_AppendOutput($result, o); - free(*$1); - } -} - -/* TYPEMAPS FOR MEMORY MANAGEMENT OF INT ARRAYS */ -%typemap(in, numinputs=0)int** int_out (long* temp), int* int_dim (int temp){ - $1 = &temp; -} -%typemap(argout) (int** int_out, int* int_dim) { - if (*$1) { - PyObject *o = PyList_New(*$2); - int i; - long* temp = *$1; - for(i=0; i<*$2; i++) { - PyList_SetItem(o, i, PyInt_FromLong(temp[i])); - } - $result = SWIG_Python_AppendOutput($result, o); - free(*$1); - } -} - -/* TYPEMAP FOR ENUMERATED TYPES */ -%typemap(in) EnumeratedType (int val, int ecode = 0) { - if (PyObject_HasAttrString($input,"value")) { - PyObject* o; - o = PyObject_GetAttrString($input, "value"); - ecode = SWIG_AsVal_int(o, &val); - } - else { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "$symname" "', argument " "$argnum"" of type '" "$ltype""'"); - } - - $1 = ($1_type)(val); -} -%apply EnumeratedType {ENR_ElementType, ENR_Units, ENR_Time, ENR_NodeAttribute, ENR_LinkAttribute} - - -/* RENAME FUNCTIONS PYTHON STYLE */ -%rename("%(undercase)s") ""; - -/* INSERTS CUSTOM EXCEPTION HANDLING IN WRAPPER */ -%exception -{ - char* err_msg; - ENR_clearError(arg1); - $function - if (ENR_checkError(arg1, &err_msg)) - { - PyErr_SetString(PyExc_Exception, err_msg); - SWIG_fail; - } -} -/* INSERT EXCEPTION HANDLING FOR THESE FUNCTIONS */ -int ENR_open(ENR_Handle p_handle, const char* path); - -int ENR_getVersion(ENR_Handle p_handle, int* int_out); -int ENR_getNetSize(ENR_Handle p_handle, int** int_out, int* int_dim); -int ENR_getUnits(ENR_Handle p_handle, ENR_Units t_enum, int* int_out); -int ENR_getTimes(ENR_Handle p_handle, ENR_Time t_enum, int* int_out); -int ENR_getElementName(ENR_Handle p_handle, ENR_ElementType t_enum, - int elementIndex, char** string_out, int* slen); -int ENR_getEnergyUsage(ENR_Handle p_handle, int pumpIndex, - int* int_out, float** float_out, int* int_dim); -int ENR_getNetReacts(ENR_Handle p_handle, float** float_out, int* int_dim); - - -int ENR_getNodeAttribute(ENR_Handle p_handle, int periodIndex, - ENR_NodeAttribute t_enum, float** float_out, int* int_dim); -int ENR_getLinkAttribute(ENR_Handle p_handle, int periodIndex, - ENR_LinkAttribute t_enum, float** float_out, int* int_dim); -%exception; - -/* NO EXCEPTION HANDLING FOR THESE FUNCTIONS */ -int ENR_init(ENR_Handle* p_handle_out); -int ENR_close(ENR_Handle* p_handle_out); -void ENR_free(void** array); - -void ENR_clearError(ENR_Handle p_handle); -int ENR_checkError(ENR_Handle p_handle, char** msg_buffer); - - -/* CODE ADDED DIRECTLY TO SWIGGED INTERFACE MODULE */ -%pythoncode%{ -import enum - -class ElementType(enum.Enum): - NODE = ENR_node - LINK = ENR_link - -class Units(enum.Enum): - FLOW_UNIT = ENR_flowUnits - PRESS_UNIT = ENR_pressUnits - -class Time(enum.Enum): - REPORT_START = ENR_reportStart - REPORT_STEP = ENR_reportStep - SIM_DURATION = ENR_simDuration - NUM_PERIODS = ENR_numPeriods - -class NodeAttribute(enum.Enum): - DEMAND = ENR_demand - HEAD = ENR_head - PRESSURE = ENR_pressure - QUALITY = ENR_quality - -class LinkAttribute(enum.Enum): - FLOW = ENR_flow - VELOCITY = ENR_velocity - HEADLOSS = ENR_headloss - AVG_QUALITY = ENR_avgQuality - STATUS = ENR_status - SETTING = ENR_setting - RX_RATE = ENR_rxRate - FRCTN_FCTR = ENR_frctnFctr -%} diff --git a/tools/epanet-output/src/errormanager.c b/tools/epanet-output/src/errormanager.c deleted file mode 100644 index 49e41db..0000000 --- a/tools/epanet-output/src/errormanager.c +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------------- -// -// errormanager.c -// -// Purpose: Provides a simple interface for managing runtime error messages. -// -// Date: 08/25/2017 -// -// Author: Michael E. Tryby -// US EPA - ORD/NRMRL -//----------------------------------------------------------------------------- -#include -#include -#include "errormanager.h" - -error_handle_t* new_errormanager(void (*p_error_message)(int, char*, int)) -// -// Purpose: Constructs a new error handle. -// -{ - error_handle_t* error_handle; - error_handle = (error_handle_t*)calloc(1, sizeof(error_handle_t)); - - error_handle->p_msg_lookup = p_error_message; - - return error_handle; -} - -void dst_errormanager(error_handle_t* error_handle) -// -// Purpose: Destroys the error handle. -// -{ - free(error_handle); -} - -int set_error(error_handle_t* error_handle, int errorcode) -// -// Purpose: Sets an error code in the handle. -// -{ - // If the error code is 0 no action is taken and 0 is returned. - // This is a feature not a bug. - if (errorcode) - error_handle->error_status = errorcode; - - return errorcode; -} - -char* check_error(error_handle_t* error_handle) -// -// Purpose: Returns the error message or NULL. -// -// Note: Caller must free memory allocated by check_error -// -{ - char* temp = NULL; - - if (error_handle->error_status != 0) { - temp = (char*) calloc(ERR_MAXMSG, sizeof(char)); - - if (temp) - error_handle->p_msg_lookup(error_handle->error_status, temp, ERR_MAXMSG); - } - return temp; -} - -void clear_error(error_handle_t* error_handle) -// -// Purpose: Clears the error from the handle. -// -{ - error_handle->error_status = 0; -} diff --git a/tools/epanet-output/src/errormanager.h b/tools/epanet-output/src/errormanager.h deleted file mode 100644 index d62b6a3..0000000 --- a/tools/epanet-output/src/errormanager.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * errormanager.h - * - * Created on: Aug 25, 2017 - * - * Author: Michael E. Tryby - * US EPA - ORD/NRMRL - */ - -#ifndef ERRORMANAGER_H_ -#define ERRORMANAGER_H_ - -#define ERR_MAXMSG 256 - -typedef struct error_s { - int error_status; - void (*p_msg_lookup)(int, char*, int); -} error_handle_t; - -error_handle_t* new_errormanager(void (*p_error_message)(int, char*, int)); -void dst_errormanager(error_handle_t* error_handle); - -int set_error(error_handle_t* error_handle, int errorcode); -char* check_error(error_handle_t* error_handle); -void clear_error(error_handle_t* error_handle); - -#endif /* ERRORMANAGER_H_ */ diff --git a/tools/epanet-output/src/messages.h b/tools/epanet-output/src/messages.h deleted file mode 100644 index bc04a7d..0000000 --- a/tools/epanet-output/src/messages.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * messages.h - EPANET - * - * Created on: June 1, 2017 - * - * Author: Michael E. Tryby - * US EPA - ORD/NRMRL - */ - -#ifndef MESSAGES_H_ -#define MESSAGES_H_ -/*------------------- Error Messages --------------------*/ -#define MSG_MAXLEN 53 - -#define WARN10 "Warning: model run issued warnings" - -#define ERR411 "Input Error 411: no memory allocated for results" -#define ERR412 "Input Error 412: binary file hasn't been opened" -#define ERR421 "Input Error 421: invalid parameter code" -#define ERR422 "Input Error 422: reporting period index out of range" -#define ERR423 "Input Error 423: element index out of range" - -#define ERR434 "File Error 434: unable to open binary file" -#define ERR435 "File Error 435: invalid binary file type" -#define ERR436 "File Error 436: no results in binary file" - -#define ERRERR "Error: An unknown error has occurred" - -#endif /* MESSAGES_H_ */ diff --git a/tools/epanet-output/test/data/__init__.py b/tools/epanet-output/test/data/__init__.py deleted file mode 100644 index ca2e575..0000000 --- a/tools/epanet-output/test/data/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- - -# __init__.py -# -# Created: 11/13/2017 -# Author: Michael E. Tryby -# US EPA - ORD/NRMRL -# - -import os - -DATA_PATH = os.path.abspath(os.path.dirname(__file__)) - -OUTPUT_FILE_EXAMPLE1 = os.path.join(DATA_PATH, 'net1.out') diff --git a/tools/epanet-output/test/data/net1.out b/tools/epanet-output/test/data/net1.out deleted file mode 100644 index 6cede26b23767e4bd91a30d2ccaba14f34904ba3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16832 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 VZ{1BMO!v?feK@&oH21$7{s%(sdMW?_ diff --git a/tools/epanet-output/test/test_epanet_output.cpp b/tools/epanet-output/test/test_epanet_output.cpp deleted file mode 100644 index ed4f79d..0000000 --- a/tools/epanet-output/test/test_epanet_output.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * test_epanet_output.cpp - * - * Created: 8/4/2017 - * Author: Michael E. Tryby - * US EPA - ORD/NRMRL - * - * Unit testing for EPANET Output API using google test. -*/ - -#include -#include -#include -#include "gtest/gtest.h" - -#include "../src/epanet_output.h" - -#define PROJECT_HOME "C:/Users/mtryby/Workspace/GitRepo/michaeltryby/epanet/" -#define DATA_PATH "tools/epanet-output/test/data/net1.out" - - -namespace { - -TEST(ENR_init, InitTest) { - ENR_Handle p_handle; - - int error = ENR_init(&p_handle); - ASSERT_EQ(0, error); - ASSERT_TRUE(p_handle != NULL); -} - -TEST(ENR_open, OpenTest) { - std::string path = std::string(PROJECT_HOME) + std::string(DATA_PATH); - ENR_Handle p_handle; - ENR_init(&p_handle); - - int error = ENR_open(p_handle, path.c_str()); - ASSERT_EQ(0, error); - ENR_close(&p_handle); -} - -TEST(ENR_close, CloseTest) { - ENR_Handle p_handle; - int error = ENR_init(&p_handle); - - error = ENR_close(&p_handle); - ASSERT_EQ(-1, error); - ASSERT_TRUE(p_handle != NULL); -} - - - -class OutputapiTest : public testing::Test { -protected: - // SetUp for OutputapiTest fixture - virtual void SetUp() { - std::string path = std::string(PROJECT_HOME) + std::string(DATA_PATH); - - error = ENR_init(&p_handle); - ENR_clearError(p_handle); - error = ENR_open(p_handle, path.c_str()); - } - - // TearDown for OutputapiTest fixture - virtual void TearDown() { - ENR_free((void**)&array); - error = ENR_close(&p_handle); - } - - int error = 0; - ENR_Handle p_handle = NULL; - - float* array = NULL; - int array_dim = 0; -}; - -TEST_F(OutputapiTest, getNetSizeTest) { - int* i_array = NULL; - // nodes, tanks, links, pumps, valves - int ref_array[5] = {11,2,13,1,0}; - - error = ENR_getNetSize(p_handle, &i_array, &array_dim); - ASSERT_EQ(0, error); - - for (int i = 0; i < array_dim; i++) - EXPECT_EQ(ref_array[i], i_array[i]); - - ENR_free((void**)&i_array); -} - -TEST_F(OutputapiTest, getElementName) { - char* name = new char[MAXID]; - int length, index = 1; - - error = ENR_getElementName(p_handle, ENR_node, index, &name, &length); - ASSERT_EQ(0, error); - - EXPECT_STREQ("10", name); - - delete(name); -} - -TEST_F(OutputapiTest, getNodeAttributeTest) { - float ref_array[11] = { 1.0, - 0.44407997, - 0.43766347, - 0.42827705, - 0.41342604, - 0.42804748, - 0.44152543, - 0.40502965, - 0.38635802, - 1.0, - 0.96745253 }; - - error = ENR_getNodeAttribute(p_handle, 1, ENR_quality, &array, &array_dim); - ASSERT_EQ(0, error); - - for (int i = 0; i < array_dim; i++) - EXPECT_FLOAT_EQ(ref_array[i], array[i]); -} - -TEST_F(OutputapiTest, getLinkAttributeTest) { - float ref_array[13] = { 1848.5812, - 1220.4274, - 130.11162, - 187.6893, - 119.8884, - 40.464489, - -748.58112, - 478.15378, - 191.73459, - 30.111609, - 140.46449, - 59.535515, - 1848.5812}; - - error = ENR_getLinkAttribute(p_handle, 1, ENR_flow, &array ,&array_dim); - ASSERT_EQ(0, error); - - for (int i = 0; i < array_dim; i++) - EXPECT_FLOAT_EQ(ref_array[i], array[i]); -} - -TEST_F(OutputapiTest, getNodeResultTest) { - float ref_array[4] = {0.041142918, - 150.0, - 987.98358, - 120.45029}; - - error = ENR_getNodeResult(p_handle, 1, 2, &array, &array_dim); - ASSERT_EQ(0, error); - - for (int i = 0; i < array_dim; i++) - EXPECT_FLOAT_EQ(ref_array[i], array[i]); -} - -TEST_F(OutputapiTest, getLinkResultTest) { - float ref_array[8] = {0.58586824, - 1892.2433, - 0.0, - -200.71875, - 1.0, - 3.0, - 1.0, - 0.0}; - - error = ENR_getLinkResult(p_handle, 24, 13, &array, &array_dim); - ASSERT_EQ(0, error); - - for (int i = 0; i < array_dim; i++) - EXPECT_FLOAT_EQ(ref_array[i], array[i]); -} - -TEST_F(OutputapiTest, getNodeSeriesTest){ - float ref_array[10] = {119.25731, - 120.45029, - 121.19854, - 122.00622, - 122.37414, - 122.8122, - 122.82034, - 122.90379, - 123.40434, - 123.81807}; - - error = ENR_getNodeSeries(p_handle, 2, ENR_pressure, 0, 10, &array, &array_dim); - ASSERT_EQ(0, error); - - for (int i = 0; i < array_dim; i++) - EXPECT_FLOAT_EQ(ref_array[i], array[i]); -} - -TEST_F(OutputapiTest, getLinkSeriesTest) { - float ref_array[10] = {1234.2072, - 1220.4274, - 1164.4, - 1154.8175, - 1100.0635, - 1094.759, - 1041.7854, - 1040.7617, - 1087.556, - 1082.5011}; - - error = ENR_getLinkSeries(p_handle, 2, ENR_flow, 0, 10, &array, &array_dim); - ASSERT_EQ(0, error); - - for (int i = 0; i < array_dim; i++) - EXPECT_FLOAT_EQ(ref_array[i], array[i]); -} - -TEST_F(OutputapiTest, getNetReactsTest) { - float ref_array[4] = {18806.59, - 85424.438, - 115174.05, - 238972.66}; - - error = ENR_getNetReacts(p_handle, &array, &array_dim); - ASSERT_EQ(0, error); - - for (int i = 0; i < array_dim; i++) - EXPECT_FLOAT_EQ(ref_array[i], array[i]); -} - -TEST_F(OutputapiTest, getEnergyUsageTest) { - float ref_array[6] = {57.712959, - 75.0, - 880.41583, - 96.254318, - 96.707115, - 0.0}; - - int linkIdx; - - error = ENR_getEnergyUsage(p_handle, 1, &linkIdx, &array, &array_dim); - ASSERT_EQ(0, error); - - for (int i = 0; i < array_dim; i++) - EXPECT_FLOAT_EQ(ref_array[i], array[i]); -} - -} - -GTEST_API_ int main(int argc, char **argv) { - - printf("Running main() from gtest_main.cc\n"); - testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} From 5687c6354864a71226a7eee5cbb3ac8cfa5d1ca8 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Thu, 21 Mar 2019 13:11:10 -0400 Subject: [PATCH 04/16] Reorganizing unit tests Unit tests for the toolkit are consolidated into one test module with a separate test suite for related API functions. --- tests/CMakeLists.txt | 79 +++++---- tests/shared_test.cpp | 5 - .../{test_rprtanlys.cpp => test_analysis.cpp} | 58 ++----- tests/{test_addrule.cpp => test_control.cpp} | 21 ++- ..._demand_categories.cpp => test_demand.cpp} | 29 ++-- tests/test_hydraulics.cpp | 85 +++++++++ tests/test_hydrqual.cpp | 163 ------------------ tests/test_link.cpp | 31 ++-- tests/test_net_builder.cpp | 20 ++- tests/test_node.cpp | 27 +-- ...ttern_curve_funcs.cpp => test_pattern.cpp} | 19 +- tests/{test_proj.cpp => test_project.cpp} | 33 ++-- tests/test_quality.cpp | 101 +++++++++++ tests/test_reent.cpp | 17 +- tests/test_report.cpp | 51 ++++++ tests/test_toolkit.cpp | 65 +++++++ tests/{shared_test.hpp => test_toolkit.hpp} | 70 +++----- 17 files changed, 511 insertions(+), 363 deletions(-) delete mode 100644 tests/shared_test.cpp rename tests/{test_rprtanlys.cpp => test_analysis.cpp} (57%) rename tests/{test_addrule.cpp => test_control.cpp} (81%) rename tests/{test_demand_categories.cpp => test_demand.cpp} (73%) create mode 100644 tests/test_hydraulics.cpp delete mode 100644 tests/test_hydrqual.cpp rename tests/{test_pattern_curve_funcs.cpp => test_pattern.cpp} (87%) rename tests/{test_proj.cpp => test_project.cpp} (90%) create mode 100644 tests/test_quality.cpp create mode 100644 tests/test_report.cpp create mode 100644 tests/test_toolkit.cpp rename tests/{shared_test.hpp => test_toolkit.hpp} (58%) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2b285f1..d48dac1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,41 +24,62 @@ endif(UNIX) IF(MSVC) set(Boost_DEBUG OFF) set(Boost_DETAILED_FAILURE_MSG OFF) - set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_STATIC_LIBS OFF) ENDIF(MSVC) set(Boost_THREAD_FOUND OFF) -find_package(Boost COMPONENTS unit_test_framework system thread filesystem) +find_package(Boost COMPONENTS unit_test_framework filesystem) include_directories (${Boost_INCLUDE_DIRS}) -#I like to keep test files in a separate source directory called test -file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test_*.cpp) +set(toolkit_test_srcs + test_toolkit.cpp + test_project.cpp + test_hydraulics.cpp + test_quality.cpp + test_report.cpp + test_analysis.cpp + test_node.cpp + test_demand.cpp + test_link.cpp +# test_pump.cpp + test_pattern.cpp +# test_curve.cpp + test_control.cpp) -add_library(shared_test OBJECT shared_test.cpp) +add_executable(test_toolkit ${toolkit_test_srcs}) + +target_link_libraries(test_toolkit ${Boost_LIBRARIES} epanet2) + + + +#I like to keep test files in a separate source directory called test +#file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test_*.cpp) + +#add_library(shared_test OBJECT shared_test.cpp) #Run through each source -foreach(testSrc ${TEST_SRCS}) - #Extract the filename without an extension (NAME_WE) - get_filename_component(testName ${testSrc} NAME_WE) - - #Add compile target - IF(${testName} MATCHES "test_reent") - add_executable(${testName} ${testSrc}) - ELSE (TRUE) - add_executable(${testName} ${testSrc} $) - ENDIF(${testName} MATCHES "test_reent") - - #link to Boost libraries AND your targets and dependencies - IF(MSVC) - target_link_libraries(${testName} ${Boost_LIBRARIES} epanet2 epanet-output) - ELSE(TRUE) - target_link_libraries(${testName} ${Boost_LIBRARIES} pthread epanet2 epanet-output) - ENDIF(MSVC) - - #Finally add it to test execution - #Notice the WORKING_DIRECTORY and COMMAND - add_test(NAME ${testName} - COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${testName} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) -endforeach(testSrc) +#foreach(testSrc ${TEST_SRCS}) +# #Extract the filename without an extension (NAME_WE) +# get_filename_component(testName ${testSrc} NAME_WE) +# +# #Add compile target +# IF(${testName} MATCHES "test_reent") +# add_executable(${testName} ${testSrc}) +# ELSE (TRUE) +# add_executable(${testName} ${testSrc} $) +# ENDIF(${testName} MATCHES "test_reent") +# +# #link to Boost libraries AND your targets and dependencies +# IF(MSVC) +# target_link_libraries(${testName} ${Boost_LIBRARIES} epanet2 epanet-output) +# ELSE(TRUE) +# target_link_libraries(${testName} ${Boost_LIBRARIES} pthread epanet2 epanet-output) +# ENDIF(MSVC) +# +# #Finally add it to test execution +# #Notice the WORKING_DIRECTORY and COMMAND +# add_test(NAME ${testName} +# COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${testName} +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) +#endforeach(testSrc) diff --git a/tests/shared_test.cpp b/tests/shared_test.cpp deleted file mode 100644 index 97387a1..0000000 --- a/tests/shared_test.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// -// Hack to get boost unit test to compile faster -// - -#include diff --git a/tests/test_rprtanlys.cpp b/tests/test_analysis.cpp similarity index 57% rename from tests/test_rprtanlys.cpp rename to tests/test_analysis.cpp index 01e452c..2b1e367 100644 --- a/tests/test_rprtanlys.cpp +++ b/tests/test_analysis.cpp @@ -1,49 +1,23 @@ -// -// test_rprtanlys.cpp -// -// Date Created: February 28, 2019 -// -// Author: Michael E. Tryby -// US EPA - ORD/NRMRL -// +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_analysis.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ -#define BOOST_TEST_MODULE hydqual +#define BOOST_ALL_DYN_LINK +#include -#include "shared_test.hpp" - -using namespace boost; +#include "test_toolkit.hpp" -BOOST_AUTO_TEST_SUITE (test_rprtanlys) - -BOOST_FIXTURE_TEST_CASE(test_rprt_anlysstats, FixtureOpenClose) -{ - int i; - double array[5]; - - std::vector test; - std::vector ref = {3.0, 7.0799498320679432e-06, 1.6680242187483429e-08, - 0.0089173150106518495, 0.99999998187144024}; - - error = EN_solveH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_solveQ(ph); - BOOST_REQUIRE(error == 0); - - - for (i=EN_ITERATIONS; i<=EN_MASSBALANCE; i++) { - error = EN_getstatistic(ph, i, &array[i]); - BOOST_REQUIRE(error == 0); - } - - test.assign(array, array + 5); -// BOOST_CHECK_EQUAL_COLLECTIONS(ref.begin(), ref.end(), test.begin(), test.end()); - BOOST_CHECK(check_cdd_double(test, ref, 3)); - - error = EN_getstatistic(ph, 8, &array[0]); - BOOST_CHECK(error == 251); -} +BOOST_AUTO_TEST_SUITE (test_analysis) BOOST_FIXTURE_TEST_CASE(test_anlys_getoption, FixtureOpenClose) { diff --git a/tests/test_addrule.cpp b/tests/test_control.cpp similarity index 81% rename from tests/test_addrule.cpp rename to tests/test_control.cpp index bbc6172..8a3f309 100644 --- a/tests/test_addrule.cpp +++ b/tests/test_control.cpp @@ -1,5 +1,15 @@ -// Test of EN_addrule, EN_deletenode & EN_deletelink EPANET API Functions -#define _CRT_SECURE_NO_DEPRECATE +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_control.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ /* This is a test for the API functions that adds rules and deletes @@ -8,9 +18,10 @@ node or link appearing in any simple or rule-based controls. */ -#define BOOST_TEST_MODULE "rules" +#define BOOST_ALL_DYN_LINK +#include -#include "shared_test.hpp" +#include "test_toolkit.hpp" char R1[] = "RULE 1 \n IF NODE 2 LEVEL < 100 \n THEN LINK 9 STATUS = OPEN"; @@ -19,7 +30,7 @@ char R3[] = "RULE 3\nIF NODE 23 PRESSURE ABOVE 140\nAND NODE 2 LEVEL > 120\n" "THEN LINK 113 STATUS = CLOSED\nELSE LINK 22 STATUS = CLOSED"; -BOOST_AUTO_TEST_SUITE (test_addrule) +BOOST_AUTO_TEST_SUITE (test_controls) BOOST_FIXTURE_TEST_CASE(test_add_get_rule, FixtureOpenClose) { diff --git a/tests/test_demand_categories.cpp b/tests/test_demand.cpp similarity index 73% rename from tests/test_demand_categories.cpp rename to tests/test_demand.cpp index f4ee864..5ad8272 100644 --- a/tests/test_demand_categories.cpp +++ b/tests/test_demand.cpp @@ -1,18 +1,23 @@ -// -// test_demand_categories.cpp -// - /* -This is a test for the demand categories names get\set APIs -A demand category name is set, the network is saved, reopened and the new demand category name is checked. + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_analysis.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** */ -#define BOOST_TEST_MODULE "demands" +#define BOOST_ALL_DYN_LINK +#include -#include "shared_test.hpp" +#include "test_toolkit.hpp" -BOOST_AUTO_TEST_SUITE (test_demands) +BOOST_AUTO_TEST_SUITE (test_demand) BOOST_AUTO_TEST_CASE(test_categories_save) { @@ -41,7 +46,7 @@ BOOST_AUTO_TEST_CASE(test_categories_save) BOOST_REQUIRE(error == 0); } -BOOST_AUTO_TEST_CASE(test_categories_reopen, * boost::unit_test::depends_on("test_demands/test_categories_save")) +BOOST_AUTO_TEST_CASE(test_categories_reopen, * boost::unit_test::depends_on("test_demand/test_categories_save")) { int error = 0; int Nindex, ndem; @@ -59,11 +64,11 @@ BOOST_AUTO_TEST_CASE(test_categories_reopen, * boost::unit_test::depends_on("tes error = EN_getnumdemands(ph, Nindex, &ndem); BOOST_REQUIRE(error == 0); BOOST_CHECK(ndem == 1); - + char demname[80]; error = EN_getdemandname(ph, Nindex, ndem, demname); BOOST_REQUIRE(error == 0); - + BOOST_CHECK(check_string(demname, "Demand category name")); error = EN_close(ph); diff --git a/tests/test_hydraulics.cpp b/tests/test_hydraulics.cpp new file mode 100644 index 0000000..0da7e50 --- /dev/null +++ b/tests/test_hydraulics.cpp @@ -0,0 +1,85 @@ +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_hydraulics.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ + +#define BOOST_ALL_DYN_LINK +#include +#include + +#include "test_toolkit.hpp" + + +BOOST_AUTO_TEST_SUITE (test_hydraulics) + +BOOST_FIXTURE_TEST_CASE(test_solveH, FixtureOpenClose) +{ + error = EN_solveH(ph); + BOOST_REQUIRE(error == 0); +} + +BOOST_FIXTURE_TEST_CASE(test_hyd_step, FixtureOpenClose) +{ + int flag = 00; + long t, tstep; + + error = EN_openH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_initH(ph, flag); + BOOST_REQUIRE(error == 0); + + do { + error = EN_runH(ph, &t); + BOOST_REQUIRE(error == 0); + + error = EN_nextH(ph, &tstep); + BOOST_REQUIRE(error == 0); + + } while (tstep > 0); + + error = EN_closeH(ph); + BOOST_REQUIRE(error == 0); +} + +BOOST_FIXTURE_TEST_CASE(test_hydr_save, FixtureOpenClose) +{ + error = EN_solveH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_saveH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_report(ph); + BOOST_REQUIRE(error == 0); +} + +BOOST_FIXTURE_TEST_CASE(test_hydr_savefile, FixtureOpenClose) +{ + error = EN_solveH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_savehydfile(ph, "test_savefile.hyd"); + BOOST_REQUIRE(error == 0); + + BOOST_CHECK(boost::filesystem::exists("test_savefile.hyd") == true); +} + +BOOST_FIXTURE_TEST_CASE(test_hydr_usefile, FixtureOpenClose, * boost::unit_test::depends_on("test_hydraulics/test_hydr_savefile")) +{ + error = EN_usehydfile(ph, "test_savefile.hyd"); + BOOST_REQUIRE(error == 0); + + error = EN_solveQ(ph); + BOOST_REQUIRE(error == 0); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_hydrqual.cpp b/tests/test_hydrqual.cpp deleted file mode 100644 index 4364545..0000000 --- a/tests/test_hydrqual.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// -// test_hydrqual.cpp -// -// Date Created: February 28, 2019 -// -// Author: Michael E. Tryby -// US EPA - ORD/NRMRL -// - - -#define BOOST_TEST_MODULE hydrqual - -#include "shared_test.hpp" - - -using namespace std; -using namespace boost; - - -BOOST_AUTO_TEST_SUITE (test_hydrqual) - -BOOST_FIXTURE_TEST_CASE(test_solveH_solveQ, FixtureOpenClose) -{ - error = EN_solveH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_solveQ(ph); - BOOST_REQUIRE(error == 0); - - error = EN_report(ph); - BOOST_REQUIRE(error == 0); -} - -BOOST_FIXTURE_TEST_CASE(test_hyd_step, FixtureOpenClose) -{ - int flag = 00; - long t, tstep; - - error = EN_openH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_initH(ph, flag); - BOOST_REQUIRE(error == 0); - - do { - error = EN_runH(ph, &t); - BOOST_REQUIRE(error == 0); - - error = EN_nextH(ph, &tstep); - BOOST_REQUIRE(error == 0); - - } while (tstep > 0); - - error = EN_closeH(ph); - BOOST_REQUIRE(error == 0); -} - -BOOST_FIXTURE_TEST_CASE(test_qual_step, FixtureOpenClose) -{ - int flag = 0; - long t, tstep; - - error = EN_solveH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_openQ(ph); - BOOST_REQUIRE(error == 0); - - error = EN_initQ(ph, flag); - BOOST_REQUIRE(error == 0); - - do { - error = EN_runQ(ph, &t); - BOOST_REQUIRE(error == 0); - - error = EN_stepQ(ph, &tstep); - BOOST_REQUIRE(error == 0); - - } while (tstep > 0); - - error = EN_closeQ(ph); - BOOST_REQUIRE(error == 0); -} - -BOOST_FIXTURE_TEST_CASE(test_progressive_step, FixtureOpenClose) -{ - int flag = EN_NOSAVE; - long t, tstep_h, tstep_q; - - error = EN_openH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_initH(ph, flag); - BOOST_REQUIRE(error == 0); - - error = EN_openQ(ph); - BOOST_REQUIRE(error == 0); - - error = EN_initQ(ph, flag); - BOOST_REQUIRE(error == 0); - - do { - error = EN_runH(ph, &t); - BOOST_REQUIRE(error == 0); - - error = EN_runQ(ph, &t); - BOOST_REQUIRE(error == 0); - - error = EN_nextH(ph, &tstep_h); - BOOST_REQUIRE(error == 0); - - error = EN_nextQ(ph, &tstep_q); - BOOST_REQUIRE(error == 0); - - } while (tstep_h > 0); - - error = EN_closeH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_closeQ(ph); - BOOST_REQUIRE(error == 0); - -} - -BOOST_FIXTURE_TEST_CASE(test_hydr_save, FixtureOpenClose) -{ - error = EN_solveH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_saveH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_report(ph); - BOOST_REQUIRE(error == 0); -} - -BOOST_FIXTURE_TEST_CASE(test_hydr_savefile, FixtureOpenClose) -{ - string hyd_file("test_savefile.hyd"); - - error = EN_solveH(ph); - BOOST_REQUIRE(error == 0); - - error = EN_savehydfile(ph, hyd_file.c_str()); - BOOST_REQUIRE(error == 0); - - BOOST_CHECK(filesystem::exists(hyd_file) == true); -} - -BOOST_FIXTURE_TEST_CASE(test_hydr_usefile, FixtureOpenClose, * unit_test::depends_on("test_hydrqual/test_hydr_savefile")) -{ - string hyd_file("test_savefile.hyd"); - - error = EN_usehydfile(ph, hyd_file.c_str()); - BOOST_REQUIRE(error == 0); - - error = EN_solveQ(ph); - BOOST_REQUIRE(error == 0); -} - - - -BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_link.cpp b/tests/test_link.cpp index a712b0f..aaa5b4e 100644 --- a/tests/test_link.cpp +++ b/tests/test_link.cpp @@ -1,17 +1,20 @@ -// Test of ENsetlinktype EPANET API Function -#define _CRT_SECURE_NO_DEPRECATE - /* -This is a test for the API function that changes a link's type. -Two links in Net1.inp are changed: Pipe 113 is reversed with a CV added -and Pipe 121 is changed to a 100 psi PRV. After running the revised model, -at hour 0 the flow in Pipe 113 should be zero and the pressure at node 31 -of the PRV 121 should be 100. + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_link.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** */ -#define BOOST_TEST_MODULE "link" +#define BOOST_ALL_DYN_LINK +#include -#include "shared_test.hpp" +#include "test_toolkit.hpp" BOOST_AUTO_TEST_SUITE (test_link) @@ -86,12 +89,8 @@ BOOST_AUTO_TEST_CASE(test_setlinktype) EN_deleteproject(&ph); } -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(setid_save_reopen) - -BOOST_AUTO_TEST_CASE(test_setid_save) +BOOST_AUTO_TEST_CASE(test_link_setid_save) { int error = 0; @@ -120,7 +119,7 @@ BOOST_AUTO_TEST_CASE(test_setid_save) EN_deleteproject(&ph); } -BOOST_AUTO_TEST_CASE(test_setid_reopen, * boost::unit_test::depends_on("setid_save_reopen/test_setid_save")) +BOOST_AUTO_TEST_CASE(test_link_setid_reopen, * boost::unit_test::depends_on("test_link/test_link_setid_save")) { int error = 0; int index; diff --git a/tests/test_net_builder.cpp b/tests/test_net_builder.cpp index 056e4e6..d6ae6a7 100644 --- a/tests/test_net_builder.cpp +++ b/tests/test_net_builder.cpp @@ -1,7 +1,15 @@ -// Test of EPANET's Network Building Functions -// -// This is a test of the API functions EN_setjuncdata, EN_settankdata & EN_setpipedata -// +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_net_builder.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ #define BOOST_TEST_MODULE "net_builder" @@ -246,7 +254,7 @@ BOOST_AUTO_TEST_CASE(test_open_net1, * boost::unit_test::depends_on("test_net_bu EN_createproject(&ph); error = EN_open(ph, "net_builder.inp", DATA_PATH_RPT, DATA_PATH_OUT); BOOST_REQUIRE(error == 0); - + error = EN_getnodeindex(ph, (char *)"2", &Nindex); BOOST_REQUIRE(error == 0); @@ -351,7 +359,7 @@ BOOST_FIXTURE_TEST_CASE(test_save_net2, FixtureInitClose) BOOST_AUTO_TEST_CASE(test_reopen_net2, *boost::unit_test::depends_on("test_net_builder/test_save_net2")) { int error, index; - + double p1_2, p2_2; double q1_2, q2_2; diff --git a/tests/test_node.cpp b/tests/test_node.cpp index 21ca9df..a15793b 100644 --- a/tests/test_node.cpp +++ b/tests/test_node.cpp @@ -1,18 +1,23 @@ -// -// test_node.cpp -// -// Date Created: February 8, 2019 -// -// Author: Michael E. Tryby -// US EPA - ORD/NRMRL -// +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_node.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ -#define BOOST_TEST_MODULE "node" +#define BOOST_ALL_DYN_LINK +#include -#include "shared_test.hpp" +#include "test_toolkit.hpp" -BOOST_AUTO_TEST_SUITE (node_props_after_open) +BOOST_AUTO_TEST_SUITE (test_node) BOOST_FIXTURE_TEST_CASE(test_junc_props, FixtureOpenClose) { diff --git a/tests/test_pattern_curve_funcs.cpp b/tests/test_pattern.cpp similarity index 87% rename from tests/test_pattern_curve_funcs.cpp rename to tests/test_pattern.cpp index a3e90e9..b3b6542 100644 --- a/tests/test_pattern_curve_funcs.cpp +++ b/tests/test_pattern.cpp @@ -1,9 +1,20 @@ -// Test of the EN_setpatternid, EN_setcurveid, EN_deletepattern & EN_deletecurve -// EPANET 2.2 API functions +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_pattern.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ -#define BOOST_TEST_MODULE "pattern_curve" +#define BOOST_ALL_DYN_LINK +#include -#include "shared_test.hpp" +#include "test_toolkit.hpp" BOOST_AUTO_TEST_SUITE (pattern) diff --git a/tests/test_proj.cpp b/tests/test_project.cpp similarity index 90% rename from tests/test_proj.cpp rename to tests/test_project.cpp index 1fa9258..351f695 100644 --- a/tests/test_proj.cpp +++ b/tests/test_project.cpp @@ -1,17 +1,23 @@ -// -// test_project.cpp -// -// Date Created: January 24, 2018 -// -// Author: Michael E. Tryby -// US EPA - ORD/NRMRL -// +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_project.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ -#define BOOST_TEST_MODULE "project" -#include "shared_test.hpp" +#define BOOST_ALL_DYN_LINK +#include +#include + +#include "test_toolkit.hpp" -using namespace boost; BOOST_AUTO_TEST_SUITE (test_project) @@ -61,14 +67,14 @@ BOOST_AUTO_TEST_CASE(test_save) error = EN_saveinpfile(ph_save, "test_reopen.inp"); BOOST_REQUIRE(error == 0); - BOOST_CHECK(filesystem::exists("test_reopen.inp") == true); + BOOST_CHECK(boost::filesystem::exists("test_reopen.inp") == true); error = EN_close(ph_save); BOOST_REQUIRE(error == 0); EN_deleteproject(&ph_save); } -BOOST_AUTO_TEST_CASE(test_reopen, * unit_test::depends_on("test_project/test_save")) +BOOST_AUTO_TEST_CASE(test_reopen, * boost::unit_test::depends_on("test_project/test_save")) { int error; @@ -100,7 +106,6 @@ BOOST_AUTO_TEST_CASE(test_run) BOOST_AUTO_TEST_SUITE_END() - BOOST_AUTO_TEST_SUITE(test_proj_fixture) BOOST_FIXTURE_TEST_CASE(test_title, FixtureOpenClose) diff --git a/tests/test_quality.cpp b/tests/test_quality.cpp new file mode 100644 index 0000000..e2eeaef --- /dev/null +++ b/tests/test_quality.cpp @@ -0,0 +1,101 @@ +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_quality.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ + +#define BOOST_ALL_DYN_LINK +#include + +#include "test_toolkit.hpp" + + +BOOST_AUTO_TEST_SUITE (test_quality) + +BOOST_FIXTURE_TEST_CASE(test_solveQ, FixtureOpenClose) +{ + error = EN_solveH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_solveQ(ph); + BOOST_REQUIRE(error == 0); + + error = EN_report(ph); + BOOST_REQUIRE(error == 0); +} + +BOOST_FIXTURE_TEST_CASE(test_qual_step, FixtureOpenClose) +{ + int flag = 0; + long t, tstep; + + error = EN_solveH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_openQ(ph); + BOOST_REQUIRE(error == 0); + + error = EN_initQ(ph, flag); + BOOST_REQUIRE(error == 0); + + do { + error = EN_runQ(ph, &t); + BOOST_REQUIRE(error == 0); + + error = EN_stepQ(ph, &tstep); + BOOST_REQUIRE(error == 0); + + } while (tstep > 0); + + error = EN_closeQ(ph); + BOOST_REQUIRE(error == 0); +} + +BOOST_FIXTURE_TEST_CASE(test_progressive_step, FixtureOpenClose) +{ + int flag = EN_NOSAVE; + long t, tstep_h, tstep_q; + + error = EN_openH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_initH(ph, flag); + BOOST_REQUIRE(error == 0); + + error = EN_openQ(ph); + BOOST_REQUIRE(error == 0); + + error = EN_initQ(ph, flag); + BOOST_REQUIRE(error == 0); + + do { + error = EN_runH(ph, &t); + BOOST_REQUIRE(error == 0); + + error = EN_runQ(ph, &t); + BOOST_REQUIRE(error == 0); + + error = EN_nextH(ph, &tstep_h); + BOOST_REQUIRE(error == 0); + + error = EN_nextQ(ph, &tstep_q); + BOOST_REQUIRE(error == 0); + + } while (tstep_h > 0); + + error = EN_closeH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_closeQ(ph); + BOOST_REQUIRE(error == 0); + +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_reent.cpp b/tests/test_reent.cpp index 3a59425..875ad49 100644 --- a/tests/test_reent.cpp +++ b/tests/test_reent.cpp @@ -1,11 +1,14 @@ /* - * test_reent.cpp - * - * Created: 8/30/2018 - * Author: Michael E. Tryby - * US EPA - ORD/NRMRL - * - * Multi-threading / reentrancy test for EPANET Toolkit API. + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_reent.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** */ #include diff --git a/tests/test_report.cpp b/tests/test_report.cpp new file mode 100644 index 0000000..8f9e82c --- /dev/null +++ b/tests/test_report.cpp @@ -0,0 +1,51 @@ +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_report.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ + +#define BOOST_ALL_DYN_LINK +#include + +#include "test_toolkit.hpp" + + +BOOST_AUTO_TEST_SUITE (test_report) + +BOOST_FIXTURE_TEST_CASE(test_rprt_anlysstats, FixtureOpenClose) +{ + int i; + double array[5]; + + std::vector test; + std::vector ref = {3.0, 7.0799498320679432e-06, 1.6680242187483429e-08, + 0.0089173150106518495, 0.99999998187144024}; + + error = EN_solveH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_solveQ(ph); + BOOST_REQUIRE(error == 0); + + + for (i=EN_ITERATIONS; i<=EN_MASSBALANCE; i++) { + error = EN_getstatistic(ph, i, &array[i]); + BOOST_REQUIRE(error == 0); + } + + test.assign(array, array + 5); +// BOOST_CHECK_EQUAL_COLLECTIONS(ref.begin(), ref.end(), test.begin(), test.end()); + BOOST_CHECK(check_cdd_double(test, ref, 3)); + + error = EN_getstatistic(ph, 8, &array[0]); + BOOST_CHECK(error == 251); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_toolkit.cpp b/tests/test_toolkit.cpp new file mode 100644 index 0000000..8c4b191 --- /dev/null +++ b/tests/test_toolkit.cpp @@ -0,0 +1,65 @@ +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_toolkit.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ + + +#define BOOST_TEST_MODULE toolkit +#define BOOST_ALL_DYN_LINK + +#include + +#include "test_toolkit.hpp" + + +// Custom test to check the minimum number of correct decimal digits between +// the test and the ref vectors. +boost::test_tools::predicate_result check_cdd_double(std::vector& test, + std::vector& ref, long cdd_tol){ + double tmp, min_cdd = 10.0; + + // TODO: What if the vectors aren't the same length? + + std::vector::iterator test_it; + std::vector::iterator ref_it; + + for (test_it = test.begin(), ref_it = ref.begin(); + (test_it < test.end()) && (ref_it < ref.end()); + ++test_it, ++ref_it) + { + if (*test_it != *ref_it) { + // Compute log absolute error + tmp = abs(*test_it - *ref_it); + if (tmp < 1.0e-7) + tmp = 1.0e-7; + + else if (tmp > 2.0) + tmp = 1.0; + + tmp = -log10(tmp); + if (tmp < 0.0) + tmp = 0.0; + + if (tmp < min_cdd) + min_cdd = tmp; + } + } + + return floor(min_cdd) >= cdd_tol; +} + +boost::test_tools::predicate_result check_string(std::string test, std::string ref) +{ + if (ref.compare(test) == 0) + return true; + else + return false; +} diff --git a/tests/shared_test.hpp b/tests/test_toolkit.hpp similarity index 58% rename from tests/shared_test.hpp rename to tests/test_toolkit.hpp index 19fe8b7..1aa7400 100644 --- a/tests/shared_test.hpp +++ b/tests/test_toolkit.hpp @@ -1,4 +1,18 @@ +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_toolkit.hpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ +#ifndef TEST_TOOLKIT_HPP +#define TEST_TOOLKIT_HPP #ifdef _WIN32 @@ -12,58 +26,9 @@ #include -#include -#include - #include "epanet2_2.h" - -// Custom test to check the minimum number of correct decimal digits between -// the test and the ref vectors. -boost::test_tools::predicate_result check_cdd_double(std::vector& test, - std::vector& ref, long cdd_tol){ - double tmp, min_cdd = 10.0; - - // TODO: What if the vectors aren't the same length? - - std::vector::iterator test_it; - std::vector::iterator ref_it; - - for (test_it = test.begin(), ref_it = ref.begin(); - (test_it < test.end()) && (ref_it < ref.end()); - ++test_it, ++ref_it) - { - if (*test_it != *ref_it) { - // Compute log absolute error - tmp = abs(*test_it - *ref_it); - if (tmp < 1.0e-7) - tmp = 1.0e-7; - - else if (tmp > 2.0) - tmp = 1.0; - - tmp = -log10(tmp); - if (tmp < 0.0) - tmp = 0.0; - - if (tmp < min_cdd) - min_cdd = tmp; - } - } - - return floor(min_cdd) >= cdd_tol; -} - -boost::test_tools::predicate_result check_string(std::string test, std::string ref) -{ - if (ref.compare(test) == 0) - return true; - else - return false; -} - - #define DATA_PATH_NET1 "./net1.inp" #define DATA_PATH_RPT "./test.rpt" #define DATA_PATH_OUT "./test.out" @@ -123,3 +88,10 @@ struct FixtureAfterStep{ long t, tstep, tstop; EN_Project ph; }; + +boost::test_tools::predicate_result check_cdd_double(std::vector& test, + std::vector& ref, long cdd_tol); +boost::test_tools::predicate_result check_string(std::string test, std::string ref); + + +#endif //TEST_TOOLKIT_HPP From 0c56df4041b3bf778855bc93913a0cc28521aa60 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Thu, 21 Mar 2019 13:44:31 -0400 Subject: [PATCH 05/16] Reorganizing tests Adding test_net_builder and test_reent to cmake build script. --- tests/CMakeLists.txt | 46 +++++++++++++------------------------- tests/test_net_builder.cpp | 5 +++-- tests/test_reent.cpp | 1 + 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d48dac1..375561c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -28,7 +28,7 @@ IF(MSVC) ENDIF(MSVC) set(Boost_THREAD_FOUND OFF) -find_package(Boost COMPONENTS unit_test_framework filesystem) +find_package(Boost COMPONENTS unit_test_framework filesystem thread) include_directories (${Boost_INCLUDE_DIRS}) @@ -45,41 +45,27 @@ set(toolkit_test_srcs # test_pump.cpp test_pattern.cpp # test_curve.cpp - test_control.cpp) + test_control.cpp + test_net_builder.cpp) add_executable(test_toolkit ${toolkit_test_srcs}) target_link_libraries(test_toolkit ${Boost_LIBRARIES} epanet2) +add_test(NAME test_toolkit + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_toolkit + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) -#I like to keep test files in a separate source directory called test -#file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test_*.cpp) -#add_library(shared_test OBJECT shared_test.cpp) +add_executable(test_reent test_reent.cpp) -#Run through each source -#foreach(testSrc ${TEST_SRCS}) -# #Extract the filename without an extension (NAME_WE) -# get_filename_component(testName ${testSrc} NAME_WE) -# -# #Add compile target -# IF(${testName} MATCHES "test_reent") -# add_executable(${testName} ${testSrc}) -# ELSE (TRUE) -# add_executable(${testName} ${testSrc} $) -# ENDIF(${testName} MATCHES "test_reent") -# -# #link to Boost libraries AND your targets and dependencies -# IF(MSVC) -# target_link_libraries(${testName} ${Boost_LIBRARIES} epanet2 epanet-output) -# ELSE(TRUE) -# target_link_libraries(${testName} ${Boost_LIBRARIES} pthread epanet2 epanet-output) -# ENDIF(MSVC) -# -# #Finally add it to test execution -# #Notice the WORKING_DIRECTORY and COMMAND -# add_test(NAME ${testName} -# COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${testName} -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) -#endforeach(testSrc) +IF(MSVC) + target_link_libraries(test_reent ${Boost_LIBRARIES} epanet2) +ELSE(TRUE) + target_link_libraries(test_reent ${Boost_LIBRARIES} pthread epanet2) +ENDIF(MSVC) + +add_test(NAME test_reent + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_reent + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) diff --git a/tests/test_net_builder.cpp b/tests/test_net_builder.cpp index d6ae6a7..daaa2b6 100644 --- a/tests/test_net_builder.cpp +++ b/tests/test_net_builder.cpp @@ -11,9 +11,10 @@ ****************************************************************************** */ -#define BOOST_TEST_MODULE "net_builder" +#define BOOST_ALL_DYN_LINK +#include -#include "shared_test.hpp" +#include "test_toolkit.hpp" BOOST_AUTO_TEST_SUITE(test_net_builder) diff --git a/tests/test_reent.cpp b/tests/test_reent.cpp index 875ad49..f296117 100644 --- a/tests/test_reent.cpp +++ b/tests/test_reent.cpp @@ -15,6 +15,7 @@ #include #include +#define BOOST_ALL_DYN_LINK #include #include "epanet2_2.h" From 48facd89d0d2e7faea881a212081e8fffbfa715e Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Thu, 21 Mar 2019 18:08:05 -0400 Subject: [PATCH 06/16] Fixing test build on gcc --- CMakeLists.txt | 8 +++++--- appveyor.yml | 2 ++ tests/CMakeLists.txt | 2 +- tests/outfile/CMakeLists.txt | 14 +++++++++++--- tests/outfile/data/example1.out | Bin 0 -> 16832 bytes tests/outfile/test_output.cpp | 6 ------ tests/test_analysis.cpp | 2 +- tests/test_control.cpp | 2 -- tests/test_demand.cpp | 1 - tests/test_hydraulics.cpp | 1 - tests/test_link.cpp | 1 - tests/test_net_builder.cpp | 1 - tests/test_node.cpp | 1 - tests/test_pattern.cpp | 1 - tests/test_project.cpp | 2 -- tests/test_quality.cpp | 1 - tests/test_reent.cpp | 5 ++--- tests/test_report.cpp | 1 - tests/test_toolkit.cpp | 2 -- tests/util/CMakeLists.txt | 17 +++++++++++++++-- tests/util/test_errormanager.cpp | 20 ++++++++++---------- 21 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 tests/outfile/data/example1.out diff --git a/CMakeLists.txt b/CMakeLists.txt index 499b1e4..4bf4748 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,12 +28,12 @@ cmake_minimum_required (VERSION 2.8.8) project(EPANET) +include(CTest) # Append local dir to module search path list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) -option(BUILD_TESTS "Build unit tests (requires Boost test)" OFF) option(BUILD_PY_LIB "Build library for Python wrapper" OFF) option(BUILD_COVERAGE "Build library for coverage" OFF) @@ -43,10 +43,12 @@ IF (NOT BUILD_PY_LIB) ENDIF (NOT BUILD_PY_LIB) add_subdirectory(src/outfile) -IF (BUILD_TESTS) +IF (BUILD_TESTING) + enable_testing() add_subdirectory(tests) add_subdirectory(tests/outfile) -ENDIF (BUILD_TESTS) + add_subdirectory(tests/util) +ENDIF (BUILD_TESTING) # Sets for output directory for executables and libraries. diff --git a/appveyor.yml b/appveyor.yml index 7db9355..c02546e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,6 +21,7 @@ environment: GENERATOR: "Visual Studio 15 2017" GROUP: "SUPPORTED" BOOST_ROOT: "C:/Libraries/boost_1_67_0" + PLATFORM: "win32" REF_BUILD_ID: "220dev5" # New build on Visual Studio 15 2017 @@ -37,6 +38,7 @@ init: - set EPANET_HOME=%APPVEYOR_BUILD_FOLDER% - set BUILD_HOME=buildprod - set TEST_HOME=nrtestsuite + - set PATH=%PATH%;%BOOST_ROOT%/ # See values set - echo %APPVEYOR_BUILD_WORKER_IMAGE% diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 375561c..12807c1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,7 +12,6 @@ #Setup CMake to run tests enable_testing() - # Sets for output directory for executables and libraries. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) @@ -25,6 +24,7 @@ IF(MSVC) set(Boost_DEBUG OFF) set(Boost_DETAILED_FAILURE_MSG OFF) set(Boost_USE_STATIC_LIBS OFF) + add_definitions(-DBOOST_ALL_DYN_LINK) ENDIF(MSVC) set(Boost_THREAD_FOUND OFF) diff --git a/tests/outfile/CMakeLists.txt b/tests/outfile/CMakeLists.txt index e7c2de7..b14bb84 100644 --- a/tests/outfile/CMakeLists.txt +++ b/tests/outfile/CMakeLists.txt @@ -9,11 +9,19 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set (Boost_USE_STATIC_LIBS OFF) +if (MSVC) + set (Boost_USE_STATIC_LIBS OFF) + add_definitions(-DBOOST_ALL_DYN_LINK) +endif(MSVC) + find_package(Boost COMPONENTS unit_test_framework) include_directories (${Boost_INCLUDE_DIRS} ../../src/outfile/include) -add_executable(test_errormanager test_output.cpp) +add_executable(test_output test_output.cpp) -target_link_libraries(test_errormanager ${Boost_LIBRARIES} epanet-output) +target_link_libraries(test_output ${Boost_LIBRARIES} epanet-output) + +add_test(NAME test_output + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_output + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) diff --git a/tests/outfile/data/example1.out b/tests/outfile/data/example1.out new file mode 100644 index 0000000000000000000000000000000000000000..416c98bde53c34b136525b364ade3842ec5d0f1d GIT binary patch literal 16832 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 literal 0 HcmV?d00001 diff --git a/tests/outfile/test_output.cpp b/tests/outfile/test_output.cpp index eb381b2..bcae21d 100644 --- a/tests/outfile/test_output.cpp +++ b/tests/outfile/test_output.cpp @@ -8,13 +8,7 @@ * Unit testing for EPANET Output API. */ -// NOTE: Travis installs libboost test version 1.5.4 -// NOTE: Can not dyn link boost using Visual Studio 10 2010 -//#define BOOST_TEST_DYN_LINK - - #define BOOST_TEST_MODULE "output" -#define BOOST_TEST_DYN_LINK #include #include diff --git a/tests/test_analysis.cpp b/tests/test_analysis.cpp index 2b1e367..f7120f1 100644 --- a/tests/test_analysis.cpp +++ b/tests/test_analysis.cpp @@ -11,7 +11,7 @@ ****************************************************************************** */ -#define BOOST_ALL_DYN_LINK +//#define BOOST_ALL_DYN_LINK #include #include "test_toolkit.hpp" diff --git a/tests/test_control.cpp b/tests/test_control.cpp index 8a3f309..32b3f5f 100644 --- a/tests/test_control.cpp +++ b/tests/test_control.cpp @@ -17,8 +17,6 @@ nodes and links from a project. Deletion can be conditional on node or link appearing in any simple or rule-based controls. */ - -#define BOOST_ALL_DYN_LINK #include #include "test_toolkit.hpp" diff --git a/tests/test_demand.cpp b/tests/test_demand.cpp index 5ad8272..3a7d38f 100644 --- a/tests/test_demand.cpp +++ b/tests/test_demand.cpp @@ -11,7 +11,6 @@ ****************************************************************************** */ -#define BOOST_ALL_DYN_LINK #include #include "test_toolkit.hpp" diff --git a/tests/test_hydraulics.cpp b/tests/test_hydraulics.cpp index 0da7e50..8fe81a0 100644 --- a/tests/test_hydraulics.cpp +++ b/tests/test_hydraulics.cpp @@ -11,7 +11,6 @@ ****************************************************************************** */ -#define BOOST_ALL_DYN_LINK #include #include diff --git a/tests/test_link.cpp b/tests/test_link.cpp index aaa5b4e..0b9a25a 100644 --- a/tests/test_link.cpp +++ b/tests/test_link.cpp @@ -11,7 +11,6 @@ ****************************************************************************** */ -#define BOOST_ALL_DYN_LINK #include #include "test_toolkit.hpp" diff --git a/tests/test_net_builder.cpp b/tests/test_net_builder.cpp index daaa2b6..5c6f274 100644 --- a/tests/test_net_builder.cpp +++ b/tests/test_net_builder.cpp @@ -11,7 +11,6 @@ ****************************************************************************** */ -#define BOOST_ALL_DYN_LINK #include #include "test_toolkit.hpp" diff --git a/tests/test_node.cpp b/tests/test_node.cpp index a15793b..68376fd 100644 --- a/tests/test_node.cpp +++ b/tests/test_node.cpp @@ -11,7 +11,6 @@ ****************************************************************************** */ -#define BOOST_ALL_DYN_LINK #include #include "test_toolkit.hpp" diff --git a/tests/test_pattern.cpp b/tests/test_pattern.cpp index b3b6542..a13cab6 100644 --- a/tests/test_pattern.cpp +++ b/tests/test_pattern.cpp @@ -11,7 +11,6 @@ ****************************************************************************** */ -#define BOOST_ALL_DYN_LINK #include #include "test_toolkit.hpp" diff --git a/tests/test_project.cpp b/tests/test_project.cpp index 351f695..6f0b68c 100644 --- a/tests/test_project.cpp +++ b/tests/test_project.cpp @@ -11,8 +11,6 @@ ****************************************************************************** */ - -#define BOOST_ALL_DYN_LINK #include #include diff --git a/tests/test_quality.cpp b/tests/test_quality.cpp index e2eeaef..973732a 100644 --- a/tests/test_quality.cpp +++ b/tests/test_quality.cpp @@ -11,7 +11,6 @@ ****************************************************************************** */ -#define BOOST_ALL_DYN_LINK #include #include "test_toolkit.hpp" diff --git a/tests/test_reent.cpp b/tests/test_reent.cpp index f296117..14cf154 100644 --- a/tests/test_reent.cpp +++ b/tests/test_reent.cpp @@ -11,13 +11,12 @@ ****************************************************************************** */ +#include + #include #include #include -#define BOOST_ALL_DYN_LINK -#include - #include "epanet2_2.h" #define NUM_THREADS 2 diff --git a/tests/test_report.cpp b/tests/test_report.cpp index 8f9e82c..f1268a3 100644 --- a/tests/test_report.cpp +++ b/tests/test_report.cpp @@ -11,7 +11,6 @@ ****************************************************************************** */ -#define BOOST_ALL_DYN_LINK #include #include "test_toolkit.hpp" diff --git a/tests/test_toolkit.cpp b/tests/test_toolkit.cpp index 8c4b191..33945c8 100644 --- a/tests/test_toolkit.cpp +++ b/tests/test_toolkit.cpp @@ -11,9 +11,7 @@ ****************************************************************************** */ - #define BOOST_TEST_MODULE toolkit -#define BOOST_ALL_DYN_LINK #include diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt index df2f743..2c380ff 100644 --- a/tests/util/CMakeLists.txt +++ b/tests/util/CMakeLists.txt @@ -1,10 +1,20 @@ -cmake_minimum_required(VERSION 3.12) enable_testing() -set (Boost_USE_STATIC_LIBS OFF) +# Sets for output directory for executables and libraries +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + + +IF(MSVC) + set (Boost_USE_STATIC_LIBS OFF) + add_definitions(-DBOOST_ALL_DYN_LINK) +ENDIF(MSVC) + + find_package(Boost COMPONENTS unit_test_framework) include_directories (${Boost_INCLUDE_DIRS} ../../src/) @@ -16,3 +26,6 @@ set (test_source add_executable(test_errormanager ${test_source}) target_link_libraries(test_errormanager ${Boost_LIBRARIES}) + +add_test(NAME test_errormanager + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_errormanager) diff --git a/tests/util/test_errormanager.cpp b/tests/util/test_errormanager.cpp index 7d270ae..0003ee2 100644 --- a/tests/util/test_errormanager.cpp +++ b/tests/util/test_errormanager.cpp @@ -1,7 +1,7 @@ #define BOOST_TEST_MODULE errormanager -#define BOOST_TEST_DYN_LINK +//#define BOOST_TEST_DYN_LINK #include #include "util/errormanager.h" @@ -37,19 +37,19 @@ BOOST_AUTO_TEST_SUITE(test_errormanager) BOOST_AUTO_TEST_CASE (test_create_destroy) { error_handle_t *error_handle = NULL; - error_handle = error_new_manager(&mock_lookup); + error_handle = create_error_manager(&mock_lookup); - error_dst_manager(error_handle); + delete_error_manager(error_handle); } struct Fixture{ Fixture() { error_message = NULL; - error_handle = error_new_manager(&mock_lookup); + error_handle = create_error_manager(&mock_lookup); } ~Fixture() { - error_dst_manager(error_handle); + delete_error_manager(error_handle); free(error_message); } int error; @@ -60,21 +60,21 @@ struct Fixture{ BOOST_FIXTURE_TEST_CASE (test_set_clear, Fixture) { - error = error_set(error_handle, 100); + error = set_error(error_handle, 100); BOOST_CHECK(error == 100); - error_clear(error_handle); - error = error_check(error_handle, &error_message); + clear_error(error_handle); + error = check_error(error_handle, &error_message); BOOST_CHECK(error == 0); BOOST_CHECK(error_message == NULL); } BOOST_FIXTURE_TEST_CASE(test_set_check, Fixture) { - error = error_set(error_handle, 100); + error = set_error(error_handle, 100); BOOST_CHECK(error == 100); - error = error_check(error_handle, &error_message); + error = check_error(error_handle, &error_message); BOOST_CHECK(check_string(error_message, MESSAGE_STRING)); } From eb4ae7f670ef8660ac1f103d2cbb0111bef2c2f6 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Thu, 21 Mar 2019 18:19:17 -0400 Subject: [PATCH 07/16] Adding boost system for gcc build --- tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 12807c1..a27194d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -28,7 +28,7 @@ IF(MSVC) ENDIF(MSVC) set(Boost_THREAD_FOUND OFF) -find_package(Boost COMPONENTS unit_test_framework filesystem thread) +find_package(Boost COMPONENTS unit_test_framework system thread filesystem) include_directories (${Boost_INCLUDE_DIRS}) From 82055f24a9ec6b6088c53188cdc89cee0bf5f783 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Thu, 21 Mar 2019 18:34:01 -0400 Subject: [PATCH 08/16] Updating CI scripts --- .travis.yml | 4 ++-- appveyor.yml | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index fc37c27..5ab4945 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,14 +40,14 @@ before_script: - cd $BUILD_HOME - cmake -DCMAKE_C_COMPILER=${CC} -DCMAKE_CXX_COMPILER=${CXX} - -DBUILD_TESTS=ON + -DBUILD_TESTING=ON -DBUILD_COVERAGE=ON .. script: - cmake --build . # run unit tests - cd tests - - ctest + - ctest test # run regression tests - cd $EPANET_HOME - pip install -r tools/requirements.txt diff --git a/appveyor.yml b/appveyor.yml index c02546e..606f9c0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -55,9 +55,8 @@ before_build: - mkdir %BUILD_HOME% - cd %BUILD_HOME% - cmake -G "%GENERATOR%" - -DBUILD_TESTS=ON - -DBOOST_ROOT="%BOOST_ROOT%" - -DBoost_USE_STATIC_LIBS="ON" .. + -DBUILD_TESTING=ON + -DBOOST_ROOT="%BOOST_ROOT%" .. # run custom build script build_script: @@ -71,7 +70,7 @@ before_test: test_script: # run unit tests - cd %BUILD_HOME%\tests - - ctest -C Release + - ctest -C Release RUN_TESTS # run regression tests - cd %EPANET_HOME% - tools\run-nrtest.cmd %REF_BUILD_ID% %SUT_BUILD_ID% From 66c274c3437e7291a4888acb685b1de33d82d464 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 22 Mar 2019 09:14:26 -0400 Subject: [PATCH 09/16] Adding BOOST_TEST_MAIN for gcc build --- tests/CMakeLists.txt | 2 -- tests/test_toolkit.cpp | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a27194d..670e0b7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,8 +2,6 @@ # CMakeLists.txt - CMake configuration file for epanet/tests # # Created: February 13, 2018 -# Author: Constantin Savtchenko -# Ref: http://neyasystems.com/an-engineers-guide-to-unit-testing-cmake-and-boost-unit-tests/ # # Modified by: Michael E. Tryby # US EPA ORD/NRMRL diff --git a/tests/test_toolkit.cpp b/tests/test_toolkit.cpp index 33945c8..f4c760b 100644 --- a/tests/test_toolkit.cpp +++ b/tests/test_toolkit.cpp @@ -11,6 +11,7 @@ ****************************************************************************** */ +#define BOOST_TEST_MAIN #define BOOST_TEST_MODULE toolkit #include From 84341c3237750b35bfa52c963e8fdb4df3d24d6b Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 22 Mar 2019 09:20:33 -0400 Subject: [PATCH 10/16] Switching MSVC to static link --- tests/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 670e0b7..8853b0e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,8 +21,8 @@ endif(UNIX) IF(MSVC) set(Boost_DEBUG OFF) set(Boost_DETAILED_FAILURE_MSG OFF) - set(Boost_USE_STATIC_LIBS OFF) - add_definitions(-DBOOST_ALL_DYN_LINK) + set(Boost_USE_STATIC_LIBS ON) +# add_definitions(-DBOOST_ALL_DYN_LINK) ENDIF(MSVC) set(Boost_THREAD_FOUND OFF) From c9903620cbbe246c8371b3beb1af4a4dc938d0a5 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 22 Mar 2019 09:55:34 -0400 Subject: [PATCH 11/16] Fine tuning linking strategy static linking on Windows (MSVC and mingw) dyn linking everywhere else. --- tests/CMakeLists.txt | 10 +++++----- tests/outfile/CMakeLists.txt | 9 ++++++--- tests/test_toolkit.cpp | 2 +- tests/util/CMakeLists.txt | 10 ++++++---- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8853b0e..b91c02f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -18,12 +18,12 @@ if(UNIX) endif(UNIX) #Prep ourselves for compiling boost -IF(MSVC) - set(Boost_DEBUG OFF) - set(Boost_DETAILED_FAILURE_MSG OFF) +IF(WIN32) set(Boost_USE_STATIC_LIBS ON) -# add_definitions(-DBOOST_ALL_DYN_LINK) -ENDIF(MSVC) +ELSE(TRUE) + set(Boost_USE_STATIC_LIBS OFF) + add_definitions(-DBOOST_ALL_DYN_LINK) +ENDIF(WIN32) set(Boost_THREAD_FOUND OFF) find_package(Boost COMPONENTS unit_test_framework system thread filesystem) diff --git a/tests/outfile/CMakeLists.txt b/tests/outfile/CMakeLists.txt index b14bb84..84e00a4 100644 --- a/tests/outfile/CMakeLists.txt +++ b/tests/outfile/CMakeLists.txt @@ -9,10 +9,13 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -if (MSVC) - set (Boost_USE_STATIC_LIBS OFF) +#Prep ourselves for compiling boost +IF(WIN32) + set(Boost_USE_STATIC_LIBS ON) +ELSE(TRUE) + set(Boost_USE_STATIC_LIBS OFF) add_definitions(-DBOOST_ALL_DYN_LINK) -endif(MSVC) +ENDIF(WIN32) find_package(Boost COMPONENTS unit_test_framework) include_directories (${Boost_INCLUDE_DIRS} ../../src/outfile/include) diff --git a/tests/test_toolkit.cpp b/tests/test_toolkit.cpp index f4c760b..70718f1 100644 --- a/tests/test_toolkit.cpp +++ b/tests/test_toolkit.cpp @@ -14,7 +14,7 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_MODULE toolkit -#include +#include #include "test_toolkit.hpp" diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt index 2c380ff..27f33c8 100644 --- a/tests/util/CMakeLists.txt +++ b/tests/util/CMakeLists.txt @@ -9,11 +9,13 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -IF(MSVC) - set (Boost_USE_STATIC_LIBS OFF) +#Prep ourselves for compiling boost +IF(WIN32) + set(Boost_USE_STATIC_LIBS ON) +ELSE(TRUE) + set(Boost_USE_STATIC_LIBS OFF) add_definitions(-DBOOST_ALL_DYN_LINK) -ENDIF(MSVC) - +ENDIF(WIN32) find_package(Boost COMPONENTS unit_test_framework) include_directories (${Boost_INCLUDE_DIRS} ../../src/) From ec72db5d8277e8911c7fcff7f5eaf64821fb2d19 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 22 Mar 2019 11:08:54 -0400 Subject: [PATCH 12/16] pulling up call to find_packages eliminates multiple calls to find_packages --- CMakeLists.txt | 19 +++++++++++++++---- tests/CMakeLists.txt | 14 -------------- tests/outfile/CMakeLists.txt | 16 +--------------- tests/util/CMakeLists.txt | 15 +-------------- 4 files changed, 17 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bf4748..1dc6fd9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,10 +44,21 @@ ENDIF (NOT BUILD_PY_LIB) add_subdirectory(src/outfile) IF (BUILD_TESTING) - enable_testing() - add_subdirectory(tests) - add_subdirectory(tests/outfile) - add_subdirectory(tests/util) + #Prep ourselves for compiling boost + IF(WIN32) + set(Boost_USE_STATIC_LIBS ON) + ELSE(TRUE) + set(Boost_USE_STATIC_LIBS OFF) + add_definitions(-DBOOST_ALL_DYN_LINK) + ENDIF(WIN32) + + find_package(Boost COMPONENTS unit_test_framework system thread filesystem) + include_directories (${Boost_INCLUDE_DIRS}) + + enable_testing() + add_subdirectory(tests) + add_subdirectory(tests/outfile) + add_subdirectory(tests/util) ENDIF (BUILD_TESTING) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b91c02f..8028eef 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,8 +7,6 @@ # US EPA ORD/NRMRL # -#Setup CMake to run tests -enable_testing() # Sets for output directory for executables and libraries. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) @@ -17,18 +15,6 @@ if(UNIX) set(CMAKE_CXX_FLAGS "-std=c++11") endif(UNIX) -#Prep ourselves for compiling boost -IF(WIN32) - set(Boost_USE_STATIC_LIBS ON) -ELSE(TRUE) - set(Boost_USE_STATIC_LIBS OFF) - add_definitions(-DBOOST_ALL_DYN_LINK) -ENDIF(WIN32) - -set(Boost_THREAD_FOUND OFF) -find_package(Boost COMPONENTS unit_test_framework system thread filesystem) -include_directories (${Boost_INCLUDE_DIRS}) - set(toolkit_test_srcs test_toolkit.cpp diff --git a/tests/outfile/CMakeLists.txt b/tests/outfile/CMakeLists.txt index 84e00a4..c9d7fc0 100644 --- a/tests/outfile/CMakeLists.txt +++ b/tests/outfile/CMakeLists.txt @@ -1,28 +1,14 @@ -enable_testing() - # Sets for output directory for executables and libraries set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -#Prep ourselves for compiling boost -IF(WIN32) - set(Boost_USE_STATIC_LIBS ON) -ELSE(TRUE) - set(Boost_USE_STATIC_LIBS OFF) - add_definitions(-DBOOST_ALL_DYN_LINK) -ENDIF(WIN32) - -find_package(Boost COMPONENTS unit_test_framework) -include_directories (${Boost_INCLUDE_DIRS} ../../src/outfile/include) - - add_executable(test_output test_output.cpp) - +target_include_directories(test_output PUBLIC ../../src/outfile/include) target_link_libraries(test_output ${Boost_LIBRARIES} epanet-output) add_test(NAME test_output diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt index 27f33c8..713f113 100644 --- a/tests/util/CMakeLists.txt +++ b/tests/util/CMakeLists.txt @@ -1,32 +1,19 @@ -enable_testing() - # Sets for output directory for executables and libraries set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -#Prep ourselves for compiling boost -IF(WIN32) - set(Boost_USE_STATIC_LIBS ON) -ELSE(TRUE) - set(Boost_USE_STATIC_LIBS OFF) - add_definitions(-DBOOST_ALL_DYN_LINK) -ENDIF(WIN32) - -find_package(Boost COMPONENTS unit_test_framework) -include_directories (${Boost_INCLUDE_DIRS} ../../src/) - set (test_source ./test_errormanager.cpp ../../src/util/errormanager.c ) add_executable(test_errormanager ${test_source}) - +target_include_directories(test_errormanager PUBLIC ../../src/) target_link_libraries(test_errormanager ${Boost_LIBRARIES}) add_test(NAME test_errormanager From 2bf3be4c64ba98d3d2f437d7f6f78a0598f05de3 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 22 Mar 2019 11:51:08 -0400 Subject: [PATCH 13/16] Adding tests at test root Couldn't get tests in subdirectores to work so adding them at test root instead. --- .travis.yml | 2 +- CMakeLists.txt | 9 ++++----- appveyor.yml | 2 +- tests/CMakeLists.txt | 9 +++++++++ tests/outfile/CMakeLists.txt | 4 ---- tests/util/CMakeLists.txt | 3 --- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ab4945..b12e143 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,7 +47,7 @@ script: - cmake --build . # run unit tests - cd tests - - ctest test + - ctest --output-on-failure # run regression tests - cd $EPANET_HOME - pip install -r tools/requirements.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dc6fd9..93fbda1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,12 +28,11 @@ cmake_minimum_required (VERSION 2.8.8) project(EPANET) -include(CTest) # Append local dir to module search path list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) - +option(BUILD_TESTS "Build tests (requires Boost)" OFF) option(BUILD_PY_LIB "Build library for Python wrapper" OFF) option(BUILD_COVERAGE "Build library for coverage" OFF) @@ -43,8 +42,8 @@ IF (NOT BUILD_PY_LIB) ENDIF (NOT BUILD_PY_LIB) add_subdirectory(src/outfile) -IF (BUILD_TESTING) - #Prep ourselves for compiling boost +IF (BUILD_TESTS) + #Prep ourselves for compiling with boost IF(WIN32) set(Boost_USE_STATIC_LIBS ON) ELSE(TRUE) @@ -59,7 +58,7 @@ IF (BUILD_TESTING) add_subdirectory(tests) add_subdirectory(tests/outfile) add_subdirectory(tests/util) -ENDIF (BUILD_TESTING) +ENDIF (BUILD_TESTS) # Sets for output directory for executables and libraries. diff --git a/appveyor.yml b/appveyor.yml index 606f9c0..e234cd5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -70,7 +70,7 @@ before_test: test_script: # run unit tests - cd %BUILD_HOME%\tests - - ctest -C Release RUN_TESTS + - ctest -C Release --output-on-failure # run regression tests - cd %EPANET_HOME% - tools\run-nrtest.cmd %REF_BUILD_ID% %SUT_BUILD_ID% diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8028eef..7f3cd97 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,3 +53,12 @@ ENDIF(MSVC) add_test(NAME test_reent COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_reent WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) + + +# ctest doesn't like tests added in subdirectories so adding them here +add_test(NAME test_errormanager + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_errormanager) + +add_test(NAME test_output + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_output + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) diff --git a/tests/outfile/CMakeLists.txt b/tests/outfile/CMakeLists.txt index c9d7fc0..162a2ee 100644 --- a/tests/outfile/CMakeLists.txt +++ b/tests/outfile/CMakeLists.txt @@ -10,7 +10,3 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) add_executable(test_output test_output.cpp) target_include_directories(test_output PUBLIC ../../src/outfile/include) target_link_libraries(test_output ${Boost_LIBRARIES} epanet-output) - -add_test(NAME test_output - COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_output - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt index 713f113..6173a07 100644 --- a/tests/util/CMakeLists.txt +++ b/tests/util/CMakeLists.txt @@ -15,6 +15,3 @@ set (test_source add_executable(test_errormanager ${test_source}) target_include_directories(test_errormanager PUBLIC ../../src/) target_link_libraries(test_errormanager ${Boost_LIBRARIES}) - -add_test(NAME test_errormanager - COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_errormanager) From 44938918bf4b2dcdcf3fb4c1a54d33ef6e2ea128 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 22 Mar 2019 11:59:59 -0400 Subject: [PATCH 14/16] Rolling back option to BUILD_TESTS BUILD_TESTING is defined within cmake when ctest module is included. Rolled back include(CTest) so we are going to define our own test option instead. --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b12e143..3349562 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ before_script: - cd $BUILD_HOME - cmake -DCMAKE_C_COMPILER=${CC} -DCMAKE_CXX_COMPILER=${CXX} - -DBUILD_TESTING=ON + -DBUILD_TESTS=ON -DBUILD_COVERAGE=ON .. script: diff --git a/appveyor.yml b/appveyor.yml index e234cd5..1d3f5ae 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -55,7 +55,7 @@ before_build: - mkdir %BUILD_HOME% - cd %BUILD_HOME% - cmake -G "%GENERATOR%" - -DBUILD_TESTING=ON + -DBUILD_TESTS=ON -DBOOST_ROOT="%BOOST_ROOT%" .. # run custom build script From df4e62b550dccc3a71156eee627f6d14452bd832 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 22 Mar 2019 15:34:34 -0400 Subject: [PATCH 15/16] Adding comment test --- tests/CMakeLists.txt | 4 +- tests/test_curve.cpp | 40 ++++++++++++++++ tests/test_demand.cpp | 2 +- tests/test_link.cpp | 31 +++++++++++- tests/test_node.cpp | 106 +++++++++++++++++++++++++++++++++++++++++ tests/test_pattern.cpp | 19 ++++++++ tests/test_toolkit.cpp | 2 + tests/test_toolkit.hpp | 12 +---- 8 files changed, 201 insertions(+), 15 deletions(-) create mode 100644 tests/test_curve.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7f3cd97..d16c376 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -28,7 +28,7 @@ set(toolkit_test_srcs test_link.cpp # test_pump.cpp test_pattern.cpp -# test_curve.cpp + test_curve.cpp test_control.cpp test_net_builder.cpp) @@ -61,4 +61,4 @@ add_test(NAME test_errormanager add_test(NAME test_output COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_output - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data) + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/outfile/data) diff --git a/tests/test_curve.cpp b/tests/test_curve.cpp new file mode 100644 index 0000000..941b473 --- /dev/null +++ b/tests/test_curve.cpp @@ -0,0 +1,40 @@ +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: test_curve.cpp + Description: Tests EPANET toolkit api functions + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 03/21/2019 + ****************************************************************************** +*/ + +#include + +#include "test_toolkit.hpp" + + +BOOST_AUTO_TEST_SUITE (curve) + +BOOST_FIXTURE_TEST_CASE(test_curve_comments, FixtureOpenClose) +{ + int index; + char comment[EN_MAXMSG + 1]; + + // Set curve comments + error = EN_getcurveindex(ph, (char *)"1", &index); + BOOST_REQUIRE(error == 0); + error = EN_setcomment(ph, EN_CURVE, index, (char *)"Curve 1"); + BOOST_REQUIRE(error == 0); + + // Check curve comments + error = EN_getcurveindex(ph, (char *)"1", &index); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_CURVE, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"Curve 1")); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_demand.cpp b/tests/test_demand.cpp index 3a7d38f..2955079 100644 --- a/tests/test_demand.cpp +++ b/tests/test_demand.cpp @@ -2,7 +2,7 @@ ****************************************************************************** Project: OWA EPANET Version: 2.2 - Module: test_analysis.cpp + Module: test_demand.cpp Description: Tests EPANET toolkit api functions Authors: see AUTHORS Copyright: see AUTHORS diff --git a/tests/test_link.cpp b/tests/test_link.cpp index 0b9a25a..15f451e 100644 --- a/tests/test_link.cpp +++ b/tests/test_link.cpp @@ -133,12 +133,41 @@ BOOST_AUTO_TEST_CASE(test_link_setid_reopen, * boost::unit_test::depends_on("tes // Check that 3rd link has its new name error = EN_getlinkindex(ph, (char *)"Link3", &index); BOOST_REQUIRE(error == 0); - BOOST_REQUIRE(index == 3); + BOOST_CHECK(index == 3); error = EN_close(ph); BOOST_REQUIRE(error == 0); EN_deleteproject(&ph); } +BOOST_FIXTURE_TEST_CASE(test_link_comments, FixtureOpenClose) +{ + int index; + char comment[EN_MAXMSG + 1]; + + // Set link comments + error = EN_getlinkindex(ph, (char *)"11", &index); + BOOST_REQUIRE(error == 0); + error = EN_setcomment(ph, EN_LINK, index, (char *)"P11"); + BOOST_REQUIRE(error == 0); + + error = EN_getlinkindex(ph, (char *)"9", &index); + BOOST_REQUIRE(error == 0); + error = EN_setcomment(ph, EN_LINK, index, (char *)"Pump9"); + BOOST_REQUIRE(error == 0); + + // Check link comments + error = EN_getlinkindex(ph, (char *)"11", &index); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_LINK, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"P11")); + + error = EN_getlinkindex(ph, (char *)"9", &index); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_LINK, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"Pump9")); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_node.cpp b/tests/test_node.cpp index 68376fd..cc79c48 100644 --- a/tests/test_node.cpp +++ b/tests/test_node.cpp @@ -192,3 +192,109 @@ BOOST_AUTO_TEST_CASE(test_setid_reopen, * boost::unit_test::depends_on("setid_sa } BOOST_AUTO_TEST_SUITE_END() + + +BOOST_AUTO_TEST_SUITE(node_comments) + +BOOST_FIXTURE_TEST_CASE(test_node_comments, FixtureOpenClose) +{ + int index; + char comment[EN_MAXMSG + 1]; + + // Add comments to selected objects + error = EN_getnodeindex(ph, (char *)"11", &index); + BOOST_REQUIRE(error == 0); + error = EN_setcomment(ph, EN_NODE, index, (char *)"J11"); + BOOST_REQUIRE(error == 0); + + error = EN_getnodeindex(ph, (char *)"23", &index); + BOOST_REQUIRE(error == 0); + error = EN_setcomment(ph, EN_NODE, index, (char *)"Junc23"); + BOOST_REQUIRE(error == 0); + + // Check comments + error = EN_getnodeindex(ph, (char *)"11", &index); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_NODE, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"J11")); + + error = EN_getnodeindex(ph, (char *)"23", &index); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_NODE, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"Junc23")); +} + +BOOST_FIXTURE_TEST_CASE(test_replace_comment, FixtureOpenClose) +{ + int index; + char comment[EN_MAXMSG + 1]; + + // Replace short comment with longer one and vice versa + error = EN_getnodeindex(ph, (char *)"11", &index); + BOOST_REQUIRE(error == 0); + error = EN_setcomment(ph, EN_NODE, index, (char *)"Junction11"); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_NODE, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"Junction11")); + + error = EN_setcomment(ph, EN_NODE, index, (char *)"J11"); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_NODE, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"J11")); +} + +BOOST_FIXTURE_TEST_CASE(test_save_comment, FixtureOpenClose) +{ + int index; + + // Add comments to selected objects + error = EN_getnodeindex(ph, (char *)"11", &index); + BOOST_REQUIRE(error == 0); + error = EN_setcomment(ph, EN_NODE, index, (char *)"J11"); + BOOST_REQUIRE(error == 0); + + error = EN_getnodeindex(ph, (char *)"23", &index); + BOOST_REQUIRE(error == 0); + error = EN_setcomment(ph, EN_NODE, index, (char *)"Junc23"); + BOOST_REQUIRE(error == 0); + + error = EN_saveinpfile(ph, DATA_PATH_TMP); + BOOST_REQUIRE(error == 0); +} + +BOOST_AUTO_TEST_CASE(test_reopen_comment, * boost::unit_test::depends_on("node_comments/test_save_comment")) +{ + int error, index; + char comment[EN_MAXMSG + 1]; + + // Create & load a project + EN_Project ph = NULL; + EN_createproject(&ph); + + error = EN_open(ph, DATA_PATH_TMP, DATA_PATH_RPT, ""); + BOOST_REQUIRE(error == 0); + + // Check that comments were saved & read correctly + // Check comments + error = EN_getnodeindex(ph, (char *)"11", &index); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_NODE, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"J11")); + + error = EN_getnodeindex(ph, (char *)"23", &index); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_NODE, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"Junc23")); + + // Close project + EN_close(ph); + EN_deleteproject(&ph); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_pattern.cpp b/tests/test_pattern.cpp index a13cab6..674ea76 100644 --- a/tests/test_pattern.cpp +++ b/tests/test_pattern.cpp @@ -131,4 +131,23 @@ BOOST_AUTO_TEST_CASE(add_set_pattern) EN_deleteproject(&ph); } +BOOST_FIXTURE_TEST_CASE(test_pattern_comments, FixtureOpenClose) +{ + int index; + char comment[EN_MAXMSG + 1]; + + // Set pattern comment + error = EN_getpatternindex(ph, (char *)"1", &index); + BOOST_REQUIRE(error == 0); + error = EN_setcomment(ph, EN_TIMEPAT, index, (char *)"Time Pattern 1"); + BOOST_REQUIRE(error == 0); + + // Check pattern comment + error = EN_getpatternindex(ph, (char *)"1", &index); + BOOST_REQUIRE(error == 0); + error = EN_getcomment(ph, EN_TIMEPAT, index, comment); + BOOST_REQUIRE(error == 0); + BOOST_CHECK(check_string(comment, (char *)"Time Pattern 1")); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_toolkit.cpp b/tests/test_toolkit.cpp index 70718f1..f1cb75d 100644 --- a/tests/test_toolkit.cpp +++ b/tests/test_toolkit.cpp @@ -14,6 +14,8 @@ #define BOOST_TEST_MAIN #define BOOST_TEST_MODULE toolkit +#include + #include #include "test_toolkit.hpp" diff --git a/tests/test_toolkit.hpp b/tests/test_toolkit.hpp index 1aa7400..03ac664 100644 --- a/tests/test_toolkit.hpp +++ b/tests/test_toolkit.hpp @@ -15,21 +15,11 @@ #define TEST_TOOLKIT_HPP -#ifdef _WIN32 -#define _CRTDBG_MAP_ALLOC -#include -#include -#else -#include -#endif - - -#include - #include "epanet2_2.h" #define DATA_PATH_NET1 "./net1.inp" +#define DATA_PATH_TMP "./tmp.inp" #define DATA_PATH_RPT "./test.rpt" #define DATA_PATH_OUT "./test.out" From 1e7cba167c8064239ec6040274e77d37c748b6c9 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Fri, 22 Mar 2019 15:35:35 -0400 Subject: [PATCH 16/16] Delete test_comments.cpp --- tests/test_comments.cpp | 131 ---------------------------------------- 1 file changed, 131 deletions(-) delete mode 100644 tests/test_comments.cpp diff --git a/tests/test_comments.cpp b/tests/test_comments.cpp deleted file mode 100644 index 404b5ce..0000000 --- a/tests/test_comments.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// Test of EPANET's Comment Handling Functions -// -// This is a test of the API functions EN_getcomment and EN_setcomment -// -#define _CRT_SECURE_NO_DEPRECATE - -//#define NO_BOOST - -#ifndef NO_BOOST -#define BOOST_TEST_MODULE "toolkit" -#include -#endif - -#include -#include -#include "epanet2_2.h" - -#define DATA_PATH_INP "./net1.inp" -#define DATA_PATH_RPT "./test.rpt" -#define DATA_PATH_OUT "./test.out" -#define DATA_PATH_TMP "./tmp.inp" - -#ifdef NO_BOOST -#define BOOST_REQUIRE(x) (((x)) ? cout << "\nPassed at line " << __LINE__ : cout << "\nFailed at line " << __LINE__ ) -#endif - -using namespace std; - -int checkComments(EN_Project ph) -{ - int index; - char comment[EN_MAXMSG + 1]; - EN_getnodeindex(ph, (char *)"11", &index); - EN_getcomment(ph, EN_NODE, index, comment); - if (strcmp(comment, (char *)"J11") != 0) return 0; - - EN_getnodeindex(ph, (char *)"23", &index); - EN_getcomment(ph, EN_NODE, index, comment); - if (strcmp(comment, (char *)"Junc23") != 0) return 0; - - EN_getlinkindex(ph, (char *)"11", &index); - EN_getcomment(ph, EN_LINK, index, comment); - if (strcmp(comment, (char *)"P11") != 0) return 0; - - EN_getlinkindex(ph, (char *)"9", &index); - EN_getcomment(ph, EN_LINK, index, comment); - if (strcmp(comment, (char *)"Pump9") != 0) return 0; - - EN_getpatternindex(ph, (char *)"1", &index); - EN_getcomment(ph, EN_TIMEPAT, index, comment); - if (strcmp(comment, (char *)"Time Pattern 1") != 0) return 0; - - EN_getcurveindex(ph, (char *)"1", &index); - EN_getcomment(ph, EN_CURVE, index, comment); - if (strcmp(comment, (char *)"Curve 1") != 0) return 0; - return 1; -} - -#ifndef NO_BOOST -BOOST_AUTO_TEST_SUITE (test_toolkit) -BOOST_AUTO_TEST_CASE(test_setlinktype) -{ -#else -int main(int argc, char *argv[]) -{ -#endif - - int error = 0; - int index; - char comment[EN_MAXMSG+1]; - - // Create & load a project - EN_Project ph = NULL; - EN_createproject(&ph); - std::string path_inp = string(DATA_PATH_INP); - std::string path_rpt = string(DATA_PATH_RPT); - std::string path_out = string(DATA_PATH_OUT); - error = EN_open(ph, path_inp.c_str(), path_rpt.c_str(), ""); - BOOST_REQUIRE(error == 0); - - // Add comments to selected objects - EN_getnodeindex(ph, (char *)"11", &index); - EN_setcomment(ph, EN_NODE, index, (char *)"J11"); - EN_getnodeindex(ph, (char *)"23", &index); - EN_setcomment(ph, EN_NODE, index, (char *)"Junc23"); - EN_getlinkindex(ph, (char *)"11", &index); - - EN_setcomment(ph, EN_LINK, index, (char *)"P11"); - EN_getlinkindex(ph, (char *)"9", &index); - EN_setcomment(ph, EN_LINK, index, (char *)"Pump9"); - - EN_getpatternindex(ph, (char *)"1", &index); - EN_setcomment(ph, EN_TIMEPAT, index, (char *)"Time Pattern 1"); - - EN_getcurveindex(ph, (char *)"1", &index); - EN_setcomment(ph, EN_CURVE, index, (char *)"Curve 1"); - - // Retrieve comments and test their values - BOOST_REQUIRE(checkComments(ph) == 1); - - // Replace short comment with longer one and vice versa - EN_getnodeindex(ph, (char *)"11", &index); - EN_setcomment(ph, EN_NODE, index, (char *)"Junction11"); - EN_getcomment(ph, EN_NODE, index, comment); - BOOST_REQUIRE(strcmp(comment, (char *)"Junction11") == 0); - EN_setcomment(ph, EN_NODE, index, (char *)"J11"); - EN_getcomment(ph, EN_NODE, index, comment); - BOOST_REQUIRE(strcmp(comment, (char *)"J11") == 0); - - // Save & re-open project - string path_tmp = string(DATA_PATH_TMP); - EN_saveinpfile(ph, path_tmp.c_str()); - EN_close(ph); - error = EN_open(ph, path_tmp.c_str(), path_rpt.c_str(), ""); - BOOST_REQUIRE(error == 0); - - // Check that comments were saved & read correctly - BOOST_REQUIRE(checkComments(ph) == 1); - remove(path_tmp.c_str()); - - // Close project - EN_close(ph); - EN_deleteproject(&ph); - -#ifdef NO_BOOST - return 0; -#endif -} -#ifndef NO_BOOST -BOOST_AUTO_TEST_SUITE_END() -#endif \ No newline at end of file