-- |
-- Some QuickCheck utility functions.
module B9.QCUtil where

import Control.Monad
import Test.QuickCheck

arbitraryEnv :: Arbitrary a => Gen [(String, a)]
arbitraryEnv :: Gen [(String, a)]
arbitraryEnv = Gen (String, a) -> Gen [(String, a)]
forall a. Gen a -> Gen [a]
listOf ((,) (String -> a -> (String, a))
-> Gen String -> Gen (a -> (String, a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Char -> Gen String
forall a. Gen a -> Gen [a]
listOf1 ((Char, Char) -> Gen Char
forall a. Random a => (a, a) -> Gen a
choose (Char
'a', Char
'z')) Gen (a -> (String, a)) -> Gen a -> Gen (String, a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
forall a. Arbitrary a => Gen a
arbitrary)

halfSize :: Gen a -> Gen a
halfSize :: Gen a -> Gen a
halfSize Gen a
g = (Int -> Gen a) -> Gen a
forall a. (Int -> Gen a) -> Gen a
sized ((Int -> Gen a -> Gen a) -> Gen a -> Int -> Gen a
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> Gen a -> Gen a
forall a. Int -> Gen a -> Gen a
resize Gen a
g (Int -> Gen a) -> (Int -> Int) -> Int -> Gen a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int) -> Int -> Int -> Int
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> Int -> Int
forall a. Integral a => a -> a -> a
div Int
2)

smaller :: Gen a -> Gen a
smaller :: Gen a -> Gen a
smaller Gen a
g = (Int -> Gen a) -> Gen a
forall a. (Int -> Gen a) -> Gen a
sized ((Int -> Gen a -> Gen a) -> Gen a -> Int -> Gen a
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> Gen a -> Gen a
forall a. Int -> Gen a -> Gen a
resize Gen a
g (Int -> Gen a) -> (Int -> Int) -> Int -> Gen a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int) -> Int -> Int -> Int
forall a b c. (a -> b -> c) -> b -> a -> c
flip (-) Int
1)

arbitraryFilePath :: Gen FilePath
arbitraryFilePath :: Gen String
arbitraryFilePath = do
  String
path <-
    [String] -> String
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join
      ([String] -> String) -> Gen [String] -> Gen String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen String -> Gen [String]
forall a. Gen a -> Gen [a]
listOf
        ( [String] -> Gen String
forall a. [a] -> Gen a
elements
            [ String
"/",
              String
"../",
              String
"./",
              String
"etc/",
              String
"opt/",
              String
"user/",
              String
"var/",
              String
"tmp/",
              String
"doc/",
              String
"share/",
              String
"conf.d/"
            ]
        )
  String
prefix <- [String] -> Gen String
forall a. [a] -> Gen a
elements [String
"foo_", String
"", String
"alt_", String
"ssh-", String
""]
  String
body <- [String] -> Gen String
forall a. [a] -> Gen a
elements [String
"www", String
"passwd", String
"cert", String
"opnsfe", String
"runtime"]
  String
extension <- [String] -> Gen String
forall a. [a] -> Gen a
elements [String
".txt", String
".png", String
".ps", String
".erl", String
""]
  String -> Gen String
forall (m :: * -> *) a. Monad m => a -> m a
return (String
path String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
prefix String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
body String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
extension)

arbitraryLetter :: Gen Char
arbitraryLetter :: Gen Char
arbitraryLetter = [Gen Char] -> Gen Char
forall a. [Gen a] -> Gen a
oneof [Gen Char
arbitraryLetterUpper, Gen Char
arbitraryLetterLower]

arbitraryLetterUpper :: Gen Char
arbitraryLetterUpper :: Gen Char
arbitraryLetterUpper = String -> Gen Char
forall a. [a] -> Gen a
elements [Char
'A' .. Char
'Z']

arbitraryLetterLower :: Gen Char
arbitraryLetterLower :: Gen Char
arbitraryLetterLower = String -> Gen Char
forall a. [a] -> Gen a
elements [Char
'a' .. Char
'z']

arbitraryDigit :: Gen Char
arbitraryDigit :: Gen Char
arbitraryDigit = String -> Gen Char
forall a. [a] -> Gen a
elements [Char
'0' .. Char
'9']