{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

module Test.Cardano.Binary.SizeBounds (
  tests,
)
where

import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Map as M
import Data.Proxy (Proxy (Proxy))
import Data.Tagged (Tagged (..))
import qualified Data.Text as T
import Data.Typeable (typeRep)
import Data.Word (Word32, Word8)

import Cardano.Binary

import Hedgehog (Gen, Group (..), checkParallel)
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range

import Data.Int (Int64)
import Test.Cardano.Binary.Helpers

tests :: IO Bool
tests :: IO Bool
tests =
  let
    listOf :: Gen a -> Gen [a]
    listOf :: forall a. Gen a -> Gen [a]
listOf = Range Int -> GenT Identity a -> GenT Identity [a]
forall (m :: * -> *) a. MonadGen m => Range Int -> m a -> m [a]
Gen.list (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
0 Int
300)
   in
    Group -> IO Bool
forall (m :: * -> *). MonadIO m => Group -> m Bool
checkParallel (Group -> IO Bool) -> Group -> IO Bool
forall a b. (a -> b) -> a -> b
$
      GroupName -> [(PropertyName, Property)] -> Group
Group
        GroupName
"Encoded size bounds for core types."
        [ (PropertyName
"()", SizeTestConfig () -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig () -> Property) -> SizeTestConfig () -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig ()
forall a. Show a => SizeTestConfig a
scfg {gen = pure (), precise = True})
        , (PropertyName
"Bool", SizeTestConfig Bool -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Bool -> Property)
-> SizeTestConfig Bool -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Bool
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.bool, precise = True})
        , (PropertyName
"Word", SizeTestConfig Word -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Word -> Property)
-> SizeTestConfig Word -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Word
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.word Range.exponentialBounded})
        , (PropertyName
"Word8", SizeTestConfig Word8 -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Word8 -> Property)
-> SizeTestConfig Word8 -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Word8
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.word8 Range.exponentialBounded})
        , (PropertyName
"Word16", SizeTestConfig Word16 -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Word16 -> Property)
-> SizeTestConfig Word16 -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Word16
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.word16 Range.exponentialBounded})
        , (PropertyName
"Word32", SizeTestConfig Word32 -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Word32 -> Property)
-> SizeTestConfig Word32 -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Word32
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.word32 Range.exponentialBounded})
        , (PropertyName
"Word64", SizeTestConfig Word64 -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Word64 -> Property)
-> SizeTestConfig Word64 -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Word64
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.word64 Range.exponentialBounded})
        , (PropertyName
"Int", SizeTestConfig Int -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Int -> Property) -> SizeTestConfig Int -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Int
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.int Range.exponentialBounded})
        ,
          ( PropertyName
"Int (precision)"
          , SizeTestConfig Int -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Int -> Property) -> SizeTestConfig Int -> Property
forall a b. (a -> b) -> a -> b
$
              SizeTestConfig Int
forall a. Buildable a => SizeTestConfig a
cfg
                { gen = Gen.int Range.exponentialBounded
                , computedCtx = \Int
x ->
                    [(TypeRep, SizeOverride)] -> Map TypeRep SizeOverride
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
                      [
                        ( Proxy Int -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @Int)
                        , Size -> SizeOverride
SizeConstant (Size -> SizeOverride) -> Size -> SizeOverride
forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral @Integer @Size (Integer -> Size) -> Integer -> Size
forall a b. (a -> b) -> a -> b
$ Int -> Integer
forall s a. (Integral s, Integral a) => s -> a
withWordSize Int
x
                        )
                      ]
                , precise = True
                }
          )
        ,
          ( PropertyName
"Float"
          , SizeTestConfig Float -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Float -> Property)
-> SizeTestConfig Float -> Property
forall a b. (a -> b) -> a -> b
$
              SizeTestConfig Float
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.float (Range.exponentialFloat (-1000000) 1000000)}
          )
        , (PropertyName
"Int32", SizeTestConfig Int32 -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Int32 -> Property)
-> SizeTestConfig Int32 -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Int32
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.int32 Range.exponentialBounded})
        , (PropertyName
"Int64", SizeTestConfig Int64 -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Int64 -> Property)
-> SizeTestConfig Int64 -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Int64
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.int64 Range.exponentialBounded})
        ,
          ( PropertyName
"Tagged () Word32"
          , SizeTestConfig (Tagged () Word32) -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig (Tagged () Word32) -> Property)
