nspace-0.2.0.0: test/OctTreeSpec.hs
{-# OPTIONS_GHC -Wno-orphans #-}
module OctTreeSpec where
import Data.Foldable
import Data.Monoid (Sum)
import Data.OctTree hiding (elements)
import Data.OctTree.Internal (cubeContainsPoint, Free(..))
import Data.Ratio
import Data.Semigroup (Any(..), Max(..))
import Data.Semilattice
import Prelude hiding (lookup)
import QuadTreeSpec ()
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
instance Arbitrary a => Arbitrary (Oct a) where
arbitrary = Oct <$> arbitrary <*> arbitrary
shrink = genericShrink
instance Arbitrary a => Arbitrary (Cube a) where
arbitrary = Cube <$> arbitrary <*> arbitrary
shrink = genericShrink
instance Arbitrary a => Arbitrary (V3 a) where
arbitrary = V3 <$> arbitrary <*> arbitrary <*> arbitrary
shrink = genericShrink
instance EqProp a => EqProp (OctTree a) where
q1 =-= q2 = property $ \a -> flip lookup q1 a =-= flip lookup q2 a
instance Arbitrary a => Arbitrary (Free a) where
arbitrary =
let terminal = [Fill <$> arbitrary]
in sized $ \n ->
case n <= 1 of
True -> oneof terminal
False -> oneof $
[ Split <$> Test.QuickCheck.scale (`div` 4) arbitrary
] <> terminal
shrink = genericShrink
instance Arbitrary a => Arbitrary (OctTree a) where
arbitrary = OctTree <$> arbitrary <*> elements [0..10] <*> arbitrary
observe :: OctTree a -> V3 Rational -> a
observe = flip lookup
propBatch :: String -> TestBatch -> Spec
propBatch s = describe s . traverse_ (uncurry prop) . unbatch
spec :: Spec
spec = modifyMaxSuccess (const 10000) $ do
prop "empty" $ \(a :: Int) ->
observe (pure a)
=-= const a
prop "fill" $ \r (a :: Int) q ->
observe (fill r a q)
=-= \p -> if cubeContainsPoint r p then a else observe q p
prop "fuse" $ \(q :: OctTree (Sum Int)) ->
observe (fuse q)
=-= observe q
prop "query" $ \(applyFun -> f :: Bool -> Any) q x y z w h d ->
let r = Cube (V3 x y z) (V3 w h d) in
query f r q =-= f (lookup (midpoint r) q) /\
foldr1 (/\) ((flip (query f) q) <$> subdivide r)
prop "tocubes" $ \(ot :: OctTree Int) -> do
ot =-= foldr (uncurry fill) (pure $ defaultValue ot) (toCubes ot)
prop "mempty" $
observe (mempty @(OctTree (Sum Int)))
=-= mempty
prop "<>" $ \(q1 :: OctTree (Sum Int)) q2 ->
observe (q1 <> q2)
=-= observe q1 <> observe q2
propBatch "OctTree Semigroup" $ semigroup ((0 :: Max Int), (0 :: Int))
propBatch "OctTree Monoid" $ monoid ((0 :: Max Int), ([] :: [Int]))
propBatch "OctTree Applicative" $ applicative (undefined :: OctTree (Int, Int, Int))