]> gitweb.michael.orlitzky.com - hath.git/commitdiff
Add a new "normalize" function to the Cidr module.
authorMichael Orlitzky <michael@orlitzky.com>
Mon, 17 Apr 2017 01:56:51 +0000 (21:56 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Mon, 17 Apr 2017 01:56:51 +0000 (21:56 -0400)
There are several different ways to represent the same Cidr, as their
Eq instance shows. The canonical way to represent a given CIDR is with
its host bits zeroed out; for example, "127.0.0.0/8" instead of
"127.0.0.1/8". This commit adds a normalization function to the Cidr
module.

It should be possible to use the new function to clean up the code
some, and to allow the user to specify normalized output for the
"reduced" mode.

src/Cidr.hs

index 5a5ba3f2f332cdb6548aa23621859a9bc6bca6f3..8991c7f29d19a4b1b2bb673cb901fbc6cfaa4b4e 100644 (file)
@@ -16,6 +16,7 @@ module Cidr
   min_octet2,
   min_octet3,
   min_octet4,
+  normalize
 ) where
 
 import Data.List (nubBy)
@@ -261,6 +262,14 @@ adjacent cidr1 cidr2
 enumerate :: Cidr -> [IPv4Address]
 enumerate cidr = [(min_host cidr)..(max_host cidr)]
 
+
+-- | Replace any masked bits in this CIDR's IPv4Address with zeros.
+normalize :: Cidr -> Cidr
+normalize (Cidr addr mask) =
+  Cidr nrml_addr mask
+  where
+    nrml_addr = apply_mask addr mask B.Zero
+
 -- Test lists.
 cidr_tests :: TestTree
 cidr_tests =
@@ -281,13 +290,17 @@ cidr_tests =
     test_combine_contained2,
     test_combine_all1,
     test_combine_all2,
-    test_combine_all3 ]
+    test_combine_all3,
+    test_normalize1,
+    test_normalize2,
+    test_normalize3 ]
 
 cidr_properties :: TestTree
 cidr_properties =
   testGroup "CIDR Properties" [
       prop_all_cidrs_contain_themselves,
-      prop_contains_proper_antisymmetric ]
+      prop_contains_proper_antisymmetric,
+      prop_normalize_idempotent ]
 
 
 -- HUnit Tests
@@ -483,6 +496,31 @@ test_combine_all3 =
     expected = [read "10.0.0.16/30" :: Cidr]
     actual = combine_all test_cidrs
 
+test_normalize1 :: TestTree
+test_normalize1 =
+  testCase desc $ actual @?= expected
+  where
+    desc = "127.0.0.1/8 normalized is 127.0.0.0/8"
+    expected = read "127.0.0.0/8" :: Cidr
+    actual = normalize (read "127.0.0.1/8" :: Cidr)
+
+
+test_normalize2 :: TestTree
+test_normalize2 =
+  testCase desc $ actual @?= expected
+  where
+    desc = "192.168.1.101/24 normalized is 192.168.1.0/24"
+    expected = read "192.168.1.0/24" :: Cidr
+    actual = normalize (read "192.168.1.101/24" :: Cidr)
+
+test_normalize3 :: TestTree
+test_normalize3 =
+  testCase desc $ actual @?= expected
+  where
+    desc = "10.10.10.10/22 normalized is 10.10.8.0/22"
+    expected = read "10.10.8.0/22" :: Cidr
+    actual = normalize (read "10.10.10.10/22" :: Cidr)
+
 -- QuickCheck Tests
 prop_all_cidrs_contain_themselves :: TestTree
 prop_all_cidrs_contain_themselves =
@@ -502,3 +540,12 @@ prop_contains_proper_antisymmetric =
     prop cidr1 cidr2 =
       (cidr1 `contains_proper` cidr2) ==>
         (not (cidr2 `contains_proper` cidr1))
+
+
+-- Running "normalize" a second time shouldn't do anything.
+prop_normalize_idempotent :: TestTree
+prop_normalize_idempotent =
+  testProperty "The CIDR \"normalize\" function is idempotent " prop
+  where
+    prop :: Cidr -> Bool
+    prop cidr = (normalize cidr) == (normalize (normalize cidr))