elocrypt 0.3.1 → 0.3.2
raw patch · 5 files changed
+123/−4 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- elocrypt.cabal +6/−3
- src/cli/Main.hs +1/−1
- test/Test/Elocrypt/Instances.hs +20/−0
- test/Test/Elocrypt/TrigraphTest.hs +22/−0
- test/Test/ElocryptTest.hs +74/−0
elocrypt.cabal view
@@ -1,5 +1,5 @@ name: elocrypt-version: 0.3.1+version: 0.3.2 synopsis: Generate easy-to-remember, hard-to-guess passwords homepage: https://www.github.com/sgillespie/elocrypt license: OtherLicense@@ -9,7 +9,10 @@ copyright: Copyright: (c) 2015 Sean Gillespie category: Cryptography build-type: Simple-extra-source-files: README.md+extra-source-files: README.md,+ test/*.hs,+ test/Test/*.hs,+ test/Test/Elocrypt/*.hs cabal-version: >=1.10 description:@@ -23,7 +26,7 @@ source-repository this type: git location: https://github.com/sgillespie/elocrypt.git- tag: v0.3.0+ tag: v0.3.2 library exposed-modules: Data.Elocrypt,
src/cli/Main.hs view
@@ -10,7 +10,7 @@ import Data.Elocrypt -version = "elocrypt 0.3.1"+version = "elocrypt 0.3.2" main :: IO () main = do
+ test/Test/Elocrypt/Instances.hs view
@@ -0,0 +1,20 @@+module Test.Elocrypt.Instances where++import Control.Monad+import System.Random+import Test.QuickCheck++instance Arbitrary StdGen where+ arbitrary = mkStdGen `liftM` arbitrary++newtype AlphaChar = Alpha Char+ deriving (Eq, Ord, Show)++instance Arbitrary AlphaChar where+ arbitrary = Alpha `liftM` elements ['a'..'z']++newtype GreaterThan2 a = GT2 { greaterThan2 :: a }+ deriving (Eq, Ord, Show)++instance (Num a, Ord a, Arbitrary a) => Arbitrary (GreaterThan2 a) where+ arbitrary = GT2 `fmap` (arbitrary `suchThat` (>2))
+ test/Test/Elocrypt/TrigraphTest.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE TemplateHaskell #-}+module Test.Elocrypt.TrigraphTest where++import Control.Monad+import Test.QuickCheck+import Test.Tasty.QuickCheck (testProperty)+import Test.Tasty.TH++import Test.Elocrypt.Instances+import Data.Elocrypt.Trigraph++tests = $(testGroupGenerator)++prop_findFrequencyShouldSucceedWith2Chars :: AlphaChar -> AlphaChar -> Bool+prop_findFrequencyShouldSucceedWith2Chars (Alpha c1) (Alpha c2)+ = fromJust (findFrequency [c1, c2])+ where fromJust (Just _) = True+ fromJust Nothing = False++prop_findFrequencyShouldFailWithNot2Chars :: String -> Property+prop_findFrequencyShouldFailWithNot2Chars str+ = length str /= 2 ==> findFrequency str == Nothing
+ test/Test/ElocryptTest.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE TemplateHaskell #-}+module Test.ElocryptTest where++import Control.Monad+import Control.Monad.Random hiding (next)+import Data.Maybe+import System.Random hiding (next)+import Test.QuickCheck+import Test.Tasty.QuickCheck (testProperty)+import Test.Tasty.TH++import Data.Elocrypt+import Data.Elocrypt.Trigraph+import Test.Elocrypt.Instances++tests = $(testGroupGenerator)++prop_genPasswordShouldBeUnique :: GreaterThan2 Int -> StdGen -> Bool+prop_genPasswordShouldBeUnique (GT2 len) gen+ = p /= fst (genPassword len gen')+ where (p, gen') = genPassword len gen++prop_genPasswordsShouldBeUnique :: GreaterThan2 Int -> StdGen -> Bool+prop_genPasswordsShouldBeUnique (GT2 len) gen+ = p /= ps+ where (p:ps:_) = fst (genPasswords len gen)++prop_newPasswordShouldBeLength :: GreaterThan2 Int -> StdGen -> Bool+prop_newPasswordShouldBeLength (GT2 len) gen = length (newPassword len gen) == len++prop_newPasswordShouldConsistOfAlphabet :: GreaterThan2 Int -> StdGen -> Bool+prop_newPasswordShouldConsistOfAlphabet (GT2 len) gen+ = all ((flip elem) alphabet) (newPassword len gen)++prop_newPasswordsShouldBeUnique :: GreaterThan2 Int -> StdGen -> Bool+prop_newPasswordsShouldBeUnique (GT2 len) gen+ = p /= ps+ where (p:ps:_) = newPasswords len gen++prop_first2ShouldHaveLength2 :: StdGen -> Bool+prop_first2ShouldHaveLength2 g = length (evalRand first2 g) == 2++prop_nextShouldSkip0Weights :: AlphaChar -> AlphaChar -> StdGen -> Property+prop_nextShouldSkip0Weights (Alpha c1) (Alpha c2) gen = isCandidate next' [c1, c2]+ where next' = evalRand (next . reverse $ [c1, c2]) gen++prop_lastNShouldSkip0Weights :: AlphaChar -> AlphaChar -> Int -> StdGen -> Property+prop_lastNShouldSkip0Weights (Alpha c1) (Alpha c2) len gen+ = len > 0 ==> lastNShouldSkip0Weights' lastN'+ where f2 = [c1, c2]+ lastN' = evalRand (lastN (reverse [c1, c2]) len) gen++lastNShouldSkip0Weights' :: String -> Property+lastNShouldSkip0Weights' (p:ps:pss:psss) = isCandidate p [pss, ps] .&&.+ lastNShouldSkip0Weights' (ps:pss:psss)+lastNShouldSkip0Weights' _ = property True++-- Utility functions+isCandidate :: Char -> String -> Property+isCandidate c (s:ss:sss) = hasCandidates f2 ==>+ isJust $ elem c `liftM` findNextCandidates f2+ where f2 = [s, ss]++isCandidate _ _ = undefined -- This really shouldn't ever happen++hasCandidates :: String -> Bool+hasCandidates s = (not . null) `liftM` findNextCandidates s == Just True++findNextCandidates :: String -> Maybe [Char]+findNextCandidates (c1:c2:_) = map fst `liftM` frequency+ where f2 = [c1, c2]+ frequency = (filter ((/=0) . snd) . zip ['a'..'z']) `liftM` findFrequency f2++findNextCandidates _ = Nothing -- This really shouldn't ever happen