packages feed

elocrypt-2.0.1: test/IntegTest/Elocrypt/PasswordTest.hs

{-# LANGUAGE TemplateHaskell #-}
module IntegTest.Elocrypt.PasswordTest where

import Data.Char
import Data.List
import Data.Maybe
import Control.Monad

import Test.Tasty hiding (Timeout)
import Test.Tasty.QuickCheck (testProperty)
import Test.Tasty.TH

import Test.Elocrypt.QuickCheck

tests :: TestTree
tests = $(testGroupGenerator)

elocrypt = "elocrypt"

-- |All passwords have specified length
prop_printsPasswordsWithLength :: WordCliOptions -> Property
prop_printsPasswordsWithLength (WordCliOptions opts)
  = isJust len ==>
    ioProperty $ do
      (_, out, _, _) <- run opts
      response <- readHandle out

      let len'   = fromJust len
          words' = words response

      return (all ((==) len' . length) words')

  where CliOptions{cliLength=len} = opts

-- |Prints nothing when length is 0
prop_printsNothingWhenLengthIsZero :: WordCliOptions -> Property
prop_printsNothingWhenLengthIsZero (WordCliOptions opts)
  = ioProperty $ do
      let opts' = opts { cliLength = Just 0 }

      (_, out, _, _) <- run opts'
      response <- readHandle out
      return (response == "")

-- |Always prints at least 1 password
prop_printsLongPasswords :: WordCliOptions -> Property
prop_printsLongPasswords (WordCliOptions opts)
  = forAll (scale (*7) arbitrary) $ \len ->
      ioProperty $ do
        let len'  = getPositive len
            opts' = opts { cliLength = Just len' }

        (_, out, _, _) <- run opts'
        response <- readHandle out

        return $
          cover 30 (len' > 80) "long" $
            all (>=1) . map (length . words) . lines $ response

-- |Prints the specified number of passwords
prop_printsNumberPasswords :: Positive Int -> WordCliOptions -> Property
prop_printsNumberPasswords (Positive num) (WordCliOptions opts)
  = ioProperty $ do
      let opts' = opts { cliNumber = Just num }

      (_, out, _, _) <- run opts'
      response <- readHandle out

      let words' = words response

      return $ num == length words'

-- |Prints multiple passwords per line when length is sufficiently small
prop_printsMultiplePasswordsPerLine :: WordCliOptions -> Property
prop_printsMultiplePasswordsPerLine (WordCliOptions opts)
  = isNothing len || fromJust len <= 38 ==>
    ioProperty $ do
      (_, out, _, _) <- run opts
      response <- readHandle out

      return $
        all (>1) . tail . reverse . map (length . words) . lines $ response

  where CliOptions{cliLength=len} = opts

-- |Prints capitals when specified
prop_printsCapitals :: WordCliOptions -> Property
prop_printsCapitals (WordCliOptions opts)
  = ioProperty $ do
      let opts' = opts { cliCapitals = True }

      (_, out, _, _) <- run opts'
      response <- readHandle out

      let passes = words response

      return $
        cover 80 (any (any isUpper) passes) "has caps" True