dahdit-test-0.7.0: src/Test/Dahdit/GenDefault.hs
{-# LANGUAGE UndecidableInstances #-}
module Test.Dahdit.GenDefault
( genSigned
, genUnsigned
, genFractional
, genEnum
, genSum
, genList
, genSeq
, genString
, genSBS
, genText
, LengthBounds (..)
, DahditTag
)
where
import Dahdit
( BoolByte (..)
, DoubleBE (..)
, DoubleLE (..)
, ExactBytes (..)
, FloatBE (..)
, FloatLE (..)
, Int16BE (..)
, Int16LE (..)
, Int32BE (..)
, Int32LE (..)
, Int64BE (..)
, Int64LE (..)
, StaticBytes (..)
, StaticSeq (..)
, TermBytes16 (..)
, TermBytes8 (..)
, Word16BE (..)
, Word16LE (..)
, Word32BE (..)
, Word32LE (..)
, Word64BE (..)
, Word64LE (..)
)
import Data.ByteString.Internal (w2c)
import Data.ByteString.Short (ShortByteString)
import Data.ByteString.Short qualified as BSS
import Data.Int (Int16, Int32, Int64, Int8)
import Data.IntMap (IntMap)
import Data.IntMap qualified as IntMap
import Data.IntSet (IntSet)
import Data.IntSet qualified as IntSet
import Data.List.NonEmpty (NonEmpty (..))
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Proxy (Proxy (..))
import Data.Ratio ((%))
import Data.Sequence (Seq)
import Data.Sequence qualified as Seq
import Data.Set (Set)
import Data.Set qualified as Set
import Data.Text (Text)
import Data.Text qualified as T
import Data.Word (Word16, Word32, Word64, Word8)
import GHC.TypeLits (KnownNat, natVal)
import PropUnit (Gen, GenDefault (..), genDefaultGeneric)
import PropUnit.Hedgehog.Gen qualified as Gen
import PropUnit.Hedgehog.Range qualified as Range
genPrintableChar :: Gen Char
genPrintableChar = fmap w2c (Gen.integral (Range.constant 32 126))
genSigned :: (Integral a, Bounded a) => Gen a
genSigned = Gen.integral (Range.constantFrom 0 minBound maxBound)
genUnsigned :: (Integral a, Bounded a) => Gen a
genUnsigned = Gen.integral (Range.constant 0 maxBound)
genFractional :: (Fractional a) => Gen a
genFractional = do
-- Picked so bound**2 fits in int
let bound = 3037000499 :: Int
n <- Gen.integral (Range.constant 0 bound)
b <- Gen.integral (Range.constant 1 bound)
a <- Gen.integral (Range.constantFrom 0 ((-n) * b) (n * b))
return (fromRational (fromIntegral a % fromIntegral b))
genEnum :: (Enum a, Bounded a) => Gen a
genEnum = Gen.enumBounded
genSum :: NonEmpty (Gen a) -> Gen a
genSum (g :| gs) = Gen.choice (g : gs)
genList :: Word -> Word -> Gen a -> Gen [a]
genList mn mx = Gen.list (Range.constant (fromIntegral mn) (fromIntegral mx))
genSeq :: Word -> Word -> Gen a -> Gen (Seq a)
genSeq mn mx = fmap Seq.fromList . genList mn mx
genString :: Word -> Word -> Gen String
genString mn mx = genList mn mx genPrintableChar
genSBS :: Word -> Word -> Gen ShortByteString
genSBS mn mx = fmap BSS.pack (genList mn mx genUnsigned)
genText :: Word -> Word -> Gen Text
genText mn mx = fmap T.pack (genString mn mx)
newtype ViaSigned a = ViaSigned {unViaSigned :: a}
instance (Integral a, Bounded a) => GenDefault p (ViaSigned a) where
genDefault _ = fmap ViaSigned genSigned
newtype ViaUnsigned a = ViaUnsigned {unViaUnsigned :: a}
instance (Integral a, Bounded a) => GenDefault p (ViaUnsigned a) where
genDefault _ = fmap ViaUnsigned genUnsigned
newtype ViaFractional a = ViaFractional {unViaFractional :: a}
instance (Fractional a) => GenDefault p (ViaFractional a) where
genDefault _ = fmap ViaFractional genFractional
class LengthBounds p a where
lengthBounds :: Proxy p -> Proxy a -> (Word, Word)
proxyForRange :: (x -> b) -> Proxy b
proxyForRange _ = Proxy
genListLike :: (LengthBounds p b, GenDefault p a) => ([a] -> b) -> Proxy p -> Gen b
genListLike f p =
let (mn, mx) = lengthBounds p (proxyForRange f)
in fmap f (genList mn mx (genDefault p))
data DahditTag p
type D = DahditTag
instance GenDefault (D p) Word8 where
genDefault _ = genUnsigned
instance GenDefault (D p) Int8 where
genDefault _ = genSigned
instance GenDefault (D p) Word16 where
genDefault _ = genUnsigned
instance GenDefault (D p) Int16 where
genDefault _ = genSigned
instance GenDefault (D p) Word32 where
genDefault _ = genUnsigned
instance GenDefault (D p) Int32 where
genDefault _ = genSigned
instance GenDefault (D p) Word64 where
genDefault _ = genUnsigned
instance GenDefault (D p) Int64 where
genDefault _ = genSigned
instance GenDefault (D p) Float where
genDefault _ = genFractional
instance GenDefault (D p) Double where
genDefault _ = genFractional
instance GenDefault (D p) Int where
genDefault _ = genSigned
instance GenDefault (D p) Word16LE where
genDefault = fmap Word16LE . genDefault
instance GenDefault (D p) Int16LE where
genDefault = fmap Int16LE . genDefault
instance GenDefault (D p) Word32LE where
genDefault = fmap Word32LE . genDefault
instance GenDefault (D p) Int32LE where
genDefault = fmap Int32LE . genDefault
instance GenDefault (D p) Word64LE where
genDefault = fmap Word64LE . genDefault
instance GenDefault (D p) Int64LE where
genDefault = fmap Int64LE . genDefault
instance GenDefault (D p) FloatLE where
genDefault = fmap FloatLE . genDefault
instance GenDefault (D p) DoubleLE where
genDefault = fmap DoubleLE . genDefault
instance GenDefault (D p) Word16BE where
genDefault = fmap Word16BE . genDefault
instance GenDefault (D p) Int16BE where
genDefault = fmap Int16BE . genDefault
instance GenDefault (D p) Word32BE where
genDefault = fmap Word32BE . genDefault
instance GenDefault (D p) Int32BE where
genDefault = fmap Int32BE . genDefault
instance GenDefault (D p) Word64BE where
genDefault = fmap Word64BE . genDefault
instance GenDefault (D p) Int64BE where
genDefault = fmap Int64BE . genDefault
instance GenDefault (D p) FloatBE where
genDefault = fmap FloatBE . genDefault
instance GenDefault (D p) DoubleBE where
genDefault = fmap DoubleBE . genDefault
instance GenDefault (D p) Char where
genDefault = fmap w2c . genDefault
instance GenDefault (D p) () where
genDefault = genDefaultGeneric
instance GenDefault (D p) Bool where
genDefault = genDefaultGeneric
instance (GenDefault (D p) a) => GenDefault (D p) (Maybe a) where
genDefault = genDefaultGeneric
instance (GenDefault (D p) a, GenDefault (D p) b) => GenDefault (D p) (Either a b) where
genDefault = genDefaultGeneric
instance (GenDefault (D p) a, GenDefault (D p) b) => GenDefault (D p) (a, b) where
genDefault = genDefaultGeneric
instance (GenDefault (D p) a, GenDefault (D p) b, GenDefault (D p) c) => GenDefault (D p) (a, b, c) where
genDefault = genDefaultGeneric
instance (GenDefault (D p) a, GenDefault (D p) b, GenDefault (D p) c, GenDefault (D p) d) => GenDefault (D p) (a, b, c, d) where
genDefault = genDefaultGeneric
instance
(GenDefault (D p) a, GenDefault (D p) b, GenDefault (D p) c, GenDefault (D p) d, GenDefault (D p) e)
=> GenDefault (D p) (a, b, c, d, e)
where
genDefault = genDefaultGeneric
instance (LengthBounds (D p) [a], GenDefault (D p) a) => GenDefault (D p) [a] where
genDefault = genListLike id
instance (LengthBounds (D p) (Seq a), GenDefault (D p) a) => GenDefault (D p) (Seq a) where
genDefault = genListLike Seq.fromList
instance (LengthBounds (D p) (Map a b), GenDefault (D p) a, GenDefault (D p) b, Ord a) => GenDefault (D p) (Map a b) where
genDefault = genListLike Map.fromList
instance (LengthBounds (D p) (Set a), GenDefault (D p) a, Ord a) => GenDefault (D p) (Set a) where
genDefault = genListLike Set.fromList
instance (LengthBounds (D p) IntSet) => GenDefault (D p) IntSet where
genDefault = genListLike IntSet.fromList
instance (LengthBounds (D p) (IntMap a), GenDefault (D p) a) => GenDefault (D p) (IntMap a) where
genDefault = genListLike IntMap.fromList
instance (LengthBounds (D p) TermBytes8) => GenDefault (D p) TermBytes8 where
genDefault = genListLike (TermBytes8 . BSS.pack)
instance (LengthBounds (D p) TermBytes16) => GenDefault (D p) TermBytes16 where
genDefault = genListLike (TermBytes16 . BSS.pack)
instance (KnownNat n) => GenDefault (D p) (StaticBytes n) where
genDefault _ =
let mn = fromInteger (natVal (Proxy @n))
in fmap (StaticBytes . BSS.pack) (genList mn mn (genDefault @(D p) Proxy))
instance (KnownNat n, GenDefault (D p) a) => GenDefault (D p) (StaticSeq n a) where
genDefault _ =
let mn = fromInteger (natVal (Proxy @n))
in fmap (StaticSeq . Seq.fromList) (genList mn mn (genDefault @(D p) Proxy))
instance GenDefault (D p) BoolByte where
genDefault = fmap BoolByte . genDefault
instance GenDefault (D p) (ExactBytes n s) where
genDefault _ = pure (ExactBytes ())