{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Data.SafeJSON.Test (
testConsistency
, testConsistency'
, testMigration
, testReverseMigration
, (<=?)
, (>=?)
, testRoundTrip
, migrateRoundTrip
, migrateReverseRoundTrip
, TestMigrate
, TestReverseMigrate
, testRoundTripProp
, migrateRoundTripProp
, migrateReverseRoundTripProp
, testRoundTripProp'
, migrateRoundTripProp'
, migrateReverseRoundTripProp'
, Proxy(..)
) where
import Data.Aeson.Types (parseEither)
import Data.Proxy
import Data.SafeJSON.Internal
import Test.Tasty (TestTree)
import Test.Tasty.HUnit (Assertion, assertEqual)
import Test.Tasty.QuickCheck (Arbitrary, testProperty)
testConsistency :: forall a. SafeJSON a => Assertion
testConsistency = checkConsistency p $ \_ -> return ()
where p = Proxy :: Proxy a
testConsistency' :: forall a. SafeJSON a => Proxy a -> Assertion
testConsistency' = flip checkConsistency $ \_ -> return ()
testRoundTrip :: (Show a, Eq a, SafeJSON a) => a -> Assertion
testRoundTrip a = "To JSON and back not consistent" `assertEqual` Right a $
parseEither (safeFromJSON . safeToJSON) a
testRoundTripProp' :: forall a. (Eq a, Show a, Arbitrary a, SafeJSON a) => Proxy a -> String -> TestTree
testRoundTripProp' _ s = testProperty s $ \a ->
Right (a :: a) == parseEither (safeFromJSON . safeToJSON) a
testRoundTripProp :: forall a. (Eq a, Show a, Arbitrary a, SafeJSON a) => String -> TestTree
testRoundTripProp s = testProperty s $ \a ->
Right (a :: a) == parseEither (safeFromJSON . safeToJSON) a
testMigration :: (Show a, Eq a, Migrate a) => MigrateFrom a -> a -> Assertion
testMigration = assertEqual "Unexpected result of SafeJSON migration" . migrate
testReverseMigration :: (Show a, Eq a, Migrate (Reverse a)) => MigrateFrom (Reverse a) -> a -> Assertion
testReverseMigration = assertEqual "Unexpected result of SafeJSON migration" . unReverse . migrate
infix 1 >=?, <=?
(<=?) :: (Show a, Eq a, Migrate a) => MigrateFrom a -> a -> Assertion
(<=?) = testMigration
(>=?) :: (Show a, Eq a, Migrate (Reverse a)) => MigrateFrom (Reverse a) -> a -> Assertion
(>=?) = testReverseMigration
migrateRoundTrip :: forall a. (Eq a, Show a, SafeJSON a, Migrate a) => MigrateFrom a -> Assertion
migrateRoundTrip oldType = "Unexpected result of decoding encoded older type" `assertEqual` Right (migrate oldType :: a) $
parseEither (safeFromJSON . safeToJSON) oldType
migrateReverseRoundTrip :: forall a. (Eq a, Show a, SafeJSON a, Migrate (Reverse a)) => MigrateFrom (Reverse a) -> Assertion
migrateReverseRoundTrip newType = "Unexpected result of decoding encoded newer type" `assertEqual` Right (unReverse $ migrate newType :: a) $
parseEither (safeFromJSON . safeToJSON) newType
type TestMigrate a b =
( Eq a
, Show (MigrateFrom a)
, Arbitrary (MigrateFrom a)
, SafeJSON a
, SafeJSON (MigrateFrom a)
, Migrate a
, MigrateFrom a ~ b
)
migrateRoundTripProp' :: forall a b. TestMigrate a b => Proxy (a,b) -> String -> TestTree
migrateRoundTripProp' _ s = testProperty s $ \a ->
Right (migrate a :: a) == parseEither (safeFromJSON . safeToJSON) a
migrateRoundTripProp :: forall a b. TestMigrate a b => String -> TestTree
migrateRoundTripProp s = testProperty s $ \a ->
Right (migrate a :: a) == parseEither (safeFromJSON . safeToJSON) a
type TestReverseMigrate a b =
( Eq a
, Show (MigrateFrom (Reverse a))
, Arbitrary (MigrateFrom (Reverse a))
, SafeJSON a
, Migrate (Reverse a)
, MigrateFrom (Reverse a) ~ b
)
migrateReverseRoundTripProp' :: forall a b. TestReverseMigrate a b => Proxy (a,b) -> String -> TestTree
migrateReverseRoundTripProp' _ s = testProperty s $ \a ->
Right (unReverse $ migrate a :: a) == parseEither (safeFromJSON . safeToJSON) a
migrateReverseRoundTripProp :: forall a b. TestReverseMigrate a b => String -> TestTree
migrateReverseRoundTripProp s = testProperty s $ \a ->
Right (unReverse $ migrate a :: a) == parseEither (safeFromJSON . safeToJSON) a