55//
66// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
77// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
8+ // Copyright (c) 2026 Gennaro Prota (gennaro.prota@gmail.com)
89//
910// Official repository: https://github.com/cppalliance/mrdocs
1011//
1718#include " Support/Comparison.hpp"
1819#include < lib/ConfigImpl.hpp>
1920#include < lib/CorpusImpl.hpp>
21+ #include < lib/Gen/hbs/DataDrivenGenerators.hpp>
2022#include < lib/MrDocsCompilationDatabase.hpp>
2123#include < lib/SingleFileDB.hpp>
2224#include < lib/Support/ExecuteAndWaitWithLogging.hpp>
@@ -37,9 +39,10 @@ namespace mrdocs {
3739
3840TestRunner::
3941TestRunner (std::string_view generator)
40- : gen_(findGenerator( generator) )
42+ : genId_( generator)
4143{
42- MRDOCS_ASSERT (gen_ != nullptr );
44+ // The generator is looked up per-test in `handleFile`; after that,
45+ // test's mrdocs.yml has been loaded and addon discovery has run.
4346}
4447
4548namespace {
@@ -165,8 +168,37 @@ handleFile(
165168 if (!ensureRegularCpp (filePath))
166169 return ;
167170
168- auto resolved = resolveTestLayout (
169- filePath, dirSettings, gen_->fileExtension (), dirs_, testArgs.action );
171+ // Load the per-file mrdocs.yml first so data-driven generators
172+ // contributed via addons-supplemental are visible to discovery
173+ // before the chosen generator is looked up.
174+ //
175+ // The generator registry is process-global and persists across
176+ // tests. `discoverDataDrivenGenerators` is idempotent (it skips ids
177+ // already installed), so re-running it per fixture is safe; but
178+ // it also means the first fixture that registers a given id
179+ // wins, and a later fixture that ships a generator directory
180+ // with the same id will see its own contents quietly ignored.
181+ Expected<LoadedTestSettings> loaded =
182+ loadTestSettings (filePath, dirSettings, dirs_);
183+ if (!loaded)
184+ {
185+ return report::error (" {}: \" {}\" " , loaded.error (), filePath);
186+ }
187+ Expected<void > discovered =
188+ hbs::discoverDataDrivenGenerators (loaded->settings );
189+ if (!discovered)
190+ {
191+ return report::error (" {}: \" {}\" " , discovered.error (), filePath);
192+ }
193+ Generator const * gen = findGenerator (genId_);
194+ if (!gen)
195+ {
196+ return report::error (
197+ " {}: the Generator \" {}\" was not found" , filePath, genId_);
198+ }
199+
200+ Expected<ResolvedLayout> resolved = buildTestLayout (
201+ filePath, *std::move (loaded), gen->fileExtension (), dirs_, testArgs.action );
170202 if (!resolved)
171203 {
172204 return report::error (" {}: \" {}\" " , resolved.error (), filePath);
@@ -194,7 +226,7 @@ handleFile(
194226 db,
195227 config,
196228 defaultIncludePaths);
197- handleCompilationDatabase (filePath, compilations, config, layout);
229+ handleCompilationDatabase (filePath, *gen, compilations, config, layout);
198230 };
199231
200232 runWith ({ " clang" , " -std=c++23" });
@@ -204,6 +236,7 @@ handleFile(
204236void
205237TestRunner::handleCompilationDatabase (
206238 llvm::StringRef filePath,
239+ Generator const & gen,
207240 MrDocsCompilationDatabase const & compilations,
208241 std::shared_ptr<ConfigImpl const > const & config,
209242 TestLayout const & layout)
@@ -219,7 +252,7 @@ TestRunner::handleCompilationDatabase(
219252 {
220253 test_support::SinglePageArgs args{
221254 layout,
222- *gen_ ,
255+ gen ,
223256 **corpus,
224257 filePath,
225258 testArgs.action ,
@@ -237,7 +270,7 @@ TestRunner::handleCompilationDatabase(
237270 {
238271 test_support::MultipageArgs args{
239272 layout,
240- *gen_ ,
273+ gen ,
241274 **corpus,
242275 testArgs.action ,
243276 testArgs.forceOption .getValue (),
0 commit comments