content: {-
     Tests for connection establishment and athorization. It is assumed
     than these tests being executed with different settings in pg_hba.conf
  -}
  import Control.Exception (finally)
  import Data.Monoid ((<>))
  import Data.Foldable
  import qualified Data.ByteString as B
  import System.Process (callCommand)
  import Test.Tasty
  import Test.Tasty.HUnit
  
  import Database.PostgreSQL.Driver.Connection
  import Database.PostgreSQL.Driver.Settings
  
  main :: IO ()
  main = defaultMain $ testGroup "Postgres-wire"
      [ testConnection "Connection trust" confTrust
      , testConnection "Connection with password" confPassword
      , testConnection "Connection with md5" confPassword
      ]
  
  testConnection :: TestName -> B.ByteString -> TestTree
  testConnection name confContent = testCase name $ withPghba confContent $
      traverse_ connectAndClose
          [ defaultSettings { settingsHost = "" }
          , defaultSettings { settingsHost = "/var/run/postgresql" }
          , defaultSettings { settingsHost = "localhost" }
          ]
    where
      connectAndClose settings = connect settings >>= either (error . show) close
      defaultSettings = ConnectionSettings
          { settingsHost     = ""
          , settingsPort     = 5432
          , settingsDatabase = "test_connection"
          , settingsUser     = "test_postgres"
          , settingsPassword = "password"
          , settingsTls      = NoTls
          }
  
  pghbaFilename :: FilePath
  pghbaFilename = "/etc/postgresql/10/main/pg_hba.conf"
  
  withPghba :: B.ByteString -> IO a -> IO a
  withPghba confContent action = do
      oldContent <- B.readFile pghbaFilename
      B.writeFile pghbaFilename confContent
      (restart >> action) `finally`
          (B.writeFile pghbaFilename oldContent >> restart)
    where
      restart = callCommand "service postgresql restart"
  
  makeConf :: B.ByteString -> B.ByteString
  makeConf method =
       "local all   postgres                     peer\n"
    <> "local all   all                          " <> method <> "\n"
    <> "host  all   all             127.0.0.1/32 " <> method <> "\n"
    <> "host  all   all             ::1/128      " <> method <> "\n"
  
  confTrust :: B.ByteString
  confTrust = makeConf "trust"
  
  confPassword :: B.ByteString
  confPassword = makeConf "password"
  
  confMd5 :: B.ByteString
  confMd5 = makeConf "md5"
  
  