@@ -1,10 +1,10 @@
11-- | General quicktest properties for the text library
22--
3−{-# LANGUAGE BangPatterns, FlexibleInstances, OverloadedStrings,
4− ScopedTypeVariables, TypeSynonymInstances, CPP #-}
3+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, OverloadedStrings,
4+ ScopedTypeVariables, TypeSynonymInstances #-}
55{-# OPTIONS_GHC -fno-enable-rewrite-rules #-}
66{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
7−module Data.Text.Tests.Properties
7+module Tests.Properties
88 (
99 tests
1010 ) where
@@ -16,6 +16,7 @@ import Text.Show.Functions ()
1616import Control.Arrow ((***), second)
1717import Control.Exception (catch)
1818import Data.Char (chr, isDigit, isHexDigit, isLower, isSpace, isUpper, ord)
19+import Data.Int (Int8, Int16, Int32, Int64)
1920import Data.Monoid (Monoid(..))
2021import Data.String (fromString)
2122import Data.Text.Encoding.Error
@@ -24,13 +25,13 @@ import Data.Text.Fusion.Size
2425import Data.Text.Lazy.Read as TL
2526import Data.Text.Read as T
2627import Data.Text.Search (indices)
27−import Data.Word (Word8, Word16, Word32)
28+import Data.Word (Word, Word8, Word16, Word32, Word64)
2829import Numeric (showHex)
29−import Prelude hiding (catch, replicate)
3030import Test.Framework (Test, testGroup)
3131import Test.Framework.Providers.QuickCheck2 (testProperty)
3232import qualified Data.Bits as Bits (shiftL, shiftR)
3333import qualified Data.ByteString as B
34+import qualified Data.ByteString.Lazy as BL
3435import qualified Data.List as L
3536import qualified Data.Text as T
3637import qualified Data.Text.Encoding as E
@@ -39,6 +40,8 @@ import qualified Data.Text.Fusion.Common as S
3940import qualified Data.Text.IO as T
4041import qualified Data.Text.Lazy as TL
4142import qualified Data.Text.Lazy.Builder as TB
43+import qualified Data.Text.Lazy.Builder.Int as TB
44+import qualified Data.Text.Lazy.Builder.RealFloat as TB
4245import qualified Data.Text.Lazy.Encoding as EL
4346import qualified Data.Text.Lazy.Fusion as SL
4447import qualified Data.Text.Lazy.IO as TL
@@ -46,9 +49,15 @@ import qualified Data.Text.Lazy.Search as S (indices)
4649import qualified Data.Text.UnsafeShift as U
4750import qualified System.IO as IO
4851
49−import Data.Text.Tests.QuickCheckUtils
50−import Data.Text.Tests.Utils
51−import qualified Data.Text.Tests.SlowFunctions as Slow
52+import Tests.QuickCheckUtils
53+import Tests.Utils
54+import qualified Tests.SlowFunctions as Slow
55+
56+#if MIN_VERSION_base(4,6,0)
57+import Prelude hiding (replicate)
58+#else
59+import Prelude hiding (catch, replicate)
60+#endif
5261
5362t_pack_unpack = (T.unpack . T.pack) `eq` id
5463tl_pack_unpack = (TL.unpack . TL.pack) `eq` id
@@ -62,10 +71,20 @@ tl_unstreamChunks x = f 11 x == f 1000 x
6271tl_chunk_unchunk = (TL.fromChunks . TL.toChunks) `eq` id
6372tl_from_to_strict = (TL.fromStrict . TL.toStrict) `eq` id
6473
74+-- Note: this silently truncates code-points > 255 to 8-bit due to 'B.pack'
75+encodeL1 :: T.Text -> B.ByteString
76+encodeL1 = B.pack . map (fromIntegral . fromEnum) . T.unpack
77+encodeLazyL1 :: TL.Text -> BL.ByteString
78+encodeLazyL1 = BL.fromChunks . map encodeL1 . TL.toChunks
79+
6580t_ascii t = E.decodeASCII (E.encodeUtf8 a) == a
6681 where a = T.map (\c -> chr (ord c `mod` 128)) t
6782tl_ascii t = EL.decodeASCII (EL.encodeUtf8 a) == a
6883 where a = TL.map (\c -> chr (ord c `mod` 128)) t
84+t_latin1 t = E.decodeLatin1 (encodeL1 a) == a
85+ where a = T.map (\c -> chr (ord c `mod` 256)) t
86+tl_latin1 t = EL.decodeLatin1 (encodeLazyL1 a) == a
87+ where a = TL.map (\c -> chr (ord c `mod` 256)) t
6988t_utf8 = forAll genUnicode $ (E.decodeUtf8 . E.encodeUtf8) `eq` id
7089t_utf8' = forAll genUnicode $ (E.decodeUtf8' . E.encodeUtf8) `eq` (id . Right)
7190tl_utf8 = forAll genUnicode $ (EL.decodeUtf8 . EL.encodeUtf8) `eq` id
@@ -79,6 +98,18 @@ tl_utf32LE = forAll genUnicode $ (EL.decodeUtf32LE . EL.encodeUtf32LE) `eq` id
7998t_utf32BE = forAll genUnicode $ (E.decodeUtf32BE . E.encodeUtf32BE) `eq` id
8099tl_utf32BE = forAll genUnicode $ (EL.decodeUtf32BE . EL.encodeUtf32BE) `eq` id
81100
101+t_utf8_incr = do
102+ Positive n <- arbitrary
103+ forAll genUnicode $ recode n `eq` id
104+ where recode n = T.concat . feedChunksOf n E.streamDecodeUtf8 . E.encodeUtf8
105+ feedChunksOf :: Int -> (B.ByteString -> E.Decoding) -> B.ByteString
106+ -> [T.Text]
107+ feedChunksOf n f bs
108+ | B.null bs = []
109+ | otherwise = let (a,b) = B.splitAt n bs
110+ E.Some t _ f' = f a
111+ in t : feedChunksOf n f' b
112+
82113-- This is a poor attempt to ensure that the error handling paths on
83114-- decode are exercised in some way. Proper testing would be rather
84115-- more involved.
@@ -610,17 +641,55 @@ shiftR_Word32 = shiftR :: Word32 -> Property
610641
611642-- Builder.
612643
613−t_builderSingleton = id `eqP`
614− (unpackS . TB.toLazyText . mconcat . map TB.singleton)
615−t_builderFromText = L.concat `eq` (unpackS . TB.toLazyText . mconcat .
644+tb_singleton = id `eqP`
645+ (unpackS . TB.toLazyText . mconcat . map TB.singleton)
646+tb_fromText = L.concat `eq` (unpackS . TB.toLazyText . mconcat .
616647 map (TB.fromText . packS))
617−t_builderAssociative s1 s2 s3 =
648+tb_associative s1 s2 s3 =
618649 TB.toLazyText (b1 `mappend` (b2 `mappend` b3)) ==
619650 TB.toLazyText ((b1 `mappend` b2) `mappend` b3)
620651 where b1 = TB.fromText (packS s1)
621652 b2 = TB.fromText (packS s2)
622653 b3 = TB.fromText (packS s3)
623654
655+-- Numeric builder stuff.
656+
657+tb_decimal :: (Integral a, Show a) => a -> Bool
658+tb_decimal = (TB.toLazyText . TB.decimal) `eq` (TL.pack . show)
659+
660+tb_decimal_integer (a::Integer) = tb_decimal a
661+tb_decimal_int (a::Int) = tb_decimal a
662+tb_decimal_int8 (a::Int8) = tb_decimal a
663+tb_decimal_int16 (a::Int16) = tb_decimal a
664+tb_decimal_int32 (a::Int32) = tb_decimal a
665+tb_decimal_int64 (a::Int64) = tb_decimal a
666+tb_decimal_word (a::Word) = tb_decimal a
667+tb_decimal_word8 (a::Word8) = tb_decimal a
668+tb_decimal_word16 (a::Word16) = tb_decimal a
669+tb_decimal_word32 (a::Word32) = tb_decimal a
670+tb_decimal_word64 (a::Word64) = tb_decimal a
671+
672+tb_hex :: (Integral a, Show a) => a -> Bool
673+tb_hex = (TB.toLazyText . TB.hexadecimal) `eq` (TL.pack . flip showHex "")
674+
675+tb_hexadecimal_integer (a::Integer) = tb_hex a
676+tb_hexadecimal_int (a::Int) = tb_hex a
677+tb_hexadecimal_int8 (a::Int8) = tb_hex a
678+tb_hexadecimal_int16 (a::Int16) = tb_hex a
679+tb_hexadecimal_int32 (a::Int32) = tb_hex a
680+tb_hexadecimal_int64 (a::Int64) = tb_hex a
681+tb_hexadecimal_word (a::Word) = tb_hex a
682+tb_hexadecimal_word8 (a::Word8) = tb_hex a
683+tb_hexadecimal_word16 (a::Word16) = tb_hex a
684+tb_hexadecimal_word32 (a::Word32) = tb_hex a
685+tb_hexadecimal_word64 (a::Word64) = tb_hex a
686+
687+tb_realfloat :: (RealFloat a, Show a) => a -> Bool
688+tb_realfloat = (TB.toLazyText . TB.realFloat) `eq` (TL.pack . show)
689+
690+tb_realfloat_float (a::Float) = tb_realfloat a
691+tb_realfloat_double (a::Double) = tb_realfloat a
692+
624693-- Reading.
625694
626695t_decimal (n::Int) s =
@@ -681,6 +750,8 @@ t_take_drop_16 m t = T.append (takeWord16 n t) (dropWord16 n t) == t
681750 where n = small m
682751t_use_from t = monadicIO $ assert . (==t) =<< run (useAsPtr t fromPtr)
683752
753+t_copy t = T.copy t == t
754+
684755-- Regression tests.
685756s_filter_eq s = S.filter p t == S.streamList (filter p s)
686757 where p = (/= S.last t)
@@ -691,7 +762,7 @@ s_filter_eq s = S.filter p t == S.streamList (filter p s)
691762-- themselves.
692763shorten :: Int -> S.Stream a -> S.Stream a
693764shorten n t@(S.Stream arr off len)
694− | n > 0 = S.Stream arr off (smaller (exactSize n) len)
765+ | n > 0 = S.Stream arr off (smaller (exactSize n) len)
695766 | otherwise = t
696767
697768tests :: Test
@@ -713,8 +784,11 @@ tests =
713784 testGroup "transcoding" [
714785 testProperty "t_ascii" t_ascii,
715786 testProperty "tl_ascii" tl_ascii,
787+ testProperty "t_latin1" t_latin1,
788+ testProperty "tl_latin1" tl_latin1,
716789 testProperty "t_utf8" t_utf8,
717790 testProperty "t_utf8'" t_utf8',
791+ testProperty "t_utf8_incr" t_utf8_incr,
718792 testProperty "tl_utf8" tl_utf8,
719793 testProperty "tl_utf8'" tl_utf8',
720794 testProperty "t_utf16LE" t_utf16LE,
@@ -1080,9 +1154,39 @@ tests =
10801154 ],
10811155
10821156 testGroup "builder" [
1083− testProperty "t_builderSingleton" t_builderSingleton,
1084− testProperty "t_builderFromText" t_builderFromText,
1085− testProperty "t_builderAssociative" t_builderAssociative
1157+ testProperty "tb_associative" tb_associative,
1158+ testGroup "decimal" [
1159+ testProperty "tb_decimal_int" tb_decimal_int,
1160+ testProperty "tb_decimal_int8" tb_decimal_int8,
1161+ testProperty "tb_decimal_int16" tb_decimal_int16,
1162+ testProperty "tb_decimal_int32" tb_decimal_int32,
1163+ testProperty "tb_decimal_int64" tb_decimal_int64,
1164+ testProperty "tb_decimal_integer" tb_decimal_integer,
1165+ testProperty "tb_decimal_word" tb_decimal_word,
1166+ testProperty "tb_decimal_word8" tb_decimal_word8,
1167+ testProperty "tb_decimal_word16" tb_decimal_word16,
1168+ testProperty "tb_decimal_word32" tb_decimal_word32,
1169+ testProperty "tb_decimal_word64" tb_decimal_word64
1170+ ],
1171+ testGroup "hexadecimal" [
1172+ testProperty "tb_hexadecimal_int" tb_hexadecimal_int,
1173+ testProperty "tb_hexadecimal_int8" tb_hexadecimal_int8,
1174+ testProperty "tb_hexadecimal_int16" tb_hexadecimal_int16,
1175+ testProperty "tb_hexadecimal_int32" tb_hexadecimal_int32,
1176+ testProperty "tb_hexadecimal_int64" tb_hexadecimal_int64,
1177+ testProperty "tb_hexadecimal_integer" tb_hexadecimal_integer,
1178+ testProperty "tb_hexadecimal_word" tb_hexadecimal_word,
1179+ testProperty "tb_hexadecimal_word8" tb_hexadecimal_word8,
1180+ testProperty "tb_hexadecimal_word16" tb_hexadecimal_word16,
1181+ testProperty "tb_hexadecimal_word32" tb_hexadecimal_word32,
1182+ testProperty "tb_hexadecimal_word64" tb_hexadecimal_word64
1183+ ],
1184+ testGroup "realfloat" [
1185+ testProperty "tb_realfloat_double" tb_realfloat_double,
1186+ testProperty "tb_realfloat_float" tb_realfloat_float
1187+ ],
1188+ testProperty "tb_fromText" tb_fromText,
1189+ testProperty "tb_singleton" tb_singleton
10861190 ],
10871191
10881192 testGroup "read" [
@@ -1113,6 +1217,7 @@ tests =
11131217 testProperty "t_dropWord16" t_dropWord16,
11141218 testProperty "t_takeWord16" t_takeWord16,
11151219 testProperty "t_take_drop_16" t_take_drop_16,
1116− testProperty "t_use_from" t_use_from
1220+ testProperty "t_use_from" t_use_from,
1221+ testProperty "t_copy" t_copy
11171222 ]
11181223 ]