packages feed

vector-split-1.0.0.0: test/Spec.hs

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE CPP #-}

import           Test.Tasty
import qualified Test.Tasty.QuickCheck as QC

import           Test.QuickCheck
import           Test.QuickCheck.Function

import qualified Data.Vector as V
import qualified Data.Vector.Split as V
import qualified Data.Vector.Split.Internal as V

import qualified Data.List       as L
import qualified Data.List.Split as L

import           Data.Char

import           Debug.Trace

main :: IO ()
main = defaultMain tests



tests = testGroup "tests" 
  [ testGroup "basic strategies"
    [ QC.testProperty "oneOf" prop_oneOf
    , QC.testProperty "onSublist" prop_onSublist
    , QC.testProperty "whenElt" prop_whenElt
    ]
  , testGroup "strategy transformers"
    [ QC.testProperty "dropDelims" prop_dropDelims
    , QC.testProperty "keepDelimsL" prop_keepDelimsL
    , QC.testProperty "keepDelimsR" prop_keepDelimsR
    , QC.testProperty "condense" prop_condense
    , QC.testProperty "dropInitBlank" prop_dropInitBlank
    , QC.testProperty "dropFinalBlank" prop_dropFinalBlank
    , QC.testProperty "dropInnerBlank" prop_dropInnerBlank
    ]
  , testGroup "other splitting methods"
    [ QC.testProperty "chunksOf" prop_chunksOf
    , QC.testProperty "splitPlaces" prop_splitPlaces
    , QC.testProperty "splitPlacesBlanks" prop_splitPlacesBlanks
    , QC.testProperty "chop" prop_chop
    , QC.testProperty "chopGroup" prop_chopGroup
#if MIN_VERSION_split(2,3,0)
    , QC.testProperty "divvy" prop_divvy
#endif
    ]
  , testGroup "convenience functions"
    [ QC.testProperty "splitOn" prop_splitOn
    , QC.testProperty "splitOneOf" prop_splitOneOf
    , QC.testProperty "splitWhen" prop_splitWhen
    , QC.testProperty "endBy" prop_endBy
    , QC.testProperty "endByOneOf" prop_endByOneOf
    , QC.testProperty "wordsBy" prop_wordsBy
    , QC.testProperty "linesBy" prop_linesBy
    ]
  ]

-- small set of elements used for testing

newtype Elt = Elt { unElt :: Char } deriving (Eq)

type Elements = [Elt]
type SomeElements = NonEmptyList Elt

instance Show Elt where
    show (Elt c) = show c

instance Arbitrary Elt where
    arbitrary = elements (map Elt "abcde")

instance CoArbitrary Elt where
  coarbitrary = coarbitrary . ord . unElt


instance Function Elt where
  function = functionMap unElt Elt

-- Basic Strategies

prop_oneOf :: Elements -> Elements -> Property
prop_oneOf d = listVsVec (L.split (L.oneOf d)) (V.split (V.oneOf (V.fromList d)))

prop_onSublist :: SomeElements -> Elements -> Property
prop_onSublist (NonEmpty d) = listVsVec (L.split (L.onSublist d)) (V.split (V.onSublist (V.fromList d)))

prop_whenElt :: Fun Elt Bool -> Elements -> Property
prop_whenElt (Fun _ f) = listVsVec (L.split (L.whenElt f)) (V.split (V.whenElt f))



-- Strategy Transformers

prop_dropDelims :: SomeElements -> Elements -> Property
prop_dropDelims (NonEmpty d) = listVsVec (L.split (L.dropDelims (L.oneOf d)))
                                         (V.split (V.dropDelims . V.oneOf (V.fromList d)))

prop_keepDelimsL :: SomeElements -> Elements -> Property
prop_keepDelimsL (NonEmpty d) = listVsVec (L.split (L.keepDelimsL (L.oneOf d)))
                                          (V.split (V.keepDelimsL . V.oneOf (V.fromList d)))

prop_keepDelimsR :: SomeElements -> Elements -> Property
prop_keepDelimsR (NonEmpty d) = listVsVec (L.split (L.keepDelimsR (L.oneOf d)))
                                          (V.split (V.keepDelimsR . V.oneOf (V.fromList d)))

