feat: add optional asynchronous/parallel support#312
feat: add optional asynchronous/parallel support#312Daan Timmer (daantimmer) wants to merge 20 commits intomainfrom
Conversation
✅
|
| Descriptor | Linter | Files | Fixed | Errors | Warnings | Elapsed time |
|---|---|---|---|---|---|---|
| ✅ ACTION | actionlint | 6 | 0 | 0 | 0.03s | |
| ✅ CPP | clang-format | 231 | 0 | 0 | 0 | 1.8s |
| ✅ DOCKERFILE | hadolint | 1 | 0 | 0 | 0.03s | |
| markdownlint | 7 | 4 | 17 | 0 | 1.18s | |
| ✅ MARKDOWN | markdown-table-formatter | 7 | 4 | 0 | 0 | 0.32s |
| ✅ REPOSITORY | git_diff | yes | no | no | 0.03s | |
| ✅ REPOSITORY | grype | yes | no | no | 34.47s | |
| ✅ REPOSITORY | ls-lint | yes | no | no | 0.1s | |
| ✅ REPOSITORY | secretlint | yes | no | no | 4.57s | |
| ✅ REPOSITORY | syft | yes | no | no | 2.18s | |
| ✅ REPOSITORY | trivy | yes | no | no | 13.15s | |
| ✅ REPOSITORY | trivy-sbom | yes | no | no | 0.27s | |
| ✅ REPOSITORY | trufflehog | yes | no | no | 5.59s | |
| lychee | 86 | 1 | 0 | 3.43s | ||
| ✅ YAML | prettier | 10 | 0 | 0 | 0 | 0.75s |
| ✅ YAML | v8r | 10 | 0 | 0 | 9.0s | |
| ✅ YAML | yamllint | 10 | 0 | 0 | 0.64s |
Detailed Issues
⚠️ SPELL / lychee - 1 error
[404] https://github.com/yourname/amp-cucumber-cpp-runner.git | Network error: Not Found
📝 Summary
---------------------
🔍 Total..........159
✅ Successful.....158
⏳ Timeouts.........0
🔀 Redirected.......0
👻 Excluded.........0
❓ Unknown..........0
🚫 Errors...........1
Errors in CONTRIBUTING.md
[404] https://github.com/yourname/amp-cucumber-cpp-runner.git | Network error: Not Found
⚠️ MARKDOWN / markdownlint - 17 errors
CHANGELOG.md:30 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Features"]
CHANGELOG.md:37 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Chores"]
CHANGELOG.md:45 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "⚠ BREAKING CHANGES"]
CHANGELOG.md:49 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Features"]
CHANGELOG.md:58 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Features"]
CHANGELOG.md:64 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Chores"]
CHANGELOG.md:72 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "⚠ BREAKING CHANGES"]
CHANGELOG.md:76 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Features"]
CHANGELOG.md:81 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Bug Fixes"]
CHANGELOG.md:90 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Features"]
CHANGELOG.md:101 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Chores"]
CHANGELOG.md:109 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "⚠ BREAKING CHANGES"]
CHANGELOG.md:113 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Features"]
CHANGELOG.md:138 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Bug Fixes"]
CHANGELOG.md:145 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Chores"]
cmake/WindowsToolchainFilesProvidedBy.md:1 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "<https://github.com/MarkSchofi..."]
README.md:114 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
See detailed reports in MegaLinter artifacts
Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining FLAVOR_SUGGESTIONS: false)
- Documentation: Custom Flavors
- Command:
npx mega-linter-runner@9.4.0 --custom-flavor-setup --custom-flavor-linters ACTION_ACTIONLINT,CPP_CLANG_FORMAT,DOCKERFILE_HADOLINT,MARKDOWN_MARKDOWNLINT,MARKDOWN_MARKDOWN_TABLE_FORMATTER,REPOSITORY_GIT_DIFF,REPOSITORY_GRYPE,REPOSITORY_LS_LINT,REPOSITORY_SECRETLINT,REPOSITORY_SYFT,REPOSITORY_TRIVY,REPOSITORY_TRIVY_SBOM,REPOSITORY_TRUFFLEHOG,SPELL_LYCHEE,YAML_PRETTIER,YAML_YAMLLINT,YAML_V8R

