Context
I have the following function:
prop_SignAndVerify :: (PrivKey a b) => Blind a -> BS.ByteString -> Bool
prop_SignAndVerify bsk msg = case verify pk msg sig of
Left e -> error e
Right b -> b
where
sk = getBlind bsk
pk = toPublic sk
sig = case sign sk msg of
Left e -> error e
Right s -> s
I would like to do something like:
-- instance PrivKey RSA.PrivateKey RSA.PublicKey where...
genRSA :: Gen RSA.PrivateKey
genRSAMessage :: Gen BS.ByteString
main = do
quickCheck . verbose
$ forAll genRSA
$ forAll genRSAMessage prop_SignAndVerify
That is, I would like to use explicit generators to generate arbitrary values for Blind a and BS.ByteString in the parameters of prop_SignAndVerify.
The code above, however, doesn't work, because the function forAll has type signature:
forAll :: (Show a, Testable prop) => Gen a -> (a -> prop) -> Property
This function runs the generator and apples the generated arbitrary value to (a -> prop), returning a Property. This Property however cannot be further partially applied; it hides the underlying function.
I think what we need for the above to work would be something like:
forAll' :: (Show a, Testable prop) => Gen a -> (a -> prop) -> prop
Question
So my question is, how can I use genRSA and genRSAMessage over the parameters of prop_SignAndVerify, or is there an alternative approach?
Thanks
You want to check prop_SignAndVerify key message for all many keys and messages. So if we had a fixed key, our tests would look like that:
main = do
quickCheck . verbose $
let key = someGeneratedKey
in forAll genRSAMessage $ \message ->
prop_SignAndVerify key message
If we had a fixed message, our test would look like this:
main = do
quickCheck . verbose $
forAll genRSAMessage $ \key ->
let message = someMessage
in prop_SignAndVerify key message
All we have to do is to combine both variants:
main = do
quickCheck . verbose $
forAll genRSA $ \key ->
forAll genRSAMessage $ \message ->
prop_SignAndVerify key message
You can get rid of the message due to eta conversion, but in my opinion tests should be easily readable.
You could take advantage of the monadic nature of Gen to compose a more complex Gen value from your property:
main =
let g = do
key <- genRSA
message <- genRSAMessage
return $ prop_SignAndVerify (Blind key) message
in quickCheck . verbose $ forAll g id
Here, g is a Gen Bool value.
Alternatively, you can take advantage of the applicative nature of Gen and compose g using <*>:
main =
let g =
return (\key message -> prop_SignAndVerify (Blind key) message)
<*> genRSA
<*> genRSAMessage
in quickCheck . verbose $ forAll g id
g is still a Gen Bool value here as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With