Commit e8064869 authored by Dominik Charousset's avatar Dominik Charousset

Fix segfault during test shutdown

parent e2bea08c
...@@ -35,7 +35,7 @@ public: ...@@ -35,7 +35,7 @@ public:
virtual std::unique_ptr<runnable> make(context_ptr state) = 0; virtual std::unique_ptr<runnable> make(context_ptr state) = 0;
protected: protected:
std::unique_ptr<factory> next_; factory* next_ = nullptr;
std::string_view suite_name_; std::string_view suite_name_;
std::string_view description_; std::string_view description_;
block_type type_; block_type type_;
......
...@@ -19,6 +19,12 @@ namespace caf::test { ...@@ -19,6 +19,12 @@ namespace caf::test {
/// A registry for our factories. /// A registry for our factories.
class CAF_TEST_EXPORT registry { class CAF_TEST_EXPORT registry {
public: public:
constexpr registry() noexcept : head_(nullptr), tail_(nullptr) {
// nop
}
~registry();
/// Maps test names to factories. Elements are sorted by the order of their /// Maps test names to factories. Elements are sorted by the order of their
/// registration. /// registration.
using tests_map = unordered_flat_map<std::string_view, factory*>; using tests_map = unordered_flat_map<std::string_view, factory*>;
...@@ -38,21 +44,16 @@ public: ...@@ -38,21 +44,16 @@ public:
this->type_); this->type_);
} }
}; };
auto ptr = std::make_unique<impl>(suite_name, description, type); return instance().add(new impl(suite_name, description, type));
auto result = reinterpret_cast<ptrdiff_t>(ptr.get());
if (head_ == nullptr) {
head_ = std::move(ptr);
tail_ = head_.get();
} else {
tail_->next_ = std::move(ptr);
tail_ = tail_->next_.get();
}
return result;
} }
private: private:
static std::unique_ptr<factory> head_; ptrdiff_t add(factory* new_factory);
static factory* tail_;
static registry& instance();
factory* head_;
factory* tail_;
}; };
} // namespace caf::test } // namespace caf::test
...@@ -9,9 +9,18 @@ ...@@ -9,9 +9,18 @@
namespace caf::test { namespace caf::test {
registry::~registry() {
auto ptr = head_;
while (ptr != nullptr) {
auto next = ptr->next_;
delete ptr;
ptr = next;
}
}
registry::suites_map registry::suites() { registry::suites_map registry::suites() {
suites_map result; suites_map result;
for (auto ptr = head_.get(); ptr != nullptr; ptr = ptr->next_.get()) { for (auto* ptr = instance().head_; ptr != nullptr; ptr = ptr->next_) {
auto& suite = result[ptr->suite_name_]; auto& suite = result[ptr->suite_name_];
if (auto [iter, ok] = suite.emplace(ptr->description_, ptr); !ok) { if (auto [iter, ok] = suite.emplace(ptr->description_, ptr); !ok) {
auto msg = detail::format("duplicate test name in suite {}: {}", auto msg = detail::format("duplicate test name in suite {}: {}",
...@@ -22,8 +31,25 @@ registry::suites_map registry::suites() { ...@@ -22,8 +31,25 @@ registry::suites_map registry::suites() {
return result; return result;
} }
std::unique_ptr<factory> registry::head_; ptrdiff_t registry::add(factory* new_factory) {
if (head_ == nullptr) {
head_ = new_factory;
tail_ = head_;
} else {
tail_->next_ = new_factory;
tail_ = new_factory;
}
return reinterpret_cast<ptrdiff_t>(new_factory);
}
factory* registry::tail_; namespace {
registry default_instance;
} // namespace
registry& registry::instance() {
return default_instance;
}
} // namespace caf::test } // namespace caf::test
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment