1
module Test.CerealConduit (tests) where
1
{-# LANGUAGE FlexibleContexts, RankNTypes #-}
3
module Test.CerealConduit where
3
5
import Control.Monad.Identity
6
import Control.Monad.Exception
7
import Control.Monad.Error
8
import Control.Monad.Trans.Maybe
5
10
import qualified Data.Conduit as C
6
11
import Data.Conduit.Cereal
7
import Data.Conduit.List
12
import Data.Conduit.Cereal.Internal
13
import Data.Conduit.List as CL
8
14
import Data.Serialize
9
15
import qualified Data.ByteString as BS
10
import Test.Framework.Providers.HUnit
16
--import Test.Framework.Providers.HUnit
19
import qualified Data.List as L
20
import Prelude hiding (take)
22
-- For the sake of these tests, all SomeExceptions are equal
23
instance Eq SomeException where
26
twoItemGet :: Get Word8
15
33
sinktest1 = TestCase (assertEqual "Handles starting with empty bytestring"
17
(runIdentity $ (sourceList [BS.pack [], BS.pack [1]]) C.$$ (sinkGet getWord8)))
35
(runIdentity $ runExceptionT $ (sourceList [BS.pack [], BS.pack [1]]) C.$$ (sinkGet getWord8)))
20
38
sinktest2 = TestCase (assertEqual "Handles empty bytestring in middle"
22
(runIdentity $ (sourceList [BS.pack [1], BS.pack [], BS.pack [3]]) C.$$ (sinkGet (do
40
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1], BS.pack [], BS.pack [3]]) C.$$ (sinkGet (do
28
46
sinktest3 = TestCase (assertBool "Handles no data"
29
(case (runIdentity $ (sourceList []) C.$$ (sinkGet getWord8)) of
47
(case runIdentity $ runExceptionT $ (sourceList []) C.$$ (sinkGet getWord8) of
34
52
sinktest4 = TestCase (assertEqual "Consumes no data"
36
(runIdentity $ (sourceList [BS.pack [1]]) C.$$ (sinkGet $ return ())))
38
twoItemGet :: Get Word8
54
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1]]) C.$$ (sinkGet $ return ())))
57
sinktest5 = TestCase (assertEqual "Empty list"
59
(runIdentity $ runExceptionT $ (sourceList []) C.$$ (sinkGet $ return ())))
62
sinktest6 = TestCase (assertEqual "Leftover input works"
63
(Right (1, BS.pack [2, 3, 4, 5]))
64
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1, 2, 3], BS.pack [4, 5]]) C.$$ (do
65
output <- sinkGet getWord8
67
return (output, BS.concat output'))))
69
-- Current sink implementation will terminate the pipe in case of error.
70
-- One may need non-terminating version like one defined below to get access to Leftovers
72
sinkGetMaybe :: Monad m => Get output -> C.Sink BS.ByteString m (Maybe output)
73
sinkGetMaybe = mkSinkGet errorHandler terminationHandler . fmap Just
74
where errorHandler msg s = C.Done s Nothing
75
terminationHandler f s = C.Done s Nothing
78
sinktest7 = TestCase (assertBool "Leftover input with failure works"
79
(case runIdentity $ do
80
(sourceList [BS.pack [1, 2]]) C.$$ (do
81
output <- sinkGetMaybe (getWord8 >> fail "" :: Get Word8)
83
return (output, BS.concat output')) of
84
(Nothing, bs) -> bs == BS.pack [1, 2]
44
87
conduittest1 :: Test
45
88
conduittest1 = TestCase (assertEqual "Handles starting with empty bytestring"
47
(runIdentity $ (sourceList [BS.pack [], BS.pack [1]]) C.$= conduitGet twoItemGet C.$$ consume))
90
(runIdentity $ runExceptionT $ (sourceList [BS.pack [], BS.pack [1]]) C.$= conduitGet twoItemGet C.$$ CL.consume))
49
92
conduittest2 :: Test
50
93
conduittest2 = TestCase (assertEqual "Works when the get is split across items"
52
(runIdentity $ (sourceList [BS.pack [1], BS.pack [2]]) C.$= conduitGet twoItemGet C.$$ consume))
95
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1], BS.pack [2]]) C.$= conduitGet twoItemGet C.$$ CL.consume))
54
97
conduittest3 :: Test
55
98
conduittest3 = TestCase (assertEqual "Works when empty bytestring in middle of get"
57
(runIdentity $ (sourceList [BS.pack [1], BS.pack [], BS.pack [2]]) C.$= conduitGet twoItemGet C.$$ consume))
100
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1], BS.pack [], BS.pack [2]]) C.$= conduitGet twoItemGet C.$$ CL.consume))
59
102
conduittest4 :: Test
60
103
conduittest4 = TestCase (assertEqual "Works when empty bytestring at end of get"
62
(runIdentity $ (sourceList [BS.pack [1, 2], BS.pack [], BS.pack [3, 4]]) C.$= conduitGet twoItemGet C.$$ consume))
105
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1, 2], BS.pack []]) C.$= conduitGet twoItemGet C.$$ CL.consume))
64
107
conduittest5 :: Test
65
108
conduittest5 = TestCase (assertEqual "Works when multiple gets are in an item"
67
(runIdentity $ (sourceList [BS.pack [1, 2, 3, 4]]) C.$= conduitGet twoItemGet C.$$ consume))
110
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1, 2, 3, 4]]) C.$= conduitGet twoItemGet C.$$ CL.consume))
69
112
conduittest6 :: Test
70
113
conduittest6 = TestCase (assertEqual "Works with leftovers"
72
(runIdentity $ (sourceList [BS.pack [1, 2, 3]]) C.$= conduitGet twoItemGet C.$$ consume))
74
sinktests = TestList [sinktest1, sinktest2, sinktest3, sinktest4]
76
conduittests = TestList [conduittest1, conduittest2, conduittest3, conduittest4, conduittest5, conduittest6]
115
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1, 2, 3]]) C.$= conduitGet twoItemGet C.$$ CL.consume))
118
conduittest7 = let c = 10 in TestCase (assertEqual "Works with infinite lists"
119
(Right $ L.replicate c ())
120
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1, 2, 3]]) C.$= conduitGet (return ()) C.$$ take c))
123
conduittest8 = let c = 10 in TestCase (assertEqual "Works with empty source and infinite lists"
124
(Right $ L.replicate c ())
125
(runIdentity $ runExceptionT $ (sourceList []) C.$= conduitGet (return ()) C.$$ take c))
128
conduittest9 = let c = 10 in TestCase (assertEqual "Works with two well-placed items"
130
(runIdentity $ runExceptionT $ (sourceList [BS.pack [1, 2], BS.pack [3, 4]]) C.$= conduitGet twoItemGet C.$$ CL.consume))
132
conduittest10 :: Test
133
conduittest10 = TestCase (assertBool "Failure works"
134
(case runIdentity $ runExceptionT $ (sourceList [BS.pack [1, 2], BS.pack [3, 4]]) C.$= conduitGet (getWord8 >> fail "omfg") C.$$ CL.consume of
138
conduittest11 :: Test
139
conduittest11 = TestCase (assertBool "Immediate failure works"
140
(case runIdentity $ runExceptionT $ (sourceList [BS.pack [1, 2], BS.pack [3, 4]]) C.$= conduitGet (fail "omfg") C.$$ CL.consume of
144
conduittest12 :: Test
145
conduittest12 = TestCase (assertBool "Immediate failure with empty input works"
146
(case runIdentity $ runExceptionT $ (sourceList []) C.$= conduitGet (fail "omfg") C.$$ CL.consume of
151
-- This test CAN'T work because of the type of HaveOutput.
152
conduittest13 :: Test
153
conduittest13 = TestCase (assertEqual "Leftover success conduit input works"
154
([12], BS.pack [3, 4, 5])
155
(runIdentity $ (sourceList [BS.pack [10, 2, 3], BS.pack [4, 5]]) C.$$ (do
156
output <- (conduitGet twoItemGet) C.=$ (CL.take 1)
157
output' <- CL.consume
158
return (output, BS.concat output'))))
161
conduittest14 :: Test
162
conduittest14 = TestCase (assertEqual "Leftover failure conduit input works"
163
(Right ([], BS.singleton 1))
164
(runIdentity $ runExceptionT $ (sourceList [BS.singleton 1]) C.$$ (do
165
output <- (conduitGet twoItemGet) C.=$ (CL.take 1)
166
output' <- CL.consume
167
return (output, BS.concat output'))))
169
sinktests = TestList [ sinktest1
178
conduittests = TestList [ conduittest1
78
194
hunittests = TestList [sinktests, conduittests]
80
tests = hUnitTestToTests hunittests
196
--tests = hUnitTestToTests hunittests
83
199
counts <- runTestTT hunittests