From 32aab3088906c8683d00ea4a79269e62d52e445f Mon Sep 17 00:00:00 2001
From: Carsten Patzke <carsten.patzke@desy.de>
Date: Thu, 26 Mar 2020 17:18:04 +0100
Subject: [PATCH] Integration test added line output and ErrorTemplate support

---
 tests/automatic/common/cpp/CMakeLists.txt     |  2 +-
 tests/automatic/common/cpp/include/testing.h  | 61 ++++++++++++++-
 tests/automatic/common/cpp/src/testing.cpp    | 77 +++++++++++--------
 .../consumer/consumer_api/consumer_api.cpp    |  4 -
 .../next_multithread_broker.cpp               |  3 -
 .../curl_httpclient_command.cpp               |  4 -
 .../parse_config_file/parse_config_file.cpp   |  3 -
 .../mongo_db/connect/connect_mongodb.cpp      |  1 -
 .../insert_retrieve_mongodb.cpp               |  7 +-
 .../insert_retrieve_dataset_mongodb.cpp       |  7 +-
 .../mongo_db/upsert/upsert_mongodb.cpp        |  3 -
 .../client_serv/ip_tcp_network.cpp            |  1 -
 .../client_serv_multicon/multicon.cpp         |  1 -
 .../read_file_content/read_file_content.cpp   |  2 +-
 .../read_folder_content.cpp                   |  4 -
 .../read_string_from_file.cpp                 |  2 +-
 .../read_subdirectories.cpp                   |  4 -
 .../resolve_hostname_to_ip.cpp                |  4 -
 .../write_data_to_file/write_data_to_file.cpp |  4 +-
 19 files changed, 111 insertions(+), 83 deletions(-)

