{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module HaskellWorks.Data.Xml.Conduit.BlankSpec (spec) where
import Data.Char
import Data.Monoid
import HaskellWorks.Data.ByteString
import HaskellWorks.Data.Conduit.List
import HaskellWorks.Data.Xml.Conduit.Blank
import Test.Hspec
import Test.QuickCheck
import qualified Data.ByteString as BS
{-# ANN module ("HLint: ignore Redundant do" :: String) #-}
{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
whenBlankedXmlShouldBe :: BS.ByteString -> BS.ByteString -> Spec
whenBlankedXmlShouldBe original expected = do
it (show original <> " when blanked xml should be " <> show expected) $ do
BS.concat (runListConduit blankXml [original]) `shouldBe` expected
repeatBS :: Int -> BS.ByteString -> BS.ByteString
repeatBS n bs | n > 0 = bs <> repeatBS (n - 1) bs
repeatBS _ _ = BS.empty
noSpaces :: BS.ByteString -> BS.ByteString
noSpaces = BS.filter (/= fromIntegral (ord ' '))
data Annotated a b = Annotated a b deriving Show
instance Eq a => Eq (Annotated a b) where
(Annotated a _) == (Annotated b _) = a == b
spec :: Spec
spec = describe "HaskellWorks.Data.Xml.Conduit.BlankSpec" $ do
describe "Can blank XML" $ do
"" `whenBlankedXmlShouldBe` "< >"
"" `whenBlankedXmlShouldBe` "< >"
"text" `whenBlankedXmlShouldBe` "< t >"
" text " `whenBlankedXmlShouldBe` "< t >"
"" `whenBlankedXmlShouldBe` "< ()>"
"" `whenBlankedXmlShouldBe` "< (a v )>"
"" `whenBlankedXmlShouldBe` "< (a v )>"
"" `whenBlankedXmlShouldBe` "< (a v )>"
"" `whenBlankedXmlShouldBe` "< (a v a v )>"
"text" `whenBlankedXmlShouldBe` "< (a v a v )t >"
"" `whenBlankedXmlShouldBe` "< (a v a v )>"
"" `whenBlankedXmlShouldBe` "< (a v )< > >"
"test" `whenBlankedXmlShouldBe` "< (a v )< t > >"
" text bold " `whenBlankedXmlShouldBe` "< t < t > >"
" text bold uuu" `whenBlankedXmlShouldBe` "< t < t > t >"
"" `whenBlankedXmlShouldBe` "< (a v )>"
" " `whenBlankedXmlShouldBe` "< [ ] >"
" " `whenBlankedXmlShouldBe` "< [ ] >"
" " `whenBlankedXmlShouldBe` "< [ ] >"
"" `whenBlankedXmlShouldBe` "< (a v a v )>"
"]>" `whenBlankedXmlShouldBe` "[ [ ] ]"
"Hello,\
\ world!]]>" `whenBlankedXmlShouldBe` "< [ ] >"
"" `whenBlankedXmlShouldBe` "< [ ] >"
"00" `whenBlankedXmlShouldBe` "< < t >< > >"
"0" `whenBlankedXmlShouldBe` "< < t >< > >"
it "Can blank across chunk boundaries with basic tags" $ do
let inputOriginalPrefix = "\n\n "
let inputOriginalSuffix = "\n \n \n \n \n \n\n"
let inputOriginal = inputOriginalPrefix <> inputOriginalSuffix
let inputOriginalChunked = chunkedBy 16 inputOriginal
let inputOriginalBlanked = runListConduit blankXml inputOriginalChunked
forAll (choose (0, 16)) $ \(n :: Int) -> do
let inputShifted = inputOriginalPrefix <> repeatBS n " " <> inputOriginalSuffix
let inputShiftedChunked = chunkedBy 16 inputShifted
let inputShiftedBlanked = runListConduit blankXml inputShiftedChunked
noSpaces (BS.concat inputShiftedBlanked) `shouldBe` noSpaces (BS.concat inputOriginalBlanked)
it "Can blank across chunk boundaries with auto-close tags" $ do
let inputOriginalPrefix = ""
let inputOriginalSuffix = "\n"
let inputOriginal = inputOriginalPrefix <> inputOriginalSuffix
let inputOriginalChunked = chunkedBy 16 inputOriginal
let inputOriginalBlanked = runListConduit blankXml inputOriginalChunked
forAll (choose (0, 16)) $ \(n :: Int) -> do
let inputShifted = inputOriginalPrefix <> repeatBS n " " <> inputOriginalSuffix
let inputShiftedChunked = chunkedBy 16 inputShifted
let inputShiftedBlanked = runListConduit blankXml inputShiftedChunked
-- putStrLn $ show (BS.concat inputShiftedBlanked) <> " vs " <> show (BS.concat inputOriginalBlanked)
let actual = Annotated (noSpaces (BS.concat inputShiftedBlanked )) (inputShiftedBlanked, n)
let expected = Annotated (noSpaces (BS.concat inputOriginalBlanked)) (inputOriginalBlanked, n)
actual `shouldBe` expected
it "Can blank across chunk boundaries with auto-close tags" $ do
let inputOriginalPrefix = ""
let inputOriginalSuffix = "\n"
let inputOriginal = inputOriginalPrefix <> inputOriginalSuffix
let inputOriginalChunked = chunkedBy 16 inputOriginal
let inputOriginalBlanked = runListConduit blankXml inputOriginalChunked
let n = 15
let inputShifted = inputOriginalPrefix <> repeatBS n " " <> inputOriginalSuffix
let inputShiftedChunked = chunkedBy 16 inputShifted
let inputShiftedBlanked = runListConduit blankXml inputShiftedChunked
-- putStrLn $ show (BS.concat inputShiftedBlanked) <> " vs " <> show (BS.concat inputOriginalBlanked)
let actual = Annotated (noSpaces (BS.concat inputShiftedBlanked )) (inputShiftedBlanked, n)
let expected = Annotated (noSpaces (BS.concat inputOriginalBlanked)) (inputOriginalBlanked, n)
actual `shouldBe` expected