    -- |
    -- Module      : Crypto.Cipher.Tests
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : Stable
    -- Portability : Excellent
    --

    {-# LANGUAGE ViewPatterns #-}
    module Crypto.Cipher.Tests
        ( testBlockCipher
        , testBlockCipherIO
        , testStreamCipher
        -- * KATs
        , defaultKATs
        , defaultStreamKATs
        , KATs(..)
        , KAT_Stream(..)
        , KAT_ECB(..)
        , KAT_CBC(..)
        , KAT_CFB(..)
        , KAT_CTR(..)
        , KAT_XTS(..)
        , KAT_AEAD(..)
        ) where

    import Test.Framework (Test, testGroup)

    import Crypto.Cipher.Types
    import Crypto.Cipher.Types.Unsafe
    import Crypto.Cipher.Tests.KATs
    import Crypto.Cipher.Tests.Properties

    -- | Return tests for a specific blockcipher and a list of KATs
    testBlockCipher :: BlockCipher a => KATs -> a -> Test
    testBlockCipher :: forall a. BlockCipher a => KATs -> a -> Test
    testBlockCipher KATs
    kats a
    cipher = TestName -> [Test] -> Test
    testGroup (a -> TestName
    forall cipher. Cipher cipher => cipher -> TestName
    cipherName a
    cipher)
        (  (if KATs
    kats KATs -> KATs -> Bool
    forall a. Eq a => a -> a -> Bool
    == KATs
    defaultKATs  then [] else [KATs -> a -> Test
    forall a. BlockCipher a => KATs -> a -> Test
    testKATs KATs
    kats a
    cipher])
        [Test] -> [Test] -> [Test]
    forall a. [a] -> [a] -> [a]
    ++ a -> [Test]
    forall a. BlockCipher a => a -> [Test]
    testModes a
    cipher
        )

    -- | Return test for a specific blockcipher and a list of KATs
    testBlockCipherIO :: BlockCipherIO a => KATs -> a -> Test
    testBlockCipherIO :: forall a. BlockCipherIO a => KATs -> a -> Test
    testBlockCipherIO KATs
    _ a
    cipher = TestName -> [Test] -> Test
    testGroup (TestName
    "mutable " TestName -> TestName -> TestName
    forall a. [a] -> [a] -> [a]
    ++ a -> TestName
    forall cipher. Cipher cipher => cipher -> TestName
    cipherName a
    cipher)
        ( []
        [Test] -> [Test] -> [Test]
    forall a. [a] -> [a] -> [a]
    ++ a -> [Test]
    forall a. BlockCipherIO a => a -> [Test]
    testIOModes a
    cipher
        )

    -- | Return tests for a specific streamcipher and a list of KATs
    testStreamCipher :: StreamCipher a => [KAT_Stream] -> a -> Test
    testStreamCipher :: forall a. StreamCipher a => [KAT_Stream] -> a -> Test
    testStreamCipher [KAT_Stream]
    kats a
    cipher = TestName -> [Test] -> Test
    testGroup (a -> TestName
    forall cipher. Cipher cipher => cipher -> TestName
    cipherName a
    cipher)
        (  (if [KAT_Stream]
    kats [KAT_Stream] -> [KAT_Stream] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [KAT_Stream]
    defaultStreamKATs then [] else [[KAT_Stream] -> a -> Test
    forall a. StreamCipher a => [KAT_Stream] -> a -> Test
    testStreamKATs [KAT_Stream]
    kats a
    cipher])
        [Test] -> [Test] -> [Test]
    forall a. [a] -> [a] -> [a]
    ++ a -> [Test]
    forall a. StreamCipher a => a -> [Test]
    testStream a
    cipher
        )