Blame tests/Tests.hs

Packit ae7d4f
import Test.Tasty.QuickCheck
Packit ae7d4f
import Test.Tasty
Packit ae7d4f
Packit ae7d4f
import Control.Applicative
Packit ae7d4f
import Data.ASN1.Get (runGet, Result(..))
Packit ae7d4f
import Data.ASN1.BitArray
Packit ae7d4f
import Data.ASN1.Prim
Packit ae7d4f
import Data.ASN1.Serialize
Packit ae7d4f
import Data.ASN1.BinaryEncoding.Parse
Packit ae7d4f
import Data.ASN1.BinaryEncoding.Writer
Packit ae7d4f
import Data.ASN1.BinaryEncoding
Packit ae7d4f
import Data.ASN1.Encoding
Packit ae7d4f
import Data.ASN1.Types
Packit ae7d4f
import Data.ASN1.Types.Lowlevel
Packit ae7d4f
Packit ae7d4f
import Data.Hourglass
Packit ae7d4f
Packit ae7d4f
import qualified Data.ByteString as B
Packit ae7d4f
Packit ae7d4f
import Control.Monad
Packit ae7d4f
Packit ae7d4f
instance Arbitrary ASN1Class where
Packit ae7d4f
        arbitrary = elements [ Universal, Application, Context, Private ]
Packit ae7d4f
Packit ae7d4f
instance Arbitrary ASN1Length where
Packit ae7d4f
        arbitrary = do
Packit ae7d4f
                c <- choose (0,2) :: Gen Int
Packit ae7d4f
                case c of
Packit ae7d4f
                        0 -> liftM LenShort (choose (0,0x79))
Packit ae7d4f
                        1 -> do
Packit ae7d4f
                                nb <- choose (0x80,0x1000)
Packit ae7d4f
                                return $ mkSmallestLength nb
Packit ae7d4f
                        _ -> return LenIndefinite
Packit ae7d4f
                where
Packit ae7d4f
                        nbBytes nb = if nb > 255 then 1 + nbBytes (nb `div` 256) else 1
Packit ae7d4f
Packit ae7d4f
arbitraryDefiniteLength :: Gen ASN1Length
Packit ae7d4f
arbitraryDefiniteLength = arbitrary `suchThat` (\l -> l /= LenIndefinite)
Packit ae7d4f
Packit ae7d4f
arbitraryTag :: Gen ASN1Tag
Packit ae7d4f
arbitraryTag = choose(1,10000)
Packit ae7d4f
Packit ae7d4f
instance Arbitrary ASN1Header where
Packit ae7d4f
        arbitrary = liftM4 ASN1Header arbitrary arbitraryTag arbitrary arbitrary
Packit ae7d4f
Packit ae7d4f
arbitraryEvents :: Gen ASN1Events
Packit ae7d4f
arbitraryEvents = do
Packit ae7d4f
        hdr@(ASN1Header _ _ _ len) <- liftM4 ASN1Header arbitrary arbitraryTag (return False) arbitraryDefiniteLength
Packit ae7d4f
        let blen = case len of
Packit ae7d4f
                LenLong _ x -> x
Packit ae7d4f
                LenShort x  -> x
Packit ae7d4f
                _           -> 0
Packit ae7d4f
        pr <- liftM Primitive (arbitraryBSsized blen)
Packit ae7d4f
        return (ASN1Events [Header hdr, pr])
Packit ae7d4f
Packit ae7d4f
newtype ASN1Events = ASN1Events [ASN1Event]
Packit ae7d4f
Packit ae7d4f
instance Show ASN1Events where
Packit ae7d4f
        show (ASN1Events x) = show x
Packit ae7d4f
Packit ae7d4f
instance Arbitrary ASN1Events where
Packit ae7d4f
        arbitrary = arbitraryEvents
Packit ae7d4f
Packit ae7d4f
Packit ae7d4f
arbitraryOID :: Gen OID
Packit ae7d4f
arbitraryOID = do
Packit ae7d4f
        i1  <- choose (0,2) :: Gen Integer
Packit ae7d4f
        i2  <- choose (0,39) :: Gen Integer
Packit ae7d4f
        ran <- choose (0,30) :: Gen Int
Packit ae7d4f
        l   <- replicateM ran (suchThat arbitrary (\i -> i > 0))
Packit ae7d4f
        return $ (i1:i2:l)
