packages feed

winery-1.3.2: test/Spec.hs

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-missing-signatures#-}
import Control.Monad
import Barbies.Bare
import Barbies.TH
import Data.ByteString (ByteString)
import Data.Fixed (Pico)
import Data.Functor.Identity
import Data.Int
import Data.IntMap (IntMap)
import Data.IntSet (IntSet)
import Data.Map (Map)
import Data.Scientific (Scientific)
import Data.Sequence (Seq)
import Data.Set (Set)
import Data.Text (Text)
import Data.Time (NominalDiffTime)
import Codec.Winery
import Codec.Winery.Internal
import Data.Word
import qualified Data.ByteString.FastBuilder as B
import qualified Data.ByteString.Lazy as BL
import qualified Data.HashMap.Strict as HM
import qualified Data.Vector as V
import qualified Data.Vector.Storable as SV
import qualified Data.Vector.Unboxed as UV
import GHC.Generics
import Test.QuickCheck
import qualified Test.QuickCheck.Gen as Gen
import Test.QuickCheck.Instances ()
import Control.Applicative ((<|>))

prop_VarInt :: Int -> Property
prop_VarInt i = evalDecoder decodeVarInt
  (B.toStrictByteString $ varInt i) === i

newtype Nano = Nano NominalDiffTime deriving (Show, Eq, Serialise)

instance Arbitrary Nano where
  arbitrary = Nano . realToFrac . (1000*) <$> (arbitrary :: Gen Pico)

prop_Unit = testSerialise @ ()
prop_Bool = testSerialise @ Bool
prop_Word8 = testSerialise @ Word8
prop_Word16 = testSerialise @ Word16
prop_Word32 = testSerialise @ Word32
prop_Word64 = testSerialise @ Word64
prop_Word = testSerialise @ Word
prop_Int8 = testSerialise @ Int8
prop_Int16 = testSerialise @ Int16
prop_Int32 = testSerialise @ Int32
prop_Int64 = testSerialise @ Int64
prop_Int = testSerialise @ Int
prop_Float = testSerialise @ Float
prop_Double = testSerialise @ Double
prop_Text = testSerialise @ Text
prop_Integer = testSerialise @ Integer
prop_Char = testSerialise @ Char
prop_Maybe_Int = testSerialise @ (Maybe Int)
prop_ByteString = testSerialise @ ByteString
prop_ByteString_Lazy = testSerialise @ BL.ByteString
-- prop_UTCTime = testSerialise @ UTCTime
prop_NominalDiffTime = testSerialise @ Nano
prop_List_Int = testSerialise @ [Int]
prop_Vector_Int = testSerialise @ (V.Vector Int) . V.fromList
prop_Vector_Storable_Int = testSerialise @ (SV.Vector Int) . SV.fromList
prop_Vector_Unboxed_Int = testSerialise @ (UV.Vector Int) . UV.fromList
prop_Map_Int_Int = testSerialise @ (Map Int Int)
prop_HashMap_String_Int = testSerialise @ (HM.HashMap String Int) . HM.fromList
prop_IntMap_Int = testSerialise @ (IntMap Int)
prop_Set_Int = testSerialise @ (Set Int)
prop_IntSet = testSerialise @ IntSet
prop_Seq_Int = testSerialise @ (Seq Int)
prop_Scientific = testSerialise @ Scientific
prop_Tuple2 = testSerialise @ (Bool, Int)
prop_Tuple3 = testSerialise @ (Bool, Int, Text)
prop_Tuple4 = testSerialise @ (Bool, Int, Text, Double)
prop_Either_String_Int = testSerialise @ (Either String Int)
prop_Ordering = testSerialise @ Ordering

data TRec = TRec
  { foo :: !Int
  , bar :: !Text
  } deriving (Show, Eq, Generic)

instance Arbitrary TRec where
  arbitrary = TRec <$> arbitrary <*> arbitrary

instance Serialise TRec where
  bundleSerialise = bundleVia WineryRecord

prop_TRec = testSerialise @ TRec

data TList a = TCons a (TList a) | TNil deriving (Show, Eq, Generic)

instance Serialise a => Serialise (TList a) where
  bundleSerialise = bundleVia WineryVariant

instance Arbitrary a => Arbitrary (TList a) where
  arbitrary = sized $ \n -> if n <= 0
    then pure TNil
    else TCons <$> arbitrary <*> scale pred arbitrary

prop_TList_Int = testSerialise @ (TList Int)

data Tree
  = Leaf
  | Branch Node
  deriving (Show, Eq, Generic)

data Node = Node { left :: !Tree, value :: !Int, right :: !Tree }
  deriving (Show, Eq, Generic)

instance Arbitrary Tree where
  arbitrary = sized $ \n -> if n <= 0
    then pure Leaf
    else Branch <$> arbitrary

instance Arbitrary Node where
  arbitrary = sized $ \n -> do
    leftSize <- Gen.choose (0, max 0 $ n - 1)
    let rightSize = max 0 $ n - 1 - leftSize
    Node <$> resize leftSize arbitrary <*> arbitrary <*> resize rightSize arbitrary

instance Serialise Tree where
  bundleSerialise = bundleVia WineryVariant

instance Serialise Node where
  bundleSerialise = (bundleVia WineryRecord)
    { bundleExtractor = buildExtractor $ Node
      <$> (extractField "left" <|> extractField "leftChild")
      <*> extractField "value"
      <*> (extractField "right" <|> extractField "rightChild")
    }

prop_tree = testSerialise @ Tree
prop_node = testSerialise @ Node

data Foo = Foo | Bar | Baz | Qux | FooBar | FooBaz | FooQux deriving (Generic, Eq, Show, Enum)

instance Arbitrary Foo where
  arbitrary = toEnum <$> Gen.choose (0, 6)

instance Serialise Foo where
  bundleSerialise = bundleVia WineryVariant

prop_Foo = testSerialise @ Foo

data Soup = Shoyu | Miso | Tonkotsu deriving (Generic, Eq, Show, Enum)

instance Arbitrary Soup where
  arbitrary = toEnum <$> Gen.choose (0, 2)

instance Serialise Soup where
  bundleSerialise = bundleVia WineryVariant

data Food = Rice | Ramen Soup | Pasta Text Text deriving (Generic, Eq, Show)

instance Arbitrary Food where
  arbitrary = Gen.oneof
    [ pure Rice
    , Ramen <$> arbitrary
    , Pasta
      <$> Gen.elements ["Spaghetti", "Rigatoni", "Linguine"]
      <*> Gen.elements ["Aglio e olio", "L'amatriciana", "Carbonara"]
    ]

instance Serialise Food where
  bundleSerialise = bundleVia WineryVariant
  extractor = buildExtractor
    $ ("Rice", \() -> Rice)
    `extractConstructor` ("Ramen", Ramen)
    `extractConstructor` ("Pasta", uncurry Pasta)
    `extractConstructor` extractVoid

prop_Food = testSerialise @ Food

declareBareB [d|
  data HRecB = HRec
    { baz :: !Int
    , qux :: !Text
    } deriving Generic
    |]
type HRec = HRecB Bare Identity

instance Serialise HRec where
  bundleSerialise = bundleVia WineryRecord
  extractor = fmap bstrip $ buildRecordExtractor bextractors
    { qux = extractField "qux" <|> extractField "oldQux" }

deriving instance Show HRec
deriving instance Eq HRec

instance Arbitrary HRec where
  arbitrary = HRec <$> arbitrary <*> arbitrary
prop_HRec = testSerialise @ HRec
return []
main = $quickCheckAll >>= flip unless (error "Failed")