packages feed

lsm-tree-1.0.0.0: test/Test/Database/LSMTree/Internal/Serialise/Class.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications    #-}

module Test.Database.LSMTree.Internal.Serialise.Class (tests) where

import           Data.ByteString (ByteString)
import           Data.ByteString.Lazy (LazyByteString)
import           Data.ByteString.Short (ShortByteString)
import           Data.Constraint (Dict (..))
import           Data.Int
import           Data.Monoid (Sum)
import           Data.Primitive (ByteArray)
import           Data.WideWord (Word128, Word256)
import           Data.Word
import           Database.LSMTree.Extras.Generators ()
import           Database.LSMTree.Extras.UTxO (UTxOKey, UTxOValue)
import           Database.LSMTree.Internal.Serialise.Class
import           Test.Tasty
import           Test.Tasty.QuickCheck

tests :: TestTree
tests = testGroup "Test.Database.LSMTree.Internal.Serialise.Class" [
      testGroup "String" (allProperties @String (Just Dict))

      -- Int
    , testGroup "Int8"  (allProperties @Int8  Nothing)
    , testGroup "Int16" (allProperties @Int16 Nothing)
    , testGroup "Int32" (allProperties @Int32 Nothing)
    , testGroup "Int64" (allProperties @Int64 Nothing)
    , testGroup "Int"   (allProperties @Int   Nothing)

      -- Word
    , testGroup "Word8"  (allProperties @Word8  (Just Dict))
    , testGroup "Word16" (allProperties @Word16 (Just Dict))
    , testGroup "Word32" (allProperties @Word32 (Just Dict))
    , testGroup "Word64" (allProperties @Word64 (Just Dict))
    , testGroup "Word"   (allProperties @Word   (Just Dict))

      -- ByteString
    , testGroup "ByteString"      (allProperties @ByteString      (Just Dict))
    , testGroup "LazyByteString"  (allProperties @LazyByteString  (Just Dict))
    , testGroup "ShortByteString" (allProperties @ShortByteString (Just Dict))
    , testGroup "ByteArray"       (allProperties @ByteArray       Nothing    )

      -- UTXO
    , testGroup "Word128"         (allProperties   @Word128   (Just Dict))
    , testGroup "Word256"         (allProperties   @Word256   (Just Dict))
    , testGroup "UTxOKey"         (keyProperties   @UTxOKey   Nothing    )
    , testGroup "UTxOValue"       (valueProperties @UTxOValue            )

      -- Modifiers
    , testGroup "Sum Word" (valueProperties @(Sum Word))
    ]

allProperties ::
     forall a. (Ord a, Show a, Arbitrary a, SerialiseKey a, SerialiseValue a)
  => Maybe (Dict (SerialiseKeyOrderPreserving a))
  -> [TestTree]
allProperties orderPreserving = keyProperties @a orderPreserving <> valueProperties @a

keyProperties ::
     forall a. (Ord a, Show a, Arbitrary a, SerialiseKey a)
  => Maybe (Dict (SerialiseKeyOrderPreserving a))
  -> [TestTree]
keyProperties orderPreserving =
    [ testProperty "prop_roundtripSerialiseKey" $
        prop_roundtripSerialiseKey @a
    , testProperty "prop_roundtripSerialiseKeyUpToSlicing" $
        prop_roundtripSerialiseKeyUpToSlicing @a
    , testProperty "prop_orderPreservationSerialiseKey" $ \k1 k2 ->
        let modifier = case orderPreserving of
              Just Dict -> id
              Nothing   -> expectFailure
        in  modifier $ prop_orderPreservationSerialiseKey @a k1 k2

    ]

valueProperties :: forall a. (Ord a, Show a, Arbitrary a, SerialiseValue a) => [TestTree]
valueProperties =
    [ testProperty "prop_roundtripSerialiseValue" $
        prop_roundtripSerialiseValue @a
    , testProperty "prop_roundtripSerialiseValueUpToSlicing" $
        prop_roundtripSerialiseValueUpToSlicing @a
    ]

prop_roundtripSerialiseKey :: forall k. (Eq k, Show k, SerialiseKey k) => k -> Property
prop_roundtripSerialiseKey k =
    counterexample ("serialised: " <> show (serialiseKey k)) $
    counterexample ("deserialised: " <> show @k (deserialiseKey (serialiseKey k))) $
      serialiseKeyIdentity k

prop_roundtripSerialiseKeyUpToSlicing ::
     forall k. (Eq k, Show k, SerialiseKey k)
  => RawBytes -> k -> RawBytes -> Property
prop_roundtripSerialiseKeyUpToSlicing prefix x suffix =
    counterexample ("serialised: " <> show @RawBytes k) $
    counterexample ("serialised and sliced: " <> show @RawBytes k') $
    counterexample ("deserialised: " <> show @k x') $
      serialiseKeyIdentityUpToSlicing prefix x suffix
  where
    k = serialiseKey x
    k' = packSlice prefix k suffix
    x' = deserialiseKey k'

prop_orderPreservationSerialiseKey :: forall k. (Ord k, SerialiseKey k) => k -> k -> Property
prop_orderPreservationSerialiseKey x y =
    counterexample ("serialised: " <> show (serialiseKey x, serialiseKey y)) $
    counterexample ("compare: " <> show (compare x y)) $
    counterexample ("compare serialised: " <> show (compare (serialiseKey x) (serialiseKey y))) $
      serialiseKeyPreservesOrdering x y

prop_roundtripSerialiseValue :: forall v. (Eq v, Show v, SerialiseValue v) => v -> Property
prop_roundtripSerialiseValue v =
    counterexample ("serialised: " <> show (serialiseValue v)) $
    counterexample ("deserialised: " <> show @v (deserialiseValue (serialiseValue v))) $
      serialiseValueIdentity v

prop_roundtripSerialiseValueUpToSlicing ::
     forall v. (Eq v, Show v, SerialiseValue v)
  => RawBytes -> v -> RawBytes -> Property
prop_roundtripSerialiseValueUpToSlicing prefix x suffix =
    counterexample ("serialised: " <> show v) $
    counterexample ("serialised and sliced: " <> show @RawBytes v') $
    counterexample ("deserialised: " <> show @v x') $
      serialiseValueIdentityUpToSlicing prefix x suffix
  where
    v = serialiseValue x
    v' = packSlice prefix v suffix
    x' = deserialiseValue v'