@@ -14,7 +14,7 @@ import Data.Word
1414import qualified Data.Text as T
1515import Data.Text (pack,unpack)
1616import qualified Data.Text.Fusion as S
17−import Data.Text.Fusion (unstream,stream)
17+import Data.Text.Fusion (stream, unstream)
1818import qualified Data.List as L
1919
2020
@@ -22,16 +22,17 @@ import QuickCheckUtils
2222
2323prop_pack_unpack s = (unpack . pack) s == s
2424prop_stream_unstream t = (unstream . stream) t == t
25+prop_reverse_stream t = (S.reverse . S.reverseStream) t == t
2526prop_singleton c = [c] == (unpack . T.singleton) c
2627
2728-- Do two functions give the same answer?
2829eq :: (Eq a) => (t -> a) -> (t -> a) -> t -> Bool
2930eq a b s = a s == b s
3031-- What about with the RHS packed?
31−eqP :: (Eq a) => (String -> a) -> (T.Text -> a) -> String -> Word8 -> Bool
32−eqP a b s w = a s == b t &&
33− a sa == b ta &&
34− a sb == b tb
32+eqP :: (Eq a, Show a) => (String -> a) -> (T.Text -> a) -> String -> Word8 -> Bool
33+eqP a b s w = eq "orig" (a s) (b t) &&
34+ eq "head" (a sa) (b ta) &&
35+ eq "tail" (a sb) (b tb)
3536 where t = pack s
3637 (sa,sb) = splitAt m s
3738 (ta,tb) = T.splitAt m t
@@ -39,6 +40,8 @@ eqP a b s w = a s == b t &&
3940 m | l == 0 = n
4041 | otherwise = n `mod` l
4142 n = fromIntegral w
43+ eq s a b | a == b = True
44+ | otherwise = trace (s ++ ": " ++ show a ++ " /= " ++ show b) False
4245-- Or with the string non-empty, and the RHS packed?
4346eqEP :: (Eq a) =>
4447 (String -> a) -> (T.Text -> a) -> NotEmpty String -> Word8 -> Bool
@@ -76,6 +79,7 @@ prop_intercalate c = L.intercalate c `eq` (unpack . T.intercalate (pack c) . m
7679prop_intersperse c = L.intersperse c `eqP` (unpack . T.intersperse c)
7780prop_transpose = L.transpose `eq` (map unpack . T.transpose . map pack)
7881prop_reverse = L.reverse `eqP` (unpack . T.reverse)
82+prop_reverse_short n = L.reverse `eqP` (unpack . S.reverse . shorten n . stream)
7983
8084prop_foldl f z = L.foldl f z `eqP` (T.foldl f z)
8185 where types = f :: Char -> Char -> Char
@@ -96,6 +100,7 @@ prop_minimum = L.minimum `eqEP` T.minimum
96100
97101prop_scanl f z = L.scanl f z `eqP` (unpack . T.scanl f z)
98102prop_scanl1 f = L.scanl1 f `eqP` (unpack . T.scanl1 f)
103+prop_scanr f z = L.scanr f z `eqP` (unpack . T.scanr f z)
99104
100105prop_mapAccumL f z = (snd . L.mapAccumL f z)`eqP` (unpack . T.mapAccumL f z)
101106 where types = f :: Int -> Char -> (Int,Char)
@@ -168,6 +173,14 @@ prop_elemIndices c = L.elemIndices c`eqP` T.elemIndices c
168173prop_count c = (L.length . L.elemIndices c) `eqP` T.count c
169174prop_zipWith c s = L.zipWith c s `eqP` (unpack . T.zipWith c (pack s))
170175
176+-- Make a stream appear shorter than it really is, to ensure that
177+-- functions that consume inaccurately sized streams behave
178+-- themselves.
179+shorten :: Int -> S.Stream a -> S.Stream a
180+shorten n t@(S.Stream arr off len)
181+ | n < len && n > 0 = S.Stream arr off n
182+ | otherwise = t
183+
171184main = run tests =<< getArgs
172185
173186run :: [(String, Int -> IO (Bool,Int))] -> [String] -> IO ()
@@ -185,6 +198,7 @@ tests :: [(String, Int -> IO (Bool, Int))]
185198tests = [
186199 ("prop_pack_unpack", mytest prop_pack_unpack),
187200 ("prop_stream_unstream", mytest prop_stream_unstream),
201+ ("prop_reverse_stream", mytest prop_reverse_stream),
188202 ("prop_singleton", mytest prop_singleton),
189203
190204 ("prop_cons", mytest prop_cons),
@@ -207,6 +221,7 @@ tests = [
207221 ("prop_intersperse", mytest prop_intersperse),
208222 ("prop_transpose", mytest prop_transpose),
209223 ("prop_reverse", mytest prop_reverse),
224+ ("prop_reverse_short", mytest prop_reverse_short),
210225
211226 ("prop_foldl", mytest prop_foldl),
212227 ("prop_foldl'", mytest prop_foldl'),
@@ -224,6 +239,7 @@ tests = [
224239
225240 ("prop_scanl", mytest prop_scanl),
226241 ("prop_scanl1", mytest prop_scanl1),
242+ ("prop_scanr", mytest prop_scanr),
227243
228244 ("prop_mapAccumL", mytest prop_mapAccumL),
229245