quickcheck-text-0.1.2.1/src/0000755000000000000000000000000012571372507013733 5ustar0000000000000000quickcheck-text-0.1.2.1/src/Data/0000755000000000000000000000000012571372507014604 5ustar0000000000000000quickcheck-text-0.1.2.1/src/Data/Text/0000755000000000000000000000000012731426445015527 5ustar0000000000000000quickcheck-text-0.1.2.1/src/Test/0000755000000000000000000000000012571372471014652 5ustar0000000000000000quickcheck-text-0.1.2.1/src/Test/QuickCheck/0000755000000000000000000000000012770720505016660 5ustar0000000000000000quickcheck-text-0.1.2.1/test/0000755000000000000000000000000012731426445014122 5ustar0000000000000000quickcheck-text-0.1.2.1/src/Test/QuickCheck/Utf8.hs0000644000000000000000000000711712770720505020050 0ustar0000000000000000module Test.QuickCheck.Utf8( genValidUtf8 , shrinkValidUtf8 , utf8BS , shrinkUtf8BS , genValidUtf81 , shrinkValidUtf81 , utf8BS1 , shrinkUtf8BS1 -- * Generators for single characters , genChar , genUtf8Character , oneByte , twoByte , threeByte ) where import Control.Monad import Data.Binary.Builder import Data.ByteString (ByteString) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding import Data.Text.Internal.Encoding.Utf8 import Data.Word import Test.QuickCheck -- | -- Generate a possibly-empty valid UTF-8 'Text' value. genValidUtf8 :: Gen Text genValidUtf8 = fmap decodeUtf8 utf8BS -- | -- Shrink a possible-empty valid UTF-8 'Text' value. shrinkValidUtf8 :: Text -> [Text] shrinkValidUtf8 = fmap T.pack . shrink . T.unpack -- | -- Generate a possibly-empty sequence of bytes which represent a valid -- UTF-8 code point. utf8BS :: Gen ByteString utf8BS = fmap BS.concat . listOf $ oneof symbolTypes -- | -- Shrink a possible-empty sequence of bytes which represent a valid -- UTF-8 code point. shrinkUtf8BS :: ByteString -> [ByteString] shrinkUtf8BS = fmap encodeUtf8 . shrinkValidUtf8 . decodeUtf8 -- | -- Like 'genValidUtf8', but does not allow empty 'Text' values. genValidUtf81 :: Gen Text genValidUtf81 = fmap decodeUtf8 utf8BS1 -- | -- List 'genValidUtf8', bute does not allow empty 'Text' values. shrinkValidUtf81 :: Text -> [Text] shrinkValidUtf81 = filter (not . T.null) . shrinkValidUtf8 -- | -- Like 'utf8BS', but does not allow empty 'ByteString's. utf8BS1 :: Gen ByteString utf8BS1 = fmap BS.concat . listOf1 $ oneof symbolTypes -- | -- Like 'shrinkUtf8BS', but does not allow empty 'ByteString's. shrinkUtf8BS1 :: ByteString -> [ByteString] shrinkUtf8BS1 = filter (not . BS.null) . shrinkUtf8BS symbolTypes :: [Gen ByteString] symbolTypes = [ oneByte , twoByte , threeByte ] inRange :: Int -> Int -> Gen Word8 inRange lo hi = fmap fromIntegral $ elements [lo..hi] -- | Generate a valid 'Char'. Note that this is UTF-16, not UTF-8, but -- the intent is the same: the Arbitrary instance for 'Char' in quickcheck -- makes no attempt to generate valid non-ASCII characters at this time. genChar :: Gen Char genChar = fmap (T.head . decodeUtf8) genUtf8Character -- | A valid UTF-8 character, one to three bytes long. genUtf8Character :: Gen ByteString genUtf8Character = oneof [ oneByte , twoByte , threeByte ] -- | Single-byte UTF-8 (i.e., a standard ASCII byte with a cleared MSB). oneByte :: Gen ByteString oneByte = fmap (BS.pack . return) $ inRange 0 127 -- 0bbbbbbb twoByte :: Gen ByteString twoByte = do b1 <- inRange 0xC2 0xDF -- 110bbbbb b2 <- nonInitial return . buildUtf $ putBytes2 b1 b2 threeByte :: Gen ByteString threeByte = do (b1, b2) <- oneof [b3_1, b3_2, b3_3, b3_4] b3 <- nonInitial return . buildUtf $ putBytes3 b1 b2 b3 where b3_1 = (,) `fmap` return 0xE0 `ap` inRange 0xA0 0xBF b3_2 = (,) `fmap` inRange 0xE1 0xEC `ap` nonInitial b3_3 = (,) `fmap` return 0xED `ap` inRange 0x80 0x9F b3_4 = (,) `fmap` inRange 0xEE 0xEF `ap` nonInitial buildUtf :: Builder -> ByteString buildUtf = BS.concat . BL.toChunks . toLazyByteString putBytes2 :: Word8 -> Word8 -> Builder putBytes2 b1 b2 = putCharUtf8 $ chr2 b1 b2 putBytes3 :: Word8 -> Word8 -> Word8 -> Builder putBytes3 b1 b2 b3 = putCharUtf8 $ chr3 b1 b2 b3 nonInitial :: Gen Word8 nonInitial = inRange 0x80 0xBF quickcheck-text-0.1.2.1/src/Data/Text/Arbitrary.hs0000644000000000000000000000041512731426445020022 0ustar0000000000000000{-# OPTIONS_GHC -fno-warn-orphans #-} module Data.Text.Arbitrary( Text() ) where import Data.Text import Test.QuickCheck import Test.QuickCheck.Utf8 instance Arbitrary Text where arbitrary = genValidUtf8 shrink = shrinkValidUtf8 quickcheck-text-0.1.2.1/test/properties.hs0000644000000000000000000000342112731426445016652 0ustar0000000000000000{-# LANGUAGE TemplateHaskell #-} module Main where import Control.Monad import Data.Bits import qualified Data.ByteString as BS import qualified Data.Text as T import Data.Text.Encoding import System.Exit import Test.QuickCheck import Test.QuickCheck.Utf8 prop_decodes_without_exception :: Property prop_decodes_without_exception = forAllAndShrinks utf8BS shrinkUtf8BS $ \bs -> let t = decodeUtf8 bs in (T.length t >=) 0 === True prop_oneByte_lsb :: Property prop_oneByte_lsb = forAll oneByte $ \bs -> let b = head $ BS.unpack bs in testBit b 7 === False prop_oneByte_range :: Property prop_oneByte_range = forAll oneByte $ \bs -> let s = sum $ fmap fromIntegral $ BS.unpack bs in (s >= 0 && s <= 127) prop_twoByte_range :: Property prop_twoByte_range = forAll twoByte $ \bs -> let s = sum $ fmap fromIntegral $ BS.unpack bs in (s >= 320 && s <= 65439) prop_threeByte_range :: Property prop_threeByte_range = forAll threeByte $ \bs -> let s = sum $ fmap fromIntegral $ BS.unpack bs in (s >= 480 && s <= 16777071) prop_validUtf81_length :: Property prop_validUtf81_length = forAllAndShrinks utf8BS1 shrinkUtf8BS1 $ \bs -> BS.length bs >= 1 prop_validUtf81_valid :: Property prop_validUtf81_valid = forAllAndShrinks utf8BS1 shrinkUtf8BS1 $ \bs -> let t = decodeUtf8 bs in (T.length t >= 1) === True -- | -- Ensure that the shrink applied to the generated value also satisfies the property. forAllAndShrinks :: (Show a, Testable prop) => Gen a -> (a -> [a]) -> (a -> prop) -> Property forAllAndShrinks gen shr prop = forAll (gen >>= \x -> return (x : shr x)) $ \xs -> conjoin $ fmap prop xs return [] props :: IO Bool props = $quickCheckAll main :: IO () main = props >>= flip when exitFailure . not quickcheck-text-0.1.2.1/LICENSE0000644000000000000000000000204112571372241014141 0ustar0000000000000000Copyright (c) 2015 Sharif Olorin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. quickcheck-text-0.1.2.1/Setup.hs0000644000000000000000000000005612571372241014574 0ustar0000000000000000import Distribution.Simple main = defaultMain quickcheck-text-0.1.2.1/quickcheck-text.cabal0000644000000000000000000000340212770720505017217 0ustar0000000000000000name: quickcheck-text version: 0.1.2.1 synopsis: Alternative arbitrary instance for Text description: The usual Arbitrary instance for Text (in ) only has single-byte instances and so isn't an ideal representation of a valid UTF-8 character. This package has generators for one-, two- and three-byte UTF-8 characters (all that are currently in use). homepage: https://github.com/olorin/quickcheck-text license: MIT license-file: LICENSE author: Sharif Olorin maintainer: sio@tesser.org copyright: 2015-2016 Sharif Olorin and others category: Text build-type: Simple cabal-version: >=1.10 extra-source-files: README.md source-repository head type: git location: git@github.com:olorin/quickcheck-text.git library exposed-modules: Test.QuickCheck.Utf8 Data.Text.Arbitrary build-depends: base >=4 && <5 , QuickCheck , binary , bytestring , text hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall test-suite properties hs-source-dirs: test main-is: properties.hs type: exitcode-stdio-1.0 default-language: Haskell2010 ghc-options: -Wall build-depends: base >=4.7 && <5 , QuickCheck , bytestring , quickcheck-text , text quickcheck-text-0.1.2.1/README.md0000644000000000000000000000053312573502204014413 0ustar0000000000000000# quickcheck-text The usual Arbitrary instance for Text (in [quickcheck-instances](https://hackage.haskell.org/package/quickcheck-instances)) only has single-byte instances and so isn't an ideal representation of a valid UTF-8 character. This package has generators for one-, two- and three-byte UTF-8 characters (all that are currently in use).