elocrypt-2.0.0: test/IntegTest/Elocrypt/PassphraseTest.hs
{-# LANGUAGE TemplateHaskell #-}
module IntegTest.Elocrypt.PassphraseTest where
import Control.Monad
import Data.Bool
import Data.Char
import Data.List
import Data.Maybe
import Test.QuickCheck
import Test.Tasty hiding (Timeout)
import Test.Tasty.QuickCheck (testProperty)
import Test.Tasty.TH
import qualified Test.Proctest as Proctest
import Test.Elocrypt.QuickCheck
tests :: TestTree
tests = $(testGroupGenerator)
elocrypt = "elocrypt"
-- |Passphrases consist of words in specified length range
prop_printsWordsWithLengthRange :: PhraseCliOptions -> Property
prop_printsWordsWithLengthRange (PhraseCliOptions opts)
= isJust minLen && isJust maxLen && fromJust maxLen <= 79 ==>
ioProperty $ do
(_, out, _, _) <- run opts
response <- readHandle out
let words' = words response
minLen' = fromJust minLen
maxLen' = fromJust maxLen
return (all ((\n -> n >= minLen' && n <= maxLen') . length) words')
where CliOptions{cliLength=minLen, cliMaxLength=maxLen} = opts
-- |Passphrases consist of words with specified minimum range
prop_printsWordsWithMinLength:: PhraseCliOptions -> Property
prop_printsWordsWithMinLength(PhraseCliOptions opts)
= isJust minLen && fromJust minLen <= 79 ==>
ioProperty $ do
(_, out, _, _) <- run opts
response <- readHandle out
return . all ((>= min (fromJust minLen) 10) . length) . words $ response
where CliOptions{cliLength=minLen} = opts
-- |Prints the specificed number of phrases
prop_printsSpecifiedNumberOfPassphrases :: PhraseCliOptions -> Property
prop_printsSpecifiedNumberOfPassphrases (PhraseCliOptions opts)
= isJust number &&
(isJust maxLen || isNothing len) && -- maxLen > len
maybe True (< 79) maxLen ==> -- minLen/maxLen < 79
ioProperty $ do
(_, out, _, _) <- run opts
response <- readHandle out
let phrases = lines response
return $ counterexample (failMsg phrases)
(fromJust number == length phrases)
where CliOptions{cliNumber=number, cliLength=len, cliMaxLength=maxLen} = opts
failMsg p = "length phrases (" ++ show (length p) ++
") /= " ++ show (fromJust number)
-- |Prints multiple passwords per line
prop_printsMultipleWordsPerLine :: PhraseCliOptions
-> LessThan20 Int
-> LessThan20 Int
-> Property
prop_printsMultipleWordsPerLine (PhraseCliOptions opts) (LT20 min) (LT20 max)
= ioProperty $ do
let opts' = opts { -- Make sure we can fit 2+ words on a line
cliLength = Just min,
cliMaxLength = Just max}
(_, out, _, _) <- run opts'
response <- readHandle out
return $
all (>1) . tail . reverse . map (length . words) . lines $ response
-- |Always prints a passphrase
prop_printsLongPassphrases :: PhraseCliOptions
-> Positive Int
-> Positive Int
-> Property
prop_printsLongPassphrases (PhraseCliOptions opts) (Positive min) (Positive max)
= forAll (scale (*7) arbitrary) $ \min ->
ioProperty $ do
let minLen = getPositive min
opts' = opts{
cliLength = Just minLen,
cliMaxLength = Just (minLen + max)}
(_, out, _, _) <- run opts
response <- readHandle out
return $
cover (minLen > 80) 20 "long" $
all (>=1) . map (length . words) . lines $ response
-- |Prints capitals when specified
prop_printsCapitals :: PhraseCliOptions -> Property
prop_printsCapitals (PhraseCliOptions opts)
= ioProperty $ do
let opts' = opts { cliCapitals = True }
(_, out, _, _) <- run opts'
response <- readHandle out
let phrases = lines response
return $
cover (any (any isUpper) phrases) 80 "has caps" True