Blame test/Properties.hs

Packit 2632c6
{-# LANGUAGE FlexibleInstances  #-}
Packit 2632c6
{-# LANGUAGE StandaloneDeriving #-}
Packit 2632c6
module Main where
Packit 2632c6
Packit 2632c6
import           Data.List.Split.Internals
Packit 2632c6
import           Test.QuickCheck
Packit 2632c6
import           Test.QuickCheck.Function
Packit 2632c6
Packit 2632c6
import           Control.Monad
Packit 2632c6
import           System.Environment
Packit 2632c6
import           Text.Printf
Packit 2632c6
Packit 2632c6
import           Data.Char
Packit 2632c6
import           Data.Functor
Packit 2632c6
import           Data.List                 (genericTake, group, intercalate,
Packit 2632c6
                                            isInfixOf, isPrefixOf, isSuffixOf,
Packit 2632c6
                                            tails)
Packit 2632c6
import           Data.Maybe                (isJust)
Packit 2632c6
Packit 2632c6
newtype Elt = Elt { unElt :: Char }
Packit 2632c6
  deriving (Eq)
Packit 2632c6
Packit 2632c6
instance Show Elt where
Packit 2632c6
  show (Elt c) = show c
Packit 2632c6
Packit 2632c6
instance Arbitrary Elt where
Packit 2632c6
  arbitrary = elements (map Elt "abcde")
Packit 2632c6
Packit 2632c6
instance CoArbitrary Elt where
Packit 2632c6
  coarbitrary = coarbitrary . ord . unElt
Packit 2632c6
Packit 2632c6
instance Function Elt where
Packit 2632c6
  function = functionMap unElt Elt
Packit 2632c6
Packit 2632c6
deriving instance Show (Splitter Elt)
Packit 2632c6
Packit 2632c6
instance Show (Delimiter Elt) where
Packit 2632c6
  show (Delimiter ps) = show (map function ps)
Packit 2632c6
Packit 2632c6
instance (Arbitrary a, CoArbitrary a, Function a) => Arbitrary (Delimiter a) where
Packit 2632c6
  arbitrary = (Delimiter . map apply) <$> arbitrary
Packit 2632c6
Packit 2632c6
instance Arbitrary a => Arbitrary (Chunk a) where
Packit 2632c6
  arbitrary = oneof [ liftM Text (listOf arbitrary)
Packit 2632c6
                    , liftM Delim (listOf arbitrary)
Packit 2632c6
                    ]
Packit 2632c6
Packit 2632c6
instance Arbitrary DelimPolicy where
Packit 2632c6
  arbitrary = elements [Drop, Keep, KeepLeft, KeepRight]
Packit 2632c6
Packit 2632c6
instance Arbitrary CondensePolicy where
Packit 2632c6
  arbitrary = elements [Condense, KeepBlankFields]
Packit 2632c6
Packit 2632c6
instance Arbitrary EndPolicy where
Packit 2632c6
  arbitrary = elements [DropBlank, KeepBlank]
Packit 2632c6
Packit 2632c6
instance (Arbitrary a, CoArbitrary a, Function a) => Arbitrary (Splitter a) where
Packit 2632c6
  arbitrary = liftM5 Splitter arbitrary arbitrary arbitrary arbitrary arbitrary
Packit 2632c6
Packit 2632c6
type Delim a = [Fun a Bool]
Packit 2632c6
Packit 2632c6
unDelim :: Delim a -> Delimiter a
Packit 2632c6
unDelim = Delimiter . map apply
Packit 2632c6
Packit 2632c6
main :: IO ()
Packit 2632c6
main = do
Packit 2632c6
    results <- mapM (\(s,t) -> printf "%-40s" s >> t) tests
Packit 2632c6
    when (not . all isSuccess $ results) $ fail "Not all tests passed!"
Packit 2632c6
 where
Packit 2632c6
    isSuccess (Success{}) = True
Packit 2632c6
    isSuccess _ = False
Packit 2632c6
    qc x = quickCheckWithResult (stdArgs { maxSuccess = 200 }) x
Packit 2632c6
    tests = [ ("default/id",                    qc prop_default_id)
Packit 2632c6
            , ("match/decompose",               qc prop_match_decompose)
Packit 2632c6
            , ("match/yields delim",            qc prop_match_yields_delim)
Packit 2632c6
            , ("splitInternal/lossless",        qc prop_splitInternal_lossless)
Packit 2632c6
            , ("splitInternal/yields delims",   qc prop_splitInternal_yields_delims)
Packit 2632c6
            , ("splitInternal/text",            qc prop_splitInternal_text_not_delims)
Packit 2632c6
            , ("doCondense/no consec delims",   qc prop_doCondense_no_consec_delims)
Packit 2632c6
            , ("insBlanks/no consec delims",    qc prop_insBlanks_no_consec_delims)
Packit 2632c6
            , ("insBlanks/fl not delims",       qc prop_insBlanks_fl_not_delim)
Packit 2632c6
            , ("mergeL/no delims",              qc prop_mergeL_no_delims)
Packit 2632c6
            , ("mergeR/no delims",              qc prop_mergeR_no_delims)
Packit 2632c6
            , ("oneOf",                         qc prop_oneOf)
Packit 2632c6
            , ("oneOf/not text",                qc prop_oneOf_not_text)
Packit 2632c6
            , ("onSublist",                     qc prop_onSublist)
Packit 2632c6
            , ("onSublist/not text",            qc prop_onSublist_not_text)
Packit 2632c6
            , ("whenElt",                       qc prop_whenElt)
Packit 2632c6
            , ("whenElt/not text",              qc prop_whenElt_not_text)
Packit 2632c6
            , ("process/dropDelims",            qc prop_dropDelims)
Packit 2632c6
            , ("process/keepDelimsL no delims", qc prop_keepDelimsL_no_delims)
Packit 2632c6
            , ("process/keepDelimsR no delims", qc prop_keepDelimsR_no_delims)
Packit 2632c6
            , ("process/keepDelimsL match",     qc prop_keepDelimsL_match)
Packit 2632c6
            , ("process/keepDelimsR match",     qc prop_keepDelimsR_match)
Packit 2632c6
            , ("condense/no consec delims",     qc prop_condense_no_consec_delims)
Packit 2632c6
            , ("condense/all delims",           qc prop_condense_all_delims)
Packit 2632c6
            , ("dropInitBlank",                 qc prop_dropInitBlank)
Packit 2632c6
            , ("dropFinalBlank",                qc prop_dropFinalBlank)
Packit 2632c6
            , ("dropBlanks",                    qc prop_dropBlanks)
Packit 2632c6
            , ("startsWith",                    qc prop_startsWith)
Packit 2632c6
            , ("startsWithOneOf",               qc prop_startsWithOneOf)
Packit 2632c6
            , ("endsWith",                      qc prop_endsWith)
Packit 2632c6
            , ("endsWithOneOf",                 qc prop_endsWithOneOf)
Packit 2632c6
            , ("splitOn/right inv",             qc prop_splitOn_right_inv)
Packit 2632c6
            , ("splitOn/idem",                  qc prop_splitOn_intercalate_idem)
Packit 2632c6
            , ("splitOn/empty delim",           qc prop_splitOn_empty_delim)
Packit 2632c6
            , ("split/empty delim",             qc prop_split_empty_delim_drop)
Packit 2632c6
            , ("chunksOf/lengths",              qc prop_chunksOf_all_n)
Packit 2632c6
            , ("chunksOf/last <= n",            qc prop_chunksOf_last_less_n)
Packit 2632c6
            , ("chunksOf/preserve",             qc prop_chunksOf_preserve)
Packit 2632c6
            , ("splitPlaces/lengths",           qc prop_splitPlaces_lengths)
Packit 2632c6
            , ("splitPlaces/last <= n",         qc prop_splitPlaces_last_less_n)
Packit 2632c6
            , ("splitPlaces/preserve",          qc prop_splitPlaces_preserve)
Packit 2632c6
            , ("splitPlaces/chunksOf",          qc prop_splitPlaces_chunksOf)
Packit 2632c6
            , ("splitPlacesB/length",           qc prop_splitPlacesB_length)
Packit 2632c6
            , ("splitPlacesB/last <= n",        qc prop_splitPlacesB_last_less_n)
Packit 2632c6
            , ("splitPlacesB/preserve",         qc prop_splitPlacesB_preserve)
Packit 2632c6
            , ("lines",                         qc prop_lines)
Packit 2632c6
            , ("wordsBy/words",                 qc prop_wordsBy_words)
Packit 2632c6
            , ("linesBy/lines",                 qc prop_linesBy_lines)
Packit 2632c6
            , ("chop/group",                    qc prop_chop_group)
Packit 2632c6
            , ("chop/words",                    qc prop_chop_words)
Packit 2632c6
            , ("divvy/evenly",                  qc prop_divvy_evenly)
Packit 2632c6
            , ("divvy/discard_remainder",  qc prop_divvy_discard_remainder)
Packit 2632c6
            , ("divvy/outputlists_allsame_length", qc prop_divvy_outputlists_allsame_length)
Packit 2632c6
            , ("divvy/output_are_sublists", qc prop_divvy_output_are_sublists)
Packit 2632c6
            , ("divvy/heads", qc prop_divvy_heads)
Packit 2632c6
            ]
Packit 2632c6
Packit 2632c6
prop_default_id :: [Elt] -> Bool
Packit 2632c6
prop_default_id l = split defaultSplitter l == [l]
Packit 2632c6
Packit 2632c6
prop_match_decompose :: Delim Elt -> [Elt] -> Bool
Packit 2632c6
prop_match_decompose d l = maybe True ((==l) . uncurry (++)) $ matchDelim (unDelim d) l
Packit 2632c6
Packit 2632c6
isDelimMatch :: Delim Elt -> [Elt] -> Bool
Packit 2632c6
isDelimMatch d l = matchDelim (unDelim d) l == Just (l,[])
Packit 2632c6
Packit 2632c6
prop_match_yields_delim :: Delim Elt -> [Elt] -> Bool
Packit 2632c6
prop_match_yields_delim d l =
Packit 2632c6
    case matchDelim (unDelim d) l of
Packit 2632c6
      Nothing -> True
Packit 2632c6
      Just (del,rest) -> isDelimMatch d del
Packit 2632c6
Packit 2632c6
prop_splitInternal_lossless :: Delim Elt -> [Elt] -> Bool
Packit 2632c6
prop_splitInternal_lossless d l = concatMap fromElem (splitInternal (unDelim d) l) == l
Packit 2632c6
Packit 2632c6
prop_splitInternal_yields_delims :: Delim Elt -> [Elt] -> Bool
Packit 2632c6
prop_splitInternal_yields_delims d l =
Packit 2632c6
    all (isDelimMatch d) $ [ del | (Delim del) <- splitInternal d' l ]
Packit 2632c6
  where d' = unDelim d
Packit 2632c6
Packit 2632c6
prop_splitInternal_text_not_delims :: Delim Elt -> [Elt] -> Bool
Packit 2632c6
prop_splitInternal_text_not_delims d l =
Packit 2632c6
    all (not . isDelimMatch d) $ [ ch | (Text ch) <- splitInternal d' l ]
Packit 2632c6
  where d' = unDelim d
Packit 2632c6
Packit 2632c6
noConsecDelims :: SplitList Elt -> Bool
Packit 2632c6
noConsecDelims [] = True
Packit 2632c6
noConsecDelims [x] = True
Packit 2632c6
noConsecDelims (Delim _ : Delim _ : _) = False
Packit 2632c6
noConsecDelims (_ : xs) = noConsecDelims xs
Packit 2632c6
Packit 2632c6
prop_doCondense_no_consec_delims :: SplitList Elt -> Bool
Packit 2632c6
prop_doCondense_no_consec_delims l = noConsecDelims $ doCondense Condense l
Packit 2632c6
Packit 2632c6
prop_insBlanks_no_consec_delims :: SplitList Elt -> Bool
Packit 2632c6
prop_insBlanks_no_consec_delims l = noConsecDelims $ insertBlanks Condense l
Packit 2632c6
Packit 2632c6
prop_insBlanks_fl_not_delim :: SplitList Elt -> Bool
Packit 2632c6
prop_insBlanks_fl_not_delim l =
Packit 2632c6
    case insertBlanks Condense l of
Packit 2632c6
      [] -> True
Packit 2632c6
      xs -> (not . isDelim $ head xs) && (not . isDelim $ last xs)
Packit 2632c6
Packit 2632c6
prop_mergeL_no_delims :: SplitList Elt -> Bool
Packit 2632c6
prop_mergeL_no_delims = all (not . isDelim) . mergeLeft . insertBlanks Condense
Packit 2632c6
Packit 2632c6
prop_mergeR_no_delims :: SplitList Elt -> Bool
Packit 2632c6
prop_mergeR_no_delims = all (not . isDelim) . mergeRight . insertBlanks Condense
Packit 2632c6
Packit 2632c6
getDelims :: Splitter Elt -> [Elt] -> [[Elt]]
Packit 2632c6
getDelims s l = [ d | Delim d <- splitInternal (delimiter s) l ]
Packit 2632c6
Packit 2632c6
getTexts :: Splitter Elt -> [Elt] -> [[Elt]]
Packit 2632c6
getTexts s l = [ c | Text c <- splitInternal (delimiter s) l ]
Packit 2632c6
Packit 2632c6
prop_oneOf :: [Elt] -> [Elt] -> Bool
Packit 2632c6
prop_oneOf elts l = all ((==1) . length) ds && all ((`elem` elts) . head) ds
Packit 2632c6
  where ds = getDelims (oneOf elts) l
Packit 2632c6
Packit 2632c6
prop_oneOf_not_text :: [Elt] -> [Elt] -> Bool
Packit 2632c6
prop_oneOf_not_text elts l = all (not . (`elem` elts)) (concat cs)
Packit 2632c6
  where cs = getTexts (oneOf elts) l
Packit 2632c6
Packit 2632c6
prop_onSublist :: [Elt] -> [Elt] -> Bool
Packit 2632c6
prop_onSublist sub l = all (==sub) $ getDelims (onSublist sub) l
Packit 2632c6
Packit 2632c6
prop_onSublist_not_text :: [Elt] -> [Elt] -> Property
Packit 2632c6
prop_onSublist_not_text sub l =
Packit 2632c6
    (not . null $ sub) ==>
Packit 2632c6
      all (not . isInfixOf sub) $ getTexts (onSublist sub) l
Packit 2632c6
Packit 2632c6
prop_whenElt :: (Fun Elt Bool) -> [Elt] -> Bool
Packit 2632c6
prop_whenElt (Fun _ p) l = all ((==1) . length) ds && all (p . head) ds
Packit 2632c6
  where ds = getDelims (whenElt p) l
Packit 2632c6
Packit 2632c6
prop_whenElt_not_text :: (Fun Elt Bool) -> [Elt] -> Bool
Packit 2632c6
prop_whenElt_not_text (Fun _ p) l = all (not . p) (concat cs)
Packit 2632c6
  where cs = getTexts (whenElt p) l
Packit 2632c6
Packit 2632c6
process :: Splitter Elt -> [Elt] -> SplitList Elt
Packit 2632c6
process s = postProcess s . splitInternal (delimiter s)
Packit 2632c6
Packit 2632c6
prop_dropDelims :: Splitter Elt -> [Elt] -> Bool
Packit 2632c6
prop_dropDelims s l = all (not . isDelim) (process (dropDelims s) l)
Packit 2632c6
Packit 2632c6
prop_keepDelimsL_no_delims :: Splitter Elt -> [Elt] -> Bool
Packit 2632c6
prop_keepDelimsL_no_delims s l = all (not . isDelim) (process (keepDelimsL s) l)
Packit 2632c6
Packit 2632c6
prop_keepDelimsL_match :: Splitter Elt -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_keepDelimsL_match s (NonEmpty l) =
Packit 2632c6
  all (isJust . matchDelim (delimiter s)) [ c | Text c <- tail p ]
Packit 2632c6
    where p = process (keepDelimsL s) l
Packit 2632c6
Packit 2632c6
prop_keepDelimsR_no_delims :: Splitter Elt -> [Elt] -> Bool
Packit 2632c6
prop_keepDelimsR_no_delims s l = all (not . isDelim) (process (keepDelimsR s) l)
Packit 2632c6
Packit 2632c6
prop_keepDelimsR_match :: Splitter Elt -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_keepDelimsR_match s (NonEmpty l) =
Packit 2632c6
  all (any (isJust . matchDelim (delimiter s)) . tails)
Packit 2632c6
    [ c | Text c <- init p ]
Packit 2632c6
      where p = process (keepDelimsR s) l
Packit 2632c6
Packit 2632c6
prop_condense_no_consec_delims :: Splitter Elt -> [Elt] -> Bool
Packit 2632c6
prop_condense_no_consec_delims s l = noConsecDelims $ process (condense s) l
Packit 2632c6
Packit 2632c6
prop_condense_all_delims :: Splitter Elt -> [Elt] -> Bool
Packit 2632c6
prop_condense_all_delims s l = all allDelims p
Packit 2632c6
  where p = [ d | Delim d <- process (condense s) l ]
Packit 2632c6
        allDelims t = all isDelim (splitInternal (delimiter s) t)
Packit 2632c6
Packit 2632c6
prop_dropInitBlank :: Splitter Elt -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_dropInitBlank s (NonEmpty l) = head p /= Text []
Packit 2632c6
  where p = process (dropInitBlank $ s { delimPolicy = Keep } ) l
Packit 2632c6
Packit 2632c6
prop_dropFinalBlank :: Splitter Elt -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_dropFinalBlank s (NonEmpty l) = last p /= Text []
Packit 2632c6
  where p = process (dropFinalBlank $ s { delimPolicy = Keep } ) l
Packit 2632c6
Packit 2632c6
prop_dropBlanks :: Splitter Elt -> [Elt] -> Bool
Packit 2632c6
prop_dropBlanks s = null . filter (== (Text [])) . process (dropBlanks s)
Packit 2632c6
Packit 2632c6
prop_startsWith :: [Elt] -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_startsWith s (NonEmpty l) = all (s `isPrefixOf`) (tail $ split (startsWith s) l)
Packit 2632c6
Packit 2632c6
prop_startsWithOneOf :: [Elt] -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_startsWithOneOf elts (NonEmpty l) = all ((`elem` elts) . head) (tail $ split (startsWithOneOf elts) l)
Packit 2632c6
Packit 2632c6
prop_endsWith :: [Elt] -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_endsWith s (NonEmpty l) = all (s `isSuffixOf`) (init $ split (endsWith s) l)
Packit 2632c6
Packit 2632c6
prop_endsWithOneOf :: [Elt] -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_endsWithOneOf elts (NonEmpty l) = all ((`elem` elts) . last) (init $ split (endsWithOneOf elts) l)
Packit 2632c6
Packit 2632c6
prop_splitOn_right_inv :: [Elt] -> [Elt] -> Bool
Packit 2632c6
prop_splitOn_right_inv x l = intercalate x (splitOn x l) == l
Packit 2632c6
Packit 2632c6
{- This property fails: for example,
Packit 2632c6
Packit 2632c6
      splitOn "dd" (intercalate "dd" ["d",""]) == ["","d"]
Packit 2632c6
Packit 2632c6
   so it's not enough just to say that the delimiter is not an infix of
Packit 2632c6
   any elements of l!
Packit 2632c6
Packit 2632c6
Packit 2632c6
prop_splitOn_left_inv :: [Elt] -> NonEmptyList [Elt] -> Property
Packit 2632c6
prop_splitOn_left_inv x (NonEmpty ls) = not (any (x `isInfixOf`) ls) ==>
Packit 2632c6
                                        splitOn x (intercalate x ls) == ls
Packit 2632c6
-}
Packit 2632c6
Packit 2632c6
-- Note, the below property is in fact logically entailed by
Packit 2632c6
-- prop_splitOn_right_inv, but we keep it here just for kicks.
Packit 2632c6
prop_splitOn_intercalate_idem :: [Elt] -> [[Elt]] -> Bool
Packit 2632c6
prop_splitOn_intercalate_idem x ls = f (f ls) == f ls
Packit 2632c6
  where f = splitOn x . intercalate x
Packit 2632c6
Packit 2632c6
prop_splitOn_empty_delim :: [Elt] -> Bool
Packit 2632c6
prop_splitOn_empty_delim ls = splitOn [] ls == [] : map (:[]) ls
Packit 2632c6
Packit 2632c6
prop_split_empty_delim_drop :: [Elt] -> Bool
Packit 2632c6
prop_split_empty_delim_drop ls
Packit 2632c6
  = split (dropDelims . dropBlanks $ onSublist []) ls == map (:[]) ls
Packit 2632c6
Packit 2632c6
prop_chunksOf_all_n :: Positive Int -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_chunksOf_all_n (Positive n) (NonEmpty l) = all ((==n) . length) (init $ chunksOf n l)
Packit 2632c6
Packit 2632c6
prop_chunksOf_last_less_n :: Positive Int -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_chunksOf_last_less_n (Positive n) (NonEmpty l) = (<=n) . length . last $ chunksOf n l
Packit 2632c6
Packit 2632c6
prop_chunksOf_preserve :: Positive Int -> [Elt] -> Bool
Packit 2632c6
prop_chunksOf_preserve (Positive n) l = concat (chunksOf n l) == l
Packit 2632c6
Packit 2632c6
prop_splitPlaces_lengths :: [NonNegative Int] -> [Elt] -> Bool
Packit 2632c6
prop_splitPlaces_lengths ps = and . mInit . zipWith (==) ps' . map length . splitPlaces ps'
Packit 2632c6
  where ps' = map unNN ps
Packit 2632c6
Packit 2632c6
prop_splitPlaces_last_less_n :: NonEmptyList (NonNegative Int) -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_splitPlaces_last_less_n (NonEmpty ps) (NonEmpty l) = (head $ drop (length l' - 1) ps') >= length (last l')
Packit 2632c6
  where l' = splitPlaces ps' l
Packit 2632c6
        ps' = map unNN ps
Packit 2632c6
Packit 2632c6
prop_splitPlaces_preserve :: [NonNegative Integer] -> [Elt] -> Bool
Packit 2632c6
prop_splitPlaces_preserve ps l = concat (splitPlaces ps' l) == genericTake (sum ps') l
Packit 2632c6
  where ps' = map unNN ps
Packit 2632c6
Packit 2632c6
prop_splitPlaces_chunksOf :: Positive Int -> [Elt] -> Bool
Packit 2632c6
prop_splitPlaces_chunksOf (Positive n) l = splitPlaces (repeat n) l == chunksOf n l
Packit 2632c6
Packit 2632c6
prop_splitPlacesB_length :: [NonNegative Int] -> [Elt] -> Bool
Packit 2632c6
prop_splitPlacesB_length ps xs = length ps' == length (splitPlacesBlanks ps' xs)
Packit 2632c6
  where ps' = map unNN ps
Packit 2632c6
Packit 2632c6
prop_splitPlacesB_last_less_n :: NonEmptyList (NonNegative Int) -> NonEmptyList Elt -> Bool
Packit 2632c6
prop_splitPlacesB_last_less_n (NonEmpty ps) (NonEmpty l) = (head $ drop (length l' - 1) ps') >= length (last l')
Packit 2632c6
  where l' = splitPlacesBlanks ps' l
Packit 2632c6
        ps' = map unNN ps
Packit 2632c6
Packit 2632c6
prop_splitPlacesB_preserve :: [NonNegative Integer] -> [Elt] -> Bool
Packit 2632c6
prop_splitPlacesB_preserve ps l = concat (splitPlacesBlanks ps' l) == genericTake (sum ps') l
Packit 2632c6
  where ps' = map unNN ps
Packit 2632c6
Packit 2632c6
unNN :: NonNegative a -> a
Packit 2632c6
unNN (NonNegative x) = x
Packit 2632c6
Packit 2632c6
mInit :: [a] -> [a]
Packit 2632c6
mInit [] = []
Packit 2632c6
mInit [x] = []
Packit 2632c6
mInit (x:xs) = x : init xs
Packit 2632c6
Packit 2632c6
newtype EltWS = EltWS { unEltWS :: Char }
Packit 2632c6
  deriving (Eq, Show)
Packit 2632c6
Packit 2632c6
instance Arbitrary EltWS where
Packit 2632c6
  arbitrary = elements (map EltWS "abcde \n")
Packit 2632c6
Packit 2632c6
prop_lines :: [EltWS] -> Bool
Packit 2632c6
prop_lines s = lines s' == endBy "\n" s'
Packit 2632c6
  where s' = map unEltWS s
Packit 2632c6
Packit 2632c6
prop_wordsBy_words :: [EltWS] -> Bool
Packit 2632c6
prop_wordsBy_words s = words s' == wordsBy isSpace s'
Packit 2632c6
  where s' = map unEltWS s
Packit 2632c6
Packit 2632c6
prop_linesBy_lines :: [EltWS] -> Bool
Packit 2632c6
prop_linesBy_lines s = lines s' == linesBy (=='\n') s'
Packit 2632c6
  where s' = map unEltWS s
Packit 2632c6
Packit 2632c6
prop_chop_group :: [Elt] -> Bool
Packit 2632c6
prop_chop_group s = chop (\xs@(x:_) -> span (==x) xs) s == group s
Packit 2632c6
Packit 2632c6
prop_chop_words :: [EltWS] -> Bool
Packit 2632c6
prop_chop_words s = words s' == (filter (not . null) . chop (span (not . isSpace) . dropWhile isSpace) $ s')
Packit 2632c6
  where s' = map unEltWS s
Packit 2632c6
Packit 2632c6
prop_divvy_evenly :: [Elt] -> Positive Int -> Bool
Packit 2632c6
prop_divvy_evenly elems (Positive n) = concat (divvy n n elems') == elems'
Packit 2632c6
  where
Packit 2632c6
    -- Chop off the smallest possible tail of elems to make the length
Packit 2632c6
    -- evenly divisible by n.  This property used to have a
Packit 2632c6
    -- precondition (length elemens `mod` n == 0), but that led to too
Packit 2632c6
    -- many discarded test cases and occasional test suite failures.
Packit 2632c6
    elems' = take ((length elems `div` n) * n) elems
Packit 2632c6
Packit 2632c6
prop_divvy_discard_remainder :: [Elt] -> Positive Int -> Bool
Packit 2632c6
prop_divvy_discard_remainder elems (Positive n) =
Packit 2632c6
  concat (divvy n n elems) == (reverse . drop (length elems `mod` n) . reverse $ elems)
Packit 2632c6
Packit 2632c6
prop_divvy_outputlists_allsame_length :: [Elt] -> Positive Int -> Positive Int -> Bool
Packit 2632c6
prop_divvy_outputlists_allsame_length elems (Positive n) (Positive m) = allSame xs
Packit 2632c6
  where
Packit 2632c6
    allSame :: [Int] -> Bool
Packit 2632c6
    allSame [] = True
Packit 2632c6
    allSame zs = and $ map (== head zs) (tail zs)
Packit 2632c6
    xs = map length (divvy n m elems)
Packit 2632c6
Packit 2632c6
prop_divvy_output_are_sublists :: [Elt] -> Positive Int -> Positive Int -> Bool
Packit 2632c6
prop_divvy_output_are_sublists elems (Positive n) (Positive m) = and $ map (\x -> isInfixOf x elems) xs
Packit 2632c6
  where xs = divvy n m elems
Packit 2632c6
Packit 2632c6
takeEvery :: Int -> [a] -> [a]
Packit 2632c6
takeEvery _ [] = []
Packit 2632c6
takeEvery n lst = (map head . chunksOf n) $ lst
Packit 2632c6
Packit 2632c6
initNth :: Int -> [a] -> [a]
Packit 2632c6
initNth _ [] = []
Packit 2632c6
initNth n lst = (reverse . drop n . reverse) $ lst
Packit 2632c6
Packit 2632c6
prop_divvy_heads :: [Elt] -> Positive Int -> Positive Int -> Bool
Packit 2632c6
prop_divvy_heads [] _ _ = True
Packit 2632c6
prop_divvy_heads elems (Positive n) (Positive m) = hds1 == hds2
Packit 2632c6
  where hds1 = takeEvery m (initNth (n - 1) elems)
Packit 2632c6
        hds2 = map head $ divvy n m elems
Packit 2632c6