-> SizeTestConfig (Tagged () Word32) -> Property
forall a b. (a -> b) -> a -> b
$
              (forall a. Show a => SizeTestConfig a
scfg @(Tagged () Word32))
                { gen = Tagged <$> Gen.word32 Range.exponentialBounded
                }
          )
        ,
          ( PropertyName
"(Bool, Bool)"
          , SizeTestConfig (Bool, Bool) -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig (Bool, Bool) -> Property)
-> SizeTestConfig (Bool, Bool) -> Property
forall a b. (a -> b) -> a -> b
$
              SizeTestConfig (Bool, Bool)
forall a. Show a => SizeTestConfig a
scfg {gen = (,) <$> Gen.bool <*> Gen.bool, precise = True}
          )
        ,
          ( PropertyName
"(Bool, Bool, Bool)"
          , SizeTestConfig (Bool, Bool, Bool) -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig (Bool, Bool, Bool) -> Property)
-> SizeTestConfig (Bool, Bool, Bool) -> Property
forall a b. (a -> b) -> a -> b
$
              SizeTestConfig (Bool, Bool, Bool)
forall a. Show a => SizeTestConfig a
scfg
                { gen = (,,) <$> Gen.bool <*> Gen.bool <*> Gen.bool
                , precise = True
                }
          )
        ,
          ( PropertyName
"(Bool, Bool, Bool, Bool)"
          , SizeTestConfig (Bool, Bool, Bool, Bool) -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig (Bool, Bool, Bool, Bool) -> Property)
-> SizeTestConfig (Bool, Bool, Bool, Bool) -> Property
forall a b. (a -> b) -> a -> b
$
              SizeTestConfig (Bool, Bool, Bool, Bool)
forall a. Show a => SizeTestConfig a
scfg
                { gen = (,,,) <$> Gen.bool <*> Gen.bool <*> Gen.bool <*> Gen.bool
                , precise = True
                }
          )
        ,
          ( PropertyName
"ByteString"
          , SizeTestConfig ByteString -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig ByteString -> Property)
-> SizeTestConfig ByteString -> Property
forall a b. (a -> b) -> a -> b
$
              (forall a. Show a => SizeTestConfig a
scfg @BS.ByteString)
                { debug = show . (BS.unpack :: BS.ByteString -> [Word8])
                , gen = Gen.bytes (Range.linear 0 1000)
                , computedCtx = \ByteString
bs ->
                    [(TypeRep, SizeOverride)] -> Map TypeRep SizeOverride
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
                      [
                        ( Proxy (LengthOf ByteString) -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(LengthOf BS.ByteString))
                        , Size -> SizeOverride
SizeConstant (Size -> SizeOverride) -> Size -> SizeOverride
forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int @Size (Int -> Size) -> Int -> Size
forall a b. (a -> b) -> a -> b
$ ByteString -> Int
BS.length ByteString
bs
                        )
                      ]
                , precise = True
                }
          )
        ,
          ( PropertyName
"Lazy.ByteString"
          , SizeTestConfig ByteString -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig ByteString -> Property)
-> SizeTestConfig ByteString -> Property
forall a b. (a -> b) -> a -> b
$
              (forall a. Show a => SizeTestConfig a
scfg @LBS.ByteString)
                { debug = show . (LBS.unpack :: LBS.ByteString -> [Word8])
                , computedCtx = \ByteString
bs ->
                    [(TypeRep, SizeOverride)] -> Map TypeRep SizeOverride
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
                      [
                        ( Proxy (LengthOf ByteString) -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(LengthOf LBS.ByteString))
                        , Size -> SizeOverride
SizeConstant (Size -> SizeOverride) -> Size -> SizeOverride
forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int64 @Size (Int64 -> Size) -> Int64 -> Size
forall a b. (a -> b) -> a -> b
$ ByteString -> Int64
LBS.length ByteString
bs
                        )
                      ]
                , gen = LBS.fromStrict <$> Gen.bytes (Range.linear 0 1000)
                , precise = True
                }
          )
        ,
          ( PropertyName
"Text"
          , SizeTestConfig Text -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Text -> Property)
-> SizeTestConfig Text -> Property
forall a b. (a -> b) -> a -> b
$
              SizeTestConfig Text
