Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(test): assertApproxEq, assertNotEq, assertFalse #38

Merged
merged 19 commits into from
Apr 22, 2022

Conversation

OliverNChalk
Copy link
Contributor

Brief

This PR adds the following assertions:

  • assertApproxEq(a, b, reason?) [uint256, int256]
  • assertNotEq(a, b, reason?) [address, bytes, int, uint, string]
  • assertFalse(a, reason?) [bool]

Deliverables

Unsure if this is of interest at this level or should be pitched to ds-test. It however seems that ds-test is not being actively extended at the moment, hence the PR here. We use a forked version of forge-std and find these asserts useful but understand if this is out of scope/not going to be merged.

Would be good to get a decision/some discussion on where most appropriate to extend the current set of assertions which have some gaps imo.

@ultrasecreth
Copy link

For what is worth, was going to propose/add similar stuff :)

@brockelmore
Copy link
Member

@transmissions11 curious your thoughts here, I know you were going to maybe do a clean-room rewrite of some existing contracts into forge-std

@brockelmore
Copy link
Member

brockelmore commented Apr 19, 2022

Can you just yonk the various methods you want from here? Have permission from t11 to do so. Have received feedback from people that those methods are generally better implementations

@OliverNChalk
Copy link
Contributor Author

OliverNChalk commented Apr 20, 2022

Chucked a few more commits on this, largely driven by the suggestion to use @transmissions11's impls. To summarize, the following should be resolved:

  • assertApproxEq implementation from t11s
  • assertRelApproxEq implementation from t11s
  • assertEq(bool, bool) implementation from t11s (note name is diff)
  • assertEq(bytes, bytes) implementation from t11s (note name is diff)

Areas to cover/discuss:

  • Naming of assertEq variants (solmate impl has things like assertBoolEq, where I've tried to align with ds-test's assertEq argument overloading approach)
  • Maintaining error message support (i did this to align with ds-test but I personally rarely use it and would be happy without)
  • Scope (i have not picked up things like gas metering, fail(), bound) to keep the scope of PR just to enhancing assets)
  • Log alignment style, mainly did this to sanity check spacing but unsure if this is wanted in here

Copy link
Collaborator

@mds1 mds1 left a comment

Choose a reason for hiding this comment

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

Thanks a lot @OliverNChalk!! Looking forward to having these in forge-std

Naming of assertEq variants (solmate impl has things like assertBoolEq, where I've tried to align with ds-test's assertEq argument overloading approach)

Agree with naming the overloads assertEq instead of solmate's assertBoolEq

Maintaining error message support (i did this to align with ds-test but I personally rarely use it and would be happy without)

Supporting error messages for consistency seems like the right approach, though I also rarely use them

Scope (i have not picked up things like gas metering, fail(), bound) to keep the scope of PR just to enhancing assets)

bound is a very popular solmate helper for fuzz tests that is recommended in the docs, so that one is definitely worth upstreaming here. Gas metering and others are more questionable so we can leave them out for now / discuss in a separate issue if people want to consider them

Log alignment style, mainly did this to sanity check spacing but unsure if this is wanted in here

Sorry can you clarify what you mean here?

src/Test.sol Outdated Show resolved Hide resolved
src/Test.sol Outdated Show resolved Hide resolved
src/Test.sol Outdated Show resolved Hide resolved
src/Test.sol Outdated

/*//////////////////////////////////////////////////////////////////////////
REL APPROX EQUAL
//////////////////////////////////////////////////////////////////////////*/
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit, but really just need one section header for all the assertions to differentiate them from the other helper methods. Maybe just called "Assertions"

Copy link
Contributor Author

@OliverNChalk OliverNChalk Apr 21, 2022

Choose a reason for hiding this comment

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

Happy to collapse into ASSERTIONS section, only hesitation would be if we wanted to properly overload assertApproxEqRel and assertApproxEqAbs. Then we might want to group these guys in their own region, separate to the assertEq region.

