PgInit.hs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# OPTIONS_GHC -fno-warn-orphans #-}
  3. module PgInit (
  4. runConn
  5. , MonadIO
  6. , persistSettings
  7. , MkPersistSettings (..)
  8. , db
  9. , BackendKey(..)
  10. , GenerateKey(..)
  11. -- re-exports
  12. , module Control.Monad.Trans.Reader
  13. , module Control.Monad
  14. , module Database.Persist.Sql
  15. , module Database.Persist
  16. , module Database.Persist.Sql.Raw.QQ
  17. , module Init
  18. , module Test.Hspec
  19. , module Test.HUnit
  20. , BS.ByteString
  21. , Int32, Int64
  22. , liftIO
  23. , mkPersist, mkMigrate, share, sqlSettings, persistLowerCase, persistUpperCase
  24. , SomeException
  25. , Text
  26. , TestFn(..)
  27. ) where
  28. import Init
  29. ( TestFn(..), truncateTimeOfDay, truncateUTCTime
  30. , truncateToMicro, arbText, liftA2, GenerateKey(..)
  31. , (@/=), (@==), (==@), MonadFail
  32. , assertNotEqual, assertNotEmpty, assertEmpty, asIO
  33. , isTravis, RunDb
  34. )
  35. -- re-exports
  36. import Control.Exception (SomeException)
  37. import Control.Monad (void, replicateM, liftM, when, forM_)
  38. import Control.Monad.Trans.Reader
  39. import Data.Aeson (Value(..))
  40. import Database.Persist.TH (mkPersist, mkMigrate, share, sqlSettings, persistLowerCase, persistUpperCase, MkPersistSettings(..))
  41. import Database.Persist.Sql.Raw.QQ
  42. import Database.Persist.Postgresql.JSON()
  43. import Test.Hspec
  44. import Test.QuickCheck.Instances ()
  45. -- testing
  46. import Test.HUnit ((@?=),(@=?), Assertion, assertFailure, assertBool)
  47. import Test.QuickCheck
  48. import Control.Monad (unless, (>=>))
  49. import Control.Monad.IO.Class
  50. import Control.Monad.IO.Unlift (MonadUnliftIO)
  51. import Control.Monad.Logger
  52. import Control.Monad.Trans.Resource (ResourceT, runResourceT)
  53. import qualified Data.ByteString as BS
  54. import qualified Data.HashMap.Strict as HM
  55. import Data.Int (Int32, Int64)
  56. import Data.Maybe (fromMaybe)
  57. import Data.Monoid ((<>))
  58. import Data.Text (Text)
  59. import System.Environment (getEnvironment)
  60. import System.Log.FastLogger (fromLogStr)
  61. import Database.Persist
  62. import Database.Persist.Postgresql
  63. import Database.Persist.Sql
  64. import Database.Persist.TH ()
  65. _debugOn :: Bool
  66. _debugOn = False
  67. dockerPg :: IO (Maybe BS.ByteString)
  68. dockerPg = do
  69. env <- liftIO getEnvironment
  70. return $ case lookup "POSTGRES_NAME" env of
  71. Just _name -> Just "postgres" -- /persistent/postgres
  72. _ -> Nothing
  73. persistSettings :: MkPersistSettings
  74. persistSettings = sqlSettings { mpsGeneric = True }
  75. runConn :: MonadUnliftIO m => SqlPersistT (LoggingT m) t -> m ()
  76. runConn f = do
  77. travis <- liftIO isTravis
  78. let debugPrint = not travis && _debugOn
  79. let printDebug = if debugPrint then print . fromLogStr else void . return
  80. flip runLoggingT (\_ _ _ s -> printDebug s) $ do
  81. _ <- if travis
  82. then withPostgresqlPool "host=localhost port=5432 user=postgres dbname=persistent" 1 $ runSqlPool f
  83. else do
  84. host <- fromMaybe "localhost" <$> liftIO dockerPg
  85. withPostgresqlPool ("host=" <> host <> " port=5432 user=postgres dbname=test") 1 $ runSqlPool f
  86. return ()
  87. db :: SqlPersistT (LoggingT (ResourceT IO)) () -> Assertion
  88. db actions = do
  89. runResourceT $ runConn $ actions >> transactionUndo
  90. instance Arbitrary Value where
  91. arbitrary = frequency [ (1, pure Null)
  92. , (1, Bool <$> arbitrary)
  93. , (2, Number <$> arbitrary)
  94. , (2, String <$> arbText)
  95. , (3, Array <$> limitIt 4 arbitrary)
  96. , (3, Object <$> arbObject)
  97. ]
  98. where limitIt i x = sized $ \n -> do
  99. let m = if n > i then i else n
  100. resize m x
  101. arbObject = limitIt 4 -- Recursion can make execution divergent
  102. $ fmap HM.fromList -- HashMap -> [(,)]
  103. . listOf -- [(,)] -> (,)
  104. . liftA2 (,) arbText -- (,) -> Text and Value
  105. $ limitIt 4 arbitrary -- Again, precaution against divergent recursion.