Packit ae7d4f
Packit ae7d4f
arbitraryBSsized :: Int -> Gen B.ByteString
Packit ae7d4f
arbitraryBSsized len = do
Packit ae7d4f
        ws <- replicateM len (choose (0, 255) :: Gen Int)
Packit ae7d4f
        return $ B.pack $ map fromIntegral ws
Packit ae7d4f
Packit ae7d4f
instance Arbitrary B.ByteString where
Packit ae7d4f
        arbitrary = do
Packit ae7d4f
                len <- choose (0, 529) :: Gen Int
Packit ae7d4f
                arbitraryBSsized len
Packit ae7d4f
Packit ae7d4f
instance Arbitrary BitArray where
Packit ae7d4f
        arbitrary = do
Packit ae7d4f
                bs <- arbitrary
Packit ae7d4f
                w  <- choose (0,7) :: Gen Int
Packit ae7d4f
                return $ toBitArray bs w
Packit ae7d4f
Packit ae7d4f
instance Arbitrary Date where
Packit ae7d4f
    arbitrary = do
Packit ae7d4f
        y <- choose (1951, 2050)
Packit ae7d4f
        m <- elements [ January .. December]
Packit ae7d4f
        d <- choose (1, 30)
Packit ae7d4f
        return $ normalizeDate $ Date y m d
Packit ae7d4f
Packit ae7d4f
normalizeDate :: Date -> Date
Packit ae7d4f
normalizeDate origDate
Packit ae7d4f
    | y < 1951  = normalizeDate (Date (y + 50) m d)
Packit ae7d4f
    | otherwise = normalizedDate
Packit ae7d4f
  where
Packit ae7d4f
    normalizedDate@(Date y m d) = timeConvert (timeConvert origDate :: Elapsed)
Packit ae7d4f
Packit ae7d4f
instance Arbitrary TimeOfDay where
Packit ae7d4f
    arbitrary = do
Packit ae7d4f
        h    <- choose (0, 23)
Packit ae7d4f
        mi   <- choose (0, 59)
Packit ae7d4f
        se   <- choose (0, 59)
Packit ae7d4f
        nsec <- return 0
Packit ae7d4f
        return $ TimeOfDay (Hours h) (Minutes mi) (Seconds se) nsec
Packit ae7d4f
Packit ae7d4f
instance Arbitrary DateTime where
Packit ae7d4f
    arbitrary = DateTime <$> arbitrary <*> arbitrary
Packit ae7d4f
Packit ae7d4f
instance Arbitrary TimezoneOffset where
Packit ae7d4f
    arbitrary = elements [ timezone_UTC, TimezoneOffset 60, TimezoneOffset 120, TimezoneOffset (-360) ]
Packit ae7d4f
Packit ae7d4f
instance Arbitrary Elapsed where
Packit ae7d4f
    arbitrary = Elapsed . Seconds <$> arbitrary
Packit ae7d4f
Packit ae7d4f
instance Arbitrary ASN1TimeType where
Packit ae7d4f
    arbitrary = elements [TimeUTC, TimeGeneralized]
Packit ae7d4f
Packit ae7d4f
instance Arbitrary ASN1StringEncoding where
Packit ae7d4f
    arbitrary = elements [UTF8, Numeric, Printable, T61, VideoTex, IA5, Graphic, Visible, General, UTF32, BMP]
