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

Proposed fix for issue #185 #186

Merged
merged 3 commits into from
Jul 8, 2019
Merged

Proposed fix for issue #185 #186

merged 3 commits into from
Jul 8, 2019

Conversation

marklam
Copy link
Contributor

@marklam marklam commented Jun 27, 2019

#185

The problem looks to be that the clamp on exponential ranges is performed after the conversion to the target type, so if the value falls just outside the range then an exception is thrown before the clamp occurs.

This moves the clamp to before the conversion, but maybe a better fix would be to sort out the calculation that's going out of bounds in the first place.

Copy link
Member

@moodmosaic moodmosaic left a comment

Choose a reason for hiding this comment

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

Thank you for looking at this ❤️ I think what's happening here is that we're hitting some off-by-one error. Here's the result of your test, without applying any other code change:

Starting test execution, please wait...
[xUnit.net 00:00:07.0504320]     Hedgehog.Tests.GenTests.can create exponentially bounded uint64 [FAIL]
  X Hedgehog.Tests.GenTests.can create exponentially bounded uint64 [1s 970ms]
  Error Message:
   System.OverflowException : Value was either too large or too small for a UInt64.
  Stack Trace:
     at System.Numerics.BigInteger.op_Explicit(BigInteger value)
   at <StartupCode$Hedgehog>[email protected](BigInteger x) in ..\fsharp-hedgehog\src\Hedgehog\Numeric.fs:line 205
   at Hedgehog.Tests.GenTests.can create exponentially bounded [email protected](Int32 sz) in ..\fsharp-hedgehog\tests\Hedgehog.Tests\GenTests.fs:line 90
   at Hedgehog.Range.Bounds[a](Int32 sz, Range`1 _arg1) in ..\fsharp-hedgehog\src\Hedgehog\Range.fs:line 42
   at [email protected](Seed seed, Int32 size) in ..\fsharp-hedgehog\src\Hedgehog\Gen.fs:line 473
   at Hedgehog.Random.unsafeRun[a](Seed seed, Int32 size, Random`1 _arg1) in ..\fsharp-hedgehog\src\Hedgehog\Random.fs:line 11
   at [email protected](Seed seed, Int32 size) in ..\fsharp-hedgehog\src\Hedgehog\Random.fs:line 40
   at Hedgehog.Random.unsafeRun[a](Seed seed, Int32 size, Random`1 _arg1) in ..\fsharp-hedgehog\src\Hedgehog\Random.fs:line 11
   at Hedgehog.Random.run[a](Seed seed, Int32 size, Random`1 r) in ..\fsharp-hedgehog\src\Hedgehog\Random.fs:line 14
   at [email protected](Seed seed, Random`1 random) in ..\fsharp-hedgehog\src\Hedgehog\Gen.fs:line 45
   at [email protected](Seed seed0, Int32 size) in ..\fsharp-hedgehog\src\Hedgehog\Gen.fs:line 47
   at Hedgehog.Random.unsafeRun[a](Seed seed, Int32 size, Random`1 _arg1) in ..\fsharp-hedgehog\src\Hedgehog\Random.fs:line 11
   at [email protected](Seed seed, Int32 size) in ..\fsharp-hedgehog\src\Hedgehog\Random.fs:line 18
   at Hedgehog.Random.unsafeRun[a](Seed seed, Int32 size, Random`1 _arg1) in ..\fsharp-hedgehog\src\Hedgehog\Random.fs:line 11
   at Hedgehog.Random.run[a](Seed seed, Int32 size, Random`1 r) in ..\fsharp-hedgehog\src\Hedgehog\Random.fs:line 14
   at [email protected](Seed seed, Int32 size, Int32 tests, Int32 discards) in ..\fsharp-hedgehog\src\Hedgehog\Property.fs:line 343
   at Hedgehog.Property.Report(Int32 n, Property`1 p) in ..\fsharp-hedgehog\src\Hedgehog\Property.fs:line 356
   at Hedgehog.Property.Report(Property`1 p) in ..\fsharp-hedgehog\src\Hedgehog\Property.fs:line 360
   at Hedgehog.Property.Check(Property`1 p) in ..\fsharp-hedgehog\src\Hedgehog\Property.fs:line 369
   at Hedgehog.Tests.GenTests.can create exponentially bounded uint64() in ..\fsharp-hedgehog\tests\Hedgehog.Tests\GenTests.fs:line 89
[xUnit.net 00:00:07.6352928]     Hedgehog.Tests.GenTests.can create exponentially bounded int64 [FAIL]

Notice this:

   at <StartupCode$Hedgehog>[email protected](BigInteger x) in ..\fsharp-hedgehog\src\Hedgehog\Numeric.fs:line 205

When the test fails, the input to that function is 18446744073709551616 which is exactly off-by-one the largest possible value of UInt64:

18446744073709551616 // Off-by-one
18446744073709551615 // UInt64.MaxValue

If that's the case (I'm 88% sure at this point), we shouldn't then need to re-arrange clamp and scale.

src/Hedgehog/Range.fs Outdated Show resolved Hide resolved
src/Hedgehog/Range.fs Outdated Show resolved Hide resolved
@@ -122,7 +122,7 @@ module Range =
fromBigInt (z + diff)

/// Scale an integral exponentially with the size parameter.
let inline scaleExponential (sz0 : Size) (z0 : 'a) (n0 : 'a) : 'a =
let inline scaleExponential (lo : 'a) (hi : 'a) (sz0 : Size) (z0 : 'a) (n0 : 'a) : 'a =
Copy link
Member

Choose a reason for hiding this comment

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

@jacobstanley, I don't like this change, but other alternatives I've tried make the F# compiler infer 'a as bigint and breaks everything. Since scaleExponential is internal I'll go ahead and merge this.

Right now exponential 64-bit un/signed integers can cause arithmetic overflows, and break upstream packages, so I'll go ahead and proceed with this fix.

@moodmosaic moodmosaic merged commit 07805fd into hedgehogqa:master Jul 8, 2019
@moodmosaic
Copy link
Member

Thank you for all the help @marklam and @cmeeren. A new release will be up on NuGet Gallery soon.

@moodmosaic
Copy link
Member

@marklam, do you have a Twitter account? Usually, when doing a new release, we announce it on Twitter and give credit to all contributors that helped get the release out.

@marklam
Copy link
Contributor Author

marklam commented Jul 9, 2019

Thanks @moodmosaic, I'm @_marklam_ on twitter.

@ghost ghost added this to the 0.8.3 milestone Sep 22, 2021
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.

2 participants