packages feed

hpqtypes-effectful-1.1.0.0: test/Main.hs

{-# LANGUAGE OverloadedStrings #-}

module Main (main) where

import Control.Monad (void)
import Data.Int (Int32)
import Data.Text qualified as T
import Effectful
import Effectful.Exception
import Effectful.HPQTypes
import System.Environment (lookupEnv)
import Test.Tasty
import Test.Tasty.HUnit

main :: IO ()
main = defaultMain tests

tests :: TestTree
tests =
  testGroup
    "tests"
    [ testCase "test getLastQuery" testGetLastQuery
    , testCase "test withFrozenLastQuery" testWithFrozenLastQuery
    , testCase "test connection stats retrieval with new connection" testConnectionStatsWithNewConnection
    ]

testGetLastQuery :: Assertion
testGetLastQuery = do
  dbUrl <- getConnString
  let connectionSource = simpleSource $ defaultConnectionSettings {csConnInfo = dbUrl}
  void . runEff . runDB (unConnectionSource connectionSource) defaultTransactionSettings $ do
    do
      -- Run the first query and perform some basic sanity checks
      let sql = "SELECT 1"
      rowNo <- runSQL sql
      liftIO $ assertEqual "One row should be retrieved" 1 rowNo
      result <- fetchMany (runIdentity @Int32)
      liftIO $ assertEqual "Result should be [1]" [1] result
      (_, SomeSQL lastQuery) <- getLastQuery
      liftIO $ assertEqual "SQL don't match" (show sql) (show lastQuery)
    do
      -- Run the second query and check that `getLastQuery` gives updated result
      let newSQL = "SELECT 2"
      runSQL_ newSQL
      (_, SomeSQL newLastQuery) <- getLastQuery
      liftIO $ assertEqual "SQL don't match" (show newSQL) (show newLastQuery)

testWithFrozenLastQuery :: Assertion
testWithFrozenLastQuery = do
  dbUrl <- getConnString
  let connectionSource = simpleSource $ defaultConnectionSettings {csConnInfo = dbUrl}
  void . runEff . runDB (unConnectionSource connectionSource) defaultTransactionSettings $ do
    let sql = "SELECT 1"
    runSQL_ sql
    withFrozenLastQuery $ do
      runSQL_ "SELECT 2"
      (_, SomeSQL lastQuery) <- getLastQuery
      liftIO $ assertEqual "The last query before freeze should be reported" (show sql) (show lastQuery)
    (_, SomeSQL lastQuery) <- getLastQuery
    liftIO $ assertEqual "The last query before freeze should be reported" (show sql) (show lastQuery)

testConnectionStatsWithNewConnection :: Assertion
testConnectionStatsWithNewConnection = do
  dbUrl <- getConnString
  let connectionSource = simpleSource $ defaultConnectionSettings {csConnInfo = dbUrl}
  void . runEff . runDB (unConnectionSource connectionSource) defaultTransactionSettings $ do
    runSQL_ "SELECT 1"
    runSQL_ "SELECT 2"
    stats <- getConnectionStats
    liftIO $ assertEqual "Incorrect statsQueries" 2 $ statsQueries stats
    unsafeWithoutTransaction
      . bracket_
        (runSQL_ "CREATE TABLE some_table (field INT)")
        (runSQL_ "DROP TABLE some_table")
      $ do
        runSQL_ "BEGIN"
        runSQL_ "INSERT INTO some_table VALUES (1)"
        withNewConnection $ do
          newStats <- getConnectionStats
          liftIO $ assertEqual "Connection stats should be reset" 0 $ statsQueries newStats
          noOfResults <- runSQL "SELECT * FROM some_table"
          liftIO $ assertEqual "Results should not be visible yet" 0 noOfResults
        runSQL_ "COMMIT"
        noOfResults <- runSQL "SELECT * FROM some_table"
        liftIO $ assertEqual "Results should be visible" 1 noOfResults

----------------------------------------
-- Helpers

getConnString :: IO T.Text
getConnString =
  lookupEnv "GITHUB_ACTIONS" >>= \case
    Just "true" -> pure . T.pack $ "host=postgres user=postgres password=postgres"
    _ -> do
      lookupEnv "DATABASE_URL" >>= \case
        Just url -> pure $ T.pack url
        Nothing -> error "DATABASE_URL environment variable is not set"