elocrypt-1.0.0: test/IntegTest/Elocrypt/PassphraseTest.hs
{-# LANGUAGE TemplateHaskell #-}
module IntegTest.Elocrypt.PassphraseTest where
import Control.Monad
import Data.List
import Data.Maybe
import Test.Proctest
import Test.Proctest.Assertions
import Test.QuickCheck
import Test.Tasty hiding (Timeout)
import Test.Tasty.QuickCheck (testProperty)
import Test.Tasty.TH
import Test.Elocrypt.Instances
tests :: TestTree
tests = $(testGroupGenerator)
elocrypt = "elocrypt"
prop_printsWordsWithSpecifiedLengthRange :: PhraseCliArgs -> Property
prop_printsWordsWithSpecifiedLengthRange (PhraseCliArgs args)
= length (getPosParams args) == 2 ==>
ioProperty $ do
(_, out', _, _) <- run' elocrypt args
response <- readHandle out'
let (minLen:maxLen:_) = map read (getPosParams args)
words' = words response
return (all ((\n -> n >= minLen && n <= maxLen) . length) words')
prop_printsWordsWithSpecifiedMinLengthRange :: PhraseCliArgs -> Property
prop_printsWordsWithSpecifiedMinLengthRange (PhraseCliArgs args)
= length (getPosParams args) == 1 ==>
ioProperty $ do
(_, out', _, _) <- run' elocrypt args
response <- readHandle out'
let (minLen:_) = map read (getPosParams args)
return . all ((>= min minLen 10) . length) . words $ response
prop_printsWordsWithDefaultLengthRange :: PhraseCliArgs -> Property
prop_printsWordsWithDefaultLengthRange (PhraseCliArgs args)
= length (getPosParams args) == 0 ==>
ioProperty $ do
(_, out', _, _) <- run' elocrypt args
response <- readHandle out'
let words' = words response
return (all ((\n -> n >= 8 && n <= 10) . length) words')
prop_printsSpecifiedNumberOfPassphrases :: PhraseCliArgs -> Property
prop_printsSpecifiedNumberOfPassphrases (PhraseCliArgs args)
= isJust (getArg "-n" args) &&
length (getPosParams args) /= 1 ==> -- Make sure maxLen > minLen
ioProperty $ do
(_, out', _, _) <- run' elocrypt args
response <- readHandle out'
let number = read . fromJust . getArg "-n" $ args
phrases = lines response
return (number == length phrases)
prop_printsMultipleWordsPerLine :: PhraseCliArgs -> Property
prop_printsMultipleWordsPerLine (PhraseCliArgs args)
= sum (map read (getPosParams args) :: [Integer]) <= 29 ==>
ioProperty $ do
(_, out', _, _) <- run' elocrypt args
response <- readHandle out'
return $
all (>1) . tail . reverse . map (length . words) . lines $ response
prop_printsLongPassphrases :: GreaterThan79 Int -> GreaterThan0 Int -> Property
prop_printsLongPassphrases (GT79 minLen) (GT0 maxLen)
= ioProperty $ do
(_, out', _, _) <- run' elocrypt ["-p",
show minLen,
show (minLen + maxLen)]
response <- readHandle out'
return . all (==1) . map (length . words) . lines $ response
getArg :: String -> [String] -> Maybe String
getArg prefix args = (tail . dropWhile (not . elem')) `liftM` arg
where arg = find (isPrefixOf prefix) args
elem' = (flip elem) [' ', '=']
getPosParams :: [String] -> [String]
getPosParams = filter ((/= '-') . head)
run' :: FilePath -> [String] -> IO (Handle, Handle, Handle, ProcessHandle)
run' exe args = do
res@(_, _, _, p) <- run exe args
sleep'
_ <- assertExitedSuccess (seconds 2) p
return res
readHandle :: Handle -> IO String
readHandle = (<$>) asUtf8Str . waitOutput (seconds 2) 5000
sleep' :: IO ()
sleep' = sleep (seconds 0.0001)
assertExitedSuccess :: Timeout -> ProcessHandle -> IO Bool
assertExitedSuccess t = liftM (== ExitSuccess) . assertExitedTimeout t
assertExitedFailure :: Timeout -> ProcessHandle -> IO Bool
assertExitedFailure t = liftM not . assertExitedSuccess t