jiridanek commented on a change in pull request #880:
URL: https://github.com/apache/qpid-dispatch/pull/880#discussion_r505549994
##########
File path: tests/c_unittests/test_add_link.cpp
##########
@@ -0,0 +1,127 @@
+#include <cstddef>
+#include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <thread>
+
+#include "./qdr_doctest.h" // or .hpp, to make it clear this is a C++ header?
+
+extern "C" {
+#include "../../src/router_core/agent_config_auto_link.h"
+//#include <router_core/agent_config_auto_link.h>
+
+// declarations that don't have .h file
+void qd_router_setup_late(qd_dispatch_t *qd);
+}
+
+// This could be a viable path to address some sanitizer issues. Decide
+// that unittested code is not allowed to leak, under unittests, and
+// enforce it. As the amount of unittested code increases, the leaks
+// will get squeezed out, maybe.
+
+/// Redirects leak reports to a file, and fails the test if
+/// anything is reported (even suppressed leaks).
+class WithNoMemoryLeaks {
+ public:
+ char *path = strdup("unittests_memory_debug_logs_XXXXXX");
+ WithNoMemoryLeaks() {
+#if QD_MEMORY_DEBUG
+ int fd = mkstemp(path);
+ REQUIRE(fd != -1);
+ qd_alloc_debug_dump(path);
+#endif // QD_MEMORY_DEBUG
+ }
+
+ ~WithNoMemoryLeaks() {
+#if QD_MEMORY_DEBUG
+ std::ifstream f(path);
+ std::stringstream buffer;
+ buffer << f.rdbuf();
+ std::string reports = buffer.str();
+ CHECK_MESSAGE(reports.length() == 0, reports);
+ qd_alloc_debug_dump(nullptr);
+#endif // QD_MEMORY_DEBUG
+
+ free(path);
+ // TODO close that fd?
+ }
+};
+
+// It is not possible to initialize the router multiple times in the same
thread, due to
+// alloc pools declared as `extern __thread qd_alloc_pool_t *`. These will
have wrong values
+// the second time around, and there is no good way to hunt them all down and
NULL them.
+
+// This also prevents me from doing a startup time benchmark. I can't run
multiple startups
+// in a loop to average them easily. There will be a way, but not with `for
(auto _ : state)`.
+
+/// Initializes and deinitializes the router
+class QDR {
+ public:
+ qd_dispatch_t *qd;
+ void start() {
+ // prepare the smallest amount of things that qd_dispatch_free needs
to be present
+ qd = qd_dispatch(nullptr, false);
+ // qd can be configured at this point, e.g. qd->thread_count
+ REQUIRE(qd_dispatch_prepare(qd) == QD_ERROR_NONE);
+ qd_router_setup_late(qd); // sets up e.g. qd->router->router_core
+ };
+
+ /// cleaning up too early after init will lead to leaks and other
+ /// unpleasantries (I observed some invalid pointer accesses)
+ void wait() const {
+ // todo Can I detect when startup is done?
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
Review comment:
I haven't figured this out. If I don't wait, I get crashes. Is there
something specific I can wait for, or do I need a random timeout, or maybe for
a specific line in log? Initializing dispatch starts new thread(s) and I cannot
then call `qd_dispatch_free()` before the threads are done initializing.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]