pantry-0.8.3: test/Pantry/Internal/StaticBytesSpec.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Pantry.Internal.StaticBytesSpec
( spec
) where
import Control.Monad ( replicateM )
import qualified Data.ByteString as B
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Storable as VS
import qualified Data.Vector.Unboxed as VU
import Pantry.Internal.StaticBytes
import RIO
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
spec :: Spec
spec = do
describe "ByteString" $ tests B.pack
describe "Storable Vector" $ tests VS.fromList
describe "Unboxed Vector" $ tests VU.fromList
describe "Primitive Vector" $ tests VP.fromList
tests :: (Eq dbytes, Show dbytes, DynamicBytes dbytes) => ([Word8] -> dbytes) -> Spec
tests pack = do
it "disallows 4 bytes" $ property $ \(w1,w2,w3,w4) ->
toStaticExact (pack [w1,w2,w3,w4]) `shouldBe` (Left NotEnoughBytes :: Either StaticBytesException Bytes8)
it "toStaticExact matches ByteString" $ property $ \(w1,w2,w3,w4) -> property $ \(w5,w6,w7,w8) -> do
let octets = [w1,w2,w3,w4,w5,w6,w7,w8]
(expected :: Bytes8) = either impureThrow id $ toStaticExact (B.pack octets)
actual = either impureThrow id $ toStaticExact (pack octets)
actual `shouldBe` expected
it "fromStatic round trips" $ property $ \(w1,w2,w3,w4) -> property $ \(w5,w6,w7,w8) -> do
let octets = [w1,w2,w3,w4,w5,w6,w7,w8]
v1 = pack octets
(b8 :: Bytes8) = either impureThrow id $ toStaticExact v1
v2 = fromStatic b8
v2 `shouldBe` v1
it "allows 8 bytes" $ property $ \(w1,w2,w3,w4) -> property $ \(w5,w6,w7,w8) -> do
let bs = pack [w1,w2,w3,w4,w5,w6,w7,w8]
case toStaticExact bs of
Left e -> throwIO e
Right b8 -> fromStatic (b8 :: Bytes8) `shouldBe` bs
toStaticExact bs `shouldBe` (Left NotEnoughBytes :: Either StaticBytesException Bytes16)
it "padding is the same as trailing nulls" $ property $ \(w1,w2,w3,w4) -> do
let ws = [w1,w2,w3,w4]
bs1 = pack $ ws ++ replicate 4 0
bs2 = pack ws
Right (toStaticPadTruncate bs2 :: Bytes8) `shouldBe` toStaticExact bs1
prop "handles bytes16" $ \octets -> do
let bs = pack $ take 16 octets
(b16 :: Bytes16) = either impureThrow id $ toStaticPad bs
fromStatic b16 `shouldBe` pack (take 16 (octets ++ replicate 16 0))
it "spot check bytes16" $ forAll (replicateM 16 arbitrary) $ \ws -> do
let bs = pack ws
(b16 :: Bytes16) = either impureThrow id $ toStaticPad bs
fromStatic b16 `shouldBe` pack ws
prop "handles bytes32" $ \octets -> do
let bs = pack $ take 32 octets
(b32 :: Bytes32) = either impureThrow id $ toStaticPad bs
fromStatic b32 `shouldBe` pack (take 32 (take 32 octets ++ replicate 32 0))
prop "fuzz with encodeUtf8" $ \chars -> do
let t = T.pack $ filter (/= '\0') chars
bs = TE.encodeUtf8 t
bs128 = pack $ B.unpack $ B.take 128 $ bs `B.append` B.replicate 128 0
b128 = toStaticPadTruncate (pack $ B.unpack bs) :: Bytes128
fromStatic b128 `shouldBe` bs128