@@ -0,0 +1,36 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Bytea where
3+
4+import Data.ByteString (ByteString)
5+import Data.Text (Text)
6+import Database.PostgreSQL.Simple
7+import Test.HUnit
8+
9+import qualified Crypto.Hash.MD5 as MD5
10+import qualified Data.ByteString as B
11+import qualified Data.ByteString.Base16 as Base16
12+import qualified Data.Text.Encoding as TE
13+
14+testBytea :: Connection -> Test
15+testBytea conn = TestList
16+ [ testStr "empty" []
17+ , testStr "\"hello\"" $ map (fromIntegral . fromEnum) ("hello" :: String)
18+ , testStr "ascending" [0..255]
19+ , testStr "descending" [255,254..0]
20+ , testStr "ascending, doubled up" $ doubleUp [0..255]
21+ , testStr "descending, doubled up" $ doubleUp [255,254..0]
22+ ]
23+ where
24+ testStr label bytes = TestLabel label $ TestCase $ do
25+ let bs = B.pack bytes
26+
27+ [Only h] <- query conn "SELECT md5(?::bytea)" [Binary bs]
28+ assertBool "Haskell -> SQL conversion altered the string" $ md5 bs == h
29+
30+ [Only (Binary r)] <- query conn "SELECT ?::bytea" [Binary bs]
31+ assertBool "SQL -> Haskell conversion altered the string" $ bs == r
32+
33+ doubleUp = concatMap (\x -> [x, x])
34+
35+md5 :: ByteString -> Text
36+md5 = TE.decodeUtf8 . Base16.encode . MD5.hash