content: {-# LANGUAGE ScopedTypeVariables #-}
  
  module MysqlTests(tests)  where
  
  import qualified BinaryRow
  import qualified BinaryRowNew
  import qualified BinLog
  import qualified BinLogNew
  import           Control.Concurrent    (forkIO, threadDelay)
  import           Control.Exception     (bracket, catch)
  import           Control.Monad
  import qualified Data.ByteString       as B
  import           Database.MySQL.Base
  import           Database.MySQL.BinLog
  import           System.Environment
  import qualified System.IO.Streams as Stream
  import           Test.Tasty
  import           Test.Tasty.HUnit
  import qualified TextRow
  import qualified ExecuteMany
  import qualified TextRowNew
  
  tests :: TestTree
  tests = testCaseSteps "mysql-haskell test suit" $ \step -> do
  
      step "preparing table..."
      (greet, c) <- connectDetail defaultConnectInfo {ciUser = "testMySQLHaskell", ciDatabase = "testMySQLHaskell"}
  
      let ver = greetingVersion greet
          isNew = "5.6" `B.isPrefixOf` ver
                  || "5.7" `B.isPrefixOf` ver  -- from MySQL 5.6.4 and up
                                               -- TIME, DATETIME, and TIMESTAMP support fractional seconds
  
  
      execute_ c "DROP TABLE IF EXISTS test"
      execute_ c "DROP TABLE IF EXISTS test_new"
  
      execute_ c  "CREATE TABLE test(\
                  \__id           INT,\
                  \__bit          BIT(16),\
                  \__tinyInt      TINYINT,\
                  \__tinyIntU     TINYINT UNSIGNED,\
                  \__smallInt     SMALLINT,\
                  \__smallIntU    SMALLINT UNSIGNED,\
                  \__mediumInt    MEDIUMINT,\
                  \__mediumIntU   MEDIUMINT UNSIGNED,\
                  \__int          INT,\
                  \__intU         INT UNSIGNED,\
                  \__bigInt       BIGINT,\
                  \__bigIntU      BIGINT UNSIGNED,\
                  \__decimal      DECIMAL(20,10),\
                  \__float        FLOAT,\
                  \__double       DOUBLE,\
                  \__date         DATE,\
                  \__datetime     DATETIME,\
                  \__timestamp    TIMESTAMP NULL,\
                  \__time         TIME,\
                  \__year         YEAR(4),\
                  \__char         CHAR(8),\
                  \__varchar      VARCHAR(1024),\
                  \__binary       BINARY(8),\
                  \__varbinary    VARBINARY(1024),\
                  \__tinyblob     TINYBLOB,\
                  \__tinytext     TINYTEXT,\
                  \__blob         BLOB(1000000),\
                  \__text         TEXT(1000000),\
                  \__enum         ENUM('foo', 'bar', 'qux'),\
                  \__set          SET('foo', 'bar', 'qux')\
                  \) CHARACTER SET utf8"
  
      resetTestTable c
  
      step "testing executeMany"
      ExecuteMany.tests c
  
      resetTestTable c
  
      step "testing text protocol"
      TextRow.tests c
  
      resetTestTable c
  
      step "testing binary protocol"
      BinaryRow.tests c
  
      resetTestTable c
  
  
      when isNew $ do
          execute_ c "CREATE TABLE test_new(\
                     \__id           INT,\
                     \__datetime     DATETIME(2),\
                     \__timestamp    TIMESTAMP(4) NULL,\
                     \__time         TIME(6)\
                     \) CHARACTER SET utf8"
  
          resetTest57Table c
  
          step "testing MySQL5.7 extra text protocol"
          TextRowNew.tests c
  
          resetTest57Table c
  
          step "testing MySQL5.7 extra binary protocol"
          BinaryRowNew.tests c
  
          void $ resetTest57Table c
  
      step "testing binlog protocol"
  
      if isNew
      then do
          forkIO BinLogNew.eventProducer
          BinLogNew.tests c
      else do
          forkIO BinLog.eventProducer
          BinLog.tests c
  
      close c
  
      (greet, c) <- connectDetail defaultConnectInfo {ciUser = "testMySQLHaskell", ciDatabase = "testMySQLHaskell"}
      execute_ c "SET PASSWORD = PASSWORD('123456abcdefg???')"
      close c
  
      let loginFailMsg = "ERRException (ERR {errCode = 1045, errState = \"28000\", \
              \errMsg = \"Access denied for user 'testMySQLHaskell'@'localhost' (using password: YES)\"})"
  
      (greet, c) <- connectDetail
          defaultConnectInfo {ciUser = "testMySQLHaskell", ciDatabase = "testMySQLHaskell", ciPassword = "123456abcdefg???"}
      execute_ c "SET PASSWORD = PASSWORD('')"
      close c
  
      catch
          (void $ connectDetail
                      defaultConnectInfo
                          {ciUser = "testMySQLHaskell", ciDatabase = "testMySQLHaskell", ciPassword = "wrongPassWord"})
          (\ (e :: ERRException) -> assertEqual "wrong password should fail to login" (show e) loginFailMsg)
  
    where
      resetTestTable c = do
              execute_ c  "DELETE FROM test WHERE __id=0"
              execute_ c  "INSERT INTO test VALUES(\
                      \0,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL,\
                      \NULL\
                      \)"
  
      resetTest57Table c = do
              execute_ c  "DELETE FROM test_new WHERE __id=0"
              execute_ c  "INSERT INTO test_new VALUES(\
                          \0,\
                          \NULL,\
                          \NULL,\
                          \NULL\
                          \)"
  
  
  