{-# OPTIONS -fno-warn-orphans #-} import Test.QuickCheck (Gen, Arbitrary (..), choose, oneof) import Test.QuickCheck.Simple (defaultMain, Test, qcTest) import Control.Applicative ((<$>), (<*>)) import Control.Monad (replicateM) import Data.Maybe (fromJust) import Data.List (isPrefixOf, isSuffixOf) import Data.Word (Word8, Word16) import Data.PostgreSQL.NetworkAddress import Database.PostgreSQL.Parser (Parser, evalParser) import qualified Database.PostgreSQL.Parser as Parser import Database.PostgreSQL.Printer (Printer, execPrinter) import qualified Database.PostgreSQL.Printer as Printer instance Arbitrary V4HostAddress where arbitrary = V4HostAddress <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary instance Arbitrary V6HostAddress where arbitrary = V6HostAddress <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary mask4 :: Gen Word8 mask4 = choose (0, 32) mask6 :: Gen Word8 mask6 = choose (0, 128) newtype A6Input = A6Input [Word16] deriving (Eq, Show) instance Arbitrary A6Input where arbitrary= A6Input <$> (choose (0, 8) >>= (`replicateM` arbitrary)) instance Arbitrary NetAddress where arbitrary = oneof [ NetAddress4 <$> arbitrary <*> mask4 , NetAddress6 <$> arbitrary <*> mask6 ] instance Arbitrary Cidr where arbitrary = oneof [ fromJust <$> (cidr4' <$> arbitrary <*> mask4) , fromJust <$> (cidr6' <$> arbitrary <*> mask6) ] isoProp :: Eq a => Printer a -> Parser a -> a -> Bool isoProp pr ps a = Right a == (evalParser ps $ execPrinter pr a) prop_v4HostAddressIso :: V4HostAddress -> Bool prop_v4HostAddressIso = isoProp Printer.v4HostAddress Parser.v4HostAddress prop_v6HostAddressIso :: V6HostAddress -> Bool prop_v6HostAddressIso = isoProp Printer.v6HostAddress Parser.v6HostAddress prop_v6HostAddressDcIsoL :: V6HostAddress -> Bool prop_v6HostAddressDcIsoL a6 = v6HostAddress [w0, w1, w2, w3, w4, w5, w6, w7] [] == Just a6 where (w0, w1, w2, w3, w4, w5, w6, w7) = v6HostAddressWords a6 prop_v6HostAddressDcIsoR :: V6HostAddress -> Bool prop_v6HostAddressDcIsoR a6 = v6HostAddress [] [w0, w1, w2, w3, w4, w5, w6, w7] == Just a6 where (w0, w1, w2, w3, w4, w5, w6, w7) = v6HostAddressWords a6 prop_v6HostAddressCons :: A6Input -> A6Input -> Bool prop_v6HostAddressCons (A6Input il) (A6Input ir) = case v6HostAddress il ir of Nothing -> length (il ++ ir) > 8 Just (V6HostAddress w0 w1 w2 w3 w4 w5 w6 w7) | let ws = [w0, w1, w2, w3, w4, w5, w6, w7] -> length (il ++ ir) <= 8 && il `isPrefixOf` ws && ir `isSuffixOf` ws prop_netAddressPpIso :: NetAddress -> Bool prop_netAddressPpIso = isoProp Printer.netAddress Parser.netAddress prop_netAddressDcIso :: NetAddress -> Bool prop_netAddressDcIso na = dc == Just na where dc = case na of NetAddress4 a4 m -> netAddress4 a4 m NetAddress6 a6 m -> netAddress6 a6 m prop_netAddress4Cons :: V4HostAddress -> Word8 -> Bool prop_netAddress4Cons a4 m = case netAddress4 a4 m of Nothing -> m > 32 Just (NetAddress4 a4' m') -> a4 == a4' && m == m' Just (NetAddress6 {}) -> False prop_netAddress6Cons :: V6HostAddress -> Word8 -> Bool prop_netAddress6Cons a6 m = case netAddress6 a6 m of Nothing -> m > 128 Just (NetAddress4 {}) -> False Just (NetAddress6 a6' m') -> a6 == a6' && m == m' prop_cidrDcIso :: Cidr -> Bool prop_cidrDcIso cidr@(Cidr na) = dc == Just cidr where dc = case na of NetAddress4 a4 m -> cidr4 a4 m NetAddress6 a6 m -> cidr6 a6 m prop_cidr4Cons :: V4HostAddress -> Word8 -> Bool prop_cidr4Cons a4 m = case cidr4 a4 m of Nothing -> m > 32 || case cidr4' a4 m of Nothing -> False Just (Cidr (NetAddress4 a4' m')) -> m' == m && a4' /= a4 Just (Cidr (NetAddress6 {})) -> False Just (Cidr (NetAddress4 a4' m')) -> m' == m && a4' == a4 Just (Cidr (NetAddress6 {})) -> False prop_cidr6Cons :: V6HostAddress -> Word8 -> Bool prop_cidr6Cons a6 m = case cidr6 a6 m of Nothing -> m > 128 || case cidr6' a6 m of Nothing -> False Just (Cidr (NetAddress4 {})) -> False Just (Cidr (NetAddress6 a6' m')) -> m' == m && a6' /= a6 Just (Cidr (NetAddress4 {})) -> False Just (Cidr (NetAddress6 a6' m')) -> m' == m && a6' == a6 tests :: [Test] tests = [ qcTest "v4 address iso - print parse" prop_v4HostAddressIso , qcTest "v6 address iso - print parse" prop_v6HostAddressIso , qcTest "v6 address iso - destruct construct-left" prop_v6HostAddressDcIsoL , qcTest "v6 address iso - destruct construct-right" prop_v6HostAddressDcIsoR , qcTest "v6 address construction" prop_v6HostAddressCons , qcTest "network address iso - print parse" prop_netAddressPpIso , qcTest "network address iso - destruct construct" prop_netAddressDcIso , qcTest "network address 4 construction" prop_netAddress4Cons , qcTest "network address 6 construction" prop_netAddress6Cons , qcTest "cidr iso - destruct construct" prop_cidrDcIso , qcTest "cidr-4 construction" prop_cidr4Cons , qcTest "cidr-6 construction" prop_cidr6Cons ] main :: IO () main = defaultMain tests