forall a. Buildable a => SizeTestConfig a
cfg
                { gen = Gen.text (Range.linear 0 1000) Gen.latin1
                , computedCtx = \Text
bs ->
                    [(TypeRep, SizeOverride)] -> Map TypeRep SizeOverride
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
                      [
                        ( Proxy (LengthOf Text) -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(LengthOf T.Text))
                        , Size -> SizeOverride
SizeConstant (Size -> SizeOverride) -> Size -> SizeOverride
forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int @Size (Int -> Size) -> Int -> Size
forall a b. (a -> b) -> a -> b
$ Text -> Int
T.length Text
bs
                        )
                      ]
                }
          )
        ,
          ( PropertyName
"Text 2"
          , SizeTestConfig Text -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Text -> Property)
-> SizeTestConfig Text -> Property
forall a b. (a -> b) -> a -> b
$
              SizeTestConfig Text
forall a. Buildable a => SizeTestConfig a
cfg
                { gen = Gen.text (Range.linear 0 1000) Gen.unicode
                , computedCtx = \Text
bs ->
                    [(TypeRep, SizeOverride)] -> Map TypeRep SizeOverride
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
                      [
                        ( Proxy (LengthOf Text) -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(LengthOf T.Text))
                        , Size -> SizeOverride
SizeConstant (Size -> SizeOverride) -> Size -> SizeOverride
forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int @Size (Int -> Size) -> Int -> Size
forall a b. (a -> b) -> a -> b
$ Text -> Int
T.length Text
bs
                        )
                      ]
                }
          )
        ,
          ( PropertyName
"[Bool]"
          , SizeTestConfig [Bool] -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig [Bool] -> Property)
-> SizeTestConfig [Bool] -> Property
forall a b. (a -> b) -> a -> b
$
              SizeTestConfig [Bool]
forall a. Show a => SizeTestConfig a
scfg
                { gen = listOf Gen.bool
                , computedCtx = \[Bool]
bs ->
                    [(TypeRep, SizeOverride)] -> Map TypeRep SizeOverride
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
                      [
                        ( Proxy (LengthOf [Bool]) -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(LengthOf [Bool]))
                        , Size -> SizeOverride
SizeConstant (Size -> SizeOverride) -> Size -> SizeOverride
forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int @Size (Int -> Size) -> Int -> Size
forall a b. (a -> b) -> a -> b
$ [Bool] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Bool]
bs
                        )
                      ]
                , precise = True
                }
          )
        ,
          ( PropertyName
"NonEmpty Bool"
          , SizeTestConfig [Bool] -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig [Bool] -> Property)
-> SizeTestConfig [Bool] -> Property
forall a b. (a -> b) -> a -> b
$
              SizeTestConfig [Bool]
forall a. Show a => SizeTestConfig a
scfg
                { gen = listOf Gen.bool
                , computedCtx = \[Bool]
bs ->
                    [(TypeRep, SizeOverride)] -> Map TypeRep SizeOverride
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
                      [
                        ( Proxy (LengthOf [Bool]) -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(LengthOf [Bool]))
                        , Size -> SizeOverride
SizeConstant (Size -> SizeOverride) -> Size -> SizeOverride
forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral @Int @Size (Int -> Size) -> Int -> Size
forall a b. (a -> b) -> a -> b
$ [Bool] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Bool]
bs
                        )
                      ]
                , precise = True
                }
          )
        ,
          ( PropertyName
"Either Bool Bool"
          , SizeTestConfig (Either Bool Bool) -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig (Either Bool Bool) -> Property)
-> SizeTestConfig (Either Bool Bool) -> Property
forall a b. (a -> b) -> a -> b
$
              (forall a. Show a => SizeTestConfig a
scfg @(Either Bool Bool))
                { gen = Left <$> Gen.bool
                , precise = True
                }
          )
        ,
          ( PropertyName
"Either Bool Bool"
          , SizeTestConfig (Either Bool Bool) -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig (Either Bool Bool) -> Property)
-> SizeTestConfig (Either Bool Bool) -> Property
forall a b. (a -> b) -> a -> b
$
              (forall a. Show a => SizeTestConfig a
scfg @(Either Bool Bool))
                { gen = Right <$> Gen.bool
                , precise = True
                }
          )
        , (PropertyName
"Maybe Bool", SizeTestConfig Bool -> Property
forall a. ToCBOR a => SizeTestConfig a -> Property
sizeTest (SizeTestConfig Bool -> Property)
-> SizeTestConfig Bool -> Property
forall a b. (a -> b) -> a -> b
$ SizeTestConfig Bool
forall a. Buildable a => SizeTestConfig a
cfg {gen = Gen.bool, precise = True})
        ]