This is an automated email from the ASF dual-hosted git repository.

jdanek pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git

commit f1d76afd7246396ca68ee66e6427e2f0280ae5e7
Author: Jiri DanÄ›k <[email protected]>
AuthorDate: Wed Dec 22 19:31:11 2021 +0100

    DISPATCH-1783 first test using the cpp-stub tool
    
    The test was originally proposed on DISPATCH-1566
---
 tests/CMakeLists.txt                               |  6 ++-
 tests/c_unittests/CMakeLists.txt                   |  9 +++-
 tests/c_unittests/c_unittests_main.cpp             | 58 +++++++++++++++++++++-
 ...c_unittests_main.cpp => qdr_stubbing_probe.cpp} | 15 ++++--
 ...c_unittests_main.cpp => qdr_stubbing_probe.hpp} | 26 ++++++++--
 tests/c_unittests/test_terminus.cpp                | 21 ++++++++
 6 files changed, 123 insertions(+), 12 deletions(-)

diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index fa6cad5..58507d2 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -274,7 +274,11 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/config-2
 install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ssl_certs
         DESTINATION ${QPID_DISPATCH_HOME_INSTALLED}/tests)
 
-add_subdirectory(c_unittests)
+# cpp-stub requires Linux
+if(UNIX AND NOT APPLE)
+  add_subdirectory(cpp-stub)
+  add_subdirectory(c_unittests)
+endif()
 
 if(BUILD_BENCHMARKS)
   add_subdirectory(c_benchmarks)
diff --git a/tests/c_unittests/CMakeLists.txt b/tests/c_unittests/CMakeLists.txt
index be1364f..5a9a9e5 100644
--- a/tests/c_unittests/CMakeLists.txt
+++ b/tests/c_unittests/CMakeLists.txt
@@ -17,7 +17,11 @@
 ## under the License.
 ##
 
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD_FLAGS}")
+# -fno-inline: just to be extra sure, no particular reason so far
+# -fno-builtin: GCC would optimize e.g. abs() and we would not be able to stub
+# -fno-stack-protector: 
https://stackoverflow.com/questions/12201625/disable-using-sprintf-chk
+# -D_FORTIFY_SOURCE=0: for Ubuntu with -O1+, 
https://stackoverflow.com/questions/34907503/gcc-fread-chk-warn-warning
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD_FLAGS} -fno-inline 
-fno-builtin -fno-stack-protector -U_FORTIFY_SOURCE")
 # DISPATCH-2196 Linking object files containing instances of the same C++ 
template fails on s390x with sanitizers enabled
 if(CMAKE_SYSTEM_PROCESSOR STREQUAL "s390x")
     # set the sanitizer flags only for linking, not for compilation; this 
