hasql/tasty/Main.hs

418 lines
14 KiB
Haskell
Raw Normal View History

2015-11-10 21:19:41 +03:00
module Main where
2016-01-22 18:43:15 +03:00
import Main.Prelude hiding (assert)
2015-11-10 21:19:41 +03:00
import Test.QuickCheck.Instances
import Test.Tasty
2015-12-06 07:06:31 +03:00
import Test.Tasty.Runners
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck
2015-11-10 21:19:41 +03:00
import qualified Test.QuickCheck as QuickCheck
2015-12-06 07:06:31 +03:00
import qualified Main.Queries as Queries
2015-11-15 12:13:45 +03:00
import qualified Main.DSL as DSL
2016-01-24 19:15:11 +03:00
import qualified Main.Connection as Connection
2015-11-22 10:10:21 +03:00
import qualified Hasql.Query as Query
2015-12-05 09:09:31 +03:00
import qualified Hasql.Encoders as Encoders
import qualified Hasql.Decoders as Decoders
2016-01-22 18:43:15 +03:00
import qualified Hasql.Session as Session
2015-11-10 21:19:41 +03:00
main =
defaultMain tree
tree =
2015-12-06 07:06:31 +03:00
localOption (NumThreads 1) $
2015-11-15 12:13:45 +03:00
testGroup "All tests"
2015-11-10 21:19:41 +03:00
[
testCase "IN simulation" $
let
query =
Query.statement "select true where 1 = any ($1)" encoder decoder True
where
encoder =
Encoders.value (Encoders.array (Encoders.arrayDimension foldl' (Encoders.arrayValue Encoders.int8)))
decoder =
fmap (maybe False (const True)) (Decoders.maybeRow (Decoders.value Decoders.bool))
session =
do
result1 <- Session.query [1, 2] query
result2 <- Session.query [2, 3] query
return (result1, result2)
in do
x <- Connection.with (Session.run session)
assertEqual (show x) (Right (Right (True, False))) x
,
testCase "NOT IN simulation" $
let
query =
Query.statement "select true where 3 <> all ($1)" encoder decoder True
where
encoder =
Encoders.value (Encoders.array (Encoders.arrayDimension foldl' (Encoders.arrayValue Encoders.int8)))
decoder =
fmap (maybe False (const True)) (Decoders.maybeRow (Decoders.value Decoders.bool))
session =
do
result1 <- Session.query [1, 2] query
result2 <- Session.query [2, 3] query
return (result1, result2)
in do
x <- Connection.with (Session.run session)
assertEqual (show x) (Right (Right (True, False))) x
,
2016-10-01 15:34:44 +03:00
testCase "Composite decoding" $
let
query =
Query.statement sql encoder decoder True
where
sql =
"select (1, true)"
encoder =
Encoders.unit
decoder =
Decoders.singleRow (Decoders.value (Decoders.composite ((,) <$> Decoders.compositeValue Decoders.int8 <*> Decoders.compositeValue Decoders.bool)))
session =
Session.query () query
in do
x <- Connection.with (Session.run session)
assertEqual (show x) (Right (Right (1, True))) x
,
2016-12-08 21:46:24 +03:00
testCase "Complex composite decoding" $
let
query =
Query.statement sql encoder decoder True
where
sql =
"select (1, true) as entity1, ('hello', 3) as entity2"
encoder =
Encoders.unit
decoder =
2016-12-09 11:34:26 +03:00
Decoders.singleRow $
(,) <$> Decoders.value entity1 <*> Decoders.value entity2
where
entity1 =
Decoders.composite $
(,) <$> Decoders.compositeValue Decoders.int8 <*> Decoders.compositeValue Decoders.bool
entity2 =
Decoders.composite $
(,) <$> Decoders.compositeValue Decoders.text <*> Decoders.compositeValue Decoders.int8
2016-12-08 21:46:24 +03:00
session =
Session.query () query
in do
x <- Connection.with (Session.run session)
assertEqual (show x) (Right (Right ((1, True), ("hello", 3)))) x
,
2016-04-12 22:16:57 +03:00
testCase "Empty array" $
let
io =
do
x <- Connection.with (Session.run session)
assertEqual (show x) (Right (Right [])) x
where
session =
Session.query () query
where
query =
Query.statement sql encoder decoder True
where
sql =
"select array[]::int8[]"
encoder =
Encoders.unit
decoder =
Decoders.singleRow (Decoders.value (Decoders.array (Decoders.arrayDimension replicateM (Decoders.arrayValue Decoders.int8))))
in io
,
2016-02-26 14:11:30 +03:00
testCase "Failing prepared statements" $
let
io =
Connection.with (Session.run session) >>=
(assertBool <$> show <*> resultTest)
where
resultTest =
\case
Right (Left (Session.ResultError (Session.ServerError "26000" _ _ _))) -> False
_ -> True
session =
catchError session (const (pure ())) *> session
where
session =
Session.query () query
where
query =
Query.statement sql encoder decoder True
where
sql =
"absurd"
encoder =
Encoders.unit
decoder =
Decoders.unit
in io
,
2016-02-23 09:41:23 +03:00
testCase "Prepared statements after error" $
let
io =
Connection.with (Session.run session) >>=
\x -> assertBool (show x) (either (const False) isRight x)
where
session =
try *> fail *> try
where
try =
Session.query 1 query
where
query =
Query.statement sql encoder decoder True
where
sql =
"select $1 :: int8"
encoder =
Encoders.value Encoders.int8
decoder =
Decoders.singleRow $ Decoders.value Decoders.int8
fail =
catchError (Session.sql "absurd") (const (pure ()))
in io
,
2016-01-24 19:15:11 +03:00
testCase "\"in progress after error\" bugfix" $
let
sumQuery :: Query.Query (Int64, Int64) Int64
sumQuery =
Query.statement sql encoder decoder True
where
sql =
"select ($1 + $2)"
encoder =
contramap fst (Encoders.value Encoders.int8) <>
contramap snd (Encoders.value Encoders.int8)
decoder =
Decoders.singleRow (Decoders.value Decoders.int8)
sumSession :: Session.Session Int64
sumSession =
Session.sql "begin" *> Session.query (1, 1) sumQuery <* Session.sql "end"
errorSession :: Session.Session ()
errorSession =
Session.sql "asldfjsldk"
io =
Connection.with $ \c -> do
Session.run errorSession c
Session.run sumSession c
in io >>= \x -> assertBool (show x) (either (const False) isRight x)
,
2016-01-22 18:43:15 +03:00
testCase "\"another command is already in progress\" bugfix" $
let
sumQuery :: Query.Query (Int64, Int64) Int64
sumQuery =
Query.statement sql encoder decoder True
where
sql =
"select ($1 + $2)"
encoder =
contramap fst (Encoders.value Encoders.int8) <>
contramap snd (Encoders.value Encoders.int8)
decoder =
Decoders.singleRow (Decoders.value Decoders.int8)
session :: Session.Session Int64
session =
do
Session.sql "begin;"
s <- Session.query (1,1) sumQuery
Session.sql "end;"
return s
2016-01-24 19:15:11 +03:00
in DSL.session session >>= \x -> assertEqual (show x) (Right 2) x
2016-01-22 18:43:15 +03:00
,
2015-12-06 07:06:31 +03:00
testCase "Executing the same query twice" $
pure ()
,
testCase "Interval Encoding" $
let
actualIO =
DSL.session $ do
let
query =
Query.statement sql encoder decoder True
where
sql =
"select $1 = interval '10 seconds'"
decoder =
(Decoders.singleRow (Decoders.value (Decoders.bool)))
encoder =
Encoders.value (Encoders.interval)
in DSL.query (10 :: DiffTime) query
in actualIO >>= \x -> assertEqual (show x) (Right True) x
,
testCase "Interval Decoding" $
let
actualIO =
DSL.session $ do
let
query =
Query.statement sql encoder decoder True
where
sql =
"select interval '10 seconds'"
decoder =
(Decoders.singleRow (Decoders.value (Decoders.interval)))
encoder =
Encoders.unit
in DSL.query () query
in actualIO >>= \x -> assertEqual (show x) (Right (10 :: DiffTime)) x
,
testCase "Interval Encoding/Decoding" $
let
actualIO =
DSL.session $ do
let
query =
Query.statement sql encoder decoder True
where
sql =
"select $1"
decoder =
(Decoders.singleRow (Decoders.value (Decoders.interval)))
encoder =
Encoders.value (Encoders.interval)
in DSL.query (10 :: DiffTime) query
in actualIO >>= \x -> assertEqual (show x) (Right (10 :: DiffTime)) x
,
2016-01-13 16:15:35 +03:00
testCase "Unknown" $
let
actualIO =
DSL.session $ do
let
query =
Query.statement sql mempty Decoders.unit True
where
sql =
"drop type if exists mood"
in DSL.query () query
let
query =
Query.statement sql mempty Decoders.unit True
where
sql =
"create type mood as enum ('sad', 'ok', 'happy')"
in DSL.query () query
let
query =
Query.statement sql encoder decoder True
where
sql =
"select $1 = ('ok' :: mood)"
decoder =
(Decoders.singleRow (Decoders.value (Decoders.bool)))
encoder =
Encoders.value (Encoders.unknown)
in DSL.query "ok" query
in actualIO >>= assertEqual "" (Right True)
,
2015-12-06 07:06:31 +03:00
testCase "Enum" $
2015-11-15 12:13:45 +03:00
let
2015-12-06 07:06:31 +03:00
actualIO =
2015-11-15 12:13:45 +03:00
DSL.session $ do
let
query =
2015-12-21 16:11:14 +03:00
Query.statement sql mempty Decoders.unit True
2015-11-15 12:13:45 +03:00
where
sql =
"drop type if exists mood"
in DSL.query () query
let
query =
2015-12-21 16:11:14 +03:00
Query.statement sql mempty Decoders.unit True
2015-11-15 12:13:45 +03:00
where
sql =
"create type mood as enum ('sad', 'ok', 'happy')"
in DSL.query () query
let
query =
2015-12-21 16:11:14 +03:00
Query.statement sql encoder decoder True
2015-11-15 12:13:45 +03:00
where
sql =
"select ($1 :: mood)"
2015-11-21 13:36:01 +03:00
decoder =
2015-12-05 09:09:31 +03:00
(Decoders.singleRow (Decoders.value (Decoders.enum (Just . id))))
2015-11-21 13:36:01 +03:00
encoder =
2015-12-05 09:09:31 +03:00
Encoders.value (Encoders.enum id)
2015-11-15 12:13:45 +03:00
in DSL.query "ok" query
2015-12-06 07:06:31 +03:00
in actualIO >>= assertEqual "" (Right "ok")
2015-11-15 12:13:45 +03:00
,
2015-12-06 07:06:31 +03:00
testCase "The same prepared statement used on different types" $
2015-11-15 12:13:45 +03:00
let
2015-12-06 07:06:31 +03:00
actualIO =
2015-11-15 12:13:45 +03:00
DSL.session $ do
let
effect1 =
DSL.query "ok" query
where
query =
2015-12-21 16:11:14 +03:00
Query.statement sql encoder decoder True
2015-11-15 12:13:45 +03:00
where
sql =
"select $1"
2015-11-21 13:36:01 +03:00
encoder =
2015-12-05 09:09:31 +03:00
Encoders.value Encoders.text
2015-11-21 13:36:01 +03:00
decoder =
2015-12-05 09:09:31 +03:00
(Decoders.singleRow (Decoders.value (Decoders.text)))
2015-11-15 12:13:45 +03:00
effect2 =
DSL.query 1 query
where
query =
2015-12-21 16:11:14 +03:00
Query.statement sql encoder decoder True
2015-11-15 12:13:45 +03:00
where
sql =
"select $1"
2015-11-21 13:36:01 +03:00
encoder =
2015-12-05 09:09:31 +03:00
Encoders.value Encoders.int8
2015-11-21 13:36:01 +03:00
decoder =
2015-12-05 09:09:31 +03:00
(Decoders.singleRow (Decoders.value Decoders.int8))
2015-11-15 12:13:45 +03:00
in (,) <$> effect1 <*> effect2
2015-12-06 07:06:31 +03:00
in actualIO >>= assertEqual "" (Right ("ok", 1))
2015-11-15 12:13:45 +03:00
,
2015-12-06 07:06:31 +03:00
testCase "Affected rows counting" $
replicateM_ 13 $
2015-11-15 12:13:45 +03:00
let
2015-12-06 07:06:31 +03:00
actualIO =
2015-11-15 12:13:45 +03:00
DSL.session $ do
dropTable
createTable
replicateM_ 100 insertRow
deleteRows <* dropTable
where
dropTable =
DSL.query () $ Queries.plain $
"drop table if exists a"
createTable =
DSL.query () $ Queries.plain $
"create table a (id bigserial not null, name varchar not null, primary key (id))"
insertRow =
DSL.query () $ Queries.plain $
"insert into a (name) values ('a')"
deleteRows =
2015-12-21 16:11:14 +03:00
DSL.query () $ Query.statement sql def decoder False
2015-11-15 12:13:45 +03:00
where
sql =
"delete from a"
2015-11-21 13:36:01 +03:00
decoder =
2015-12-05 09:09:31 +03:00
Decoders.rowsAffected
2015-12-06 07:06:31 +03:00
in actualIO >>= assertEqual "" (Right 100)
2015-11-15 12:13:45 +03:00
,
2015-12-06 07:06:31 +03:00
testCase "Result of an auto-incremented column" $
2015-11-15 12:13:45 +03:00
let
actualIO =
DSL.session $ do
DSL.query () $ Queries.plain $ "drop table if exists a"
DSL.query () $ Queries.plain $ "create table a (id serial not null, v char not null, primary key (id))"
2015-12-21 16:11:14 +03:00
id1 <- DSL.query () $ Query.statement "insert into a (v) values ('a') returning id" def (Decoders.singleRow (Decoders.value Decoders.int4)) False
id2 <- DSL.query () $ Query.statement "insert into a (v) values ('b') returning id" def (Decoders.singleRow (Decoders.value Decoders.int4)) False
2015-11-15 12:13:45 +03:00
DSL.query () $ Queries.plain $ "drop table if exists a"
pure (id1, id2)
2015-12-06 07:06:31 +03:00
in assertEqual "" (Right (1, 2)) =<< actualIO
2015-11-18 22:56:36 +03:00
,
2015-12-06 07:06:31 +03:00
testCase "List decoding" $
2015-11-18 22:56:36 +03:00
let
actualIO =
DSL.session $ DSL.query () $ Queries.selectList
2016-10-01 15:34:44 +03:00
in assertEqual "" (Right [(1, 2), (3, 4), (5, 6)]) =<< actualIO
2015-11-10 21:19:41 +03:00
]
2015-11-15 12:13:45 +03:00