Skip to content

Feature: Implementing Algorithm Superclass#47

Merged
MahirEmran merged 13 commits intomainfrom
algorithm-superclass
Apr 17, 2026
Merged

Feature: Implementing Algorithm Superclass#47
MahirEmran merged 13 commits intomainfrom
algorithm-superclass

Conversation

@MahirEmran
Copy link
Copy Markdown
Contributor

@MahirEmran MahirEmran commented Oct 28, 2025

Description

Resolves #23

  • Added EdgeFilteringAlgorithm into DistancePipelineExecutor constructor
  • Edited DistancePipeline to have 4 items
  • Added edge_filters.hpp w/ ProvideEdgeFilteringAlgorithm and ModifyingPipeline
  • Added OPT_ASSIGN flags

Artifacts for PR #47 (DO NOT CHANGE)

@nguy8tri
Copy link
Copy Markdown
Collaborator

nguy8tri commented Nov 4, 2025

Hi, so you may notice that your coverage is failing for unapparent reasons. A recent bug that was introduced into Linux is the likely culprit, but unfortunately, we don't know what the bug is or how to fix it. However, we do know a way to go around it. I have noticed that you've added some new tests to pipeline-tests.cpp. You should try moving them to nominal-pipeline-test.cpp to see if it fixes the issue. If that doesn't work, try making all the pipeline tests in one file.

Note

For reference, there seems to be an issue where instantiating templates across multiple locations makes for uncombined or incomplete coverage data. Thus, the solution to this issue is to only test a particular instantiation in one file. Attempting to test them in both files (as you've done for DistancePipeline) will for some reason make gcovr believe that some things are not fully covered.

Also, I highly encourage you to work with mocks instead of instantiating new objects. This may seem odd at first, but it is a very robust way to mock behavior instead of making full on implementations, however small it looks. For instance, all your test stages within sequential-pipeline can easily be reformed into:

EXPECT_CALL(mock, function(args...)).WillOnce(testing::Return(your stuff))

As odd as it seems, it is an industry essential in nominal software development, but also just a good way to not worry about making test classes. This whole thing about mocking falls under something called Dependency Injection, used everywhere in the real world. To learn more about it, please look here: Mocking and Dependency Injection. You should also look at the purpose of the providers folder, detailed in Executor Injection, which is NEVER to be used directly in test cases (only indirectly through integration tests) :).

For reference the two functions that were not called (and why your coverage is failing in Github) are (there is almost no logic to this by the way):

  • [found::SequentialPipeline<std::pair<found::EulerAngles, found::EulerAngles>, found::Quaternion, 1ul>::Run(std::pair<found::EulerAngles, found::EulerAngles> const&) (line 222)]
  • [found::SequentialPipeline<std::vector<found::LocationRecord, std::allocatorfound::LocationRecord >, std::vector<found::LocationRecord, std::allocatorfound::LocationRecord >, 2ul>::Run(std::vector<found::LocationRecord, std::allocatorfound::LocationRecord > const&) (line 222)]

Copy link
Copy Markdown
Collaborator

@nguy8tri nguy8tri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to leave this to Josh, but I realized some confusion and tough issues warrant my input on this.

I want to first commend you on doing all this, its not easy to pick up a new code space and to run with it. That being said, there are many things that must be corrected. I think you will see that a lot of this could've been avoided by looking over the thourough documentation in FOUND (but who does that am I right haha?).

