{-# LANGUAGE ExistentialQuantification,ImplicitParams #-} module Test.Tester where import Data.Encoding import Data.Encoding.UTF8 import Test.HUnit import Data.Word import Data.Char import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS import Test.QuickCheck hiding (Testable) import Prelude hiding (readFile) import System.IO.Encoding data EncodingTest = forall enc. (Encoding enc,Show enc) => EncodingTest enc String [Word8] | forall enc. (Encoding enc,Show enc) => EncodingFileTest enc FilePath FilePath | forall enc. (Encoding enc,Show enc) => DecodingError enc [Word8] DecodingException | forall enc. (Encoding enc,Show enc) => EncodingError enc String EncodingException instance Testable EncodingTest where test (EncodingTest enc src trg) = TestList [TestLabel (show enc ++ " encoding") (TestCase $ encodeStrictByteStringExplicit enc src @?= Right (BS.pack trg)) ,TestLabel (show enc ++ " decoding") (TestCase $ decodeStrictByteStringExplicit enc (BS.pack trg) @=? Right src) ] test (EncodingFileTest e src trg) = test $ do str_src <- (let ?enc = e in readFile src) bsrc <- LBS.readFile src str_trg <- (let ?enc = UTF8 in readFile trg) str_src @?= str_trg --bsrc @=? (encodeLazyByteString enc str_trg) test (DecodingError enc src ex) = TestLabel (show enc ++ " decoding error") (TestCase $ decodeStrictByteStringExplicit enc (BS.pack src) @=? Left ex) charGen :: Gen Char charGen = let ascii = choose (0x00,0x7F) >>= return.chr oneByte = choose (0x80,0xFF) >>= return.chr twoByte = choose (0x0100,0xFFFF) >>= return.chr threeByte = choose (0x010000,0x10FFFF) >>= return.chr in frequency [(40,ascii),(30,oneByte),(20,twoByte),(10,threeByte)] quickCheckEncoding :: Encoding enc => enc -> IO () quickCheckEncoding e = do quickCheck (encodingIdentity e) quickCheck (decodingIdentity e) encodingIdentity :: Encoding enc => enc -> Property encodingIdentity e = let gen = listOf1 (charGen `suchThat` (encodeable e)) in forAll gen (\str -> case encodeStrictByteStringExplicit e str of Left err -> property False Right res -> case decodeStrictByteStringExplicit e res of Left err -> property False Right res2 -> property (str==res2)) decodingIdentity :: Encoding enc => enc -> [Word8] -> Property decodingIdentity e wrd = classify (null wrd) "trivial" $ case decoded of Left err -> label "trivial" $ property True Right res -> case encodeStrictByteStringExplicit e res of Left err -> property False Right res' -> property (bstr==res') where bstr = BS.pack wrd decoded = decodeStrictByteStringExplicit e bstr