From 278b96d51a495b912243efa3a83407d3f830d83f Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 16 Apr 2017 21:56:51 -0400 Subject: [PATCH] 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. --- src/Cidr.hs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) 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)) -- 2.43.2