For now if we don't plan to fully do all the overloads in this PR, happy to just collapse to one collection and move on

Copy link
Collaborator

Choose a reason for hiding this comment

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

only hesitation would be if we wanted to properly overload assertApproxEqRel and assertApproxEqAbs

By "properly overload" do you mean with types other than int256/uint256? If so, I think just supporting int256/uint256 would cover most cases and is sufficient.

Either way, both a single Assertions section or two sections (one for assertEqs, one for approx equals) is good with me. I don't feel strongly about this, but see the thumbs up from @ZeroEkkusu so will leave it up to you both 😛

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It ends up being 4 sections if you group overloaded functions together. This may be excessive and the argument for would be if we expect more overloads to come down the track - then this makes it blindingly obvious where to put them and whether they comply with existing style/format.

Will defer to @ZeroEkkusu to act as tie breaker and move this forward. For reference here is the commit where I group overloaded assertions together: 924456a

Copy link
Collaborator

Choose a reason for hiding this comment

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

The idea I had was to use the big headers to divide the main parts of the contract:
"STD-CHEATS", "STD-ASSERTIONS", "STD-ERRORS", "STD-STORAGE".

I like the order as is, assertEq --> assertApproxEqAbs... It's logical IMO. Just put assertFalse first. I don't think we need any dividers rn; we can always add them later, as that'd be a non-breaking change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, summary of changes:

  • Collapse assertion code regions into one: 99a36d8
  • Re-order assertFalse: 3c15901
  • Add STD-CHEATS code region: 113b11c

Changes not done:

  • Did not add STD-ERRORS or STD-STORAGE as these are standalone libraries, not regions within contract Test

src/Test.sol Outdated Show resolved Hide resolved
@OliverNChalk
Copy link
Contributor Author

Log alignment style, mainly did this to sanity check spacing but unsure if this is wanted in here

Sorry can you clarify what you mean here?

To help ensure the error messaging comes out aligned on the console, the following indentation style is used:

image

This is somewhat not standard as the ( is aligned on indentation multiples (4 spaces), so wanted to call it out in case people didn't want it in

@mds1
Copy link
Collaborator

mds1 commented Apr 21, 2022

To help ensure the error messaging comes out aligned on the console, the following indentation style is used:

This is somewhat not standard as the ( is aligned on indentation multiples (4 spaces), so wanted to call it out in case people didn't want it in

Ah I see, this is fine with me, will leave it to anyone else to raise objections! 😅

Copy link
Collaborator

@mds1 mds1 left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @OliverNChalk! If you want to add solmate's bound in this PR feel free, otherwise I can PR that in later.

Otherwise @ZeroEkkusu feel free to merge whenever the last open comment is resolved

@ZeroEkkusu
Copy link
Collaborator

If you include bound in this PR, add it as a std-cheat below deployCode. ^^

@OliverNChalk
Copy link
Contributor Author

If you include bound in this PR, add it as a std-cheat below deployCode. ^^

Have opted to leave this out as it feels most appropriate in a separate PR. I'll throw that up post merge if no one beats me to the punchb

Copy link
Collaborator

@ZeroEkkusu ZeroEkkusu left a comment

Choose a reason for hiding this comment

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

Added a few comments. Otherwise, looks good!

emit log_named_decimal_int (" % Delta", percentDelta, 18);
fail();
}
}
}


Copy link
Collaborator

Choose a reason for hiding this comment

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

We should add a header here before stdError "STD-ERRORS" to separate them from the assertions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done, can resolve if happy

@@ -159,7 +359,7 @@ library stdError {
struct StdStorage {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here "STD-STORAGE"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done, can resolve if happy

Copy link
Collaborator

@ZeroEkkusu ZeroEkkusu left a comment

Choose a reason for hiding this comment

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

Lgtm, thanks!

@ZeroEkkusu ZeroEkkusu merged commit 6329843 into foundry-rs:master Apr 22, 2022
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.

5 participants