-
Notifications
You must be signed in to change notification settings - Fork 260
Validate volume filter config (closes #571) #589
Validate volume filter config (closes #571) #589
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
almost done
plugins/volumeFilter.go
Outdated
|
||
// return the original error, as it is already well-formatted | ||
if _, e := parseVolumeFilterMode(string(c.mode)); e != nil { | ||
return e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should always wrap the error as a habit as it helps trace the error path. long term we will need to find a less verbose solution, but this has been working well so far.
plugins/volumeFilter_test.go
Outdated
name string | ||
sellBaseCapBase *float64 | ||
sellBaseCapQuote *float64 | ||
mode volumeFilterMode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should take action as an input too.
don't need to add more than 1 test case to make sure it fails on an invalid value.
all existing cases should take a combination of buy
and sell
action (or maybe all are sell
but only one success case is buy
to prove the buy case also works)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. To make this more efficient (vary across buy and sell for existing tests), I've just done the same loop over modes and actions we've done in other test cases.
plugins/volumeFilter_test.go
Outdated
t.Run(k.name, func(t *testing.T) { | ||
c := makeRawVolumeFilterConfig(k.sellBaseCapBase, k.sellBaseCapQuote, k.mode, k.marketIDs, k.accountIDs) | ||
gotErr := c.Validate() | ||
assert.Equal(t, gotErr, k.wantErr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should wantErr
be the second arg and gotErr
the third arg?
plugins/filterFactory.go
Outdated
@@ -145,6 +145,15 @@ func makeVolumeFilterConfig(configInput string) (*VolumeFilterConfig, error) { | |||
return nil, fmt.Errorf("invalid input (%s), the third part needs to be \"base\" or \"quote\"", configInput) | |||
} | |||
|
|||
// marketIDs and account IDs might not be present in the config string, but cannot be nil on the config | |||
if config.additionalMarketIDs == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@debnil this is not a good idea. now we have two places that "set" these two arrays, here and in parseVolumeFilterModifier
.
coding philosophy tip: the goal of software isn't to hide errors, but to surface errors that do occur more transparently, because they will occur.
in this case we are trying to hide the fact that the input value is nil
by automagically handling it. What this inadvertently does is it expands the API for the VolumeFilterConfig
which was not our goal here but is the unintended side-effect. please revert back.
I'm not sure if we had discussed adding this logic, but if there was a previous comment that indicated it please let me know so I can clarify requested changes better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These lines changed because now, when we validate the config, we check that market IDs and account IDs are not nil. This function is what creates a config. Previously, when parsing a config string, if it did not specify the account and market IDs, those would be nil by default.
It wasn't explicitly requested - but this failed CI (because the config now fails validation in all of these functions). Hence, I made these changes.
The point of this pull request is to validate the config. That requires making changes like this to other functions that are now invalid. We could in theory split these in a separate PR, but that seems meaningless without the validation changes. If these changes are a bad idea, then we should either reconsider the validation scheme or change how the parsing logic works above this - I think this approach does that in the cleanest way possible, given the way that market and account IDs are parsed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to take a step back when looking at this PR. nil
is a valid value for both arrays, lets not change the API.
Can you please do the following?
- In
makeFilterVolume
, add a comment above the line where we callutils.Dedupe
to say thatappend(s, nil. . .)
is valid. - In
makeSQLQueryDailyVolume
above where we check the length of optionalAccountIDs, add a comment that says that len(a) where a is a nil array is valid and returns 0 - In the struct definition of VolumeFilterConfig, add a comment next to the two arrays saying that these can be nil
- In
TestDailyVolumeByDate_QueryRow
copy the first test case and replacequeryByOptionalAccountIDs: []string{}
withqueryByOptionalAccountIDs:nil,
leaving everything else the same. - Remove all changes in this PR related to converting
nil
to an empty array and remove the check from validation.
If the above does not work for some reason, please let me know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good - these are good clarifications, changes made!
plugins/filterFactory_test.go
Outdated
@@ -143,48 +143,48 @@ func TestMakeVolumeFilterConfig(t *testing.T) { | |||
wantConfig: &VolumeFilterConfig{ | |||
BaseAssetCapInBaseUnits: pointy.Float64(3500.0), | |||
BaseAssetCapInQuoteUnits: nil, | |||
additionalMarketIDs: nil, | |||
optionalAccountIDs: nil, | |||
additionalMarketIDs: []string{}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why did these lines change?
I assume this was working correctly in the last round of reviews, otherwise I would have commented on it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR submission tip: if this is a "new idea" you should comment on why something changed.
In general when you make a PR you should add 2-3 comments inline to "guide" the reviewer on how to view the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I sent a message on Slack about this when I sent the PR, but you're right that it should get posted on the PR too. Adding it here:
I had to make a couple changes in other tests that are now failing due to validation. It doesn't really make sense to separate these changes into other PRs, since the changes matter because of validation. These are things like "no nil marketIDs or optionalAccountIDs on volumeFilterConfig after parsing".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh actually, I did notice these CI failures - that's why I didn't request a review on this two weeks ago - was planning on coming back and fixing those after the other PRs in buy TWAP were done, you just beat me to the review :) The version that you reviewed (the initial commit) has all of these failures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok thanks for clarifying. see above, we can revert all this to the original form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we were almost done in the last review, but there's a lot of red and green lines from the last iteration of the review. Inline I've requested to revert most of the "new ideas" and to fix up the suggestions made in the previous iteration.
See the new Pull Request Guide for details on the expectations when submitting Pull Requests.
plugins/filterFactory_test.go
Outdated
@@ -143,48 +143,48 @@ func TestMakeVolumeFilterConfig(t *testing.T) { | |||
wantConfig: &VolumeFilterConfig{ | |||
BaseAssetCapInBaseUnits: pointy.Float64(3500.0), | |||
BaseAssetCapInQuoteUnits: nil, | |||
additionalMarketIDs: nil, | |||
optionalAccountIDs: nil, | |||
additionalMarketIDs: []string{}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR submission tip: if this is a "new idea" you should comment on why something changed.
In general when you make a PR you should add 2-3 comments inline to "guide" the reviewer on how to view the PR.
plugins/volumeFilter_test.go
Outdated
}, | ||
} | ||
|
||
for _, mode := range []volumeFilterMode{volumeFilterModeExact, volumeFilterModeIgnore} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the test has become more complex with this change vs what was in the last round of review, therefore harder to maintain.
there's also too many red and green lines from the last round of reviews which is increasing the PR overhead. please revert and do the changes that were requested previously, quoting below for reference since the previous comment is now marked as outdated:
should take action as an input too.
don't need to add more than 1 test case to make sure it fails on an invalid value.
all existing cases should take a combination of buy and sell action (or maybe all are sell but only one success case is buy to prove the buy case also works)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those changes are already done. It now loops over both buy and sell actions (which is what these comments request). I'm also looping over the mode, as that's the testing pattern we've used in the tests done in the last few weeks - as I put out this PR 2-3 weeks ago, before we started varying over modes and actions in these config tests. But the mode loop is not essential, and I can hard code the mode in the testing struct if you think it makes sense.
I've also added two invalid test cases - one to test invalid action, one to test invalid mode, since those wouldn't be caught by the above testing. 2 versus 1 failure cases isn't a huge difference, especially when both test otherwise untested failure cases.
That said, this is making me reconsider the quantitative checks of red and green lines outlined in the PR policy we're discussing. The vast majority of the red and green lines in this file are because of a level of indentation changing. This is directly because of the request to test buy and sell actions for most test cases. It's just easier to do that systematically than pick some successful cases and create a couple of test cases. The additional changes due to mode are (+1, -10): one additional line to loop over the mode, and ten deletions of the mode from each test.
As discussed above, the other changes displayed are the result of separate changes that came up when I ran these tests locally, found a bunch of tests now failing because of validation, and fixed those. I'm not sure why the CI didn't trigger those failures, since validate was being called before. But I don't think not including them in this PR is an option. Agreed the process level fix here is to include a comment about this - which I sent over Slack but somehow didn't get commented to the PR - that's on me, so all good there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It now loops over both buy and sell actions (which is what these comments request).
I think this is where the misunderstanding is on this issue. I was expecting hardcoded cases, some of which were buys and some other as sells.
let's do the following:
- back out this for loop change and revert back to all the old test cases
- add a new test case where it fails on an invalid value of action. success case invalid memory address or nil pointer dereference when SOURCE_SECRET_SEED is empty in config #1 should use action buy, success case Support CAP-0003: Account for the "liabilities" on an account #2 should use action sell.
I think the above is really all we need. can we do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, perfect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have a very clean way forward now. let's try and land this in the next shot.
plugins/filterFactory_test.go
Outdated
@@ -143,48 +143,48 @@ func TestMakeVolumeFilterConfig(t *testing.T) { | |||
wantConfig: &VolumeFilterConfig{ | |||
BaseAssetCapInBaseUnits: pointy.Float64(3500.0), | |||
BaseAssetCapInQuoteUnits: nil, | |||
additionalMarketIDs: nil, | |||
optionalAccountIDs: nil, | |||
additionalMarketIDs: []string{}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok thanks for clarifying. see above, we can revert all this to the original form.
plugins/volumeFilter_test.go
Outdated
}, | ||
} | ||
|
||
for _, mode := range []volumeFilterMode{volumeFilterModeExact, volumeFilterModeIgnore} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It now loops over both buy and sell actions (which is what these comments request).
I think this is where the misunderstanding is on this issue. I was expecting hardcoded cases, some of which were buys and some other as sells.
let's do the following:
- back out this for loop change and revert back to all the old test cases
- add a new test case where it fails on an invalid value of action. success case invalid memory address or nil pointer dereference when SOURCE_SECRET_SEED is empty in config #1 should use action buy, success case Support CAP-0003: Account for the "liabilities" on an account #2 should use action sell.
I think the above is really all we need. can we do this?
plugins/filterFactory.go
Outdated
@@ -145,6 +145,15 @@ func makeVolumeFilterConfig(configInput string) (*VolumeFilterConfig, error) { | |||
return nil, fmt.Errorf("invalid input (%s), the third part needs to be \"base\" or \"quote\"", configInput) | |||
} | |||
|
|||
// marketIDs and account IDs might not be present in the config string, but cannot be nil on the config | |||
if config.additionalMarketIDs == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to take a step back when looking at this PR. nil
is a valid value for both arrays, lets not change the API.
Can you please do the following?
- In
makeFilterVolume
, add a comment above the line where we callutils.Dedupe
to say thatappend(s, nil. . .)
is valid. - In
makeSQLQueryDailyVolume
above where we check the length of optionalAccountIDs, add a comment that says that len(a) where a is a nil array is valid and returns 0 - In the struct definition of VolumeFilterConfig, add a comment next to the two arrays saying that these can be nil
- In
TestDailyVolumeByDate_QueryRow
copy the first test case and replacequeryByOptionalAccountIDs: []string{}
withqueryByOptionalAccountIDs:nil,
leaving everything else the same. - Remove all changes in this PR related to converting
nil
to an empty array and remove the check from validation.
If the above does not work for some reason, please let me know.
plugins/volumeFilter.go
Outdated
return fmt.Errorf("could not parse action: %s", e) | ||
} | ||
|
||
if c.additionalMarketIDs == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove these nil
errors. I think this is what is causing all the issues. these are not required since nil
is a valid value for both arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, this makes sense and completely resolves the issue.
So just making sure we're on the same page: when validating the config, no check would be applied to market IDs or to action IDs? The only check we had discussed was non-nil. If that's now fine, I don't think another one would make sense. But let me know if we should check any values or anything like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks great, thank you @debnil ! 🎉
This PR adds additional validation for the volume filter config; calls that validation within the volume filter constructor; and adds necessary tests for that validation. It also edits other tests of the volume config that now fail because of validation. This closes #571.