{-# LANGUAGE DataKinds #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Main (main) where
import Test.Tasty
import Test.Tasty.HUnit
import Data.Int (Int64)
import Data.Text (Text)
import Database.Persist (PersistField (..), PersistValue (..))
import Polytropos
import Polytropos.Persistent
type MyRec = Record '[ "x" ':= Int, "y" ':= Int, "z" ':= Int ]
-- Heterogeneous row: each field marshals through its own PersistField.
type Hetero = Record '[ "n" ':= Int, "b" ':= Bool, "w" ':= Int ]
myRec :: MyRec
myRec = REC { x = 1, y = 2, z = 3 }
heteroRec :: Hetero
heteroRec = REC { n = 7, b = True, w = 9 }
type RowOf20 =
'[ "f00" ':= Int, "f01" ':= Int, "f02" ':= Int, "f03" ':= Int, "f04" ':= Int
, "f05" ':= Int, "f06" ':= Int, "f07" ':= Int, "f08" ':= Int, "f09" ':= Int
, "f10" ':= Int, "f11" ':= Int, "f12" ':= Int, "f13" ':= Int, "f14" ':= Int
, "f15" ':= Int, "f16" ':= Int, "f17" ':= Int, "f18" ':= Int, "f19" ':= Int
]
buildBig :: Int -> Record RowOf20
buildBig n =
insertField (Field @"f00") n
$ insertField (Field @"f01") n
$ insertField (Field @"f02") n
$ insertField (Field @"f03") n
$ insertField (Field @"f04") n
$ insertField (Field @"f05") n
$ insertField (Field @"f06") n
$ insertField (Field @"f07") n
$ insertField (Field @"f08") n
$ insertField (Field @"f09") n
$ insertField (Field @"f10") n
$ insertField (Field @"f11") n
$ insertField (Field @"f12") n
$ insertField (Field @"f13") n
$ insertField (Field @"f14") n
$ insertField (Field @"f15") n
$ insertField (Field @"f16") n
$ insertField (Field @"f17") n
$ insertField (Field @"f18") n
$ insertField (Field @"f19") n
$ emptyRecord
main :: IO ()
main = defaultMain $ testGroup "Persistent Integration"
[ testGroup "PersistRow marshalling"
[ testCase "roundtrip 3 fields" $
fromPersistValuesRecord (toPersistFieldsRecord myRec)
@?= Right myRec
, testCase "roundtrip heterogeneous row" $
fromPersistValuesRecord (toPersistFieldsRecord heteroRec)
@?= Right heteroRec
, testCase "roundtrip 20 fields" $ do
let big = buildBig (42 :: Int)
fromPersistValuesRecord (toPersistFieldsRecord big)
@?= Right big
, testCase "serializes fields in row order" $
toPersistFieldsRecord myRec
@?= [ PersistInt64 1, PersistInt64 2, PersistInt64 3 ]
, testCase "rejects a short row" $
case (fromPersistValuesRecord (take 2 (toPersistFieldsRecord myRec)) :: Either Text' MyRec) of
Left _ -> return ()
Right _ -> assertFailure "short row should not decode"
, testCase "rejects a long row" $
case (fromPersistValuesRecord (PersistInt64 9 : toPersistFieldsRecord myRec) :: Either Text' MyRec) of
Left _ -> return ()
Right _ -> assertFailure "long row should not decode"
]
, testGroup "PersistField bridge"
[ testCase "record roundtrips through PersistList" $ do
let pv = toPersistValue myRec
(fromPersistValue pv :: Either Text' MyRec) @?= Right myRec
, testCase "non-list value is rejected" $
case (fromPersistValue (PersistInt64 5) :: Either Text' MyRec) of
Left _ -> return ()
Right _ -> assertFailure "PersistInt64 should not decode as a record"
]
, testGroup "Entity wrapper"
[ testCase "entity row is key-then-fields" $ do
let e = toPolyRowEntity (123 :: Int64) myRec
fromPolyRowEntity e
@?= (123 :: Int64, [ PersistInt64 123, PersistInt64 1, PersistInt64 2, PersistInt64 3 ])
, testCase "entity roundtrip" $ do
let e = toPolyRowEntity (77 :: Int64) myRec
let (k, vs) = fromPolyRowEntity e
k @?= polyRowKey e
(fromPersistValuesRecord (drop 1 vs) :: Either Text' MyRec)
@?= Right (polyRowRecord e)
]
]
type Text' = Text