Feature: Implementing Algorithm Superclass#47
Conversation
|
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 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 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 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 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):
|
There was a problem hiding this comment.
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:
- 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.
- 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.
- 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)
- 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)
- Nitpicky style things to help you conform to the rest of the code.
- (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!
…s, moving providers to stage_providers, removing autos (replacing w/ std::unique_ptr), reordering distancepipeline
nguy8tri
left a comment
There was a problem hiding this comment.
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
…, updating pipelines to own stages (and modifying executors/pipeline tests accordingly), updating documentation
|
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. |
nguy8tri
left a comment
There was a problem hiding this comment.
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.
| /// The stages of this | ||
| Action *stages[N]; | ||
| /// Ownership storage for the stages | ||
| std::unique_ptr<Action> ownedStages[N]; |
There was a problem hiding this comment.
Would it be easier to just get rid of Action *stages[N]; and just have std::unique_ptr<Action> ownedStages[N]
| * 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) { |
There was a problem hiding this comment.
Should be under stage-providers
…s -> stage-providers, using rvalue in stage-providers
|
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. |
nguy8tri
left a comment
There was a problem hiding this comment.
Good job on the edits. I have now started moving towards stylistic edits (with a few programmatic ones too).
| /// The stages of this | ||
| Action *stages[N]; | ||
| /// Ownership storage for the stages | ||
| std::unique_ptr<Action> ownedStages[N]; |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
| /// The stages of this | ||
| Action *stages[N]; | ||
| /// Ownership storage for the stages | ||
| std::unique_ptr<Action> ownedStages[N]; |
| * | ||
| * 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) |
There was a problem hiding this comment.
You are stating a postcondition here. For this, you will use the @post annotation instead of appending this parenthetical here.
| * | ||
| * @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 |
There was a problem hiding this comment.
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.
| std::move(distAlg), | ||
| std::move(vecAlg)); | ||
| } else { | ||
| return std::make_unique<DistancePipelineExecutor>(std::move(options), |
| */ | ||
| template<typename I, typename O> SequentialPipeline &AddStage(FunctionStage<I, O> &stage) { | ||
| template<typename StageType> | ||
| SequentialPipeline &AddStage(std::unique_ptr<StageType> stage) { |
There was a problem hiding this comment.
If you want, you can change AddStage and Complete to accept && parameters to save space, but I'll let you decide.
| MOCK_METHOD(PositionVector, Run, (const PositionVector& points), (override)); | ||
| }; | ||
|
|
||
| class MockEdgeFilteringAlgorithm : public EdgeFilteringAlgorithm { |
There was a problem hiding this comment.
Place in order (so below edge detection)
| @@ -0,0 +1,44 @@ | |||
| #include <gtest/gtest.h> | |||
There was a problem hiding this comment.
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.
| } | ||
|
|
||
| // TODO: Remove/replace when noop-edge-filter is not needed. | ||
| TEST_F(IntegrationTest, TestMainDistanceNoOpEdgeFilterDisabled) { |
There was a problem hiding this comment.
Doesn't one of the other tests cover not using the filter? In that case you could get rid of this.
nguy8tri
left a comment
There was a problem hiding this comment.
Everything looks good, congratulations on doing this
Description
Resolves #23
Artifacts for PR #47 (DO NOT CHANGE)