{-# LANGUAGE QuasiQuotes #-} {- Testing strategies: fromString . toString == id ** Todo? toString . fromString == almost id ** Todo? postgresql -> haskell -> postgresql * Done haskell -> postgresql -> haskell ** Todo? But still, what we really want to establish is that the two values correspond; for example, a conversion that consistently added hour when printed to a string and subtracted an hour when parsed from string would still pass these tests. -} module Time (testTime) where import Common import Control.Monad(forM_, replicateM_) import Data.Time import Data.ByteString(ByteString) import Database.PostgreSQL.Simple.SqlQQ numTests :: Int numTests = 200 testTime :: TestEnv -> Test testTime env@TestEnv{..} = TestCase $ do initializeTable env execute_ conn "SET timezone TO 'UTC'" checkRoundTrips env execute_ conn "SET timezone TO 'America/Chicago'" checkRoundTrips env execute_ conn "SET timezone TO 'Asia/Tokyo'" checkRoundTrips env execute_ conn "SET timezone TO 'Asia/Kathmandu'" checkRoundTrips env execute_ conn "SET timezone TO 'America/St_Johns'" checkRoundTrips env initializeTable :: TestEnv -> IO () initializeTable TestEnv{..} = withTransaction conn $ do execute_ conn [sql| CREATE TEMPORARY TABLE testtime ( x serial, y timestamptz, PRIMARY KEY(x) ) |] let pop :: ByteString -> Double -> IO () = \x y -> replicateM_ numTests $ execute conn [sql| INSERT INTO testtime (y) VALUES ('1936-01-01 00:00:00+00'::timestamptz + ?::interval * ROUND(RANDOM() * ?)) |] (x,y) pop "1 microsecond" 6.3113904e15 pop "10 microseconds" 6.3113904e14 pop "100 microseconds" 6.3113904e13 pop "1 millisecond" 6.3113904e12 pop "10 milliseconds" 6.3113904e11 pop "100 milliseconds" 6.3113904e10 pop "1 second" 6.3113904e9 checkRoundTrips :: TestEnv -> IO () checkRoundTrips TestEnv{..} = do yxs :: [(UTCTime, Int)] <- query_ conn [sql| SELECT y, x FROM testtime |] forM_ yxs $ \yx -> do res <- query conn [sql| SELECT y=? FROM testtime WHERE x=? |] yx assertBool "UTCTime did not round-trip from SQL to Haskell and back" $ res == [Only True]