generated from tpl/purs
154 lines
5.0 KiB
Haskell
154 lines
5.0 KiB
Haskell
module Test.Main
|
|
( main
|
|
) where
|
|
|
|
import Prelude
|
|
|
|
import Control.Monad.Aff (Aff, launchAff)
|
|
import Control.Monad.Aff.AVar (AVAR)
|
|
import Control.Monad.Aff.Console (CONSOLE)
|
|
import Control.Monad.Eff (Eff)
|
|
import Control.Monad.Eff.Class (liftEff)
|
|
import Control.Monad.Eff.Exception (EXCEPTION, error)
|
|
import Control.Monad.Eff.Now (NOW)
|
|
import Control.Monad.Error.Class (catchError, throwError, try)
|
|
import Data.DateTime.Instant (Instant, unInstant)
|
|
import Data.Decimal as D
|
|
import Data.Foldable (all)
|
|
import Data.JSDate (toInstant)
|
|
import Data.JSDate as JSDate
|
|
import Data.Maybe (Maybe(..), fromJust)
|
|
import Data.Newtype (unwrap)
|
|
import Database.PostgreSQL (Connection, POSTGRESQL, PoolConfiguration, Query(Query), Row0(Row0), Row1(Row1), Row2(Row2), Row3(Row3), Row9(Row9), execute, newPool, query, scalar, withConnection, withTransaction)
|
|
import Math ((%))
|
|
import Partial.Unsafe (unsafePartial)
|
|
import Test.Assert (ASSERT, assert)
|
|
import Test.Unit (suite)
|
|
import Test.Unit as Test.Unit
|
|
import Test.Unit.Console (TESTOUTPUT)
|
|
import Test.Unit.Main (runTest)
|
|
|
|
withRollback
|
|
:: ∀ eff
|
|
. Connection
|
|
-> Aff (postgreSQL :: POSTGRESQL | eff) Unit
|
|
-> Aff (postgreSQL :: POSTGRESQL | eff) Unit
|
|
withRollback conn action = do
|
|
execute conn (Query "BEGIN TRANSACTION") Row0
|
|
catchError (action >>= const rollback) (\e -> rollback >>= const (throwError e))
|
|
where
|
|
rollback = execute conn (Query "ROLLBACK") Row0
|
|
|
|
test
|
|
:: ∀ eff
|
|
. Connection
|
|
-> String
|
|
-> Aff ( postgreSQL :: POSTGRESQL | eff) Unit
|
|
-> Test.Unit.TestSuite (postgreSQL :: POSTGRESQL | eff)
|
|
test conn t a = Test.Unit.test t (withRollback conn a)
|
|
|
|
now :: ∀ eff. Eff (now :: NOW | eff) Instant
|
|
now = unsafePartial $ (fromJust <<< toInstant) <$> JSDate.now
|
|
|
|
main :: ∀ eff. Eff (assert :: ASSERT, avar :: AVAR, console :: CONSOLE, exception :: EXCEPTION, now :: NOW, postgreSQL :: POSTGRESQL, testOutput :: TESTOUTPUT | eff) Unit
|
|
main = void $ launchAff do
|
|
pool <- newPool config
|
|
withConnection pool \conn -> do
|
|
execute conn (Query """
|
|
CREATE TEMPORARY TABLE foods (
|
|
name text NOT NULL,
|
|
delicious boolean NOT NULL,
|
|
price NUMERIC(4,2) NOT NULL,
|
|
added TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (name)
|
|
)
|
|
""") Row0
|
|
|
|
liftEff $ runTest $ do
|
|
suite "Postgresql client" $ do
|
|
let
|
|
testCount n = do
|
|
count <- scalar conn (Query """
|
|
SELECT count(*) = $1
|
|
FROM foods
|
|
""") (Row1 n)
|
|
liftEff <<< assert $ count == Just true
|
|
|
|
Test.Unit.test "transaction commit" $ do
|
|
withTransaction conn do
|
|
execute conn (Query """
|
|
INSERT INTO foods (name, delicious, price)
|
|
VALUES ($1, $2, $3)
|
|
""") (Row3 "pork" true (D.fromString "8.30"))
|
|
testCount 1
|
|
testCount 1
|
|
execute conn (Query """
|
|
DELETE FROM foods
|
|
""") Row0
|
|
|
|
Test.Unit.test "transaction rollback" $ do
|
|
_ <- try $ withTransaction conn do
|
|
execute conn (Query """
|
|
INSERT INTO foods (name, delicious, price)
|
|
VALUES ($1, $2, $3)
|
|
""") (Row3 "pork" true (D.fromString "8.30"))
|
|
testCount 1
|
|
throwError $ error "fail"
|
|
testCount 0
|
|
|
|
let
|
|
insertFood =
|
|
execute conn (Query """
|
|
INSERT INTO foods (name, delicious, price)
|
|
VALUES ($1, $2, $3), ($4, $5, $6), ($7, $8, $9)
|
|
""") (Row9
|
|
"pork" true (D.fromString "8.30")
|
|
"sauerkraut" false (D.fromString "3.30")
|
|
"rookworst" true (D.fromString "5.60"))
|
|
test conn "select column subset" $ do
|
|
insertFood
|
|
names <- query conn (Query """
|
|
SELECT name, delicious
|
|
FROM foods
|
|
WHERE delicious
|
|
ORDER BY name ASC
|
|
""") Row0
|
|
liftEff <<< assert $ names == [Row2 "pork" true, Row2 "rookworst" true]
|
|
|
|
test conn "select default instant value" $ do
|
|
before <- liftEff $ (unwrap <<< unInstant) <$> now
|
|
insertFood
|
|
added <- query conn (Query """
|
|
SELECT added
|
|
FROM foods
|
|
""") Row0
|
|
after <- liftEff $ (unwrap <<< unInstant) <$> now
|
|
-- | timestamps are fetched without milliseconds so we have to
|
|
-- | round before value down
|
|
liftEff <<< assert $ all
|
|
(\(Row1 t) ->
|
|
( unwrap $ unInstant t) >= (before - before % 1000.0)
|
|
&& after >= (unwrap $ unInstant t))
|
|
added
|
|
|
|
test conn "select decimal" $ do
|
|
insertFood
|
|
sauerkrautPrice <- query conn (Query """
|
|
SELECT price
|
|
FROM foods
|
|
WHERE NOT delicious
|
|
""") Row0
|
|
liftEff <<< assert $ sauerkrautPrice == [Row1 (D.fromString "3.30")]
|
|
|
|
|
|
config :: PoolConfiguration
|
|
config =
|
|
{ user: "postgres"
|
|
, password: "lol123"
|
|
, host: "127.0.0.1"
|
|
, port: 5432
|
|
, database: "purspg"
|
|
, max: 10
|
|
, idleTimeoutMillis: 1000
|
|
}
|