A summary of what I saw:

  1. I saw many opportunities for Dependency Mocking. Trust me, its worth your time, so take some time to learn how its used via the links in the comments.
  2. I also saw a lack of understanding around Dependency Injection Framework that's used in the code. No worries, that's not even taught in the 4 years (in my case 5) that you're at UW.
  3. Confusion around the coverage. That's understandable, we'll work through it together (for reference, we faced the same issue before, and it took me 3 months to figure it out)
  4. Unnecessary code that is good in theory but useless/unoptimized in production. That will take a while to shake itself out (I'm still doing that myself)
  5. Nitpicky style things to help you conform to the rest of the code.
  6. (Were you using AI? No pressure, I'm not your professor, and I use it a lot in my work as a software dev. However, some things seemed out of place so I thought I'd ask for curiosity sake.)

Anyways, I hope the comments here will be helpful! Please ask me any questions you might have!

Comment thread src/command-line/execution/executors.cpp
Comment thread src/command-line/execution/executors.hpp Outdated
Comment thread src/command-line/execution/executors.hpp Outdated
Comment thread src/command-line/parsing/options.hpp
Comment thread src/common/pipeline/pipelines.hpp Outdated
Comment thread test/distance/edge-filters-test.cpp
Comment thread test/distance/edge-filters-test.cpp Outdated
Comment thread test/distance/edge-filters-test.cpp Outdated
Comment thread test/distance/edge-filters-test.cpp Outdated
Comment thread test/distance/edge-filters-test.cpp Outdated
Comment thread src/distance/edge-filters.hpp Outdated
@MahirEmran MahirEmran requested a review from nguy8tri November 5, 2025 22:54
@nguy8tri nguy8tri changed the title Implementing Algorithm Superclass Feature: Implementing Algorithm Superclass Nov 9, 2025
Copy link
Copy Markdown
Collaborator

@nguy8tri nguy8tri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job on the changes. However there were a few changes thay weren't done, so I've explicitly marked them. Let me know if you have questions

Comment thread src/command-line/execution/executors.cpp Outdated
Comment thread src/command-line/execution/executors.hpp
Comment thread src/command-line/execution/executors.hpp
Comment thread src/distance/edge-filters.hpp Outdated
Comment thread src/providers/factory.hpp Outdated
Comment thread src/providers/stage-providers.hpp Outdated
Comment thread src/providers/stage-providers.hpp Outdated
Comment thread src/providers/stage-providers.hpp Outdated
Comment thread test/common/mocks/distance-mocks.hpp Outdated
Comment thread test/distance/edge-filters-test.cpp Outdated
MahirEmran and others added 2 commits November 20, 2025 13:33
…, updating pipelines to own stages (and modifying executors/pipeline tests accordingly), updating documentation
@MahirEmran
Copy link
Copy Markdown
Contributor Author

I had to make a merge in executors-test.cpp because (maybe some commit between last commit and now) there was difference in how DistanceOptions obj was being constructed. I feel like the one that was there before was odd (set all the fields in constructor rather than initializing object, then explicitly setting fields after), so I just went with current changes.

Had to rerun documentation check because first check failed the juliandate time test both attempts.

@MahirEmran MahirEmran requested a review from nguy8tri November 20, 2025 22:00
Copy link
Copy Markdown
Collaborator

@nguy8tri nguy8tri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work (and sorry I didn't respond soon). I just requested a change to eliminate a redundant variable and another comment (I'm a bit tired writing this so I don't have more meaningful comments right now). Please resolve all comments that are no longer relavent.

Comment thread src/common/pipeline/pipelines.hpp Outdated
/// The stages of this
Action *stages[N];
/// Ownership storage for the stages
std::unique_ptr<Action> ownedStages[N];
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be easier to just get rid of Action *stages[N]; and just have std::unique_ptr<Action> ownedStages[N]

Comment thread src/distance/edge-filters.hpp Outdated
* that are enabled in options and returns it. If no filter is enabled,
* returns nullptr to indicate "no filters".
*/
inline std::unique_ptr<EdgeFilteringAlgorithms> ProvideEdgeFilteringAlgorithm(const DistanceOptions &options) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be under stage-providers

…s -> stage-providers, using rvalue in stage-providers
@MahirEmran
Copy link
Copy Markdown
Contributor Author

I'm not sure how to see the changes that were requested, maybe issue on my end but Github just isn't showing me anything. Maybe I made the edits implicitly? Not sure.
Resolved comments resolved through previous commits, left the ones about rvalue unresolved and moving the provider to stage-providers since this commit should hopefully resolve them.

Copy link
Copy Markdown
Collaborator

@nguy8tri nguy8tri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job on the edits. I have now started moving towards stylistic edits (with a few programmatic ones too).

Comment thread src/common/pipeline/pipelines.hpp Outdated
/// The stages of this
Action *stages[N];
/// Ownership storage for the stages
std::unique_ptr<Action> ownedStages[N];
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just change this to stages instead of ownedStages

* and it throws an error if the image is not valid.
* Constructs a DistancePipelineExecutor (no edge-filters)
*
* @param options The DistanceOptions to configure the pipeline (moved into the executor)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for this comment (moved into the executor), we know this from reading the code, and its also an editorial change that no one would have context on years down the line.

Comment thread src/common/pipeline/pipelines.hpp Outdated
/// The stages of this
Action *stages[N];
/// Ownership storage for the stages
std::unique_ptr<Action> ownedStages[N];
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call this stages

Comment thread src/common/pipeline/pipelines.hpp Outdated
*
* Adds a stage to this pipeline, taking ownership of the provided stage.
*
* @param stage The stage to add to the pipeline (ownership transferred via unique_ptr)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are stating a postcondition here. For this, you will use the @post annotation instead of appending this parenthetical here.

Comment thread src/common/pipeline/pipelines.hpp Outdated
*
* @param stage The stage to add to the pipeline (ownership transferred via unique_ptr)
*
* @throw std::invalid_argument iff this pipeline has already been completed
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use this to mean the class itself when we're not in the initial description (Top description of this multi line comment). Its odd, I know, but I want you to get used to the practice. After all, classes represent objects, so referring to ourselves as this makes sense.

Comment thread src/providers/factory.hpp Outdated
std::move(distAlg),
std::move(vecAlg));
} else {
return std::make_unique<DistancePipelineExecutor>(std::move(options),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forward options

Comment thread src/common/pipeline/pipelines.hpp Outdated
*/
template<typename I, typename O> SequentialPipeline &AddStage(FunctionStage<I, O> &stage) {
template<typename StageType>
SequentialPipeline &AddStage(std::unique_ptr<StageType> stage) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want, you can change AddStage and Complete to accept && parameters to save space, but I'll let you decide.

Comment thread test/common/mocks/distance-mocks.hpp Outdated
MOCK_METHOD(PositionVector, Run, (const PositionVector& points), (override));
};

class MockEdgeFilteringAlgorithm : public EdgeFilteringAlgorithm {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Place in order (so below edge detection)

@@ -0,0 +1,44 @@
#include <gtest/gtest.h>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what this is here for, perhaps you should put tests in here for NoOpEdgeFilter instead, because you're testing pipeline behavior as opposed to actual filter behavior. In other words, a test for using the no op edge filtering algorithm will suffice here.

Comment thread test/integration/integration-test.cpp Outdated
}

// TODO: Remove/replace when noop-edge-filter is not needed.
TEST_F(IntegrationTest, TestMainDistanceNoOpEdgeFilterDisabled) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't one of the other tests cover not using the filter? In that case you could get rid of this.

@MahirEmran MahirEmran requested a review from nguy8tri March 27, 2026 23:21
Copy link
Copy Markdown
Collaborator

@nguy8tri nguy8tri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks good, congratulations on doing this

@MahirEmran MahirEmran merged commit 3713b37 into main Apr 17, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integration: Create Algorithm Superclass

2 participants