-- Copyright (C) 2010 John Millikin -- -- See license.txt for details module Main (tests, main) where 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 qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Char8 as B8 import qualified Data.Text as T import qualified Data.Text.Lazy as TL import qualified Data.Text.Encoding as TE import Test.QuickCheck hiding ((.&.)) import Test.QuickCheck.Poly import qualified Test.Framework as F import Test.Framework.Providers.QuickCheck2 (testProperty) import Control.Applicative import Control.Exception import Control.Monad import Data.Bits import Data.Char (chr) import Data.Monoid import Data.Functor.Identity import Data.String tests :: [F.Test] tests = [ test_StreamInstances , test_Primitives , test_Text , test_ListAnalogues , test_Other ] main :: IO () main = F.defaultMain tests -- Stream instances {{{ test_StreamInstances :: F.Test test_StreamInstances = F.testGroup "Stream Instances" [ test_StreamMonoid , test_StreamFunctor , test_StreamApplicative , test_StreamMonad ] test_StreamMonoid :: F.Test test_StreamMonoid = F.testGroup "Monoid Stream" props where props = [ testProperty "law 1" prop_law1 , testProperty "law 2" prop_law2 , testProperty "law 3" prop_law3 , testProperty "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 test_StreamFunctor :: F.Test test_StreamFunctor = F.testGroup "Functor Stream" props where props = [ testProperty "law 1" prop_law1 , testProperty "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 test_StreamApplicative :: F.Test test_StreamApplicative = F.testGroup "Applicative Stream" props where props = [ testProperty "law 1" prop_law1 , testProperty "law 2" prop_law2 , testProperty "law 3" prop_law3 , testProperty "law 4" prop_law4 , testProperty "law 5" prop_law5 ] prop_law1 :: E.Stream A -> Bool prop_law1 v = (pure id <*> v) == v prop_law2 :: Blind (E.Stream (B -> C)) -> Blind (E.Stream (A -> B)) -> E.Stream A -> Bool prop_law2 (Blind u) (Blind v) w = (pure (.) <*> u <*> v <*> w) == (u <*> (v <*> w)) prop_law3 :: Blind (A -> B) -> A -> Bool prop_law3 (Blind f) x = (pure f <*> pure x) == (pure (f x) `asTypeOf` E.Chunks [B 0]) prop_law4 :: Blind (E.Stream (A -> B)) -> A -> Bool prop_law4 (Blind u) y = (u <*> pure y) == (pure ($ y) <*> u) prop_law5 :: Blind (A -> B) -> E.Stream A -> Bool prop_law5 (Blind f) x = (fmap f x) == (pure f <*> x) test_StreamMonad :: F.Test test_StreamMonad = F.testGroup "Monad Stream" props where props = [ testProperty "law 1" prop_law1 , testProperty "law 2" prop_law2 , testProperty "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 :: String -> E.Enumeratee A A Identity (Maybe A) -> F.Test test_Enumeratee name enee = F.testGroup name props where props = [ testProperty "incremental" prop_incremental , testProperty "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 a <- enee $$ E.throwError (ErrorCall "") EL.consume in result == xs -- }}} -- Primitives {{{ test_Primitives :: F.Test test_Primitives = F.testGroup "Primitives" [ test_Map , test_ConcatMap , test_MapM , test_ConcatMapM , test_Filter , test_FilterM ] test_Map :: F.Test test_Map = test_Enumeratee "map" (E.map id) test_ConcatMap :: F.Test test_ConcatMap = test_Enumeratee "concatMap" (E.concatMap (:[])) test_MapM :: F.Test test_MapM = test_Enumeratee "mapM" (E.mapM return) test_ConcatMapM :: F.Test test_ConcatMapM = test_Enumeratee "concatMapM" (E.concatMapM (\x -> return [x])) test_Filter :: F.Test test_Filter = test_Enumeratee "filter" (E.filter (\_ -> True)) test_FilterM :: F.Test test_FilterM = test_Enumeratee "filterM" (E.filterM (\_ -> return True)) -- }}} -- Text encoding / decoding {{{ test_Text :: F.Test test_Text = F.testGroup "Text" [ test_Encoding , test_Decoding ] test_Encoding :: F.Test test_Encoding = F.testGroup "Encoding" [ test_Encode_ASCII , test_Encode_ISO8859 ] test_Encode_ASCII :: F.Test test_Encode_ASCII = F.testGroup "ASCII" props where props = [ testProperty "works" (forAll genASCII prop_works) , testProperty "error" prop_error , testProperty "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) test_Encode_ISO8859 :: F.Test test_Encode_ISO8859 = F.testGroup "ISO-8859-1" props where props = [ testProperty "works" (forAll genISO8859 prop_works) , testProperty "error" prop_error , testProperty "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) test_Decoding :: F.Test test_Decoding = F.testGroup "Decoding" [ test_Decode_ASCII , test_Decode_UTF8 , test_Decode_UTF16_BE , test_Decode_UTF16_LE , test_Decode_UTF32_BE , test_Decode_UTF32_LE ] test_Decode_ASCII :: F.Test test_Decode_ASCII = F.testGroup "ASCII" props where props = [ testProperty "works" (forAll genASCII prop_works) , testProperty "error" prop_error , testProperty "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") test_Decode_UTF8 :: F.Test test_Decode_UTF8 = F.testGroup "UTF-8" props where props = [ testProperty "works" prop_works , testProperty "error" prop_error , testProperty "lazy" prop_lazy , testProperty "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") test_Decode_UTF16_BE :: F.Test test_Decode_UTF16_BE = F.testGroup "UTF-16-BE" props where props = [ testProperty "works" prop_works , testProperty "lazy" prop_lazy , testProperty "error" prop_error , testProperty "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") test_Decode_UTF16_LE :: F.Test test_Decode_UTF16_LE = F.testGroup "UTF-16-LE" props where props = [ testProperty "works" prop_works , testProperty "lazy" prop_lazy , testProperty "error" prop_error , testProperty "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") test_Decode_UTF32_BE :: F.Test test_Decode_UTF32_BE = F.testGroup "UTF-32-BE" props where props = [ testProperty "works" prop_works , testProperty "lazy" prop_lazy , testProperty "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]] test_Decode_UTF32_LE :: F.Test test_Decode_UTF32_LE = F.testGroup "UTF-32-LE" props where props = [ testProperty "works" prop_works , testProperty "lazy" prop_lazy , testProperty "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 {{{ test_ListAnalogues :: F.Test test_ListAnalogues = F.testGroup "list analogues" [ test_ListConsume , test_ListHead , test_ListDrop , test_ListTake -- , test_ListPeek , test_ListRequire , test_ListIsolate , test_BinaryConsume , test_BinaryHead , test_BinaryDrop , test_BinaryTake , test_BinaryRequire , test_BinaryIsolate , test_TextConsume , test_TextHead , test_TextDrop , test_TextTake , test_TextRequire , test_TextIsolate ] test_ListConsume :: F.Test test_ListConsume = testProperty "List.consume" prop where prop :: [A] -> Bool prop xs = result == xs where result = runIdentity (E.run_ iter) iter = E.enumList 1 xs $$ EL.consume test_ListHead :: F.Test test_ListHead = testProperty "List.head" prop where prop :: [A] -> Bool prop xs = result == expected where result = runIdentity (E.run_ iter) expected = case xs of [] -> (Nothing, []) (x:xs') -> (Just x, xs') iter = E.enumList 1 xs $$ do x <- EL.head extra <- EL.consume return (x, extra) test_ListDrop :: F.Test test_ListDrop = testProperty "List.drop" prop where prop :: Positive Integer -> [A] -> Bool prop (Positive n) xs = result == expected where result = runIdentity (E.run_ iter) expected = drop (fromInteger n) xs iter = E.enumList 1 xs $$ do EL.drop n EL.consume test_ListTake :: F.Test test_ListTake = testProperty "List.take" prop where prop :: Positive Integer -> [A] -> Bool prop (Positive n) xs = result == expected where result = runIdentity (E.run_ iter) expected = splitAt (fromInteger n) xs iter = E.enumList 1 xs $$ do xs <- EL.take n extra <- EL.consume return (xs, extra) {- test_ListPeek :: F.Test test_ListPeek = testProperty "List.peek" prop where prop :: Positive Integer -> [A] -> Bool prop (Positive n) xs = result == expected where result = runIdentity (E.run_ iter) expected = (take (fromInteger n) xs, xs) iter = E.enumList 1 xs $$ do xs <- EL.peek n extra <- EL.consume return (xs, extra) -} test_ListRequire :: F.Test test_ListRequire = testProperty "List.require" prop where prop :: Positive Integer -> [A] -> Bool prop (Positive n) xs = result == expected where result = case runIdentity (E.run iter) of Left exc -> Left (show exc) Right x -> Right x expected = if n > toInteger (length xs) then Left "require: Unexpected EOF" else Right xs iter = E.enumList 1 xs $$ do EL.require n EL.consume test_ListIsolate :: F.Test test_ListIsolate = testProperty "List.isolate" prop where prop :: Positive Integer -> [A] -> Bool prop (Positive n) xs = result == expected where result = runIdentity (E.run_ iter) expected = case xs of [] -> (Nothing, []) (x:[]) -> (Just x, []) (x:_:xs') -> (Just x, xs') iter = E.enumList 1 xs $$ do x <- E.joinI (EL.isolate 2 $$ EL.head) extra <- EL.consume return (x, extra) test_BinaryConsume :: F.Test test_BinaryConsume = testProperty "Binary.consume" prop where prop ts = result == BL.fromChunks ts where result = runIdentity (E.run_ iter) iter = E.enumList 1 ts $$ EB.consume test_BinaryHead :: F.Test test_BinaryHead = testProperty "Binary.head" prop where prop ts = result == expected where result = runIdentity (E.run_ iter) expected = case BL.uncons (BL.fromChunks ts) of Nothing -> (Nothing, BL.empty) Just (x, extra) -> (Just x, extra) iter = E.enumList 1 ts $$ do x <- EB.head extra <- EB.consume return (x, extra) test_BinaryDrop :: F.Test test_BinaryDrop = testProperty "Binary.drop" prop where prop :: Positive Integer -> [B.ByteString] -> Bool prop (Positive n) ts = result == expected where result = runIdentity (E.run_ iter) expected = BL.drop (fromInteger n) (BL.fromChunks ts) iter = E.enumList 1 ts $$ do EB.drop n EB.consume test_BinaryTake :: F.Test test_BinaryTake = testProperty "Binary.take" prop where prop :: Positive Integer -> [B.ByteString] -> Bool prop (Positive n) ts = result == expected where result = runIdentity (E.run_ iter) expected = BL.splitAt (fromInteger n) (BL.fromChunks ts) iter = E.enumList 1 ts $$ do xs <- EB.take n extra <- EB.consume return (xs, extra) test_BinaryRequire :: F.Test test_BinaryRequire = testProperty "Binary.require" prop where prop :: Positive Integer -> [B.ByteString] -> Bool prop (Positive n) ts = result == expected where result = case runIdentity (E.run iter) of Left exc -> Left (show exc) Right x -> Right x lazy = BL.fromChunks ts expected = if n > toInteger (BL.length lazy) then Left "require: Unexpected EOF" else Right lazy iter = E.enumList 1 ts $$ do EB.require n EB.consume test_BinaryIsolate :: F.Test test_BinaryIsolate = testProperty "Binary.isolate" prop where prop :: Positive Integer -> [B.ByteString] -> Bool prop (Positive n) ts = result == expected where result = runIdentity (E.run_ iter) expected = case BL.unpack (BL.fromChunks ts) of [] -> (Nothing, BL.empty) (x:[]) -> (Just x, BL.empty) (x:_:xs') -> (Just x, BL.pack xs') iter = E.enumList 1 ts $$ do x <- E.joinI (EB.isolate 2 $$ EB.head) extra <- EB.consume return (x, extra) test_TextConsume :: F.Test test_TextConsume = testProperty "Text.consume" prop where prop ts = result == TL.fromChunks ts where result = runIdentity (E.run_ iter) iter = E.enumList 1 ts $$ ET.consume test_TextHead :: F.Test test_TextHead = testProperty "Text.head" prop where prop ts = result == expected where result = runIdentity (E.run_ iter) expected = case TL.uncons (TL.fromChunks ts) of Nothing -> (Nothing, TL.empty) Just (x, extra) -> (Just x, extra) iter = E.enumList 1 ts $$ do x <- ET.head extra <- ET.consume return (x, extra) test_TextDrop :: F.Test test_TextDrop = testProperty "Text.drop" prop where prop :: Positive Integer -> [T.Text] -> Bool prop (Positive n) ts = result == expected where result = runIdentity (E.run_ iter) expected = TL.drop (fromInteger n) (TL.fromChunks ts) iter = E.enumList 1 ts $$ do ET.drop n ET.consume test_TextTake :: F.Test test_TextTake = testProperty "Text.take" prop where prop :: Positive Integer -> [T.Text] -> Bool prop (Positive n) ts = result == expected where result = runIdentity (E.run_ iter) expected = TL.splitAt (fromInteger n) (TL.fromChunks ts) iter = E.enumList 1 ts $$ do xs <- ET.take n extra <- ET.consume return (xs, extra) test_TextRequire :: F.Test test_TextRequire = testProperty "Text.require" prop where prop :: Positive Integer -> [T.Text] -> Bool prop (Positive n) ts = result == expected where result = case runIdentity (E.run iter) of Left exc -> Left (show exc) Right x -> Right x lazy = TL.fromChunks ts expected = if n > toInteger (TL.length lazy) then Left "require: Unexpected EOF" else Right lazy iter = E.enumList 1 ts $$ do ET.require n ET.consume test_TextIsolate :: F.Test test_TextIsolate = testProperty "Text.isolate" prop where prop :: Positive Integer -> [T.Text] -> Bool prop (Positive n) ts = result == expected where result = runIdentity (E.run_ iter) expected = case TL.unpack (TL.fromChunks ts) of [] -> (Nothing, TL.empty) (x:[]) -> (Just x, TL.empty) (x:_:xs') -> (Just x, TL.pack xs') iter = E.enumList 1 ts $$ do x <- E.joinI (ET.isolate 2 $$ ET.head) extra <- ET.consume return (x, extra) -- }}} -- Specific functions test_Other :: F.Test test_Other = F.testGroup "Other" [ test_Sequence , test_joinE ] test_Sequence :: F.Test test_Sequence = testProperty "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 :: F.Test test_joinE = testProperty "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) (E.map (* 10))) $$ EL.consume -- 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