]> gitweb.michael.orlitzky.com - hath.git/blobdiff - src/Cidr.hs
Add a new "normalize" function to the Cidr module.
[hath.git] / 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))