Packit ae7d4f
Packit ae7d4f
arbitraryPrintString encoding = do
Packit ae7d4f
    let printableString = (['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ " ()+,-./:=?")
Packit ae7d4f
    asn1CharacterString encoding <$> replicateM 21 (elements printableString)
Packit ae7d4f
Packit ae7d4f
arbitraryBS encoding = ASN1CharacterString encoding . B.pack <$> replicateM 7 (choose (0,0xff))
Packit ae7d4f
Packit ae7d4f
arbitraryIA5String = asn1CharacterString IA5 <$> replicateM 21 (choose (toEnum 0,toEnum 127))
Packit ae7d4f
Packit ae7d4f
arbitraryUCS2 :: Gen ASN1CharacterString
Packit ae7d4f
arbitraryUCS2 = asn1CharacterString BMP <$> replicateM 12 (choose (toEnum 0,toEnum 0xffff))
Packit ae7d4f
Packit ae7d4f
arbitraryUnicode :: ASN1StringEncoding -> Gen ASN1CharacterString
Packit ae7d4f
arbitraryUnicode e = asn1CharacterString e <$> replicateM 35 (choose (toEnum 0,toEnum 0x10ffff))
Packit ae7d4f
Packit ae7d4f
instance Arbitrary ASN1CharacterString where
Packit ae7d4f
    arbitrary = oneof
Packit ae7d4f
            [ arbitraryUnicode UTF8
Packit ae7d4f
            , arbitraryUnicode UTF32
Packit ae7d4f
            , arbitraryUCS2
Packit ae7d4f
            , arbitraryPrintString Numeric
Packit ae7d4f
            , arbitraryPrintString Printable
Packit ae7d4f
            , arbitraryBS T61
Packit ae7d4f
            , arbitraryBS VideoTex
Packit ae7d4f
            , arbitraryIA5String
Packit ae7d4f
            , arbitraryPrintString Graphic
Packit ae7d4f
            , arbitraryPrintString Visible
Packit ae7d4f
            , arbitraryPrintString General
Packit ae7d4f
            ]
Packit ae7d4f
Packit ae7d4f
instance Arbitrary ASN1 where
Packit ae7d4f
        arbitrary = oneof
Packit ae7d4f
                [ liftM Boolean arbitrary
Packit ae7d4f
                , liftM IntVal arbitrary
Packit ae7d4f
                , liftM BitString arbitrary
Packit ae7d4f
                , liftM OctetString arbitrary
Packit ae7d4f
                , return Null
Packit ae7d4f
                , liftM OID arbitraryOID
Packit ae7d4f
                --, Real Double
Packit ae7d4f
                -- , return Enumerated
Packit ae7d4f
                , ASN1String <$> arbitrary
Packit ae7d4f
                , ASN1Time <$> arbitrary <*> arbitrary <*> arbitrary
Packit ae7d4f
                ]
Packit ae7d4f
Packit ae7d4f
newtype ASN1s = ASN1s [ASN1]
Packit ae7d4f
Packit ae7d4f
instance Show ASN1s where
Packit ae7d4f
        show (ASN1s x) = show x
Packit ae7d4f
Packit ae7d4f
instance Arbitrary ASN1s where
Packit ae7d4f
        arbitrary = do
Packit ae7d4f
                x <- choose (0,5) :: Gen Int
Packit ae7d4f
                z <- case x of
Packit ae7d4f
                        4 -> makeList Sequence
Packit ae7d4f
                        3 -> makeList Set
Packit ae7d4f
                        _ -> resize 2 $ listOf1 arbitrary
Packit ae7d4f
                return $ ASN1s z
Packit ae7d4f
                where
Packit ae7d4f
                        makeList str = do
Packit ae7d4f
                                (ASN1s l) <- arbitrary
Packit ae7d4f
                                return ([Start str] ++ l ++ [End str])
Packit ae7d4f
Packit ae7d4f
prop_header_marshalling_id :: ASN1Header -> Bool
Packit ae7d4f
prop_header_marshalling_id v = (ofDone $ runGet getHeader $ putHeader v) == Right v
Packit ae7d4f
    where ofDone (Done r _ _) = Right r
Packit ae7d4f
          ofDone _            = Left "not done"
Packit ae7d4f
Packit ae7d4f
prop_event_marshalling_id :: ASN1Events -> Bool
Packit ae7d4f
prop_event_marshalling_id (ASN1Events e) = (parseLBS $ toLazyByteString e) == Right e
Packit ae7d4f
Packit ae7d4f
prop_asn1_der_marshalling_id v = (decodeASN1 DER . encodeASN1 DER) v `assertEq` Right v
Packit ae7d4f
    where assertEq got expected
Packit ae7d4f
                 | got /= expected = error ("got: " ++ show got ++ " expected: " ++ show expected)
Packit ae7d4f
                 | otherwise       = True
Packit ae7d4f
Packit ae7d4f
marshallingTests = testGroup "Marshalling"
Packit ae7d4f
    [ testProperty "Header" prop_header_marshalling_id
Packit ae7d4f
    , testProperty "Event"  prop_event_marshalling_id
Packit ae7d4f
    , testProperty "DER"    prop_asn1_der_marshalling_id
Packit ae7d4f
    ]
Packit ae7d4f
Packit ae7d4f
main = defaultMain $ testGroup "asn1-encoding" [marshallingTests]