packages feed

transaction-0.1.1.2: test/Spec.hs

{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Prelude hiding
  ( all
  , any
  , break
  , drop
  , dropWhile
  , filter
  , foldMap
  , foldl
  , foldl1
  , foldr
  , foldr1
  , head
  , init
  , last
  , length
  , repeat
  , null
  , replicate
  , reverse
  , seq
  , span
  , splitAt
  , tail
  , take
  , takeWhile
  )
import Data.Bifunctor (Bifunctor(..))
import Data.MonoTraversable
  ( MonoFoldable(..)
  , MonoFunctor(..)
  , MonoPointed(..)
  , MonoTraversable(..)
  )
import Data.Sequences (IsSequence(..), SemiSequence(..))
import Data.Transaction
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
import Test.QuickCheck.Exception

main :: IO ()
main = hspec spec

exceptionableEq :: Eq a => Either AnException a -> Either AnException a -> Bool
exceptionableEq (Left _) (Left _) = True
exceptionableEq (Right a) (Right b) = a == b
exceptionableEq _ _ = False

spec :: Spec
spec = do
  describe "MonoFunctor" $ do
    describe "omap" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (a :: [Int]) ->
          omap f a == (toList . omap f . listToTrans) a

  describe "MonoFoldable" $ do
    describe "ofoldMap" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (a :: [Int]) ->
          (ofoldMap f a :: String) ==
          (ofoldMap f $ listToTrans a)
    describe "ofoldr" $ do
      modifyMaxSize (const 20) $ prop "is equivalent to list" $
        \f (a :: String) (mono :: [Int]) ->
          (ofoldr (applyFun2 f) a mono) ==
          (ofoldr (applyFun2 f) a $ listToTrans mono)
    describe "ofoldl'" $ do
      modifyMaxSize (const 20) $ prop "is equivalent to list" $
        \f (a :: String) (mono :: [Int]) ->
          (ofoldl' (applyFun2 f) a mono) ==
          (ofoldl' (applyFun2 f) a $ listToTrans mono)
    describe "otoList" $ do
      prop "is equivalent to list" $
        \(mono :: [Int]) ->
          otoList (listToTrans mono) == mono
    describe "oall" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (mono :: [Int]) ->
          (oall f mono) ==
          (oall f $ listToTrans mono)
    describe "oany" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (mono :: [Int]) ->
          (oany f mono) ==
          (oany f $ listToTrans mono)
    describe "onull" $ do
      prop "is equivalent to list" $
        \(mono :: [Int]) ->
          (onull mono) ==
          (onull $ listToTrans mono)
    describe "olength" $ do
      prop "is equivalent to list" $
        \(mono :: [Int]) ->
          (olength mono) ==
          (olength $ listToTrans mono)
    describe "olength64" $ do
      prop "is equivalent to list" $
        \(mono :: [Int]) ->
          (olength64 mono) ==
          (olength64 $ listToTrans mono)
    describe "ocompareLength" $ do
      prop "is equivalent to list" $
        \(i :: Integer) (mono :: [String]) ->
          (ocompareLength mono i) ==
          (ocompareLength (listToTrans mono) i)
    describe "otraverse_" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (mono :: [Int]) ->
          (otraverse_ (f :: Int -> Maybe String) mono) ==
          (otraverse_ f $ listToTrans mono)
    describe "ofor_" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (mono :: [Int]) ->
          (ofor_ mono (f :: Int -> Maybe String)) ==
          (ofor_ (listToTrans mono) f)
    describe "omapM_" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (mono :: [Int]) ->
          (omapM_ (f :: Int -> Maybe ()) mono) ==
          (omapM_ f (listToTrans mono))
    describe "oforM_" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (mono :: [Int]) ->
          (ofor_ mono (f :: Int -> Maybe ())) ==
          (ofor_ (listToTrans mono) f)
    describe "ofoldlM" $ do
      modifyMaxSize (const 40) $ prop "is equivalent to list" $
        \f (a :: String) (mono :: [Int]) ->
          (ofoldlM (applyFun2 f) a mono :: Maybe String) ==
          (ofoldlM (applyFun2 f) a (listToTrans mono))
    describe "ofoldMap1Ex" $ do
      it "is equivalent to list" $ again $ \(Fun _ f) (mono :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (ofoldMap1Ex f mono :: String)
          <*> tryEvaluate (ofoldMap1Ex f (listToTrans mono))
    describe "ofoldr1Ex" $ do
      it "is equivalent to list" $ again $ \f (mono :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (ofoldr1Ex (applyFun2 f) mono)
          <*> tryEvaluate (ofoldr1Ex (applyFun2 f) (listToTrans mono))
    describe "ofoldl1Ex'" $ do
      it "is equivalent to list" $ again $ \f (mono :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (ofoldl1Ex' (applyFun2 f) mono)
          <*> tryEvaluate (ofoldl1Ex' (applyFun2 f) (listToTrans mono))
    describe "headEx" $ do
      it "is equivalent to list" $ again $ \(mono :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (headEx mono)
          <*> tryEvaluate (headEx (listToTrans mono))
    describe "lastEx" $ do
      it "is equivalent to list" $ again $ \(mono :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (lastEx mono)
          <*> tryEvaluate (lastEx (listToTrans mono))
    describe "unsafeHead" $ do
      it "is equivalent to list" $ again $ \(mono :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (unsafeHead mono)
          <*> tryEvaluate (unsafeHead (listToTrans mono))
    describe "unsafeLast" $ do
      it "is equivalent to list" $ again $ \(mono :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (unsafeLast mono)
          <*> tryEvaluate (unsafeLast (listToTrans mono))
    describe "maximumByEx" $ do
      it "is equivalent to list" $ again $ \f (mono :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (maximumByEx (applyFun2 f) mono)
          <*> tryEvaluate (maximumByEx (applyFun2 f) (listToTrans mono))
    describe "minimumByEx" $ do
      it "is equivalent to list" $ again $ \f (mono :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (minimumByEx (applyFun2 f) mono)
          <*> tryEvaluate (minimumByEx (applyFun2 f) (listToTrans mono))

#if MIN_VERSION_mono_traversable(1,0,5)
    describe "oelem" $ do
      prop "is equivalent to list" $
        \(a :: Int) (mono :: [Int]) ->
          (oelem a mono) ==
          (oelem a (listToTrans mono))
    describe "onotElem" $ do
      prop "is equivalent to list" $
        \(a :: Int) (mono :: [Int]) ->
          (onotElem a mono) ==
          (onotElem a (listToTrans mono))
#endif

  describe "MonoPointed" $ do
    describe "opoint" $ do
      prop "is equivalent to list" $
        \(a :: Int) ->
          (opoint a) ==
          (toList $ opoint a)

  describe "SemiSequence" $ do
    describe "intersperse" $ do
      prop "is equivalent to list" $
        \(seq :: [Int]) a ->
          (intersperse a seq) ==
          (toList $ intersperse a $ listToTrans seq)
    describe "reverse" $ do
      prop "is equivalent to list" $
        \(seq :: [Int]) ->
          (reverse seq) ==
          (toList $ reverse $ listToTrans seq)
    describe "sortBy" $ do
      prop "is equivalent to list" $
        \f (seq :: [Int]) ->
          (sortBy (applyFun2 f) seq) ==
          (toList $ sortBy (applyFun2 f) $ listToTrans seq)
    describe "cons" $ do
      prop "is equivalent to list" $
        \a (seq :: [Int]) ->
          (cons a seq) ==
          (toList $ cons a $ listToTrans seq)
    describe "snoc" $ do
      prop "is equivalent to list" $
        \a (seq :: [Int]) ->
          (snoc seq a) ==
          (toList $ snoc (listToTrans seq) a)

  describe "MonoTraversable" $ do
    describe "otraverse" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (mono :: [Int]) ->
          (otraverse (f :: Int -> Maybe Int) mono) ==
          (toList <$> otraverse f (listToTrans mono))
    describe "omapM" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (mono :: [Int]) ->
          (otraverse (f :: Int -> Maybe Int) mono) ==
          (toList <$> otraverse f (listToTrans mono))

  describe "IsSequence" $ do
    describe "fromList" $ do
      prop "is equivalent to list" $
        \(seq :: [Int]) ->
          (toList $ fromList seq) == seq
#if MIN_VERSION_mono_traversable(1,0,2)
    describe "lengthIndex" $ do
      prop "is equivalent to list" $
        \(seq :: [Int]) ->
          (lengthIndex seq) ==
          (lengthIndex (listToTrans seq))
#endif
    describe "break" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (seq :: [Int]) ->
          (break f seq) ==
          (let (a,b) = break f (listToTrans seq) in (toList a, toList b))
    describe "span" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (seq :: [Int]) ->
          (span f seq) ==
          (let (a,b) = span f (listToTrans seq) in (toList a, toList b))
    describe "dropWhile" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (seq :: [Int]) ->
          (dropWhile f seq) ==
          (toList $ dropWhile f $ listToTrans seq)
    describe "takeWhile" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (seq :: [Int]) ->
          (takeWhile f seq) ==
          (toList $ takeWhile f $ listToTrans seq)
    describe "splitAt" $ do
      prop "is equivalent to list" $
        \n (seq :: [Int]) ->
          (splitAt n seq) ==
          (let (a,b) = splitAt n (listToTrans seq) in (toList a, toList b))
    describe "unsafeSplitAt" $ do
      prop "is equivalent to list" $
        \n (seq :: [Int]) ->
          (unsafeSplitAt n seq) ==
          (let (a,b) = unsafeSplitAt n (listToTrans seq) in (toList a, toList b))
    describe "take" $ do
      prop "is equivalent to list" $
        \n (seq :: [Int]) ->
          (take n seq) ==
          (toList $ take n $ fromList seq)
    describe "unsafeTake" $ do
      prop "is equivalent to list" $
        \n (seq :: [Int]) ->
          (unsafeTake n seq) ==
          (toList $ unsafeTake n $ fromList seq)
    describe "drop" $ do
      prop "is equivalent to list" $
        \n (seq :: [Int]) ->
          (drop n seq) ==
          (toList $ drop n $ fromList seq)
    describe "unsafeDrop" $ do
      prop "is equivalent to list" $
        \n (seq :: [Int]) ->
          (unsafeDrop n seq) ==
          (toList $ unsafeDrop n $ fromList seq)
#if MIN_VERSION_mono_traversable(1,0,4)
    describe "dropEnd" $ do
      prop "is equivalent to list" $
        \n (seq :: [Int]) ->
          (dropEnd n seq) ==
          (toList $ dropEnd n $ fromList seq)
#endif
    describe "partition" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (seq :: [Int]) ->
          (partition f seq) ==
          (let (a, b) = partition f (listToTrans seq) in (toList a, toList b))
    describe "uncons" $ do
      prop "is equivalent to list" $
        \(seq :: [Int]) ->
          (uncons seq) ==
          (second toList <$> uncons (listToTrans seq))
    describe "unsnoc" $ do
      prop "is equivalent to list" $
        \(seq :: [Int]) ->
          (unsnoc seq) ==
          (first toList <$> unsnoc (listToTrans seq))
    describe "filter" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (seq :: [Int]) ->
          (filter f seq) ==
          (toList $ filter f $ listToTrans seq)
    describe "filterM" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (seq :: [Int]) ->
          (filterM (f :: Int -> Maybe Bool) seq) ==
          (toList <$> filterM f (listToTrans seq))
    describe "replicate" $ do
      prop "is equivalent to list" $
        \n (a :: Int) ->
          (replicate n a) ==
          (toList $ replicate n a)
    describe "replicateM" $ do
      prop "is equivalent to list" $
        \n (ma :: Maybe Int) ->
          (replicateM n ma) ==
          (toList <$> replicateM n ma)
    describe "groupBy" $ do
      prop "is equivalent to list" $
        \f (seq :: [Int]) ->
          (groupBy (applyFun2 f) seq) ==
          (map toList $ groupBy (applyFun2 f) $ listToTrans seq)
    describe "groupAllOn" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (seq :: [Int]) ->
          (groupAllOn (f :: Int -> String) seq) ==
          (map toList $ groupAllOn f $ listToTrans seq)
    describe "subsequences" $ do
      modifyMaxSize (const 10) $ prop "is equivalent to list" $
        \(seq :: [Int]) ->
          (subsequences seq) ==
          (map toList $ subsequences $ listToTrans seq)
    describe "permutations" $ do
      modifyMaxSize (const 10) $ prop "is equivalent to list" $
        \(seq :: [Int]) ->
          (permutations seq) ==
          (map toList $ permutations $ listToTrans seq)
    describe "tailEx" $ do
      it "is equivalent to list" $ again $ \(seq :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (tailEx seq)
          <*> tryEvaluate (toList $ tailEx $ listToTrans seq)
    describe "tailMay" $ do
      prop "is equivalent to list" $
        \(seq :: [Int]) ->
          (tailMay seq) ==
          (fmap toList $ tailMay $ listToTrans seq)
    describe "initEx" $ do
      it "is equivalent to list" $ again $ \(seq :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (initEx seq)
          <*> tryEvaluate (toList $ initEx $ listToTrans seq)
    describe "initMay" $ do
      prop "is equivalent to list" $
        \(seq :: [Int]) ->
          (initMay seq) ==
          (fmap toList $ initMay $ listToTrans seq)
    describe "unsafeTail" $ do
      it "is equivalent to list" $ again $ \(seq :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (unsafeTail seq)
          <*> tryEvaluate (toList $ unsafeTail $ listToTrans seq)
    describe "unsafeInit" $ do
      it "is equivalent to list" $ again $ \(seq :: [Int]) -> ioProperty $
        exceptionableEq
          <$> tryEvaluate (unsafeInit seq)
          <*> tryEvaluate (toList $ unsafeInit $ listToTrans seq)
    describe "index" $ do
      prop "is equivalent to list" $
        \(seq :: [Int]) n ->
          (index seq n) ==
          (index (listToTrans seq) n)
    describe "indexEx" $ do
      it "is equivalent to list" $ again $ \(seq :: [Int]) n -> ioProperty $
        exceptionableEq <$> tryEvaluate (indexEx seq n) <*> tryEvaluate (indexEx (listToTrans seq) n)
    describe "unsafeIndex" $ do
      it "is equivalent to list" $ again $ \(seq :: [Int]) n -> ioProperty $
        exceptionableEq <$> tryEvaluate (unsafeIndex seq n) <*> tryEvaluate (unsafeIndex (listToTrans seq) n)

    describe "splitWhen" $ do
      prop "is equivalent to list" $
        \(Fun _ f) (seq :: [Int]) ->
          (splitWhen f seq) ==
          (fmap toList $ splitWhen f $ listToTrans seq)

listToTrans :: [a] -> Transaction a
listToTrans = fromList