rascal-1.1.4: src/Test.hs
module Main where
import Data.List (elemIndices, findIndices, union, isPrefixOf)
import Test.Tasty
import Test.Tasty.QuickCheck (testProperty)
import Test.Tasty.HUnit
import Test.QuickCheck
import Data.Map (assocs)
import Control.Applicative ((<$>))
import Rascal.Utils
import Rascal.Conf
data Lines = Lines [String] deriving (Show)
instance Arbitrary Lines where
arbitrary =
Lines <$> listOf1 (listOf (choose ('!', '~')))
main :: IO ()
main = defaultMain tests
tests :: TestTree
tests = testGroup "Tests" [properties, unitTests]
properties :: TestTree
properties = testGroup "Invariants checked with QuickCheck"
[ testProperty "letterizeLines introduces the correct number of newlines"
prop_letterizedLinesUnlines
, testProperty "letterizeLines adds 4 chars per line"
prop_letterizedLinesLength
, testProperty "cleanUp only add lines"
prop_cleanUpLines
, testProperty "cleanUp only replaces spaces by newlines"
prop_cleanUpSpacesToLines
, testProperty "indentLines keeps lines under width"
prop_indentStringHasWidth
, testProperty "indentLines properly adds prefix"
prop_indentStringInsertsPrefix
]
prop_letterizedLinesUnlines :: Lines -> Property
prop_letterizedLinesUnlines (Lines l) =
length l <= 25 ==>
(length . lines . letterizeLines) l == length l
prop_letterizedLinesLength :: Lines -> Bool
prop_letterizedLinesLength (Lines l) =
length (head l) + 4 == length (head (lines (letterizeLines l)))
data WordList = WordList
{ wrds :: String
, len :: Int
} deriving (Show)
instance Arbitrary WordList where
arbitrary = do
Lines w <- arbitrary
-- |don't want words that span the entire line length
l <- choose (maximum (map length w) + 1, 200)
return $ WordList (toStrLn w) l
toStrLn :: [String] -> String
toStrLn wl =
unwords wl ++ "\n"
prop_cleanUpLines :: WordList -> Property
prop_cleanUpLines wl =
let s = wrds wl
l = len wl
initialNewLines = elemIndices '\n' s
cleanedNewLines = elemIndices '\n' (cleanUp s l)
-- | if there are HTML entities to be escaped, it will introduce a shift
in unescape s == s ==>
cleanedNewLines `union` initialNewLines == cleanedNewLines
prop_cleanUpSpacesToLines :: WordList -> Property
prop_cleanUpSpacesToLines wl =
let s = wrds wl
l = len wl
-- | if there are HTML entities to be escaped, it will introduce a shift
in unescape s == s ==>
findIndices (`elem` " \n") (cleanUp s l) == findIndices (`elem` " \n") s
prop_indentStringHasWidth :: Int -> String -> String -> Property
prop_indentStringHasWidth w prefix s =
length prefix < w ==>
all (\l -> length l <= w) $ lines (indentString w prefix s)
prop_indentStringInsertsPrefix :: Int -> String -> String -> Property
prop_indentStringInsertsPrefix w p s =
length p < w && '\n' `notElem` p ==>
all (isPrefixOf p) $ lines (indentString w p s)
unitTests :: TestTree
unitTests = testGroup "Unit tests" [unescapeTests, hrefsTests, parseConfigTests]
unescapeTests :: TestTree
unescapeTests = testGroup "unescape"
[ testCase "unescapes empty" $
unescape "" @?= ""
, testCase "unescapes nothing" $
unescape "& unescape amp nothing;" @?= "& unescape amp nothing;"
, testCase "unescapes &" $
unescape "& unescape & me;" @?= "& unescape & me;"
, testCase "unescapes < and >" $
unescape "& unescape <me>;" @?= "& unescape <me>;"
]
hrefsTests :: TestTree
hrefsTests =
testGroup "hrefs" [testCase "no hrefs in empty" $ hrefs "" @?= []]
parseConfigTests :: TestTree
parseConfigTests = testGroup "parseConfig"
[ testCase "parseConfig empty" $
assocs (parseConfig "") @?= []
, testCase "parseConfig dummy" $
assocs (parseConfig "foo: bar\nstupid is stupid") @?= [("foo", "bar")]
, testCase "parseConfig spaces" $
assocs (parseConfig " foo : bar \n stupid = really stupid ") @?=
[("foo", "bar"), ("stupid", "really stupid")]
]