prop_condense :: SomeElements -> Elements -> Property
prop_condense (NonEmpty d) = listVsVec (L.split (L.condense (L.oneOf d)))
                                       (V.split (V.condense . V.oneOf (V.fromList d)))

prop_dropInitBlank :: SomeElements -> Elements -> Property
prop_dropInitBlank (NonEmpty d) = listVsVec (L.split (L.dropInitBlank (L.oneOf d)))
                                            (V.split (V.dropInitBlank . V.oneOf (V.fromList d)))

prop_dropFinalBlank :: SomeElements -> Elements -> Property
prop_dropFinalBlank (NonEmpty d) = listVsVec (L.split (L.dropFinalBlank (L.oneOf d)))
                                             (V.split (V.dropFinalBlank . V.oneOf (V.fromList d)))

prop_dropInnerBlank :: SomeElements -> Elements -> Property
prop_dropInnerBlank (NonEmpty d) = listVsVec (L.split (L.dropInnerBlanks (L.oneOf d)))
                                             (V.split (V.dropInnerBlanks . V.oneOf (V.fromList d)))

-- Other Splitting Methods

prop_chunksOf :: Positive Int -> [Double] -> Property
prop_chunksOf (Positive i) = listVsVec (L.chunksOf i) (V.chunksOf i)

prop_splitPlaces :: [Positive Int] -> [Double] -> Property
prop_splitPlaces is = listVsVec (L.splitPlaces is') (V.splitPlaces is')
    where is' = map getPositive is

prop_splitPlacesBlanks :: [Positive Int] -> [Double] -> Property
prop_splitPlacesBlanks is = listVsVec (L.splitPlacesBlanks is') (V.splitPlacesBlanks is')
    where is' = map getPositive is

prop_chop :: [Double] -> Property
prop_chop = listVsVec (L.chop (L.splitAt 10)) (V.chop (V.splitAt 10))

prop_chopGroup :: [Double] -> Property
prop_chopGroup = listVsVec (L.chop (\xs -> L.span (== L.head xs) xs)) (V.chop (\xs -> V.span (== V.head xs) xs))

#if MIN_VERSION_split(2,3,0)
prop_divvy :: Positive Int -> Positive Int -> [Double] -> Property
prop_divvy (Positive n) (Positive m) = listVsVec (L.divvy n m) (V.divvy n m)
#endif



-- Convenience functions

prop_splitOneOf :: SomeElements -> Elements -> Property
prop_splitOneOf (NonEmpty ds) = listVsVec (L.splitOneOf ds) (V.splitOneOf (V.fromList ds))

prop_splitOn :: SomeElements -> Elements -> Property
prop_splitOn (NonEmpty ds) = listVsVec (L.splitOn ds) (V.splitOn (V.fromList ds))

prop_splitWhen :: Fun Elt Bool -> Elements -> Property
prop_splitWhen (Fun _ f) = listVsVec (L.splitWhen f) (V.splitWhen f)

prop_endBy :: SomeElements -> Elements -> Property
prop_endBy (NonEmpty p) = listVsVec (L.endBy p) (V.endBy (V.fromList p))

prop_endByOneOf :: SomeElements -> Elements -> Property
prop_endByOneOf (NonEmpty p) = listVsVec (L.endByOneOf p) (V.endByOneOf (V.fromList p))

prop_wordsBy :: Fun Elt Bool -> Elements -> Property
prop_wordsBy (Fun _ f) = listVsVec (L.wordsBy f) (V.wordsBy f)

prop_linesBy :: Fun Elt Bool -> Elements -> Property
prop_linesBy (Fun _ f) = listVsVec (L.linesBy f) (V.linesBy f)




-- | compare a list splitting vs a vector splitting function
listVsVec :: (Show a, Eq a) => ([a] -> [[a]]) -> (V.Vector a -> [V.Vector a]) -> [a] -> Property
listVsVec a b l = ls === map V.toList vs
    where v = V.fromList l
          ls = a l
          vs = b v