circular-0.1.0: test/Data/Stack/CircularSpec.hs
{-# LANGUAGE FlexibleInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-- |
-- Module : Data.Stack.CircularSpec
-- Description : Unit tests for Data.Stack.Circular
-- Copyright : (c) Dominik Schrempf, 2020
-- License : GPL-3.0-or-later
--
-- Maintainer : dominik.schrempf@gmail.com
-- Stability : unstable
-- Portability : portable
--
-- Creation date: Thu Jun 18 10:21:28 2020.
module Data.Stack.CircularSpec
( spec,
)
where
import Control.Exception
import Data.Aeson
import Data.Stack.Circular as C
import Data.Vector (Vector)
import qualified Data.Vector as V
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck hiding (Success, Result)
import Test.QuickCheck.Instances.Vector ()
import Prelude hiding (sum, product)
instance Arbitrary (CStack Vector Int) where
arbitrary = do
s <- getSize
n <- choose (1, s+1)
v <- V.fromList <$> vector n
i <- choose (0, n-1)
m <- choose (1, n)
return $ CStack v i m
se :: CStack Vector Int
se = empty 10
ss :: CStack Vector Int
ss = push 13 se
prop_from_to_id :: Vector Int -> Bool
prop_from_to_id v
| V.length v == 0 = True
| otherwise = toVector (fromVector v) == v
prop_pop :: Vector Int -> Bool
prop_pop v
| V.length v == 0 = True
| otherwise = toVector (snd $ pop $ fromVector v) == V.init v
prop_push_pop :: Int -> Vector Int -> Bool
prop_push_pop x v
| V.length v == 0 = True
| otherwise = toVector (snd $ pop $ push x $ fromVector v) == V.tail v
prop_push :: Int -> Vector Int -> Bool
prop_push x v
| V.length v == 0 = True
| otherwise = toVector (push x $ fromVector v) == V.tail v V.++ V.singleton x
prop_many_pushes :: [Int] -> Vector Int -> Bool
prop_many_pushes xs v
| V.length v == 0 = True
| length xs <= V.length v = True
| otherwise =
toVector (foldr push (fromVector v) xs)
== V.fromList (reverse $ take (V.length v) xs)
prop_length :: CStack Vector Int -> Bool
prop_length c = V.length (toVector c) == curSize c
jsonId :: CStack Vector Int -> Result (CStack Vector Int)
jsonId c = fromJSON $ toJSON c
prop_json_sum :: CStack Vector Int -> Bool
prop_json_sum c = (sum <$> jsonId c) == Success (sum c)
prop_json_product :: CStack Vector Int -> Bool
prop_json_product c = (product <$> jsonId c) == Success (product c)
-- Check current size and max size.
prop_json_misc :: CStack Vector Int -> Bool
prop_json_misc c = ((curSize <$> jsonId c) == Success (curSize c)) &&
((V.length . stack <$> jsonId c) == Success (V.length $ stack c))
spec :: Spec
spec = do
describe "construction" $ it "doesn't choke on weird inputs" $ do
print ss
toVector se `shouldBe` V.empty
toVector (snd $ pop ss) `shouldBe` V.empty
describe "conversion identities" $ do
it "correctly converts partly filled stacks" $
toVector ss `shouldBe` V.singleton 13
prop "toVector . fromVector is identity" (prop_from_to_id :: Vector Int -> Bool)
describe "conversion failure" $
it "fails to convert empty vectors" $
evaluate (fromVector V.empty) `shouldThrow` anyErrorCall
describe "properties" $ do
prop "pop" prop_pop
prop "push" prop_push
prop "push pop" prop_push_pop
prop "many pushed" prop_many_pushes
prop "length" prop_length
prop "json sum" prop_json_sum
prop "json product" prop_json_product
prop "json misc" prop_json_misc
describe "laziness" $
it "should not conflict with intuition" $
toVector ss `shouldNotBe` toVector (push 10 ss)