yeamer-0.1.0.0: test/tasty/test.hs
-- |
-- Module : Main
-- Copyright : (c) Justus Sagemüller 2017
-- License : GPL v3
--
-- Maintainer : (@) jsag $ hvl.no
-- Stability : experimental
-- Portability : portable
--
module Main where
import Presentation.Yeamer.Internal.Grid
import Data.Semigroup.Numbered
import qualified Data.Aeson as JSON
import Test.Tasty
import Test.Tasty.HUnit
import qualified Test.Tasty.QuickCheck as QC
import Test.Tasty.QuickCheck (Arbitrary(..))
import Control.Monad
main = defaultMain tests
tests :: TestTree
tests = testGroup "Tests"
[ testGroup "Grids"
[ testGroup "Concatenation"
[ testCase "Singletons, horizontal"
$ pure 0 │ pure 1
=#?@= ( GridDivisions [ [pure 0, pure 1] ]
, GridLayout 2 1 [(GridRange 0 1 0 1, 0), (GridRange 1 2 0 1, 1)] )
, testCase "Singletons, vertical"
$ pure 1
──
pure 2
=#?@= ( GridDivisions [ [pure 1]
, [pure 2] ]
, GridLayout 1 2 [(GridRange 0 1 0 1, 1), (GridRange 0 1 1 2, 2)] )
, testCase "Quadrat"
$ pure 0 │ pure 1
──
pure 2 │ pure 3
=#?@= ( GridDivisions [ [pure 0, pure 1]
, [pure 2, pure 3] ]
, GridLayout 2 2 [ (GridRange 0 1 0 1, 0), (GridRange 1 2 0 1, 1)
, (GridRange 0 1 1 2, 2), (GridRange 1 2 1 2, 3) ] )
, testCase "Rectangle, landscape"
$ pure 0 │ pure 1 │ pure 4
──
pure 2 │ pure 3 │ pure 5
=#?@= ( GridDivisions [ [pure 0, pure 1, pure 4]
, [pure 2, pure 3, pure 5] ]
, GridLayout 3 2
[ (GridRange 0 1 0 1, 0), (GridRange 1 2 0 1, 1), (GridRange 2 3 0 1, 4)
, (GridRange 0 1 1 2, 2), (GridRange 1 2 1 2, 3), (GridRange 2 3 1 2, 5) ] )
, testCase "Rectangle, portrait"
$ pure 0 │ pure 1
──
pure 2 │ pure 3
──
pure 4 │ pure 5
=#?@= ( GridDivisions [ [pure 0, pure 1]
, [pure 2, pure 3]
, [pure 4, pure 5] ]
, GridLayout 2 3
[ (GridRange 0 1 0 1, 0), (GridRange 1 2 0 1, 1)
, (GridRange 0 1 1 2, 2), (GridRange 1 2 1 2, 3)
, (GridRange 0 1 2 3, 4), (GridRange 1 2 2 3, 5) ] )
, testCase "Rectangle (built non-sequentially)"
$ pure 0 │ pure 1
──
pure 2 │ pure 3 ┃ pure 4
──
pure 5
@?= GridDivisions [ [pure 0, pure 1, pure 4]
, [pure 2, pure 3, pure 5] ]
, testCase "Nonuniform last row"
$ pure 0 │ pure 1 │ pure 2
──
pure 3 │ pure 4 │ pure 5
──
pure 6 │ pure 7
=#?@= ( GridDivisions [ [GridDivisions [[pure 0,pure 1,pure 2]]]
, [GridDivisions [[pure 3,pure 4,pure 5]]]
, [GridDivisions [[pure 6 , pure 7]]] ]
, GridLayout 4 3
[ (GridRange 0 1 0 1, 0), (GridRange 1 3 0 1, 1), (GridRange 3 4 0 1, 2)
, (GridRange 0 1 1 2, 3), (GridRange 1 3 1 2, 4), (GridRange 3 4 1 2, 5)
, (GridRange 0 2 2 3, 6), (GridRange 2 4 2 3, 7) ] )
, testCase "Nonuniform first row"
$ pure 0 │ pure 1 │ pure 2
──
pure 3 │ pure 5
──
pure 6 │ pure 7
=#?@= (GridDivisions [[GridDivisions [[pure 0,pure 1,pure 2]]]
,[GridDivisions [[pure 3 , pure 5]
,[pure 6 , pure 7]]]]
, GridLayout 4 3
[ (GridRange 0 1 0 1, 0), (GridRange 1 3 0 1, 1), (GridRange 3 4 0 1, 2)
, (GridRange 0 2 1 2, 3), (GridRange 2 4 1 2, 5)
, (GridRange 0 2 2 3, 6), (GridRange 2 4 2 3, 7) ] )
]
, testGroup "JSON consistency"
[ QC.testProperty "Parsing back structure"
$ \g -> JSON.decode (JSON.encode g)
== Just (g :: Gridded ())
, QC.testProperty "Parsing back structure and values"
$ \g -> JSON.decode (JSON.encode g)
== Just (g :: Gridded Int)
]
]
]
instance (Arbitrary a) => Arbitrary (Gridded a) where
arbitrary = do
values <- arbitrary
arbGrid values
where arbGrid [] = do
emptyDir <- arbitrary
return . GridDivisions $ if emptyDir then [] else [[]]
arbGrid [v] = return $ GridRegion v
arbGrid values = GridDivisions <$> do
[width,height] <- replicateM 2
$ (+1) . (`mod`maxSize) . QC.getNonNegative <$> arbitrary
let portionSize = fromIntegral n / fromIntegral (width*height)
portions = splitPortns portionSize 0 0 values
rows = splitEach width portions
forM rows $ mapM arbGrid
where n = length values
maxSize = floor $ fromIntegral n
splitPortns _ _ _ [] = []
splitPortns pnSize pos ideal l
= case splitAt thisSize l of
(portion, rest) ->
portion : splitPortns pnSize (pos+thisSize) (ideal+pnSize) rest
where thisSize
| fromIntegral pos > ideal = floor pnSize
| otherwise = ceiling pnSize
splitEach _ [] = []
splitEach n l = case splitAt n l of
(portion,rest) -> portion : splitEach n rest
infix 1 =#?@=
(=#?@=) :: (Eq a, Show a) => Gridded a -> (Gridded a, GridLayout a) -> Assertion
a =#?@= b = (a, layoutGrid a) @?= b