diff --git a/tests/automatic/common/cpp/CMakeLists.txt b/tests/automatic/common/cpp/CMakeLists.txt
index e01bd7c09..fe0347972 100644
--- a/tests/automatic/common/cpp/CMakeLists.txt
+++ b/tests/automatic/common/cpp/CMakeLists.txt
@@ -6,7 +6,7 @@ set(SOURCE_FILES
 # Library
 ################################
 add_library(${TARGET_NAME} STATIC ${SOURCE_FILES})
-target_include_directories(${TARGET_NAME} PUBLIC include)
+target_include_directories(${TARGET_NAME} PUBLIC include ${ASAPO_CXX_COMMON_INCLUDE_DIR})
 set_target_properties(${TARGET_NAME} PROPERTIES LINKER_LANGUAGE CXX)
 
 #Add all necessary common libraries
diff --git a/tests/automatic/common/cpp/include/testing.h b/tests/automatic/common/cpp/include/testing.h
index 798187d80..d127dfd93 100644
--- a/tests/automatic/common/cpp/include/testing.h
+++ b/tests/automatic/common/cpp/include/testing.h
@@ -1,15 +1,68 @@
 #ifndef ASAPO_TESTING_H
 #define ASAPO_TESTING_H
 
+#include <common/error.h>
 #include <string>
 
 namespace asapo {
 
-void M_AssertEq(const std::string& expected, const std::string& got);
-void M_AssertEq(int expected, int got);
-void M_AssertTrue(bool value, std::string name = "");
-void M_AssertContains(const std::string& whole, const std::string& sub);
+void _M_INTERNAL_PrintComment(const std::string& comment);
+void _M_INTERNAL_ThrowError(const std::string& expected, const std::string& got, const std::string& comment);
 
+void _M_AssertTrue(bool value, const std::string& comment);
+void _M_AssertContains(const std::string& whole, const std::string& sub, const std::string& comment);
+
+void _M_AssertEq(const std::string& expected, const std::string& got, const std::string& comment);
+void _M_AssertEq(int expected, int got, const std::string& comment);
+
+// Error checks
+void _M_AssertEq(const Error& expected, const Error& got, const std::string& comment);
+// decltype(nullptr) == nullptr_t but we are using an old bamboo compiler that does not know this
+void _M_AssertEq(const decltype(nullptr)& expected, const Error& got, const std::string& comment);
+template<class ErrorTemplateType>
+inline void _M_AssertEq(const ErrorTemplateType& expected, const Error& got, const std::string& comment) {
+    _M_INTERNAL_PrintComment(comment);
+    if (expected != got) {
+        _M_INTERNAL_ThrowError(expected.Text(), got ? got->Explain() : "No error", comment);
+    }
+}
+
+// Function that helps to convert the __LINE__ to a string
+#define _M_INTERNAL_TO_STRING_WRAPPER(x) #x
+#define _M_INTERNAL_TO_STRING(x) _M_INTERNAL_TO_STRING_WRAPPER(x)
+#define _M_INTERNAL_COMMENT_PREFIX "Line " _M_INTERNAL_TO_STRING(__LINE__) ": "
+
+// These macros are handling optional arguments
+// https://stackoverflow.com/a/3048361/3338196
+#define _M_AssertEq_2_ARGS(e, g) \
+    asapo::_M_AssertEq(e, g, _M_INTERNAL_COMMENT_PREFIX "Expect " # g " to be " # e)
+#define _M_AssertEq_3_ARGS(e, g, c) \
+    asapo::_M_AssertEq(e, g, _M_INTERNAL_COMMENT_PREFIX c)
+
+#define _M_AssertContains_2_ARGS(whole, sub) \
+    asapo::_M_AssertContains(whole, sub, _M_INTERNAL_COMMENT_PREFIX "Expect " # whole " to contain substring " # sub)
+#define _M_AssertContains_3_ARGS(whole, sub, c) \
+    asapo::_M_AssertContains(whole, sub, _M_INTERNAL_COMMENT_PREFIX c)
+
+#define _M_AssertTrue_1_ARGS(value) \
+    asapo::_M_AssertTrue(value, _M_INTERNAL_COMMENT_PREFIX "Expect " # value " to be true")
+#define _M_AssertTrue_2_ARGS(value, c) \
+    asapo::_M_AssertTrue(value, _M_INTERNAL_COMMENT_PREFIX c)
+
+#define _M_GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
+#define _M_MACRO_CHOOSER_2_3(func, ...) _M_GET_4TH_ARG(__VA_ARGS__,  _ ## func ## _3_ARGS, _ ## func ## _2_ARGS, )
+#define _M_GET_3TH_ARG(arg1, arg2, arg3, ...) arg3
+#define _M_MACRO_CHOOSER_1_2(func, ...) _M_GET_3TH_ARG(__VA_ARGS__,  _ ## func ## _2_ARGS, _ ## func ## _1_ARGS, )
+
+// MSVC Fix... >:(
+// https://stackoverflow.com/a/5134656/3338196
+#define _M_EXPAND( x ) x
+
+// Calls available to the user
+// Can be used like the real _M_Assert... functions, the comment is optional
+#define M_AssertEq(...) _M_EXPAND(_M_MACRO_CHOOSER_2_3(M_AssertEq, __VA_ARGS__)(__VA_ARGS__))
+#define M_AssertContains(...) _M_EXPAND(_M_MACRO_CHOOSER_2_3(M_AssertContains, __VA_ARGS__)(__VA_ARGS__))
+#define M_AssertTrue(...) _M_EXPAND(_M_MACRO_CHOOSER_1_2(M_AssertTrue, __VA_ARGS__)(__VA_ARGS__))
 
 }
 
diff --git a/tests/automatic/common/cpp/src/testing.cpp b/tests/automatic/common/cpp/src/testing.cpp
index ca14d633b..17b333cd7 100644
--- a/tests/automatic/common/cpp/src/testing.cpp
+++ b/tests/automatic/common/cpp/src/testing.cpp
@@ -5,55 +5,72 @@
 
 namespace asapo {
 
+std::string EraseSpaces(const std::string& str) {
+    auto tmp = str;
+    auto end_pos = std::remove(tmp.begin(), tmp.end(), ' ');
+    tmp.erase(end_pos, tmp.end());
+    return tmp;
+}
+
+void _M_INTERNAL_PrintComment(const std::string& comment) {
+    std::cout << comment << std::endl;
+}
+
+void _M_INTERNAL_ThrowError(const std::string& expected, const std::string& got, const std::string& comment) {
+    std::cerr << "Assert failed: " << comment << std::endl
+              << "Expected:\t'" << expected << "'" << std::endl
+              << "Obtained:\t'" << got << "'" << std::endl;
+    exit(EXIT_FAILURE);
+}
+
+/// Generic equal check
 template<typename T>
-void T_AssertEq(const T& expected, const T& got) {
+void T_AssertEq(const T& expected, const T& got, const std::string& comment) {
+    _M_INTERNAL_PrintComment(comment);
     if (expected != got) {
-        std::cerr << "Assert failed:\n"
-                  << "Expected:\t'" << expected << "'\n"
-                  << "Obtained:\t'" << got << "'\n";
+        std::cerr << "Assert failed: " << comment << std::endl
+                  << "Expected:\t'" << expected << "'" << std::endl
+                  << "Obtained:\t'" << got << "'" << std::endl;
         exit(EXIT_FAILURE);
     }
 }
 
-void M_AssertTrue(bool value, std::string name) {
-    std::cout << "asserting " << name << std::endl;
+void _M_AssertTrue(bool value, const std::string& comment) {
+    _M_INTERNAL_PrintComment(comment);
     if (!value) {
-        std::cerr << "Assert failed: " << name << "\n"
-                  << "Expected:\t'" << "1" << "'\n"
-                  << "Obtained:\t'" << value << "'\n";
-        exit(EXIT_FAILURE);
+        _M_INTERNAL_ThrowError("true", "false", comment);
     }
-
-}
-
-void M_AssertEq(const std::string& expected, const std::string& got) {
-    T_AssertEq(expected, got);
 }
 
-void M_AssertEq(int expected, int got) {
-    T_AssertEq(expected, got);
-}
-
-
-std::string EraseSpaces(const std::string& str) {
-    auto tmp = str;
-    auto end_pos = std::remove(tmp.begin(), tmp.end(), ' ');
-    tmp.erase(end_pos, tmp.end());
-    return tmp;
-}
-void M_AssertContains( const std::string& whole, const std::string& sub) {
+void _M_AssertContains(const std::string& whole, const std::string& sub, const std::string& comment) {
     auto whole_t = EraseSpaces(whole);
     auto sub_t = EraseSpaces(sub);
 
+    _M_INTERNAL_PrintComment(comment);
     if (whole_t.find(sub_t) == std::string::npos) {
-        std::cerr << "Assert failed:\n"
-                  << "Got (spaces erased):\t'" << whole_t << "'\n"
-                  << "Expected containes (spaces erased):\t'" << sub_t << "'\n";
+        std::cerr << "Assert failed: " << std::endl
+                  << "Got (spaces erased):\t'" << whole_t << "'" << std::endl
+                  << "Expected contains (spaces erased):\t'" << sub_t << "'" << std::endl;
 
         exit(EXIT_FAILURE);
     }
 }
 
+void _M_AssertEq(const std::string& expected, const std::string& got, const std::string& comment) {
+    T_AssertEq(expected, got, comment);
+}
+
+void _M_AssertEq(int expected, int got, const std::string& comment) {
+    T_AssertEq(expected, got, comment);
+}
+
+void _M_AssertEq(const Error& expected, const Error& got, const std::string& comment) {
+    T_AssertEq(expected, got, comment);
+}
+
+void _M_AssertEq(const decltype(nullptr)& expected, const Error& got, const std::string& comment) {
+    T_AssertEq(Error{}, got, comment);
+}
 
 }
 
diff --git a/tests/automatic/consumer/consumer_api/consumer_api.cpp b/tests/automatic/consumer/consumer_api/consumer_api.cpp
index 73ebf67fe..d9065c56e 100644
--- a/tests/automatic/consumer/consumer_api/consumer_api.cpp
+++ b/tests/automatic/consumer/consumer_api/consumer_api.cpp
@@ -6,10 +6,6 @@
 #include "consumer/data_broker.h"
 #include "testing.h"
 
-using asapo::M_AssertEq;
-using asapo::M_AssertTrue;
-
-
 struct Args {
     std::string server;
     std::string run_name;
diff --git a/tests/automatic/consumer/next_multithread_broker/next_multithread_broker.cpp b/tests/automatic/consumer/next_multithread_broker/next_multithread_broker.cpp
index deea0768f..df24e18c1 100644
--- a/tests/automatic/consumer/next_multithread_broker/next_multithread_broker.cpp
+++ b/tests/automatic/consumer/next_multithread_broker/next_multithread_broker.cpp
@@ -5,9 +5,6 @@
 #include "consumer/data_broker.h"
 #include "testing.h"
 
-using asapo::M_AssertEq;
-using asapo::M_AssertTrue;
-
 void Assert(std::vector<asapo::FileInfos> file_infos, int nthreads, int nfiles) {
     std::vector<std::string> expect, result;
     for (int i = 1; i <= nfiles; i++) {
diff --git a/tests/automatic/curl_http_client/curl_http_client_command/curl_httpclient_command.cpp b/tests/automatic/curl_http_client/curl_http_client_command/curl_httpclient_command.cpp
index 264d88c6b..63d202b67 100644
--- a/tests/automatic/curl_http_client/curl_http_client_command/curl_httpclient_command.cpp
+++ b/tests/automatic/curl_http_client/curl_http_client_command/curl_httpclient_command.cpp
@@ -5,10 +5,6 @@
 #include "../../../consumer/api/cpp/src/server_data_broker.h"
 #include "preprocessor/definitions.h"
 
-using asapo::M_AssertEq;
-using asapo::M_AssertContains;
-using asapo::M_AssertTrue;
-
 struct Args {
     std::string uri_authorizer;
     std::string uri_fts;
diff --git a/tests/automatic/json_parser/parse_config_file/parse_config_file.cpp b/tests/automatic/json_parser/parse_config_file/parse_config_file.cpp
index eb4bb5903..3ebdc9f11 100644
--- a/tests/automatic/json_parser/parse_config_file/parse_config_file.cpp
+++ b/tests/automatic/json_parser/parse_config_file/parse_config_file.cpp
@@ -6,9 +6,6 @@
 
 #include "testing.h"
 
-using asapo::M_AssertEq;
-
-
 using namespace asapo;
 
 struct Settings {
diff --git a/tests/automatic/mongo_db/connect/connect_mongodb.cpp b/tests/automatic/mongo_db/connect/connect_mongodb.cpp
index 9c156098c..8715aae99 100644
--- a/tests/automatic/mongo_db/connect/connect_mongodb.cpp
+++ b/tests/automatic/mongo_db/connect/connect_mongodb.cpp
@@ -5,7 +5,6 @@
 #include "testing.h"
 #include "database/db_error.h"
 
-using asapo::M_AssertContains;
 using asapo::Error;
 
 void Assert(const Error& error, const std::string& expect) {
diff --git a/tests/automatic/mongo_db/insert_retrieve/insert_retrieve_mongodb.cpp b/tests/automatic/mongo_db/insert_retrieve/insert_retrieve_mongodb.cpp
index abeb042eb..8cf88e458 100644
--- a/tests/automatic/mongo_db/insert_retrieve/insert_retrieve_mongodb.cpp
+++ b/tests/automatic/mongo_db/insert_retrieve/insert_retrieve_mongodb.cpp
@@ -4,13 +4,8 @@
 #include "../../../common/cpp/src/database/mongodb_client.h"
 #include "testing.h"
 
-
-using asapo::M_AssertContains;
-using asapo::M_AssertTrue;
 using asapo::Error;
 
-
-
 void Assert(const Error& error, const std::string& expect) {
     std::string result;
     if (error == nullptr) {
@@ -66,7 +61,7 @@ int main(int argc, char* argv[]) {
         db_new.Connect("127.0.0.1", "data");
         err = db_new.GetById("test", fi.id, &fi_db);
         M_AssertTrue(fi_db == fi, "get record from db");
-        Assert(err, "OK");
+        M_AssertEq(nullptr, err);
         err = db_new.GetById("test", 0, &fi_db);
         Assert(err, "No record");
     }
diff --git a/tests/automatic/mongo_db/insert_retrieve_dataset/insert_retrieve_dataset_mongodb.cpp b/tests/automatic/mongo_db/insert_retrieve_dataset/insert_retrieve_dataset_mongodb.cpp
index 944bfed46..6cbaba641 100644
--- a/tests/automatic/mongo_db/insert_retrieve_dataset/insert_retrieve_dataset_mongodb.cpp
+++ b/tests/automatic/mongo_db/insert_retrieve_dataset/insert_retrieve_dataset_mongodb.cpp
@@ -4,13 +4,8 @@
 #include "../../../common/cpp/src/database/mongodb_client.h"
 #include "testing.h"
 
-
-using asapo::M_AssertContains;
-using asapo::M_AssertTrue;
-
 using asapo::Error;
 
-
 void Assert(const Error& error, const std::string& expect) {
     std::string result;
     if (error == nullptr) {
@@ -71,7 +66,7 @@ int main(int argc, char* argv[]) {
         asapo::FileInfo fi_db;
         err = db.GetDataSetById("test", subset_id, fi.id, &fi_db);
         M_AssertTrue(fi_db == fi, "get record from db");
-        Assert(err, "OK");
+        M_AssertEq(nullptr, err);
         err = db.GetDataSetById("test", 0, 0, &fi_db);
         Assert(err, "No record");
     }
diff --git a/tests/automatic/mongo_db/upsert/upsert_mongodb.cpp b/tests/automatic/mongo_db/upsert/upsert_mongodb.cpp
index 89ec2de53..f1420bcf6 100644
--- a/tests/automatic/mongo_db/upsert/upsert_mongodb.cpp
+++ b/tests/automatic/mongo_db/upsert/upsert_mongodb.cpp
@@ -4,11 +4,8 @@
 #include "../../../common/cpp/src/database/mongodb_client.h"
 #include "testing.h"
 
-
-using asapo::M_AssertContains;
 using asapo::Error;
 
-
 void Assert(const Error& error, const std::string& expect) {
     std::string result;
     if (error == nullptr) {
diff --git a/tests/automatic/system_io/ip_tcp_network/client_serv/ip_tcp_network.cpp b/tests/automatic/system_io/ip_tcp_network/client_serv/ip_tcp_network.cpp
index 2c3dea1c3..a0a0c224b 100644
--- a/tests/automatic/system_io/ip_tcp_network/client_serv/ip_tcp_network.cpp
+++ b/tests/automatic/system_io/ip_tcp_network/client_serv/ip_tcp_network.cpp
@@ -13,7 +13,6 @@ using asapo::AddressFamilies;
 using asapo::SocketTypes;
 using asapo::SocketProtocols;
 using asapo::FileDescriptor;
-using asapo::M_AssertEq;
 
 using namespace std::chrono;
 
diff --git a/tests/automatic/system_io/ip_tcp_network/client_serv_multicon/multicon.cpp b/tests/automatic/system_io/ip_tcp_network/client_serv_multicon/multicon.cpp
index 12a9fbc2e..bb40830c9 100644
--- a/tests/automatic/system_io/ip_tcp_network/client_serv_multicon/multicon.cpp
+++ b/tests/automatic/system_io/ip_tcp_network/client_serv_multicon/multicon.cpp
@@ -14,7 +14,6 @@ using asapo::AddressFamilies;
 using asapo::SocketTypes;
 using asapo::SocketProtocols;
 using asapo::SocketDescriptor;
-using asapo::M_AssertEq;
 
 using namespace std::chrono;
 
diff --git a/tests/automatic/system_io/read_file_content/read_file_content.cpp b/tests/automatic/system_io/read_file_content/read_file_content.cpp
index 8e495e722..3fe4893f5 100644
--- a/tests/automatic/system_io/read_file_content/read_file_content.cpp
+++ b/tests/automatic/system_io/read_file_content/read_file_content.cpp
@@ -32,6 +32,6 @@ int main(int argc, char* argv[]) {
         result = err->Explain();
     }
 
-    asapo::M_AssertContains(result, expect);
+    M_AssertContains(result, expect);
     return 0;
 }
diff --git a/tests/automatic/system_io/read_folder_content/read_folder_content.cpp b/tests/automatic/system_io/read_folder_content/read_folder_content.cpp
index dea3ca1a9..017d6fa76 100644
--- a/tests/automatic/system_io/read_folder_content/read_folder_content.cpp
+++ b/tests/automatic/system_io/read_folder_content/read_folder_content.cpp
@@ -6,10 +6,6 @@
 using asapo::IO;
 using asapo::Error;
 
-
-using asapo::M_AssertEq;
-using asapo::M_AssertContains;
-
 int main(int argc, char* argv[]) {
     if (argc != 3) {
         std::cout << "Wrong number of arguments" << std::endl;
diff --git a/tests/automatic/system_io/read_string_from_file/read_string_from_file.cpp b/tests/automatic/system_io/read_string_from_file/read_string_from_file.cpp
index 9c12ac417..acc770383 100644
--- a/tests/automatic/system_io/read_string_from_file/read_string_from_file.cpp
+++ b/tests/automatic/system_io/read_string_from_file/read_string_from_file.cpp
@@ -22,6 +22,6 @@ int main(int argc, char* argv[]) {
         result = err->Explain();
     }
 
-    asapo::M_AssertContains(result, expect);
+    M_AssertContains(result, expect);
     return 0;
 }
diff --git a/tests/automatic/system_io/read_subdirectories/read_subdirectories.cpp b/tests/automatic/system_io/read_subdirectories/read_subdirectories.cpp
index ecb33cb30..0b3549041 100644
--- a/tests/automatic/system_io/read_subdirectories/read_subdirectories.cpp
+++ b/tests/automatic/system_io/read_subdirectories/read_subdirectories.cpp
@@ -6,10 +6,6 @@
 using asapo::IO;
 using asapo::Error;
 
-
-using asapo::M_AssertEq;
-using asapo::M_AssertContains;
-
 int main(int argc, char* argv[]) {
     if (argc != 3) {
         std::cout << "Wrong number of arguments" << std::endl;
diff --git a/tests/automatic/system_io/resolve_hostname_to_ip/resolve_hostname_to_ip.cpp b/tests/automatic/system_io/resolve_hostname_to_ip/resolve_hostname_to_ip.cpp
index 71c5984a3..c45cd6b19 100644
--- a/tests/automatic/system_io/resolve_hostname_to_ip/resolve_hostname_to_ip.cpp
+++ b/tests/automatic/system_io/resolve_hostname_to_ip/resolve_hostname_to_ip.cpp
@@ -6,10 +6,6 @@
 using asapo::Error;
 using asapo::ErrorType;
 
-using asapo::M_AssertEq;
-using asapo::M_AssertTrue;
-
-
 void Check(const std::string& expected_ip_address, const std::string& hostname) {
     std::cout << "Checking: " << hostname << std::endl;
     Error err;
diff --git a/tests/automatic/system_io/write_data_to_file/write_data_to_file.cpp b/tests/automatic/system_io/write_data_to_file/write_data_to_file.cpp
index 8231f5f4b..3879e7c9c 100644
--- a/tests/automatic/system_io/write_data_to_file/write_data_to_file.cpp
+++ b/tests/automatic/system_io/write_data_to_file/write_data_to_file.cpp
@@ -36,7 +36,7 @@ void AssertGoodResult(const std::unique_ptr<IO>& io, const Error& err, const Fil
     Error read_err;
     uint64_t size = params.length;
     auto read_data = io->GetDataFromFile(params.fname, &size, &read_err);
-    asapo::M_AssertContains(std::string(read_data.get(), read_data.get() + params.length), "123");
+    M_AssertContains(std::string(read_data.get(), read_data.get() + params.length), "123");
 }
 
 void AssertBadResult(const Error& err, const Args& params) {
@@ -44,7 +44,7 @@ void AssertBadResult(const Error& err, const Args& params) {
         std::cerr << "Should be error" << std::endl;
         exit(EXIT_FAILURE);
     }
-    asapo::M_AssertContains(err->Explain(), params.message);
+    M_AssertContains(err->Explain(), params.message);
 }
 
 
-- 
GitLab