Don't store extra copy of all TestCaseInfo* in TestRegistry

We used to store a full vector of "views" of the registered test infos,
so that it can be retrieved externally. However, the only user of that
interface left was `Session`, specifically `Session::applyFilenameAsTags`.

By moving the adding of the filename tags into the `ITestCaseRegistry`
interface, we avoid storing the vector and make the initial test registration
faster.

The new code is ugly and shows a design/layering issue, but no worse than
the previous approach did.
This commit is contained in:
Martin Hořeňovský
2026-08-22 23:28:11 +02:00
parent 69da66ee73
commit ef3a728265
6 changed files with 19 additions and 17 deletions
+4
View File
@@ -72,6 +72,10 @@ namespace Catch {
#endif
}
ITestCaseRegistry& getMutableTestCaseRegistry() override {
return m_testCaseRegistry;
}
private:
TestRegistry m_testCaseRegistry;
ReporterRegistry m_reporterRegistry;
+1 -3
View File
@@ -140,9 +140,7 @@ namespace Catch {
};
void applyFilenamesAsTags() {
for (auto const& testInfo : getRegistryHub().getTestCaseRegistry().getAllInfos()) {
testInfo->addFilenameTag();
}
getMutableRegistryHub().getMutableTestCaseRegistry().enableFilenameTags();
}
// Creates empty file at path. The path must be writable, we do not
@@ -53,6 +53,8 @@ namespace Catch {
virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 0;
virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
virtual void registerStartupException() noexcept = 0;
virtual ITestCaseRegistry& getMutableTestCaseRegistry() = 0;
};
IRegistryHub const& getRegistryHub();
@@ -19,8 +19,7 @@ namespace Catch {
class ITestCaseRegistry {
public:
virtual ~ITestCaseRegistry(); // = default
// TODO: this exists only for adding filenames to test cases -- let's expose this in a saner way later
virtual std::vector<TestCaseInfo* > const& getAllInfos() const = 0;
virtual void enableFilenameTags() = 0;
virtual std::vector<TestCaseHandle> const& getAllTests() const = 0;
virtual std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const = 0;
};
@@ -131,21 +131,21 @@ namespace Catch {
// We pre-reserve some reasonable number of tests to avoid the
// initial geometric growth churning during test registration.
m_handles.reserve( kInitialTestCount );
m_viewed_test_infos.reserve( kInitialTestCount );
m_owned_test_infos.reserve( kInitialTestCount );
m_test_infos.reserve( kInitialTestCount );
m_invokers.reserve( kInitialTestCount );
}
TestRegistry::~TestRegistry() = default;
void TestRegistry::registerTest(Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker) {
m_handles.emplace_back(testInfo.get(), testInvoker.get());
m_viewed_test_infos.push_back(testInfo.get());
m_owned_test_infos.push_back(CATCH_MOVE(testInfo));
m_test_infos.push_back(CATCH_MOVE(testInfo));
m_invokers.push_back(CATCH_MOVE(testInvoker));
}
std::vector<TestCaseInfo*> const& TestRegistry::getAllInfos() const {
return m_viewed_test_infos;
void TestRegistry::enableFilenameTags() {
for (auto& info : m_test_infos) {
info->addFilenameTag();
}
}
std::vector<TestCaseHandle> const& TestRegistry::getAllTests() const {
@@ -31,8 +31,8 @@ namespace Catch {
class TestRegistry final : public ITestCaseRegistry {
public:
void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
void enableFilenameTags() override;
std::vector<TestCaseInfo*> const& getAllInfos() const override;
std::vector<TestCaseHandle> const& getAllTests() const override;
std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const override;
@@ -40,12 +40,11 @@ namespace Catch {
~TestRegistry() override; // = default
private:
std::vector<Detail::unique_ptr<TestCaseInfo>> m_owned_test_infos;
// Keeps a materialized vector for `getAllInfos`.
// We should get rid of that eventually (see interface note)
std::vector<TestCaseInfo*> m_viewed_test_infos;
// Owns the test infos for handles
std::vector<Detail::unique_ptr<TestCaseInfo>> m_test_infos;
// Owns the test invokers for handles
std::vector<Detail::unique_ptr<ITestInvoker>> m_invokers;
std::vector<TestCaseHandle> m_handles;
mutable TestRunOrder m_currentSortOrder = TestRunOrder::Declared;
mutable std::vector<TestCaseHandle> m_sortedFunctions;