]> gitweb.michael.orlitzky.com - hath.git/commitdiff
src/IPv4Address.hs: fix the inverse toEnum/fromEnum property on x86.
authorMichael Orlitzky <michael@orlitzky.com>
Mon, 4 Mar 2019 02:26:31 +0000 (21:26 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Mon, 4 Mar 2019 02:26:31 +0000 (21:26 -0500)
The second half of the fix in the previous commit turned out to be in
the test itself. The "smallness test" that I was using was to compare
against the number (2^32 - 1), which works great if said number is
interpreted as a 64-bit integer. However on x86 systems, it's a 32-bit
integer, namely negative one! Oops.

This commit splits that test into two; one that tests randomly-generated
Int32s, and one that tests randomly-generated Int64s. Hopefully this
ensures that no similar problems with the machine Int type creep in.

src/IPv4Address.hs

index 85d86616023b19f3cc936ac2f69f1b65020df880..4399b05f3ecb1728eca31be6eae5e833a23a3b5b 100644 (file)
@@ -5,14 +5,17 @@ module IPv4Address(
   most_sig_bit_different )
 where
 
-import Data.Word (Word32)
+import Data.Int ( Int32, Int64 )
+import Data.Word ( Word32 )
 
 import Test.Tasty ( TestTree, testGroup )
 import Test.Tasty.HUnit ( (@?=), testCase )
 import Test.Tasty.QuickCheck (
   Arbitrary( arbitrary ),
   Gen,
+  Large,
   Property,
+  Small,
   (==>),
   testProperty )
 
@@ -360,17 +363,42 @@ ipv4address_properties :: TestTree
 ipv4address_properties =
   testGroup
     "IPv4 Address Properties "
-    [ prop_from_enum_to_enum_inverses ]
+    [ prop_from_enum_to_enum_inverses_x32,
+      prop_from_enum_to_enum_inverses_x64 ]
 
 -- QuickCheck properties
-prop_from_enum_to_enum_inverses :: TestTree
-prop_from_enum_to_enum_inverses =
-  testProperty "fromEnum and toEnum are inverses" prop
+--
+-- We have two different tests to show that toEnum and fromEnum are
+-- inverses of one another. This part of the code isn't really
+-- type-safe, because the stupid Enum class insists that we use a
+-- machine 'Int' for our representation. Since IPv4 addresses can
+-- correspond to very large 32-bit integers, there's a possibility
+-- that our math is wrong in 32- but not 64-bits, and vice-versa.
+--
+-- tl;dr we want to ensure that this test passes when the 'Int' type
+-- is both 32-bit and 64-bit.
+
+-- Generate "Small" 64-bit numbers, because almost all 64-bit integers are
+-- too large to satisfy our predicate (i.e. also be 32-bit integers).
+prop_from_enum_to_enum_inverses_x64 :: TestTree
+prop_from_enum_to_enum_inverses_x64 =
+  testProperty "fromEnum and toEnum are inverses (x64)" prop
   where
-    prop :: Int -> Property
+    prop :: (Small Int64) -> Property
     prop x =
-      (0 <= x) && (x <= 2^(32 :: Integer) - 1) ==>
-        fromEnum (toEnum x :: IPv4Address) == x
+      0 <= x && x <= 2^(32 :: Integer) - 1 ==>
+        fromIntegral (fromEnum (toEnum (fromIntegral x) :: IPv4Address)) == x
+
+-- According to the QuickCheck documentation, we need the "Large"
+-- modifier to ensure that the test cases are drawn from the entire
+-- range of Int32 values.
+prop_from_enum_to_enum_inverses_x32 :: TestTree
+prop_from_enum_to_enum_inverses_x32 =
+  testProperty "fromEnum and toEnum are inverses (x32)" prop
+  where
+    prop :: (Large Int32) -> Bool
+    prop x =
+      fromIntegral (fromEnum (toEnum (fromIntegral x) :: IPv4Address)) == x
 
 -- HUnit Tests
 mk_testaddr :: Int -> Int -> Int -> Int -> IPv4Address