module Tests.Arbitrary.Xml where import Control.Applicative ((<$>), (<*>)) import Test.QuickCheck import Test.QuickCheck.Instances() -- import Data.DeriveTH import qualified Data.Text as Text import Data.XML.Types import Tests.Arbitrary.Common import Text.CharRanges selectFromRange :: Range -> Gen Char selectFromRange (Single a) = return a selectFromRange (Range a b) = choose (a, b) nameStartChar :: [Range] nameStartChar = [ -- Single ':' Single '_' , Range 'A' 'Z' , Range 'a' 'z' , Range '\xC0' '\xD6' , Range '\xD8' '\xF6' , Range '\xF8' '\x2FF' , Range '\x370' '\x37D' , Range '\x37F' '\x1FFF' , Range '\x200C' '\x200D' , Range '\x2070' '\x218F' , Range '\x2C00' '\x2FEF' , Range '\x3001' '\xD7FF' , Range '\xF900' '\xFDCF' , Range '\xFDF0' '\xFFFD' , Range '\x10000' '\xEFFFF' ] nameChar :: [Range] nameChar = Single '-' : Single '.' : Single '\xB7' : Range '0' '9' : Range '\x0300' '\x036F' : Range '\x203F' '\x2040' : nameStartChar genNCName :: Gen Text.Text genNCName = do sc <- elements nameStartChar >>= selectFromRange ncs <- listOf $ elements nameChar >>= selectFromRange return . Text.pack $ sc:ncs -- | Cap the size of child elements. slow :: Gen a -> Gen a slow g = sized $ \n -> resize (min 5 (n `div` 4)) g instance Arbitrary Name where arbitrary = Name <$> genNCName <*> genMaybe genNCName <*> genMaybe genNCName where genMaybe g = oneof [return Nothing, Just <$> g] shrink (Name a b c) = [ Name a' b c | a' <- shrinkText1 a] ++[ Name a b' c | b' <- shrinkTextMaybe b] ++[ Name a b c' | c' <- shrinkTextMaybe c] instance Arbitrary Content where arbitrary = ContentText <$> arbitrary shrink (ContentText txt) = ContentText <$> shrinkText1 txt shrink _ = [] instance Arbitrary Node where arbitrary = oneof [ NodeElement <$> arbitrary , NodeContent <$> arbitrary ] shrink (NodeElement e) = NodeElement <$> shrink e shrink (NodeContent c) = NodeContent <$> shrink c shrink _ = [] instance Arbitrary Element where arbitrary = Element <$> arbitrary <*> slow arbitrary <*> slow arbitrary shrink (Element a b c) = [ Element a' b c | a' <- shrink a] ++[ Element a b' c | b' <- shrink b] ++[ Element a b c' | c' <- shrink c]