packages feed

postgis-trivial-0.0.1.0: test/Tests/Storable.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-orphans #-}

module Tests.Storable where

import GHC.Base
import GHC.Show ( Show(..) )
import Foreign.Storable.Record as Store
import Foreign.Storable ( Storable (..) )
import Control.Exception ( bracket )
import Data.List ( length )
import qualified Data.Vector.Storable as VS
import Test.HUnit
import Database.PostgreSQL.Simple

import Database.Postgis.Trivial.Storable
import Data.ByteString (ByteString)


-- type InnerData = VS.Vector P2D

data GeoDuo = GeoDuo
        { dx :: !Double
        , dy :: !Double
        } deriving (Show, Eq)

storeGeoDuo :: Store.Dictionary GeoDuo
storeGeoDuo = Store.run $
    liftA2 GeoDuo
        (Store.element dx)
        (Store.element dy)

instance Storable GeoDuo where
   sizeOf = Store.sizeOf storeGeoDuo
   alignment = Store.alignment storeGeoDuo
   peek = Store.peek storeGeoDuo
   poke = Store.poke storeGeoDuo

type instance Cast GeoDuo = P2DS

instance Castable GeoDuo where
    toPointND (GeoDuo y x) = Point2DS x y
    fromPointND (Point2DS x y) = GeoDuo y x

type SomeData = VS.Vector GeoDuo


data GeoTrio = GeoTrio
        { tx :: !Double
        , ty :: !Double
        , tz :: !Double
        } deriving (Show, Eq)

storeGeoTrio :: Store.Dictionary GeoTrio
storeGeoTrio = Store.run $
    liftA3 GeoTrio
        (Store.element tx)
        (Store.element ty)
        (Store.element tz)

instance Storable GeoTrio where
   sizeOf = Store.sizeOf storeGeoTrio
   alignment = Store.alignment storeGeoTrio
   peek = Store.peek storeGeoTrio
   poke = Store.poke storeGeoTrio

type instance Cast GeoTrio = P3DZS

instance Castable GeoTrio where
    toPointND (GeoTrio x y z) = Point3DZS x y z
    fromPointND (Point3DZS x y z) = GeoTrio x y z

type SomeDataZ = VS.Vector GeoTrio

tMutability ::Test
tMutability = TestList
    [ "safe update" ~:
        VS.fromList [Point2DS 1 2, Point2DS 1.5 2.5, Point2DS 2.5 3, Point2DS 1 2] VS.//
            [(2, Point2DS 2 13), (0, Point2DS 10 2)]
        ~?= VS.fromList [Point2DS 10 2, Point2DS 1.5 2.5, Point2DS 2 13, Point2DS 1 2]
    , "unsafe update" ~:
        VS.unsafeUpd
            (VS.fromList [Point2DS 1 2, Point2DS 1.5 2.5, Point2DS 2.5 3, Point2DS 1 2])
            [(2, Point2DS 2 13), (0, Point2DS 10 2)]
        ~?= VS.fromList [Point2DS 10 2, Point2DS 1.5 2.5, Point2DS 2 13, Point2DS 1 2]
    ]

tInsSel :: ByteString -> Test
tInsSel dbconn = TestList
    [ "linestring (2D, Unboxed Vector)" ~: bracket
        (connectPostgreSQL dbconn) close
        (\conn -> do
            let srid = Just 3785 :: SRID
                ls0 = VS.fromList [Point2DS 1 2, Point2DS 1.5 2.5, Point2DS 2.5 3, Point2DS 1 2]
            _ <- execute_ conn "TRUNCATE linestrings"
            _ <- execute conn "INSERT INTO linestrings (geom) VALUES (?)"
                (Only (putLS srid ls0))
            [Only res] <- query_ conn "SELECT * FROM linestrings"
            let (srid', ls0') = getLS res
            _ <- execute_ conn "TRUNCATE linestrings"
            VS.length ls0'==VS.length ls0 && srid'==srid && ls0'==ls0 @?= True
        )
    , "linestring (2D, Unboxed Vector)" ~: bracket
        (connectPostgreSQL dbconn) close
        (\conn -> do
            let srid = Just 3785 :: SRID
                ls0 = VS.fromList [GeoDuo 1 2, GeoDuo 1.5 2.5, GeoDuo 2.5 3, GeoDuo 1 2]
            _ <- execute_ conn "TRUNCATE linestrings"
            _ <- execute conn "INSERT INTO linestrings (geom) VALUES (?)"
                (Only (putLS srid ls0))
            [Only res] <- query_ conn "SELECT * FROM linestrings"
            let (srid', ls0') = getLS res
            _ <- execute_ conn "TRUNCATE linestrings"
            VS.length ls0'==VS.length ls0 && srid'==srid && ls0'==ls0 @?= True
        )
    , "linestring (3D, Unboxed Vector)" ~: bracket
        (connectPostgreSQL dbconn) close
        (\conn -> do
            let srid = Just 3785 :: SRID
                ls0 = VS.fromList [GeoTrio 1 2 0, GeoTrio 1.5 2.5 10, GeoTrio 2.5 3 20, GeoTrio 1 2 30]
            _ <- execute_ conn "TRUNCATE linestringZs"
            _ <- execute conn "INSERT INTO linestringZs (geom) VALUES (?)"
                (Only (putLS srid ls0))
            [Only res] <- query_ conn "SELECT * FROM linestringZs"
            let (srid', ls0') = getLS res
            _ <- execute_ conn "TRUNCATE linestringZs"
            VS.length ls0'==VS.length ls0 && srid'==srid && ls0'==ls0 @?= True
        )
    , "multilinestring" ~: bracket
        (connectPostgreSQL dbconn) close
        (\conn -> do
            let srid = Just 3785 :: SRID
                mls0 =
                    [ VS.fromList [GeoDuo 1 2, GeoDuo 1.5 2.5, GeoDuo 2.5 3, GeoDuo 1 2]
                    , VS.fromList []
                    , VS.fromList [GeoDuo 1 2] ]
            _ <- execute_ conn "TRUNCATE multilinestrings"
            _ <- execute conn "INSERT INTO multilinestrings (geom) VALUES (?)"
                (Only (putMLS srid mls0))
            [Only res] <- query_ conn "SELECT * FROM multilinestrings"
            let (srid', mls0'::[SomeData]) = getMLS res
            _ <- execute_ conn "TRUNCATE multilinestrings"
            length mls0'==length mls0 && srid'==srid && mls0'==mls0 @?= True
        )
    ]