purebred-email-0.6: tests/ContentTransferEncodings.hs
-- This file is part of purebred-email
-- Copyright (C) 2017-2018 Róman Joost and Fraser Tweedale
--
-- purebred-email is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Affero General Public License for more details.
--
-- You should have received a copy of the GNU Affero General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
module ContentTransferEncodings where
import Data.Word
import Control.Lens (clonePrism, preview, review)
import qualified Data.ByteString as B
import Test.Tasty
import Test.Tasty.QuickCheck
import Test.QuickCheck.Instances ()
import Data.MIME.Base64 (contentTransferEncodingBase64)
import Data.MIME.QuotedPrintable
import Data.MIME.Types
properties :: TestTree
properties = localOption (QuickCheckMaxSize 1000) $
testGroup "codec properties"
[ testGroup "Content-Transfer-Encoding properties"
[ testProperty "base64 round-trip"
(prop_roundtrip contentTransferEncodingBase64)
, testProperty "quoted-printable round-trip"
(prop_roundtrip contentTransferEncodingQuotedPrintable)
, testProperty "base64 line length <= 76"
(prop_linelength contentTransferEncodingBase64)
, testProperty "quoted-printable line length <= 76"
(prop_linelength contentTransferEncodingQuotedPrintable)
]
, testGroup "encoded-word codec properties"
[ testProperty "Q round-trip" (prop_roundtrip q)
, testProperty "Q does not contain spaces" (prop_notElem q 32 {- ' ' -})
]
]
prop_roundtrip :: ContentTransferEncoding -> B.ByteString -> Bool
prop_roundtrip p s = preview (clonePrism p) (review (clonePrism p) s) == Just s
prop_linelength :: ContentTransferEncoding -> B.ByteString -> Property
prop_linelength p s =
let
encoded = review (clonePrism p) s
prop = all ((<= 76) . B.length) (splitOnCRLF encoded)
in
checkCoverage $ cover 50 (B.length encoded > 100) "long output" prop
prop_notElem :: EncodedWordEncoding -> Word8 -> B.ByteString -> Bool
prop_notElem enc c = B.notElem c . review (clonePrism enc)
splitOnCRLF :: B.ByteString -> [B.ByteString]
splitOnCRLF s =
let (l, r) = B.breakSubstring "\r\n" s
in
if B.null r
then [l]
else l : splitOnCRLF (B.drop 2 r)