workarounds the failure
@@ -27,6 +31,7 @@ else()
 endif()
 
 add_executable(c_unittests
+        qdr_stubbing_probe.cpp
         c_unittests_main.cpp
         doctest.h
         qdr_doctest.hpp
@@ -37,7 +42,7 @@ add_executable(c_unittests
         test_router_startup.cpp
         test_terminus.cpp
         $<TARGET_OBJECTS:qpid-dispatch>)
-target_link_libraries(c_unittests pthread qpid-dispatch-libraries)
+target_link_libraries(c_unittests cpp-stub pthread qpid-dispatch-libraries)
 
 file(COPY
         ${CMAKE_CURRENT_SOURCE_DIR}/minimal_silent.conf
diff --git a/tests/c_unittests/c_unittests_main.cpp 
b/tests/c_unittests/c_unittests_main.cpp
index 651cc14..de06ee2 100644
--- a/tests/c_unittests/c_unittests_main.cpp
+++ b/tests/c_unittests/c_unittests_main.cpp
@@ -17,5 +17,61 @@
  * under the License.
  */
 
-#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#define DOCTEST_CONFIG_IMPLEMENT
 #include "qdr_doctest.hpp"
+#include "cpp_stub.h"
+#include "qdr_stubbing_probe.hpp"
+
+#include <cstdio>
+#include <cstdlib>
+
+bool check_stubbing_works()
+{
+
+#if (defined(__s390__) || defined(__s390x__) || defined(__zarch__))
+    return false; // cpp-stub does not support
+#endif
+
+    {
+        Stub stub;
+        stub.set(probe, +[](int)->int { return 42; });
+        if (probe(0) != 42) {
+            return false;
+        }
+    }
+    {
+        Stub stub;
+        stub.set(abs, +[](int)->int{ return 24; });
+        if (probe(0) != 24) {
+            return false;
+        }
+    }
+    return true;
+}
+
+// https://github.com/doctest/doctest/blob/master/doc/markdown/main.md
+int main(int argc, char** argv)
+{
+    doctest::Context context;
+
+    if (!check_stubbing_works()) {
+#ifdef QD_REQUIRE_STUBBING_WORKS
+        fprintf(stderr, "QD_REQUIRE_STUBBING_WORKS was defined, but stubbing 
doesn't work\n");
+        abort();
+#else
+        fprintf(stderr, "Stubbing doesn't work. Define 
QD_REQUIRE_STUBBING_WORKS to get an abort()\n");
+#endif
+        context.addFilter("test-case-exclude", "*_STUB_*"); // skip testcases 
that require stubbing
+        context.addFilter("subcase-exclude", "*_STUB_*"); //  ditto for 
subcases
+    }
+
+    context.applyCommandLine(argc, argv);
+
+    int res = context.run();
+
+    if (context.shouldExit()) {
+        return res;
+    }
+
+    return res;
+}
diff --git a/tests/c_unittests/c_unittests_main.cpp 
b/tests/c_unittests/qdr_stubbing_probe.cpp
similarity index 78%
copy from tests/c_unittests/c_unittests_main.cpp
copy to tests/c_unittests/qdr_stubbing_probe.cpp
index 651cc14..8fe9cfd 100644
--- a/tests/c_unittests/c_unittests_main.cpp
+++ b/tests/c_unittests/qdr_stubbing_probe.cpp
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -17,5 +17,12 @@
  * under the License.
  */
 
-#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
-#include "qdr_doctest.hpp"
+#include "qdr_stubbing_probe.hpp"
+
+#include <cstdlib>
+
+int probe(int i)
+{
+    // we need to compile tests with `-fno-builtin` so that GCC does not 
replace this with its own inlined implementation
+    return abs(i);
+}
diff --git a/tests/c_unittests/c_unittests_main.cpp 
b/tests/c_unittests/qdr_stubbing_probe.hpp
similarity index 50%
copy from tests/c_unittests/c_unittests_main.cpp
copy to tests/c_unittests/qdr_stubbing_probe.hpp
index 651cc14..10f29f0 100644
--- a/tests/c_unittests/c_unittests_main.cpp
+++ b/tests/c_unittests/qdr_stubbing_probe.hpp
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -17,5 +17,23 @@
  * under the License.
  */
 
-#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
-#include "qdr_doctest.hpp"
+#ifndef QPID_DISPATCH_QDR_STUBBING_PROBE
+#define QPID_DISPATCH_QDR_STUBBING_PROBE
+
+/**
+ *
+ * This is an utility to perform ad-hoc check whether stubbing is succeeding.
+ *
+ * Note that `probe` is in a different compilation unit than 
`check_stubbing_works`.
+ * This is important, because functions called from the same compilation unit 
can be stubbed only
+ * with a Debug build (CMake profile), whereas functions in a different 
compilation unit
+ * can be stubbed even in RelWithDebInfo build. Enabling LTO seems to make any 
stubbing impossible.
+ */
+
+/// dummy function returning abs(int), convenient target for stubbing
+int probe(int);
+
+/// attempts to stub `probe` and returns true if successful
+bool check_stubbing_works();
+
+#endif  // QPID_DISPATCH_QDR_STUBBING_PROBE
diff --git a/tests/c_unittests/test_terminus.cpp 
b/tests/c_unittests/test_terminus.cpp
index 52d91ce..0e5057b 100644
--- a/tests/c_unittests/test_terminus.cpp
+++ b/tests/c_unittests/test_terminus.cpp
@@ -18,6 +18,7 @@
  */
 
 #include "qdr_doctest.hpp"
+#include "cpp_stub.h"
 
 extern "C" {
 #include "qpid/dispatch/router_core.h"
@@ -29,6 +30,15 @@ extern "C" {
 #include <stdio.h>
 }
 
+namespace vsnprintf_stub
+{
+int rc = 0;
+int stub(char *str, size_t size, const char *format, ...)
+{
+    return rc;
+}
+}  // namespace vsnprintf_stub
+
 TEST_CASE("test_safe_snprintf") {
     const int   OUTPUT_SIZE = 128;
     const char *TEST_MESSAGE = "something";
@@ -73,6 +83,17 @@ TEST_CASE("test_safe_snprintf") {
             CHECK(0 == len);
         }
     }
+
+    SUBCASE("vsnprintf failure (_STUB_)") {
+        Stub stub;
+        stub.set(vsnprintf, vsnprintf_stub::stub);
+        vsnprintf_stub::rc = -1;
+
+        output[0] = 'a';
+        len       = safe_snprintf(output, LEN + 10, TEST_MESSAGE);
+        CHECK(0 == len);
+        CHECK('\0' == output[0]);
+    }
 }
 
 TEST_CASE("test_qdr_terminus_format") {

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to