packages feed

typed-encoding-encoding-0.1.0.0: test/Test/SafeDecodingSpec.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# OPTIONS_GHC -fwarn-unused-imports #-}

-- | 
module Test.SafeDecodingSpec where


import           Data.TypedEncoding 
import           Data.TypedEncoding.Pkg.Encoding.Conv 
import           Data.TypedEncoding.Pkg.Encoding.Instances ()
import           Data.TypedEncoding.Pkg.Encoding.Warn.Instances ()

import           Data.TypedEncoding 

import           Test.QuickCheck.Instances.ByteString ()
import           Test.QuickCheck
import           Test.QuickCheck.Property
import           Test.Hspec
import           GHC.TypeLits
import           Data.Either

-- | decoding should never fail if encoding succeeds
propEncDec :: forall s . (Algorithm s "enc-pkg/encoding") => 
               Encoding (Either EncodeEx) s "enc-pkg/encoding" () String 
               -> Decoding (Either UnexpectedDecodeEx) s "enc-pkg/encoding" () String 
               -> String 
               -> Property
propEncDec encf decf str = property $ liftBool (_propSafeDecoding @s encf decf () str)
 

propValidation  :: forall s . (Algorithm s "enc-pkg/encoding") => 
                   Encoding (Either EncodeEx) s "enc-pkg/encoding" () String 
                   -> Validation (Either RecreateEx) s "enc-pkg/encoding" () String 
                   -> Decoding (Either UnexpectedDecodeEx) s "enc-pkg/encoding" () String 
                   -> String 
                   -> Property
propValidation encf vf decf str = property $ liftBool (_propSafeValidatedDecoding @s vf decf () modStr)
    -- bit of ugly hack, it would be much more work to control Arbitrary outside of this call
    where 
        modStr = case str of 
            'a': _ -> str                               -- most likely invalid encoding
            _ -> either (const str) getPayload . _runEncoding @s encf . toEncoding () $ str -- most likely a valid encoded string
 

data TestSuite = OneBitOnly | All


suite :: 
       TestSuite
       -> (forall s . (Algorithm s "enc-pkg/encoding", KnownSymbol s) => 
          Decoding (Either UnexpectedDecodeEx) s "enc-pkg/encoding" () String 
          -> String 
          -> Property) 
       -> SpecWith ()
suite _ prop = do 
    it "utf8"          $ property $ prop @"enc-pkg/encoding:utf8"         decString 
    it "jis_x_0208"    $ property $ prop @"enc-pkg/encoding:jis_x_0208"   decString 
    it "koi8_r"        $ property $ prop @"enc-pkg/encoding:koi8_r"       decString
    it "koi8_u"        $ property $ prop @"enc-pkg/encoding:koi8_u"       decString
    it "iso8859_1"     $ property $ prop @"enc-pkg/encoding:iso8859_1"    decString
    it "iso8859_2"     $ property $ prop @"enc-pkg/encoding:iso8859_2"    decString
    it "iso8859_3"     $ property $ prop @"enc-pkg/encoding:iso8859_3"    decString
    it "iso8859_4"     $ property $ prop @"enc-pkg/encoding:iso8859_4"    decString
    it "iso8859_5"     $ property $ prop @"enc-pkg/encoding:iso8859_5"    decString
    it "iso8859_6"     $ property $ prop @"enc-pkg/encoding:iso8859_6"    decString
    it "iso8859_7"     $ property $ prop @"enc-pkg/encoding:iso8859_7"    decString
    it "iso8859_8"     $ property $ prop @"enc-pkg/encoding:iso8859_8"    decString
    it "iso8859_9"     $ property $ prop @"enc-pkg/encoding:iso8859_9"    decString
    it "iso8859_10"    $ property $ prop @"enc-pkg/encoding:iso8859_10"   decString
    it "iso8859_11"    $ property $ prop @"enc-pkg/encoding:iso8859_11"   decString
    it "iso8859_13"    $ property $ prop @"enc-pkg/encoding:iso8859_13"   decString
    it "iso8859_14"    $ property $ prop @"enc-pkg/encoding:iso8859_14"   decString
    it "iso8859_15"    $ property $ prop @"enc-pkg/encoding:iso8859_15"   decString
    it "iso8859_16"    $ property $ prop @"enc-pkg/encoding:iso8859_16"   decString
    it "cp1250"        $ property $ prop @"enc-pkg/encoding:cp1250"       decString
    it "cp1251"        $ property $ prop @"enc-pkg/encoding:cp1251"       decString
    it "cp1252"        $ property $ prop @"enc-pkg/encoding:cp1252"       decString
    it "cp1253"        $ property $ prop @"enc-pkg/encoding:cp1253"       decString
    it "cp1254"        $ property $ prop @"enc-pkg/encoding:cp1254"       decString
    it "cp1255"        $ property $ prop @"enc-pkg/encoding:cp1255"       decString
    it "cp1256"        $ property $ prop @"enc-pkg/encoding:cp1256"       decString
    it "cp1257"        $ property $ prop @"enc-pkg/encoding:cp1257"       decString
    it "cp1258"        $ property $ prop @"enc-pkg/encoding:cp1258"       decString
    it "gb18030"       $ property $ prop @"enc-pkg/encoding:gb18030"      decString
    it "macintosh"     $ property $ prop @"enc-pkg/encoding:macintosh"    decString
    it "jis_x_0201"    $ property $ prop @"enc-pkg/encoding:jis_x_0201"   decString
    it "cp437"         $ property $ prop @"enc-pkg/encoding:cp437"        decString
    it "cp737"         $ property $ prop @"enc-pkg/encoding:cp737"        decString
    it "cp775"         $ property $ prop @"enc-pkg/encoding:cp775"        decString
    it "cp850"         $ property $ prop @"enc-pkg/encoding:cp850"        decString
    it "cp852"         $ property $ prop @"enc-pkg/encoding:cp852"        decString
    it "cp855"         $ property $ prop @"enc-pkg/encoding:cp855"        decString
    it "cp857"         $ property $ prop @"enc-pkg/encoding:cp857"        decString
    it "cp860"         $ property $ prop @"enc-pkg/encoding:cp860"        decString
    it "cp861"         $ property $ prop @"enc-pkg/encoding:cp861"        decString
    it "cp862"         $ property $ prop @"enc-pkg/encoding:cp862"        decString
    it "cp863"         $ property $ prop @"enc-pkg/encoding:cp863"        decString
    it "cp864"         $ property $ prop @"enc-pkg/encoding:cp864"        decString
    it "cp865"         $ property $ prop @"enc-pkg/encoding:cp865"        decString
    it "cp866"         $ property $ prop @"enc-pkg/encoding:cp866"        decString
    it "cp869"         $ property $ prop @"enc-pkg/encoding:cp869"        decString
    it "cp874"         $ property $ prop @"enc-pkg/encoding:cp874"        decString
    
    -- /encoding/ package issue, it allows encoding on invalid character that later fails during decode:
    -- it "cp932"         $ property $ prop @"enc-pkg/encoding:cp932"       encString decString



spec :: Spec 
spec =  
    describe "Sanity" $ do
        describe "save decode after encode" $ 
             suite All (propEncDec encString)
        describe "save decode after validate" $ 
             suite All (propValidation encString validation)

runSpec :: IO ()
runSpec = hspec spec