packages feed

enumerator 0.4.14 → 0.4.15

raw patch · 69 files changed

+5251/−1563 lines, 69 filesdep −extensible-exceptionsdep ~basedep ~containersPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: extensible-exceptions

Dependency ranges changed: base, containers

API changes (from Hackage documentation)

- Data.Enumerator: Chunks :: [a] -> Stream a
- Data.Enumerator: Continue :: (Stream a -> Iteratee a m b) -> Step a m b
- Data.Enumerator: EOF :: Stream a
- Data.Enumerator: Error :: SomeException -> Step a m b
- Data.Enumerator: Yield :: b -> (Stream a) -> Step a m b
- Data.Enumerator: checkContinue0 :: Monad m => (Enumerator a m b -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> Enumerator a m b
- Data.Enumerator: checkContinue1 :: Monad m => ((s1 -> Enumerator a m b) -> s1 -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> s1 -> Enumerator a m b
- Data.Enumerator: checkDone :: Monad m => ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b
- Data.Enumerator: checkDoneEx :: Monad m => Stream a' -> ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b
- Data.Enumerator: continue :: Monad m => (Stream a -> Iteratee a m b) -> Iteratee a m b
- Data.Enumerator: data Step a m b
- Data.Enumerator: data Stream a
- Data.Enumerator: enumEOF :: Monad m => Enumerator a m b
- Data.Enumerator: instance (Typeable a, Typeable1 m) => Typeable1 (Iteratee a m)
- Data.Enumerator: instance (Typeable a, Typeable1 m) => Typeable1 (Step a m)
- Data.Enumerator: instance Applicative Stream
- Data.Enumerator: instance Eq a => Eq (Stream a)
- Data.Enumerator: instance Functor Stream
- Data.Enumerator: instance Monad Stream
- Data.Enumerator: instance Monad m => Applicative (Iteratee a m)
- Data.Enumerator: instance Monad m => Functor (Iteratee a m)
- Data.Enumerator: instance Monad m => Monad (Iteratee a m)
- Data.Enumerator: instance MonadIO m => MonadIO (Iteratee a m)
- Data.Enumerator: instance MonadTrans (Iteratee a)
- Data.Enumerator: instance Monoid (Stream a)
- Data.Enumerator: instance Show a => Show (Stream a)
- Data.Enumerator: instance Typeable1 Stream
- Data.Enumerator: returnI :: Monad m => Step a m b -> Iteratee a m b
- Data.Enumerator: yield :: Monad m => b -> Stream a -> Iteratee a m b
- Data.Enumerator.IO: enumFile :: FilePath -> Enumerator ByteString IO b
- Data.Enumerator.IO: enumHandle :: MonadIO m => Integer -> Handle -> Enumerator ByteString m b
- Data.Enumerator.IO: iterHandle :: MonadIO m => Handle -> Iteratee ByteString m ()
+ Data.Enumerator: enumLists :: Monad m => [[a]] -> Enumerator a m b
+ Data.Enumerator: runLists :: [[a]] -> Iteratee a Identity b -> Either SomeException b
+ Data.Enumerator: runLists_ :: [[a]] -> Iteratee a Identity b -> b
+ Data.Enumerator.Internal: ($$) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b'
+ Data.Enumerator.Internal: (<==<) :: Monad m => (Step a m b -> Iteratee a' m b') -> Enumerator a m b -> Step a m b -> Iteratee a' m b'
+ Data.Enumerator.Internal: (==<<) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b'
+ Data.Enumerator.Internal: (>==>) :: Monad m => Enumerator a m b -> (Step a m b -> Iteratee a' m b') -> Step a m b -> Iteratee a' m b'
+ Data.Enumerator.Internal: (>>==) :: Monad m => Iteratee a m b -> (Step a m b -> Iteratee a' m b') -> Iteratee a' m b'
+ Data.Enumerator.Internal: Chunks :: [a] -> Stream a
+ Data.Enumerator.Internal: Continue :: (Stream a -> Iteratee a m b) -> Step a m b
+ Data.Enumerator.Internal: EOF :: Stream a
+ Data.Enumerator.Internal: Error :: SomeException -> Step a m b
+ Data.Enumerator.Internal: Iteratee :: m (Step a m b) -> Iteratee a m b
+ Data.Enumerator.Internal: Yield :: b -> (Stream a) -> Step a m b
+ Data.Enumerator.Internal: checkContinue0 :: Monad m => (Enumerator a m b -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> Enumerator a m b
+ Data.Enumerator.Internal: checkContinue1 :: Monad m => ((s1 -> Enumerator a m b) -> s1 -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> s1 -> Enumerator a m b
+ Data.Enumerator.Internal: checkDone :: Monad m => ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b
+ Data.Enumerator.Internal: checkDoneEx :: Monad m => Stream a' -> ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b
+ Data.Enumerator.Internal: continue :: Monad m => (Stream a -> Iteratee a m b) -> Iteratee a m b
+ Data.Enumerator.Internal: data Step a m b
+ Data.Enumerator.Internal: data Stream a
+ Data.Enumerator.Internal: enumEOF :: Monad m => Enumerator a m b
+ Data.Enumerator.Internal: instance (Typeable a, Typeable1 m) => Typeable1 (Iteratee a m)
+ Data.Enumerator.Internal: instance (Typeable a, Typeable1 m) => Typeable1 (Step a m)
+ Data.Enumerator.Internal: instance Applicative Stream
+ Data.Enumerator.Internal: instance Eq a => Eq (Stream a)
+ Data.Enumerator.Internal: instance Functor Stream
+ Data.Enumerator.Internal: instance Monad Stream
+ Data.Enumerator.Internal: instance Monad m => Applicative (Iteratee a m)
+ Data.Enumerator.Internal: instance Monad m => Functor (Iteratee a m)
+ Data.Enumerator.Internal: instance Monad m => Monad (Iteratee a m)
+ Data.Enumerator.Internal: instance MonadIO m => MonadIO (Iteratee a m)
+ Data.Enumerator.Internal: instance MonadTrans (Iteratee a)
+ Data.Enumerator.Internal: instance Monoid (Stream a)
+ Data.Enumerator.Internal: instance Show a => Show (Stream a)
+ Data.Enumerator.Internal: instance Typeable1 Stream
+ Data.Enumerator.Internal: newtype Iteratee a m b
+ Data.Enumerator.Internal: returnI :: Monad m => Step a m b -> Iteratee a m b
+ Data.Enumerator.Internal: runIteratee :: Iteratee a m b -> m (Step a m b)
+ Data.Enumerator.Internal: type Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai m b)
+ Data.Enumerator.Internal: type Enumerator a m b = Step a m b -> Iteratee a m b
+ Data.Enumerator.Internal: yield :: Monad m => b -> Stream a -> Iteratee a m b

Files

enumerator.cabal view
@@ -1,5 +1,5 @@ name: enumerator-version: 0.4.14+version: 0.4.15 synopsis: Reliable, high-performance processing with left-fold enumerators license: MIT license-file: license.txt@@ -63,39 +63,94 @@   scripts/common.bash   scripts/dist   scripts/run-benchmarks+  scripts/run-coverage   scripts/run-tests   --   tests/enumerator-tests.cabal-  tests/Tests.hs+  tests/EnumeratorTests.hs+  tests/EnumeratorTests/Binary.hs+  tests/EnumeratorTests/Binary/Consume.hs+  tests/EnumeratorTests/Binary/Drop.hs+  tests/EnumeratorTests/Binary/Fold.hs+  tests/EnumeratorTests/Binary/Handle.hs+  tests/EnumeratorTests/Binary/Isolate.hs+  tests/EnumeratorTests/Binary/Iterate.hs+  tests/EnumeratorTests/Binary/Map.hs+  tests/EnumeratorTests/Binary/Repeat.hs+  tests/EnumeratorTests/Binary/Replicate.hs+  tests/EnumeratorTests/Binary/Require.hs+  tests/EnumeratorTests/Binary/Split.hs+  tests/EnumeratorTests/Binary/Unfold.hs+  tests/EnumeratorTests/Binary/Util.hs+  tests/EnumeratorTests/Binary/Zip.hs+  tests/EnumeratorTests/CatchError.hs+  tests/EnumeratorTests/Compatibility.hs+  tests/EnumeratorTests/Instances.hs+  tests/EnumeratorTests/Join.hs+  tests/EnumeratorTests/List.hs+  tests/EnumeratorTests/List/Consume.hs+  tests/EnumeratorTests/List/Drop.hs+  tests/EnumeratorTests/List/Fold.hs+  tests/EnumeratorTests/List/Isolate.hs+  tests/EnumeratorTests/List/Iterate.hs+  tests/EnumeratorTests/List/Map.hs+  tests/EnumeratorTests/List/Repeat.hs+  tests/EnumeratorTests/List/Replicate.hs+  tests/EnumeratorTests/List/Require.hs+  tests/EnumeratorTests/List/Split.hs+  tests/EnumeratorTests/List/Unfold.hs+  tests/EnumeratorTests/List/Unique.hs+  tests/EnumeratorTests/List/Util.hs+  tests/EnumeratorTests/List/Zip.hs+  tests/EnumeratorTests/Misc.hs+  tests/EnumeratorTests/Sequence.hs+  tests/EnumeratorTests/Stream.hs+  tests/EnumeratorTests/Text.hs+  tests/EnumeratorTests/Text/Codecs.hs+  tests/EnumeratorTests/Text/Consume.hs+  tests/EnumeratorTests/Text/Drop.hs+  tests/EnumeratorTests/Text/Fold.hs+  tests/EnumeratorTests/Text/Handle.hs+  tests/EnumeratorTests/Text/Isolate.hs+  tests/EnumeratorTests/Text/Iterate.hs+  tests/EnumeratorTests/Text/Map.hs+  tests/EnumeratorTests/Text/Repeat.hs+  tests/EnumeratorTests/Text/Replicate.hs+  tests/EnumeratorTests/Text/Require.hs+  tests/EnumeratorTests/Text/Split.hs+  tests/EnumeratorTests/Text/Unfold.hs+  tests/EnumeratorTests/Text/Util.hs+  tests/EnumeratorTests/Text/Zip.hs+  tests/EnumeratorTests/Util.hs  source-repository head   type: bazaar-  location: http://john-millikin.com/software/enumerator/+  location: https://john-millikin.com/software/enumerator/ +source-repository this+  type: bazaar+  location: https://john-millikin.com/branches/enumerator/0.4/+  tag: enumerator_0.4.15+ library   ghc-options: -Wall -O2   hs-source-dirs: lib    build-depends:-      transformers >= 0.2 && < 0.3+      base >= 4.0 && < 5.0+    , transformers >= 0.2 && < 0.3     , bytestring >= 0.9 && < 0.10-    , containers+    , containers >= 0.1 && < 0.5     , text >= 0.7 && < 0.12 -  if impl(ghc >= 6.10)-    build-depends:-        base >= 4 && < 5-  else-    build-depends:-        base >= 3 && < 4-      , extensible-exceptions >= 0.1 && < 0.2-   exposed-modules:     Data.Enumerator     Data.Enumerator.Binary-    Data.Enumerator.Text-    Data.Enumerator.List+    Data.Enumerator.Internal     Data.Enumerator.IO+    Data.Enumerator.List+    Data.Enumerator.Text    other-modules:+    Data.Enumerator.Compatibility     Data.Enumerator.Util
examples/wc.hs view
@@ -8,30 +8,30 @@ -- ----------------------------------------------------------------------------- module Main (main) where-import Data.Enumerator as E-import qualified Data.Enumerator.Binary as EB-import qualified Data.Enumerator.Text as ET-import qualified Data.ByteString as B --- support imports-import Control.Monad (unless, forM_)-import System.IO-import System.Console.GetOpt-import System.Environment-import System.Exit+import           Control.Monad (unless, forM_)+import           Data.ByteString (ByteString)+import           System.Console.GetOpt+import           System.IO+import           System.Environment+import           System.Exit +import           Data.Enumerator as E+import qualified Data.Enumerator.Binary as Binary+import qualified Data.Enumerator.Text as Text+ -- support wc modes -c (bytes), -m (characters), and -l (lines)  -- iterBytes simply counts how many bytes are in each chunk, accumulates this -- count, and returns it when EOF is received. -iterBytes :: Monad m => Iteratee B.ByteString m Integer-iterBytes = EB.fold (\acc _ -> acc + 1) 0+iterBytes :: Monad m => Iteratee ByteString m Integer+iterBytes = Binary.fold (\acc _ -> acc + 1) 0  -- iterLines is similar, except it only counts newlines ('\n') -iterLines :: Monad m => Iteratee B.ByteString m Integer-iterLines = EB.fold step 0 where+iterLines :: Monad m => Iteratee ByteString m Integer+iterLines = Binary.fold step 0 where 	step acc 0xA = acc + 1 	step acc _ = acc @@ -39,13 +39,11 @@ -- assuming UTF-8) before performing any counting. Leftover bytes, not part -- of a valid UTF-8 character, are yielded as surplus ----- Note the use of joinI. 'ET.decode' is an enumeratee, which means it returns--- an iteratee yielding an inner step. 'joinI' "collapses" an enumeratee's--- return value, much as 'join' does to monadic values.+-- Note the use of (=$). This lets an enumeratee send data directly to an+-- iteratee, without worrying about leftover input. -iterChars :: Monad m => Iteratee B.ByteString m Integer-iterChars = joinI (ET.decode ET.utf8 $$ count) where-	count = ET.fold (\acc _ -> acc + 1) 0+iterChars :: Monad m => Iteratee ByteString m Integer+iterChars = Text.decode Text.utf8 =$ Text.fold (\acc _ -> acc + 1) 0  main :: IO () main = do@@ -60,9 +58,9 @@ 		OptionChars -> iterChars 	 	forM_ files $ \filename -> do-		putStr $ filename ++ ": "+		putStr (filename ++ ": ") 		-		eitherStat <- run (EB.enumFile filename $$ iter)+		eitherStat <- run (Binary.enumFile filename $$ iter) 		putStrLn $ case eitherStat of 			Left err -> "ERROR: " ++ show err 			Right stat -> show stat
lib/Data/Enumerator.hs view
@@ -6,9 +6,7 @@ -- Maintainer: jmillikin@gmail.com -- Portability: portable ----- Core enumerator types, and some useful primitives.------ This module is intended to be imported qualified:+-- For compatibility reasons, this module should imported qualified: -- -- @ -- import qualified Data.Enumerator as E@@ -17,18 +15,18 @@ 	( 	 	-- * Types-	  Stream (..)-	, Iteratee (..)-	, Step (..)+	  Iteratee 	, Enumerator 	, Enumeratee 	-	-- * Primitives-	, returnI-	, continue-	, yield+	-- * Running iteratees+	, run+	, run_ 	-	-- ** Operators+	-- * Operators+	-- | Compatibility note: Most of these will be obsoleted by+	-- version 0.5. Please make sure your @.cabal@ files have a+	-- @<0.5@ limit on the @enumerator@ dependency. 	, (>>==) 	, (==<<) 	, ($$)@@ -37,11 +35,7 @@ 	, (=$) 	, ($=) 	-	-- ** Running iteratees-	, run-	, run_-	-	-- ** Error handling+	-- * Error handling 	, throwError 	, catchError 	@@ -50,222 +44,55 @@ 	, joinI 	, joinE 	, Data.Enumerator.sequence-	, enumEOF-	, checkContinue0-	, checkContinue1-	, checkDoneEx-	, checkDone 	, isEOF 	, tryIO+	, liftTrans 	-	-- ** Testing and debugging+	-- * Testing and debugging 	, printChunks 	, enumList+	, enumLists+	, runLists+	, runLists_ 	-	-- * Legacy compatibility+	-- * Internal interfaces+	-- | This module export will be removed in version 0.5. If you+	-- depend on internal implementation details, please import+	-- @"Data.Enumerator.Internal"@ directly.+	, module Data.Enumerator.Internal 	-	-- ** Obsolete-	, liftTrans-	, liftI+	-- Obsolete and pointless 	, peek 	, Data.Enumerator.last 	, Data.Enumerator.length 	-	-- ** Aliases-	, Data.Enumerator.head-	, Data.Enumerator.drop-	, Data.Enumerator.dropWhile-	, Data.Enumerator.span-	, Data.Enumerator.break-	, consume-	, Data.Enumerator.foldl-	, Data.Enumerator.foldl'-	, foldM-	, Data.Enumerator.iterate-	, iterateM-	, Data.Enumerator.repeat-	, repeatM-	, Data.Enumerator.replicate-	, replicateM-	, generateM-	, Data.Enumerator.map-	, Data.Enumerator.mapM-	, Data.Enumerator.concatMap-	, concatMapM-	, Data.Enumerator.filter-	, filterM-	, liftFoldL-	, liftFoldL'-	, liftFoldM-	+	-- Legacy compatibility+	-- These legacy compatibility functions will be removed in+	-- version 0.5.+	, module Data.Enumerator.Compatibility 	) where -import           Control.Applicative as A import qualified Control.Exception as Exc import qualified Control.Monad as CM import           Control.Monad.IO.Class (MonadIO, liftIO) import           Control.Monad.Trans.Class (MonadTrans, lift)-import           Data.Function (fix)+import           Data.Functor.Identity (Identity, runIdentity) import           Data.List (genericLength, genericSplitAt)-import           Data.Monoid (Monoid, mempty, mappend, mconcat)-import           Data.Typeable ( Typeable, typeOf-                               , Typeable1, typeOf1-                               , mkTyConApp, mkTyCon) -import {-# SOURCE #-} qualified Data.Enumerator.List as EL---- | A 'Stream' is a sequence of chunks generated by an 'Enumerator'.------ @('Chunks' [])@ is used to indicate that a stream is still active, but--- currently has no available data. Iteratees should ignore empty chunks.-data Stream a-	= Chunks [a]-	| EOF-	deriving (Show, Eq)--instance Monad Stream where-	return = Chunks . return-	Chunks xs >>= f = mconcat (fmap f xs)-	EOF >>= _ = EOF--instance Monoid (Stream a) where-	mempty = Chunks mempty-	mappend (Chunks xs) (Chunks ys) = Chunks (xs ++ ys)-	mappend _ _ = EOF--data Step a m b-	-- | The 'Iteratee' is capable of accepting more input. Note that more input-	-- is not necessarily required; the 'Iteratee' might be able to generate a-	-- value immediately if it receives 'EOF'.-	= Continue (Stream a -> Iteratee a m b)-	-	-- | The 'Iteratee' cannot receive any more input, and has generated a-	-- result. Included in this value is left-over input, which can be passed to-	-- composed 'Iteratee's.-	| Yield b (Stream a)-	-	-- | The 'Iteratee' encountered an error which prevents it from proceeding-	-- further.-	| Error Exc.SomeException---- | The primary data type for this library, which consumes--- input from a 'Stream' until it either generates a value or encounters--- an error. Rather than requiring all input at once, an iteratee will--- return 'Continue' when it is capable of processing more data.------ In general, iteratees begin in the 'Continue' state. As each chunk is--- passed to the continuation, the iteratee returns the next step:--- 'Continue' for more data, 'Yield' when it's finished, or 'Error' to--- abort processing.-newtype Iteratee a m b = Iteratee-	{ runIteratee :: m (Step a m b)-	}--instance Monad m => Monad (Iteratee a m) where-	return x = yield x (Chunks [])--	m0 >>= f = ($ m0) $ fix $-		\bind m -> Iteratee $ runIteratee m >>= \r1 ->-			case r1 of-				Continue k -> return (Continue (bind . k))-				Error err -> return (Error err)-				Yield x (Chunks []) -> runIteratee (f x)-				Yield x extra -> runIteratee (f x) >>= \r2 ->-					case r2 of-						Continue k -> runIteratee (k extra)-						Error err -> return (Error err)-						Yield x' _ -> return (Yield x' extra)--instance MonadTrans (Iteratee a) where-	lift m = Iteratee (m >>= runIteratee . return)--instance MonadIO m => MonadIO (Iteratee a m) where-	liftIO = lift . liftIO---- | While 'Iteratee's consume data, enumerators generate it. Since--- @'Iteratee'@ is an alias for @m ('Step' a m b)@, 'Enumerator's can--- be considered step transformers of type--- @'Step' a m b -> m ('Step' a m b)@.------ 'Enumerator's typically read from an external source (parser, handle,--- random generator, etc). They feed chunks into an 'Iteratee' until the--- source runs out of data (triggering 'EOF') or the iteratee finishes--- processing ('Yield's a value).-type Enumerator a m b = Step a m b -> Iteratee a m b---- | In cases where an enumerator acts as both a source and sink, the resulting--- type is named an 'Enumeratee'. Enumeratees have two input types,--- &#x201c;outer a&#x201d; (@aOut@) and &#x201c;inner a&#x201d; (@aIn@).-type Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai m b)---- | Since: 0.4.8-instance Typeable1 Stream where-	typeOf1 _ = mkTyConApp tyCon [] where-		tyCon = mkTyCon "Data.Enumerator.Stream"---- | Since: 0.4.6-instance (Typeable a, Typeable1 m) =>-	Typeable1 (Iteratee a m) where-		typeOf1 i = let-			tyCon = mkTyCon "Data.Enumerator.Iteratee"-			(a, m) = peel i-			-			peel :: Iteratee a m b -> (a, m ())-			peel = undefined-			-			in mkTyConApp tyCon [typeOf a, typeOf1 m]---- | Since: 0.4.8-instance (Typeable a, Typeable1 m) =>-	Typeable1 (Step a m) where-		typeOf1 s = let-			tyCon = mkTyCon "Data.Enumerator.Step"-			(a, m) = peel s-			-			peel :: Step a m b -> (a, m ())-			peel = undefined-			-			in mkTyConApp tyCon [typeOf a, typeOf1 m]--instance Monad m => Functor (Iteratee a m) where-	fmap = CM.liftM--instance Monad m => A.Applicative (Iteratee a m) where-	pure = return-	(<*>) = CM.ap--instance Functor Stream where-	fmap f (Chunks xs) = Chunks (fmap f xs)-	fmap _ EOF = EOF---- | Since: 0.4.5-instance A.Applicative Stream where-	pure = return-	(<*>) = CM.ap---- | @'returnI' step = 'Iteratee' (return step)@-returnI :: Monad m => Step a m b -> Iteratee a m b-returnI step = Iteratee (return step)---- | @'yield' x extra = 'returnI' ('Yield' x extra)@------ WARNING: due to the current encoding of iteratees in this library,--- careless use of the 'yield' primitive may violate the monad laws.--- To prevent this, always make sure that an iteratee never yields--- extra data unless it has received at least one input element.------ More strictly, iteratees may not yield data that they did not--- receive as input. Don't use 'yield' to &#x201c;inject&#x201d; elements--- into the stream.-yield :: Monad m => b -> Stream a -> Iteratee a m b-yield x extra = returnI (Yield x extra)---- | @'continue' k = 'returnI' ('Continue' k)@-continue :: Monad m => (Stream a -> Iteratee a m b) -> Iteratee a m b-continue k = returnI (Continue k)+import           Data.Enumerator.Compatibility+import           Data.Enumerator.Internal  -- | Run an iteratee until it finishes, and return either the final value -- (if it succeeded) or the error (if it failed).+--+-- > import Data.Enumerator+-- > import Data.Enumerator.List as EL+-- >+-- > main = do+-- >     result <- run (EL.iterate succ 'A' $$ EL.take 5)+-- >     case result of+-- >         Left exc -> putStrLn ("Got an exception: " ++ show exc)+-- >         Right chars -> putStrLn ("Got characters: " ++ show chars) run :: Monad m => Iteratee a m b     -> m (Either Exc.SomeException b) run i = do@@ -278,11 +105,18 @@ -- | Like 'run', except errors are converted to exceptions and thrown. -- Primarily useful for small scripts or other simple cases. --+-- > import Data.Enumerator+-- > import Data.Enumerator.List as EL+-- >+-- > main = do+-- >     chars <- run_ (EL.iterate succ 'A' $$ EL.take 5)+-- >     putStrLn ("Got characters: " ++ show chars)+-- -- Since: 0.4.1 run_ :: Monad m => Iteratee a m b -> m b run_ i = run i >>= either Exc.throw return --- | @'throwError' exc = 'returnI' ('Error' ('Exc.toException' exc))@+-- | The moral equivalent of 'Exc.throwIO' for iteratees. throwError :: (Monad m, Exc.Exception e) => e -> Iteratee a m b throwError exc = returnI (Error (Exc.toException exc)) @@ -291,15 +125,12 @@ -- all errors to be represented by 'Exc.SomeException', libraries with -- varying error types can be easily composed. ----- WARNING: after a few rounds of "catchError doesn't work because X", this--- function has grown into a horrible monster. I have no concept of what--- unexpected behaviors lurk in its dark crevices. Users are strongly advised--- to wrap all uses of @catchError@ with an appropriate @isolate@, such as--- @Data.Enumerator.List.isolate@ or @Data.Enumerator.Binary.isolate@, which--- will handle input framing even in the face of unexpected errors.------ Within the error handler, it is difficult or impossible to know how much--- input the original iteratee has consumed.+-- WARNING: Within the error handler, it is difficult or impossible to know+-- how much input the original iteratee has consumed. Users are strongly+-- advised to wrap all uses of @catchError@ with an appropriate isolation+-- enumeratee, such as @Data.Enumerator.List.isolate@ or+-- @Data.Enumerator.Binary.isolate@, which will handle input framing even+-- in the face of unexpected errors. -- -- Since: 0.1.1 catchError :: Monad m@@ -331,61 +162,6 @@ 					_ -> return step' 			Continue k' -> return (Continue (wrap k')) -infixl 1 >>==-infixr 1 ==<<-infixr 0 $$-infixr 1 >==>-infixr 1 <==<---- | Equivalent to '(>>=)' for @m ('Step' a m b)@; allows 'Iteratee's with--- different input types to be composed.--(>>==) :: Monad m-       => Iteratee a m b-       -> (Step a m b -> Iteratee a' m b')-       -> Iteratee a' m b'-i >>== f = Iteratee (runIteratee i >>= runIteratee . f)---- | @'(==\<\<)' = flip '(\>\>==)'@-(==<<) :: Monad m-       => (Step a m b -> Iteratee a' m b')-       -> Iteratee a m b-       -> Iteratee a' m b'-(==<<) = flip (>>==)---- | @'($$)' = '(==\<\<)'@------ This might be easier to read when passing a chain of iteratees to an--- enumerator.------ Since: 0.1.1-($$) :: Monad m-     => (Step a m b -> Iteratee a' m b')-     -> Iteratee a m b-     -> Iteratee a' m b'-($$) = (==<<)---- | @'(>==>)' e1 e2 s = e1 s '>>==' e2@------ Since: 0.1.1-(>==>) :: Monad m-       => Enumerator a m b-       -> (Step a m b -> Iteratee a' m b')-       -> Step a m b-       -> Iteratee a' m b'-(>==>) e1 e2 s = e1 s >>== e2---- | @'(\<==\<)' = flip '(>==>)'@------ Since: 0.1.1--(<==<) :: Monad m-       => (Step a m b -> Iteratee a' m b')-       -> Enumerator a m b-       -> Step a m b-       -> Iteratee a' m b'-(<==<) = flip (>==>)- -- | Print chunks as they're received from the enumerator, optionally -- printing empty chunks. printChunks :: (MonadIO m, Show a)@@ -402,9 +178,13 @@ 		yield () EOF  -- | @'enumList' n xs@ enumerates /xs/ as a stream, passing /n/ inputs per--- chunk.+-- chunk. This is primarily useful for testing, debugging, and REPL+-- exploration. ----- Primarily useful for testing and debugging.+-- Compatibility note: In version 0.5, 'enumList' will be changed to the+-- type:+--+-- > enumList :: Monad m => [a] -> Enumerator a m b enumList :: Monad m => Integer -> [a] -> Enumerator a m b enumList n = loop where 	loop xs (Continue k) | not (null xs) = let@@ -412,14 +192,39 @@ 		in k (Chunks s1) >>== loop s2 	loop _ step = returnI step +-- | @'enumLists' xs@ enumerates /xs/ as a stream, where each element is a+-- separate chunk. This is primarily useful for testing and debugging.+--+-- Since: 0.4.15+enumLists :: Monad m => [[a]] -> Enumerator a m b+enumLists (xs:xss) (Continue k) = k (Chunks xs) >>== enumLists xss+enumLists _ step = returnI step --- | Compose a list of 'Enumerator's using @'(>>==)'@+-- | Run an iteratee with the given input, and return either the final value+-- (if it succeeded) or the error (if it failed).+--+-- Since: 0.4.15+runLists :: [[a]] -> Iteratee a Identity b -> Either Exc.SomeException b+runLists lists iter = runIdentity (run (enumLists lists $$ iter))++-- | Like 'runLists', except errors are converted to exceptions and thrown.+--+-- Since: 0.4.15+runLists_ :: [[a]] -> Iteratee a Identity b -> b+runLists_ lists iter = runIdentity (run_ (enumLists lists $$ iter))++-- | Compose a list of 'Enumerator's using @('>==>').@ concatEnums :: Monad m => [Enumerator a m b]             -> Enumerator a m b concatEnums = Prelude.foldl (>==>) returnI --- | 'joinI' is used to &#x201C;flatten&#x201D; 'Enumeratee's into an--- 'Iteratee'.+-- | &#x201c;Wraps&#x201d; an iteratee /inner/ in an enumeratee /wrapper/.+-- The resulting iteratee will consume /wrapper/&#x2019;s input type and+-- yield /inner/&#x2019;s output type.+--+-- See the documentation for ('=$').+--+-- @joinI (enum $$ iter) = enum =$ iter@ joinI :: Monad m => Iteratee a m (Step a' m b)       -> Iteratee a m b joinI outer = outer >>= check where@@ -431,9 +236,7 @@  infixr 0 =$ --- | @enum =$ iter = 'joinI' (enum $$ iter)@------ &#x201c;Wraps&#x201d; an iteratee /inner/ in an enumeratee /wrapper/.+-- | &#x201c;Wraps&#x201d; an iteratee /inner/ in an enumeratee /wrapper/. -- The resulting iteratee will consume /wrapper/&#x2019;s input type and -- yield /inner/&#x2019;s output type. --@@ -441,11 +244,11 @@ -- that extra will be discarded. -- -- As an example, consider an iteratee that converts a stream of UTF8-encoded--- bytes into a single 'TL.Text':+-- bytes into a single @Text@: -- -- > consumeUTF8 :: Monad m => Iteratee ByteString m Text ----- It could be written with either 'joinI' or '(=$)':+-- It could be written with either 'joinI' or @(=$)@: -- -- > import Data.Enumerator.Text as ET -- >@@ -456,7 +259,14 @@ (=$) :: Monad m => Enumeratee ao ai m b -> Iteratee ai m b -> Iteratee ao m b enum =$ iter = joinI (enum $$ iter) --- | Flatten an enumerator/enumeratee pair into a single enumerator.+-- | &#x201c;Wraps&#x201d; an enumerator /inner/ in an enumeratee /wrapper/.+-- The resulting enumerator will generate /wrapper/&#x2019;s output type.+--+-- See the documentation for ('$=').+--+-- @joinE enum enee = enum $= enee@+--+-- Since: 0.4.5 joinE :: Monad m       => Enumerator ao m (Step ai m b)       -> Enumeratee ao ai m b@@ -468,11 +278,9 @@ 		Yield x _ -> return x 		Continue _ -> error "joinE: divergent iteratee" -infixr 0 $=+infixl 1 $= --- | @enum $= enee = 'joinE' enum enee@------ &#x201c;Wraps&#x201d; an enumerator /inner/ in an enumeratee /wrapper/.+-- | &#x201c;Wraps&#x201d; an enumerator /inner/ in an enumeratee /wrapper/. -- The resulting enumerator will generate /wrapper/&#x2019;s output type. -- -- As an example, consider an enumerator that yields line character counts@@ -480,7 +288,7 @@ -- -- > enumFileCounts :: FilePath -> Enumerator Int IO b ----- It could be written with either 'joinE' or '($=)':+-- It could be written with either 'joinE' or @($=)@: -- -- > import Data.Text as T -- > import Data.Enumerator.List as EL@@ -489,6 +297,9 @@ -- > enumFileCounts path = joinE (enumFile path) (EL.map T.length) -- > enumFileCounts path = enumFile path $= EL.map T.length --+-- Compatibility note: in version 0.4.15, the associativity of @($=)@ was+-- changed from @infixr 0@ to @infixl 1@.+-- -- Since: 0.4.9 ($=) :: Monad m      => Enumerator ao m (Step ai m b)@@ -507,45 +318,15 @@ 		else step k 	step k = i >>= \v -> k (Chunks [v]) >>== loop --- | Sends 'EOF' to its iteratee. Most clients should use 'run' or 'run_'--- instead.-enumEOF :: Monad m => Enumerator a m b-enumEOF (Yield x _) = yield x EOF-enumEOF (Error err) = throwError err-enumEOF (Continue k) = k EOF >>== check where-	check (Continue _) = error "enumEOF: divergent iteratee"-	check s = enumEOF s---- | A common pattern in 'Enumeratee' implementations is to check whether--- the inner 'Iteratee' has finished, and if so, to return its output.--- 'checkDone' passes its parameter a continuation if the 'Iteratee'--- can still consume input, or yields otherwise.------ Since: 0.4.3-checkDoneEx :: Monad m =>-	Stream a' ->-	((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) ->-	Enumeratee a' a m b-checkDoneEx _     f (Continue k) = f k-checkDoneEx extra _ step         = yield step extra---- | @'checkDone' = 'checkDoneEx' ('Chunks' [])@------ Use this for enumeratees which do not have an input buffer.-checkDone :: Monad m =>-	((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) ->-	Enumeratee a' a m b-checkDone = checkDoneEx (Chunks [])---- | Check whether a stream has reached EOF. Most clients should use--- 'Data.Enumerator.List.head' instead.+-- | Check whether a stream has reached EOF. Note that if the stream is not+-- at EOF, @isEOF@ may cause data to be read from the enumerator. isEOF :: Monad m => Iteratee a m Bool isEOF = continue $ \s -> case s of 	EOF -> yield True s 	_ -> yield False s  -- | Try to run an IO computation. If it throws an exception, the exception--- is caught and converted into an {\tt Error}.+-- is caught and passed to 'throwError'. -- -- Since: 0.4.9 tryIO :: MonadIO m => IO b -> Iteratee a m b@@ -555,54 +336,8 @@ 		Right b -> Yield b (Chunks []) 		Left err -> Error err --- | A common pattern in 'Enumerator' implementations is to check whether--- the inner 'Iteratee' has finished, and if so, to return its output.--- 'checkContinue0' passes its parameter a continuation if the 'Iteratee'--- can still consume input; if not, it returns the iteratee's step.------ The type signature here is a bit crazy, but it's actually very easy to--- use. Take this code:------ > repeat :: Monad m => a -> Enumerator a m b--- > repeat x = loop where--- > 	loop (Continue k) = k (Chunks [x]) >>== loop--- > 	loop step = returnI step------ And rewrite it without the boilerplate:------ > repeat :: Monad m => a -> Enumerator a m b--- > repeat x = checkContinue0 $ \loop k -> k (Chunks [x] >>== loop------ Since: 0.4.9-checkContinue0 :: Monad m-               => (Enumerator a m b-                -> (Stream a -> Iteratee a m b)-                -> Iteratee a m b)-               -> Enumerator a m b-checkContinue0 inner = loop where-	loop (Continue k) = inner loop k-	loop step = returnI step----- | Like 'checkContinue0', but allows each loop step to use a state value:------ > iterate :: Monad m => (a -> a) -> a -> Enumerator a m b--- > iterate f = checkContinue1 $ \loop a k -> k (Chunks [a]) >>== loop (f a)------ Since: 0.4.9-checkContinue1 :: Monad m-               => ((s1 -> Enumerator a m b)-                -> s1-                -> (Stream a -> Iteratee a m b)-                -> Iteratee a m b)-               -> s1-               -> Enumerator a m b-checkContinue1 inner = loop where-	loop s (Continue k) = inner loop s k-	loop _ step = returnI step---- | Lift an 'Iteratee' onto a monad transformer, re-wrapping the--- 'Iteratee'&#x2019;s inner monadic values.+-- | Lift an 'Iteratee' onto a monad transformer, re-wrapping its+-- inner monadic values. -- -- Since: 0.1.1 liftTrans :: (Monad m, MonadTrans t, Monad (t m)) =>@@ -614,13 +349,6 @@ 		Error err -> Error err 		Continue k -> Continue (liftTrans . k) -{-# DEPRECATED liftI "Use 'Data.Enumerator.continue' instead" #-}---- | Deprecated in 0.4.5: use 'Data.Enumerator.continue' instead-liftI :: Monad m => (Stream a -> Step a m b)-      -> Iteratee a m b-liftI k = continue (returnI . k)- -- | Peek at the next element in the stream, or 'Nothing' if the stream -- has ended. peek :: Monad m => Iteratee a m (Maybe a)@@ -648,172 +376,3 @@ 	len = genericLength 	loop n (Chunks xs) = continue (loop (n + len xs)) 	loop n EOF = yield n EOF--{-# DEPRECATED head "Use 'Data.Enumerator.List.head' instead" #-}--- | Deprecated in 0.4.5: use 'Data.Enumerator.List.head' instead-head :: Monad m => Iteratee a m (Maybe a)-head = EL.head--{-# DEPRECATED drop "Use 'Data.Enumerator.List.drop' instead" #-}--- | Deprecated in 0.4.5: use 'Data.Enumerator.List.drop' instead-drop :: Monad m => Integer -> Iteratee a m ()-drop = EL.drop--{-# DEPRECATED dropWhile "Use 'Data.Enumerator.List.dropWhile' instead" #-}--- | Deprecated in 0.4.5: use 'Data.Enumerator.List.dropWhile' instead-dropWhile :: Monad m => (a -> Bool) -> Iteratee a m ()-dropWhile = EL.dropWhile--{-# DEPRECATED span "Use 'Data.Enumerator.List.takeWhile' instead" #-}--- | Deprecated in 0.4.5: use 'Data.Enumerator.List.takeWhile' instead-span :: Monad m => (a -> Bool) -> Iteratee a m [a]-span = EL.takeWhile--{-# DEPRECATED break "Use 'Data.Enumerator.List.takeWhile' instead" #-}--- | Deprecated in 0.4.5: use 'Data.Enumerator.List.takeWhile' instead-break :: Monad m => (a -> Bool) -> Iteratee a m [a]-break p = EL.takeWhile (not . p)--{-# DEPRECATED consume "Use 'Data.Enumerator.List.consume' instead" #-}--- | Deprecated in 0.4.5: use 'Data.Enumerator.List.consume' instead-consume :: Monad m => Iteratee a m [a]-consume = EL.consume--{-# DEPRECATED foldl "Use Data.Enumerator.List.fold instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.fold' instead------ Since: 0.4.5-foldl :: Monad m => (b -> a -> b) -> b -> Iteratee a m b-foldl step = continue . loop where-	fold = Prelude.foldl step-	loop acc stream = case stream of-		Chunks [] -> continue (loop acc)-		Chunks xs -> continue (loop (fold acc xs))-		EOF -> yield acc EOF--{-# DEPRECATED foldl' "Use Data.Enumerator.List.fold instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.fold' instead------ Since: 0.4.5-foldl' :: Monad m => (b -> a -> b) -> b -> Iteratee a m b-foldl' = EL.fold--{-# DEPRECATED foldM "Use Data.Enumerator.List.foldM instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.foldM' instead------ Since: 0.4.5-foldM :: Monad m => (b -> a -> m b) -> b -> Iteratee a m b-foldM = EL.foldM--{-# DEPRECATED iterate "Use Data.Enumerator.List.iterate instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.iterate' instead------ Since: 0.4.5-iterate :: Monad m => (a -> a) -> a -> Enumerator a m b-iterate = EL.iterate--{-# DEPRECATED iterateM "Use Data.Enumerator.List.iterateM instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.iterateM' instead------ Since: 0.4.5-iterateM :: Monad m => (a -> m a) -> a -> Enumerator a m b-iterateM = EL.iterateM--{-# DEPRECATED repeat "Use Data.Enumerator.List.repeat instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.repeat' instead------ Since: 0.4.5-repeat :: Monad m => a -> Enumerator a m b-repeat = EL.repeat--{-# DEPRECATED repeatM "Use Data.Enumerator.List.repeatM instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.repeatM' instead------ Since: 0.4.5-repeatM :: Monad m => m a -> Enumerator a m b-repeatM = EL.repeatM--{-# DEPRECATED replicate "Use Data.Enumerator.List.replicate instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.replicate' instead------ Since: 0.4.5-replicate :: Monad m => Integer -> a -> Enumerator a m b-replicate = EL.replicate--{-# DEPRECATED replicateM "Use Data.Enumerator.List.replicateM instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.replicateM' instead------ Since: 0.4.5-replicateM :: Monad m => Integer -> m a -> Enumerator a m b-replicateM = EL.replicateM--{-# DEPRECATED generateM "Use Data.Enumerator.List.generateM instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.generateM' instead------ Since: 0.4.5-generateM :: Monad m => m (Maybe a) -> Enumerator a m b-generateM = EL.generateM--{-# DEPRECATED map "Use Data.Enumerator.List.map instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.map' instead-map :: Monad m => (ao -> ai) -> Enumeratee ao ai m b-map = EL.map--{-# DEPRECATED mapM "Use Data.Enumerator.List.mapM instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.mapM' instead------ Since: 0.4.3-mapM :: Monad m => (ao -> m ai) -> Enumeratee ao ai m b-mapM = EL.mapM--{-# DEPRECATED concatMap "Use Data.Enumerator.List.concatMap instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.concatMap' instead------ Since: 0.4.3-concatMap :: Monad m => (ao -> [ai]) -> Enumeratee ao ai m b-concatMap = EL.concatMap--{-# DEPRECATED concatMapM "Use Data.Enumerator.List.concatMapM instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.concatMapM' instead------ Since: 0.4.5-concatMapM :: Monad m => (ao -> m [ai]) -> Enumeratee ao ai m b-concatMapM = EL.concatMapM--{-# DEPRECATED filter "Use Data.Enumerator.List.filter instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.filter' instead------ Since: 0.4.5-filter :: Monad m => (a -> Bool) -> Enumeratee a a m b-filter = EL.filter--{-# DEPRECATED filterM "Use Data.Enumerator.List.filterM instead" #-}--- | Deprecated in 0.4.8: use 'Data.Enumerator.List.filterM' instead------ Since: 0.4.5-filterM :: Monad m => (a -> m Bool) -> Enumeratee a a m b-filterM = EL.filterM--{-# DEPRECATED liftFoldL "Use Data.Enumerator.List.fold instead" #-}--- | Deprecated in 0.4.5: use 'Data.Enumerator.List.fold' instead------ Since: 0.1.1-liftFoldL :: Monad m => (b -> a -> b) -> b-          -> Iteratee a m b-liftFoldL = Data.Enumerator.foldl--{-# DEPRECATED liftFoldL' "Use Data.Enumerator.List.fold instead" #-}--- | Deprecated in 0.4.5: use 'Data.Enumerator.List.fold' instead------ Since: 0.1.1-liftFoldL' :: Monad m => (b -> a -> b) -> b-           -> Iteratee a m b-liftFoldL' = EL.fold--{-# DEPRECATED liftFoldM "Use Data.Enumerator.List.foldM instead" #-}--- | Deprecated in 0.4.5: use 'Data.Enumerator.List.foldM' instead------ Since: 0.1.1-liftFoldM :: Monad m => (b -> a -> m b) -> b-          -> Iteratee a m b-liftFoldM = EL.foldM
lib/Data/Enumerator/Binary.hs view
@@ -108,9 +108,8 @@ import qualified System.IO as IO import           System.IO.Error (isEOFError) -import           Data.Enumerator hiding ( head, drop, iterateM, repeatM, replicateM-                                        , generateM, filterM, consume, foldM-                                        , concatMapM)+import           Data.Enumerator.Internal+import           Data.Enumerator (isEOF, throwError, tryIO) import qualified Data.Enumerator.List as EL  -- | Consume the entire input stream with a strict left fold, one byte@@ -194,7 +193,7 @@ 	loop k (x:xs) = do 		fx <- lift (f x) 		k (Chunks [fx]) >>==-			checkDoneEx (Chunks [B.pack xs]) (\k' -> loop k' xs)+			checkDoneEx (Chunks [B.pack xs]) (`loop` xs)  -- | Similar to 'Data.Enumerator.Binary.concatMap', but with a stateful step -- function.@@ -326,7 +325,7 @@ 		len = toInteger (BL.length lazy) 		 		iter = if len < n'-			then continue (loop (acc . (BL.append lazy)) (n' - len))+			then continue (loop (acc . BL.append lazy) (n' - len)) 			else let 				(xs', extra) = BL.splitAt (fromInteger n') lazy 				in yield (acc xs') (toChunks extra)@@ -343,7 +342,7 @@ 		lazy = BL.fromChunks xs 		(xs', extra) = BL.span p lazy 		iter = if BL.null extra-			then continue (loop (acc . (BL.append lazy)))+			then continue (loop (acc . BL.append lazy)) 			else yield (acc xs') (toChunks extra) 	loop acc EOF = yield (acc BL.empty) EOF @@ -355,7 +354,7 @@ 	loop acc (Chunks []) = continue (loop acc) 	loop acc (Chunks xs) = iter where 		lazy = BL.fromChunks xs-		iter = continue (loop (acc . (BL.append lazy)))+		iter = continue (loop (acc . BL.append lazy)) 	loop acc EOF = yield (acc BL.empty) EOF  -- | Pass input from a stream through two iteratees at once. Excess input is@@ -665,7 +664,7 @@ 		lazy = BL.fromChunks xs 		len = toInteger (BL.length lazy) 		iter = if len < n'-			then continue (loop (acc . (BL.append lazy)) (n' - len))+			then continue (loop (acc . BL.append lazy) (n' - len)) 			else yield () (toChunks (acc lazy)) 	loop _ _ EOF = throwError (Exc.ErrorCall "require: Unexpected EOF") @@ -686,8 +685,8 @@ 			then k (Chunks xs) >>== isolate (n - len) 			else let 				(s1, s2) = BL.splitAt (fromInteger n) lazy-				in k (toChunks s1) >>== (\step -> yield step (toChunks s2))-	loop EOF = k EOF >>== (\step -> yield step EOF)+				in k (toChunks s1) >>== (`yield` toChunks s2)+	loop EOF = k EOF >>== (`yield` EOF) isolate n step = drop n >> return step  -- | Split on bytes satisfying a given predicate.@@ -774,7 +773,7 @@ 			if B.null bytes 				then continue k 				else feed bytes-		feed bs = k (Chunks [bs]) >>== loop (n - (toInteger (B.length bs)))+		feed bs = k (Chunks [bs]) >>== loop (n - toInteger (B.length bs)) 		in if rem <= 0 			then continue k 			else keepGoing
+ lib/Data/Enumerator/Compatibility.hs view
@@ -0,0 +1,219 @@+-- |+-- Module: Data.Enumerator.Compatibility+-- Copyright: 2010-2011 John Millikin+-- License: MIT+--+-- Maintainer: jmillikin@gmail.com+-- Portability: portable+--+-- Shims for compatibility with earlier versions of the Enumerator library.+module Data.Enumerator.Compatibility+	( liftI+	, head+	, drop+	, dropWhile+	, span+	, break+	, consume+	, foldl+	, foldl'+	, foldM+	, iterate+	, iterateM+	, repeat+	, repeatM+	, replicate+	, replicateM+	, generateM+	, map+	, mapM+	, concatMap+	, concatMapM+	, filter+	, filterM+	, liftFoldL+	, liftFoldL'+	, liftFoldM+	+	) where++import qualified Prelude+import           Prelude (Bool, Integer, Maybe, Monad, not, (.))++import           Data.Enumerator.Internal+import {-# SOURCE #-} qualified Data.Enumerator.List as EL++{-# DEPRECATED liftI "Use 'Data.Enumerator.continue' instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.continue' instead+liftI :: Monad m => (Stream a -> Step a m b)+      -> Iteratee a m b+liftI k = continue (returnI . k)++{-# DEPRECATED head "Use 'Data.Enumerator.List.head' instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.List.head' instead+head :: Monad m => Iteratee a m (Maybe a)+head = EL.head++{-# DEPRECATED drop "Use 'Data.Enumerator.List.drop' instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.List.drop' instead+drop :: Monad m => Integer -> Iteratee a m ()+drop = EL.drop++{-# DEPRECATED dropWhile "Use 'Data.Enumerator.List.dropWhile' instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.List.dropWhile' instead+dropWhile :: Monad m => (a -> Bool) -> Iteratee a m ()+dropWhile = EL.dropWhile++{-# DEPRECATED span "Use 'Data.Enumerator.List.takeWhile' instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.List.takeWhile' instead+span :: Monad m => (a -> Bool) -> Iteratee a m [a]+span = EL.takeWhile++{-# DEPRECATED break "Use 'Data.Enumerator.List.takeWhile' instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.List.takeWhile' instead+break :: Monad m => (a -> Bool) -> Iteratee a m [a]+break p = EL.takeWhile (not . p)++{-# DEPRECATED consume "Use 'Data.Enumerator.List.consume' instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.List.consume' instead+consume :: Monad m => Iteratee a m [a]+consume = EL.consume++{-# DEPRECATED foldl "Use Data.Enumerator.List.fold instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.fold' instead+--+-- Since: 0.4.5+foldl :: Monad m => (b -> a -> b) -> b -> Iteratee a m b+foldl step = continue . loop where+	fold = Prelude.foldl step+	loop acc stream = case stream of+		Chunks [] -> continue (loop acc)+		Chunks xs -> continue (loop (fold acc xs))+		EOF -> yield acc EOF++{-# DEPRECATED foldl' "Use Data.Enumerator.List.fold instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.fold' instead+--+-- Since: 0.4.5+foldl' :: Monad m => (b -> a -> b) -> b -> Iteratee a m b+foldl' = EL.fold++{-# DEPRECATED foldM "Use Data.Enumerator.List.foldM instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.foldM' instead+--+-- Since: 0.4.5+foldM :: Monad m => (b -> a -> m b) -> b -> Iteratee a m b+foldM = EL.foldM++{-# DEPRECATED iterate "Use Data.Enumerator.List.iterate instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.iterate' instead+--+-- Since: 0.4.5+iterate :: Monad m => (a -> a) -> a -> Enumerator a m b+iterate = EL.iterate++{-# DEPRECATED iterateM "Use Data.Enumerator.List.iterateM instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.iterateM' instead+--+-- Since: 0.4.5+iterateM :: Monad m => (a -> m a) -> a -> Enumerator a m b+iterateM = EL.iterateM++{-# DEPRECATED repeat "Use Data.Enumerator.List.repeat instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.repeat' instead+--+-- Since: 0.4.5+repeat :: Monad m => a -> Enumerator a m b+repeat = EL.repeat++{-# DEPRECATED repeatM "Use Data.Enumerator.List.repeatM instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.repeatM' instead+--+-- Since: 0.4.5+repeatM :: Monad m => m a -> Enumerator a m b+repeatM = EL.repeatM++{-# DEPRECATED replicate "Use Data.Enumerator.List.replicate instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.replicate' instead+--+-- Since: 0.4.5+replicate :: Monad m => Integer -> a -> Enumerator a m b+replicate = EL.replicate++{-# DEPRECATED replicateM "Use Data.Enumerator.List.replicateM instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.replicateM' instead+--+-- Since: 0.4.5+replicateM :: Monad m => Integer -> m a -> Enumerator a m b+replicateM = EL.replicateM++{-# DEPRECATED generateM "Use Data.Enumerator.List.generateM instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.generateM' instead+--+-- Since: 0.4.5+generateM :: Monad m => m (Maybe a) -> Enumerator a m b+generateM = EL.generateM++{-# DEPRECATED map "Use Data.Enumerator.List.map instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.map' instead+map :: Monad m => (ao -> ai) -> Enumeratee ao ai m b+map = EL.map++{-# DEPRECATED mapM "Use Data.Enumerator.List.mapM instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.mapM' instead+--+-- Since: 0.4.3+mapM :: Monad m => (ao -> m ai) -> Enumeratee ao ai m b+mapM = EL.mapM++{-# DEPRECATED concatMap "Use Data.Enumerator.List.concatMap instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.concatMap' instead+--+-- Since: 0.4.3+concatMap :: Monad m => (ao -> [ai]) -> Enumeratee ao ai m b+concatMap = EL.concatMap++{-# DEPRECATED concatMapM "Use Data.Enumerator.List.concatMapM instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.concatMapM' instead+--+-- Since: 0.4.5+concatMapM :: Monad m => (ao -> m [ai]) -> Enumeratee ao ai m b+concatMapM = EL.concatMapM++{-# DEPRECATED filter "Use Data.Enumerator.List.filter instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.filter' instead+--+-- Since: 0.4.5+filter :: Monad m => (a -> Bool) -> Enumeratee a a m b+filter = EL.filter++{-# DEPRECATED filterM "Use Data.Enumerator.List.filterM instead" #-}+-- | Deprecated in 0.4.8: use 'Data.Enumerator.List.filterM' instead+--+-- Since: 0.4.5+filterM :: Monad m => (a -> m Bool) -> Enumeratee a a m b+filterM = EL.filterM++{-# DEPRECATED liftFoldL "Use Data.Enumerator.List.fold instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.List.fold' instead+--+-- Since: 0.1.1+liftFoldL :: Monad m => (b -> a -> b) -> b+          -> Iteratee a m b+liftFoldL = foldl++{-# DEPRECATED liftFoldL' "Use Data.Enumerator.List.fold instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.List.fold' instead+--+-- Since: 0.1.1+liftFoldL' :: Monad m => (b -> a -> b) -> b+           -> Iteratee a m b+liftFoldL' = EL.fold++{-# DEPRECATED liftFoldM "Use Data.Enumerator.List.foldM instead" #-}+-- | Deprecated in 0.4.5: use 'Data.Enumerator.List.foldM' instead+--+-- Since: 0.1.1+liftFoldM :: Monad m => (b -> a -> m b) -> b+          -> Iteratee a m b+liftFoldM = EL.foldM
lib/Data/Enumerator/IO.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_HADDOCK hide #-}+ -- | -- Module: Data.Enumerator.IO -- Copyright: 2010-2011 John Millikin
+ lib/Data/Enumerator/Internal.hs view
@@ -0,0 +1,342 @@+-- |+-- Module: Data.Enumerator.Internal+-- Copyright: 2010-2011 John Millikin+-- License: MIT+--+-- Maintainer: jmillikin@gmail.com+-- Portability: portable+--+-- Core enumerator types, and some useful primitives.+--+-- Be careful when using the functions defined in this module, as they will+-- allow you to create iteratees which violate the monad laws.+module Data.Enumerator.Internal+	( Stream (..)+	, Iteratee (..)+	, Step (..)+	, Enumerator+	, Enumeratee+	+	-- * Primitives+	, returnI+	, continue+	, yield+	+	-- * Operators+	, (>>==)+	, (==<<)+	, ($$)+	, (>==>)+	, (<==<)+	+	-- * Miscellaneous+	, enumEOF+	, checkContinue0+	, checkContinue1+	, checkDoneEx+	, checkDone+	+	) where++import           Control.Applicative as A+import qualified Control.Exception as Exc+import qualified Control.Monad as CM+import           Control.Monad.IO.Class (MonadIO, liftIO)+import           Control.Monad.Trans.Class (MonadTrans, lift)+import           Data.Function (fix)+import           Data.Monoid (Monoid, mempty, mappend, mconcat)+import           Data.Typeable ( Typeable, typeOf+                               , Typeable1, typeOf1+                               , mkTyConApp, mkTyCon)++-- | A 'Stream' is a sequence of chunks generated by an 'Enumerator'.+--+-- @('Chunks' [])@ is used to indicate that a stream is still active, but+-- currently has no available data. Iteratees should ignore empty chunks.+data Stream a+	= Chunks [a]+	| EOF+	deriving (Show, Eq)++instance Monad Stream where+	return = Chunks . return+	Chunks xs >>= f = mconcat (fmap f xs)+	EOF >>= _ = EOF++instance Monoid (Stream a) where+	mempty = Chunks mempty+	mappend (Chunks xs) (Chunks ys) = Chunks (xs ++ ys)+	mappend _ _ = EOF++data Step a m b+	-- | The 'Iteratee' is capable of accepting more input. Note that more input+	-- is not necessarily required; the 'Iteratee' might be able to generate a+	-- value immediately if it receives 'EOF'.+	= Continue (Stream a -> Iteratee a m b)+	+	-- | The 'Iteratee' cannot receive any more input, and has generated a+	-- result. Included in this value is left-over input, which can be passed to+	-- composed 'Iteratee's.+	| Yield b (Stream a)+	+	-- | The 'Iteratee' encountered an error which prevents it from proceeding+	-- further.+	| Error Exc.SomeException++-- | The primary data type for this library; an iteratee consumes+-- chunks of input from a stream until it either yields a value or+-- encounters an error.+--+-- Compatibility note: @Iteratee@ will become abstract in @enumerator_0.5@. If+-- you depend on internal implementation details, please import+-- @"Data.Enumerator.Internal"@.++-- In general, iteratees begin in the 'Continue' state. As each chunk is+-- passed to the continuation, the iteratee returns the next step:+-- 'Continue' for more data, 'Yield' when it's finished, or 'Error' to+-- abort processing.+newtype Iteratee a m b = Iteratee+	{ runIteratee :: m (Step a m b)+	}++instance Monad m => Monad (Iteratee a m) where+	return x = yield x (Chunks [])++	m0 >>= f = ($ m0) $ fix $+		\bind m -> Iteratee $ runIteratee m >>= \r1 ->+			case r1 of+				Continue k -> return (Continue (bind . k))+				Error err -> return (Error err)+				Yield x (Chunks []) -> runIteratee (f x)+				Yield x extra -> runIteratee (f x) >>= \r2 ->+					case r2 of+						Continue k -> runIteratee (k extra)+						Error err -> return (Error err)+						Yield x' _ -> return (Yield x' extra)++instance MonadTrans (Iteratee a) where+	lift m = Iteratee (m >>= runIteratee . return)++instance MonadIO m => MonadIO (Iteratee a m) where+	liftIO = lift . liftIO++-- | Enumerators are sources of data, to be consumed by iteratees.+-- Enumerators typically read from an external source (parser, handle,+-- random generator, etc), then feed chunks into an tteratee until:+--+-- * The input source runs out of data.+--+-- * The iteratee yields a result value.+--+-- * The iteratee throws an exception.++-- Since @'Iteratee'@ is an alias for @m ('Step' a m b)@, 'Enumerator's can+-- be considered step transformers of type @'Step' a m b -> m ('Step' a m b)@.+type Enumerator a m b = Step a m b -> Iteratee a m b++-- | An enumeratee acts as a stream adapter; place one between an enumerator+-- and an iteratee, and it changes the type or contents of the input stream.+--+-- Most users will want to combine enumerators, enumeratees, and iteratees+-- using the stream combinators @joinI@ and @joinE@, or their operator aliases+-- @(=$)@ and @($=)@. These combinators are used to manage how left-over input+-- is passed between elements of the data processing pipeline.+type Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai m b)++-- | Since: 0.4.8+instance Typeable1 Stream where+	typeOf1 _ = mkTyConApp tyCon [] where+		tyCon = mkTyCon "Data.Enumerator.Stream"++-- | Since: 0.4.6+instance (Typeable a, Typeable1 m) =>+	Typeable1 (Iteratee a m) where+		typeOf1 i = let+			tyCon = mkTyCon "Data.Enumerator.Iteratee"+			(a, m) = peel i+			+			peel :: Iteratee a m b -> (a, m ())+			peel = undefined+			+			in mkTyConApp tyCon [typeOf a, typeOf1 m]++-- | Since: 0.4.8+instance (Typeable a, Typeable1 m) =>+	Typeable1 (Step a m) where+		typeOf1 s = let+			tyCon = mkTyCon "Data.Enumerator.Step"+			(a, m) = peel s+			+			peel :: Step a m b -> (a, m ())+			peel = undefined+			+			in mkTyConApp tyCon [typeOf a, typeOf1 m]++instance Monad m => Functor (Iteratee a m) where+	fmap = CM.liftM++instance Monad m => A.Applicative (Iteratee a m) where+	pure = return+	(<*>) = CM.ap++instance Functor Stream where+	fmap f (Chunks xs) = Chunks (fmap f xs)+	fmap _ EOF = EOF++-- | Since: 0.4.5+instance A.Applicative Stream where+	pure = return+	(<*>) = CM.ap++-- | @'returnI' step = 'Iteratee' (return step)@+returnI :: Monad m => Step a m b -> Iteratee a m b+returnI step = Iteratee (return step)++-- | @'yield' x extra = 'returnI' ('Yield' x extra)@+--+-- WARNING: due to the current encoding of iteratees in this library,+-- careless use of the 'yield' primitive may violate the monad laws.+-- To prevent this, always make sure that an iteratee never yields+-- extra data unless it has received at least one input element.+--+-- More strictly, iteratees may not yield data that they did not+-- receive as input. Don't use 'yield' to &#x201c;inject&#x201d; elements+-- into the stream.+yield :: Monad m => b -> Stream a -> Iteratee a m b+yield x extra = returnI (Yield x extra)++-- | @'continue' k = 'returnI' ('Continue' k)@+continue :: Monad m => (Stream a -> Iteratee a m b) -> Iteratee a m b+continue k = returnI (Continue k)++infixl 1 >>==+infixr 1 ==<<+infixr 0 $$+infixr 1 >==>+infixr 1 <==<++-- | The most primitive stream operator. @iter >>== enum@ returns a new+-- iteratee which will read from @enum@ before continuing.+(>>==) :: Monad m+       => Iteratee a m b+       -> (Step a m b -> Iteratee a' m b')+       -> Iteratee a' m b'+i >>== f = Iteratee (runIteratee i >>= runIteratee . f)++-- | @('==<<') = flip ('>>==')@+(==<<) :: Monad m+       => (Step a m b -> Iteratee a' m b')+       -> Iteratee a m b+       -> Iteratee a' m b'+(==<<) = flip (>>==)++-- | @('$$') = ('==<<')@+--+-- This is somewhat easier to read when constructing an iteratee from many+-- processing stages. You can treat it like @('$')@, and read the data flow+-- from left to right.+--+-- Since: 0.1.1+($$) :: Monad m+     => (Step a m b -> Iteratee a' m b')+     -> Iteratee a m b+     -> Iteratee a' m b'+($$) = (==<<)++-- | @('>==>') enum1 enum2 step = enum1 step '>>==' enum2@+--+-- The moral equivalent of @('CM.>=>')@ for iteratees.+--+-- Since: 0.1.1+(>==>) :: Monad m+       => Enumerator a m b+       -> (Step a m b -> Iteratee a' m b')+       -> Step a m b+       -> Iteratee a' m b'+(>==>) e1 e2 s = e1 s >>== e2++-- | @('<==<') = flip ('>==>')@+--+-- Since: 0.1.1+(<==<) :: Monad m+       => (Step a m b -> Iteratee a' m b')+       -> Enumerator a m b+       -> Step a m b+       -> Iteratee a' m b'+(<==<) = flip (>==>)++-- | Sends 'EOF' to its iteratee. Most clients should use 'run' or 'run_'+-- instead.+enumEOF :: Monad m => Enumerator a m b+enumEOF (Yield x _) = yield x EOF+enumEOF (Error err) = returnI (Error err)+enumEOF (Continue k) = k EOF >>== check where+	check (Continue _) = error "enumEOF: divergent iteratee"+	check s = enumEOF s++-- | A common pattern in 'Enumeratee' implementations is to check whether+-- the inner 'Iteratee' has finished, and if so, to return its output.+-- 'checkDone' passes its parameter a continuation if the 'Iteratee'+-- can still consume input, or yields otherwise.+--+-- Since: 0.4.3+checkDoneEx :: Monad m =>+	Stream a' ->+	((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) ->+	Enumeratee a' a m b+checkDoneEx _     f (Continue k) = f k+checkDoneEx extra _ step         = yield step extra++-- | @'checkDone' = 'checkDoneEx' ('Chunks' [])@+--+-- Use this for enumeratees which do not have an input buffer.+checkDone :: Monad m =>+	((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) ->+	Enumeratee a' a m b+checkDone = checkDoneEx (Chunks [])++-- | A common pattern in 'Enumerator' implementations is to check whether+-- the inner 'Iteratee' has finished, and if so, to return its output.+-- 'checkContinue0' passes its parameter a continuation if the 'Iteratee'+-- can still consume input; if not, it returns the iteratee's step.+--+-- The type signature here is a bit crazy, but it's actually very easy to+-- use. Take this code:+--+-- > repeat :: Monad m => a -> Enumerator a m b+-- > repeat x = loop where+-- > 	loop (Continue k) = k (Chunks [x]) >>== loop+-- > 	loop step = returnI step+--+-- And rewrite it without the boilerplate:+--+-- > repeat :: Monad m => a -> Enumerator a m b+-- > repeat x = checkContinue0 $ \loop k -> k (Chunks [x] >>== loop+--+-- Since: 0.4.9+checkContinue0 :: Monad m+               => (Enumerator a m b+                -> (Stream a -> Iteratee a m b)+                -> Iteratee a m b)+               -> Enumerator a m b+checkContinue0 inner = loop where+	loop (Continue k) = inner loop k+	loop step = returnI step+++-- | Like 'checkContinue0', but allows each loop step to use a state value:+--+-- > iterate :: Monad m => (a -> a) -> a -> Enumerator a m b+-- > iterate f = checkContinue1 $ \loop a k -> k (Chunks [a]) >>== loop (f a)+--+-- Since: 0.4.9+checkContinue1 :: Monad m+               => ((s1 -> Enumerator a m b)+                -> s1+                -> (Stream a -> Iteratee a m b)+                -> Iteratee a m b)+               -> s1+               -> Enumerator a m b+checkContinue1 inner = loop where+	loop s (Continue k) = inner loop s k+	loop _ step = returnI step
lib/Data/Enumerator/List.hs view
@@ -91,9 +91,8 @@ import           Data.Monoid (mappend) import qualified Data.Set -import           Data.Enumerator hiding ( concatMapM, iterateM, replicateM, head, drop-                                        , foldM, repeatM, generateM, filterM, consume-                                        , length)+import           Data.Enumerator (sequence, throwError)+import           Data.Enumerator.Internal  -- | Consume the entire input stream with a strict left fold, one element -- at a time.@@ -160,7 +159,7 @@ 	loop k (x:xs) = do 		fx <- lift (f x) 		k (Chunks fx) >>==-			checkDoneEx (Chunks xs) (\k' -> loop k' xs)+			checkDoneEx (Chunks xs) (`loop` xs)  -- | @'Data.Enumerator.List.concatMap' f@ applies /f/ to each input element -- and feeds the resulting outputs to the inner iteratee.@@ -676,8 +675,8 @@ 		| len xs <= n = k (Chunks xs) >>== isolate (n - len xs) 		| otherwise = let 			(s1, s2) = L.genericSplitAt n xs-			in k (Chunks s1) >>== (\step -> yield step (Chunks s2))-	loop EOF = k EOF >>== (\step -> yield step EOF)+			in k (Chunks s1) >>== (`yield` Chunks s2)+	loop EOF = k EOF >>== (`yield` EOF) isolate n step = drop n >> return step  -- | Split on elements satisfying a given predicate.
lib/Data/Enumerator/List.hs-boot view
@@ -1,5 +1,5 @@ module Data.Enumerator.List where-import {-# SOURCE #-} Data.Enumerator+import Data.Enumerator.Internal head :: Monad m => Iteratee a m (Maybe a) drop :: Monad m => Integer -> Iteratee a m () dropWhile :: Monad m => (a -> Bool) -> Iteratee a m ()
lib/Data/Enumerator/Text.hs view
@@ -129,9 +129,8 @@ import           System.IO.Error (isEOFError) import           System.IO.Unsafe (unsafePerformIO) -import           Data.Enumerator hiding ( head, drop, generateM, filterM, consume-                                        , concatMapM, iterateM, repeatM, replicateM-                                        , foldM)+import           Data.Enumerator.Internal+import           Data.Enumerator (isEOF, tryIO, throwError) import qualified Data.Enumerator.List as EL import           Data.Enumerator.Util (tSpanBy, tlSpanBy, reprWord, reprChar, textToStrict) @@ -216,7 +215,7 @@ 	loop k (x:xs) = do 		fx <- lift (f x) 		k (Chunks [fx]) >>==-			checkDoneEx (Chunks [T.pack xs]) (\k' -> loop k' xs)+			checkDoneEx (Chunks [T.pack xs]) (`loop` xs)  -- | Similar to 'Data.Enumerator.Text.concatMap', but with a stateful step -- function.@@ -347,7 +346,7 @@ 		len = toInteger (TL.length lazy) 		 		iter = if len < n'-			then continue (loop (acc . (TL.append lazy)) (n' - len))+			then continue (loop (acc . TL.append lazy) (n' - len)) 			else let 				(xs', extra) = TL.splitAt (fromInteger n') lazy 				in yield (acc xs') (toChunks extra)@@ -364,7 +363,7 @@ 		lazy = TL.fromChunks xs 		(xs', extra) = tlSpanBy p lazy 		iter = if TL.null extra-			then continue (loop (acc . (TL.append lazy)))+			then continue (loop (acc . TL.append lazy)) 			else yield (acc xs') (toChunks extra) 	loop acc EOF = yield (acc TL.empty) EOF @@ -376,7 +375,7 @@ 	loop acc (Chunks []) = continue (loop acc) 	loop acc (Chunks xs) = iter where 		lazy = TL.fromChunks xs-		iter = continue (loop (acc . (TL.append lazy)))+		iter = continue (loop (acc . TL.append lazy)) 	loop acc EOF = yield (acc TL.empty) EOF  -- | Pass input from a stream through two iteratees at once. Excess input is@@ -686,7 +685,7 @@ 		lazy = TL.fromChunks xs 		len = toInteger (TL.length lazy) 		iter = if len < n'-			then continue (loop (acc . (TL.append lazy)) (n' - len))+			then continue (loop (acc . TL.append lazy) (n' - len)) 			else yield () (toChunks (acc lazy)) 	loop _ _ EOF = throwError (Exc.ErrorCall "require: Unexpected EOF") @@ -707,8 +706,8 @@ 			then k (Chunks xs) >>== isolate (n - len) 			else let 				(s1, s2) = TL.splitAt (fromInteger n) lazy-				in k (toChunks s1) >>== (\step -> yield step (toChunks s2))-	loop EOF = k EOF >>== (\step -> yield step EOF)+				in k (toChunks s1) >>== (`yield` toChunks s2)+	loop EOF = k EOF >>== (`yield` EOF) isolate n step = drop n >> return step  -- | Split on characters satisfying a given predicate.@@ -838,13 +837,18 @@ decode :: Monad m => Codec        -> Enumeratee B.ByteString T.Text m b decode codec = checkDone (continue . step B.empty) where-	step _   k EOF = yield (Continue k) EOF+	step acc k EOF = if B.null acc+		then yield (Continue k) EOF+		else throwError (Exc.ErrorCall "Unexpected EOF while decoding") 	step acc k (Chunks xs) = loop acc k xs 	 	loop acc k [] = continue (step acc k) 	loop acc k (x:xs) = let 		(text, extra) = codecDecode codec (B.append acc x)-		extraChunks = Chunks (either snd id extra : xs)+		extraChunks = Chunks $ case extra of+			Right bytes | B.null bytes -> xs+			Right bytes -> bytes:xs+			Left (_, bytes) -> bytes:xs 		 		checkError k' = case extra of 			Left (exc, _) -> throwError exc@@ -927,8 +931,8 @@ 		       | (n + 1) == maxN = decodeTo n 		loop n = let 			req = utf16Required-				(B.index bytes 0)-				(B.index bytes 1)+				(B.index bytes n)+				(B.index bytes (n + 1)) 			decodeMore = loop $! n + req 			in if n + req > maxN 				then decodeTo n@@ -952,8 +956,8 @@ 		       | (n + 1) == maxN = decodeTo n 		loop n = let 			req = utf16Required-				(B.index bytes 1)-				(B.index bytes 0)+				(B.index bytes (n + 1))+				(B.index bytes n) 			decodeMore = loop $! n + req 			in if n + req > maxN 				then decodeTo n
lib/Data/Enumerator/Util.hs view
@@ -15,10 +15,10 @@ 		else Prelude.replicate (size - len) '0' ++ str  reprChar :: Char -> String-reprChar c = "U+" ++ (pad0 4 (showIntAtBase 16 (toUpper . intToDigit) (ord c) ""))+reprChar c = "U+" ++ pad0 4 (showIntAtBase 16 (toUpper . intToDigit) (ord c) "")  reprWord :: Word8 -> String-reprWord w = "0x" ++ (pad0 2 (showIntAtBase 16 (toUpper . intToDigit) w ""))+reprWord w = "0x" ++ pad0 2 (showIntAtBase 16 (toUpper . intToDigit) w "")  tSpanBy  :: (Char -> Bool) -> T.Text -> (T.Text, T.Text) tlSpanBy :: (Char -> Bool) -> TL.Text -> (TL.Text, TL.Text)
+ scripts/run-coverage view
@@ -0,0 +1,78 @@+#!/bin/bash+if [ ! -f 'enumerator.cabal' ]; then+	echo -n "Can't find enumerator.cabal; please run this script as"+	echo -n " ./scripts/run-coverage from within the enumerator source"+	echo " directory"+	exit 1+fi++. scripts/common.bash++require_cabal_dev++pushd tests+$CABAL_DEV -s ../cabal-dev install --flags="coverage" || exit 1+popd++rm -f enumerator_tests.tix+cabal-dev/bin/enumerator_tests $@++EXCLUDES="\+--exclude=Main \+--exclude=EnumeratorTests.Binary \+--exclude=EnumeratorTests.Binary.Consume \+--exclude=EnumeratorTests.Binary.Drop \+--exclude=EnumeratorTests.Binary.Fold \+--exclude=EnumeratorTests.Binary.Handle \+--exclude=EnumeratorTests.Binary.Isolate \+--exclude=EnumeratorTests.Binary.Iterate \+--exclude=EnumeratorTests.Binary.Map \+--exclude=EnumeratorTests.Binary.Repeat \+--exclude=EnumeratorTests.Binary.Replicate \+--exclude=EnumeratorTests.Binary.Require \+--exclude=EnumeratorTests.Binary.Split \+--exclude=EnumeratorTests.Binary.Unfold \+--exclude=EnumeratorTests.Binary.Util \+--exclude=EnumeratorTests.Binary.Zip \+--exclude=EnumeratorTests.CatchError \+--exclude=EnumeratorTests.Compatibility \+--exclude=EnumeratorTests.Instances \+--exclude=EnumeratorTests.Join \+--exclude=EnumeratorTests.List \+--exclude=EnumeratorTests.List.Consume \+--exclude=EnumeratorTests.List.Drop \+--exclude=EnumeratorTests.List.Fold \+--exclude=EnumeratorTests.List.Isolate  \+--exclude=EnumeratorTests.List.Iterate \+--exclude=EnumeratorTests.List.Map \+--exclude=EnumeratorTests.List.Repeat \+--exclude=EnumeratorTests.List.Replicate \+--exclude=EnumeratorTests.List.Require \+--exclude=EnumeratorTests.List.Split \+--exclude=EnumeratorTests.List.Unfold \+--exclude=EnumeratorTests.List.Unique \+--exclude=EnumeratorTests.List.Util \+--exclude=EnumeratorTests.List.Zip \+--exclude=EnumeratorTests.Misc \+--exclude=EnumeratorTests.Sequence \+--exclude=EnumeratorTests.Stream \+--exclude=EnumeratorTests.Text \+--exclude=EnumeratorTests.Text.Codecs \+--exclude=EnumeratorTests.Text.Consume \+--exclude=EnumeratorTests.Text.Drop \+--exclude=EnumeratorTests.Text.Fold \+--exclude=EnumeratorTests.Text.Handle \+--exclude=EnumeratorTests.Text.Isolate \+--exclude=EnumeratorTests.Text.Iterate \+--exclude=EnumeratorTests.Text.Map \+--exclude=EnumeratorTests.Text.Repeat \+--exclude=EnumeratorTests.Text.Replicate \+--exclude=EnumeratorTests.Text.Require \+--exclude=EnumeratorTests.Text.Split \+--exclude=EnumeratorTests.Text.Unfold \+--exclude=EnumeratorTests.Text.Util \+--exclude=EnumeratorTests.Text.Zip \+--exclude=EnumeratorTests.Util"++hpc markup --srcdir=src/ --srcdir=tests/ enumerator_tests.tix --destdir=hpc-markup $EXCLUDES > /dev/null+hpc report --srcdir=src/ --srcdir=tests/ enumerator_tests.tix $EXCLUDES
+ tests/EnumeratorTests.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module Main+	( tests+	, main+	) where++import           Test.Chell (Suite, defaultMain)++import           EnumeratorTests.Binary (test_Binary)+import           EnumeratorTests.CatchError (test_CatchError)+import           EnumeratorTests.Compatibility (test_Compatibility)+import           EnumeratorTests.Instances (test_Instances)+import           EnumeratorTests.Join+import           EnumeratorTests.List (test_List)+import           EnumeratorTests.Misc+import           EnumeratorTests.Sequence (test_Sequence)+import           EnumeratorTests.Stream (test_Stream)+import           EnumeratorTests.Text (test_Text)++tests :: [Suite]+tests =+	[ test_Binary+	, test_CatchError+	, test_Compatibility+	, test_ConcatEnums+	, test_EnumEOF+	, test_Instances+	, test_JoinE+	, test_JoinI+	, test_JoinOperatorAssociativity+	, test_Last+	, test_Length+	, test_LiftTrans+	, test_List+	, test_Peek+	, test_PrintChunks+	, test_Sequence+	, test_Stream+	, test_Text+	, test_TryIO+	]++main :: IO ()+main = Test.Chell.defaultMain tests
+ tests/EnumeratorTests/Binary.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary+	( test_Binary+	) where++import           Test.Chell++import           EnumeratorTests.Binary.Consume+import           EnumeratorTests.Binary.Drop+import           EnumeratorTests.Binary.Fold+import           EnumeratorTests.Binary.Handle+import           EnumeratorTests.Binary.Isolate+import           EnumeratorTests.Binary.Iterate+import           EnumeratorTests.Binary.Map+import           EnumeratorTests.Binary.Repeat+import           EnumeratorTests.Binary.Replicate+import           EnumeratorTests.Binary.Require+import           EnumeratorTests.Binary.Split+import           EnumeratorTests.Binary.Unfold+import           EnumeratorTests.Binary.Zip++test_Binary :: Suite+test_Binary = suite "binary"+	[ test_Consume+	, test_ConcatMap+	, test_ConcatMapM+	, test_ConcatMapAccum+	, test_ConcatMapAccumM+	, test_Drop+	, test_DropWhile+	, test_EnumHandle+	, test_EnumHandleRange+	, test_Filter+	, test_FilterM+	, test_Fold+	, test_FoldM+	, test_GenerateM+	, test_Head+	, test_Head_+	, test_Isolate+	, test_Iterate+	, test_IterateM+	, test_IterHandle+	, test_Map+	, test_MapM+	, test_MapM_+	, test_MapAccum+	, test_MapAccumM+	, test_Repeat+	, test_RepeatM+	, test_Replicate+	, test_ReplicateM+	, test_Require+	, test_SplitWhen+	, test_Take+	, test_TakeWhile+	, test_Unfold+	, test_UnfoldM+	, test_Zip+	]
+ tests/EnumeratorTests/Binary/Consume.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Consume+	( test_Consume+	, test_Head+	, test_Head_+	, test_Take+	, test_TakeWhile+	) where++import           Control.Exception+import           Data.Word (Word8)+import           Test.Chell++import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Binary as EB++import           EnumeratorTests.Util (equalExc)++test_Consume :: Suite+test_Consume = assertions "consume" $ do+	$expect $ equal+		("ABC", Nothing)+		(E.runLists_ [[], ["A", "B"], ["C"]] $ do+			xs <- EB.consume+			h <- EL.head+			return (xs, h))++test_Head :: Suite+test_Head = assertions "head" $ do+	$expect $ equal+		(Just 0x41, ["BC", "DE"])+		(E.runLists_ [[], ["ABC", "DE"]] $ do+			x <- EB.head+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(Nothing :: Maybe Word8, [])+		(E.runLists_ [] $ do+			x <- EB.head+			extra <- EL.consume+			return (x, extra))++test_Head_ :: Suite+test_Head_ = assertions "head_" $ do+	$expect $ equal+		(0x41, ["BC", "DE"])+		(E.runLists_ [["ABC"], ["DE"]] $ do+			x <- EB.head_+			extra <- EL.consume+			return (x, extra))+	$expect $ equalExc+		(ErrorCall "head_: stream has ended")+		(E.runLists [] $ do+			x <- EB.head_+			extra <- EL.consume+			return (x, extra))++test_Take :: Suite+test_Take = assertions "take" $ do+	$expect $ equal+		("ABC", ["D", "E"])+		(E.runLists_ [["A", "B"], ["C", "D"], ["E"]] $ do+			x <- EB.take 3+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		("AB", [])+		(E.runLists_ [["A"], ["B"]] $ do+			x <- EB.take 3+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		("", ["A", "B"])+		(E.runLists_ [["A"], ["B"]] $ do+			x <- EB.take 0+			extra <- EL.consume+			return (x, extra))++test_TakeWhile :: Suite+test_TakeWhile = assertions "takeWhile" $ do+	$expect $ equal+		("ABC", ["D", "E"])+		(E.runLists_ [[], ["A", "B"], ["C", "D"], ["E"]] $ do+			x <- EB.takeWhile (< 0x44)+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		("AB", [])+		(E.runLists_ [["A"], ["B"]] $ do+			x <- EB.takeWhile (< 0x44)+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		("", ["A", "B"])+		(E.runLists_ [["A"], ["B"]] $ do+			x <- EB.takeWhile (< 0x41)+			extra <- EL.consume+			return (x, extra))
+ tests/EnumeratorTests/Binary/Drop.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Drop+	( test_Drop+	, test_DropWhile+	, test_Filter+	, test_FilterM+	) where++import           Test.Chell++import           Data.Enumerator ((=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++test_Drop :: Suite+test_Drop = assertions "drop" $ do+	$expect $ equal+		["ABCDE"]+		(E.runLists_ [["ABCDE"]] $ do+			EB.drop 0+			EL.consume)+	$expect $ equal+		["CDE"]+		(E.runLists_ [["ABCDE"]] $ do+			EB.drop 2+			EL.consume)+	$expect $ equal+		["CDE"]+		(E.runLists_ [["A"], ["BCDE"]] $ do+			EB.drop 2+			EL.consume)++test_DropWhile :: Suite+test_DropWhile = assertions "dropWhile" $ do+	$expect $ equal+		["CDE"]+		(E.runLists_ [["ABCDE"]] $ do+			EB.dropWhile (< 0x43)+			EL.consume)+	$expect $ equal+		[]+		(E.runLists_ [["ABCDE"]] $ do+			EB.dropWhile (\_ -> True)+			EL.consume)++test_Filter :: Suite+test_Filter = assertions "filter" $ do+	$expect $ equal+		["A", "B", "", "D", "E"]+		(E.runLists_ [["ABCDE"]] $ do+			EB.filter (/= 0x43) =$ EL.consume)++test_FilterM :: Suite+test_FilterM = assertions "filterM" $ do+	$expect $ equal+		["A", "B", "", "D", "E"]+		(E.runLists_ [["ABCDE"]] $ do+			EB.filterM (\x -> return (x /= 0x43)) =$ EL.consume)
+ tests/EnumeratorTests/Binary/Fold.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Fold+	( test_Fold+	, test_FoldM+	) where++import           Control.Monad (foldM)+import qualified Data.ByteString+import           Data.ByteString (ByteString)+import           Data.Functor.Identity (runIdentity)+import           Data.Word (Word8)+import           Test.Chell+import           Test.Chell.QuickCheck+import           Test.QuickCheck.Poly+import           Test.QuickCheck.Modifiers++import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB++import           EnumeratorTests.Util ()++test_Fold :: Suite+test_Fold = property "fold" prop_Fold++prop_Fold :: Blind (B -> Word8 -> B) -> B -> ByteString -> Bool+prop_Fold (Blind f) z text = result == expected where+	result = E.runLists_ [[text]] (EB.fold f z)+	expected = Data.ByteString.foldl' f z text++test_FoldM :: Suite+test_FoldM = property "foldM" prop_FoldM++prop_FoldM :: Blind (B -> Word8 -> B) -> B -> ByteString -> Bool+prop_FoldM (Blind f) z text = result == expected where+	result = E.runLists_ [[text]] (EB.foldM f' z)+	expected = runIdentity (foldM f' z (Data.ByteString.unpack text))+	f' b a = return (f b a)
+ tests/EnumeratorTests/Binary/Handle.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Handle+	( test_EnumHandle+	, test_EnumHandleRange+	, test_IterHandle+	) where++import           Test.Chell++#ifdef MIN_VERSION_knob++import           Data.Knob+import qualified System.IO as IO++import qualified Data.Enumerator as E+import           Data.Enumerator (($$))+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++test_EnumHandle :: Suite+test_EnumHandle = assertions "enumHandle" $ do+	knob <- newKnob "01234567"+	chunks <- withFileHandle knob "" IO.ReadMode $ \h -> do+		E.run_ (EB.enumHandle 3 h $$ EL.consume)+	$expect (equal chunks ["012", "345", "67"])++test_EnumHandleRange :: Suite+test_EnumHandleRange = assertions "enumHandleRange" $ do+	knob <- newKnob "01234567"+	+	-- no offset or count+	do+		chunks <- withFileHandle knob "" IO.ReadMode $ \h -> do+			E.run_ (EB.enumHandleRange 3 Nothing Nothing h $$ EL.consume)+		$expect (equal chunks ["012", "345", "67"])+	+	-- offset+	do+		chunks <- withFileHandle knob "" IO.ReadMode $ \h -> do+			E.run_ (EB.enumHandleRange 3 (Just 1) Nothing h $$ EL.consume)+		$expect (equal chunks ["123", "456", "7"])+	+	-- count+	do+		chunks <- withFileHandle knob "" IO.ReadMode $ \h -> do+			E.run_ (EB.enumHandleRange 3 Nothing (Just 7) h $$ EL.consume)+		$expect (equal chunks ["012", "345", "6"])+	+	-- count beyond EOF+	do+		chunks <- withFileHandle knob "" IO.ReadMode $ \h -> do+			E.run_ (EB.enumHandleRange 3 Nothing (Just 10) h $$ EL.consume)+		$expect (equal chunks ["012", "345", "67"])+	+	-- offset + count+	do+		chunks <- withFileHandle knob "" IO.ReadMode $ \h -> do+			E.run_ (EB.enumHandleRange 3 (Just 1) (Just 6) h $$ EL.consume)+		$expect (equal chunks ["123", "456"])++test_IterHandle :: Suite+test_IterHandle = assertions "iterHandle" $ do+	knob <- newKnob ""+	withFileHandle knob "" IO.WriteMode $ \h -> do+		E.run_ (E.enumLists [[], ["A", "B"], ["C"]] $$ EB.iterHandle h)+	bytes <- Data.Knob.getContents knob+	$expect (equal bytes "ABC")++#else++import           EnumeratorTests.Util (todo)++test_EnumHandle :: Suite+test_EnumHandle = todo "enumHandle"++test_EnumHandleRange :: Suite+test_EnumHandleRange = todo "enumHandleRange"++test_IterHandle :: Suite+test_IterHandle = todo "iterHandle"++#endif
+ tests/EnumeratorTests/Binary/Isolate.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Isolate+	( test_Isolate+	) where++import qualified Data.ByteString.Lazy as BL+import           Data.Word (Word8)++import           Test.Chell+import           Test.Chell.QuickCheck++import           Data.Enumerator (($$), (=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.Binary.Util (prop_Bytes)++test_Isolate :: Suite+test_Isolate = suite "isolate"+	[ prop_Isolate+	, test_DropExtra+	, test_HandleEOF+	, test_BadParameter+	]++prop_Isolate :: Suite+prop_Isolate = property "model" $ prop_Bytes+	(do+		x <- E.joinI (EB.isolate 2 $$ EB.head)+		extra <- EB.consume+		return (x, extra))+	(\bytes -> Right $ case BL.unpack bytes of+		[] -> (Nothing, BL.empty)+		(x:[]) -> (Just x, BL.empty)+		(x:_:xs) -> (Just x, BL.pack xs))++test_DropExtra :: Suite+test_DropExtra = assertions "drop-extra" $ do+	$expect $ equal+		(Just 0x41, ["C"])+		(E.runLists_ [[], ["A"], ["B"], ["C"]] $ do+			x <- EB.isolate 2 =$ EB.head+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(Just 0x41, ["C"])+		(E.runLists_ [["A", "B", "C"]] $ do+			x <- EB.isolate 2 =$ EB.head+			extra <- EL.consume+			return (x, extra))++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ equal+		(Nothing :: Maybe Word8, [])+		(E.runLists_ [] $ do+			x <- EB.isolate 2 =$ EB.head+			extra <- EL.consume+			return (x, extra))++test_BadParameter :: Suite+test_BadParameter = assertions "bad-parameter" $ do+	$expect $ equal+		(Nothing, ["A", "B", "C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			x <- EB.isolate 0 =$ EB.head+			extra <- EL.consume+			return (x, extra))
+ tests/EnumeratorTests/Binary/Iterate.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Iterate+	( test_Iterate+	, test_IterateM+	) where++import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++test_Iterate :: Suite+test_Iterate = assertions "iterate" $ do+	$expect $ equal+		["A", "B", "C"]+		(runIdentity (E.run_ (EB.iterate succ 0x41 $$ EL.take 3)))++test_IterateM :: Suite+test_IterateM = assertions "iterateM" $ do+	let succM = return . succ+	$expect $ equal+		["A", "B", "C"]+		(runIdentity (E.run_ (EB.iterateM succM 0x41 $$ EL.take 3)))
+ tests/EnumeratorTests/Binary/Map.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Map+	( test_Map+	, test_MapM+	, test_MapM_+	, test_ConcatMap+	, test_ConcatMapM+	, test_ConcatMapAccum+	, test_ConcatMapAccumM+	, test_MapAccum+	, test_MapAccumM+	) where++import           Control.Monad.Trans.Writer (execWriter, tell)+import qualified Data.ByteString as B+import           Test.Chell++import           Data.Enumerator (($$), (=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++test_Map :: Suite+test_Map = assertions "map" $ do+	$expect $ equal+		["a", "b"]+		(E.runLists_ [["AB"]] $ do+			EB.map (+ 0x20) =$ EL.consume)+	$expect $ equal+		(["a", "b"], ["CDEF", "GH"])+		(E.runLists_ [["ABCD", "EF"], ["GH"]] $ do+			xs <- EB.map (+ 0x20) =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_MapM :: Suite+test_MapM = assertions "mapM" $ do+	$expect $ equal+		["a", "b"]+		(E.runLists_ [["AB"]] $ do+			EB.mapM (\x -> return (x + 0x20)) =$ EL.consume)+	$expect $ equal+		(["a", "b"], ["CDEF", "GH"])+		(E.runLists_ [["ABCD", "EF"], ["GH"]] $ do+			xs <- EB.mapM (\x -> return (x + 0x20)) =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_MapM_ :: Suite+test_MapM_ = assertions "mapM_" $ do+	$expect $ equal+		[0x41, 0x42]+		(execWriter (E.run_ (E.enumLists [["AB"]] $$ EB.mapM_ (\x -> tell [x]))))++test_ConcatMap :: Suite+test_ConcatMap = assertions "concatMap" $ do+	$expect $ equal+		["Aa", "Bb"]+		(E.runLists_ [["AB"]] $ do+			EB.concatMap (\x -> B.pack [x, x + 0x20]) =$ EL.consume)+	$expect $ equal+		(["Aa", "Bb"], ["CDEF", "GH"])+		(E.runLists_ [["ABCD", "EF"], ["GH"]] $ do+			xs <- EB.concatMap (\x -> B.pack [x, x + 0x20]) =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_ConcatMapM :: Suite+test_ConcatMapM = assertions "concatMapM" $ do+	$expect $ equal+		["Aa", "Bb"]+		(E.runLists_ [["AB"]] $ do+			EB.concatMapM (\x -> return (B.pack [x, x + 0x20])) =$ EL.consume)+	$expect $ equal+		(["Aa", "Bb"], ["CDEF", "GH"])+		(E.runLists_ [["ABCD", "EF"], ["GH"]] $ do+			xs <- EB.concatMapM (\x -> return (B.pack [x, x + 0x20])) =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_MapAccum :: Suite+test_MapAccum = assertions "mapAccum" $ do+	let step s ao = (s + 1, ao + s)+	$expect $ equal+		["B", "D", "F"]+		(E.runLists_ [["A", "B"], ["C"]] $ do+			EB.mapAccum step 1 =$ EL.consume)+	$expect $ equal+		("B", ["", "B", "C"])+		(E.runLists_ [["A", "B"], ["C"]] $ do+			xs <- EB.mapAccum step 1 =$ EB.take 1+			extra <- EL.consume+			return (xs, extra))++test_MapAccumM :: Suite+test_MapAccumM = assertions "mapAccumM" $ do+	let step s ao = return (s + 1, ao + s)+	$expect $ equal+		["B", "D", "F"]+		(E.runLists_ [["A", "B"], ["C"]] $ do+			EB.mapAccumM step 1 =$ EL.consume)+	$expect $ equal+		("B", ["", "B", "C"])+		(E.runLists_ [["A", "B"], ["C"]] $ do+			xs <- EB.mapAccumM step 1 =$ EB.take 1+			extra <- EL.consume+			return (xs, extra))++test_ConcatMapAccum :: Suite+test_ConcatMapAccum = assertions "concatMapAccum" $ do+	let step s ao = (s + 1, B.replicate s ao)+	$expect $ equal+		["A", "BB", "CCC"]+		(E.runLists_ [["A", "B"], ["C"]] $ do+			EB.concatMapAccum step 1 =$ EL.consume)+	$expect $ equal+		("AB", ["", "C"])+		(E.runLists_ [["A", "B"], ["C"]] $ do+			xs <- EB.concatMapAccum step 1 =$ EB.take 2+			extra <- EL.consume+			return (xs, extra))++test_ConcatMapAccumM :: Suite+test_ConcatMapAccumM = assertions "concatMapAccumM" $ do+	let step s ao = return (s + 1, B.replicate s ao)+	$expect $ equal+		["A", "BB", "CCC"]+		(E.runLists_ [["A", "B"], ["C"]] $ do+			EB.concatMapAccumM step 1 =$ EL.consume)+	$expect $ equal+		("AB", ["", "C"])+		(E.runLists_ [["A", "B"], ["C"]] $ do+			xs <- EB.concatMapAccumM step 1 =$ EB.take 2+			extra <- EL.consume+			return (xs, extra))
+ tests/EnumeratorTests/Binary/Repeat.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Repeat+	( test_Repeat+	, test_RepeatM+	, test_GenerateM+	) where++import           Control.Monad.Trans.State+import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++test_Repeat :: Suite+test_Repeat = assertions "repeat" $ do+	$expect $ equal+		["A", "A", "A"]+		(runIdentity (E.run_ (EB.repeat 0x41 $$ EL.take 3)))++test_RepeatM :: Suite+test_RepeatM = assertions "repeatM" $ do+	let step = do+		c <- get+		put (succ c)+		return c+	$expect $ equal+		["A", "B", "C"]+		(evalState (E.run_ (EB.repeatM step $$ EL.take 3)) 0x41)++test_GenerateM :: Suite+test_GenerateM = assertions "generateM" $ do+	let step = do+		c <- get+		if c > 0x43+			then return Nothing+			else do+				put (succ c)+				return (Just c)+	$expect $ equal+		["A", "B", "C"]+		(evalState (E.run_ (EB.generateM step $$ EL.consume)) 0x41)
+ tests/EnumeratorTests/Binary/Replicate.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Replicate+	( test_Replicate+	, test_ReplicateM+	) where++import           Control.Monad.Trans.State+import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++test_Replicate :: Suite+test_Replicate = assertions "replicate" $ do+	$expect $ equal+		["A", "A", "A"]+		(runIdentity (E.run_ (EB.replicate 3 0x41 $$ EL.consume)))++test_ReplicateM :: Suite+test_ReplicateM = assertions "replicateM" $ do+	let step = do+		c <- get+		put (succ c)+		return c+	$expect $ equal+		["A", "B", "C"]+		(evalState (E.run_ (EB.replicateM 3 step $$ EL.consume)) 0x41)+	$expect $ equal+		["A", "B"]+		(evalState (E.run_ (EB.replicateM 3 step $$ EL.take 2)) 0x41)
+ tests/EnumeratorTests/Binary/Require.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Require+	( test_Require+	) where++import qualified Control.Exception as Exc+import qualified Data.ByteString.Lazy as BL+import           Test.Chell+import           Test.Chell.QuickCheck++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.Binary.Util++test_Require :: Suite+test_Require = suite "require"+	[ prop_Require+	, test_YieldsInput+	, test_HandleEOF+	, test_BadParameter+	]++prop_Require :: Suite+prop_Require = property "model" $ prop_BytesN+	(\n -> do+		EB.require n+		EB.consume)+	(\n xs -> if n > toInteger (BL.length xs)+		then Left (Exc.ErrorCall "require: Unexpected EOF")+		else Right xs)++test_YieldsInput :: Suite+test_YieldsInput = assertions "yields-input" $ do+	$expect $ equal+		["A", "B", "C"]+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			EB.require 2+			EL.consume)+	$expect $ equal+		["A", "B", "C"]+		(E.runLists_ [["A", "B", "C"]] $ do+			EB.require 2+			EL.consume)++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ throwsEq+		(Exc.ErrorCall "require: Unexpected EOF")+		(E.run_ (E.enumLists [] $$ do+			EB.require 2+			EL.consume))++test_BadParameter :: Suite+test_BadParameter = assertions "bad-parameter" $ do+	$expect $ equal+		[]+		(E.runLists_ [] $ do+			EB.require 0+			EL.consume)
+ tests/EnumeratorTests/Binary/Split.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Split+	( test_SplitWhen+	) where++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL++import qualified Data.List.Split as LS+import           Test.Chell+import           Test.Chell.QuickCheck++import           Data.Enumerator (($$), (=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Binary as EB++import           EnumeratorTests.Binary.Util++test_SplitWhen :: Suite+test_SplitWhen = suite "splitWhen"+	[ prop_SplitWhen+	, test_HandleEmpty+	]++prop_SplitWhen :: Suite+prop_SplitWhen = property "model" $ prop_BytesX+	(\c -> do+		xs <- E.joinI (EB.splitWhen (== c) $$ EL.consume)+		extra <- EL.consume+		return (xs, extra))+	(\c text -> let+		split = LS.split . LS.dropFinalBlank . LS.dropDelims . LS.whenElt+		chars = BL.unpack text+		in Right (map B.pack (split (== c) chars), []))++test_HandleEmpty :: Suite+test_HandleEmpty = assertions "empty" $ do+	$expect $ equal+		([], Nothing)+		(E.runLists_ [[""]] $ do+			xs <- EB.splitWhen (== 0x2C) =$ EL.consume+			extra <- EL.head+			return (xs, extra))
+ tests/EnumeratorTests/Binary/Unfold.hs view
@@ -0,0 +1,37 @@++{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Unfold+	( test_Unfold+	, test_UnfoldM+	) where++import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++test_Unfold :: Suite+test_Unfold = assertions "unfold" $ do+	let step x = if x > 0x43+		then Nothing+		else Just (x, succ x)+	$expect $ equal+		["A", "B", "C"]+		(runIdentity (E.run_ (EB.unfold step 0x41 $$ EL.consume)))++test_UnfoldM :: Suite+test_UnfoldM = assertions "unfoldM" $ do+	let step x = return $ if x > 0x43+		then Nothing+		else Just (x, succ x)+	$expect $ equal+		["A", "B", "C"]+		(runIdentity (E.run_ (EB.unfoldM step 0x41 $$ EL.consume)))
+ tests/EnumeratorTests/Binary/Util.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Util+	( prop_Bytes+	, prop_BytesN+	, prop_BytesX+	) where++import           Control.Exception (ErrorCall)+import           Data.ByteString (ByteString)+import qualified Data.ByteString.Lazy as BL+import           Data.Functor.Identity (Identity)++import           Test.QuickCheck hiding (property)++import           Data.Enumerator (Iteratee)++import           EnumeratorTests.Util (check)++prop_Bytes :: Eq b+           => Iteratee ByteString Identity b+           -> (BL.ByteString -> Either ErrorCall b)+           -> [ByteString]+           -> Bool+prop_Bytes iter plain = check iter (plain . BL.fromChunks)++prop_BytesN :: Eq b+            => (t -> Iteratee ByteString Identity b)+            -> (t -> BL.ByteString -> Either ErrorCall b)+            -> Positive t+            -> [ByteString]+            -> Bool+prop_BytesN iter plain (Positive n) = check (iter n) (plain n . BL.fromChunks)++prop_BytesX :: Eq b+            => (t -> Iteratee ByteString Identity b)+            -> (t -> BL.ByteString -> Either ErrorCall b)+            -> t+            -> [ByteString]+            -> Bool+prop_BytesX iter plain x = check (iter x) (plain x . BL.fromChunks)
+ tests/EnumeratorTests/Binary/Zip.hs view
@@ -0,0 +1,165 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Binary.Zip+	( test_Zip+	) where++import qualified Control.Exception as Exc+import           Data.ByteString (ByteString)+import           Data.Functor.Identity (Identity)+import           Data.Text (Text)+import           Test.Chell++import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.Util (equalExc)++test_ZipN :: (Eq b, Show b) => Text -> E.Iteratee ByteString Identity b -> b -> Suite+test_ZipN name iter expected = assertions name $ do+	$expect $ equal+		expected+		(E.runLists_ [[], ["A"], ["B"]] iter)++$([d||])++test_Zip :: Suite+test_Zip = suite "zip"+	[ test_ContinueContinue+	, test_YieldContinue+	, test_ContinueYield+	, test_YieldYield+	, test_ErrorFirst+	, test_ErrorSecond+	, test_HandleEOF+	, test_Zip3+	, test_Zip4+	, test_Zip5+	, test_Zip6+	, test_Zip7+	, test_ZipWith+	, test_ZipWith3+	, test_ZipWith4+	, test_ZipWith5+	, test_ZipWith6+	, test_ZipWith7+	]++test_ContinueContinue :: Suite+test_ContinueContinue = assertions "continue-continue" $ do+	$expect $ equal+		("AB", "AB", ["C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			(x, y) <- EB.zip (EB.take 2) (EB.take 2)+			extra <- EL.consume+			return (x, y, extra))++test_YieldContinue :: Suite+test_YieldContinue = assertions "yield-continue" $ do+	$expect $ equal+		("A", "AB", ["C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			(x, y) <- EB.zip (EB.take 1) (EB.take 2)+			extra <- EL.consume+			return (x, y, extra))++test_ContinueYield :: Suite+test_ContinueYield = assertions "continue-yield" $ do+	$expect $ equal+		("AB", "A", ["C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			(x, y) <- EB.zip (EB.take 2) (EB.take 1)+			extra <- EL.consume+			return (x, y, extra))++test_YieldYield :: Suite+test_YieldYield = assertions "yield-yield" $ do+	$expect $ equal+		("A", "A", ["B", "C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			(x, y) <- EB.zip (EB.take 1) (EB.take 1)+			extra <- EL.consume+			return (x, y, extra))++test_ErrorFirst :: Suite+test_ErrorFirst = assertions "error-first" $ do+	$expect $ equalExc+		(Exc.ErrorCall "error")+		(E.runLists [["A"], ["B"], ["C"]] $ do+			EB.zip (E.throwError (Exc.ErrorCall "error")) (EB.take 1))++test_ErrorSecond :: Suite+test_ErrorSecond = assertions "error-second" $ do+	$expect $ equalExc+		(Exc.ErrorCall "error")+		(E.runLists [["A"], ["B"], ["C"]] $ do+			EB.zip (EB.take 1) (E.throwError (Exc.ErrorCall "error")))++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ equal+		("A", "AB", [])+		(E.runLists_ [["A"], ["B"]] $ do+			(x, y) <- EB.zip (EB.take 1) (EB.take 3)+			extra <- EL.consume+			return (x, y, extra))++test_Zip3 :: Suite+test_Zip3 = test_ZipN "zip3"+	(EB.zip3 EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41)++test_Zip4 :: Suite+test_Zip4 = test_ZipN "zip4"+	(EB.zip4 EB.head EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41, Just 0x41)++test_Zip5 :: Suite+test_Zip5 = test_ZipN "zip5"+	(EB.zip5 EB.head EB.head EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41)++test_Zip6 :: Suite+test_Zip6 = test_ZipN "zip6"+	(EB.zip6 EB.head EB.head EB.head EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41)++test_Zip7 :: Suite+test_Zip7 = test_ZipN "zip7"+	(EB.zip7 EB.head EB.head EB.head EB.head EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41)++test_ZipWith :: Suite+test_ZipWith = test_ZipN "zipWith"+	(EB.zipWith (,) EB.head EB.head)+	(Just 0x41, Just 0x41)++test_ZipWith3 :: Suite+test_ZipWith3 = test_ZipN "zipWith3"+	(EB.zipWith3 (,,) EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41)++test_ZipWith4 :: Suite+test_ZipWith4 = test_ZipN "zipWith4"+	(EB.zipWith4 (,,,) EB.head EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41, Just 0x41)++test_ZipWith5 :: Suite+test_ZipWith5 = test_ZipN "zipWith5"+	(EB.zipWith5 (,,,,) EB.head EB.head EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41)++test_ZipWith6 :: Suite+test_ZipWith6 = test_ZipN "zipWith6"+	(EB.zipWith6 (,,,,,) EB.head EB.head EB.head EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41)++test_ZipWith7 :: Suite+test_ZipWith7 = test_ZipN "zipWith7"+	(EB.zipWith7 (,,,,,,) EB.head EB.head EB.head EB.head EB.head EB.head EB.head)+	(Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41, Just 0x41)
+ tests/EnumeratorTests/CatchError.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.CatchError+	( test_CatchError+	) where++import           Control.Concurrent+import qualified Control.Exception as Exc+import           Control.Monad.IO.Class (liftIO)++import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.Util (equalExc, within)++test_CatchError :: Suite+test_CatchError = suite "catchError"+	[ test_WithoutContinue+	, test_NotDivergent+	, test_Interleaved+	, test_YieldImmediately+	, test_HandleError+	, test_HandleEOF+	, test_GotStream+	]++test_WithoutContinue :: Suite+test_WithoutContinue = assertions "without-continue" $ do+	$expect $ equalExc+		(Exc.ErrorCall "require: Unexpected EOF")+		(E.runLists [] $ E.catchError+			(E.throwError (Exc.ErrorCall "error"))+			(\_ -> EL.require 1))++test_NotDivergent :: Suite+test_NotDivergent = assertions "not-divergent" $ do+	$expect $ equalExc+		(Exc.ErrorCall "require: Unexpected EOF")+		(E.runLists [] $ E.catchError+			(do+				_ <- EL.head+				E.throwError (Exc.ErrorCall "error"))+			(\_ -> EL.require 1))++test_Interleaved :: Suite+test_Interleaved = within 1000 $ assertions "interleaved" $ do+	let enumMVar mvar = EL.repeatM (liftIO (takeMVar mvar))+	let iter mvar = do+	    	liftIO (putMVar mvar ())+	    	_ <- EL.head+	    	return True+	let onError _ = return False+	+	mvar <- liftIO newEmptyMVar+	E.run_ (enumMVar mvar $$ E.catchError (iter mvar) onError)++test_YieldImmediately :: Suite+test_YieldImmediately = assertions "yield-immediately" $ do+	$expect $ equal+		'A'+		(E.runLists_ [['A']] $ do+			E.catchError (return 'A') (\_ -> return 'B'))++test_HandleError :: Suite+test_HandleError = assertions "handle-error" $ do+	$expect $ equal+		"error"+		(E.runLists_ [] $ E.catchError+			(EL.head >> E.throwError (Exc.ErrorCall "error"))+			(\err -> return (show err)))+	$expect $ equal+		"error"+		(E.runLists_ [['A']] $ E.catchError+			(E.throwError (Exc.ErrorCall "error"))+			(\err -> return (show err)))+	$expect $ equal+		"error"+		(E.runLists_ [['A'], ['B'], ['C']] $ E.catchError+			(EL.drop 1 >> E.throwError (Exc.ErrorCall "error"))+			(\err -> return (show err)))++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ equal+		(Nothing, Nothing)+		(E.runLists_ [] $ do+			x <- E.catchError EL.head (\_ -> return (Just 'B'))+			y <- EL.head+			return (x, y))++test_GotStream :: Suite+test_GotStream = assertions "got-stream" $ do+	$expect $ equal+		(Just 'B')+		(E.runLists_ [['A'], ['B'], ['C']] $ E.catchError+			(do+				_ <- EL.head+				_ <- EL.head+				E.throwError (Exc.ErrorCall "error"))+			(\_ -> EL.head))
+ tests/EnumeratorTests/Compatibility.hs view
@@ -0,0 +1,204 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Compatibility+	( test_Compatibility+	) where++import           Data.Functor.Identity (Identity, runIdentity)+import           Data.Text (Text)+import           Test.Chell++import qualified Data.Enumerator as E+import           Data.Enumerator (($$), (=$))+import qualified Data.Enumerator.List as EL++compatIter :: (Eq a, Show a)+           => Text+           -> E.Iteratee Char Identity a+           -> E.Iteratee Char Identity a+           -> Suite+compatIter name i1 i2 = assertions name $ do+	let run i = E.runLists_ [[], ['A', 'B'], ['C', 'D'], ['E']] $ do+		x <- i+		y <- EL.consume+		return (x, y)+	$expect (equal (run i1) (run i2))++compatEnum :: (Eq a, Show a)+           => Text+           -> E.Enumerator a Identity [a]+           -> E.Enumerator a Identity [a]+           -> Suite+compatEnum name e1 e2 = assertions name $ do+	let run e = runIdentity (E.run_ (e $$ EL.take 10))+	$expect (equal (run e1) (run e2))++compatEnee :: (Eq ai, Show ai)+           => Text+           -> E.Enumeratee Char ai Identity [ai]+           -> E.Enumeratee Char ai Identity [ai]+           -> Suite+compatEnee name e1 e2 = assertions name $ do+	let run e = E.runLists_ [[], ['A', 'B'], ['C', 'D'], ['E']] (e =$ EL.consume)+	$expect (equal (run e1) (run e2))++$([d||])++test_Compatibility :: Suite+test_Compatibility = suite "compatibility"+	[ test_Head+	, test_Drop+	, test_DropWhile+	, test_Span+	, test_Break+	, test_Consume+	, test_Foldl+	, test_Foldl'+	, test_FoldM+	, test_Iterate+	, test_IterateM+	, test_Repeat+	, test_RepeatM+	, test_Replicate+	, test_ReplicateM+	, test_GenerateM+	, test_Map+	, test_MapM+	, test_ConcatMap+	, test_ConcatMapM+	, test_Filter+	, test_FilterM+	, test_LiftFoldL+	, test_LiftFoldL'+	, test_LiftFoldM+	, test_LiftI+	]++test_Head :: Suite+test_Head = compatIter "head" E.head EL.head++test_Drop :: Suite+test_Drop = compatIter "drop" (E.drop 1) (EL.drop 1)++test_DropWhile :: Suite+test_DropWhile = compatIter "dropWhile"+	(E.dropWhile (< 'C'))+	(EL.dropWhile (< 'C'))++test_Span :: Suite+test_Span = compatIter "span"+	(E.span (< 'C'))+	(EL.takeWhile (< 'C'))++test_Break :: Suite+test_Break = compatIter "break"+	(E.break (> 'C'))+	(EL.takeWhile (<= 'C'))++test_Consume :: Suite+test_Consume = compatIter "consume" E.consume EL.consume++test_Foldl :: Suite+test_Foldl = compatIter "foldl"+	(E.foldl (flip (:)) [])+	(EL.fold (flip (:)) [])++test_LiftFoldL :: Suite+test_LiftFoldL = compatIter "liftFoldL"+	(E.liftFoldL (flip (:)) [])+	(EL.fold (flip (:)) [])++test_Foldl' :: Suite+test_Foldl' = compatIter "foldl'"+	(E.foldl' (flip (:)) [])+	(EL.fold (flip (:)) [])++test_LiftFoldL' :: Suite+test_LiftFoldL' = compatIter "liftFoldl'"+	(E.liftFoldL' (flip (:)) [])+	(EL.fold (flip (:)) [])++test_FoldM :: Suite+test_FoldM = compatIter "foldM"+	(E.foldM (\xs x -> return (x:xs)) [])+	(EL.foldM (\xs x -> return (x:xs)) [])++test_LiftFoldM :: Suite+test_LiftFoldM = compatIter "liftFoldM"+	(E.liftFoldM (\xs x -> return (x:xs)) [])+	(EL.foldM (\xs x -> return (x:xs)) [])++test_Iterate :: Suite+test_Iterate = compatEnum "iterate"+	(E.iterate succ 'A')+	(EL.iterate succ 'A')++test_IterateM :: Suite+test_IterateM = compatEnum "iterateM"+	(E.iterateM (return . succ) 'A')+	(EL.iterateM (return . succ) 'A')++test_Repeat :: Suite+test_Repeat = compatEnum "repeat"+	(E.repeat 'A')+	(EL.repeat 'A')++test_RepeatM :: Suite+test_RepeatM = compatEnum "repeatM"+	(E.repeatM (return 'A'))+	(EL.repeatM (return 'A'))++test_Replicate :: Suite+test_Replicate = compatEnum "replicate"+	(E.replicate 5 'A')+	(EL.replicate 5 'A')++test_ReplicateM :: Suite+test_ReplicateM = compatEnum "replicateM"+	(E.replicateM 5 (return 'A'))+	(EL.replicateM 5 (return 'A'))++test_GenerateM :: Suite+test_GenerateM = compatEnum "generateM"+	(E.generateM (return (Just 'A')))+	(EL.generateM (return (Just 'A')))++test_Map :: Suite+test_Map = compatEnee "map"+	(E.map succ)+	(EL.map succ)++test_MapM :: Suite+test_MapM = compatEnee "mapM"+	(E.mapM (return . succ))+	(EL.mapM (return . succ))++test_ConcatMap :: Suite+test_ConcatMap = compatEnee "concatMap"+	(E.concatMap (\x -> [succ x]))+	(EL.concatMap (\x -> [succ x]))++test_ConcatMapM :: Suite+test_ConcatMapM = compatEnee "concatMapM"+	(E.concatMapM (\x -> return [succ x]))+	(EL.concatMapM (\x -> return [succ x]))++test_Filter :: Suite+test_Filter = compatEnee "filter"+	(E.filter (< 'C'))+	(EL.filter (< 'C'))++test_FilterM :: Suite+test_FilterM = compatEnee "filterM"+	(E.filterM (return . (< 'C')))+	(EL.filterM (return . (< 'C')))++test_LiftI :: Suite+test_LiftI = compatIter "liftI"+	(E.liftI (\s -> E.Yield s (E.Chunks [])))+	(E.continue (\s -> E.yield s (E.Chunks [])))
+ tests/EnumeratorTests/Instances.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Instances+	( test_Instances+	) where++import           Control.Applicative (pure, (<*>))+import           Data.Functor.Identity (runIdentity)+import           Data.Typeable (typeOf)+import           Test.Chell++import           Data.Enumerator++test_Instances :: Suite+test_Instances = suite "instances"+	[ test_Typeable+	, test_Functor+	, test_Applicative+	]++test_Typeable :: Suite+test_Typeable = suite "typeable"+	[ test_TypeableStream+	, test_TypeableIteratee+	, test_TypeableStep+	]++test_TypeableStream :: Suite+test_TypeableStream = assertions "stream" $ do+	let x = undefined :: Stream Char+	$expect $ equal+		"Data.Enumerator.Stream Char"+		(show (typeOf x))++test_TypeableIteratee :: Suite+test_TypeableIteratee = assertions "iteratee" $ do+	let x = undefined :: Iteratee Char Maybe Int+	$expect $ equal+		"Data.Enumerator.Iteratee Char Maybe Int"+		(show (typeOf x))++test_TypeableStep :: Suite+test_TypeableStep = assertions "step" $ do+	let x = undefined :: Step Char Maybe Int+	$expect $ equal+		"Data.Enumerator.Step Char Maybe Int"+		(show (typeOf x))++test_Functor :: Suite+test_Functor = assertions "functor" $ do+	$expect $ equal+		'B'+		(runIdentity (run_ (fmap succ (return 'A'))))++test_Applicative :: Suite+test_Applicative = assertions "applicative" $ do+	$expect $ equal+		'A'+		(runIdentity (run_ (pure 'A')))+	$expect $ equal+		'B'+		(runIdentity (run_ (pure succ <*> pure 'A')))
+ tests/EnumeratorTests/Join.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Join+	( test_JoinE+	, test_JoinI+	, test_JoinOperatorAssociativity+	) where++import           Control.Exception+import           Data.Char (toLower)+import           Data.Functor.Identity (Identity, runIdentity)++import           Test.Chell++import           Data.Enumerator (($$), ($=), (=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.Util (equalExc)++test_JoinE :: Suite+test_JoinE = suite "joinE"+	[ test_JoinE_Success+	, test_JoinE_Error+	, test_JoinE_Divergent+	]++test_JoinE_Success :: Suite+test_JoinE_Success = assertions "success" $ do+	let enum :: Monad m => E.Enumerator Char m b+	    enum = E.joinE (E.enumLists [['A', 'B', 'C']]) (EL.map toLower)+	$expect $ equal+		['a', 'b', 'c']+		(runIdentity (E.run_ (enum $$ EL.consume)))++test_JoinE_Error :: Suite+test_JoinE_Error = assertions "error" $ do+	let enum :: Monad m => E.Enumerator Char m b+	    enum = E.joinE (E.enumLists [['A', 'B', 'C']]) (E.sequence (E.throwError (ErrorCall "foo")))+	+	$expect $ equalExc+		(ErrorCall "foo")+		(runIdentity (E.run (enum $$ EL.consume)))++test_JoinE_Divergent :: Suite+test_JoinE_Divergent = assertions "divergent" $ do+	let enum :: Monad m => E.Enumerator Char m b+	    enum = E.joinE (E.enumLists [['A', 'B', 'C']]) (EL.map toLower)+	let diverg :: Monad m => E.Iteratee a m b+	    diverg = E.continue (\_ -> diverg)+	+	$expect $ throwsEq+		(ErrorCall "enumEOF: divergent iteratee")+		(E.run_ (enum $$ diverg))++test_JoinI :: Suite+test_JoinI = assertions "joinI" $ do+	let enum :: Monad m => E.Enumerator Char m b+	    enum = E.enumLists [['A', 'B', 'C']]+	+	let diverg :: Monad m => E.Iteratee a m b+	    diverg = E.continue (\_ -> diverg)+	+	$expect $ equal+		['a', 'b', 'c']+		(runIdentity (E.run_ (enum $$ E.joinI (EL.map toLower $$ EL.consume))))+	$expect $ equalExc+		(ErrorCall "foo")+		(runIdentity (E.run (enum $$ E.joinI (EL.map toLower $$ E.throwError (ErrorCall "foo")))))+	$expect $ throwsEq+		(ErrorCall "joinI: divergent iteratee")+		(E.run_ (enum $$ E.joinI (EL.map toLower $$ diverg)))++test_JoinOperatorAssociativity :: Suite+test_JoinOperatorAssociativity = assertions "join-operator-associativity" $ do+	let xs = ['A', 'B', 'C']+	let enum = E.enumList 1 xs+	let enee = EL.map id+	let iter = EL.consume+	xs1 <- E.run_ $ enum $$ enee =$ enee =$ iter+	xs2 <- E.run_ $ enum $= enee $$ enee =$ iter+	xs3 <- E.run_ $ enum $= enee $= enee $$ iter+	$expect (equal xs xs1)+	$expect (equal xs xs2)+	$expect (equal xs xs3)+	return ()
+ tests/EnumeratorTests/List.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List+	( test_List+	) where++import           Test.Chell++import           EnumeratorTests.List.Consume+import           EnumeratorTests.List.Drop+import           EnumeratorTests.List.Fold+import           EnumeratorTests.List.Isolate+import           EnumeratorTests.List.Iterate+import           EnumeratorTests.List.Map+import           EnumeratorTests.List.Repeat+import           EnumeratorTests.List.Replicate+import           EnumeratorTests.List.Require+import           EnumeratorTests.List.Split+import           EnumeratorTests.List.Unfold+import           EnumeratorTests.List.Unique+import           EnumeratorTests.List.Zip++test_List :: Suite+test_List = suite "list"+	[ test_Consume+	, test_ConcatMap+	, test_ConcatMapM+	, test_ConcatMapAccum+	, test_ConcatMapAccumM+	, test_Drop+	, test_DropWhile+	, test_Fold+	, test_FoldM+	, test_Filter+	, test_FilterM+	, test_GenerateM+	, test_Head+	, test_Head_+	, test_Isolate+	, test_Iterate+	, test_IterateM+	, test_Map+	, test_MapM+	, test_MapM_+	, test_MapAccum+	, test_MapAccumM+	, test_Repeat+	, test_RepeatM+	, test_Replicate+	, test_ReplicateM+	, test_Require+	, test_SplitWhen+	, test_Take+	, test_TakeWhile+	, test_Unfold+	, test_UnfoldM+	, test_Unique+	, test_Zip+	]
+ tests/EnumeratorTests/List/Consume.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Consume+	( test_Consume+	, test_Head+	, test_Head_+	, test_Take+	, test_TakeWhile+	) where++import           Control.Exception+import           Test.Chell++import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.Util (equalExc)++test_Consume :: Suite+test_Consume = assertions "consume" $ do+	$expect $ equal+		(['A', 'B', 'C'], Nothing)+		(E.runLists_ [[], ['A', 'B'], ['C']] $ do+			xs <- EL.consume+			h <- EL.head+			return (xs, h))++test_Head :: Suite+test_Head = assertions "head" $ do+	$expect $ equal+		(Just 'A', ['B', 'C'])+		(E.runLists_ [[], ['A', 'B'], ['C']] $ do+			x <- EL.head+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(Nothing :: Maybe Char, [])+		(E.runLists_ [] $ do+			x <- EL.head+			extra <- EL.consume+			return (x, extra))++test_Head_ :: Suite+test_Head_ = assertions "head_" $ do+	$expect $ equal+		('A', ['B', 'C'])+		(E.runLists_ [[], ['A', 'B'], ['C']] $ do+			x <- EL.head_+			extra <- EL.consume+			return (x, extra))+	$expect $ equalExc+		(ErrorCall "head_: stream has ended")+		(E.runLists [] $ do+			x <- EL.head_+			extra <- EL.consume+			return (x, extra))++test_Take :: Suite+test_Take = assertions "take" $ do+	$expect $ equal+		(['A', 'B', 'C'], ['D', 'E'])+		(E.runLists_ [['A', 'B'], ['C', 'D'], ['E']] $ do+			x <- EL.take 3+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(['A', 'B'], [])+		(E.runLists_ [['A'], ['B']] $ do+			x <- EL.take 3+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		([], ['A', 'B'])+		(E.runLists_ [['A'], ['B']] $ do+			x <- EL.take 0+			extra <- EL.consume+			return (x, extra))++test_TakeWhile :: Suite+test_TakeWhile = assertions "takeWhile" $ do+	$expect $ equal+		(['A', 'B', 'C'], ['D', 'E'])+		(E.runLists_ [[], ['A', 'B'], ['C', 'D'], ['E']] $ do+			x <- EL.takeWhile (< 'D')+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(['A', 'B'], [])+		(E.runLists_ [['A'], ['B']] $ do+			x <- EL.takeWhile (< 'D')+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		([], ['A', 'B'])+		(E.runLists_ [['A'], ['B']] $ do+			x <- EL.takeWhile (< 'A')+			extra <- EL.consume+			return (x, extra))
+ tests/EnumeratorTests/List/Drop.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Drop+	( test_Drop+	, test_DropWhile+	, test_Filter+	, test_FilterM+	) where++import           Test.Chell++import           Data.Enumerator ((=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++test_Drop :: Suite+test_Drop = assertions "drop" $ do+	$expect $ equal+		['A', 'B', 'C', 'D', 'E']+		(E.runLists_ [['A'], ['B'], ['C'], ['D'], ['E']] $ do+			EL.drop 0+			EL.consume)+	$expect $ equal+		['C', 'D', 'E']+		(E.runLists_ [['A'], ['B'], ['C'], ['D'], ['E']] $ do+			EL.drop 2+			EL.consume)+	$expect $ equal+		[]+		(E.runLists_ [['A']] $ do+			EL.drop 2+			EL.consume)++test_DropWhile :: Suite+test_DropWhile = assertions "dropWhile" $ do+	$expect $ equal+		['C', 'D', 'E']+		(E.runLists_ [['A'], ['B'], ['C'], ['D'], ['E']] $ do+			EL.dropWhile (< 'C')+			EL.consume)+	$expect $ equal+		[]+		(E.runLists_ [['A'], ['B'], ['C'], ['D'], ['E']] $ do+			EL.dropWhile (\_ -> True)+			EL.consume)++test_Filter :: Suite+test_Filter = assertions "filter" $ do+	$expect $ equal+		['A', 'B', 'D', 'E']+		(E.runLists_ [['A'], ['B'], ['C'], ['D'], ['E']] $ do+			EL.filter (/= 'C') =$ EL.consume)++test_FilterM :: Suite+test_FilterM = assertions "filterM" $ do+	$expect $ equal+		['A', 'B', 'D', 'E']+		(E.runLists_ [['A'], ['B'], ['C'], ['D'], ['E']] $ do+			EL.filterM (\x -> return (x /= 'C')) =$ EL.consume)
+ tests/EnumeratorTests/List/Fold.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Fold+	( test_Fold+	, test_FoldM+	) where++import qualified Control.Exception as Exception+import           Control.Monad (foldM)+import           Data.Functor.Identity (runIdentity)+import           Data.List (foldl')+import           Test.Chell+import           Test.Chell.QuickCheck+import           Test.QuickCheck.Poly+import           Test.QuickCheck.Modifiers++import qualified Data.Enumerator as E+import           Data.Enumerator (($$))+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.List.Util ()++test_Fold :: Suite+test_Fold = suite "fold"+	[ property "model" prop_Fold+	, test_FoldStrict+	, test_Fold_EOF+	]++prop_Fold :: Blind (B -> A -> B) -> B -> [A] -> Bool+prop_Fold (Blind f) z xs = result == expected where+	result = E.runLists_ [xs] (EL.fold f z)+	expected = foldl' f z xs++test_FoldStrict :: Suite+test_FoldStrict = assertions "strict" $ do+	let exc = Exception.ErrorCall "fail-step"+	let step _ x = case x of+		'C' -> Exception.throw exc+		_ -> 'a'+	$expect $ throwsEq exc (E.run_ (E.enumList 1 ['A', 'B', 'C'] $$ EL.fold step 'a'))+	$expect $ throwsEq exc (E.run_ (E.enumList 3 ['A', 'B', 'C'] $$ EL.fold step 'a'))++test_Fold_EOF :: Suite+test_Fold_EOF = assertions "eof" $ do+	$expect $ equal+		Nothing+		(E.runLists_ [] $ do+			_ <- EL.fold (++) ['A']+			EL.head)++test_FoldM :: Suite+test_FoldM = suite "foldM"+	[ property "model" prop_FoldM+	, test_FoldM_EOF+	]++prop_FoldM :: Blind (B -> A -> B) -> B -> [A] -> Bool+prop_FoldM (Blind f) z xs = result == expected where+	result = E.runLists_ [xs] (EL.foldM f' z)+	expected = runIdentity (foldM f' z xs)+	f' b a = return (f b a)++test_FoldM_EOF :: Suite+test_FoldM_EOF = assertions "eof" $ do+	$expect $ equal+		Nothing+		(E.runLists_ [] $ do+			_ <- EL.foldM (\x y -> return (x ++ y)) ['A']+			EL.head)
+ tests/EnumeratorTests/List/Isolate.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Isolate+	( test_Isolate+	) where++import           Test.Chell+import           Test.Chell.QuickCheck++import           Data.Enumerator ((=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.List.Util++test_Isolate :: Suite+test_Isolate = suite "isolate"+	[ prop_Isolate+	, test_DropExtra+	, test_HandleEOF+	, test_BadParameter+	]++prop_Isolate :: Suite+prop_Isolate = property "model" $ prop_List+	(do+		x <- EL.isolate 2 =$ EL.head+		extra <- EL.consume+		return (x, extra))+	(\xs -> Right $ case xs of+		[] -> (Nothing, [])+		(x:[]) -> (Just x, [])+		(x:_:xs') -> (Just x, xs'))++test_DropExtra :: Suite+test_DropExtra = assertions "drop-extra" $ do+	$expect $ equal+		(Just 'A', ['C'])+		(E.runLists_ [[], ['A'], ['B'], ['C']] $ do+			x <- EL.isolate 2 =$ EL.head+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(Just 'A', ['C'])+		(E.runLists_ [['A', 'B', 'C']] $ do+			x <- EL.isolate 2 =$ EL.head+			extra <- EL.consume+			return (x, extra))++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ equal+		(Nothing :: Maybe Char, [])+		(E.runLists_ [] $ do+			x <- EL.isolate 2 =$ EL.head+			extra <- EL.consume+			return (x, extra))++test_BadParameter :: Suite+test_BadParameter = assertions "bad-parameter" $ do+	$expect $ equal+		(Nothing, ['A', 'B', 'C'])+		(E.runLists_ [['A'], ['B'], ['C']] $ do+			x <- EL.isolate 0 =$ EL.head+			extra <- EL.consume+			return (x, extra))
+ tests/EnumeratorTests/List/Iterate.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Iterate+	( test_Iterate+	, test_IterateM+	) where++import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++test_Iterate :: Suite+test_Iterate = assertions "iterate" $ do+	$expect $ equal+		['A', 'B', 'C']+		(runIdentity (E.run_ (EL.iterate succ 'A' $$ EL.take 3)))++test_IterateM :: Suite+test_IterateM = assertions "iterateM" $ do+	let succM = return . succ+	$expect $ equal+		['A', 'B', 'C']+		(runIdentity (E.run_ (EL.iterateM succM 'A' $$ EL.take 3)))
+ tests/EnumeratorTests/List/Map.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Map+	( test_Map+	, test_MapM+	, test_MapM_+	, test_ConcatMap+	, test_ConcatMapM+	, test_ConcatMapAccum+	, test_ConcatMapAccumM+	, test_MapAccum+	, test_MapAccumM+	) where++import           Control.Monad.Trans.Writer (execWriter, tell)+import           Data.Char (chr, ord, toLower)+import           Test.Chell++import           Data.Enumerator (($$), (=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++test_Map :: Suite+test_Map = assertions "map" $ do+	$expect $ equal+		['a', 'b', 'c']+		(E.runLists_ [['A', 'B'], ['C']] $ do+			EL.map toLower =$ EL.consume)+	$expect $ equal+		(['a'], ['B', 'C'])+		(E.runLists_ [['A', 'B'], ['C']] $ do+			xs <- EL.map toLower =$ EL.take 1+			extra <- EL.consume+			return (xs, extra))++test_MapM :: Suite+test_MapM = assertions "mapM" $ do+	let step = return . toLower+	$expect $ equal+		['a', 'b', 'c']+		(E.runLists_ [['A', 'B'], ['C']] $ do+			EL.mapM step =$ EL.consume)+	$expect $ equal+		(['a'], ['B', 'C'])+		(E.runLists_ [['A', 'B'], ['C']] $ do+			xs <- EL.mapM step =$ EL.take 1+			extra <- EL.consume+			return (xs, extra))++test_MapM_ :: Suite+test_MapM_ = assertions "mapM_" $ do+	$expect $ equal+		['A', 'B', 'C']+		(execWriter (E.run_ (E.enumList 1 ['A', 'B', 'C'] $$ EL.mapM_ (\x -> tell [x]))))++test_ConcatMap :: Suite+test_ConcatMap = assertions "concatMap" $ do+	let step ao = [ao, toLower ao]+	$expect $ equal+		['A', 'a', 'B', 'b', 'C', 'c']+		(E.runLists_ [['A', 'B'], ['C']] $ do+			EL.concatMap step =$ EL.consume)+	$expect $ equal+		(['A', 'a'], ['B', 'C'])+		(E.runLists_ [['A', 'B'], ['C']] $ do+			xs <- EL.concatMap step =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_ConcatMapM :: Suite+test_ConcatMapM = assertions "concatMapM" $ do+	let step ao = return [ao, toLower ao]+	$expect $ equal+		['A', 'a', 'B', 'b', 'C', 'c']+		(E.runLists_ [['A', 'B'], ['C']] $ do+			EL.concatMapM step =$ EL.consume)+	$expect $ equal+		(['A', 'a'], ['B', 'C'])+		(E.runLists_ [['A', 'B'], ['C']] $ do+			xs <- EL.concatMapM step =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_MapAccum :: Suite+test_MapAccum = assertions "mapAccum" $ do+	let step s ao = (s + 1, chr (ord ao + s))+	$expect $ equal+		['B', 'D', 'F']+		(E.runLists_ [['A', 'B'], ['C']] $ do+			EL.mapAccum step 1 =$ EL.consume)+	$expect $ equal+		(['B'], ['B', 'C'])+		(E.runLists_ [['A', 'B'], ['C']] $ do+			xs <- EL.mapAccum step 1 =$ EL.take 1+			extra <- EL.consume+			return (xs, extra))++test_MapAccumM :: Suite+test_MapAccumM = assertions "mapAccumM" $ do+	let step s ao = return (s + 1, chr (ord ao + s))+	$expect $ equal+		['B', 'D', 'F']+		(E.runLists_ [['A', 'B'], ['C']] $ do+			EL.mapAccumM step 1 =$ EL.consume)+	$expect $ equal+		(['B'], ['B', 'C'])+		(E.runLists_ [['A', 'B'], ['C']] $ do+			xs <- EL.mapAccumM step 1 =$ EL.take 1+			extra <- EL.consume+			return (xs, extra))++test_ConcatMapAccum :: Suite+test_ConcatMapAccum = assertions "concatMapAccum" $ do+	let step s ao = (s + 1, replicate s ao)+	$expect $ equal+		['A', 'B', 'B', 'C', 'C', 'C']+		(E.runLists_ [['A', 'B'], ['C']] $ do+			EL.concatMapAccum step 1 =$ EL.consume)+	$expect $ equal+		(['A', 'B'], ['C'])+		(E.runLists_ [['A', 'B'], ['C']] $ do+			xs <- EL.concatMapAccum step 1 =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_ConcatMapAccumM :: Suite+test_ConcatMapAccumM = assertions "concatMapAccumM" $ do+	let step s ao = return (s + 1, replicate s ao)+	$expect $ equal+		['A', 'B', 'B', 'C', 'C', 'C']+		(E.runLists_ [['A', 'B'], ['C']] $ do+			EL.concatMapAccumM step 1 =$ EL.consume)+	$expect $ equal+		(['A', 'B'], ['C'])+		(E.runLists_ [['A', 'B'], ['C']] $ do+			xs <- EL.concatMapAccumM step 1 =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))
+ tests/EnumeratorTests/List/Repeat.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Repeat+	( test_Repeat+	, test_RepeatM+	, test_GenerateM+	) where++import           Control.Monad.Trans.State+import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++test_Repeat :: Suite+test_Repeat = assertions "repeat" $ do+	$expect $ equal+		['A', 'A', 'A']+		(runIdentity (E.run_ (EL.repeat 'A' $$ EL.take 3)))++test_RepeatM :: Suite+test_RepeatM = assertions "repeatM" $ do+	let step = do+		c <- get+		put (succ c)+		return c+	$expect $ equal+		['A', 'B', 'C']+		(evalState (E.run_ (EL.repeatM step $$ EL.take 3)) 'A')++test_GenerateM :: Suite+test_GenerateM = assertions "generateM" $ do+	let step = do+		c <- get+		if c > 'C'+			then return Nothing+			else do+				put (succ c)+				return (Just c)+	$expect $ equal+		['A', 'B', 'C']+		(evalState (E.run_ (EL.generateM step $$ EL.consume)) 'A')
+ tests/EnumeratorTests/List/Replicate.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Replicate+	( test_Replicate+	, test_ReplicateM+	) where++import           Control.Monad.Trans.State+import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++test_Replicate :: Suite+test_Replicate = assertions "replicate" $ do+	$expect $ equal+		['A', 'A', 'A']+		(runIdentity (E.run_ (EL.replicate 3 'A' $$ EL.consume)))+	$expect $ equal+		['A', 'A']+		(runIdentity (E.run_ (EL.replicate 3 'A' $$ EL.take 2)))++test_ReplicateM :: Suite+test_ReplicateM = assertions "replicateM" $ do+	let step = do+		c <- get+		put (succ c)+		return c+	$expect $ equal+		['A', 'B', 'C']+		(evalState (E.run_ (EL.replicateM 3 step $$ EL.consume)) 'A')+	$expect $ equal+		['A', 'B']+		(evalState (E.run_ (EL.replicateM 3 step $$ EL.take 2)) 'A')
+ tests/EnumeratorTests/List/Require.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Require+	( test_Require+	) where++import qualified Control.Exception as Exc+import           Test.Chell+import           Test.Chell.QuickCheck++import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.List.Util (prop_ListN)+import           EnumeratorTests.Util (equalExc)++test_Require :: Suite+test_Require = suite "require"+	[ prop_Require+	, test_YieldsInput+	, test_HandleEOF+	, test_BadParameter+	]++prop_Require :: Suite+prop_Require = property "model" $ prop_ListN+	(\n -> do+		EL.require n+		EL.consume)+	(\n xs -> if n > toInteger (length xs)+		then Left (Exc.ErrorCall "require: Unexpected EOF")+		else Right xs)++test_YieldsInput :: Suite+test_YieldsInput = assertions "yields-input" $ do+	$expect $ equal+		['A', 'B', 'C']+		(E.runLists_ [['A'], ['B'], ['C']] $ do+			EL.require 2+			EL.consume)+	$expect $ equal+		['A', 'B', 'C']+		(E.runLists_ [['A', 'B', 'C']] $ do+			EL.require 2+			EL.consume)++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ equalExc+		(Exc.ErrorCall "require: Unexpected EOF")+		(E.runLists [] $ do+			EL.require 2+			EL.consume)++test_BadParameter :: Suite+test_BadParameter = assertions "bad-parameter" $ do+	$expect $ equal+		([] :: [Char])+		(E.runLists_ [] $ do+			EL.require 0+			EL.consume)
+ tests/EnumeratorTests/List/Split.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Split+	( test_SplitWhen+	) where+++import qualified Data.List.Split as LS+import           Test.Chell+import           Test.Chell.QuickCheck++import           Data.Enumerator ((=$))+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.List.Util++test_SplitWhen :: Suite+test_SplitWhen = property "splitWhen" $ prop_ListX+	(\x -> do+		xs <- EL.splitWhen (== x) =$ EL.consume+		extra <- EL.consume+		return (xs, extra))+	(\x xs -> let+		split = LS.split . LS.dropFinalBlank . LS.dropDelims . LS.whenElt+		in Right (split (== x) xs, []))
+ tests/EnumeratorTests/List/Unfold.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Unfold+	( test_Unfold+	, test_UnfoldM+	) where++import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++test_Unfold :: Suite+test_Unfold = assertions "unfold" $ do+	let step x = if x > 'C'+		then Nothing+		else Just (x, succ x)+	$expect $ equal+		['A', 'B', 'C']+		(runIdentity (E.run_ (EL.unfold step 'A' $$ EL.consume)))++test_UnfoldM :: Suite+test_UnfoldM = assertions "unfoldM" $ do+	let step x = return $ if x > 'C'+		then Nothing+		else Just (x, succ x)+	$expect $ equal+		['A', 'B', 'C']+		(runIdentity (E.run_ (EL.unfoldM step 'A' $$ EL.consume)))
+ tests/EnumeratorTests/List/Unique.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Unique+	( test_Unique+	) where++import           Test.Chell++import           Data.Enumerator ((=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++test_Unique :: Suite+test_Unique = assertions "unique" $ do+	$expect $ equal+		['B', 'A', 'C']+		(E.runLists_ [['B'], ['A'], ['B'], ['C'], ['A']] $ do+			EL.unique =$ EL.consume)
+ tests/EnumeratorTests/List/Util.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Util+	( test_Enumeratee+	, prop_List+	, prop_ListN+	, prop_ListX+	) where++import qualified Control.Exception as Exc+import           Data.Functor.Identity (Identity, runIdentity)+import qualified Data.Text as T++import           Test.Chell+import           Test.Chell.QuickCheck+import           Test.QuickCheck hiding (property)+import           Test.QuickCheck.Poly (A)++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.Util (check)++test_Enumeratee :: T.Text -> E.Enumeratee A A Identity (Maybe A) -> Suite+test_Enumeratee name enee = suite name props where+	props = [ property "incremental" prop_incremental+	        , property "nest-errors" prop_nest_errors+	        ]+	+	prop_incremental (Positive n) (NonEmpty xs) = let+		result = runIdentity (E.run_ iter)+		expected = (Just (head xs), tail xs)+		+		iter = E.enumList n xs $$ do+			a <- E.joinI (enee $$ EL.head)+			b <- EL.consume+			return (a, b)+		+		in result == expected+	+	prop_nest_errors (Positive n) (NonEmpty xs) = let+		result = runIdentity (E.run_ iter)+		+		iter = E.enumList n xs $$ do+			_ <- enee $$ E.throwError (Exc.ErrorCall "")+			EL.consume+		+		in result == xs++prop_List :: Eq b+          => E.Iteratee A Identity b+          -> ([A] -> Either Exc.ErrorCall b)+          -> [A]+          -> Bool+prop_List iter plain = prop where+	prop :: [A] -> Bool+	prop = check iter plain++prop_ListN :: Eq b+           => (Integer -> E.Iteratee A Identity b)+           -> (Integer -> [A] -> Either Exc.ErrorCall b)+           -> Positive Integer+           -> [A]+           -> Bool+prop_ListN iter plain = prop where+	prop :: Positive Integer -> [A] -> Bool+	prop (Positive n) = check (iter n) (plain n)++prop_ListX :: Eq b+           => (A -> E.Iteratee A Identity b)+           -> (A -> [A] -> Either Exc.ErrorCall b)+           -> A+           -> [A]+           -> Bool+prop_ListX iter plain = prop where+	prop :: A -> [A] -> Bool+	prop x = check (iter x) (plain x)
+ tests/EnumeratorTests/List/Zip.hs view
@@ -0,0 +1,172 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.List.Zip+	( test_Zip+	) where++import qualified Control.Exception as Exc+import           Data.Functor.Identity (Identity)+import           Data.Text (Text)+import           Test.Chell++import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.List.Util ()+import           EnumeratorTests.Util (equalExc)++test_ZipN :: (Eq b, Show b) => Text -> E.Iteratee Char Identity b -> b -> Suite+test_ZipN name iter expected = assertions name $ do+	$expect $ equal+		expected+		(E.runLists_ [[], ['A'], ['B']] iter)++$([d||])++test_Zip :: Suite+test_Zip = suite "zip"+	[ test_ContinueContinue+	, test_YieldContinue+	, test_ContinueYield+	, test_YieldYield+	, test_ErrorFirst+	, test_ErrorSecond+	, test_HandleEOF+	, test_Zip3+	, test_Zip4+	, test_Zip5+	, test_Zip6+	, test_Zip7+	, test_ZipWith+	, test_ZipWith3+	, test_ZipWith4+	, test_ZipWith5+	, test_ZipWith6+	, test_ZipWith7+	]++test_ContinueContinue :: Suite+test_ContinueContinue = assertions "continue-continue" $ do+	$expect $ equal+		(['A', 'B'], ['A', 'B'], ['C'])+		(E.runLists_ [['A'], ['B'], ['C']] $ do+			(x, y) <- EL.zip (EL.take 2) (EL.take 2)+			extra <- EL.consume+			return (x, y, extra))++test_YieldContinue :: Suite+test_YieldContinue = assertions "yield-continue" $ do+	$expect $ equal+		(['A'], ['A', 'B'], ['C'])+		(E.runLists_ [['A'], ['B'], ['C']] $ do+			(x, y) <- EL.zip (EL.take 1) (EL.take 2)+			extra <- EL.consume+			return (x, y, extra))++test_ContinueYield :: Suite+test_ContinueYield = assertions "continue-yield" $ do+	$expect $ equal+		(['A', 'B'], ['A'], ['C'])+		(E.runLists_ [['A'], ['B'], ['C']] $ do+			(x, y) <- EL.zip (EL.take 2) (EL.take 1)+			extra <- EL.consume+			return (x, y, extra))++test_YieldYield :: Suite+test_YieldYield = assertions "yield-yield" $ do+	$expect $ equal+		(['A'], ['A'], ['B', 'C'])+		(E.runLists_ [['A'], ['B'], ['C']] $ do+			(x, y) <- EL.zip (EL.take 1) (EL.take 1)+			extra <- EL.consume+			return (x, y, extra))++test_ErrorFirst :: Suite+test_ErrorFirst = assertions "error-first" $ do+	$expect $ equalExc+		(Exc.ErrorCall "error")+		(E.runLists [['A'], ['B'], ['C']] $ do+			EL.zip (E.throwError (Exc.ErrorCall "error")) (EL.take 1))++test_ErrorSecond :: Suite+test_ErrorSecond = assertions "error-second" $ do+	$expect $ equalExc+		(Exc.ErrorCall "error")+		(E.runLists [['A'], ['B'], ['C']] $ do+			EL.zip (EL.take 1) (E.throwError (Exc.ErrorCall "error")))++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ equal+		(['A'], ['A', 'B'], [])+		(E.runLists_ [['A'], ['B']] $ do+			(x, y) <- EL.zip (EL.take 1) (EL.take 3)+			extra <- EL.consume+			return (x, y, extra))+	$expect $ equal+		(['a'], ['b'], [])+		(E.runLists_ [['A'], ['B']] $ do+			(x, y) <- EL.zip+				(E.yield ['a'] (E.Chunks []))+				(E.yield ['b'] E.EOF)+			extra <- EL.consume+			return (x, y, extra))++test_Zip3 :: Suite+test_Zip3 = test_ZipN "zip3"+	(EL.zip3 EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A')++test_Zip4 :: Suite+test_Zip4 = test_ZipN "zip4"+	(EL.zip4 EL.head EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A', Just 'A')++test_Zip5 :: Suite+test_Zip5 = test_ZipN "zip5"+	(EL.zip5 EL.head EL.head EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_Zip6 :: Suite+test_Zip6 = test_ZipN "zip6"+	(EL.zip6 EL.head EL.head EL.head EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_Zip7 :: Suite+test_Zip7 = test_ZipN "zip7"+	(EL.zip7 EL.head EL.head EL.head EL.head EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_ZipWith :: Suite+test_ZipWith = test_ZipN "zipWith"+	(EL.zipWith (,) EL.head EL.head)+	(Just 'A', Just 'A')++test_ZipWith3 :: Suite+test_ZipWith3 = test_ZipN "zipWith3"+	(EL.zipWith3 (,,) EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A')++test_ZipWith4 :: Suite+test_ZipWith4 = test_ZipN "zipWith4"+	(EL.zipWith4 (,,,) EL.head EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A', Just 'A')++test_ZipWith5 :: Suite+test_ZipWith5 = test_ZipN "zipWith5"+	(EL.zipWith5 (,,,,) EL.head EL.head EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_ZipWith6 :: Suite+test_ZipWith6 = test_ZipN "zipWith6"+	(EL.zipWith6 (,,,,,) EL.head EL.head EL.head EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_ZipWith7 :: Suite+test_ZipWith7 = test_ZipN "zipWith7"+	(EL.zipWith7 (,,,,,,) EL.head EL.head EL.head EL.head EL.head EL.head EL.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')
+ tests/EnumeratorTests/Misc.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Misc+	( test_ConcatEnums+	, test_EnumEOF+	, test_Last+	, test_Length+	, test_LiftTrans+	, test_Peek+	, test_TryIO+	, test_PrintChunks+	) where++import           Control.Exception+import           Control.Monad.Trans.Reader+import           Control.Monad.IO.Class+import           Data.Functor.Identity+import           Test.Chell++#ifdef MIN_VERSION_silently++import           System.IO.Silently (capture)++#endif++import           Data.Enumerator (($$), (<==<))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.Util (equalExc)++test_ConcatEnums :: Suite+test_ConcatEnums = assertions "concatEnums" $ do+	let enum = E.concatEnums+		[ E.enumLists [['A']]+		, E.enumLists [['B']]+		, E.enumLists [['C']]+		]+	$expect $ equal+		['A', 'B', 'C']+		(runIdentity (E.run_ (enum $$ EL.consume)))+	$expect $ equal+		['A', 'B']+		(runIdentity (E.run_ (E.enumLists [['B']] <==< E.enumLists [['A']] $$ EL.consume)))++test_EnumEOF :: Suite+test_EnumEOF = assertions "enumEOF" $ do+	let iter = E.continue (\_ -> iter)+	+	$expect $ throwsEq+		(ErrorCall "enumEOF: divergent iteratee")+		(E.runIteratee (E.enumEOF $$ iter))++test_Last :: Suite+test_Last = assertions "last" $ do+	$expect $ equal+		(Nothing :: Maybe Char, [])+		(E.runLists_ [[]] $ do+			x <- E.last+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(Just 'E', [])+		(E.runLists_ [['A', 'B'], ['C', 'D'], ['E']] $ do+			x <- E.last+			extra <- EL.consume+			return (x, extra))++test_Length :: Suite+test_Length = assertions "length" $ do+	$expect $ equal+		5+		(E.runLists_ [['A', 'B'], ['C', 'D'], ['E']] E.length)++test_LiftTrans :: Suite+test_LiftTrans = assertions "liftTrans" $ do+	let iter1 :: E.Iteratee Char Identity (Maybe Char)+	    iter1 = EL.head+	+	let iter2 :: Bool -> E.Iteratee Char (ReaderT Int Identity) (Maybe Char, [Char])+	    iter2 bad = do+	    	x <- E.liftTrans (if bad then E.throwError (ErrorCall "failed") else iter1)+	    	xs <- EL.consume+	    	return (x, xs)+	+	$expect $ equal+		(Just 'A', ['B', 'C', 'D', 'E'])+		(runIdentity (runReaderT (E.run_ (E.enumList 1 ['A'..'E'] $$ iter2 False)) 0))+	+	$expect $ equalExc+		(ErrorCall "failed")+		(runIdentity (runReaderT (E.run (E.enumList 1 ['A'..'E'] $$ iter2 True)) 0))++test_Peek :: Suite+test_Peek = assertions "peek" $ do+	$expect $ equal+		(Nothing :: Maybe Char, [])+		(E.runLists_ [] $ do+			x <- E.peek+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(Just 'A', ['A', 'B', 'C', 'D', 'E'])+		(E.runLists_ [[], ['A', 'B'], ['C', 'D'], ['E']] $ do+			x <- E.peek+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(Just 'A', ['A'])+		(E.runLists_ [['A']] $ do+			x <- E.peek+			extra <- EL.consume+			return (x, extra))++test_TryIO :: Suite+test_TryIO = assertions "tryIO" $ do+	do+		res <- E.run (E.tryIO (return 'A'))+		$expect (right res)+		let Right res' = res+		$expect (equal 'A' res')+	+	do+		res <- E.run (E.tryIO (throwIO (ErrorCall "failed")))+		$expect (equalExc (ErrorCall "failed") res)++test_PrintChunks :: Suite+#ifdef MIN_VERSION_silently+test_PrintChunks = assertions "printChunks" $ do+	do+		(stdout, _) <- liftIO (capture (E.run_ (E.enumLists [[], ['A', 'B'], ['C']] $$ E.printChunks False)))+		$expect (equal stdout "\"AB\"\n\"C\"\nEOF\n")+	do+		(stdout, _) <- liftIO (capture (E.run_ (E.enumLists [[], ['A', 'B'], ['C']] $$ E.printChunks True)))+		$expect (equal stdout "\"\"\n\"AB\"\n\"C\"\nEOF\n")+#else+test_PrintChunks = skipIf True (assertions "printChunks" (return ()))+#endif
+ tests/EnumeratorTests/Sequence.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Sequence+	( test_Sequence+	) where++import           Data.Functor.Identity (Identity, runIdentity)++import           Test.Chell+import           Test.Chell.QuickCheck+import           Test.QuickCheck hiding (property)+import           Test.QuickCheck.Poly (A)++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL++test_Sequence :: Suite+test_Sequence = property "sequence" prop where+	prop :: Positive Integer -> [A] -> Bool+	prop (Positive n) xs = result == expected where+		result = runIdentity (E.run_ iter)+		expected = map Just xs+		+		iter = E.enumList n xs $$ E.joinI (E.sequence EL.head $$ EL.consume)
+ tests/EnumeratorTests/Stream.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010-2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Stream+	( test_Stream+	) where++import           Control.Applicative (pure, (<*>))+import           Data.Monoid (mappend, mempty, mconcat)++import           Test.Chell+import           Test.Chell.QuickCheck+import           Test.QuickCheck hiding (property)+import           Test.QuickCheck.Poly (A, B, C)++import qualified Data.Enumerator as E++import           EnumeratorTests.Util ()++test_Stream :: Suite+test_Stream = suite "stream"+	[ test_Monoid+	, test_Functor+	, test_Monad+	, test_Applicative+	]++test_Monoid :: Suite+test_Monoid = suite "monoid"+	[ property "law-1" prop_MonoidLaw1+	, property "law-2" prop_MonoidLaw2+	, property "law-3" prop_MonoidLaw3+	, property "law-4" prop_MonoidLaw4+	]++prop_MonoidLaw1 :: E.Stream A -> Bool+prop_MonoidLaw1 x = mappend mempty x == x++prop_MonoidLaw2 :: E.Stream A -> Bool+prop_MonoidLaw2 x = mappend x mempty == x++prop_MonoidLaw3 :: E.Stream A -> E.Stream A -> E.Stream A -> Bool+prop_MonoidLaw3 x y z = mappend x (mappend y z) == mappend (mappend x y) z++prop_MonoidLaw4 :: [E.Stream A] -> Bool+prop_MonoidLaw4 xs = mconcat xs == foldr mappend mempty xs++test_Functor :: Suite+test_Functor = suite "functor"+	[ property "law-1" prop_FunctorLaw1+	, property "law-2" prop_FunctorLaw2+	]++prop_FunctorLaw1 :: E.Stream A -> Bool+prop_FunctorLaw1 x = fmap id x == id x++prop_FunctorLaw2 :: E.Stream A -> Blind (B -> C) -> Blind (A -> B) -> Bool+prop_FunctorLaw2 x (Blind f) (Blind g) = fmap (f . g) x == (fmap f . fmap g) x++test_Monad :: Suite+test_Monad = suite "monad"+	[ property "law-1" prop_MonadLaw1+	, property "law-2" prop_MonadLaw2+	, property "law-3" prop_MonadLaw3+	]++prop_MonadLaw1 :: A -> Blind (A -> E.Stream B) -> Bool+prop_MonadLaw1 a (Blind f) = (return a >>= f) == f a++prop_MonadLaw2 :: E.Stream A -> Bool+prop_MonadLaw2 m = (m >>= return) == m++prop_MonadLaw3 :: E.Stream A -> Blind (A -> E.Stream B) -> Blind (B -> E.Stream C) -> Bool+prop_MonadLaw3 m (Blind f) (Blind g) = ((m >>= f) >>= g) == (m >>= (\x -> f x >>= g))++test_Applicative :: Suite+test_Applicative = assertions "applicative" $ do+	$expect (equal (E.Chunks ['A']) (pure 'A'))+	$expect (equal (E.Chunks ['B']) (pure succ <*> E.Chunks ['A']))
+ tests/EnumeratorTests/Text.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text+	( test_Text+	) where++import           Test.Chell++import           EnumeratorTests.Text.Codecs+import           EnumeratorTests.Text.Consume+import           EnumeratorTests.Text.Drop+import           EnumeratorTests.Text.Fold+import           EnumeratorTests.Text.Handle+import           EnumeratorTests.Text.Isolate+import           EnumeratorTests.Text.Iterate+import           EnumeratorTests.Text.Map+import           EnumeratorTests.Text.Repeat+import           EnumeratorTests.Text.Replicate+import           EnumeratorTests.Text.Require+import           EnumeratorTests.Text.Split+import           EnumeratorTests.Text.Unfold+import           EnumeratorTests.Text.Zip++test_Text :: Suite+test_Text = suite "text"+	[ test_TextCodecs+	, test_Consume+	, test_ConcatMap+	, test_ConcatMapM+	, test_ConcatMapAccum+	, test_ConcatMapAccumM+	, test_Drop+	, test_DropWhile+	, test_EnumHandle+	, test_Filter+	, test_FilterM+	, test_Fold+	, test_FoldM+	, test_GenerateM+	, test_Head+	, test_Head_+	, test_Isolate+	, test_Iterate+	, test_IterateM+	, test_IterHandle+	, test_Lines+	, test_Map+	, test_MapM+	, test_MapM_+	, test_MapAccum+	, test_MapAccumM+	, test_Repeat+	, test_RepeatM+	, test_Replicate+	, test_ReplicateM+	, test_Require+	, test_SplitWhen+	, test_Take+	, test_TakeWhile+	, test_Unfold+	, test_UnfoldM+	, test_Zip+	]
+ tests/EnumeratorTests/Text/Codecs.hs view
@@ -0,0 +1,322 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Codecs+	( test_TextCodecs+	) where++import           Prelude hiding (words)++import           Control.Exception (ErrorCall(..))+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy as BL+import           Data.Char (ord)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Encoding as TE+import qualified Data.Text.Encoding.Error as TE++import           Test.Chell+import           Test.Chell.QuickCheck+import           Test.QuickCheck hiding (property)++import           Data.Enumerator ((=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.Binary as EB+import qualified Data.Enumerator.Text as ET+import qualified Data.Enumerator.List as EL++import           EnumeratorTests.Util++test_TextCodecs :: Suite+test_TextCodecs = suite "codecs"+	[ test_ASCII+	, test_ISO8859_1+	, test_UTF8+	, test_UTF16_BE+	, test_UTF16_LE+	, test_UTF32_BE+	, test_UTF32_LE+	]++test_ASCII :: Suite+test_ASCII = suite "ascii"+	[ property "encode" (forAll genASCII (prop_Encode ET.ascii encodeASCII))+	, property "decode" (forAll genASCII (prop_Decode ET.ascii decodeASCII))+	+	, assertions "show" $ do+	  	$expect $ equal+	  		"Codec \"ASCII\""+	  		(show ET.ascii)+	+	, assertions "encode-invalid" $ do+	  	$expect $ equalExc+	  		(ErrorCall "Codec \"ASCII\" can't encode character U+00FF")+	  		(E.runLists [["\xFF"]] (ET.encode ET.ascii =$ EB.consume))+	+	, assertions "decode-invalid" $ do+	  	$expect $ equalExc+	  		(ErrorCall "Codec \"ASCII\" can't decode byte 0xFF")+	  		(E.runLists [["\xFF"]] (ET.decode ET.ascii =$ ET.consume))+	+	, skipIf True $ assertions "lazy.broken" $ do+	  	$expect $ equal+	  		(Just 0x61, ["b"])+	  		(E.runLists_ [["", "ab"]] (do+	  			x <- ET.encode ET.ascii =$ EB.head+	  			y <- EL.consume+	  			return (x, y)))+	+	, assertions "lazy" $ do+	  	$expect $ equal+	  		(Just 0x61, ["b"])+	  		(E.runLists_ [[""], ["a"], ["b"]] $ do+	  			x <- ET.encode ET.ascii =$ EB.head+	  			y <- EL.consume+	  			return (x, y))+	  	$expect $ equal+	  		(Just 0x61, ["\xFF"])+	  		(E.runLists_ [[""], ["a\xFF"]] $ do+	  			x <- ET.encode ET.ascii =$ EB.head+	  			y <- EL.consume+	  			return (x, y))+	  	$expect $ equal+	  		(Just 'a', ["b"])+	  		(E.runLists_ [[""], ["a"], ["b"]] $ do+	  			x <- ET.decode ET.ascii =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	  	$expect $ equal+	  		(Just 'a', ["\xFF"])+	  		(E.runLists_ [[""], ["a\xFF"]] $ do+	  			x <- ET.decode ET.ascii =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	]++encodeASCII :: T.Text -> B.ByteString+encodeASCII text = if T.any (\c -> ord c > 127) text+	then error "encodeASCII: input contains non-ASCII characters."+	else B8.pack (T.unpack text)++decodeASCII :: B.ByteString -> T.Text+decodeASCII bytes = if B.any (> 127) bytes+	then error "decodeASCII: input contains non-ASCII characters."+	else T.pack (B8.unpack bytes)++test_ISO8859_1 :: Suite+test_ISO8859_1 = suite "iso8859-1"+	[ property "encode" (forAll genISO8859_1 (prop_Encode ET.iso8859_1 encodeISO8859_1))+	, property "decode" (forAll genISO8859_1 (prop_Decode ET.iso8859_1 decodeISO8859_1))+	+	, assertions "show" $ do+	  	$expect $ equal+	  		"Codec \"ISO-8859-1\""+	  		(show ET.iso8859_1)+	+	, assertions "encode-invalid" $ do+	  	$expect $ equalExc+	  		(ErrorCall "Codec \"ISO-8859-1\" can't encode character U+01FF")+	  		(E.runLists [["\x1FF"]] (ET.encode ET.iso8859_1 =$ EB.consume))+	+	, assertions "lazy" $ do+	  	$expect $ equal+	  		(Just 0x61, ["b"])+	  		(E.runLists_ [[""], ["a"], ["b"]] $ do+	  			x <- ET.encode ET.iso8859_1 =$ EB.head+	  			y <- EL.consume+	  			return (x, y))+	  	$expect $ equal+	  		(Just 0x61, ["\x1FF"])+	  		(E.runLists_ [[""], ["a\x1FF"]] $ do+	  			x <- ET.encode ET.iso8859_1 =$ EB.head+	  			y <- EL.consume+	  			return (x, y))+	  	$expect $ equal+	  		(Just 'a', ["b"])+	  		(E.runLists_ [[""], ["a"], ["b"]] $ do+	  			x <- ET.decode ET.iso8859_1 =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	]++encodeISO8859_1 :: T.Text -> B.ByteString+encodeISO8859_1 text = if T.any (\c -> ord c > 255) text+	then error "encodeASCII: input contains non-ISO8859-1 characters."+	else B8.pack (T.unpack text)++decodeISO8859_1 :: B.ByteString -> T.Text+decodeISO8859_1 bytes = T.pack (B8.unpack bytes)++test_UTF8 :: Suite+test_UTF8 = suite "utf8"+	[ property "encode" (prop_Encode ET.utf8 TE.encodeUtf8)+	, property "decode" (prop_Decode ET.utf8 TE.decodeUtf8 . TE.encodeUtf8)+	+	, assertions "show" $ do+	  	$expect $ equal+	  		"Codec \"UTF-8\""+	  		(show ET.utf8)+	+	, assertions "decode-invalid" $ do+	  	$expect $ equalExc+	  		(TE.DecodeError "Data.Text.Encoding.decodeUtf8: Invalid UTF-8 stream" (Just 0xFF))+	  		(E.runLists [["\xFF"]] (ET.decode ET.utf8 =$ ET.consume))+	  	$expect $ equalExc+	  		(ErrorCall "Unexpected EOF while decoding")+	  		(E.runLists [["\xF0"]] (ET.decode ET.utf8 =$ ET.consume))+	+	, assertions "lazy" $ do+	  	$expect $ equal+	  		(Just 'a', ["\xEF\xBD"])+	  		(E.runLists_ [["a\xEF\xBD"]] $ do+	  			x <- ET.decode ET.utf8 =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	]++test_UTF16_BE :: Suite+test_UTF16_BE = suite "utf16-be"+	[ property "encode" (prop_Encode ET.utf16_be TE.encodeUtf16BE)+	, property "decode" (prop_Decode ET.utf16_be TE.decodeUtf16BE . TE.encodeUtf16BE)+	+	, assertions "show" $ do+	  	$expect $ equal+	  		"Codec \"UTF-16-BE\""+	  		(show ET.utf16_be)+	+	, assertions "decode-invalid" $ do+	  	$expect $ equalExc+	  		(TE.DecodeError "Data.Text.Encoding.Fusion.streamUtf16BE: Invalid UTF-16BE stream" Nothing)+	  		(E.runLists [["\xDD\x1E"]] (ET.decode ET.utf16_be =$ ET.consume))+	  	$expect $ equalExc+	  		(ErrorCall "Unexpected EOF while decoding")+	  		(E.runLists [["\xD8\x00"]] (ET.decode ET.utf16_be =$ ET.consume))+	+	, assertions "lazy" $ do+	  	$expect $ equal+	  		(Just 'a', ["\x00"])+	  		(E.runLists_ [["\x00\x61\x00"]] $ do+	  			x <- ET.decode ET.utf16_be =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	  	$expect $ equal+	  		(Just 'a', ["\xDD\x1E"])+	  		(E.runLists_ [["\x00\x61\xDD\x1E"]] $ do+	  			x <- ET.decode ET.utf16_be =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	]++test_UTF16_LE :: Suite+test_UTF16_LE = suite "utf16-le"+	[ property "encode" (prop_Encode ET.utf16_le TE.encodeUtf16LE)+	, property "decode" (prop_Decode ET.utf16_le TE.decodeUtf16LE . TE.encodeUtf16LE)+	+	, assertions "show" $ do+	  	$expect $ equal+	  		"Codec \"UTF-16-LE\""+	  		(show ET.utf16_le)+	+	, assertions "decode-invalid" $ do+	  	$expect $ equalExc+	  		(TE.DecodeError "Data.Text.Encoding.Fusion.streamUtf16LE: Invalid UTF-16LE stream" Nothing)+	  		(E.runLists [["\x1E\xDD"]] (ET.decode ET.utf16_le =$ ET.consume))+	  	$expect $ equalExc+	  		(ErrorCall "Unexpected EOF while decoding")+	  		(E.runLists [["\x00\xD8"]] (ET.decode ET.utf16_le =$ ET.consume))+	+	, assertions "lazy" $ do+	  	$expect $ equal+	  		(Just 'a', ["\x00"])+	  		(E.runLists_ [["\x61\x00\x00"]] $ do+	  			x <- ET.decode ET.utf16_le =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	  	$expect $ equal+	  		(Just 'a', ["\x1E\xDD"])+	  		(E.runLists_ [["\x61\x00\x1E\xDD"]] $ do+	  			x <- ET.decode ET.utf16_le =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	]++test_UTF32_BE :: Suite+test_UTF32_BE = suite "utf32-be"+	[ property "encode" (prop_Encode ET.utf32_be TE.encodeUtf32BE)+	, property "decode" (prop_Decode ET.utf32_be TE.decodeUtf32BE . TE.encodeUtf32BE)+	+	, assertions "show" $ do+	  	$expect $ equal+	  		"Codec \"UTF-32-BE\""+	  		(show ET.utf32_be)+	+	, assertions "decode-invalid" $ do+	  	$expect $ equalExc+	  		(TE.DecodeError "Data.Text.Encoding.Fusion.streamUtf32BE: Invalid UTF-32BE stream" Nothing)+	  		(E.runLists [["\xFF\xFF\xFF\xFF"]] (ET.decode ET.utf32_be =$ ET.consume))+	  	$expect $ equalExc+	  		(ErrorCall "Unexpected EOF while decoding")+	  		(E.runLists [["\x00\x00"]] (ET.decode ET.utf32_be =$ ET.consume))+	+	, assertions "lazy" $ do+	  	$expect $ equal+	  		(Just 'a', ["\x00"])+	  		(E.runLists_ [["\x00\x00\x00\x61\x00"]] $ do+	  			x <- ET.decode ET.utf32_be =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	  	$expect $ equal+	  		(Just 'a', ["\xFF\xFF\xFF\xFF"])+	  		(E.runLists_ [["\x00\x00\x00\x61\xFF\xFF\xFF\xFF"]] $ do+	  			x <- ET.decode ET.utf32_be =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	]++test_UTF32_LE :: Suite+test_UTF32_LE = suite "utf32-le"+	[ property "encode" (prop_Encode ET.utf32_le TE.encodeUtf32LE)+	, property "decode" (prop_Decode ET.utf32_le TE.decodeUtf32LE . TE.encodeUtf32LE)+	+	, assertions "show" $ do+	  	$expect $ equal+	  		"Codec \"UTF-32-LE\""+	  		(show ET.utf32_le)+	+	, assertions "decode-invalid" $ do+	  	$expect $ equalExc+	  		(TE.DecodeError "Data.Text.Encoding.Fusion.streamUtf32LE: Invalid UTF-32LE stream" Nothing)+	  		(E.runLists [["\xFF\xFF\xFF\xFF"]] (ET.decode ET.utf32_le =$ ET.consume))+	  	$expect $ equalExc+	  		(ErrorCall "Unexpected EOF while decoding")+	  		(E.runLists [["\x00\x00"]] (ET.decode ET.utf32_le =$ ET.consume))+	+	, assertions "lazy" $ do+	  	$expect $ equal+	  		(Just 'a', ["\x00"])+	  		(E.runLists_ [["\x61\x00\x00\x00\x00"]] $ do+	  			x <- ET.decode ET.utf32_le =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	  	$expect $ equal+	  		(Just 'a', ["\xFF\xFF\xFF\xFF"])+	  		(E.runLists_ [["\x61\x00\x00\x00\xFF\xFF\xFF\xFF"]] $ do+	  			x <- ET.decode ET.utf32_le =$ ET.head+	  			y <- EL.consume+	  			return (x, y))+	]++prop_Encode :: ET.Codec -> (T.Text -> B.ByteString) -> T.Text -> Bool+prop_Encode codec model text = encoded == model text where+	lazy = E.runLists_ [[text]] (ET.encode codec =$ EB.consume)+	encoded = B.concat (BL.toChunks lazy)++prop_Decode :: ET.Codec -> (B.ByteString -> T.Text) -> B.ByteString -> Bool+prop_Decode codec model bytes = decoded == model bytes where+	lazy = E.runLists_ [[bytes]] (ET.decode codec =$ ET.consume)+	decoded = TL.toStrict lazy
+ tests/EnumeratorTests/Text/Consume.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Consume+	( test_Consume+	, test_Head+	, test_Head_+	, test_Take+	, test_TakeWhile+	) where++import           Control.Exception+import           Test.Chell++import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++import           EnumeratorTests.Util (equalExc)++test_Consume :: Suite+test_Consume = assertions "consume" $ do+	$expect $ equal+		("ABC", Nothing)+		(E.runLists_ [[], ["A", "B"], ["C"]] $ do+			xs <- ET.consume+			h <- EL.head+			return (xs, h))++test_Head :: Suite+test_Head = assertions "head" $ do+	$expect $ equal+		(Just 'A', ["BC", "DE"])+		(E.runLists_ [[], ["ABC", "DE"]] $ do+			x <- ET.head+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(Nothing :: Maybe Char, [])+		(E.runLists_ [] $ do+			x <- ET.head+			extra <- EL.consume+			return (x, extra))++test_Head_ :: Suite+test_Head_ = assertions "head_" $ do+	$expect $ equal+		('A', ["BC", "DE"])+		(E.runLists_ [["ABC"], ["DE"]] $ do+			x <- ET.head_+			extra <- EL.consume+			return (x, extra))+	$expect $ equalExc+		(ErrorCall "head_: stream has ended")+		(E.runLists [] $ do+			x <- ET.head_+			extra <- EL.consume+			return (x, extra))++test_Take :: Suite+test_Take = assertions "take" $ do+	$expect $ equal+		("ABC", ["D", "E"])+		(E.runLists_ [["A", "B"], ["C", "D"], ["E"]] $ do+			x <- ET.take 3+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		("AB", [])+		(E.runLists_ [["A"], ["B"]] $ do+			x <- ET.take 3+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		("", ["A", "B"])+		(E.runLists_ [["A"], ["B"]] $ do+			x <- ET.take 0+			extra <- EL.consume+			return (x, extra))++test_TakeWhile :: Suite+test_TakeWhile = assertions "takeWhile" $ do+	$expect $ equal+		("ABC", ["D", "E"])+		(E.runLists_ [[], ["A", "B"], ["C", "D"], ["E"]] $ do+			x <- ET.takeWhile (< 'D')+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		("AB", [])+		(E.runLists_ [["A"], ["B"]] $ do+			x <- ET.takeWhile (< 'D')+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		("", ["A", "B"])+		(E.runLists_ [["A"], ["B"]] $ do+			x <- ET.takeWhile (< 'A')+			extra <- EL.consume+			return (x, extra))
+ tests/EnumeratorTests/Text/Drop.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Drop+	( test_Drop+	, test_DropWhile+	, test_Filter+	, test_FilterM+	) where++import           Test.Chell++import           Data.Enumerator ((=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++test_Drop :: Suite+test_Drop = assertions "drop" $ do+	$expect $ equal+		["ABCDE"]+		(E.runLists_ [["ABCDE"]] $ do+			ET.drop 0+			EL.consume)+	$expect $ equal+		["CDE"]+		(E.runLists_ [["ABCDE"]] $ do+			ET.drop 2+			EL.consume)+	$expect $ equal+		["CDE"]+		(E.runLists_ [["A"], ["BCDE"]] $ do+			ET.drop 2+			EL.consume)++test_DropWhile :: Suite+test_DropWhile = assertions "dropWhile" $ do+	$expect $ equal+		["CDE"]+		(E.runLists_ [["ABCDE"]] $ do+			ET.dropWhile (< 'C')+			EL.consume)+	$expect $ equal+		[]+		(E.runLists_ [["ABCDE"]] $ do+			ET.dropWhile (\_ -> True)+			EL.consume)++test_Filter :: Suite+test_Filter = assertions "filter" $ do+	$expect $ equal+		["A", "B", "", "D", "E"]+		(E.runLists_ [["ABCDE"]] $ do+			ET.filter (/= 'C') =$ EL.consume)++test_FilterM :: Suite+test_FilterM = assertions "filterM" $ do+	$expect $ equal+		["A", "B", "", "D", "E"]+		(E.runLists_ [["ABCDE"]] $ do+			ET.filterM (\x -> return (x /= 'C')) =$ EL.consume)
+ tests/EnumeratorTests/Text/Fold.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Fold+	( test_Fold+	, test_FoldM+	) where++import           Control.Monad (foldM)+import           Data.Functor.Identity (runIdentity)+import qualified Data.Text+import           Data.Text (Text)+import           Test.Chell+import           Test.Chell.QuickCheck+import           Test.QuickCheck.Poly+import           Test.QuickCheck.Modifiers++import qualified Data.Enumerator as E+import qualified Data.Enumerator.Text as ET++import           EnumeratorTests.Util ()++test_Fold :: Suite+test_Fold = property "fold" prop_Fold++prop_Fold :: Blind (B -> Char -> B) -> B -> Text -> Bool+prop_Fold (Blind f) z text = result == expected where+	result = E.runLists_ [[text]] (ET.fold f z)+	expected = Data.Text.foldl' f z text++test_FoldM :: Suite+test_FoldM = property "foldM" prop_FoldM++prop_FoldM :: Blind (B -> Char -> B) -> B -> Text -> Bool+prop_FoldM (Blind f) z text = result == expected where+	result = E.runLists_ [[text]] (ET.foldM f' z)+	expected = runIdentity (foldM f' z (Data.Text.unpack text))+	f' b a = return (f b a)
+ tests/EnumeratorTests/Text/Handle.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Handle+	( test_EnumHandle+	, test_IterHandle+	) where++import           Test.Chell++#ifdef MIN_VERSION_knob++import           Data.Knob+import qualified System.IO as IO++import qualified Data.Enumerator as E+import           Data.Enumerator (($$))+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++test_EnumHandle :: Suite+test_EnumHandle = assertions "enumHandle" $ do+	knob <- newKnob "0123\n\n4567"+	chunks <- withFileHandle knob "" IO.ReadMode $ \h -> do+		E.run_ (ET.enumHandle h $$ EL.consume)+	$expect (equal chunks ["0123", "", "4567"])++test_IterHandle :: Suite+test_IterHandle = assertions "iterHandle" $ do+	knob <- newKnob ""+	withFileHandle knob "" IO.WriteMode $ \h -> do+		E.run_ (E.enumLists [[], ["A", "B"], ["C"]] $$ ET.iterHandle h)+	bytes <- Data.Knob.getContents knob+	$expect (equal bytes "ABC")++#else++import           EnumeratorTests.Util (todo)++test_EnumHandle :: Suite+test_EnumHandle = todo "enumHandle"++test_IterHandle :: Suite+test_IterHandle = todo "iterHandle"++#endif
+ tests/EnumeratorTests/Text/Isolate.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Isolate+	( test_Isolate+	) where++import qualified Data.Text.Lazy as TL++import           Test.Chell+import           Test.Chell.QuickCheck++import           Data.Enumerator (($$), (=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++import           EnumeratorTests.Text.Util (prop_Text)++test_Isolate :: Suite+test_Isolate = suite "isolate"+	[ prop_Isolate+	, test_DropExtra+	, test_HandleEOF+	, test_BadParameter+	]++prop_Isolate :: Suite+prop_Isolate = property "model" $ prop_Text+	(do+		x <- E.joinI (ET.isolate 2 $$ ET.head)+		extra <- ET.consume+		return (x, extra))+	(\text -> Right $ case TL.unpack text of+		[] -> (Nothing, TL.empty)+		(x:[]) -> (Just x, TL.empty)+		(x:_:xs') -> (Just x, TL.pack xs'))++test_DropExtra :: Suite+test_DropExtra = assertions "drop-extra" $ do+	$expect $ equal+		(Just 'A', ["C"])+		(E.runLists_ [[], ["A"], ["B"], ["C"]] $ do+			x <- ET.isolate 2 =$ ET.head+			extra <- EL.consume+			return (x, extra))+	$expect $ equal+		(Just 'A', ["C"])+		(E.runLists_ [["A", "B", "C"]] $ do+			x <- ET.isolate 2 =$ ET.head+			extra <- EL.consume+			return (x, extra))++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ equal+		(Nothing :: Maybe Char, [])+		(E.runLists_ [] $ do+			x <- ET.isolate 2 =$ ET.head+			extra <- EL.consume+			return (x, extra))++test_BadParameter :: Suite+test_BadParameter = assertions "bad-parameter" $ do+	$expect $ equal+		(Nothing, ["A", "B", "C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			x <- ET.isolate 0 =$ ET.head+			extra <- EL.consume+			return (x, extra))
+ tests/EnumeratorTests/Text/Iterate.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Iterate+	( test_Iterate+	, test_IterateM+	) where++import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++test_Iterate :: Suite+test_Iterate = assertions "iterate" $ do+	$expect $ equal+		["A", "B", "C"]+		(runIdentity (E.run_ (ET.iterate succ 'A' $$ EL.take 3)))++test_IterateM :: Suite+test_IterateM = assertions "iterateM" $ do+	let succM = return . succ+	$expect $ equal+		["A", "B", "C"]+		(runIdentity (E.run_ (ET.iterateM succM 'A' $$ EL.take 3)))
+ tests/EnumeratorTests/Text/Map.hs view
@@ -0,0 +1,138 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Map+	( test_Map+	, test_MapM+	, test_MapM_+	, test_ConcatMap+	, test_ConcatMapM+	, test_ConcatMapAccum+	, test_ConcatMapAccumM+	, test_MapAccum+	, test_MapAccumM+	) where++import           Control.Monad.Trans.Writer (execWriter, tell)+import           Data.Char (chr, ord, toLower)+import qualified Data.Text as T++import           Test.Chell++import           Data.Enumerator (($$), (=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++test_Map :: Suite+test_Map = assertions "map" $ do+	$expect $ equal+		["a", "b"]+		(E.runLists_ [["AB"]] (ET.map toLower =$ EL.consume))+	$expect $ equal+		(["a", "b"], ["CDEF", "GH"])+		(E.runLists_ [["ABCD", "EF"], ["GH"]] $ do+			xs <- ET.map toLower =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_MapM :: Suite+test_MapM = assertions "mapM" $ do+	$expect $ equal+		["a", "b"]+		(E.runLists_ [["AB"]] (ET.mapM (return . toLower) =$ EL.consume))+	$expect $ equal+		(["a", "b"], ["CDEF", "GH"])+		(E.runLists_ [["ABCD", "EF"], ["GH"]] $ do+			xs <- ET.mapM (return . toLower) =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_MapM_ :: Suite+test_MapM_ = assertions "mapM_" $ do+	$expect $ equal+		['A', 'B']+		(execWriter (E.run_ (E.enumLists [["AB"]] $$ ET.mapM_ (\x -> tell [x]))))++test_ConcatMap :: Suite+test_ConcatMap = assertions "concatMap" $ do+	$expect $ equal+		["Aa", "Bb"]+		(E.runLists_ [["AB"]] (ET.concatMap (\x -> T.pack [x, toLower x]) =$ EL.consume))+	$expect $ equal+		(["Aa", "Bb"], ["CDEF", "GH"])+		(E.runLists_ [["ABCD", "EF"], ["GH"]] $ do+			xs <- ET.concatMap (\x -> T.pack [x, toLower x]) =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_ConcatMapM :: Suite+test_ConcatMapM = assertions "concatMapM" $ do+	$expect $ equal+		["Aa", "Bb"]+		(E.runLists_ [["AB"]] (ET.concatMapM (\x -> return (T.pack [x, toLower x])) =$ EL.consume))+	$expect $ equal+		(["Aa", "Bb"], ["CDEF", "GH"])+		(E.runLists_ [["ABCD", "EF"], ["GH"]] $ do+			xs <- ET.concatMapM (\x -> return (T.pack [x, toLower x])) =$ EL.take 2+			extra <- EL.consume+			return (xs, extra))++test_MapAccum :: Suite+test_MapAccum = assertions "mapAccum" $ do+	let step s ao = (s + 1, chr (ord ao + s))+	$expect $ equal+		["B", "D", "F"]+		(E.runLists_ [["A", "B"], ["C"]] $ do+			ET.mapAccum step 1 =$ EL.consume)+	$expect $ equal+		("B", ["", "B", "C"])+		(E.runLists_ [["A", "B"], ["C"]] $ do+			xs <- ET.mapAccum step 1 =$ ET.take 1+			extra <- EL.consume+			return (xs, extra))++test_MapAccumM :: Suite+test_MapAccumM = assertions "mapAccumM" $ do+	let step s ao = return (s + 1, chr (ord ao + s))+	$expect $ equal+		["B", "D", "F"]+		(E.runLists_ [["A", "B"], ["C"]] $ do+			ET.mapAccumM step 1 =$ EL.consume)+	$expect $ equal+		("B", ["", "B", "C"])+		(E.runLists_ [["A", "B"], ["C"]] $ do+			xs <- ET.mapAccumM step 1 =$ ET.take 1+			extra <- EL.consume+			return (xs, extra))++test_ConcatMapAccum :: Suite+test_ConcatMapAccum = assertions "concatMapAccum" $ do+	let step s ao = (s + 1, T.replicate s (T.pack [ao]))+	$expect $ equal+		["A", "BB", "CCC"]+		(E.runLists_ [["A", "B"], ["C"]] $ do+			ET.concatMapAccum step 1 =$ EL.consume)+	$expect $ equal+		("AB", ["", "C"])+		(E.runLists_ [["A", "B"], ["C"]] $ do+			xs <- ET.concatMapAccum step 1 =$ ET.take 2+			extra <- EL.consume+			return (xs, extra))++test_ConcatMapAccumM :: Suite+test_ConcatMapAccumM = assertions "concatMapAccumM" $ do+	let step s ao = return (s + 1, T.replicate s (T.pack [ao]))+	$expect $ equal+		["A", "BB", "CCC"]+		(E.runLists_ [["A", "B"], ["C"]] $ do+			ET.concatMapAccumM step 1 =$ EL.consume)+	$expect $ equal+		("AB", ["", "C"])+		(E.runLists_ [["A", "B"], ["C"]] $ do+			xs <- ET.concatMapAccumM step 1 =$ ET.take 2+			extra <- EL.consume+			return (xs, extra))
+ tests/EnumeratorTests/Text/Repeat.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Repeat+	( test_Repeat+	, test_RepeatM+	, test_GenerateM+	) where++import           Control.Monad.Trans.State+import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++test_Repeat :: Suite+test_Repeat = assertions "repeat" $ do+	$expect $ equal+		["A", "A", "A"]+		(runIdentity (E.run_ (ET.repeat 'A' $$ EL.take 3)))++test_RepeatM :: Suite+test_RepeatM = assertions "repeatM" $ do+	let step = do+		c <- get+		put (succ c)+		return c+	$expect $ equal+		["A", "B", "C"]+		(evalState (E.run_ (ET.repeatM step $$ EL.take 3)) 'A')++test_GenerateM :: Suite+test_GenerateM = assertions "generateM" $ do+	let step = do+		c <- get+		if c > 'C'+			then return Nothing+			else do+				put (succ c)+				return (Just c)+	$expect $ equal+		["A", "B", "C"]+		(evalState (E.run_ (ET.generateM step $$ EL.consume)) 'A')
+ tests/EnumeratorTests/Text/Replicate.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Replicate+	( test_Replicate+	, test_ReplicateM+	) where++import           Control.Monad.Trans.State+import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++test_Replicate :: Suite+test_Replicate = assertions "replicate" $ do+	$expect $ equal+		["A", "A", "A"]+		(runIdentity (E.run_ (ET.replicate 3 'A' $$ EL.consume)))++test_ReplicateM :: Suite+test_ReplicateM = assertions "replicateM" $ do+	let step = do+		c <- get+		put (succ c)+		return c+	$expect $ equal+		["A", "B", "C"]+		(evalState (E.run_ (ET.replicateM 3 step $$ EL.consume)) 'A')+	$expect $ equal+		["A", "B"]+		(evalState (E.run_ (ET.replicateM 3 step $$ EL.take 2)) 'A')
+ tests/EnumeratorTests/Text/Require.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Require+	( test_Require+	) where++import qualified Control.Exception as Exc+import qualified Data.Text.Lazy as TL+import           Test.Chell+import           Test.Chell.QuickCheck++import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++import           EnumeratorTests.Text.Util+import           EnumeratorTests.Util (equalExc)++test_Require :: Suite+test_Require = suite "require"+	[ prop_Require+	, test_YieldsInput+	, test_HandleEOF+	, test_BadParameter+	]++prop_Require :: Suite+prop_Require = property "model" $ prop_TextN+	(\n -> do+		ET.require n+		ET.consume)+	(\n xs -> if n > toInteger (TL.length xs)+		then Left (Exc.ErrorCall "require: Unexpected EOF")+		else Right xs)++test_YieldsInput :: Suite+test_YieldsInput = assertions "yields-input" $ do+	$expect $ equal+		["A", "B", "C"]+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			ET.require 2+			EL.consume)+	$expect $ equal+		["A", "B", "C"]+		(E.runLists_ [["A", "B", "C"]] $ do+			ET.require 2+			EL.consume)++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ equalExc+		(Exc.ErrorCall "require: Unexpected EOF")+		(E.runLists [] $ do+			ET.require 2+			EL.consume)++test_BadParameter :: Suite+test_BadParameter = assertions "bad-parameter" $ do+	$expect $ equal+		[]+		(E.runLists_ [] $ do+			ET.require 0+			EL.consume)
+ tests/EnumeratorTests/Text/Split.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Split+	( test_SplitWhen+	, test_Lines+	) where++import qualified Data.List.Split as LS+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import           Test.Chell+import           Test.Chell.QuickCheck++import           Data.Enumerator ((=$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++import           EnumeratorTests.Text.Util++test_SplitWhen :: Suite+test_SplitWhen = suite "splitWhen"+	[ prop_SplitWhen+	, test_HandleEmpty+	]++prop_SplitWhen :: Suite+prop_SplitWhen = property "model" $ prop_TextX+	(\c -> do+		xs <- ET.splitWhen (== c) =$ EL.consume+		extra <- EL.consume+		return (xs, extra))+	(\c text -> let+		split = LS.split . LS.dropFinalBlank . LS.dropDelims . LS.whenElt+		chars = TL.unpack text+		in Right (map T.pack (split (== c) chars), []))++test_HandleEmpty :: Suite+test_HandleEmpty = assertions "empty" $ do+	$expect $ equal+		([], Nothing)+		(E.runLists_ [[""]] $ do+			xs <- ET.splitWhen (== ',') =$ EL.consume+			extra <- EL.head+			return (xs, extra))++test_Lines :: Suite+test_Lines = assertions "lines" $ do+	$expect $ equal+		["abc", "def"]+		(E.runLists_ [["abc\ndef"]] (ET.lines =$ EL.consume))+	$expect $ equal+		["abc", "def"]+		(E.runLists_ [["abc\ndef\n"]] (ET.lines =$ EL.consume))+	$expect $ equal+		["abc", "def", ""]+		(E.runLists_ [["abc\ndef\n\n"]] (ET.lines =$ EL.consume))
+ tests/EnumeratorTests/Text/Unfold.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Unfold+	( test_Unfold+	, test_UnfoldM+	) where++import           Data.Functor.Identity (runIdentity)+import           Test.Chell++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++test_Unfold :: Suite+test_Unfold = assertions "unfold" $ do+	let step x = if x > 'C'+		then Nothing+		else Just (x, succ x)+	$expect $ equal+		["A", "B", "C"]+		(runIdentity (E.run_ (ET.unfold step 'A' $$ EL.consume)))++test_UnfoldM :: Suite+test_UnfoldM = assertions "unfoldM" $ do+	let step x = return $ if x > 'C'+		then Nothing+		else Just (x, succ x)+	$expect $ equal+		["A", "B", "C"]+		(runIdentity (E.run_ (ET.unfoldM step 'A' $$ EL.consume)))
+ tests/EnumeratorTests/Text/Util.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Util+	( prop_Text+	, prop_TextN+	, prop_TextX+	) where++import           Control.Exception (ErrorCall)+import           Data.Text (Text)+import qualified Data.Text.Lazy as TL+import           Data.Functor.Identity (Identity)++import           Test.QuickCheck hiding (property)++import           Data.Enumerator (Iteratee)++import           EnumeratorTests.Util (check)++prop_Text :: Eq b+          => Iteratee Text Identity b+          -> (TL.Text -> Either ErrorCall b)+          -> [Text]+          -> Bool+prop_Text iter plain = check iter (plain . TL.fromChunks)++prop_TextN :: Eq b+           => (Integer -> Iteratee Text Identity b)+           -> (Integer -> TL.Text -> Either ErrorCall b)+           -> Positive Integer+           -> [Text]+           -> Bool+prop_TextN iter plain (Positive n) = check (iter n) (plain n . TL.fromChunks)++prop_TextX :: Eq b+           => (Char -> Iteratee Text Identity b)+           -> (Char -> TL.Text -> Either ErrorCall b)+           -> Char+           -> [Text]+           -> Bool+prop_TextX iter plain x = check (iter x) (plain x . TL.fromChunks)
+ tests/EnumeratorTests/Text/Zip.hs view
@@ -0,0 +1,164 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Text.Zip+	( test_Zip+	) where++import qualified Control.Exception as Exc+import           Data.Functor.Identity (Identity)+import           Data.Text (Text)+import           Test.Chell++import qualified Data.Enumerator as E+import qualified Data.Enumerator.List as EL+import qualified Data.Enumerator.Text as ET++import           EnumeratorTests.Util (equalExc)++test_ZipN :: (Eq b, Show b) => Text -> E.Iteratee Text Identity b -> b -> Suite+test_ZipN name iter expected = assertions name $ do+	$expect $ equal+		expected+		(E.runLists_ [[], ["A"], ["B"]] iter)++$([d||])++test_Zip :: Suite+test_Zip = suite "zip"+	[ test_ContinueContinue+	, test_YieldContinue+	, test_ContinueYield+	, test_YieldYield+	, test_ErrorFirst+	, test_ErrorSecond+	, test_HandleEOF+	, test_Zip3+	, test_Zip4+	, test_Zip5+	, test_Zip6+	, test_Zip7+	, test_ZipWith+	, test_ZipWith3+	, test_ZipWith4+	, test_ZipWith5+	, test_ZipWith6+	, test_ZipWith7+	]++test_ContinueContinue :: Suite+test_ContinueContinue = assertions "continue-continue" $ do+	$expect $ equal+		("AB", "AB", ["C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			(x, y) <- ET.zip (ET.take 2) (ET.take 2)+			extra <- EL.consume+			return (x, y, extra))++test_YieldContinue :: Suite+test_YieldContinue = assertions "yield-continue" $ do+	$expect $ equal+		("A", "AB", ["C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			(x, y) <- ET.zip (ET.take 1) (ET.take 2)+			extra <- EL.consume+			return (x, y, extra))++test_ContinueYield :: Suite+test_ContinueYield = assertions "continue-yield" $ do+	$expect $ equal+		("AB", "A", ["C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			(x, y) <- ET.zip (ET.take 2) (ET.take 1)+			extra <- EL.consume+			return (x, y, extra))++test_YieldYield :: Suite+test_YieldYield = assertions "yield-yield" $ do+	$expect $ equal+		("A", "A", ["B", "C"])+		(E.runLists_ [["A"], ["B"], ["C"]] $ do+			(x, y) <- ET.zip (ET.take 1) (ET.take 1)+			extra <- EL.consume+			return (x, y, extra))++test_ErrorFirst :: Suite+test_ErrorFirst = assertions "error-first" $ do+	$expect $ equalExc+		(Exc.ErrorCall "error")+		(E.runLists [["A"], ["B"], ["C"]] $ do+			ET.zip (E.throwError (Exc.ErrorCall "error")) (ET.take 1))++test_ErrorSecond :: Suite+test_ErrorSecond = assertions "error-second" $ do+	$expect $ equalExc+		(Exc.ErrorCall "error")+		(E.runLists [["A"], ["B"], ["C"]] $ do+			ET.zip (ET.take 1) (E.throwError (Exc.ErrorCall "error")))++test_HandleEOF :: Suite+test_HandleEOF = assertions "handle-eof" $ do+	$expect $ equal+		("A", "AB", [])+		(E.runLists_ [["A"], ["B"]] $ do+			(x, y) <- ET.zip (ET.take 1) (ET.take 3)+			extra <- EL.consume+			return (x, y, extra))++test_Zip3 :: Suite+test_Zip3 = test_ZipN "zip3"+	(ET.zip3 ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A')++test_Zip4 :: Suite+test_Zip4 = test_ZipN "zip4"+	(ET.zip4 ET.head ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A', Just 'A')++test_Zip5 :: Suite+test_Zip5 = test_ZipN "zip5"+	(ET.zip5 ET.head ET.head ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_Zip6 :: Suite+test_Zip6 = test_ZipN "zip6"+	(ET.zip6 ET.head ET.head ET.head ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_Zip7 :: Suite+test_Zip7 = test_ZipN "zip7"+	(ET.zip7 ET.head ET.head ET.head ET.head ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_ZipWith :: Suite+test_ZipWith = test_ZipN "zipWith"+	(ET.zipWith (,) ET.head ET.head)+	(Just 'A', Just 'A')++test_ZipWith3 :: Suite+test_ZipWith3 = test_ZipN "zipWith3"+	(ET.zipWith3 (,,) ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A')++test_ZipWith4 :: Suite+test_ZipWith4 = test_ZipN "zipWith4"+	(ET.zipWith4 (,,,) ET.head ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A', Just 'A')++test_ZipWith5 :: Suite+test_ZipWith5 = test_ZipN "zipWith5"+	(ET.zipWith5 (,,,,) ET.head ET.head ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_ZipWith6 :: Suite+test_ZipWith6 = test_ZipN "zipWith6"+	(ET.zipWith6 (,,,,,) ET.head ET.head ET.head ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')++test_ZipWith7 :: Suite+test_ZipWith7 = test_ZipN "zipWith7"+	(ET.zipWith7 (,,,,,,) ET.head ET.head ET.head ET.head ET.head ET.head ET.head)+	(Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A', Just 'A')
+ tests/EnumeratorTests/Util.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE OverloadedStrings #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module EnumeratorTests.Util+	( check+	, equalExc+	, todo+	, within+	, genASCII+	, genISO8859_1+	, genUnicode+	) where++import qualified Control.Exception as Exc+import           Data.Bits ((.&.))+import qualified Data.ByteString as B+import           Data.Char (chr)+import           Data.Functor.Identity (Identity, runIdentity)+import           Data.String (IsString, fromString)+import qualified Data.Text as T+import           System.Timeout (timeout)++import           Test.Chell+import           Test.QuickCheck hiding ((.&.), within)++import           Data.Enumerator (($$))+import qualified Data.Enumerator as E++check :: Eq b => E.Iteratee a Identity b -> ([a] -> Either Exc.ErrorCall b) -> [a] -> Bool+check iter plain xs = expected == run where+	expected = case plain xs of+		Left exc -> Left (Just exc)+		Right x -> Right x+	+	run = case runIdentity (E.run (E.enumList 1 xs $$ iter)) of+		Left exc -> Left (Exc.fromException exc)+		Right x -> Right x++todo :: T.Text -> Suite+todo name = skipIf True (assertions name (return ()))++genASCII :: IsString a => Gen a+genASCII = fmap fromString string where+	string = sized $ \n -> do+		k <- choose (0,n)+		sequence [ char | _ <- [1..k] ]+	+	char = chr `fmap` choose (0,0x7F)++genISO8859_1 :: IsString a => Gen a+genISO8859_1 = fmap fromString string where+	string = sized $ \n -> do+		k <- choose (0,n)+		sequence [ char | _ <- [1..k] ]+	+	char = chr `fmap` choose (0,0xFF)++genUnicode :: IsString a => Gen a+genUnicode = fmap fromString string where+	string = sized $ \n -> do+		k <- choose (0,n)+		sequence [ char | _ <- [1..k] ]+	+	excluding :: [a -> Bool] -> Gen a -> Gen a+	excluding bad gen = loop where+		loop = do+			x <- gen+			if or (map ($ x) bad)+				then loop+				else return x+	+	reserved = [lowSurrogate, highSurrogate, noncharacter]+	lowSurrogate c = c >= 0xDC00 && c <= 0xDFFF+	highSurrogate c = c >= 0xD800 && c <= 0xDBFF+	noncharacter c = masked == 0xFFFE || masked == 0xFFFF where+		masked = c .&. 0xFFFF+	+	ascii = choose (0,0x7F)+	plane0 = choose (0xF0, 0xFFFF)+	plane1 = oneof [ choose (0x10000, 0x10FFF)+	               , choose (0x11000, 0x11FFF)+	               , choose (0x12000, 0x12FFF)+	               , choose (0x13000, 0x13FFF)+	               , choose (0x1D000, 0x1DFFF)+	               , choose (0x1F000, 0x1FFFF)+	               ]+	plane2 = oneof [ choose (0x20000, 0x20FFF)+	               , choose (0x21000, 0x21FFF)+	               , choose (0x22000, 0x22FFF)+	               , choose (0x23000, 0x23FFF)+	               , choose (0x24000, 0x24FFF)+	               , choose (0x25000, 0x25FFF)+	               , choose (0x26000, 0x26FFF)+	               , choose (0x27000, 0x27FFF)+	               , choose (0x28000, 0x28FFF)+	               , choose (0x29000, 0x29FFF)+	               , choose (0x2A000, 0x2AFFF)+	               , choose (0x2B000, 0x2BFFF)+	               , choose (0x2F000, 0x2FFFF)+	               ]+	plane14 = choose (0xE0000, 0xE0FFF)+	planes = [ascii, plane0, plane1, plane2, plane14]+	+	char = chr `fmap` excluding reserved (oneof planes)++instance Arbitrary a => Arbitrary (E.Stream a) where+	arbitrary = frequency+		[ (10, return E.EOF)+		, (90, fmap E.Chunks arbitrary)+		]++instance Arbitrary T.Text where+	arbitrary = genUnicode++instance Arbitrary B.ByteString where+	arbitrary = genUnicode++instance Eq Exc.ErrorCall where+	(Exc.ErrorCall s1) == (Exc.ErrorCall s2) = s1 == s2++-- | Require a test to complete within /n/ milliseconds.+within :: Int -> Suite -> Suite+within time s = suite (suiteName s) (map wrapTest (suiteTests s)) where+	wrapTest (Test name io) = test $ Test name $ \opts -> do+		res <- timeout (time * 1000) (io opts)+		case res of+			Just res' -> return res'+			Nothing -> return (TestAborted [] (T.pack ("Test timed out after " ++ show time ++ " milliseconds")))++equalExc :: (Eq exc, Exc.Exception exc) => exc -> Either Exc.SomeException a -> Assertion+equalExc expected funResult = Assertion (return result) where+	failed :: String -> AssertionResult+	failed str = AssertionFailed (T.pack ("equalExc: " ++ show str))+	result = case funResult of+		Right _ -> failed "received Right"+		Left exc -> case Exc.fromException exc of+			Nothing -> failed ("received unexpected exception: " ++ show exc)+			Just exc' -> if expected == exc'+				then AssertionPassed+				else failed (show expected ++ " /= " ++ show exc')
− tests/Tests.hs
@@ -1,936 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}---- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>------ See license.txt for details-module Main (tests, main) where--import           Control.Concurrent-import qualified Control.Exception as Exc-import           Control.Monad.IO.Class (liftIO)-import           Data.Bits ((.&.))-import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as B8-import qualified Data.ByteString.Lazy as BL-import           Data.Char (chr)-import           Data.Functor.Identity (Identity, runIdentity)-import qualified Data.List as L-import qualified Data.List.Split as LS-import           Data.Monoid (mappend, mempty, mconcat)-import           Data.String (IsString, fromString)-import qualified Data.Text as T-import qualified Data.Text.Encoding as TE-import qualified Data.Text.Lazy as TL-import           Data.Word (Word8)-import           System.Timeout (timeout)--import           Test.Chell-import           Test.Chell.QuickCheck-import           Test.QuickCheck hiding ((.&.), property, within)-import           Test.QuickCheck.Poly (A, B, C)--import           Data.Enumerator (($$), (>>==))-import qualified Data.Enumerator as E-import qualified Data.Enumerator.Binary as EB-import qualified Data.Enumerator.Text as ET-import qualified Data.Enumerator.List as EL--tests :: [Suite]-tests =-	[ suite_StreamInstances-	, suite_Text-	, suite_ListAnalogues-	, suite_Other-	]--main :: IO ()-main = Test.Chell.defaultMain tests---- Stream instances {{{--suite_StreamInstances :: Suite-suite_StreamInstances = suite "stream-instances"-	[ suite_StreamMonoid-	, suite_StreamFunctor-	, suite_StreamMonad-	]--suite_StreamMonoid :: Suite-suite_StreamMonoid = suite "monoid" props where-	props = [ property "law-1" prop_law1-	        , property "law-2" prop_law2-	        , property "law-3" prop_law3-	        , property "law-4" prop_law4-	        ]-	-	prop_law1 :: E.Stream A -> Bool-	prop_law1 x = mappend mempty x == x-	-	prop_law2 :: E.Stream A -> Bool-	prop_law2 x = mappend x mempty == x-	-	prop_law3 :: E.Stream A -> E.Stream A -> E.Stream A -> Bool-	prop_law3 x y z = mappend x (mappend y z) == mappend (mappend x y) z-	-	prop_law4 :: [E.Stream A] -> Bool-	prop_law4 xs = mconcat xs == foldr mappend mempty xs--suite_StreamFunctor :: Suite-suite_StreamFunctor = suite "functor" props where-	props = [ property "law-1" prop_law1-	        , property "law-2" prop_law2-	        ]-	-	prop_law1 :: E.Stream A -> Bool-	prop_law1 x = fmap id x == id x-	-	prop_law2 :: E.Stream A -> Blind (B -> C) -> Blind (A -> B) -> Bool-	prop_law2 x (Blind f) (Blind g) = fmap (f . g) x == (fmap f . fmap g) x--suite_StreamMonad :: Suite-suite_StreamMonad = suite "Monad Stream" props where-	props = [ property "law-1" prop_law1-	        , property "law-2" prop_law2-	        , property "law-3" prop_law3-	        ]-	-	prop_law1 :: A -> Blind (A -> E.Stream B) -> Bool-	prop_law1 a (Blind f) = (return a >>= f) == f a-	-	prop_law2 :: E.Stream A -> Bool-	prop_law2 m = (m >>= return) == m-	-	prop_law3 :: E.Stream A -> Blind (A -> E.Stream B) -> Blind (B -> E.Stream C) -> Bool-	prop_law3 m (Blind f) (Blind g) = ((m >>= f) >>= g) == (m >>= (\x -> f x >>= g))---- }}}---- Generic properties {{{--test_Enumeratee :: T.Text -> E.Enumeratee A A Identity (Maybe A) -> Suite-test_Enumeratee name enee = suite name props where-	props = [ property "incremental" prop_incremental-	        , property "nest-errors" prop_nest_errors-	        ]-	-	prop_incremental (Positive n) (NonEmpty xs) = let-		result = runIdentity (E.run_ iter)-		expected = (Just (head xs), tail xs)-		-		iter = E.enumList n xs $$ do-			a <- E.joinI (enee $$ EL.head)-			b <- EL.consume-			return (a, b)-		-		in result == expected-	-	prop_nest_errors (Positive n) (NonEmpty xs) = let-		result = runIdentity (E.run_ iter)-		-		iter = E.enumList n xs $$ do-			_ <- enee $$ E.throwError (Exc.ErrorCall "")-			EL.consume-		-		in result == xs---- }}}---- Text encoding / decoding {{{--suite_Text :: Suite-suite_Text = suite "text"-	[ suite_Encoding-	, suite_Decoding-	]--suite_Encoding :: Suite-suite_Encoding = suite "encoding"-	[ suite_Encode_ASCII-	, suite_Encode_ISO8859-	]--suite_Encode_ASCII :: Suite-suite_Encode_ASCII = suite "ascii" props where-	props = [ property "works" (forAll genASCII prop_works)-	        , property "error" prop_error-	        , property "lazy" prop_lazy-	        ]-	-	encode iter input =-		runIdentity . E.run $-		E.enumList 1 input $$-		E.joinI (ET.encode ET.ascii $$ iter)-	-	prop_works bytes = result == map B.singleton words where-		Right result = encode EL.consume (map T.singleton chars)-		-		chars = B8.unpack bytes-		words = B.unpack bytes-	-	prop_error = isLeft (encode EL.consume input)  where-		isLeft = either (const True) (const False)-		input = [T.pack "\x61\xFF"]-	-	prop_lazy = either (const False) (== expected) result where-		result = encode EL.head input-		input = [T.pack "\x61\xFF"]-		expected = Just (B.singleton 0x61)--suite_Encode_ISO8859 :: Suite-suite_Encode_ISO8859 = suite "iso-8859-1" props where-	props = [ property "works" (forAll genISO8859 prop_works)-	        , property "error" prop_error-	        , property "lazy" prop_lazy-	        ]-	-	encode iter input =-		runIdentity . E.run $-		E.enumList 1 input $$-		E.joinI (ET.encode ET.iso8859_1 $$ iter)-	-	prop_works bytes = result == map B.singleton words where-		Right result = encode EL.consume (map T.singleton chars)-		-		chars = B8.unpack bytes-		words = B.unpack bytes-	-	prop_error = isLeft (encode EL.consume input)  where-		isLeft = either (const True) (const False)-		input = [T.pack "\x61\xFF5E"]-	-	prop_lazy = either (const False) (== expected) result where-		result = encode EL.head input-		input = [T.pack "\x61\xFF5E"]-		expected = Just (B.singleton 0x61)--suite_Decoding :: Suite-suite_Decoding = suite "decoding"-	[ suite_Decode_ASCII-	, suite_Decode_UTF8-	, suite_Decode_UTF16_BE-	, suite_Decode_UTF16_LE-	, suite_Decode_UTF32_BE-	, suite_Decode_UTF32_LE-	]--suite_Decode_ASCII :: Suite-suite_Decode_ASCII = suite "ascii" props where-	props = [ property "works" (forAll genASCII prop_works)-	        , property "error" prop_error-	        , property "lazy" prop_lazy-	        ]-	-	decode iter input =-		runIdentity . E.run $-		E.enumList 1 input $$-		E.joinI (ET.decode ET.ascii $$ iter)-	-	prop_works text = result == map T.singleton chars where-		Right result = decode EL.consume (map B.singleton bytes)-		-		bytes = B.unpack (TE.encodeUtf8 text)-		chars = T.unpack text-	-	prop_error = isLeft (decode EL.consume input)  where-		isLeft = either (const True) (const False)-		input = [B.pack [0xFF]]-	-	prop_lazy = either (const False) (== expected) result where-		result = decode EL.head input-		input = [B.pack [0x61, 0xFF]]-		expected = Just (T.pack "a")--suite_Decode_UTF8 :: Suite-suite_Decode_UTF8 = suite "utf-8" props where-	props = [ property "works" prop_works-	        , property "error" prop_error-	        , property "lazy" prop_lazy-	        , property "incremental" prop_incremental-	        ]-	-	decode iter input =-		runIdentity . E.run $-		E.enumList 1 input $$-		E.joinI (ET.decode ET.utf8 $$ iter)-	-	prop_works text = result == map T.singleton chars where-		Right result = decode EL.consume (map B.singleton bytes)-		-		bytes = B.unpack (TE.encodeUtf8 text)-		chars = T.unpack text-	-	prop_error = isLeft (decode EL.consume input)  where-		isLeft = either (const True) (const False)-		input = [B.pack [0x61, 0x80]]-	-	prop_lazy = either (const False) (== expected) result where-		result = decode EL.head input-		input = [B.pack [0x61, 0x80]]-		expected = Just (T.pack "a")-	-	prop_incremental = either (const False) (== expected) result where-		result = decode EL.head input-		input = [B.pack [0x61, 0xC2, 0xC2]]-		expected = Just (T.pack "a")--suite_Decode_UTF16_BE :: Suite-suite_Decode_UTF16_BE = suite "utf-16-be" props where-	props = [ property "works" prop_works-	        , property "lazy" prop_lazy-	        , property "error" prop_error-	        , property "incremental" prop_incremental-	        ]-	-	decode iter input =-		runIdentity . E.run $-		E.enumList 1 input $$-		E.joinI (ET.decode ET.utf16_be $$ iter)-	-	prop_works text = result == map T.singleton chars where-		Right result = decode EL.consume (map B.singleton bytes)-		-		bytes = B.unpack (TE.encodeUtf16BE text)-		chars = T.unpack text-	-	prop_lazy = either (const False) (== expected) result where-		result = decode EL.head input-		input = [B.pack [0x00, 0x61, 0xDD, 0x1E]]-		expected = Just (T.pack "a")-	-	prop_error = isLeft (decode EL.consume input)  where-		isLeft = either (const True) (const False)-		input = [B.pack [0x00, 0x61, 0xDD, 0x1E]]-	-	prop_incremental = either (const False) (== expected) result where-		result = decode EL.head input-		input = [B.pack [0x00, 0x61, 0xD8, 0x34, 0xD8, 0xD8]]-		expected = Just (T.pack "a")--suite_Decode_UTF16_LE :: Suite-suite_Decode_UTF16_LE = suite "utf-16-le" props where-	props = [ property "works" prop_works-	        , property "lazy" prop_lazy-	        , property "error" prop_error-	        , property "incremental" prop_incremental-	        ]-	-	decode iter input =-		runIdentity . E.run $-		E.enumList 1 input $$-		E.joinI (ET.decode ET.utf16_le $$ iter)-	-	prop_works text = result == map T.singleton chars where-		Right result = decode EL.consume (map B.singleton bytes)-		-		bytes = B.unpack (TE.encodeUtf16LE text)-		chars = T.unpack text-	-	prop_lazy = either (const False) (== expected) result where-		result = decode EL.head input-		input = [B.pack [0x61, 0x00, 0x1E, 0xDD]]-		expected = Just (T.pack "a")-	-	prop_error = isLeft (decode EL.consume input)  where-		isLeft = either (const True) (const False)-		input = [B.pack [0x61, 0x00, 0x1E, 0xDD]]-	-	prop_incremental = either (const False) (== expected) result where-		result = decode EL.head input-		input = [B.pack [0x61, 0x00, 0x34, 0xD8, 0xD8, 0xD8]]-		expected = Just (T.pack "a")--suite_Decode_UTF32_BE :: Suite-suite_Decode_UTF32_BE = suite "utf-32-be" props where-	props = [ property "works" prop_works-	        , property "lazy" prop_lazy-	        , property "error" prop_error-	        ]-	-	decode iter input =-		runIdentity . E.run $-		E.enumList 1 input $$-		E.joinI (ET.decode ET.utf32_be $$ iter)-	-	prop_works text = result == map T.singleton chars where-		Right result = decode EL.consume (map B.singleton bytes)-		-		bytes = B.unpack (TE.encodeUtf32BE text)-		chars = T.unpack text-	-	prop_lazy = either (const False) (== expected) result where-		result = decode EL.head input-		input = [B.pack [0x00, 0x00, 0x00, 0x61, 0xFF, 0xFF]]-		expected = Just (T.pack "a")-	-	prop_error = isLeft (decode EL.consume input)  where-		isLeft = either (const True) (const False)-		input = [B.pack [0xFF, 0xFF, 0xFF, 0xFF]]--suite_Decode_UTF32_LE :: Suite-suite_Decode_UTF32_LE = suite "utf-32-le" props where-	props = [ property "works" prop_works-	        , property "lazy" prop_lazy-	        , property "error" prop_error-	        ]-	-	decode iter input =-		runIdentity . E.run $-		E.enumList 1 input $$-		E.joinI (ET.decode ET.utf32_le $$ iter)-	-	prop_works text = result == map T.singleton chars where-		Right result = decode EL.consume (map B.singleton bytes)-		-		bytes = B.unpack (TE.encodeUtf32LE text)-		chars = T.unpack text-	-	prop_lazy = either (const False) (== expected) result where-		result = decode EL.head input-		input = [B.pack [0x61, 0x00, 0x00, 0x00, 0xFF, 0xFF]]-		expected = Just (T.pack "a")-	-	prop_error = isLeft (decode EL.consume input)  where-		isLeft = either (const True) (const False)-		input = [B.pack [0xFF, 0xFF, 0xFF, 0xFF]]---- }}}---- List analogues {{{--suite_ListAnalogues :: Suite-suite_ListAnalogues = suite "list-analogues"-	[ suite_Consume-	, suite_Head-	, suite_Drop-	, suite_Take-	, suite_Require-	, suite_Isolate-	, suite_SplitWhen-	, suite_Map-	, suite_ConcatMap-	, suite_MapM-	, suite_ConcatMapM-	, suite_MapAccum-	, suite_MapAccumM-	, suite_Filter-	, suite_FilterM-	]--check :: Eq b => E.Iteratee a Identity b -> ([a] -> Either Exc.ErrorCall b) -> [a] -> Bool-check iter plain xs = expected == run iter xs where-	expected = case plain xs of-		Left exc -> Left (Just exc)-		Right x -> Right x-	-	run iter xs = case runIdentity (E.run (E.enumList 1 xs $$ iter)) of-		Left exc -> Left (Exc.fromException exc)-		Right x -> Right x--testListAnalogue name iterList plainList iterText plainText iterBytes plainBytes = suite name tests where-	tests = [ property "list" prop_List-	        , property "text" prop_Text-	        , property "bytes" prop_Bytes-	        ]-	-	prop_List :: [A] -> Bool-	prop_List xs = check iterList plainList xs-	-	prop_Text xs = check iterText (plainText . TL.fromChunks) xs-	prop_Bytes xs = check iterBytes (plainBytes . BL.fromChunks) xs--testListAnalogueN name iterList plainList iterText plainText iterBytes plainBytes = suite name tests where-	tests = [ property "list" prop_List-	        , property "text" prop_Text-	        , property "bytes" prop_Bytes-	        ]-	-	prop_List :: Positive Integer -> [A] -> Bool-	prop_List (Positive n) xs = check (iterList n) (plainList n) xs-	-	prop_Text (Positive n) xs = check (iterText n) (plainText n . TL.fromChunks) xs-	prop_Bytes (Positive n) xs = check (iterBytes n) (plainBytes n . BL.fromChunks) xs--testListAnalogueX name iterList plainList iterText plainText iterBytes plainBytes = suite name tests where-	tests = [ property "list" prop_List-	        , property "text" prop_Text-	        , property "bytes" prop_Bytes-	        ]-	-	prop_List :: A -> [A] -> Bool-	prop_List x xs = check (iterList x) (plainList x) xs-	-	prop_Text x xs = check (iterText x) (plainText x . TL.fromChunks) xs-	prop_Bytes x xs = check (iterBytes x) (plainBytes x . BL.fromChunks) xs--suite_Consume :: Suite-suite_Consume = testListAnalogue "consume"-	EL.consume Right-	ET.consume Right-	EB.consume Right--suite_Head :: Suite-suite_Head = testListAnalogue "head"-	(do-		x <- EL.head-		extra <- EL.consume-		return (x, extra)-	)-	(\xs -> Right $ case xs of-		[] -> (Nothing, [])-		(x:xs') -> (Just x, xs'))-	(do-		x <- ET.head-		extra <- ET.consume-		return (x, extra)-	)-	(\text -> Right $ case TL.uncons text of-		Nothing -> (Nothing, TL.empty)-		Just (x, extra) -> (Just x, extra))-	(do-		x <- EB.head-		extra <- EB.consume-		return (x, extra)-	)-	(\bytes -> Right $ case BL.uncons bytes of-		Nothing -> (Nothing, BL.empty)-		Just (x, extra) -> (Just x, extra))--suite_Drop :: Suite-suite_Drop = testListAnalogueN "drop"-	(\n -> EL.drop n >> EL.consume)-	(\n -> Right . L.genericDrop n)-	(\n -> ET.drop n >> ET.consume)-	(\n -> Right . TL.drop (fromInteger n))-	(\n -> EB.drop n >> EB.consume)-	(\n -> Right . BL.drop (fromInteger n))--suite_Take :: Suite-suite_Take = testListAnalogueN "take"-	(\n -> do-		xs <- EL.take n-		extra <- EL.consume-		return (xs, extra))-	(\n -> Right . L.genericSplitAt n)-	(\n -> do-		xs <- ET.take n-		extra <- ET.consume-		return (xs, extra))-	(\n -> Right . TL.splitAt (fromInteger n))-	(\n -> do-		xs <- EB.take n-		extra <- EB.consume-		return (xs, extra))-	(\n -> Right . BL.splitAt (fromInteger n))--suite_Require :: Suite-suite_Require = testListAnalogueN "require"-	(\n -> do-		EL.require n-		EL.consume)-	(\n xs -> if n > toInteger (length xs)-		then Left (Exc.ErrorCall "require: Unexpected EOF")-		else Right xs)-	(\n -> do-		ET.require n-		ET.consume)-	(\n xs -> if n > toInteger (TL.length xs)-		then Left (Exc.ErrorCall "require: Unexpected EOF")-		else Right xs)-	(\n -> do-		EB.require n-		EB.consume)-	(\n xs -> if n > toInteger (BL.length xs)-		then Left (Exc.ErrorCall "require: Unexpected EOF")-		else Right xs)--suite_Isolate :: Suite-suite_Isolate = testListAnalogue "isolate"-	(do-		x <- E.joinI (EL.isolate 2 $$ EL.head)-		extra <- EL.consume-		return (x, extra))-	(\xs -> Right $ case xs of-		[] -> (Nothing, [])-		(x:[]) -> (Just x, [])-		(x:_:xs') -> (Just x, xs'))-	(do-		x <- E.joinI (ET.isolate 2 $$ ET.head)-		extra <- ET.consume-		return (x, extra))-	(\text -> Right $ case TL.unpack text of-		[] -> (Nothing, TL.empty)-		(x:[]) -> (Just x, TL.empty)-		(x:_:xs') -> (Just x, TL.pack xs'))-	(do-		x <- E.joinI (EB.isolate 2 $$ EB.head)-		extra <- EB.consume-		return (x, extra))-	(\bytes -> Right $ case BL.unpack bytes of-		[] -> (Nothing, BL.empty)-		(x:[]) -> (Just x, BL.empty)-		(x:_:xs) -> (Just x, BL.pack xs))--suite_SplitWhen :: Suite-suite_SplitWhen = testListAnalogueX "splitWhen"-	(\x -> do-		xs <- E.joinI (EL.splitWhen (== x) $$ EL.consume)-		extra <- EL.consume-		return (xs, extra))-	(\x xs -> let-		split = LS.split . LS.dropFinalBlank . LS.dropDelims . LS.whenElt-		in Right (split (== x) xs, []))-	(\c -> do-		xs <- E.joinI (ET.splitWhen (== c) $$ EL.consume)-		extra <- EL.consume-		return (xs, extra))-	(\c text -> let-		split = LS.split . LS.dropFinalBlank . LS.dropDelims . LS.whenElt-		chars = TL.unpack text-		in Right (map T.pack (split (== c) chars), []))-	(\x -> do-		xs <- E.joinI (EB.splitWhen (== x) $$ EL.consume)-		extra <- EL.consume-		return (xs, extra))-	(\x bytes -> let-		split = LS.split . LS.dropFinalBlank . LS.dropDelims . LS.whenElt-		words = BL.unpack bytes-		in Right (map B.pack (split (== x) words), []))--suite_Map :: Suite-suite_Map = test_Enumeratee "map" (EL.map id)--suite_ConcatMap :: Suite-suite_ConcatMap = test_Enumeratee "concatMap" (EL.concatMap (:[]))--suite_MapM :: Suite-suite_MapM = test_Enumeratee "mapM" (EL.mapM return)--suite_ConcatMapM :: Suite-suite_ConcatMapM = test_Enumeratee "concatMapM" (EL.concatMapM (\x -> return [x]))--suite_MapAccum :: Suite-suite_MapAccum = testListAnalogue "mapAccum"-	(do-		let enee = EL.mapAccum (\s ao -> (s+1, (s, ao))) 10-		a <- E.joinI (enee $$ EL.head)-		b <- EL.consume-		return (a, b))-	(\xs -> Right $ case xs of-		[] -> (Nothing, [])-		(x:xs') -> (Just (10, x), xs'))-	(do-		let enee = ET.mapAccum (\s ao -> (s+1, succ ao)) 10-		a <- E.joinI (enee $$ EL.head)-		b <- ET.consume-		return (a, b))-	(\text -> Right $ case TL.uncons text of-		Nothing -> (Nothing, TL.empty)-		Just (c, text') -> (Just (T.singleton (succ c)), text'))-	(do-		let enee = EB.mapAccum (\s ao -> (s+1, ao + s)) 10-		a <- E.joinI (enee $$ EL.head)-		b <- EB.consume-		return (a, b))-	(\bytes -> Right $ case BL.uncons bytes of-		Nothing -> (Nothing, BL.empty)-		Just (b, bytes') -> (Just (B.singleton (b + 10)), bytes'))---suite_MapAccumM :: Suite-suite_MapAccumM = testListAnalogue "mapAccumM"-	(do-		let enee = EL.mapAccumM (\s ao -> return (s+1, (s, ao))) 10-		a <- E.joinI (enee $$ EL.head)-		b <- EL.consume-		return (a, b))-	(\xs -> Right $ case xs of-		[] -> (Nothing, [])-		(x:xs') -> (Just (10, x), xs'))-	(do-		let enee = ET.mapAccumM (\s ao -> return (s+1, succ ao)) 10-		a <- E.joinI (enee $$ EL.head)-		b <- ET.consume-		return (a, b))-	(\text -> Right $ case TL.uncons text of-		Nothing -> (Nothing, TL.empty)-		Just (c, text') -> (Just (T.singleton (succ c)), text'))-	(do-		let enee = EB.mapAccumM (\s ao -> return (s+1, ao + s)) 10-		a <- E.joinI (enee $$ EL.head)-		b <- EB.consume-		return (a, b))-	(\bytes -> Right $ case BL.uncons bytes of-		Nothing -> (Nothing, BL.empty)-		Just (b, bytes') -> (Just (B.singleton (b + 10)), bytes'))--suite_Filter :: Suite-suite_Filter = test_Enumeratee "filter" (EL.filter (\_ -> True))--suite_FilterM :: Suite-suite_FilterM = test_Enumeratee "filterM" (EL.filterM (\_ -> return True))---- }}}---- Specific functions--suite_Other :: Suite-suite_Other = suite "other"-	[ test_Sequence-	, test_joinE-	, suite "catchError"-		[ test test_CatchError_WithoutContinue-		, test test_CatchError_NotDivergent-		, test test_CatchError_Interleaved-		]-	, test test_Zip-	, test test_ZipBytes-	, test test_ZipText-	]--test_Sequence :: Suite-test_Sequence = property "sequence" prop where-	prop :: Positive Integer -> [A] -> Bool-	prop (Positive n) xs = result == expected where-		result = runIdentity (E.run_ iter)-		expected = map Just xs-		-		iter = E.enumList n xs $$ E.joinI (E.sequence EL.head $$ EL.consume)--test_joinE :: Suite-test_joinE = property "joinE" prop where-	prop :: [Integer] -> Bool-	prop xs = result == expected where-		result = runIdentity (E.run_ iter)-		expected = map (* 10) xs-		-		iter = (E.joinE (E.enumList 1 xs) (EL.map (* 10))) $$ EL.consume--test_CatchError_WithoutContinue :: Test-test_CatchError_WithoutContinue = assertions "without-continue" $ do-	let iter = E.catchError-	    	(E.throwError (Exc.ErrorCall "error"))-	    	(\_ -> EL.require 1)-	-	res <- E.run (E.enumList 1 [] $$ iter)-	$assert (left res)-	-	let Left err = res-	$assert $ equal (Exc.fromException err) (Just (Exc.ErrorCall "require: Unexpected EOF"))--test_CatchError_NotDivergent :: Test-test_CatchError_NotDivergent = assertions "not-divergent" $ do-	let iter = E.catchError-	    	(do-	    		EL.head-	    		E.throwError (Exc.ErrorCall "error"))-	    	(\_ -> EL.require 1)-	-	res <- E.run (E.enumList 1 [] $$ iter)-	$assert (left res)-	-	let Left err = res-	$assert $ equal (Exc.fromException err) (Just (Exc.ErrorCall "require: Unexpected EOF"))--test_CatchError_Interleaved :: Test-test_CatchError_Interleaved = within 1000 $ assertions "interleaved" $ do-	let enumMVar mvar = EL.repeatM (liftIO (takeMVar mvar))-	let iter mvar = do-	    	liftIO (putMVar mvar ())-	    	EL.head-	    	return True-	let onError err = return False-	-	mvar <- liftIO newEmptyMVar-	E.run_ (enumMVar mvar $$ E.catchError (iter mvar) onError)--test_Zip :: Test-test_Zip = assertions "zip" $ do-	let iterTup = do-		Just x <- EL.head-		Just y <- EL.head-		return (x, y)-	let iterTupFlip = do-		Just x <- EL.head-		Just y <- EL.head-		return (y, x)-	-	let check i1 i2 = E.run_ (E.enumList 4 [1, 2, 3, 4, 5] $$ do-		(x, y) <- EL.zip i1 i2-		extra <- EL.consume-		return (x, y, extra))-	-	-- Both sides have same behavior-	(tup, tup2, extra) <- check iterTup iterTupFlip-	$expect (equal tup (1, 2))-	$expect (equal tup2 (2, 1))-	$expect (equal extra [3, 4, 5])-	-	-- First side has more extra data-	(took, tup, extra) <- check (EL.take 1) iterTup-	$expect (equal took [1])-	$expect (equal tup (1, 2))-	$expect (equal extra [3, 4, 5])-	-	-- Second side has more extra data-	(tup, took, extra) <- check iterTup (EL.take 1)-	$expect (equal tup (1, 2))-	$expect (equal took [1])-	$expect (equal extra [3, 4, 5])--test_ZipBytes :: Test-test_ZipBytes = assertions "zip-bytes" $ do-	let iterTup = do-		Just x <- EB.head-		Just y <- EB.head-		return (x, y)-	let iterTupFlip = do-		Just x <- EB.head-		Just y <- EB.head-		return (y, x)-	-	let check i1 i2 = E.run_ (E.enumList 2 ["abc", "def", "ghi"] $$ do-		(x, y) <- EB.zip i1 i2-		extra <- EL.consume-		return (x, y, extra))-	-	-- Both sides have same behavior-	(tup, tup2, extra) <- check iterTup iterTupFlip-	$expect (equal tup (0x61, 0x62))-	$expect (equal tup2 (0x62, 0x61))-	$expect (equal extra ["c", "def", "ghi"])-	-	-- First side has more extra data-	(took, tup, extra) <- check (EB.take 1) iterTup-	$expect (equal took "a")-	$expect (equal tup (0x61, 0x62))-	$expect (equal extra ["c", "def", "ghi"])-	-	-- Second side has more extra data-	(tup, took, extra) <- check iterTup (EB.take 1)-	$expect (equal tup (0x61, 0x62))-	$expect (equal took "a")-	$expect (equal extra ["c", "def", "ghi"])--test_ZipText :: Test-test_ZipText = assertions "zip-text" $ do-	let iterTup = do-		Just x <- ET.head-		Just y <- ET.head-		return (x, y)-	let iterTupFlip = do-		Just x <- ET.head-		Just y <- ET.head-		return (y, x)-	-	let check i1 i2 = E.run_ (E.enumList 2 ["abc", "def", "ghi"] $$ do-		(x, y) <- ET.zip i1 i2-		extra <- EL.consume-		return (x, y, extra))-	-	-- Both sides have same behavior-	(tup, tup2, extra) <- check iterTup iterTupFlip-	$expect (equal tup ('a', 'b'))-	$expect (equal tup2 ('b', 'a'))-	$expect (equal extra ["c", "def", "ghi"])-	-	-- First side has more extra data-	(took, tup, extra) <- check (ET.take 1) iterTup-	$expect (equal took "a")-	$expect (equal tup ('a', 'b'))-	$expect (equal extra ["c", "def", "ghi"])-	-	-- Second side has more extra data-	(tup, took, extra) <- check iterTup (ET.take 1)-	$expect (equal tup ('a', 'b'))-	$expect (equal took "a")-	$expect (equal extra ["c", "def", "ghi"])---- misc--genASCII :: IsString a => Gen a-genASCII = fmap fromString string where-	string = sized $ \n -> do-		k <- choose (0,n)-		sequence [ char | _ <- [1..k] ]-	-	char = chr `fmap` choose (0,0x7F)--genISO8859 :: IsString a => Gen a-genISO8859 = fmap fromString string where-	string = sized $ \n -> do-		k <- choose (0,n)-		sequence [ char | _ <- [1..k] ]-	-	char = chr `fmap` choose (0,0xFF)--genUnicode :: IsString a => Gen a-genUnicode = fmap fromString string where-	string = sized $ \n -> do-		k <- choose (0,n)-		sequence [ char | _ <- [1..k] ]-	-	excluding :: [a -> Bool] -> Gen a -> Gen a-	excluding bad gen = loop where-		loop = do-			x <- gen-			if or (map ($ x) bad)-				then loop-				else return x-	-	reserved = [lowSurrogate, highSurrogate, noncharacter]-	lowSurrogate c = c >= 0xDC00 && c <= 0xDFFF-	highSurrogate c = c >= 0xD800 && c <= 0xDBFF-	noncharacter c = masked == 0xFFFE || masked == 0xFFFF where-		masked = c .&. 0xFFFF-	-	ascii = choose (0,0x7F)-	plane0 = choose (0xF0, 0xFFFF)-	plane1 = oneof [ choose (0x10000, 0x10FFF)-	               , choose (0x11000, 0x11FFF)-	               , choose (0x12000, 0x12FFF)-	               , choose (0x13000, 0x13FFF)-	               , choose (0x1D000, 0x1DFFF)-	               , choose (0x1F000, 0x1FFFF)-	               ]-	plane2 = oneof [ choose (0x20000, 0x20FFF)-	               , choose (0x21000, 0x21FFF)-	               , choose (0x22000, 0x22FFF)-	               , choose (0x23000, 0x23FFF)-	               , choose (0x24000, 0x24FFF)-	               , choose (0x25000, 0x25FFF)-	               , choose (0x26000, 0x26FFF)-	               , choose (0x27000, 0x27FFF)-	               , choose (0x28000, 0x28FFF)-	               , choose (0x29000, 0x29FFF)-	               , choose (0x2A000, 0x2AFFF)-	               , choose (0x2B000, 0x2BFFF)-	               , choose (0x2F000, 0x2FFFF)-	               ]-	plane14 = choose (0xE0000, 0xE0FFF)-	planes = [ascii, plane0, plane1, plane2, plane14]-	-	char = chr `fmap` excluding reserved (oneof planes)--instance Arbitrary a => Arbitrary (E.Stream a) where-	arbitrary = frequency-		[ (10, return E.EOF)-		, (90, fmap E.Chunks arbitrary)-		]--instance Arbitrary T.Text where-	arbitrary = genUnicode--instance Arbitrary B.ByteString where-	arbitrary = genUnicode--instance Eq Exc.ErrorCall where-	(Exc.ErrorCall s1) == (Exc.ErrorCall s2) = s1 == s2---- | Require a test to complete within /n/ milliseconds.-within :: Int -> Test -> Test-within time (Test name io) = Test name $ \opts -> do-	res <- timeout (time * 1000) (io opts)-	case res of-		Just res' -> return res'-		Nothing -> return (TestAborted [] (T.pack ("Test timed out after " ++ show time ++ " milliseconds")))
tests/enumerator-tests.cabal view
@@ -3,16 +3,38 @@ build-type: Simple cabal-version: >= 1.6 +flag coverage+  default: False+  manual: True++flag test-io-functions+  default: True+ executable enumerator_tests-  main-is: Tests.hs-  ghc-options: -Wall -O2+  main-is: EnumeratorTests.hs+  ghc-options: -Wall+  hs-source-dirs: ../lib,. +  if flag(coverage)+    ghc-options: -fhpc++  if flag(test-io-functions)+    build-depends:+        base >= 4.2 && < 5.0+      , knob >= 0.1 && < 0.2++    if !os(windows)+      build-depends:+            silently+  else+    build-depends:+        base >= 4.0 && < 5.0+   build-depends:-      base > 3 && < 5-    , bytestring-    , chell >= 0.1 && < 0.2+      bytestring+    , chell >= 0.2 && < 0.3     , chell-quickcheck >= 0.1 && < 0.2-    , enumerator+    , containers     , QuickCheck     , split     , text