-- Copyright (C) 2002-2005,2007 David Roundy -- Copyright (C) 2009 Reinier Lamers -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2, 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 General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; see the file COPYING. If not, write to -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -- | This module contains unit tests of the code in 'Darcs.Email' -- -- These tests check whether the emails generated by darcs meet a few criteria. -- We check for line length and non-ASCII characters. We apparently do not have -- to check for CR-LF newlines because that's handled by sendmail. module Darcs.Test.Email ( email_parsing, email_header_no_long_lines, email_header_ascii_chars, email_header_lines_start, email_header_no_empty_lines ) where import Data.Char ( isPrint ) import qualified Data.ByteString as B ( length, unpack, null, head, filter, cons, empty, foldr, ByteString ) import qualified Data.ByteString.Char8 as BC ( unpack ) import Test.Framework ( Test ) import Test.Framework.Providers.QuickCheck2 ( testProperty ) import Printer ( text, renderPS ) import Darcs.Email ( make_email, read_email, formatHeader ) -- | Checks that darcs can read the emails it generates email_parsing :: Test email_parsing = testProperty "Checking that email can be parsed" $ \s -> unlines ("":s++["", ""]) == BC.unpack (read_email (renderPS $ make_email "reponame" [] (Just (text "contents\n")) (text $ unlines s) (Just "filename"))) -- | Check that formatHeader never creates lines longer than 78 characters -- (excluding the carriage return and line feed) email_header_no_long_lines :: Test email_header_no_long_lines = testProperty "Checking email header line length" $ \field value -> let cleanField = clean_field_string field in not $ any (>78) $ map B.length $ bs_lines $ formatHeader cleanField value -- Check that an email header does not contain non-ASCII characters -- formatHeader doesn't escape field names, there is no such thing as non-ascii -- field names afaik email_header_ascii_chars :: Test email_header_ascii_chars = testProperty "Checking email for illegal characters" $ \field value -> let cleanField = clean_field_string field in not (any (>127) (B.unpack (formatHeader cleanField value))) -- Check that header the second and later lines of a header start with a space email_header_lines_start :: Test email_header_lines_start = testProperty "Checking for spaces at start of folded email header lines" $ \field value -> let headerLines = bs_lines (formatHeader cleanField value) cleanField = clean_field_string field in all (\l -> B.null l || B.head l == 32) (tail headerLines) -- Checks that there are no lines in email headers with only whitespace email_header_no_empty_lines :: Test email_header_no_empty_lines = testProperty "Checking that there are no empty lines in email headers" $ \field value -> let headerLines = bs_lines (formatHeader cleanField value) cleanField = clean_field_string field in all (not . B.null . B.filter (not . (`elem` [10, 32, 9]))) headerLines bs_lines :: B.ByteString -> [B.ByteString] bs_lines = finalizeFold . B.foldr splitAtLines (B.empty, []) where splitAtLines 10 (thisLine, prevLines) = (B.empty, thisLine:prevLines) splitAtLines c (thisLine, prevLines) = (B.cons c thisLine, prevLines) finalizeFold (lastLine, otherLines) = lastLine : otherLines clean_field_string :: String -> String clean_field_string = filter (\c -> isPrint c && c < '\x80' && c /= ':')