{-# OPTIONS_GHC -fno-warn-orphans -fno-warn-name-shadowing #-}
module Test.Data.Radius.ArbitrariesBase (
genPacket,
genSizedString,
genAtText, genAtString,
) where
import Test.QuickCheck (Arbitrary (..), Gen, elements, choose)
import Control.Applicative ((<$>), pure, (<*>))
import Control.Monad (replicateM)
import Data.String (IsString, fromString)
import qualified Data.ByteString as BS
import Data.Word (Word16)
import Data.Serialize.Put (Put, runPut)
import Data.Radius.Scalar
(Bin128, word64Bin128, AtText (..), AtString (..), AtInteger (..), AtIpV4 (..))
import Data.Radius.Packet (codeFromWord, Code, Header(..), Packet (..))
import qualified Data.Radius.Attribute as Attribute
import qualified Data.Radius.StreamPut as Put
instance Arbitrary Code where
arbitrary = codeFromWord <$> arbitrary
instance Arbitrary Bin128 where
arbitrary = word64Bin128 <$> arbitrary <*> arbitrary
instance Arbitrary Attribute.Number where
arbitrary =
elements
[ c
| w <- [0 .. 255]
, let c = Attribute.fromWord w
, c /= Attribute.VendorSpecific
]
genSizedList :: Arbitrary a => Int -> Gen [a]
genSizedList n =
elements [0..n] >>= (`replicateM` arbitrary)
genSizedString :: IsString a => Int -> Gen a
genSizedString n = fromString <$> genSizedList n
genAtText :: Int -> Gen AtText
genAtText n = AtText <$> genSizedString (n `quot` 4)
instance Arbitrary AtText where
arbitrary = genAtText (255 - 1 - 1)
genAtString :: Int -> Gen AtString
genAtString n = AtString <$> genSizedString n
instance Arbitrary AtString where
arbitrary = genAtString (255 - 1 - 1)
instance Arbitrary AtInteger where
arbitrary = AtInteger <$> arbitrary
instance Arbitrary AtIpV4 where
arbitrary = AtIpV4 <$> arbitrary
genHeader :: Word16 -> Gen Header
genHeader len =
Header <$> arbitrary <*> arbitrary <*> pure len <*> arbitrary
instance Arbitrary Header where
arbitrary = genHeader =<< arbitrary
pseudoHeader :: Header
pseudoHeader = Header (codeFromWord 0) 0 0 (word64Bin128 0 0)
genCountedPacket :: Arbitrary a
=> Int
-> (a -> Put)
-> Gen (Packet [a], Int)
genCountedPacket ac encodeA = do
attrs <- replicateM ac arbitrary
let len = BS.length . runPut . Put.packet (mapM_ encodeA) $ Packet pseudoHeader attrs
(,) <$> (Packet <$> (genHeader $ fromIntegral len) <*> pure attrs) <*> pure len
genPacket :: Arbitrary a
=> (a -> Put)
-> Gen (Packet [a])
genPacket encodeA = do
ac <- choose (0, 31)
(p, len) <- genCountedPacket ac encodeA
if len <= 4096
then pure p
else do
ac <- choose (0, 15)
(p, len) <- genCountedPacket ac encodeA
if len <= 4096
then pure p
else error "genPacket: this should not happen broken size property (header-size + 256 * 15 < 4096)."