point-octree-0.5.5.3: tests/PropTests/OctreeTests/Exposed.hs
{- |
Module : PropTests.OctreeTests.Exposed
Copyright : Copyright (c) 2016 Michal J. Gajda
License : BSD3
Maintainer : Michael Litchard
Stability : experimental
Portability: not portable
This module provides the property tests for exposed octree functions.
-}
{-# LANGUAGE ScopedTypeVariables #-}
module PropTests.OctreeTests.Exposed
( prop_lookup
, prop_fromToList
, prop_insertionPreserved
, prop_nearest
, prop_naiveWithinRange
, prop_fmap1
, prop_fmap2
, prop_fmap3
, prop_depth_empty
, prop_depth_upper_bound
, prop_size
) where
import Prelude hiding(lookup)
import Data.List(sort, sortBy)
import Data.Vector.Class
import Control.Arrow(second)
import Data.Octree.Internal
import Data.Octree() -- test that interface module is not broken
import PropTests.Common
prop_lookup :: [(Vector3, Int)] -> Bool
prop_lookup l = all isIn l
where
ot = fromList l
isIn x = lookup ot (fst x) == Just x
prop_fromToList :: [(Vector3, Int)] -> Bool
prop_fromToList l = sort l == (sort . toList . fromList $ l)
prop_insertionPreserved :: [(Vector3, Int)] -> Bool
prop_insertionPreserved l =
sort l == (sort . toList . foldr insert (Leaf []) $ l)
prop_nearest :: [(Vector3, Int)] -> Vector3 -> Bool
prop_nearest l pt = nearest (fromList l) pt == naiveNearest pt l
prop_naiveWithinRange r l pt =
naiveWithinRange r pt l == testPoints
where
testPoints =
sort . map fst . (\o -> withinRange o r pt) . fromList . tuplify pt $ l
tuplify pt = map (\a -> (a, dist pt a))
compareDistance pt (a,_) (b,_) = compare (dist pt a) (dist pt b)
naiveNearest pt [] = Nothing
naiveNearest pt l = Just $ head byDist
where byDist = sortBy (compareDistance pt) l
naiveWithinRange r pt = sort . filter withinRange
where withinRange p = dist pt p <= r
-- unfortunately there is no Arbitrary for (a -> b)
-- since generic properties are quite common, I wonder how to force Quickcheck to default something reasonable?
prop_fmap1,prop_fmap2 :: [(Vector3, Int)] -> Bool
prop_fmap1 = genericPropertyFmap (+1)
prop_fmap2 = genericPropertyFmap (*2)
prop_fmap3 = genericPropertyFmap (show :: Int -> String)
genericPropertyFmap f l =
(sort . map (Control.Arrow.second f) $ l) == fmapTest
where fmapTest = sort . toList . fmap f . fromList $ l
prop_depth_empty = depth (Leaf []) == 0
prop_depth_upper_bound :: [(Vector3, Int)] -> Bool
prop_depth_upper_bound l =
depth ot <= max 0 (ceiling . logBase 2 . realToFrac $ size) -- worst splitting ratio possible when we take midpoint (and inputs are colinear)
where
ot = fromList l
size = length l
prop_size :: [(Vector3, Int)] -> Bool
prop_size l = size (fromList l) == length l