{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE TypeOperators #-}
module Squeal.PostgreSQL.Hspec
import Control.Exception
import Control.Monad
import Control.Monad.Base (liftBase)
+import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BSC
import qualified Database.Postgres.Temp as Temp
import Generics.SOP (K)
import Squeal.PostgreSQL
import Squeal.PostgreSQL.Pool
+import System.Environment (lookupEnv)
import Test.Hspec
data TestDB a = TestDB
- { tempDB :: Temp.DB
+ { tempDB :: Maybe Temp.DB
-- ^ Handle for temporary @postgres@ process
- , pool :: Pool a
+ , pool :: Pool a
-- ^ Pool of 50 connections to the temporary @postgres@
+ , connectionString :: ByteString
}
type Fixtures schema = (Pool (K Connection schema) -> IO ())
type Actions schema a = PoolPQ schema IO a
type SquealContext schema = TestDB (K Connection schema)
+testDBEnv :: String
+testDBEnv = "TEST_DB_CONNECTION_STRING"
+
+getOrCreateConnectionString :: IO (ByteString, Maybe Temp.DB)
+getOrCreateConnectionString = do
+ hasConnectionString <- lookupEnv testDBEnv
+ maybe createTempDB (pure . (, Nothing) . BSC.pack) hasConnectionString
+
+createTempDB :: IO (ByteString, Maybe Temp.DB)
+createTempDB = do
+ tempDB <- either throwIO return =<< Temp.startAndLogToTmp []
+ let connectionString = BSC.pack (Temp.connectionString tempDB)
+ pure (connectionString, Just tempDB)
+
-- | Start a temporary @postgres@ process and create a pool of connections to it
setupDB
:: AlignedList (Migration (Terminally PQ IO)) schema0 schema
-> Fixtures schema
-> IO (SquealContext schema)
setupDB migration fixtures = do
- tempDB <- either throwIO return =<< Temp.startAndLogToTmp []
- let connectionString = BSC.pack (Temp.connectionString tempDB)
- putStrLn $ Temp.connectionString tempDB
+ (connectionString, tempDB) <- getOrCreateConnectionString
+ BSC.putStrLn connectionString
let singleStripe = 1
keepConnectionForOneHour = 3600
poolSizeOfFifty = 50
pure TestDB {..}
-- | Drop all the connections and shutdown the @postgres@ process
-teardownDB :: TestDB a -> IO ()
-teardownDB TestDB {..} = do
+teardownDB
+ :: AlignedList (Migration (Terminally PQ IO)) schema0 schema
+ -> TestDB a
+ -> IO ()
+teardownDB migration TestDB {..} = do
+ withConnection connectionString (migrateDown migration)
destroyAllResources pool
- void $ Temp.stop tempDB
+ maybe (pure ()) (void . Temp.stop) tempDB
-- | Run an 'IO' action with a connection from the pool
withPool :: TestDB (K Connection schema) -> Actions schema a -> IO a
-> SpecWith (SquealContext schema)
-> Spec
describeDB migrate fixture str =
- beforeAll (setupDB migrate fixture) . afterAll teardownDB . describe str
+ beforeAll (setupDB migrate fixture) . afterAll (teardownDB migrate) . describe str