From e17c1ec5358470cee6529e83969726b26538f6ef Mon Sep 17 00:00:00 2001
From: Sam Yates <halfflat@gmail.com>
Date: Tue, 28 Jun 2016 18:34:09 +0200
Subject: [PATCH] Use library's own version of assert.

Sidesteps NDEBUG versus assert() issue; EXPECTS macros are
now enabled via a CMake configuration option -DWITH_ASSERTIONS=ON,
corresponding to the preprocessor define -DWITH_ASSERTIONS in
the code itself.

(Note, with assertions enabled, one of the existing tests in
test_algorithms.cpp aborts.)
---
 CMakeLists.txt            | 11 ++++++++---
 src/CMakeLists.txt        |  1 +
 src/algorithms.hpp        |  1 +
 src/cell.cpp              |  1 +
 src/cell.hpp              |  1 +
 src/matrix.hpp            |  1 +
 src/swcio.cpp             |  1 +
 src/util.hpp              |  6 ------
 src/util/debug.cpp        | 12 ++++++++++++
 src/util/debug.hpp        | 30 ++++++++++++++++++++++++++++++
 tests/test_algorithms.cpp |  4 +++-
 tests/test_optional.cpp   |  2 +-
 12 files changed, 60 insertions(+), 11 deletions(-)
 create mode 100644 src/util/debug.cpp
 create mode 100644 src/util/debug.hpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7be418be..706a1baa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
-cmake_minimum_required (VERSION 2.8)
+cmake_minimum_required(VERSION 2.8)
 
 # project info
-project (cell_algorithms)
+project(cell_algorithms)
 enable_language(CXX)
 
 # save incoming CXX flags for forwarding to modparser external project
@@ -11,7 +11,6 @@ set(SAVED_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
 set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
 include("CompilerOptions")
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXXOPT_DEBUG} ${CXXOPT_CXX11} ${CXXOPT_PTHREAD} ${CXXOPT_WALL}")
-# -g -std=c++11 -pthread -Wall")
 
 # this generates a .json file with full compilation command for each file
 set(CMAKE_EXPORT_COMPILE_COMMANDS "YES")
@@ -20,6 +19,12 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS "YES")
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
 
+# enable assertions?
+set(WITH_ASSERTIONS OFF CACHE BOOL "enable EXPECTS() assertions in code")
+if(WITH_ASSERTIONS)
+    add_definitions("-DWITH_ASSERTIONS")
+endif()
+
 # targets for extermal dependencies
 include(ExternalProject)
 externalproject_add(modparser
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 125f99db..b6e63096 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -6,6 +6,7 @@ set(BASE_SOURCES
     mechanism_interface.cpp
     parameter_list.cpp
     swcio.cpp
+    util/debug.cpp
 )
 
 add_library(cellalgo ${BASE_SOURCES} ${HEADERS})
diff --git a/src/algorithms.hpp b/src/algorithms.hpp
index 5d609b1e..f3cd9882 100644
--- a/src/algorithms.hpp
+++ b/src/algorithms.hpp
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "util.hpp"
+#include "util/debug.hpp"
 
 /*
  * Some simple wrappers around stl algorithms to improve readability of code
diff --git a/src/cell.cpp b/src/cell.cpp
index 68783157..da8febaf 100644
--- a/src/cell.cpp
+++ b/src/cell.cpp
@@ -1,5 +1,6 @@
 #include "cell.hpp"
 #include "tree.hpp"
+#include "util/debug.hpp"
 
 namespace nest {
 namespace mc {
diff --git a/src/cell.hpp b/src/cell.hpp
index 2f336f84..a10e0a8d 100644
--- a/src/cell.hpp
+++ b/src/cell.hpp
@@ -8,6 +8,7 @@
 #include "segment.hpp"
 #include "cell_tree.hpp"
 #include "stimulus.hpp"
+#include "util/debug.hpp"
 
 namespace nest {
 namespace mc {
diff --git a/src/matrix.hpp b/src/matrix.hpp
index 9e2c9e7d..d0ddb816 100644
--- a/src/matrix.hpp
+++ b/src/matrix.hpp
@@ -4,6 +4,7 @@
 #include <vector/include/Vector.hpp>
 
 #include "util.hpp"
+#include "util/debug.hpp"
 
 namespace nest {
 namespace mc {
diff --git a/src/swcio.cpp b/src/swcio.cpp
index 203f69eb..f1a272df 100644
--- a/src/swcio.cpp
+++ b/src/swcio.cpp
@@ -9,6 +9,7 @@
 #include "point.hpp"
 #include "swcio.hpp"
 #include "util.hpp"
+#include "util/debug.hpp"
 
 namespace nest {
 namespace mc {
diff --git a/src/util.hpp b/src/util.hpp
index c4362b25..29a6b28a 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -2,12 +2,6 @@
 
 #include <vector/include/Vector.hpp>
 
-#ifdef DEBUG
-#define EXPECTS(expression) assert(expression)
-#else
-#define EXPECTS(expression)
-#endif
-
 /*
 using memory::util::red;
 using memory::util::yellow;
diff --git a/src/util/debug.cpp b/src/util/debug.cpp
new file mode 100644
index 00000000..21eca07d
--- /dev/null
+++ b/src/util/debug.cpp
@@ -0,0 +1,12 @@
+#include <cstdio>
+#include <cstdlib>
+
+#include "util/debug.hpp"
+
+bool nest::mc::util::failed_assertion(const char *assertion, const char *file,
+                                      int line, const char *func)
+{
+    std::fprintf(stderr, "%s:%d %s: Assertion `%s' failed.\n", file, line, func, assertion);
+    std::abort();
+    return false;
+}
diff --git a/src/util/debug.hpp b/src/util/debug.hpp
new file mode 100644
index 00000000..148b3c44
--- /dev/null
+++ b/src/util/debug.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+namespace nest {
+namespace mc {
+namespace util {
+
+bool failed_assertion(const char *assertion, const char *file, int line, const char *func);
+
+} 
+}
+}
+
+
+#ifdef WITH_ASSERTIONS
+
+#ifdef __GNUC__
+#define DEBUG_FUNCTION_NAME __PRETTY_FUNCTION__
+#else
+#define DEBUG_FUNCTION_NAME __func__
+#endif
+
+#define EXPECTS(condition) \
+(void)((condition) || \
+       nest::mc::util::failed_assertion(#condition, __FILE__, __LINE__, DEBUG_FUNCTION_NAME))
+
+#else
+
+#define EXPECTS(condition)
+
+#endif //  def WITH_ASSERTIONS
diff --git a/tests/test_algorithms.cpp b/tests/test_algorithms.cpp
index ec25bd42..d1ffdf11 100644
--- a/tests/test_algorithms.cpp
+++ b/tests/test_algorithms.cpp
@@ -1,9 +1,11 @@
 #include <vector>
 
 #include "gtest.h"
+
+#include "algorithms.hpp"
 #include "util.hpp"
+#include "util/debug.hpp"
 
-#include "../src/algorithms.hpp"
 
 TEST(algorithms, sum)
 {
diff --git a/tests/test_optional.cpp b/tests/test_optional.cpp
index 6755525a..9c6f35cf 100644
--- a/tests/test_optional.cpp
+++ b/tests/test_optional.cpp
@@ -282,7 +282,7 @@ TEST(optionalm,conversion) {
 
 TEST(optionalm,or_operator) {
     optional<const char *> default_msg="default";
-    auto x=nullptr | default_msg;
+    auto x=(char *)0 | default_msg;
     EXPECT_TRUE((bool)x);
     EXPECT_STREQ("default",x.get());
 
-- 
GitLab