From: Michael Orlitzky Date: Mon, 17 Apr 2017 01:56:51 +0000 (-0400) Subject: Add a new "normalize" function to the Cidr module. X-Git-Tag: 0.4.0~13 X-Git-Url: https://gitweb.michael.orlitzky.com/?a=commitdiff_plain;h=278b96d51a495b912243efa3a83407d3f830d83f;p=hath.git Add a new "normalize" function to the Cidr module. 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. --- diff --git a/src/Cidr.hs b/src/Cidr.hs index 5a5ba3f..8991c7f 100644 --- a/src/Cidr.hs +++ b/src/Cidr.hs @@ -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))