Show us your support by starring ⭐ the repository
There was a problem hiding this comment.
Pull request overview
Adds optional parallel scenario execution to the cucumber-cpp runner (guarded behind CCR_ENABLE_PARALLEL_SUPPORT / ENABLE_PARALLEL_SUPPORT) by introducing a libcoro-backed runtime adapter, along with supporting refactors to broadcasting and runtime wiring.
Changes:
- Add optional libcoro dependency plumbing and CMake presets for enabling parallel support.
- Refactor
util::Broadcasterinto an interface +BroadcasterImplimplementation to support parallelized event emission. - Introduce
ParallelRuntimeAdapterselected via new--parallelruntime option (when compiled with parallel support).
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| external/jbaldwin/libcoro/CMakeLists.txt | FetchContent integration for libcoro and warning suppression configuration. |
| external/jbaldwin/CMakeLists.txt | Adds jbaldwin subtree (libcoro) to the build. |
| external/CMakeLists.txt | Conditionally includes jbaldwin deps when CCR_ENABLE_PARALLEL_SUPPORT is on. |
| cucumber_cpp/library/util/Broadcaster.hpp | Converts broadcaster into an abstract interface; adds BroadcasterImpl. |
| cucumber_cpp/library/util/Broadcaster.cpp | Moves implementations onto BroadcasterImpl; minor const-correctness tweak. |
| cucumber_cpp/library/support/Types.hpp | Adds parallel option to runtime config; tweaks enum underlying type. |
| cucumber_cpp/library/runtime/Worker.hpp | Exposes hook/suite helpers needed by adapters; adds [[nodiscard]]. |
| cucumber_cpp/library/runtime/Worker.cpp | Removes suite-level runner; small logic simplification and envelope construction tweaks. |
| cucumber_cpp/library/runtime/SerialRuntimeAdapter.hpp | Adds RunTestSuite(...) helper and includes for moved logic. |
| cucumber_cpp/library/runtime/SerialRuntimeAdapter.cpp | Hosts suite-level execution logic previously in Worker. |
| cucumber_cpp/library/runtime/ParallelRuntimeAdapter.hpp | New parallel runtime adapter interface (libcoro-based). |
| cucumber_cpp/library/runtime/ParallelRuntimeAdapter.cpp | New parallel execution implementation with thread pool + queued broadcasting. |
| cucumber_cpp/library/runtime/MakeRuntime.hpp | Removes exported MakeAdapter declaration (now internal). |
| cucumber_cpp/library/runtime/MakeRuntime.cpp | Selects serial vs parallel adapter based on options.parallel + build flag. |
| cucumber_cpp/library/runtime/CMakeLists.txt | Conditionally builds/links parallel adapter + libcoro; defines ENABLE_PARALLEL_SUPPORT. |
| cucumber_cpp/library/query/Query.hpp | Switches Query to inherit BroadcasterImpl (since Broadcaster is now abstract). |
| cucumber_cpp/library/formatter/helper/Theme.cpp | Removes unused optional helper. |
| cucumber_cpp/library/formatter/UsageFormatter.cpp | Avoids structured binding copies in loop. |
| cucumber_cpp/library/formatter/SummaryFormatter.cpp | Avoids structured binding copies; removes unused locals. |
| cucumber_cpp/library/engine/test/TestStep.cpp | Updates test fixture broadcaster type to BroadcasterImpl. |
| cucumber_cpp/library/Application.hpp | Adds parallel CLI option storage; updates broadcaster type + integer widths. |
| cucumber_cpp/library/Application.cpp | Registers --parallel when compiled with parallel support; plumbs into RunOptions. |
| compatibility/BaseCompatibility.cpp | Updates broadcaster type to BroadcasterImpl. |
| CMakePresets.json | Adds Host/Windows presets enabling parallel support. |
| CMakeLists.txt | Introduces CCR_ENABLE_PARALLEL_SUPPORT option; finds libcoro when enabled; standard settings moved earlier. |
| .vscode/launch.json | Updates debug args to include parallel run flags. |
| .clang-tidy | Disables coroutine reference-parameter guideline warning. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…+20 standard settings
…e options for libcoro
|
| "--format", | ||
| "pretty", | ||
| "summary", | ||
| // "summary", |
There was a problem hiding this comment.
todo(?)
| return status != cucumber::messages::test_step_result_status::PASSED; | ||
| } | ||
|
|
||
| coro::task<void> RunTestCase(std::unique_ptr<coro::thread_pool>& tp, coro::latch& tasksLatch, runtime::Worker& worker, const cucumber::messages::gherkin_document& gherkinDocument, const assemble::AssembledTestCase& assembledTestCase, Context& testSuiteContext, bool& failing) |
There was a problem hiding this comment.
ignore this daan
todo (me) read this function more
notes for me
i am uncertain about how the examples in the cg match up here https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rcoro-capture
i think sonar has a point that its worth thinking about the lifetime of these params
is it better to have a unique pointer ref to tp here than a shared pointer or is that stupid to think about
| } | ||
| } | ||
|
|
||
| coro::task<void> ShutdownTask(coro::latch& latch) |
There was a problem hiding this comment.
can the reference to latch being passed i become dangling or otherwise invalid between ShutdownTask's invocation and the line upon which its co_awaited on?
| bool failing = false; | ||
| runtime::Worker synchronousWorker{ testRunStartedId, broadcaster, idGenerator, options, supportCodeLibrary, programContext }; | ||
|
|
||
| failing |= IsFailing(util::GetWorstTestStepResult(synchronousWorker.RunBeforeAllHooks()).status, options.dryRun); |
There was a problem hiding this comment.
I'm not fully familiar with cucumber's nomenclature, like what does failing mean for a test, and what does dryrun mean.
But failing for this variable and function sounds wrong to me. In a dry-run the test can still fail right, the failure is just ignored? So should it not be called something like:
| failing |= IsFailing(util::GetWorstTestStepResult(synchronousWorker.RunBeforeAllHooks()).status, options.dryRun); | |
| runNextTest |= ShouldContinueTesting(util::GetWorstTestStepResult(synchronousWorker.RunBeforeAllHooks()).status, options.dryRun); |


No description provided.