git.iko.soy/typeable/postgresql-simple
on master help sign in
Add test for COPY unique constraint violation error
2800db2Ben Gamari
postgresql-simple.cabal+2
@@ -115,8 +115,10 @@ test-suite test
115 , bytestring
115 , bytestring
116 , containers
116 , containers
117 , cryptohash
117 , cryptohash
118+ , filepath
118 , tasty
119 , tasty
119 , tasty-hunit
120 , tasty-hunit
121+ , tasty-golden
120 , HUnit
122 , HUnit
121 , postgresql-simple
123 , postgresql-simple
122 , text
124 , text
test/Main.hs+34
@@ -12,6 +12,7 @@ import qualified Database.PostgreSQL.Simple.Transaction as ST
12import Control.Applicative
12import Control.Applicative
13import Control.Exception as E
13import Control.Exception as E
14import Control.Monad
14import Control.Monad
15+import Data.Char
15import Data.List (sort)
16import Data.List (sort)
16import Data.IORef
17import Data.IORef
17import Data.Typeable
18import Data.Typeable
@@ -20,13 +21,16 @@ import GHC.Generics (Generic)
20import Data.Aeson
21import Data.Aeson
21import Data.ByteString (ByteString)
22import Data.ByteString (ByteString)
22import qualified Data.ByteString as B
23import qualified Data.ByteString as B
24+import qualified Data.ByteString.Lazy.Char8 as BL
23import Data.Map (Map)
25import Data.Map (Map)
24import qualified Data.Map as Map
26import qualified Data.Map as Map
25import Data.Text(Text)
27import Data.Text(Text)
26import qualified Data.Text.Encoding as T
28import qualified Data.Text.Encoding as T
27import qualified Data.Vector as V
29import qualified Data.Vector as V
30+import System.FilePath
28
31
29import Test.Tasty
32import Test.Tasty
33+import Test.Tasty.Golden
30import Notify
34import Notify
31import Serializable
35import Serializable
32import Time
36import Time
@@ -47,6 +51,7 @@ tests env = testGroup "tests"
47 , testCase "Unicode" . testUnicode
51 , testCase "Unicode" . testUnicode
48 , testCase "Values" . testValues
52 , testCase "Values" . testValues
49 , testCase "Copy" . testCopy
53 , testCase "Copy" . testCopy
54+ , testCopyFailures
50 , testCase "Double" . testDouble
55 , testCase "Double" . testDouble
51 , testCase "1-ary generic" . testGeneric1
56 , testCase "1-ary generic" . testGeneric1
52 , testCase "2-ary generic" . testGeneric2
57 , testCase "2-ary generic" . testGeneric2
@@ -317,6 +322,35 @@ testCopy TestEnv{..} = do
317 CopyOutDone _ -> return rows
322 CopyOutDone _ -> return rows
318 CopyOutRow row -> loop (row:rows)
323 CopyOutRow row -> loop (row:rows)
319
324
325+testCopyFailures :: TestEnv -> TestTree
326+testCopyFailures env = testGroup "Copy failures"
327+ $ map ($ env)
328+ [ testCopyUniqueConstraintError ]
329+
330+goldenTest :: TestName -> IO BL.ByteString -> TestTree
331+goldenTest testName =
332+ goldenVsString testName (resultsDir </> fileName<.>"expected")
333+ where
334+ resultsDir = "test" </> "results"
335+ fileName = map normalize testName
336+ normalize c | not (isAlpha c) = '-'
337+ | otherwise = c
338+
339+-- | Test that we provide a sensible error message on failure
340+testCopyUniqueConstraintError :: TestEnv -> TestTree
341+testCopyUniqueConstraintError TestEnv{..} =
342+ goldenTest "unique constraint violation"
343+ $ handle (\(SomeException exc) -> return $ BL.pack $ show exc) $ do
344+ execute_ conn "CREATE TEMPORARY TABLE copy_unique_constraint_error_test (x int PRIMARY KEY, y text)"
345+ copy_ conn "COPY copy_unique_constraint_error_test FROM STDIN (FORMAT CSV)"
346+ mapM_ (putCopyData conn) copyRows
347+ _n <- putCopyEnd conn
348+ return BL.empty
349+ where
350+ copyRows = ["1,foo\n"
351+ ,"2,bar\n"
352+ ,"1,baz\n"]
353+
320testDouble :: TestEnv -> Assertion
354testDouble :: TestEnv -> Assertion
321testDouble TestEnv{..} = do
355testDouble TestEnv{..} = do
322 [Only (x :: Double)] <- query_ conn "SELECT 'NaN'::float8"
356 [Only (x :: Double)] <- query_ conn "SELECT 'NaN'::float8"
test/results/unique-constraint-violation.expectednew file+5
@@ -0,0 +1,5 @@
1+user error (Database.PostgreSQL.Simple.Copy.putCopyEnd: failed to parse command status
2+Connection error: ERROR: duplicate key value violates unique constraint "copy_unique_constraint_error_test_pkey"
3+DETAIL: Key (x)=(1) already exists.
4+CONTEXT: COPY copy_unique_constraint_error_test, line 3
5+)