{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module HaskellWorks.Data.Xml.Internal.BlankSpec (spec) where import Data.Char import HaskellWorks.Data.ByteString import HaskellWorks.Data.Xml.Internal.Blank import HaskellWorks.Hspec.Hedgehog import Hedgehog import Test.Hspec import qualified Data.ByteString as BS import qualified Hedgehog.Gen as G import qualified Hedgehog.Range as R {-# 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) $ requireTest $ do BS.concat (blankXml [original]) === 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.Internal.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" $ requireTest $ 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 = blankXml inputOriginalChunked n <- forAll $ G.int (R.linear 0 16) let inputShifted = inputOriginalPrefix <> repeatBS n " " <> inputOriginalSuffix let inputShiftedChunked = chunkedBy 16 inputShifted let inputShiftedBlanked = blankXml inputShiftedChunked noSpaces (BS.concat inputShiftedBlanked) === noSpaces (BS.concat inputOriginalBlanked) it "Can blank across chunk boundaries with auto-close tags" $ requireTest $ do let inputOriginalPrefix = "" let inputOriginalSuffix = "\n" let inputOriginal = inputOriginalPrefix <> inputOriginalSuffix let inputOriginalChunked = chunkedBy 16 inputOriginal let inputOriginalBlanked = blankXml inputOriginalChunked n <- forAll $ G.int (R.linear 0 16) let inputShifted = inputOriginalPrefix <> repeatBS n " " <> inputOriginalSuffix let inputShiftedChunked = chunkedBy 16 inputShifted let inputShiftedBlanked = 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 === expected it "Can blank across chunk boundaries with auto-close tags" $ requireTest $ do let inputOriginalPrefix = "" let inputOriginalSuffix = "\n" let inputOriginal = inputOriginalPrefix <> inputOriginalSuffix let inputOriginalChunked = chunkedBy 16 inputOriginal let inputOriginalBlanked = blankXml inputOriginalChunked let n = 15 let inputShifted = inputOriginalPrefix <> repeatBS n " " <> inputOriginalSuffix let inputShiftedChunked = chunkedBy 16 inputShifted let inputShiftedBlanked = 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 === expected